Skip to content

Commit

Permalink
Merge pull request #37 from askpatrickw/add-ssl-context
Browse files Browse the repository at this point in the history
Fix miniMQTT compatibility and native_networking examples
  • Loading branch information
brentru committed Jan 27, 2022
2 parents fe80aad + 79c50ef commit 4b72e22
Show file tree
Hide file tree
Showing 20 changed files with 64 additions and 22 deletions.
6 changes: 3 additions & 3 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -63,8 +63,8 @@ To create an Azure IoT Hub instance or an Azure IoT Central app, you will need a

- If you are not a student, head to `aka.ms/FreeAz <https://aka.ms/FreeAz>`_ and sign up to get $200 of credit for 30 days, as well as free tiers of a load of services. You will need a credit card for validation only, your card will not be charged.

ESP32SPI Networking
===================
ESP32 AirLift Networking
========================

To use this library, you will need to create an ESP32_SPI WifiManager, connected to WiFi. You will also need to set the current time, as this is used to generate time-based authentication keys. One way to do this is via the `Adafruit CircuitPython NTP <https://github.com/adafruit/Adafruit_CircuitPython_NTP>`_ library with the following code:

Expand All @@ -79,7 +79,7 @@ To use this library, you will need to create an ESP32_SPI WifiManager, connected
Native Networking
=================
To use this library, with boards that have native networking support, you need to be connected to a network. You will also need to set the current time, as this is used to generate time-based authentication keys. One way to do this is by using the `Adafruit IoT Time Service <https://io.adafruit.com/api/docs/#time>`_ via the `Requests library <https://github.com/adafruit/Adafruit_CircuitPython_Requests/>_` with the following code:
To use this library, with boards that have native networking support, you need to be connected to a network. You will also need to set the current time, as this is used to generate time-based authentication keys. One way to do this is by using the `Adafruit IoT Time API <https://io.adafruit.com/api/docs/#time>`_ via the `Adafruit Requests library <https://github.com/adafruit/Adafruit_CircuitPython_Requests>`_ with the following code:

.. code-block:: python
Expand Down
9 changes: 5 additions & 4 deletions adafruit_azureiot/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,15 +19,16 @@
* Adafruit CircuitPython firmware for the supported boards:
https://github.com/adafruit/circuitpython/releases
**ESP32SPI Peripheral Networking**
**With ESP32 Airlift Networking**
* Adafruit's Bus Device library: https://github.com/adafruit/Adafruit_CircuitPython_BusDevice
* Adafruit's ESP32SPI Networking library: https://github.com/adafruit/Adafruit_CircuitPython_ESP32SPI
* Adafruit's ESP32SPI library: https://github.com/adafruit/Adafruit_CircuitPython_ESP32SPI
* Adafruit's NTP library: https://github.com/adafruit/Adafruit_CircuitPython_NTP
**Native Networking**
**With Native Networking**
* CircuitPython's Wifi Module: https://docs.circuitpython.org/en/latest/shared-bindings/wifi/index.html
* Adafruit's CircuitPython Requests Library: https://github.com/adafruit/Adafruit_CircuitPython_Requests/
* Adafruit's Requests Library: https://github.com/adafruit/Adafruit_CircuitPython_Requests/
"""

from .iot_error import IoTError
Expand Down
2 changes: 2 additions & 0 deletions adafruit_azureiot/device_registration.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ def __init__(
logger: Logger = None,
):
"""Creates an instance of the device registration service
:param socket: The network socket
:param str id_scope: The ID scope of the device to register
:param str device_id: The device ID of the device to register
Expand Down Expand Up @@ -163,6 +164,7 @@ def register_device(self, expiry: int) -> str:
"""
Registers the device with the IoT Central device registration service.
Returns the hostname of the IoT hub to use over MQTT
:param int expiry: The expiry time for the registration
:returns: The underlying IoT Hub that this device should connect to
:rtype: str
Expand Down
1 change: 1 addition & 0 deletions adafruit_azureiot/iot_error.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ class IoTError(Exception):

def __init__(self, message: str):
"""Create the IoT Error
:param str message: The error message
"""
super().__init__(message)
Expand Down
17 changes: 15 additions & 2 deletions adafruit_azureiot/iot_mqtt.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@

import adafruit_minimqtt.adafruit_minimqtt as MQTT
import adafruit_logging as logging
from adafruit_logging import Logger

from .iot_error import IoTError
from .keys import compute_derived_symmetric_key
Expand All @@ -31,6 +32,7 @@ class IoTResponse:

def __init__(self, code: int, message: str):
"""Creates an IoT Response object
:param int code: The HTTP response code for this method call, for example 200 if the method was handled successfully
:param str message: The HTTP response message for this method call
"""
Expand All @@ -43,17 +45,20 @@ class IoTMQTTCallback:

def message_sent(self, data: str) -> None:
"""Called when a message is sent to the cloud
:param str data: The data send with the message
"""

def connection_status_change(self, connected: bool) -> None:
"""Called when the connection status changes
:param bool connected: True if the device is connected, otherwise false
"""

# pylint: disable=W0613, R0201
def direct_method_invoked(self, method_name: str, payload: str) -> IoTResponse:
"""Called when a direct method is invoked
:param str method_name: The name of the method that was invoked
:param str payload: The payload with the message
:returns: A response with a code and status to show if the method was correctly handled
Expand All @@ -64,6 +69,7 @@ def direct_method_invoked(self, method_name: str, payload: str) -> IoTResponse:
# pylint: disable=C0103
def cloud_to_device_message_received(self, body: str, properties: dict) -> None:
"""Called when a cloud to device message is received
:param str body: The body of the message
:param dict properties: The propreties sent with the mesage
"""
Expand All @@ -72,6 +78,7 @@ def device_twin_desired_updated(
self, desired_property_name: str, desired_property_value, desired_version: int
) -> None:
"""Called when the device twin desired properties are updated
:param str desired_property_name: The name of the desired property that was updated
:param desired_property_value: The value of the desired property that was updated
:param int desired_version: The version of the desired property that was updated
Expand All @@ -84,6 +91,7 @@ def device_twin_reported_updated(
reported_version: int,
) -> None:
"""Called when the device twin reported values are updated
:param str reported_property_name: The name of the reported property that was updated
:param reported_property_value: The value of the reported property that was updated
:param int reported_version: The version of the reported property that was updated
Expand Down Expand Up @@ -319,17 +327,18 @@ def __init__(
device_id: str,
device_sas_key: str,
token_expires: int = 21600,
logger: logging = None,
logger: Logger = None,
):
"""Create the Azure IoT MQTT client
:param IoTMQTTCallback callback: A callback class
:param socket: The socket to communicate over
:param iface: The network interface to communicate over
:param str hostname: The hostname of the MQTT broker to connect to, get this by registering the device
:param str device_id: The device ID of the device to register
:param str device_sas_key: The primary or secondary key of the device to register
:param int token_expires: The number of seconds till the token expires, defaults to 6 hours
:param adafruit_logging logger: The logger
:param Logger logger: The logger
"""
self._callback = callback
self._socket = socket
Expand Down Expand Up @@ -372,6 +381,7 @@ def _subscribe_to_twin_topics(self):

def connect(self) -> bool:
"""Connects to the MQTT broker
:returns: True if the connection is successful, otherwise False
:rtype: bool
"""
Expand Down Expand Up @@ -426,6 +436,7 @@ def reconnect(self) -> None:

def is_connected(self) -> bool:
"""Gets if there is an open connection to the MQTT broker
:returns: True if there is an open connection, False if not
:rtype: bool
"""
Expand All @@ -443,6 +454,7 @@ def send_device_to_cloud_message(
self, message, system_properties: dict = None
) -> None:
"""Send a device to cloud message from this device to Azure IoT Hub
:param message: The message data as a JSON string or a dictionary
:param system_properties: System properties to send with the message
:raises: ValueError if the message is not a string or dictionary
Expand Down Expand Up @@ -472,6 +484,7 @@ def send_device_to_cloud_message(

def send_twin_patch(self, patch) -> None:
"""Send a patch for the reported properties of the device twin
:param patch: The patch as a JSON string or a dictionary
:raises: IoTError if the data is not a string or dictionary
:raises RuntimeError: if the internet connection is not responding or is unable to connect
Expand Down
16 changes: 14 additions & 2 deletions adafruit_azureiot/iotcentral_device.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
import json
import time
import adafruit_logging as logging
from adafruit_logging import Logger
from .device_registration import DeviceRegistration
from .iot_error import IoTError
from .iot_mqtt import IoTMQTT, IoTMQTTCallback, IoTResponse
Expand All @@ -25,6 +26,7 @@ class IoTCentralDevice(IoTMQTTCallback):

def connection_status_change(self, connected: bool) -> None:
"""Called when the connection status changes
:param bool connected: True if the device is connected, otherwise false
"""
if self.on_connection_status_changed is not None:
Expand All @@ -34,6 +36,7 @@ def connection_status_change(self, connected: bool) -> None:
# pylint: disable=W0613, R0201
def direct_method_called(self, method_name: str, payload: str) -> IoTResponse:
"""Called when a direct method is invoked
:param str method_name: The name of the method that was invoked
:param str payload: The payload with the message
:returns: A response with a code and status to show if the method was correctly handled
Expand All @@ -49,6 +52,7 @@ def device_twin_desired_updated(
self, desired_property_name: str, desired_property_value, desired_version: int
) -> None:
"""Called when the device twin desired properties are updated
:param str desired_property_name: The name of the desired property that was updated
:param desired_property_value: The value of the desired property that was updated
:param int desired_version: The version of the desired property that was updated
Expand All @@ -69,6 +73,7 @@ def device_twin_reported_updated(
reported_version: int,
) -> None:
"""Called when the device twin reported values are updated
:param str reported_property_name: The name of the reported property that was updated
:param reported_property_value: The value of the reported property that was updated
:param int reported_version: The version of the reported property that was updated
Expand All @@ -88,16 +93,17 @@ def __init__(
device_id: str,
device_sas_key: str,
token_expires: int = 21600,
logger: logging = None,
logger: Logger = None,
):
"""Create the Azure IoT Central device client
:param socket: The network socket
:param iface: The network interface
:param str id_scope: The ID Scope of the device in IoT Central
:param str device_id: The device ID of the device in IoT Central
:param str device_sas_key: The primary or secondary key of the device in IoT Central
:param int token_expires: The number of seconds till the token expires, defaults to 6 hours
:param adafruit_logging logger: The logger
:param Logger logger: The logger
"""
self._socket = socket
self._iface = iface
Expand Down Expand Up @@ -132,6 +138,7 @@ def property_changed(_property_name: str, property_value, version: int) -> None

def connect(self) -> None:
"""Connects to Azure IoT Central
:raises DeviceRegistrationError: if the device cannot be registered successfully
:raises RuntimeError: if the internet connection is not responding or is unable to connect
"""
Expand Down Expand Up @@ -166,6 +173,7 @@ def connect(self) -> None:

def disconnect(self) -> None:
"""Disconnects from the MQTT broker
:raises IoTError: if there is no open connection to the MQTT broker
"""
if self._mqtt is None:
Expand All @@ -182,13 +190,15 @@ def reconnect(self) -> None:

def is_connected(self) -> bool:
"""Gets if there is an open connection to the MQTT broker
:returns: True if there is an open connection, False if not
:rtype: bool
"""
return self._mqtt.is_connected() if self._mqtt is not None else False

def loop(self) -> None:
"""Listens for MQTT messages
:raises IoTError: if there is no open connection to the MQTT broker
"""
if self._mqtt is None:
Expand All @@ -198,6 +208,7 @@ def loop(self) -> None:

def send_property(self, property_name: str, value) -> None:
"""Updates the value of a writable property
:param str property_name: The name of the property to write to
:param value: The value to set on the property
:raises IoTError: if there is no open connection to the MQTT broker
Expand All @@ -211,6 +222,7 @@ def send_property(self, property_name: str, value) -> None:

def send_telemetry(self, data) -> None:
"""Sends telemetry to the IoT Central app
:param data: The telemetry data to send
:raises IoTError: if there is no open connection to the MQTT broker
"""
Expand Down

0 comments on commit 4b72e22

Please sign in to comment.