Reputation: 89
I have a python script which I am trying to work with paho mqtt and time delay. I have looked into similar questions which discuss paho mqtt like Controlling Program with MQTT and Python. My python script is as follows:
Here is my script:
import paho.mqtt.client as mqttClient
import time
import subprocess
import os
global lastprocessed, Connected
lastprocessed = None
Connected = False #global variable for the state of the connection
def on_connect(client, userdata, flags, rc):
if rc == 0:
print("Connected to broker")
global Connected
Connected = True #Signal connection
else:
print("Connection failed")
def on_message(client, userdata, message):
global lastprocessed
if message.payload.decode() == "hello":
lastprocessed = time.time()
if lastprocessed and time.time() - lastprocessed < 20:
print("good")
broker_address= "192.168.1.111" #Broker address
port = 1883 #Broker port
user = "abcde" #Connection username
password = "12345" #Connection password
client = mqttClient.Client("Python") #create new instance
client.username_pw_set(user, password=password) #set username and password
client.on_connect= on_connect #attach function to callback
client.on_message= on_message #attach function to callback
client.connect(broker_address,port,60) #connect
client.subscribe("home/OpenMQTTGateway/433toMQTT") #subscribe
client.loop_forever() #then keep listening forever
What is happening with my code above is that, whenever "hello" is received in the payload it prints "good" but if anything else is received in the payload including "hello" it continues printing "good". It doesn't take into consideration the time of 20 seconds. I am not sure why?
What I am trying to achieve is the following:
Updated question 24/03/2021:
So my new script below keeps printing "Connected to Broker" initially it wasnt and I havent changed anything but now somehow it keeps printing and the if statements are not executed at all.
I know my script worked fine but I just need the if statements to be executed and the continuous loop i.e. continuous printing of "Connected to Broker" to stop.
import paho.mqtt.client as mqttClient
import time
import subprocess
import os
import json
global lastprocessed, Connected
lastprocessed = None
Connected = False #global variable for the state of the connection
def on_connect(client, userdata, flags, rc):
if rc == 0:
print("Connected to broker")
global Connected
Connected = True #Signal connection
else:
print("Connection failed")
x = y = 0
def on_message(client, userdata, message):
global x, y
global lastprocessed
a = str(message.payload)
data = json.loads(a);
j = data["contact"]
print(j)
if j == False:
x += 1
print(x)
if j == True:
y += 1
print(y)
if x == 1 or x == 0 and y == 1:
os.system("vcgencmd display_power 1")
if y == 2:
x = y = 0
os.system("vcgencmd display_power 0")
broker_address= "192.168.XXX.XXX" #Broker address
port = 1883 #Broker port
user = "XXXX" #Connection username
password = "XXXX" #Connection password
client = mqttClient.Client("Python") #create new instance
client.username_pw_set(user, password=password) #set username and password
client.on_connect= on_connect #attach function to callback
client.on_message= on_message #attach function to callback
client.connect(broker_address,port,60) #connect
client.subscribe("zigbee2mqtt/Xiaomi Door Sensor 2") #subscribe
client.loop_forever() #then keep listening forever
Upvotes: 0
Views: 6418
Reputation: 142651
I use loop_start()
and loop_stop()
instead of loop_forever()
and then between start
and stop
I can create own loop which can check messages and print text.
I use variable state
to control if code is before first hello
(state = "start"
) or it gets hello
and now it has to check time and repeate text "good" (state = "hello"
) or it has 20 seconds after hello
and it has print nothing (state = "other")
Inside on_message
I only change state to hello
when I get message hello
and old state is different then hello
.
import paho.mqtt.client as mqttClient
import time
# --- functions ---
def on_connect(client, userdata, flags, rc):
#global state
global connected
if rc == 0:
print("Connected to broker")
connected = True
else:
print("Connection failed")
def on_message(client, userdata, message):
global state
global last_processed
if message.payload.decode() == "hello":
if state != 'hello':
state = 'hello'
last_processed = time.time()
# OR
#if state != 'hello':
# if message.payload.decode() == "hello":
# state = 'hello'
# last_processed = time.time()
# --- main ---
broker_address = "192.168.1.111" # broker address
port = 1883 # broker port
user = "abcde" # connection username
password = "12345" # connection password
# ---
client = mqttClient.Client("Python") # create new instance
client.username_pw_set(user, password=password) # set username and password
client.on_connect= on_connect # attach function to callback
client.on_message= on_message # attach function to callback
client.connect(broker_address, port, 60) # connect
client.subscribe("home/OpenMQTTGateway/433toMQTT") # subscribe
# --- main loop ---
last_processed = None
connected = False # signal connection
state = 'start' # 'start', 'hello', 'other', 'not connected'
# ---
client.loop_start()
try:
while True:
if not connected:
print('not connected')
if state == 'start':
print('bad')
if state == 'hello':
if last_processed and time.time() - last_processed < 20:
print("good", time.time() - last_processed, end='\r') # '\r` to write it in the same line.
else:
print('bad')
state = 'other'
last_processed = None
if state == 'other':
pass
time.sleep(1.0) # to slow down example
except KeyboardInterrupt:
print('KeyboardInterrupt')
client.loop_stop()
EDIT:
If you need bad
and hello
only once then you can print first bad
before loop, and hello
when you get message and then time.sleep(20)
before you print bad
and change steate.
import paho.mqtt.client as mqttClient
import time
# --- functions ---
def on_connect(client, userdata, flags, rc):
#global state
global connected
if rc == 0:
print("Connected to broker")
connected = True
else:
print("Connection failed")
def on_message(client, userdata, message):
global state
message = message.payload.decode()
if state != 'hello':
if message == 'hello':
state = 'hello'
print('good') # once when start `hello`
else:
print('msg:', message)
# --- main ---
broker_address = "192.168.1.111" # broker address
port = 1883 # broker port
user = "abcde" # connection username
password = "12345" # connection password
# ---
client = mqttClient.Client("Python") # create new instance
client.username_pw_set(user, password=password) # set username and password
client.on_connect= on_connect # attach function to callback
client.on_message= on_message # attach function to callback
client.connect(broker_address, port, 60) # connect
client.subscribe("home/OpenMQTTGateway/433toMQTT") # subscribe
# --- main loop ---
connected = False # signal connection
state = 'other' # 'hello'
# ---
client.loop_start()
print('bad') # once at start
try:
while True:
if state == 'hello':
time.sleep(20)
print('bad') # once when end `hello`
state = 'other'
time.sleep(1.0) # to slow down example
except KeyboardInterrupt:
print('KeyboardInterrupt')
client.loop_stop()
It would be useful to use threading.Timer
instead of time.sleep()
because sleep()
blocks loop and it is not so useful if you want to do something more.
import paho.mqtt.client as mqttClient
import threading
# --- functions ---
def on_connect(client, userdata, flags, rc):
#global state
global connected
if rc == 0:
print("Connected to broker")
connected = True
else:
print("Connection failed")
def on_message(client, userdata, message):
global state
message = message.payload.decode()
if state != 'hello':
if message == 'hello':
state = 'hello'
print('good') # once when start `hello`
threading.Timer(20, end_hello).start()
else:
print('msg:', message)
def end_hello():
global state
print('bad') # once when end `hello`
state = 'other'
# --- main ---
broker_address = "192.168.1.111" # broker address
port = 1883 # broker port
user = "abcde" # connection username
password = "12345" # connection password
# ---
client = mqttClient.Client("Python") # create new instance
client.username_pw_set(user, password=password) # set username and password
client.on_connect= on_connect # attach function to callback
client.on_message= on_message # attach function to callback
client.connect(broker_address, port, 60) # connect
client.subscribe("home/OpenMQTTGateway/433toMQTT") # subscribe
# --- main loop ---
connected = False # signal connection
state = 'other' # 'hello'
# ---
print('bad') # once at start
client.loop_forever()
Eventually you can still check time in loop
import paho.mqtt.client as mqttClient
import time
# --- functions ---
def on_connect(client, userdata, flags, rc):
#global state
global connected
if rc == 0:
print("Connected to broker")
connected = True
else:
print("Connection failed")
def on_message(client, userdata, message):
global state
global last_processed
message = message.payload.decode()
if state != 'hello':
if message == 'hello':
state = 'hello'
last_processed = time.time()
print('good') # once when start `hello`
else:
print('msg:', message)
# --- main ---
broker_address = "192.168.1.111" # broker address
port = 1883 # broker port
user = "abcde" # connection username
password = "12345" # connection password
# ---
client = mqttClient.Client("Python") # create new instance
client.username_pw_set(user, password=password) # set username and password
client.on_connect= on_connect # attach function to callback
client.on_message= on_message # attach function to callback
client.connect(broker_address, port, 60) # connect
client.subscribe("home/OpenMQTTGateway/433toMQTT") # subscribe
# --- main loop ---
last_processed = None
connected = False # signal connection
state = 'other' # 'hello'
# ---
client.loop_start()
print('bad') # once at start
try:
while True:
if state == 'hello':
if time.time() >= last_processed + 20:
print('bad') # once when end `hello`
state = 'other'
time.sleep(1.0) # to slow down example
except KeyboardInterrupt:
print('KeyboardInterrupt')
client.loop_stop()
Upvotes: 2