#Local MQTT communication

1 messages ยท Page 1 of 1 (latest)

barren zodiac
#

I'm creating this thread to keep information about your problem in a easier to access location by the way

full bluff
#

Thanks , will use this going forward

barren zodiac
#

Awesome! That'll make it easier for me to keep track of the adjustments. Since I've been looking at using mqtt at some point I was interested

#

Additionally, I would use one of the nightly builds, not the beta, just because right now the nightly is pretty stable

full bluff
#

I just loaded the board with nightly build and initiated the code.py . Its executing fine as of now , Will have to wait a few minutes to see if I 'm hitting the connection error . Will keep you posted

full bluff
#

so after few minutes I got the communication error but it auto connected again which is good . The auto connect did not happen in 6.3

#

O2: 1786 ppm
Temperature: 26.4 *C
Humidity: 51.3 %
Publishing to airquality/co2
Traceback (most recent call last):
File "code.py", line 121, in <module>
File "adafruit_minimqtt/adafruit_minimqtt.py", line 754, in reconnect
File "adafruit_minimqtt/adafruit_minimqtt.py", line 441, in connect
File "adafruit_minimqtt/adafruit_minimqtt.py", line 266, in _get_connect_socket
File "adafruit_esp32spi/adafruit_esp32spi_socket.py", line 75, in connect
File "adafruit_esp32spi/adafruit_esp32spi.py", line 761, in socket_connect
File "adafruit_esp32spi/adafruit_esp32spi.py", line 663, in socket_open
File "adafruit_esp32spi/adafruit_esp32spi.py", line 325, in _send_command_get_response
File "adafruit_esp32spi/adafruit_esp32spi.py", line 295, in _wait_response_cmd
File "adafruit_esp32spi/adafruit_esp32spi.py", line 277, in _check_data
RuntimeError: Expected 01 but got 00

Code done running.

Adafruit CircuitPython 7.0.0-rc.0-6-g4922e67b8 on 2021-09-02; Adafruit Matrix Portal M4 with samd51j19

soft reboot

Auto-reload is on. Simply save files over USB to run them or enter REPL to disable.
code.py output:
Connecting to WiFi...
Connected!
Attempting to connect to 192.168.11.123
Connected to MQTT Broker!

barren zodiac
#

hmmm. I'm not fond of the soft reboot, but if it solves your problem that's good.

barren zodiac
#

Personally I'd rather 'try again', can you post your code around line 121?

full bluff
#

And it failed again with the error. This time it did not auto start

#

Traceback (most recent call last):
File "code.py", line 121, in <module>
File "adafruit_minimqtt/adafruit_minimqtt.py", line 754, in reconnect
File "adafruit_minimqtt/adafruit_minimqtt.py", line 441, in connect
File "adafruit_minimqtt/adafruit_minimqtt.py", line 266, in _get_connect_socket
File "adafruit_esp32spi/adafruit_esp32spi_socket.py", line 75, in connect
File "adafruit_esp32spi/adafruit_esp32spi.py", line 761, in socket_connect
File "adafruit_esp32spi/adafruit_esp32spi.py", line 663, in socket_open
File "adafruit_esp32spi/adafruit_esp32spi.py", line 325, in _send_command_get_response
File "adafruit_esp32spi/adafruit_esp32spi.py", line 295, in _wait_response_cmd
File "adafruit_esp32spi/adafruit_esp32spi.py", line 277, in _check_data
RuntimeError: Expected 01 but got 00

#

Sure will do

#

Line 121-- mqtt_client.reconnect()

barren zodiac
#

could you post like ten lines above and below that?

full bluff
#

Get Values from sensor

i2c = board.I2C()
scd4x = adafruit_scd4x.SCD4X(i2c)
print("Serial number:", [hex(i) for i in scd4x.serial_number])

scd4x.start_periodic_measurement()
print("Waiting for first measurement....")

while True:
try:
if scd4x.data_ready:
print("CO2: %d ppm" % scd4x.CO2)
print("Temperature: %0.1f *C" % scd4x.temperature)
print("Humidity: %0.1f %%" % scd4x.relative_humidity)
print("Publishing to %s" % mqtt_topic)
mqtt_client.publish(mqtt_topic, "%d" % scd4x.CO2)
print()
time.sleep(60)
except RuntimeError:
wifi.reset()
mqtt_client.reconnect()

#

121 is the last line

barren zodiac
#

ok, let's try some changes. Give me a moment first, I want to read through one of the comments another user made in the main help channel just to make sure I know what I'm doing

full bluff
#

Sure np

barren zodiac
#

hmm. I'm not sure what they're suggesting. We'll just have to wait for their help when they're able. Until then we can try the changes I'm more familiar with. If I'm lucky, their solution will work for me too, though my workaround does work.

#

Ok first of a couple of questions

#

is it safe to assume that when the wifi goes down, or when the power goes out, the device having a problem reconnecting is 'ok' (we can work on it later, I'm just making sure I can prioritize it correctly) or does the wifi go out often enough that that would be an issue?

full bluff
#

The wifi is pretty stable , I have ubiquiti AP's . So never had that scenario of wifi going out and the board reconnecting

barren zodiac
#

awesome, it's really not that big of an issue, just needed to make sure I understood the problem

full bluff
#

After a few minutes of running the code, it throws the error mentioned above and I had to phhysically pull out the plug and plug it in to make it work

barren zodiac
#

ok, you're still connected to the serial output so you can read print statements right?

full bluff
#

yup I am

barren zodiac
#

    except RuntimeError:
        reconnect_limit = 10
        reconnect_tries = 0
        print("Connection Dropped, trying to reconnect")
        while reconnect_tries < reconnect_limit:
            try:
                wifi.reset()
                mqtt_client.reconnect()
            except RuntimeError:
                reconnect_tries += 1
                print(reconnect_tries, " Failures")

put this code in place of your runtime error

full bluff
#

sure

barren zodiac
#

it should be indented so it works, but basically we're safely 'trying to reconnect'. If I had to bet, I think this won't solve our problem, but it should help us understand what is going on

#

oh wait, I need to make it break, give me a moment

full bluff
#

roger that

barren zodiac
#

    except RuntimeError as e:
        reconnect_limit = 10
        reconnect_tries = 0
        print("Connection Dropped, trying to reconnect")
        while reconnect_tries < reconnect_limit:
            try:
                wifi.reset()
                mqtt_client.reconnect()
            except RuntimeError:
                reconnect_tries += 1
                print(reconnect_tries, " Failures")
        if reconnect_tries >= reconnect_limit:
            raise(e)```
#

there we go, that way if it fails to ever reconnect in those 10 tries, it will hard break

#

But, if it ever prints print(reconnect_tries, " Failures"), then stops counting up, and starts printing print("CO2: %d ppm" % scd4x.CO2), then we know this approach reconnected us

full bluff
#

Updated the code and its running , it might take like 15-20 ish minutes until we hit the error

#

I will keep you posted

#

thanks for the explanation !

barren zodiac
#

No worries, that's a great reason to use the thread option on discord, makes it easier to run something and 'wait' for a failure

#

no problem, my code sets up the wifi connect information in a class, that way I can move all of that messy 'reconnect' information elsewhere in my program. I'm mostly basing this approach off of that. I think the problem is actually with sockets and opening more than we close, but we'll slowly work our way there so we can be confident about what exactly the problem was

full bluff
#

Awesome,sounds good. So far so good..no errors

#

And it stopped

#

Connection Dropped, trying to reconnect
1 Failures
2 Failures
3 Failures
4 Failures
5 Failures
6 Failures
7 Failures
8 Failures
9 Failures
10 Failures
Traceback (most recent call last):
File "code.py", line 131, in <module>
File "code.py", line 116, in <module>
File "adafruit_minimqtt/adafruit_minimqtt.py", line 621, in publish
File "adafruit_esp32spi/adafruit_esp32spi_socket.py", line 86, in send
File "adafruit_esp32spi/adafruit_esp32spi.py", line 721, in socket_write
RuntimeError: Failed to send 16 bytes (sent 0)

Code done running.

#

brb in 10 min

barren zodiac
#

ok, did it ever successfully reconnect?

full bluff
#

nope

#

it styopped

barren zodiac
#

ok, so at no point did it start saying, 1, 2, 3 failures, then CO2: 1786 ppm, Temperature: 26.4 *C, Humidity: 51.3 %

full bluff
#

Right , there were no reconnection after failure

barren zodiac
#

Ok cool, it's a bummer, but it's to be expected. Now lets look at how you initialize all of your connections

#

Can you show me all of the code used to setup mqtt_client and wifi?

full bluff
#

Will do ,stepping away for 10 min

barren zodiac
#

no worries, I have a few other projects I'll be able to take care of in the mean time ๐Ÿ™‚

full bluff
#

WiFi

try:
from secrets import secrets
except ImportError:
print("WiFi secrets are kept in secrets.py, please add them there!")
raise

If you are using a board with pre-defined ESP32 Pins:

esp32_cs = DigitalInOut(board.ESP_CS)
esp32_ready = DigitalInOut(board.ESP_BUSY)
esp32_reset = DigitalInOut(board.ESP_RESET)
spi = busio.SPI(board.SCK, board.MOSI, board.MISO)
esp = adafruit_esp32spi.ESP_SPIcontrol(spi, esp32_cs, esp32_ready, esp32_reset)
"""Use below for Most Boards"""
status_light = neopixel.NeoPixel(
board.NEOPIXEL, 1, brightness=0.2
)
wifi = adafruit_esp32spi_wifimanager.ESPSPI_WiFiManager(esp, secrets, status_light)

Connect to WiFi

print("Connecting to WiFi...")
wifi.connect()
print("Connected!")

#

Topic Setup

MQTT Topic

Use this topic if you'd like to connect to a standard MQTT broker

mqtt_topic = "airquality/co2"

Code

Define callback methods which are called when events occur

pylint: disable=unused-argument, redefined-outer-name

def connect(mqtt_client, userdata, flags, rc):
# This function will be called when the mqtt_client is connected
# successfully to the broker.
print("Connected to MQTT Broker!")
print("Flags: {0}\n RC: {1}".format(flags, rc))

def disconnect(mqtt_client, userdata, rc):
# This method is called when the mqtt_client disconnects
# from the broker.
print("Disconnected from MQTT Broker!")

def subscribe(mqtt_client, userdata, topic, granted_qos):
# This method is called when the mqtt_client subscribes to a new feed.
print("Subscribed to {0} with QOS level {1}".format(topic, granted_qos))

def unsubscribe(mqtt_client, userdata, topic, pid):
# This method is called when the mqtt_client unsubscribes from a feed.
print("Unsubscribed from {0} with PID {1}".format(topic, pid))

def publish(mqtt_client, userdata, topic, pid):
# This method is called when the mqtt_client publishes data to a feed.
print("Published to {0} with PID {1}".format(topic, pid))

def message(client, topic, message):
# Method callled when a client's subscribed feed has a new value.
print("New message on topic {0}: {1}".format(topic, message))

socket.set_interface(esp)
MQTT.set_socket(socket, esp)

Set up a MiniMQTT Client

mqtt_client = MQTT.MQTT(broker = secrets['broker'],
username = secrets['user'],
password = secrets['pass'],
port = 1883)

#

Connect callback handlers to mqtt_client

mqtt_client.on_connect = connect
mqtt_client.on_disconnect = disconnect
mqtt_client.on_subscribe = subscribe
mqtt_client.on_unsubscribe = unsubscribe
mqtt_client.on_publish = publish
mqtt_client.on_message = message

print("Attempting to connect to %s" % mqtt_client.broker)
mqtt_client.connect()

print("Subscribing to %s" % mqtt_topic)
mqtt_client.subscribe(mqtt_topic)

barren zodiac
#

can you link me to the learn guide this came from?

full bluff
#

It came from multiple guides

barren zodiac
#

sweet thank you

#

I've got to go grab lunch and get some things done, I'll jump back here once I've read through everything and have an idea of what to suggest next

full bluff
#

Sure , thank you !

barren zodiac
#

Still doing updates, but
instead of trying, mqtt_client.reconnect()
Because you reset the wifi, could you give a shot at,


        while reconnect_tries < reconnect_limit:
            try:
                try:
                    mqtt_client.disconnect()
                except RuntimeError as e:
                    print("encountered error while trying to close mqtt connection,\n", e) 
                wifi.reset()
                mqtt_client.connect()
            except RuntimeError:
                reconnect_tries += 1
                print(reconnect_tries, " Failures")
#

I'm loosely wondering if we should instead be trying to close and connect again rather than reconnect if the wifi was reset

#

if that doesn't work we'll try,

    except RuntimeError as e:
        reconnect_limit = 10
        reconnect_tries = 0
        print("Connection Dropped, trying to reconnect")
        while reconnect_tries < reconnect_limit:
            try:
                mqtt_client.reconnect()
            except RuntimeError:
                reconnect_tries += 1
                print(reconnect_tries, " Failures")
        if reconnect_tries >= reconnect_limit:
            raise(e)
#

which just tries to reconnect multiple times without the wifi reset

full bluff
#

Thanks , I will give this a try and update

#

Suntax error liine 131

#

*syntax

barren zodiac
#

indent those three lines one more level in/to the right

#

That should be the except pair to the try right below the while

full bluff
barren zodiac
#

It needs one more space, and the lines below it need to be indented in as well

full bluff
#

Sorry I am new to python

barren zodiac
#

It needs to come back out one level to the left,--my bad

#
        while reconnect_tries < reconnect_limit:
            try:
                try:
                    mqtt_client.disconnect()
                except RuntimeError as e:
                    print("encountered error while trying to close mqtt connection,\n", e) 
                wifi.reset()
                mqtt_client.connect()
            except RuntimeError:
                reconnect_tries += 1
                print(reconnect_tries, " Failures")
full bluff
#

does line 119 looks ok ?

barren zodiac
#

So that's a warning, not an error

full bluff
#

right, I uploaded code and its running

#

I"ll looking at the serial , so far so good

barren zodiac
#

Different code editors can treat it like an error. Sometimes you want that behavior, because if you've written a lot of code, and you have lots of variable that are made but never used, it very easy to accidentally use it and you end up with a weird error that's really hard to follow. This helps prevent you from having that happen

#

Earlier we printed that e, or raised it.. in fact there might be a block of code below this one you're missing where we raise that e

full bluff
#

oh okay good to know. The MU editor is a powerful editing tool with lots of information

barren zodiac
#

It really is, I'm not that great when it comes to understanding editors personally, but they are powerful

full bluff
#

agreed

#

I dont see any errors as of now . Will give it a few minutes

barren zodiac
#

let me know if you ever see it print(reconnect_tries, " Failures") or print("encountered error while trying to close mqtt connection,\n", e)

#

I should have made it make note of hitting that runtime error, but we'll deal with it later, for now let's just run it and see what happens

full bluff
#

Sure will do , I had to restart

#

Its running now , will update when I see those

barren zodiac
#

I wish we weren't bodging it with 'try again' stuff, but networking is messy, and a microcontroller only has so much ability to deal with network packets being dropped. "try again" usually works on my end

full bluff
#

Yeah I know, networking is all over the place. so many devices on 2.4 ghz wifi network .. I hope the try again works

#

CO2: 2131 ppm
Temperature: 26.1 *C
Humidity: 53.1 %
Publishing to airquality/co2
Connection Dropped, trying to reconnect
Disconnected from MQTT Broker!
1 Failures
Traceback (most recent call last):
File "code.py", line 126, in <module>
File "adafruit_minimqtt/adafruit_minimqtt.py", line 519, in disconnect
File "adafruit_minimqtt/adafruit_minimqtt.py", line 955, in is_connected
MMQTTException: MiniMQTT is not connected.

Code done running.

#

It just stopped an neopixel is white

barren zodiac
#

Ok cool, that's really informative if I'm reading it correctly

#

So, what happened was we tried to disconnect, and mqtt said, "I'm already disconnected" which is a good thing

full bluff
#

oh okay

barren zodiac
#

                try:
                    mqtt_client.disconnect()
                except RuntimeError, MMQTTException as e:
                    print("encountered error while trying to close mqtt connection,\n", e) 
                #wifi.reset()

Let's try this, we're now catching that exception that way if we try to disconnect, we know we've already been disconnected

#

I'm also commenting out the wifi reset for the moment--I want to hold off on that

full bluff
#

so only wifi reset commented out ?

#

lines below that still exist ?

barren zodiac
#

Correct

#

Sorry I'm only highlight code blocks I've made a change in

full bluff
#

ok its running now

barren zodiac
#

I can do the full code if you like

full bluff
#

no thats fine

barren zodiac
#

awesome!

full bluff
#

Just asking

full bluff
#

Connected to MQTT Broker!
Flags: 0
RC: 0
Disconnected from MQTT Broker!
Connected to MQTT Broker!
Flags: 0
RC: 0
Disconnected from MQTT Broker!
Connected to MQTT Broker!
Flags: 0
RC: 0
Disconnected from MQTT Broker!
Connected to MQTT Broker!
Flags: 0
RC: 0

#

unfortunately I coudn't get the lines above it

#

It ran fine for few minutes and printed above

#

I am going to do bbq now for the weekend , I will catch up with you on this later . I appreciate the help

#

Thanks !

barren zodiac
#

Ah no worries, you have a good one. This thread will archive, but you can open it back up when you get back. I'm slowly trying to get a feel for what's going on code wise and at least it feels like we're making progress

full bluff
#

Awesome, sounds good . You have a good rest of the day

barren zodiac
#

you too and have a great weekend

heady dew
barren zodiac
#

Ok jumping back over here--Auto101, @heady dew has been working on their own mqtt implementation and has similar issues so I've invited them to this thread as well

#

(I'd ping you but I'm going to guess it's late in the day)

#

So, give me a minute to clean up my code, but I'll post a sample of my 'json' sensor relay data

heady dew
#

Yep. Trying to put one baby to sleep and give the other one a bath.

barren zodiac
#

I'm updating the code as a whole, so I can add and remove sensors without the program crashing on startup, and I'm trying to make every sensor fit into a similar class which is tripping me up--perfect is the enemy of good in this case--and once that update is running, I'm going to build a mqtt clone so we can address the mqtt protocol and since you're both running into this same issue, we'll be able to make guides be a bit clearer, and I'll be more ready to help users with this kind of question.

Tldr, I'll post the code shortly

#

And the code is bad--I'm awful at networking, I have a bunch of glue code that exists because it was there once the program worked, not because it's ever used

heady dew
#

This is one of the situations when I prefer Raspberry Pi + blinka over CircuitPython.

barren zodiac
#

I've not yet looked super deep into MQTT, but I feel like mqtt's constantly on setup plus networking fun shenanigans is the problem here, I'm willing to bet it's more a fault of the router than the micro in the long run, but getting the micro ready to handle the networking randomness is important regardless. I think that 'being able to handle the randomness' is very solvable though

heady dew
#

Just my personal bias: microcontrollers shouldn't be doing TCP/IP. So many things can go wrong. You need a full networking stack for sufficient robustness.

barren zodiac
heady dew
#

I specifically meant TCP/IP.
There are simpler protocols like packet radio, BLE advertisements and CAN that are much more suited to microcontrollers.
The happy path scenarios in TCP/IP are easy to implement on microcontrollers. The rainy day scenarios need a full TCP/IP stack and those don't fit on microcontrollers.

full bluff
#

Thanks @barren zodiac for re opening this thread. I am available to troubleshoot any code that you may advise

barren zodiac
#

Awesome!
I'm still cleaning up my sensor code, I'm hoping to get it done shortly

barren zodiac
#

Ok, the code is a mess, but it's functionally stable. Now that I finally have that, I can start trying to make an mqtt fork of this so we can explore how it works
The extra bells and whistles are .. eh, and the 'everything' around the code.py file itself is mostly out of date. I wasn't sure what I had commited vs what I hadn't, so it's there now I suppose

#

Took more than a minute to get it in this sorry state, but so it goes, it's easier to fix code that exists, than fix nearly perfect code that doesn't exist.

full bluff
#

Do you want me to make any changes in my code referencing above ?

barren zodiac
full bluff
#

Ok

barren zodiac
#

I have my sensors reporting now, and now that I have that 'json-post' program is working, I'm going to try the mqtt setup. But the 'try again' setup is how I'm managing networking issues

#

The code does a whole lot of different failure preperation, and those


            try:
                response = self.https.post(post_sensor_webpage, json=packet_json) 
                success = True
                pixels[0]=(0,0,0)
                pixels.show()
                try: 
                    self._close_request_socket(response)
                except Exception as e:
                    print("During closing of socket, error occured", e)
            except RuntimeError as e:
                # Reasons
                # Server may be down
                run_count += 1
                print("> Runtime Error Caught", e)
                success = False
            except OSError as e:
                self.connected_to_network = False
                print("> Os Error Caught", e)
                success = False
            except OutOfRetries as e:
                print(">Outofretries>", e)
                success = False

try/excepts, are really useful--but there's still a lot of straggling code I need to remove. For example the run_count is now a invalid variable because I adjusted the function to return with a failed success flag, whereas before it sat trying again over and over

#

                try: 
                    self._close_request_socket(response)
                except Exception as e:
                    print("During closing of socket, error occured", e)
            except RuntimeError as e:
                # Reasons
                # Server may be down
                run_count += 1
                print("> Runtime Error Caught", e)
                success = False```
this block is where the program manages errors most often, and it's going to be the basis of how I try and manage mqtt errors--on a failure I'm going to try to close the socket, then open a new one up, and try again
full bluff
#

Awesome, thanks for the explanation

barren zodiac
heady dew
#

Awesome! I will take a look at it.

#

I ended up with other transient issues, and it could be because I have so many sensors connected by QWIIC cables forming a large antenna.

#

Hopefully the QWIIC featherwing can alleviate some of those issues.

barren zodiac
#

hmm. How many sensors and what's the total length of the cable (roughly)

heady dew
#

8 sensors
this part is embarrassing
1.5 feet
๐Ÿ™ƒ
I need shorter QWIIC cables

#

may be more like 2.5 feet

#

๐Ÿ˜ฉ

#

The real fun starts when I put an OLED display at the end of the chain and the display falls apart.

barren zodiac
#

ah yeah that probably approaches the signal degradation length. Have you looked at dropping the clock speed

#

oof, you need multiple micros managing and handing off communications at that level

heady dew
#

yep

barren zodiac
#

Ok, well I'm going to walk away from the computer for a while for a fresh point of view, and between this evening and tomorrow I should hopefully have a pi running an mqtt receiver, and a esp32-s2 sending it data. Then I can start testing how to handle the broken transmissions

#

(Gotta keep this thread on topic otherwise close it and move to general ๐Ÿ˜… )

heady dew
#

Scientists are actually preoccupied with accomplishment. So they are focused on whether they can do something. They never stop to ask if they should do something.

#

Jurassic World

barren zodiac
heady dew
#

Last thing I am going to say about cable length. Adafruit or Sparkfun has an I2C signal conditioner for exactly this kind of situation.

barren zodiac
#

baby steps before feature creep sets in

heady dew
#

I went with ESP32-S2 with MQTT because that's what I had on hand.
I also thought of BLE advertisements or CAN bus.
Those two will probably save me from WiFi interference in the QWIIC cables, but not with cable length.

barren zodiac
#

I think you're running into two different kinds of errors there though. One for i2c bus noise, and one for mqtt transmission drop recovery. If you have a server that can take a posted json file, you can swap from mqtt to the json without issue (my example code linked above show's how it handles failed sends) but you'll still have the read errors from the i2c bus due to it's length.

#

But I might be misreading your comment and that's something you know and have handled--my brain is grinding to a halt and it's getting harder to focus hence the walk away

heady dew
#

You are right. My setup has two issues. I am more interested in solving the intermittent WiFi/MQTT connectivity issue. The I2C bus issue can be handled with other strategies.

barren zodiac
heady dew
barren zodiac
full bluff
#

No , I wanted to keep it local

barren zodiac
#

Ok, what were you using for your local design?

#

home assistant?

full bluff
#

Yup running MQTT as a add on in HA

barren zodiac
#

Ok, I'm going to do something different and run it on a local flask server, so if that causes an issue in debugging I'll do the HA, but I am less familiar with that personally.

full bluff
#

Oh okay , just for the information I have few devices that communicate via Mqtt such as lights , motion sensors ,rf bridge and they work perfectly fine