Search code examples
pythonmqtt

how to switch between connecting and disconnecting alternatingly mqtt in python


So I was wondering if I could switch between connecting to a broker, get some messages, disconnect, do some other code, and then connecting to the broker again, and repeat all the process from there.

I have something in mind to make a simple latch. But it doesn't work. Here is the code:

While latch = 0

import paho.mqtt.client as mqtt
import time

def on_connect(client, userdata, flags, rc):  # The callback for when the client connects to the broker
    print("Connected with result code {0}".format(str(rc)))  # Print result of connection attempt
    client.subscribe("trilaterasi/ESP1")
    client.subscribe("trilaterasi/ESP2")
    client.subscribe("trilaterasi/ESP3")
    
def on_message(client, userdata, msg):
    if msg.topic == 'trilaterasi/ESP1':
        global ESP1
        ESP1 = float(msg.payload)
        print("Msg rcvd" + msg.topic + " " + str(ESP1))
    elif msg.topic == 'trilaterasi/ESP2':
        global ESP2
        ESP2 = float(msg.payload)
        print("Msg rcvd" + msg.topic + " " + str(ESP2))
    elif msg.topic == 'trilaterasi/ESP3':
        global ESP3
        ESP3 = float(msg.payload)
        print("Msg rcvd" + msg.topic + " " + str(ESP3))
        
broker = "ipaddress"
latch = 0
while latch == 0:
    client = mqtt.Client("Python")
    client.loop_start()
    client.on_connect = on_connect
    client.on_message = on_message
    client.connect(broker)
    time.sleep(5)
    client.disconnect()
    client.loop_stop()
    latch = 1

While latch = 1

while latch == 1:
    #This is the coordinates of ESPs that are mounted to the wall
    ESP1x = 300
    ESP1y = 0
    ESP2x = 0
    ESP2y = 130
    ESP3x = 150
    ESP3y = 260
    #This is the Trilateration Formula
    a = 2*(-ESP1x + ESP2x)
    b = 2*(-ESP1y + ESP2y)
    c = (ESP1**2 - ESP2**2 - ESP1x**2 + ESP2x**2 - ESP1y**2 + ESP2y**2)
    d = 2*(-ESP2x + ESP3x)
    e = 2*(-ESP2y + ESP3y)
    f = (ESP2**2 - ESP3**2 - ESP2x**2 + ESP3x**2 - ESP2y**2 + ESP3y**2)
    #This is the estimated coordinate of the BLE device
    x = ((c*e-f*b)/(e*a-b*d))
    y = ((c*d-a*f)/(b*d-a*e))
    print(x)
    print(y)
    latch = 0

It gives the result but it only runs the code once. I'm pretty new to python and mqtt so I don't really know what I'm doing wrong. I was wondering if it because the while loop and tried changing it to if but it still only ran the code once. I feel like I'm missing something here so any advice is really appreciated!


Solution

  • If I understand your question correctly then you have two while loops:

    latch = 0
    while latch == 0:
       # Do stuff
       latch = 1
    while latch == 1:
       # Do other stuff
       latch = 0
    

    And are wondering why each loop is only run once? If you want the code to run continually then an outer loop is needed e.g.

    latch = 0
    while True:
       while latch == 0:
          # Do stuff
          latch = 1
       while latch == 1:
          # Do other stuff
          latch = 0
    

    In this case latch is not actually needed because latch is only (and always) changed at the end of each segment (so the while only runs once). You can simplify as:

    while True:
       # Do stuff from first while loop (connect to MQTT broker etc)
       # Do stuff from second while loop (formula etc)
    

    However it would be worth reconsidering the structure of your application. Connecting to a broker involves some overhead (establish connection, MQTT CONNECT handshake, in your case SUBSCRIBE packets etc) so it's often best to leave the connection open (rather than frequently disconnecting as you are). This has the added benefit of missing fewer messages (another way of addressing this is by setting the QOS). Maybe try something like this (rough pseudo code):

    def recalculate():
        #This is the coordinates of ESPs that are mounted to the wall
        ESP1x = 300
        # Do calculation required when values change...
    
    def on_message(client, userdata, msg):
        if msg.topic == 'trilaterasi/ESP1':
            global ESP1
            ESP1 = float(msg.payload)
            print("Msg rcvd" + msg.topic + " " + str(ESP1))
            recalculate()
        # Handle other messages 
    
    client = mqtt.Client("Python")
    client.on_connect = on_connect
    client.on_message = on_message
    client.connect(broker)
    
    # Blocking call that processes network traffic, dispatches callbacks and
    # handles reconnecting.
    client.loop_forever()