-
Notifications
You must be signed in to change notification settings - Fork 13
Adding MQTT support for Azure IoT Central and IoT Hub #11
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
Also adding support for B tier hubs by lazy subscribing to twins
@jimbobbennett When you're ready for a review, please request me to review it or tag me. Thanks for continuing working on this. |
Will do. I just wanted to open it early to get the code reviewed by others, including some kind folks from the Azure IoT SDK team who have given me some pointers. Appreciate all your help and support with this. |
@brentru - this should be ready for review now. All the code appears to work, and I've tested all the examples with no issues. I don't seem to be able to set a reviewer, hence tagging you in. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@jimbobbennett This is awesome!!
Requesting some changes. I'll test on a PyPortal Titano after.
@@ -0,0 +1,235 @@ | |||
""" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could you include the same header used in __init__.py
here? (reference: https://github.com/adafruit/Adafruit_CircuitPython_Wiznet5k/tree/master/adafruit_wiznet5k)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
File headers added - can you verify they are ok please.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Look good, may want to update the copyright to be current:
# Copyright (c) 2019 Jim Bennett
to
# Copyright (c) 2020 Jim Bennett
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
D'oh! Will fix that....
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed!
adafruit_azureiot/iot_mqtt.py
Outdated
import json | ||
import time | ||
import adafruit_esp32spi.adafruit_esp32spi_socket as socket | ||
from adafruit_esp32spi.adafruit_esp32spi_wifimanager import ESPSPI_WiFiManager |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Instead of importing esp32spi and the esp32spi socket, could we the socket
object in instead?
This will allow us to use multiple types of socket
objects with this library like wifi, ethernet, and cellular.
We do this here in the latest MiniMQTT
: https://github.com/adafruit/Adafruit_CircuitPython_MiniMQTT/blob/master/examples/minimqtt_simpletest_eth.py#L64
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yup - I was following the pattern of the existing code, relying on the WiFi manager. Happy to change it to a socket instead!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That'd be great. Let me know if you have any Q's. I'll test with ESP32 and Ethernet socket
s.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Updated to use the socket and interface
examples/iotcentral_commands.py
Outdated
|
||
while True: | ||
# Poll every second for messages from the cloud | ||
device.loop() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You may want to handle network (physical, not mqtt) disconnection from the esp
here. ESP32 can be flaky at times.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added exception catching and reconnection
|
||
message_counter = 60 | ||
|
||
while True: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
may want to handle esp32 network and status issues in here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would that be too much for an example? The example is meant to show the simple case of sending telemetry.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It would increase the length of the example, however, adding network handling in the user-code is important to make sure new users have a good "first five minutes" and don't hit errors they can't resolve (the ESP32 can be flaky).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In adding this, I'm also going to add reconnect logic. In doing this I hit another bug in MiniMQTT - the reconnect
method gets stuck in an infinite loop. Bug here
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added reconnection on errors
@@ -1,2 +1,6 @@ | |||
Adafruit-Blinka | |||
Adafruit_CircuitPython_ESP32SPI |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same as before - I'd like to not add a requirement for esp32spi with this library to allow for new transport socket
s in the future.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
All changes should be in, let me know what you think. |
@jimbobbennett this is so awesome, thank you for the PR - we're really psyched to make Azure easier for folks to use. would you be interested in writing a guide/tutorial or publishing a project to show this off? |
Yes, definitely! I'll be building a few hands on workshops in my own GitHub repo to show this in action, and we are hoping to run some kids events in Microsoft spaces using Adafruit boards later on in the year when things open up and we can get some hardware. Would it be possible for me to create a guide for the Adafruit Learning System? I'm also building a CircuitPython library for one of our AI services which I'd love to build a guide for once it's complete. |
@jimbobbennett What does your |
Here you go: Wifi details are self explanatory. For the IoT Central connection details, create a device in IoT Central and grab the details from the Connect dialog. For the IoT Hub device connection string, create an IoT Hub, create a device in that hub and grab one of the connection strings for the device. # This file is where you keep secret settings, passwords, and tokens!
# If you put them in the code you risk committing that info or sharing it
# which would be not great. So, instead, keep it all in this one file and
# keep it a secret.
"""
Contains the secrets for your app including WiFi connection details.
DO NOT CHECK THIS INTO SOURCE CODE CONTROL!!!!11!!!
"""
secrets = {
# WiFi connection details
"ssid": "",
"password": "",
# IoT Central device connection details
"id_scope": "",
"device_id": "",
"key": "",
# IoT Hub device connection string
"device_connection_string": "",
} |
The last commit added one small update to the reconnect logic to replace the workarounds for two MiniMQTT bugs. |
@jimbobbennett - thanks for all the work on this! @brentru pointed me to it earlier today in response to some questions I had about the AzureIoT library. I was able to get the iothub_messages.py example to work, and I'm seeing data in the Azure cloud shell. I did have to install several additional libraries from your GitHub repos for it to work:
Will these eventually get folded into the final library in some way? |
These are available in the CircuitPython community bundle. This is in the Readme, but I probably should add a note to all the examples as well. |
Ah! Sure enough. Ok, thanks! |
@jimbobbennett Ok, I looked through the code, didnt see the connection string started with Ok - one final ask before I pull this in and release: Could you please add the secrets file to examples as |
@brentru - added more info, a secrets file and some images in the readme to show where to get the values from. Took a few commits because I couldn't get the rest syntax right, then PyLint became case sensitive for ignores where it wasn't before, then couldn't get sphinx working! all good fun. |
@jimbobbennett The library check process is a bit tricky. But it looks perfect now. |
Updating https://github.com/adafruit/Adafruit_CircuitPython_NeoPixel to 6.0.0 from 5.1.1: > Merge pull request adafruit/Adafruit_CircuitPython_NeoPixel#83 from adafruit/tannewt-patch-1 > Merge pull request adafruit/Adafruit_CircuitPython_NeoPixel#82 from dunkmann00/pixelbuf Updating https://github.com/adafruit/Adafruit_CircuitPython_NeoPixel_SPI to 0.8.0 from 0.4.1: > Merge pull request adafruit/Adafruit_CircuitPython_NeoPixel_SPI#15 from dunkmann00/pypixelbuf-2.0-compat Updating https://github.com/adafruit/Adafruit_CircuitPython_AzureIoT to 2.0.0 from 1.1.0: > Merge pull request adafruit/Adafruit_CircuitPython_AzureIoT#11 from jimbobbennett/master > build.yml: add black formatting check Updating https://github.com/adafruit/Adafruit_CircuitPython_Pypixelbuf to 2.0.0 from 1.0.3: > Merge pull request adafruit/Adafruit_CircuitPython_Pypixelbuf#19 from dunkmann00/dotstar_brightness > Merge pull request adafruit/Adafruit_CircuitPython_Pypixelbuf#18 from dunkmann00/_pixelbuf_cp > Merge pull request adafruit/Adafruit_CircuitPython_Pypixelbuf#17 from adafruit/black-update > build.yml: add black formatting check > Merge pull request adafruit/Adafruit_CircuitPython_Pypixelbuf#16 from kattni/update-example-name > Merge pull request adafruit/Adafruit_CircuitPython_Pypixelbuf#12 from adafruit/pylint-update > update code of coduct: discord moderation contact section > Merge pull request adafruit/Adafruit_CircuitPython_Pypixelbuf#11 from sommersoft/patch_coc > update pylintrc for black
An implementation of #7.
Azure has 2 IoT Services:
Currently the code is working based off copying it to a PyBadge with Airlift Featherwing and supports all the device capabilities of IoT Hub and Central:
IoT Hub
IoT Central
The code structure is:
device_registration.py
- contains code to register a device with IoT Central and get the underlying IoT Hub connection detailsiot_mqtt.py
- the underlying MQTT communications layer. This talks to IoT Hub and can send device to cloud, receive direct methods, receive cloud to device messages, update the device twin and receive twin updatesiothub_device.py
- the client for IoT Hub connections. This will connect to a hub via a device connection string, send device to cloud messages, update the twin and has callbacks you can set up for direct methods, cloud to device messages and twin updatesiotcentral_device.py
- the client for IoT Central connections. This will connect to IoT Central via the id scope, device id and key using the device registration service. It can send telemetry, update properties and has callbacks for commands and property updatesI've removed the HTTP SDK as MQTT provides better capabilities. The HTTP SDK also had both device and client methods on it, the MQTT implementation is device only. If we want to add a client SDK with features such as querying for devices, then that should be a different library, to be in keeping with the official Azure IoT SDKs.