How to delay the GPIO when using Flask-ask on Pi - python

I've followed a tutorial on getting Amazon Echo to talk to my Raspberry and it works beautifully.
The part I have added is the GPIO parts in the yes intent so that it flashed an LED when it receives a yes answer from the Echo. Again, it works perfectly.
Now I want to make it so there is a delay on the GPIO so that the Alexa response speaks then the LED flashes. How can I do this?
I've tried creating a variable in the yes intent that gets set to '1' when she answers. Then I tried to return it at the end by adding , variableName then creating an if command outside of the yes intent function, but the variable never seems to come out of the yesintent. I also tried defining the variable as global but still no joy. I just can't think of anything else to Google to do this and I wondered if anyone could help?
The code is as follows:
from flask import Flask
from flask_ask import Ask, statement, question, session
import json
import requests
import time
import unidecode
import RPi.GPIO as GPIO
import time
GPIO.setmode(GPIO.BOARD)
app = Flask(__name__)
ask = Ask(app, "/shocker")
#app.route('/')
def homepage():
welcome = 'hi there, how the fluff is it?'
return statement(welcome)
#ask.launch
def start_skill():
welcome_message = 'Hello there, would you like me to do something?'
return question(welcome_message)
#ask.intent("YesIntent")
def yes_intent():
GPIO.setwarnings(False)
GPIO.setup(7, GPIO.OUT)
GPIO.output(7,1)
time.sleep(1)
GPIO.output(7,0)
yes_message = 'the thing has been done'
return statement(yes_message)
#ask.intent("NoIntent")
def no_intent():
no_message = 'well then why are you wasting my time?'
return statement(no_message)
if __name__ == '__main__':
app.run()

Related

Calling Functions in Flask

Apologies in advance as this is probably the most basic question to be found here but I'm the greenest of newbies and cannot get my head around how to call a function in flask so it runs when I land on the URL.
My purpose is to try and get a python script to run when a GET request is made to the URL from WebCore (for those who don't know it's a program that allows you to code smart home functionality for SmartThings) or when I simply land at the URL. I will then tie this to a virtual switch which will start the code which controls a motor in a cat feeder so I can feed my cat remotely/by voice.
All very frivolous stuff but trying to learn some basics here, can anyone help?
As it stands I have two files, both in a root directory named 'CatFeeder'
catfeeder.py
from flask import Flask
from feed import start
app = Flask(__name__)
#app.route('/')
def feed()
return feed.start
if __name__ == '__main__':
app.run(host='0.0.0.0', port='5000', debug=True)
feed.py
import time
import RPi.GPIO as GPIO
def start():
# Next we setup the pins for use!
GPIO.setmode(GPIO.BCM)
GPIO.setwarnings(False)
Motor1Forward = 17
Motor1Backwards = 18
GPIO.setup(Motor1Forward,GPIO.OUT)
GPIO.setup(Motor1Backwards,GPIO.OUT)
print('Feeding Lola')
# Makes the motor spin forward for x seconds
# James Well Beloved - 11 seconds = 28g food (RDA Portion = 52g/4kg cat or 61g/5kg cat)
# XXXX - X seconds - Xg food
GPIO.output(Motor1Forward, True)
GPIO.output(Motor1Backwards, False)
time.sleep(11)
print('Lola Fed!')
GPIO.output(Motor1Forward, False)
GPIO.output(Motor1Backwards, False)
GPIO.cleanup()
quit()
When I set export FLASK_APP=catfeeder.py and then flask run the service runs but nothing happens when I land on the page. I assume there is something wrong in the way I am calling things.
I guess it would be easiest if I just integrated the code from feed.py into catfeeder.py but I wasn't sure what the syntax would be for this and it felt like a messy way to go about it.
Thanks in advance!
you've imported the function but didn't actually invoke it as you missed adding your brackets (), try return start()
In case you meant to return a function object and not invoke the function, you should return it by typing return start

How to change these global variables to non global variables?

I have this little program that parrots back whatever a user is saying. Right now I'm using two global variables to store the previous variable state and add 1 to it. I'm wondering if someone can please suggest some ways to do this that doesn't involve using global variables.
Note: There is no UI or front end on this thing. Its a webhook for a google home, so its just sitting server side sending things back and forth.
import random, time, os, atexit
from datetime import datetime
from random import choice
from random import shuffle
from flask import Flask, current_app, jsonify
from flask_assistant import Assistant, ask, tell, event, context_manager, request
from flask_assistant import ApiAi
app = Flask(__name__)
assist = Assistant(app)
api = ApiAi(os.environ['DEV_ACCESS_TOKEN'], os.environ['CLIENT_ACCESS_TOKEN'])
random.seed()
interrupt_count = 0
frustration_level = 0
def reset_things():
global interrupt_count
interrupt_count = 0
print("!reset_things: {0}, {1}".format(interrupt_count, frustration_level))
#assist.action('greeting')
def hello_world():
speech = 'This is the unxepected machine'
return ask(speech)
#assist.action('fallback', is_fallback=True)
def say_fallback():
print(dir(Assistant.request))
resp = request['result']['resolvedQuery']
default_resp = "boogie boo"
# if the user said soemthing
if resp:
# update the global variable
global interrupt_count
interrupt_count+=1
global frustration_level
if not interrupt_count % 3:
frustration_level+=1
print("!fallback: {0}, {1}".format(interrupt_count, frustration_level))
print(parrot)
return ask(parrot)
else:
print(default_resp)
return(default_resp)
#assist.action('help')
def help():
speech = "I am the help section"
return ask(speech)
#assist.action('quit')
def quit():
reset_things()
speech = "Leaving program"
return tell(speech)
if __name__ == '__main__':
app.run(debug=True, use_reloader=False)
The simplest solution would probably be to store the data in a cookie. You don't need a database for the data if it's very small, and it's not important enough to warrant being stored on the server.
Another related possibility is to encode the variable state in the url to your service, and have the service provide the user with an updated url to click on with every reply.

Global variable is None instead of instance - Python

I'm dealing with global variables in Python. The code should work fine, but there is a problem. I have to use global variable for instance of class Back. When I run the application it says that back is None which should be not true because the second line in setup() function - 'back = Back.Back()'
# -*- coding: utf-8 -*-
from flask import Flask
from flask import request
from flask import render_template
import Search
import Back
app = Flask(__name__)
global back
back = None
#app.route('/')
def my_form():
return render_template('my-form.html')
def setup():
global back
back = Back.Back()
def is_ascii(s):
return all(ord(c) < 128 for c in s)
#app.route('/', methods=['POST'])
def search():
from time import time
pattern = request.form['text']
startTime = time()
pattern=pattern.lower()
arr = []
if len(pattern)<1:
arr.append('Incorrect input')
currentTime = time()-startTime
return render_template('my-form.html', arr=arr, time=currentTime)
arr = []
search = Search.Search(pattern,back)
results = search.getResults()
..................
return render_template('my-form.html', arr=arr, time=currentTime, pattern=pattern)
app.debug=True
if __name__ == '__main__':
setup()
app.run()
Why is the back variable None instead of instance of Back class? Thanks
The Flask development server runs your module twice. Once to run the server itself, and another time in a child process so it can reload your whole script each time you make a change to it. It is that second process that won't run the __main__ guarded code and the global is left as None.
You'll get the same problem if you used another WSGI server; it'd import your file as a module, not as the initial script and the __main__ guard is not executed.
Use a #app.before_first_request function instead; it is guaranteed to be executed when the very first request is handled for this process. This also keeps your global working if you moved to a proper WSGI container that used multiple child processes to scale your site:
#app.before_first_request
def setup():
global back
back = Back.Back()

Python Serial Port with threading - freezing computer

Okay, time for another question/post...
So currently i am trying to develop a simple python program that has a webkit/ webpage view and a serial port interface.. Not that it should matter, but this is also running on a raspberry pi.
The following code works fine.. But it will freeze the system as soon as i uncomment the serial port line that you can see commented out.
The day has been long and this one for some reason has my brain fried.. Python is not my strongest point, but mind you this is just a quick test script for now... Yes i have used google and other resources...
#!/usr/bin/env python
import sys
import serial
import threading
import time
from PyQt4.QtCore import *
from PyQt4.QtGui import *
from PyQt4.QtWebKit import *
sURL = ""
sURL2 = ""
objSerial = serial.Serial(0)
def SerialLooper():
global objSerial
if objSerial.isOpen() == True:
print("is_responding")
#objSerial.write("is_responding")
time.sleep(10)
SerialLooper()
class TestCLASS(object):
def __init__(self):
global sURL
global sURL2
global objSerial
objSerial = serial.Serial(0)
sURL = "http://localhost/tester"
app = QApplication(sys.argv)
webMain = QWebView()
webMain.loadFinished.connect(self.load_finished)
webMain.load(QUrl(sURL))
webMain.show()
thread = threading.Thread(target=SerialLooper)
thread.start()
sys.exit(app.exec_())
def load_finished(boolNoErrors):
global sURL
print("Url - " + sURL)
#something here
#something else here
newObjClass = TestCLASS()
EDIT
Futher on this, it appears its not the multithreading but the serial.write()
It has been a while since I used serial, but IIRC it is not threadsafe (on Windows at least). You are opening the port in the main thread and performing a write in another thread. It's a bad practice anyway. You might also consider writing a simple single-threaded program to see if the serial port is actually working.
PS Your program structure could use some work. You only need one of the global statements (global objSerial), the rest do nothing. It would be better to get rid of that one, too.
And the recursive call to SerialLooper() will eventually fail when the recursion depth is exceeded; why not just use a while loop...
def SerialLooper():
while objSerial().isOpen(): # Drop the == True
# print something
# write to the port
# Sleep or do whatever

Kivy and XML RPC

I've been trying to perform communication between a kivy GUI module (my server) and another python module (my client). But so far I have problems running the xml rpc server along with the GUI run() function. I still have that problem even after running my server in a thread.
I hope someone has suggestions on how to fix my code, or just how to xml-rpc along with kivy.
Here is my code:
import kivy
kivy.require('1.7.1')
from kivy.lang import Builder
from kivy.uix.gridlayout import GridLayout
from kivy.app import App
from threading import Thread
from kivy.clock import Clock
Builder.load_file('kivy_gui.kv')
class RoamClientInterface(GridLayout):
"""
Sets up connection with XMLRPC server
"""
move = False
"""
driveForward() -> Moves robot forward
"""
def driveForward(self):
self.move = True
"""
stop() -> stops robot from moving
"""
def stop(self):
self.move = False
def returnBool(self):
return self.move
class ClientInterface(App):
def build(self):
return RoamClientInterface()
def sendCommands(dt):
print "start"
print ""
from SimpleXMLRPCServer import SimpleXMLRPCServer
server = SimpleXMLRPCServer(("localhost", 5000))
print "initialize server"
print ""
server.register_instance(RoamClientInterface())
print "register instance"
print ""
# while True:
try:
print "try handle request"
print ""
server.handle_request()
print "print handle request"
print ""
except KeyboardInterrupt:
import sys
sys.exit()
if __name__ == '__main__':
serverThread = Thread(target=sendCommands(4))
serverThread.start()
# Clock.schedule_once(sendCommands)
ClientInterface().run()
I got to solve the problem.
It is actually necessary to put it into a inside the RoamClientInterface to make it work, instead of putting it into my main function like I have it above.
I can give more detail info (show code) if anybody needs help

Categories

Resources