Issue
I am currently trying to send a message via MQTT protocol which works. I am using a raspberry Pi and a vibration sensor as a means to trigger the sending of the message. At the start I would touch the sensor and it would send loads of messages at once which is what I dont want to happen. so I tried to make it sleep for 5 seconds after it detects vibration. But now it detects one vibration and then wont detect another one but doesnt stop the running of the file. the only way i can get it to detect the vibration again is to run the file again. here is the two ways I tried:
import time
from grove.gpio import GPIO
import paho.mqtt.client as mqttClient
class GrovePiezoVibrationSensor(GPIO):
def __init__(self, pin):
super(GrovePiezoVibrationSensor, self).__init__(pin, GPIO.IN)
self._on_detect = None
@property
def on_detect(self):
return self._on_detect
@on_detect.setter
def on_detect(self, callback):
if not callable(callback):
return
if self.on_event is None:
self.on_event = self._handle_event
self._on_detect = callback
def _handle_event(self, pin, value):
if value:
if callable(self._on_detect):
self._on_detect()
time.sleep(5000)
Grove = GrovePiezoVibrationSensor
def on_connect(client, userdata, flags, rc):
if rc == 0:
print("Connected to broker")
global Connected #Use global variable
Connected = True #Signal connection
else:
print("Connection failed")
Connected = False #global variable for the state of the connection
broker_address= "hairdresser.cloudmqtt.com"
port = 15767
user = "kprpjfue"
password = "1fIq2_CIwHZj"
client = mqttClient.Client("Python") #create new instance
client.username_pw_set(user, password=password) #set username and password
client.on_connect= on_connect
client.loop_start()
client.connect(broker_address, port=port)
def main():
from grove.helper import SlotHelper
sh = SlotHelper(SlotHelper.GPIO)
pin = sh.argv2pin()
pir = GrovePiezoVibrationSensor(pin)
def callback():
print('Detected.')
value = 'detected'
client.publish("sensor/Temp", value)
pir.on_detect = callback
while True:
time.sleep(5000)
if __name__ == '__main__':
main()
while Connected != True: #Wait for connection
time.sleep(0.1)
import time
from grove.gpio import GPIO
import paho.mqtt.client as mqttClient
class GrovePiezoVibrationSensor(GPIO):
def __init__(self, pin):
super(GrovePiezoVibrationSensor, self).__init__(pin, GPIO.IN)
self._on_detect = None
@property
def on_detect(self):
return self._on_detect
@on_detect.setter
def on_detect(self, callback):
if not callable(callback):
return
if self.on_event is None:
self.on_event = self._handle_event
self._on_detect = callback
def _handle_event(self, pin, value):
if value:
if callable(self._on_detect):
self._on_detect()
time.sleep(5000)
Grove = GrovePiezoVibrationSensor
def on_connect(client, userdata, flags, rc):
if rc == 0:
print("Connected to broker")
global Connected #Use global variable
Connected = True #Signal connection
else:
print("Connection failed")
Connected = False #global variable for the state of the connection
broker_address= "hairdresser.cloudmqtt.com"
port = 15767
user = "kprpjfue"
password = "1fIq2_CIwHZj"
client = mqttClient.Client("Python") #create new instance
client.username_pw_set(user, password=password) #set username and password
client.on_connect= on_connect
client.connect(broker_address, port=port)
def main():
from grove.helper import SlotHelper
sh = SlotHelper(SlotHelper.GPIO)
pin = sh.argv2pin()
pir = GrovePiezoVibrationSensor(pin)
def callback():
print('Detected.')
value = 'detected'
client.publish("sensor/Temp", value)
pir.on_detect = callback
while True:
time.sleep(5000)
client.loop()
if __name__ == '__main__':
main()
while Connected != True: #Wait for connection
time.sleep(0.1)
As you can see under the if callable in the handle event method I told I say time.sleep(5000). Am I putting this in the wrong place?
Solution
You have not started the MQTT client network loop so it will not be able receive messages or send a message large the the MTU.
You will also get disconnected after the keep alive period.
Add client.loop_start()
before the call to client.connect()
or insert client.loop()
after the time.sleep(5000)
in the loop in main and it will be better to make it 1000 to the client loop runs at least once a second.
Adding sleeps in callbacks is normally a bad idea as it doesn't stop events from being triggered it just delays them, because they will just be queued up until the sleep times out.
You should set a flag on the first event just after sending the MQTT message which you can then expire using the While True loop in main. If a new event comes in while the flag is still set then you just don't send another MQTT message.
Answered By - hardillb Answer Checked By - Willingham (WPSolving Volunteer)