/ README.rst
README.rst
  1  Adafruit_CircuitPython_AzureIoT
  2  ================================
  3  
  4  .. image:: https://readthedocs.org/projects/adafruit-circuitpython-azureiot/badge/?version=latest
  5      :target: https://circuitpython.readthedocs.io/projects/azureiot/en/latest/
  6      :alt: Documentation Status
  7  
  8  .. image:: https://img.shields.io/discord/327254708534116352.svg
  9      :target: https://adafru.it/discord
 10      :alt: Discord
 11  
 12  .. image:: https://github.com/adafruit/Adafruit_CircuitPython_AzureIoT/workflows/Build%20CI/badge.svg
 13      :target: https://github.com/adafruit/Adafruit_CircuitPython_AzureIoT/actions/
 14      :alt: Build Status
 15  
 16  A CircuitPython device library for `Microsoft Azure IoT Services <https://azure.microsoft.com/overview/iot/?WT.mc_id=AdafruitCircuitPythonAzureIoT-github-jabenn>`_ from a CircuitPython device. This library only supports key-base authentication, it currently doesn't support X.509 certificates.
 17  
 18  Installing from PyPI
 19  =====================
 20  On supported GNU/Linux systems like the Raspberry Pi, you can install the driver locally `from
 21  PyPI <https://pypi.org/project/adafruit-circuitpython-azureiot/>`_. To install for current user:
 22  
 23  .. code-block:: shell
 24  
 25      pip3 install adafruit-circuitpython-azureiot
 26  
 27  To install system-wide (this may be required in some cases):
 28  
 29  .. code-block:: shell
 30  
 31      sudo pip3 install adafruit-circuitpython-azureiot
 32  
 33  To install in a virtual environment in your current project:
 34  
 35  .. code-block:: shell
 36  
 37      mkdir project-name && cd project-name
 38      python3 -m venv .env
 39      source .env/bin/activate
 40      pip3 install adafruit-circuitpython-azureiot
 41  
 42  Dependencies
 43  =============
 44  This driver depends on:
 45  
 46  * `Adafruit CircuitPython <https://github.com/adafruit/circuitpython>`_
 47  * `Adafruit CircuitPython MiniMQTT <https://github.com/adafruit/Adafruit_CircuitPython_MiniMQTT>`_
 48  * `Adafruit CircuitPython Requests <https://github.com/adafruit/Adafruit_CircuitPython_Requests>`_
 49  * `Adafruit CircuitPython BinASCII <https://github.com/adafruit/Adafruit_CircuitPython_Binascii>`_
 50  
 51  Please ensure all dependencies are available on the CircuitPython filesystem.
 52  This is easily achieved by downloading
 53  `the Adafruit library and driver bundle <https://github.com/adafruit/Adafruit_CircuitPython_Bundle>`_.
 54  
 55  Usage Example
 56  =============
 57  
 58  This library supports both `Azure IoT Hub <https://azure.microsoft.com/services/iot-hub/?WT.mc_id=AdafruitCircuitPythonAzureIoT-github-jabenn>`_ and `Azure IoT Central <https://azure.microsoft.com/services/iot-central/?WT.mc_id=AdafruitCircuitPythonAzureIoT-github-jabenn>`__.
 59  
 60  To create an Azure IoT Hub instance or an Azure IoT Central app, you will need an Azure subscription. If you don't have an Azure subscription, you can sign up for free:
 61  
 62  - If you are a student 18 or over, head to `aka.ms/FreeStudentAzure <https://aka.ms/FreeStudentAzure>`_ and sign up, validating with your student email address. This will give you $100 of Azure credit and free tiers of a load of service, renewable each year you are a student. You will not need a credit card.
 63  
 64  - 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.
 65  
 66  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:
 67  
 68  .. code-block:: python
 69  
 70      ntp = NTP(esp)
 71  
 72      # Wait for a valid time to be received
 73      while not ntp.valid_time:
 74          time.sleep(5)
 75          ntp.set_time()
 76  
 77  Azure IoT Hub
 78  -------------
 79  
 80  To interact with Azure IoT Hub, you will need to create a hub, and a register a device inside that hub. There is a free tier available, and this free tier allows up to 8,000 messages a day, so try not to send messages too often if you are using this tier.
 81  
 82  - Open the `Azure Portal <https://aka.ms/AzurePortalHome>`_. 
 83  - Follow the instructions in `Microsoft Docs <https://aka.ms/CreateIoTHub>`_ to create an Azure IoT Hub and register a device.
 84  - Copy the devices Primary or secondary connection string, and add this to your ``secrets.py`` file.
 85  
 86  You can find the device connection string by selecting the IoT Hub in the `Azure Portal <https://aka.ms/AzurePortalHome>`_, *selecting Explorer -> IoT devices*, then selecting your device.
 87  
 88  .. image:: iot-hub-device.png
 89     :alt: Locating the device in the IoT hub blade
 90  
 91  *Locating the device in the IoT hub blade*
 92  
 93  Then copy either the primary or secondary connection string using the copy button next to the value.
 94  
 95  .. image:: iot-hub-device-keys.png
 96     :alt: Copy the primary connection string
 97  
 98  *Copy the primary connection string*
 99  
100  **Connect your device to Azure IoT Hub**
101  
102  .. code-block:: python
103  
104      from adafruit_azureiot import IoTHubDevice
105  
106      device = IoTHubDevice(wifi, secrets["device_connection_string"])
107      device.connect()
108  
109  Once the device is connected, you will regularly need to run a ``loop`` to poll for messages from the cloud.
110  
111  .. code-block:: python
112  
113      while True:
114          device.loop()
115          time.sleep(1)
116  
117  **Send a device to cloud message**
118  
119  .. code-block:: python
120  
121      message = {"Temperature": temp}
122      device.send_device_to_cloud_message(json.dumps(message))
123  
124  **Receive device to cloud messages**
125  
126  .. code-block:: python
127  
128      def cloud_to_device_message_received(body: str, properties: dict):
129          print("Received message with body", body, "and properties", json.dumps(properties))
130  
131      # Subscribe to cloud to device messages
132      device.on_cloud_to_device_message_received = cloud_to_device_message_received
133  
134  **Receive direct methods**
135  
136  .. code-block:: python
137  
138      def direct_method_invoked(method_name: str, payload) -> IoTResponse:
139          print("Received direct method", method_name, "with data", str(payload))
140          # return a status code and message to indicate if the direct method was handled correctly
141          return IoTResponse(200, "OK")
142  
143      # Subscribe to direct methods
144      device.on_direct_method_invoked = direct_method_invoked
145  
146  **Update reported properties on the device twin**
147  
148  *This is not supported on Basic tier IoT Hubs, only on the free and standard tiers.*
149  
150  .. code-block:: python
151  
152      patch = {"Temperature": temp}
153      device.update_twin(patch)
154  
155  **Subscribe to desired property changes on the device twin**
156  
157  *This is not supported on Basic tier IoT Hubs, only on the free and standard tiers.*
158  
159  .. code-block:: python
160  
161      def device_twin_desired_updated(desired_property_name: str, desired_property_value, desired_version: int):
162          print("Property", desired_property_name, "updated to", str(desired_property_value), "version", desired_version)
163  
164      # Subscribe to desired property changes
165      device.on_device_twin_desired_updated = device_twin_desired_updated
166  
167  Azure IoT Central
168  -----------------
169  
170  To use Azure IoT Central, you will need to create an Azure IoT Central app, create a device template and register a device against the template.
171  
172  - Head to `Azure IoT Central <https://apps.azureiotcentral.com/?WT.mc_id=AdafruitCircuitPythonAzureIoT-github-jabenn>`__ 
173  - Follow the instructions in the `Microsoft Docs <https://docs.microsoft.com/azure/iot-central/core/quick-deploy-iot-central?WT.mc_id=AdafruitCircuitPythonAzureIoT-github-jabenn>`__ to create an application. Every tier is free for up to 2 devices.
174  - Follow the instructions in the `Microsoft Docs <https://docs.microsoft.com/azure/iot-central/core/quick-create-simulated-device?WT.mc_id=AdafruitCircuitPythonAzureIoT-github-jabenn>`__ to create a device template.
175  - Create a device based off the template, and select **Connect** to get the device connection details. Store the ID Scope, Device ID and either the Primary or secondary Key in your ``secrets.py`` file.
176  
177  .. image:: iot-central-connect-button.png
178     :alt: The IoT Central connect button
179  
180  *The connect button*
181  
182  .. image:: iot-central-connect-dialog.png
183     :alt: The IoT Central connection details dialog
184  
185  *The connection details dialog*
186  
187  .. code-block:: python
188  
189      secrets = {
190          # WiFi settings
191          "ssid": "",
192          "password": "",
193  
194          # Azure IoT Central settings
195          "id_scope": "",
196          "device_id": "",
197          "key": ""
198      }
199  
200  **Connect your device to your Azure IoT Central app**
201  
202  .. code-block:: python
203  
204      from adafruit_azureiot import IoTCentralDevice
205  
206      device = IoTCentralDevice(wifi, secrets["id_scope"], secrets["device_id"], secrets["key"])
207      device.connect()
208  
209  Once the device is connected, you will regularly need to run a ``loop`` to poll for messages from the cloud.
210  
211  .. code-block:: python
212  
213      while True:
214          device.loop()
215          time.sleep(1)
216  
217  **Send telemetry**
218  
219  .. code-block:: python
220  
221      message = {"Temperature": temp}
222      device.send_telemetry(json.dumps(message))
223  
224  **Listen for commands**
225  
226  .. code-block:: python
227  
228      def command_executed(command_name: str, payload) -> IoTResponse:
229          print("Command", command_name, "executed with payload", str(payload))
230          # return a status code and message to indicate if the command was handled correctly
231          return IoTResponse(200, "OK")
232  
233      # Subscribe to commands
234      device.on_command_executed = command_executed
235  
236  **Update properties**
237  
238  .. code-block:: python
239  
240      device.send_property("Desired_Temperature", temp)
241  
242  **Listen for property updates**
243  
244  .. code-block:: python
245  
246      def property_changed(property_name, property_value, version):
247          print("Property", property_name, "updated to", str(property_value), "version", str(version))
248  
249      # Subscribe to property updates
250      device.on_property_changed = property_changed
251  
252  Learning more about Azure IoT services
253  --------------------------------------
254  
255  If you want to learn more about setting up or using Azure IoT Services, check out the following resources:
256  
257  - `Azure IoT documentation on Microsoft Docs <https://docs.microsoft.com/azure/iot-fundamentals/?WT.mc_id=AdafruitCircuitPythonAzureIoT-github-jabenn>`_
258  - `IoT learning paths and modules on Microsoft Learn <https://docs.microsoft.com/learn/browse/?term=iot&WT.mc_id=AdafruitCircuitPythonAzureIoT-github-jabenn>`_ - Free, online, self-guided hands on learning with Azure IoT services
259  
260  Contributing
261  ============
262  
263  Contributions are welcome! Please read our `Code of Conduct
264  <https://github.com/adafruit/Adafruit_CircuitPython_AzureIoT/blob/master/CODE_OF_CONDUCT.md>`_
265  before contributing to help this project stay welcoming.
266  
267  Documentation
268  =============
269  
270  For information on building library documentation, please check out `this guide <https://learn.adafruit.com/creating-and-sharing-a-circuitpython-library/sharing-our-docs-on-readthedocs#sphinx-5-1>`_.