0

I'm trying to get a mqtt client receive all the messages from the topics it has subscribed to, but It receives only the first one every time I send the messages using another client.The problem is that the client should handle like 10 messages with qos 2 but instead handles only the first one.The messages are sent at the same time with a time interval of couple milliseconds. I'm not constantly sending messages.I send 10 messages every minute.Both clients are persistent. I'm certain that the message leaves the publisher because whenever a message is sent, I print it's payload. I'm using qos 2 because the messages received are then saved to a database and I don't want to have duplicates. The broker I use is activemq. So the question is why is this happening?

from sqlalchemy.ext.automap import automap_base
from sqlalchemy.orm import Session
from sqlalchemy import create_engine
from sqlalchemy import update
from sqlalchemy.ext.automap import generate_relationship
import sqlalchemy
import paho.mqtt.client as mqtt
import time  
#Function that define what to do on client conenction
def on_connect(client, userdata, rc):
    #Subscribe to all specified topics
    mqttc.subscribe(topic='/+/mysignals/sensors/+/')
def on_message(client,userdata,message):
    #Get the mysignals member id from the topic
    topic_split = message.topic.split('/')
    member_id = topic_split[1]
    session = Session(engine)
    sensor_id = topic_split[4]
    patient = session.query(Patient).filter(Patient.mysignalsid==member_id).first()
    if message.payload == None:
        payload = 0
    else:
        payload = message.payload
    if patient:
        current_time = time.time()
        if patient.id in pending.keys() and (current_time - pending[patient.id]['time_created']) <= 55:
            pending[patient.id]['record'].__dict__[sensor_id] = payload
            print time.time()
        else:
            pending.pop(patient.id,None)
            patientdata = PatientData()
            patientdata.__dict__[sensor_id] = payload
            print patientdata.__dict__[sensor_id]
            print payload
            print patientdata.temp
            patient.patientdata_collection.append(patientdata)
            session.add(patientdata)
            print time.time()
            pending.update({patient.id:{
                                    'time_created':time.time(),
                                    'record':patientdata,
                                    }})
        session.flush()
        session.commit()
        print('Wrote to database.')

pending = {}
Base = automap_base()
engine = create_engine('mysql+mysqlconnector://user:pass@localhost/db')
# reflect the tables
Base.prepare(engine, reflect=True)
Patient = Base.classes.patient
PatientData = Base.classes.patientdata
session = Session(engine)
#Create a mqtt client object
mqttc = mqtt.Client(client_id='database_logger',clean_session=False)
#Set mqtt client callbacks
mqttc.on_connect = on_connect
mqttc.on_message = on_message
#Set mqtt broker username and password
mqttc.username_pw_set('blah','blahblah')
#Connect to the mqtt broker with the specified hostname/ip adress
mqttc.connect('127.0.0.1')
mqttc.loop_forever()

Ouput:

98
98
None
1500576377.3
Wrote to database.
1500576377.43
Wrote to database.

Output should be:

98
98
None
1500576377.3
Wrote to database.
25.4
25.4
25.4
1500576377.43
Wrote to database.
Donald Duck
  • 8,409
  • 22
  • 75
  • 99
  • Edit the question to show your code – hardillb Jul 20 '17 at 18:30
  • I updated the post and added my code. – Θοδωρής Φλώκος Jul 20 '17 at 18:36
  • first, your topic should not start and end with a `/`, second what output do you get from your code? – hardillb Jul 20 '17 at 18:44
  • Edit the question, don't try and post output in comments – hardillb Jul 20 '17 at 18:47
  • Actually the message is received but its not written in the database so the mistake should be on the following line(I just printed the payload of the first part of the if statement):" pending[patient.id]['record'].__dict__[sensor_id] = payload" – Θοδωρής Φλώκος Jul 20 '17 at 19:10
  • 1
    You should post your solution in the answer. Also, you should not add "SOLVED" to the title, instead, you should accept your answer by clicking on the check mark on the left of your answer. For more information on how this site works, please read the [tour](https://stackoverflow.com/tour). – Donald Duck Jul 21 '17 at 00:24

1 Answers1

0

It wasn't a problem of the mqtt client in the end. The code was wrong and the second message wasn't written in the database.

In order to get it to work I had to replace the following line:

pending[patient.id]['record'].__dict__[sensor_id] = payload

with this one:

setattr(pending[patient.id]['record'],sensor_id,payload)

Also remove the line:

session = Session(engine)

outside of the on_message function.

I also added the line:

session.expunge_all()

below the line:

session.commit()

In order to clean the session each time a transaction is done in the database.

Donald Duck
  • 8,409
  • 22
  • 75
  • 99