0

Im using the mqtt protocol to send messages of sensor data to a mosquitto broker .What I want to do is send the sensor data every t seconds but if I receive a message proccess it in parallel.I was thiking of using time.sleep() but I think that will delay the "on_message" function too .Im using paho-mqtt and python 2.7 . Any ideas on how I could accomplish such a thing ?

Client No1.(Sends the sensor data)

from mysignals import mysignals
import paho.mqtt.client as mqtt
import time  

def on_connect(client, userdata, rc):
    mqttc.subscribe(topic='/+/mysignals/status', qos=0)
    mqttc.subscribe(topic='/+/mysignals/add_sensor',qos=0)
    mqttc.subscribe(topic='/+/mysignals/remove_sensor',qos=0)

def on_message(client,userdata,message):
    print 'received data'
    base_topic = '/mysignals'
    member_id = message.topic.split('/')[1]
    status_topic = '/mysignals/status'
    add_sensor_topic = '/mysignals/add_sensor'
    remove_sensor_topic = '/mysignals/remove_sensor'
    log_topic = '/log'
    if status_topic in message.topic:
        action = mysignals_test.change_status(int(member_id),int(message.payload))
        mqttc.publish(topic='/'+member_id+status_topic+log_topic+'/',payload=action,qos=0)
    elif add_sensor_topic in message.topic:
        action = mysignals_test.add_sensor(message.playload,int(member_id))
        mqttc.publish(topic='/'+member_id+add_sensor_topic+log_topic+'/',payload=action,qos=0)
    elif remove_sensor_topic in message.topic:
        action = mysignals_test.remove_sensor(message.payload,int(member_id))
        mqttc.publish(topic='/'+member_id+remove_sensor_topic+log_topic+'/',payload=action,qos=0)
    else:
        mqttc.publish(topic='/'+member_id+base_topic+log_topic+'/',payload='Wrong Action.',qos=0)

mysignals_test = mysignals(email='blablabla',password='blabla')
mysignals_test.add_sensor('temp',150)
mysignals_test.change_status(150,1)
mqttc = mqtt.Client(client_id='mysignals')
mqttc.on_connect = on_connect
mqttc.on_message = on_message
mqttc.connect('broker ip')
mqttc.loop_start()

while True:
    for member in mysignals_test.members:
        if member.status == 1:
            live_data = mysignals_test.live(member.member_id)
            for data in live_data:
                topic = '/'+str(data.member_id)+'/mysignals/'+str(data.sensor_id)+'/'
                qos = 0
                retain = False
                if 'raw' in data.sensor_id:
                    payload = data.values
                else:
                    payload = data.value
                mqttc.publish(topic=topic,payload=payload,qos=qos,retain=retain)
    print 'sent data'
    time.sleep(55)

Client No2(Receives data from client 1.Only subscriber.Also sends a test message to client1.only subscriber too.)

import paho.mqtt.client as mqtt

def on_connect(client, userdata, rc):
    mqttc.subscribe(topic='/+/mysignals/+/', qos=0)
    mqttc.subscribe(topic='/+/mysignals/status/+/', qos=0)
def on_disconnect(client,userdata,rc):
    pass
def on_message(client, userdata, message):
    if str(message.payload) == '':
        print 'empty message'
    else:
        print 'Received message :' + str(message.payload) + ', on topic: '+ message.topic + ', with QoS: ' + str(message.qos) 
        mqttc.publish(topic='/154/mysignals/status',payload=0,qos=0)

mqttc = mqtt.Client(client_id='P1')
mqttc.on_connect = on_connect
mqttc.on_disconnect = on_disconnect
mqttc.on_message = on_message
mqttc.connect('broker ip')
mqttc.loop_start()

Just for the record "mysignals" object is made by me its not something that exists out there.The problem with code above is that ,when Client 2 receives the sensor data it hangs and sends the test message back to the broker indefinetely.The test message that client 2 sends when it receives the sensor data should be read by client 1 and the client1 should manipulate the "mysignals" object accordingly .

Client 2 Output:

Received message :25.4, on topic: /150/mysignals/temp/, with QoS: 0
Received message :Success, on topic: /154/mysignals/status/log/, with QoS: 0
Received message :Success, on topic: /154/mysignals/status/log/, with QoS: 0
Received message :Success, on topic: /154/mysignals/status/log/, with QoS: 0
Received message :Success, on topic: /154/mysignals/status/log/, with QoS: 0
Received message :Success, on topic: /154/mysignals/status/log/, with QoS: 0
Received message :Success, on topic: /154/mysignals/status/log/, with QoS: 0
Received message :Success, on topic: /154/mysignals/status/log/, with QoS: 0
Received message :Success, on topic: /154/mysignals/status/log/, with QoS: 0
Received message :Success, on topic: /154/mysignals/status/log/, with QoS: 0
Received message :Success, on topic: /154/mysignals/status/log/, with QoS: 0
Received message :Success, on topic: /154/mysignals/status/log/, with QoS: 0
Received message :Success, on topic: /154/mysignals/status/log/, with QoS: 0
Received message :Success, on topic: /154/mysignals/status/log/, with

Client 1 Output:

Login Successfull.
sent data
sent data
received data
received data
received data
received data
received data
received data
received data
received data

PS:Im not including "mysignals.py" because is about 200 lines.

2 Answers2

1

My understanding of the way that the callbacks function in the Paho MQTT library is that the background loop (started by loop_start) will interrupt the main thread so I wouldn't worry about delays from using time.sleep(). So if your main concern is in not delaying the on_message callback, it shouldn't be a problem. I regularly have used sleep in Python scripts with MQTT callbacks.

Of course the callback may slightly delay the sensor sending data, but do you actually need the data to be sent with absolutely precise timing? Most databases-for example RRD-can easily adapt to a slightly off update time. Alternatively if your on_message callback takes an unacceptably long time to process, consider passing the payload of the MQTT message out of the callback function and process it elsewhere in your script.

If you really do need split-second precision on the sensor updates consider separating the functions into two scripts (or threads) which each serve only one purpose (sending or receiving).

blp
  • 578
  • 1
  • 5
  • 9
0

Ok I managed to get the expected result .I had to make 2 subtopics on the status subtopic .One Client should write on the log subtopic of the status suptopic and one client should write on the value subtopic of the status subtopic .Also I removed the qos parameters on the subscribes.I also added the time.sleep() and I rarely miss a message .Only when 2 messages are received on a very small time interval .Biggest issue was that I hadnt understood how topics and subtopics actually work .