Reputation: 387
Right now I am sitting on a project, where a python script subscribes to a topic on the broker and waits for a message. When a message is received the script takes some actions and shows an image for about 5 seconds. To this point everything works.
The problem I am struggling with is that when a message comes in while the function is already executing, the function gets directly executed again after it finishes. For example: If 3 messages get published directly one after another, the function gets called one after another, showing three times the image.
The behaviour I want to achieve is that messsages which get published while the function is already executing are ignored.
This link (http://www.steves-internet-guide.com/loop-python-mqtt-client/) says that:
When new messages arrive at the Python MQTT client they are placed in a receive buffer.
The messages sit in this receive buffer waiting to be read by the client program.
I think that's the problem! But I don't understand how I can avoid this buffering behaviour.
Like suggested I tried playing around with setting flags etc but this doesn't worked.
For a better understanding I wrote a simple script which prints 1, 2, 3, 4, 5
when a message is published
#!/usr/bin/env python
import os, os.path
import time
import subprocess
import paho.mqtt.client as mqtt
mqtt_username = "user"
mqtt_password = "password"
mqtt_topic = "Topic"
def on_connect(client, userdata, flags, rc):
client.subscribe(mqtt_topic)
def on_message(client, userdata, msg):
print('1')
time.sleep(1)
print('2')
time.sleep(1)
print('3')
time.sleep(1)
print('4')
time.sleep(1)
print('5')
time.sleep(1)
print('---')
client = mqtt.Client()
client.on_connect = on_connect
client.on_message = on_message
client.username_pw_set(mqtt_username, mqtt_password)
client.connect("localhost", 1883, 60)
client.loop_forever()
The messages are getting published with this command:
mosquitto_pub -d -u user -P password -t Topic -m "Hello"
Publishing one message everything is fine. Publishing three messages directly one after another results in this output:
1
2
3
4
5
---
1
2
3
4
5
---
1
2
3
4
5
---
But it should result in this output, ignoring the other two messages:
1
2
3
4
5
---
Upvotes: 0
Views: 3703
Reputation: 1489
The function could return a timestamp that is saved globally. Then you could check that timestamp in the first line of the function and return immediately, if the difference between systemtime and that timestamp is too small:
from datetime import datetime
lastMessage = 0
def on_message(client, userdata, msg):
if datetime.now().timestamp() - globals()['lastMessage'] > 5 # sec:
//this function shows an image for about 5 seconds
globals()['lastMessage'] = datetime.now().timestamp()
Upvotes: 0
Reputation: 1059
You can have a global bool variable functionCalled
to hold whether the function is called and another variable t
to hold time.time()
to record the time when function is called. Maybe you don't need a variable to hold time according to your description, but just in case.
if functionCalled:
functionCalled = false
if Time.time() - t < 5 seconds:
# DontShowImage
else:
functionCalled = true
t = time.time()
# show image`
Upvotes: 0