Global variable's value doesn't change in a thread - python

I'm making a flask application, and when the user presses a button I want for a thread to pause until the button is pressed again, and i'm planning to do this with a flag being set off. The thread can read the initial value of the flag, but when the user presses the button and the value is changed, the value remains false in the thread. It can read it successfully, but it just can't change it. I've tried making it global but it still has no effect. Here is the source -
web = False
#app.route("/")
def bg_func():
print('Thread test')
while True:
if web == False :
if Facial_Check.run() == True:
face_detected = True
t = Thread(target=bg_func)
t.start()
#app.route("/<changePin>/<action>")
def action(changePin, action):
changePin = int(changePin)
deviceName = pins[changePin]['name']
global web
if action == "on":
GPIO.output(changePin, GPIO.HIGH)
time.sleep(1)
GPIO.output(changePin, GPIO.LOW)
web = True
current_status = True
message = "Turned computer on."
if action == "off":
GPIO.output(changePin, GPIO.HIGH)
time.sleep(1)
GPIO.output(changePin, GPIO.LOW)
web = False
current_status = False
face_detected = False
message = "Turned computer off."
for pin in pins:
pins[pin]['state'] = GPIO.input(pin)
return render_template('index.html', Status=current_status)

You should use thread-specific features to be able share data between threads.
You may use current_thread for these purposes:
from flask import Flask
from time import sleep
from threading import Thread, current_thread
app = Flask(__name__)
web = current_thread()
def bg_func():
i = 0
while i < 100:
i += 1
sleep(2)
print('web is', getattr(web, 'web', None))
#app.route("/<my_web>")
def index(my_web = '0'):
before = getattr(web, 'web', None)
if my_web == '1':
setattr(web, 'web', True)
else:
setattr(web, 'web', False)
after = getattr(web, 'web', None)
return f"set {before} to {after}"
if __name__ == '__main__':
setattr(web, 'web', False)
t = Thread(target=bg_func)
t.start()
app.run(host='127.0.0.1', port=8080)
browser output will be:
set False to True
when access http://127.0.0.1:8080/1 first time
terminal output will be:
web is False
web is False
web is True
web is True
...
Update: adding example with socket client →
I added socket listeners as in your example:
Server side
from flask import Flask
from time import sleep
from threading import Thread, current_thread
from flask_socketio import SocketIO
def bg_func():
print('Thread test')
while True:
sleep(1)
print('web is ' + str(web.web))
app = Flask(__name__)
web = current_thread()
socketio = SocketIO(app)
setattr(web, 'web', None)
#app.route("/")
def action():
return 'web is ' + str(web.web)
#socketio.on('connect')
def connect():
setattr(web, 'web', True)
print('Client connected to server ')
#socketio.on('disconnect')
def disconnect():
setattr(web, 'web', False)
print('Client disconnected from server ')
if __name__ == "__main__":
t = Thread(target=bg_func)
t.start()
socketio.run(app, host='127.0.0.1', port=7878, debug=False)
Client side:
import socketio
sio = socketio.Client()
sio.connect('http://127.0.0.1:7878')
When I using client the output at server side is looking like:
...
web is None
web is None
...
Client connected to server
web is True
web is True
...
Client disconnected from server
web is False
web is False
...
BUT!
as you can see here is debug=False in my code. That is because of Flask run two app threads in DEBUG mode.
So first of web is controlled by you, second one is never changing and always will show None (if you change debug to True).

Related

Why Python console hangs when printed text is highlighted

I'm facing a problem with Python and Threads: I have a daemon thread that continuously prints "TEST" in the console, every 5 seconds.
When the console is open, and I try to highlight a few lines of text, the thread stops and it doesn't continue until I press a key on the keyboard.
Here is my code:
import threading
import time
def thread_function():
t = threading.current_thread()
while getattr(t, 'do_run', True):
print('TEST')
time.sleep(5)
def main():
x = threading.Thread(target = thread_function)
x.daemon = True
x.start()
time.sleep(1000)
x.do_run = False
x.join()
if __name__ == '__main__':
main()
Which is the cause of this behavior?

Web Push Is Not Being Executed In Job Scheduler

The job scheduler is being executed but for some reason the web push is not activated.I tried calling the web push function without the job scheduler and it does trigger a notification on browser. However, nothing gets triggered when I call it in the add_job scheduler function. The GET reminders should be called after the job scheduler if the web push were to be activated FYI. Please help.
#app.route("/notification", methods = ['POST', 'PUT'])
#token_required
def setNotifications(current_user, token):
if request.method == 'POST':
form = json.loads(request.data.decode('UTF-8'))
subscription = form["subscription"]
subscriptionId = form["subscriptionId"]
dailyReminder = True if form['daily'] is True else False
weeklyReminder = True if form['weekly'] is True else False
yearlyReminder = True if form['yearly'] is True else False
createNotif = db.session.query(User).filter(User.id == current_user.id).first()
reminder = db.session.query(Reminder).filter(Reminder.subscriptionId == subscriptionId).first()
message = json.dumps({"token": token, "subscriptionId": subscriptionId})
# print("Printing message" + message)
VAPID_CLAIMS = {
"sub": "my email"
}
if(createNotif.subscription == " "):
createNotif.subscription = json.dumps(subscription)
db.session.commit()
try:
# print("entering code")
sched.add_job(lambda:modules.send_web_push(json.loads(createNotif.subscription), message, VAPID_PRIVATE_KEY, VAPID_CLAIMS), 'date', run_date = datetime.date(2021, 5,8))
sched.start()
# modules.send_web_push(json.loads(createNotif.subscription), message, VAPID_PRIVATE_KEY, VAPID_CLAIMS)
# print("started here", flush= True)
return jsonify({'success':1})
except Exception as e:
print("error",e)
print("Could not send notification", flush=True)
return jsonify({'failed':str(e)})
if request.method == 'PUT':
removeSubscription = db.session.query(User).filter(User.id == current_user.id).first()
removeSubscription.subscription = " "
db.session.commit()
return jsonify({"success": "push notification has been updated"}), 200

Python timer in if else statement

I'm trying to create a timer that starts when a condition for an if statement is met and then stops and returns the duration when elif condition is met, is this possible?
The purpose of the application is to send a true or false value to AWS IoT from an Android application. The Python script is subscribed to AWS and receives the value and uses it to determine whether the led should be on or off.
The code I have:
from AWSIoTPythonSDK.MQTTLib import AWSIoTMQTTClient
import RPi.GPIO as GPIO
import sys
import logging
import time
from time import sleep
from timeit import default_timer as timer
import getopt
import grovepi
msgpay = None
# Custom MQTT message callback
def customCallback(client, userdata, message):
print("Received a new message: ")
print(message.payload)
print("from topic: ")
print(message.topic)
print("--------------\n\n")
global msgpay
msgpay = message.payload
led = 5
grovepi.pinMode(led, "OUTPUT")
start_time = timer()
if msgpay == "true":
print("turning on")
grovepi.digitalWrite(led, 1)
#time.sleep(3)
elif msgpay == "false":
print("turning off")
grovepi.digitalWrite(led, 0)
duration = timer() - start_time
print duration
Any help how to go about this would be appreciated.
Thanks

Socket receiving in while 1

I'm trying to create socket connections in python. I need to listen to server until it sends a message, thus I need to use while True.
Client:
import RPi.GPIO as GPIO
import time
import socket
GPIO.setmode(GPIO.BOARD)
pinLDR = 7
pinLED = 11
touch = False
sock = socket.socket()
sock.connect(('192.168.1.67', 9092))
while True:
print sock.recv(256)
def rc_time ():
count = 0
GPIO.setup(pinLDR, GPIO.OUT)
GPIO.output(pinLDR, GPIO.LOW)
time.sleep(0.1)
GPIO.setup(pinLDR, GPIO.IN)
while (GPIO.input(pinLDR) == GPIO.LOW):
count += 1
return count
def led(lh):
GPIO.setup(pinLED, GPIO.OUT)
if lh == 1:
GPIO.output(pinLED, GPIO.HIGH)
else:
GPIO.output(pinLED, GPIO.LOW)
try:
while True:
print(str(rc_time()))
if rc_time() > 5000:
if touch == False:
print "triggered"
sock.send("triggered")
touch = True
else:
if touch == True:
sock.send("nottriggered")
print "nottriggered"
touch = False
except KeyboardInterrupt:
pass
finally:
GPIO.cleanup()
sock.close()
But I have a problem with it. Nothing is printed even if a server sends a message. And the whole code after first while True doesn't work
UPDATE: The issue with the code in the question is that it has an infinite loop at the top. None of the code below this will ever execute:
while True:
print sock.recv(256)
(And apparently this particular server doesn't send a message until it's received one first, so it will never send anything.)
Here's a simple working example. If this doesn't help, you'll need to provide more context in your question.
Here's the client:
import socket
s = socket.socket()
s.connect(('localhost', 12345))
while True:
print s.recv(256)
Corresponding server code:
import socket
import time
s = socket.socket()
s.bind(('', 12345))
s.listen(0)
conn, addr = s.accept()
while True:
conn.send("Hello")
time.sleep(10)

Tkinter gui with client server in Python

I have used a Tkinter to create a simple gui with client server running . However, I can get the client server communicating for what ever reason . Can someone look at my code an tell me why it is not working
Server :
import Tkinter as tk
import os
import socket # Required to allow network communicate
import re
w, h = 500, 200
connection = None
def key(self, event):
self.frame.focus_force()
connection.send(event.keysym) # Sends the command to the robot
def SendEnterCommand(event): # Bound to the Enter key
connection.send("enter") # Sends the command to the robot
print('Sent Message - Enter') # Feedback for the controller
def SendSpaceCommand(event): # Bound to the Space key
connection.send("space") # Sends the command to the robot
print('Sent Message - Space')# Feedback for the controller
def SendKillCommand(event): # Bound to the Escape key
connection.send("kill") # Sends the command to the robot
print('Sent Message - Kill')# Feedback for the controller
# Used to check if the IP address follows the correct format
def CheckIP(IP):
pat = re.compile("^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$") # Check if the ip address value inputted follows the form of an ip address
test = pat.match(IP)
if test:
return True
else:
return False
def UpdateConnection(IPAddress, Port):
currentCommand = "empty"
serversocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # Initialise the socket
serversocket.bind((IPAddress, Port)) # Set up the socket on YOUR IP address and selected port
serversocket.listen(5) # Listen on the socket, up to 5 backlogged connections
print('waiting for a connection')
connection, client_address = serversocket.accept() # Wait for a connection, when there is one accept it
print ('Connected with ' + client_address[0] + ':' + str(client_address[1])) # Print who we are connected to
data = ""
while data != 'Kill': # Loop until the escape key is pressed
root.update()
def SetUpConnection():
IPAddress = IPEntry.get()
Port = int(PortEntry.get())
if CheckIP(IPAddress) and isinstance( Port, int ) and Port > 0 and Port < 9999: # check if the ip address is of the correct format, check if the port is an integer and greater than 0
#if InputMethodSelection.get() >= 1 and InputMethodSelection.get() <= 4: # check if there is a valid selected input option
print( "Connecting", "Connecting To Server!")
UpdateConnection(IPAddress, Port) # Connect and run the server
#else:
# print( "ERROR", "Select an input type!")
else:
tkMessageBox.showinfo( "ERROR", "Invalid IP address or port")
# Add a couple widgets. We're going to put pygame in `embed`.
root = tk.Tk()
embed = tk.Frame(root, width=w, height=h)
embed.pack()
BroadcastBTN = tk.Button(root, text='Broadcast', command=SetUpConnection)
BroadcastBTN.pack()
tk.Label(root, text="IP:").pack(anchor = "w")
IPEntry = tk.Entry(root)
IPEntry.config(width=20)
IPEntry.pack(anchor = "w")
tk.Label(root, text="Port:").pack(anchor = "w")
PortEntry = tk.Entry(root)
PortEntry.config(width=10)
PortEntry.pack(anchor = "w")
# Show the window so it's assigned an ID.
root.update()
root.bind("<Key>", key)
root.bind("<Return>", SendEnterCommand)
root.bind("<space>", SendSpaceCommand)
root.bind("<Escape>", SendKillCommand)
root.mainloop()
Client:
import socket # Required to allow network
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # Initialise the socket
print('Connecting') # user guidance output
sock.connect(("192.168.1.59", 9559))
data = ""
print('I AM CONNECTED') # user guidance output
while data != 'Kill': # Loop until the computer tries to close the connection
data = sock.recv(1024) # Recieve data from the connection
if(data == "EnterPressed"):
print("Enter Pressed")
elif(data == "space"):
print("Space Pressed")
elif(data == "forward"):
print("Forward Pressed")
elif(data == "left"):
print("Left Pressed")
elif(data == "right"):
print("Right Pressed")
elif(data == "backward"):
print("Backward Pressed")
elif(data == "pressed"):
print("pressed Pressed")
else:
print(data)
sock.close()
print('DISCONNECTED') # user guidance output

Categories