I have a pi running in a while true
python loop listening for RF signals. I also want it to listen for an MQTT signal and on receipt take a singe image with the camera. How do I set this up?
while true:
if MQTT received:
take photo
else
pass
I though about having a string variable that gets over-written by the MQTT message, then the camera picture is taken, and the string variable set to its original value, but I am sure there must be a better way…
You need to use the paho-mqtt python package in async or threaded mode. Since RF signals are probably time critical, I think you will need to go with threaded mode, to keep the delays waiting for mqtt messages out of the main loop.
I did much the same in my Energenie MQTT Client, but that’s in C rather than Python, so not much direct help.
1 Like
Solved, as per the example at https://pypi.python.org/pypi/paho-mqtt/1.1#subscribe-unsubscribe
Just place some processing in the on_message function:
def on_message(client, userdata, msg):
payload = str(msg.payload.decode('ascii')) # decode the binary string
print(msg.topic + " " + payload)
process_trigger(payload)
def process_trigger(payload):
if payload == 'ON':
print('ON triggered')
Full script - camera on remote pi triggered either by rf or mqtt and posts the captured image to HASS using mqtt:
import paho.mqtt.client as mqtt
import paho.mqtt.publish as publish
import picamera
import argparse
import signal
import sys
import time
import logging
from rpi_rf import RFDevice
rfdevice = None
### camera
camera = picamera.PiCamera()
camera.vflip=True
def post_image():
print('Taking photo')
camera.capture('img.jpg')
with open('img.jpg', "rb") as imageFile:
myFile = imageFile.read()
data = bytearray(myFile)
client.publish('dev/camera', data, mqttQos, mqttRetained) #
print('image published')
### MQTT
broker = '192.168.0.100'
topic ='dev/test'
mqttQos = 0
mqttRetained = False
def on_connect(client, userdata, flags, rc):
print("Connected with result code "+str(rc))
client.subscribe(topic)
# The callback for when a PUBLISH message is received from the server.
def on_message(client, userdata, msg):
payload = str(msg.payload.decode('ascii')) # decode the binary string
print(msg.topic + " " + payload)
process_trigger(payload)
def process_trigger(payload):
if payload == 'ON':
print('ON triggered')
post_image()
client = mqtt.Client()
client.on_connect = on_connect # call these on connect and on message
client.on_message = on_message
client.username_pw_set(username='user',password='pass') # need this
client.connect(broker)
client.loop_start() # run in background and free up main thread
### RF
# pylint: disable=unused-argument
def exithandler(signal, frame):
rfdevice.cleanup()
sys.exit(0)
logging.basicConfig(level=logging.INFO, datefmt='%Y-%m-%d %H:%M:%S',
format='%(asctime)-15s - [%(levelname)s] %(module)s: %(message)s', )
parser = argparse.ArgumentParser(description='Receives a decimal code via a 433/315MHz GPIO device')
parser.add_argument('-g', dest='gpio', type=int, default=27,
help="GPIO pin (Default: 27)")
args = parser.parse_args()
signal.signal(signal.SIGINT, exithandler)
rfdevice = RFDevice(args.gpio)
rfdevice.enable_rx()
timestamp = None
logging.info("Listening for codes on GPIO " + str(args.gpio))
code_of_interest = '9812234'
while True:
if rfdevice.rx_code_timestamp != timestamp:
timestamp = rfdevice.rx_code_timestamp
print(str(rfdevice.rx_code))
if str(rfdevice.rx_code) == code_of_interest:
post_image()
time.sleep(0.01)
rfdevice.cleanup()