... at work last week, I was planning to deal with something called Azure IoT Hub, but due to time constraints, I barely touched it. Luckily through some great efforts my colleagues made, I got a grasp of it, so when Friday came by, I was motivated to catch up. As you've seen from my previous articles, I'm interested in machine vision and Coral Boards. What those things have to do with Azure IoT Hub? My next project ...
Our company project on IoT Hub at work is about monitoring different parameters of a freezer. Which assumes sensors
that are measuring power consumption and temperature. It also assumes collecting these signals and forwarding them to
an IoT hub, where we analyze them.
I have no such sensors, so instead I came up with a LEGO use case: which character appears in front of my camera? When I place
a LEGO figure in front of my camera, I would like it to be recognized and I would like to store that recognition in the cloud.
First steps:
Microsoft suggests using Moby as a docker runtime, but they are okay with me using Docker in non-production environments. So, let's grab Docker:
# wget https://download.docker.com/linux/static/stable/aarch64/docker-20.10.3.tgz # tar xzvf docker-20.10.3.tgz # sudo cp docker/* /usr/bin/
Complete post-installation steps:
# sudo groupadd docker # sudo usermod -aG docker $USER # newgrp docker
And create a service for Docker:
# cd /etc/systemd/system # sudo vi docker.service ``` [Service] ExecStart=/usr/bin/dockerd ``` # sudo systemctl daemon-reload
We know that everything; always; works; for the first time (at least in articles), so we bravely test:
# docker pull hello-world # docker images REPOSITORY TAG IMAGE ID CREATED SIZE hello-world latest a29f45ccde2a 13 months ago 9.14kB # docker run hello-world Hello from Docker! This message shows that your installation appears to be working correctly.
Next step on our magic journey is to get the Azure IoT Edge installed:
# curl -L https://github.com/Azure/azure-iotedge/releases/download/1.1.0/libiothsm-std_1.1.0-1-1_debian9_arm64.deb -o libiothsm-std.deb && sudo dpkg -i ./libiothsm-std.deb # curl -L https://github.com/Azure/azure-iotedge/releases/download/1.1.0/iotedge_1.1.0-1_debian9_arm64.deb -o iotedge.deb && sudo dpkg -i ./iotedge.deb % Total % Received % Xferd Average Speed Time Time Time Current Dload Upload Total Spent Left Speed 100 641 100 641 0 0 2595 0 --:--:-- --:--:-- --:--:-- 2595 100 4598k 100 4598k 0 0 6752k 0 --:--:-- --:--:-- --:--:-- 6752k Selecting previously unselected package iotedge. (Reading database ... 46240 files and directories currently installed.) Preparing to unpack ./iotedge.deb ... Adding system user `iotedge' (UID 109) ... Adding new user `iotedge' (UID 109) with group `nogroup' ... Creating home directory `/var/lib/iotedge' ... Adding group `iotedge' (GID 118) ... Done. Adding user `iotedge' to group `docker' ... Adding user iotedge to group docker Done. Unpacking iotedge (1.1.0-1) ... Setting up iotedge (1.1.0-1) ... =============================================================================== Azure IoT Edge IMPORTANT: Please update the configuration file located at: /etc/iotedge/config.yaml with your device's provisioning information. You will need to restart the 'iotedge' service for these changes to take effect. To restart the 'iotedge' service, use: 'systemctl restart iotedge' - OR - /etc/init.d/iotedge restart These commands may need to be run with sudo depending on your environment. =============================================================================== Created symlink /etc/systemd/system/sockets.target.wants/iotedge.mgmt.socket → /lib/systemd/system/iotedge.mgmt.socket. Created symlink /etc/systemd/system/multi-user.target.wants/iotedge.service → /lib/systemd/system/iotedge.service. Created symlink /etc/systemd/system/sockets.target.wants/iotedge.socket → /lib/systemd/system/iotedge.socket. Processing triggers for systemd (241-7~deb10u4) ... Processing triggers for man-db (2.8.5-2) ...
... let the MS documentation talk for itself. As it's shown below (first steps), we need to edit the iotedge confiy.yaml file. You also can see that I'm ignoring reality and running things despite 'Warnings' and 'Errors'.
# sudo chmod u+w /etc/iotedge/config.yaml # sudo vi /etc/iotedge/config.yaml # sudo systemctl status iotedge ● iotedge.service - Azure IoT Edge daemon Loaded: loaded (/lib/systemd/system/iotedge.service; enabled; vendor preset: enabled) Active: active (running) since Sat 2021-02-20 09:30:07 UTC; 1s ago Docs: man:iotedged(8) Main PID: 5099 (iotedged) Tasks: 14 (limit: 4347) Memory: 7.8M CGroup: /system.slice/iotedge.service └─5099 /usr/bin/iotedged -c /etc/iotedge/config.yaml Feb 20 09:30:07 rendel iotedged[5099]: 2021-02-20T09:30:07Z [INFO] - Finished removing modules. Feb 20 09:30:07 rendel iotedged[5099]: 2021-02-20T09:30:07Z [INFO] - Edge issuer CA expiration date: 2021-05-21T09:20:45Z Feb 20 09:30:08 rendel iotedged[5099]: 2021-02-20T09:30:08Z [INFO] - Starting management API... Feb 20 09:30:08 rendel iotedged[5099]: 2021-02-20T09:30:08Z [INFO] - Starting workload API... Feb 20 09:30:08 rendel iotedged[5099]: 2021-02-20T09:30:08Z [INFO] - Starting watchdog with 60 second frequency... Feb 20 09:30:08 rendel iotedged[5099]: 2021-02-20T09:30:08Z [INFO] - Listening on fd://iotedge.mgmt.socket/ with 1 thread for management API. Feb 20 09:30:08 rendel iotedged[5099]: 2021-02-20T09:30:08Z [INFO] - Listening on fd://iotedge.socket/ with 1 thread for workload API. Feb 20 09:30:08 rendel iotedged[5099]: 2021-02-20T09:30:08Z [INFO] - Checking edge runtime status Feb 20 09:30:08 rendel iotedged[5099]: 2021-02-20T09:30:08Z [INFO] - Creating and starting edge runtime module edgeAgent Feb 20 09:30:09 rendel iotedged[5099]: 2021-02-20T09:30:09Z [INFO] - Updating identity for module $edgeAgent ``` sudo iotedge check Configuration checks -------------------- √ config.yaml is well-formed - OK √ config.yaml has well-formed connection string - OK √ container engine is installed and functional - OK √ config.yaml has correct hostname - OK √ config.yaml has correct URIs for daemon mgmt endpoint - OK √ latest security daemon - OK √ host time is close to real time - OK √ container time is close to host time - OK ‼ DNS server - Warning Container engine is not configured with DNS server setting, which may impact connectivity to IoT Hub. Please see https://aka.ms/iotedge-prod-checklist-dns for best practices. You can ignore this warning if you are setting DNS server per module in the Edge deployment. ‼ production readiness: certificates - Warning The Edge device is using self-signed automatically-generated development certificates. They will expire in 89 days (at 2021-05-21 09:20:45 UTC) causing module-to-module and downstream device communication to fail on an active deployment. After the certs have expired, restarting the IoT Edge daemon will trigger it to generate new development certs. Please consider using production certificates instead. See https://aka.ms/iotedge-prod-checklist-certs for best practices. ‼ production readiness: container engine - Warning Device is not using a production-supported container engine (moby-engine). Please see https://aka.ms/iotedge-prod-checklist-moby for details. ‼ production readiness: logs policy - Warning Container engine is not configured to rotate module logs which may cause it run out of disk space. Please see https://aka.ms/iotedge-prod-checklist-logs for best practices. You can ignore this warning if you are setting log policy per module in the Edge deployment. ‼ production readiness: Edge Agent's storage directory is persisted on the host filesystem - Warning The edgeAgent module is not configured to persist its /tmp/edgeAgent directory on the host filesystem. Data might be lost if the module is deleted or updated. Please see https://aka.ms/iotedge-storage-host for best practices. × production readiness: Edge Hub's storage directory is persisted on the host filesystem - Error Could not check current state of edgeHub container Connectivity checks ------------------- √ host can connect to and perform TLS handshake with IoT Hub AMQP port - OK √ host can connect to and perform TLS handshake with IoT Hub HTTPS / WebSockets port - OK √ host can connect to and perform TLS handshake with IoT Hub MQTT port - OK √ container on the default network can connect to IoT Hub AMQP port - OK √ container on the default network can connect to IoT Hub HTTPS / WebSockets port - OK √ container on the default network can connect to IoT Hub MQTT port - OK √ container on the IoT Edge module network can connect to IoT Hub AMQP port - OK √ container on the IoT Edge module network can connect to IoT Hub HTTPS / WebSockets port - OK √ container on the IoT Edge module network can connect to IoT Hub MQTT port - OK 17 check(s) succeeded. 5 check(s) raised warnings. Re-run with --verbose for more details. 1 check(s) raised errors. Re-run with --verbose for more details.
Let's check that the device is visible in our IoT Hub (coralEdge-xxxxxx is the name):
# az iot hub device-identity list -n xxxxx [ { "authenticationType": "sas", "capabilities": { "iotEdge": true }, "cloudToDeviceMessageCount": 0, "connectionState": "Connected", "deviceEtag": xxxxx, "deviceId": "coralEdge", "deviceScope": "ms-azure-iot-edge://coralEdge-xxxxxx", "etag": xxxxx, "lastActivityTime": "2021-02-20T18:06:24.1691626Z", "modelId": "", "properties": { "desired": { "$metadata": { "$lastUpdated": "2021-02-20T09:23:53.6707052Z" }, "$version": 1 }, "reported": { "$metadata": { "$lastUpdated": "2021-02-20T09:23:53.6707052Z" }, "$version": 1 } }, "status": "enabled", "statusUpdateTime": "0001-01-01T00:00:00Z", "version": 2, "x509Thumbprint": { "primaryThumbprint": null, "secondaryThumbprint": null } } ]
Now it's possible to send messages from the board to the IoT Hub. Below is a super simple Python code to send a message:
from azure.iot.device.aio import IoTHubDeviceClient from azure.iot.device import Message import json import datetime import asyncio CONNECTION_STRING = "HostName=xxxxx;DeviceId=coralEdge;SharedAccessKey=xxxxx" temp = [] temp.append({'timeCreated':datetime.datetime.now().isoformat(), "recognition": "Luke"}) temp = json.dumps(temp).encode() message = Message(temp) if __name__ == '__main__': client = IoTHubDeviceClient.create_from_connection_string(CONNECTION_STRING) asyncio.run(client.send_message(message))
On the other end at the IoT Hub one can monitor messages:
# az iot hub monitor-events -n xxxxx Starting event monitor, use ctrl-c to stop... { "event": { "origin": "coralEdge", "module": "", "interface": "", "component": "", "payload": [ { "timeCreated": "2021-02-21T19:01:46.574708", "recognition": "Luke" } ] } }
Today we've looked at how to transform the Coral Board into an Azure IoT Edge device. We also shown
that image detection can be done on the edge, and it's enough to send only the result of that to the cloud.
... and I'm sorry to say, but to keep this article short, I left out some parts: