4 min read

Creating an Azure IoT Edge project with 2 communicating modules

Learn how to create an Azure IoT Edge solution with 2 communicating modules (one in Python and one in Typescript)
Creating an Azure IoT Edge project with 2 communicating modules
Photo by Zan / Unsplash

When working with the Internet of Things, Azure is a valid choice! Offering IoT Hub and IoT Edge to help you create Edge modules for your devices. However, what is promised to be easy is currently quite "hard" to get working with.

Through this post I want to shed some light on how I was able to develop and push my modules today!

⚠️ Currently the state of today does not allow for easy local development as everything works through Docker compose which is orchestrated through the iotedgedev simulator tool. Just give up on this and go straight for a remote device (it will make your life much easier).

Tl;dr

Feel free to check out my latest repository to get the modules that can communicate with each other

PublicProjects/Azure-IoT-Edge/Typescript-and-Python-Modules-Communicating at master · XavierGeerinck/PublicProjects
Contribute to XavierGeerinck/PublicProjects development by creating an account on GitHub.

Goal

The goal of this post is to get acquainted with the latest development process of the Azure IoT Edge ecosystem and help deploy 2 modules (1 in Python and 1 in Typescript) that can send messages to each other.

Prerequisites

Let's start by installing our prerequisites and configuring Python correctly

💡 Currently only <= Python 3.9 is supported

# Add local bin to path
echo 'export PATH="/home/$USER/.local/bin:$PATH"' >> ~/.bashrc

# Install Python
sudo apt-update
sudo apt install -y python3.9
sudo ln -s /usr/bin/python3.9 /usr/bin/python
sudo ln -s /usr/bin/python3.9 /usr/bin/python3
sudo apt install -y python3-distutils
curl -s https://bootstrap.pypa.io/get-pip.py | python

# Install Docker
# ...

# Install Azure CLI - https://learn.microsoft.com/en-us/cli/azure/install-azure-cli 
# curl -L https://aka.ms/InstallAzureCli | bash # Note: this had the error that the path should start with /usr
pip install -U azure-cli; az upgrade

# Install IoT Edge Dev
# (v3.3.6 -> see https://pypi.org/project/iotedgedev/)
pip install -U iotedgedev 

# Create a `iotedgehubdev` folder with correct permissions 
sudo mkdir /var/lib/iotedgehubdev
sudo chmod -R 777 /var/lib/iotedgehubdev
sudo chmod -R 777 /etc/iotedgehubdev

# Install Cookiecutter
python -m pip install --user cookiecutter

# Install Yeoman and Azure IoT Edge Node.js
npm i -g yo generator-azure-iot-edge-module

# Try running `iotedgedev`
iotedgedev --help

Creating an IoT Edge Device in IoT Hub

Creating a Device

The first thing to do is to create an Azure IoT Edge device in the Azure Portal. So navigate to the IoT Hub and create a device with an identifier.

Connect the device to IoT Hub

Next up is to grab a device and connect it to IoT Hub

The below was executed for a Raspberry Pi
# Install IoT Edge
curl https://packages.microsoft.com/config/debian/11/packages-microsoft-prod.deb > ./packages-microsoft-prod.deb
sudo apt install ./packages-microsoft-prod.deb
sudo apt update

# Install Moby Container Engine
sudo apt install -y moby-engine

# Configure Moby for local logging

# Install IoT Edge Runtime
sudo apt -y install aziot-edge

# Provision with its cloud identity and check the status
sudo iotedge config mp --connection-string "CONNECTION_STRING"
sudo iotedge config apply
sudo iotedge system status

Creating an IoT Edge Solution

Creating the modules

For our solution we wanted to have 2 modules in a solution that communicate to each other. One node.js and one Python

# Create the solution
iotedgedev solution init --template python iot-edge

# Add a module
iotedgedev solution add --template python AudioRecording

# Add a module
iotedgedev solution add --template nodejs AudioInferencing

Build and push your modules

The device is connected to our IoT Hub and we can start deploying modules to it. So let's configure our Template to include our containers and push the modules.

To configure the template, open the .env file and ensure that your CONTAINER_REGISTRY_SERVER, CONTAINER_REGISTRY_USERNAME and CONTAINER_REGISTRY_PASSWORD variables are set

We are up and running now, we can publish our modules by running:

PLATFORM=arm32v7
ACR_REPO=YOUR_ACR_NAME

# Initialize qemu
docker run --rm --privileged multiarch/qemu-user-static --reset -p yes

# Generate the config from the deployment template
# More info: https://learn.microsoft.com/en-us/azure/iot-edge/module-composition?view=iotedge-1.4
iotedgedev solution genconfig --file deployment.template.json \
    --platform $PLATFORM

# Build and push your modules for the target architecture
for d in modules/*; do
    MODULE_DIR=$d
    MODULE_NAME=$(echo $d | cut -d "/" -f 2)
    MODULE_NAME_LOWER=$(echo $MODULE_NAME | tr '[:upper:]' '[:lower:]')

    echo "building $ACR_REPO.azurecr.io/$MODULE_NAME_LOWER"
    docker buildx build --push --platform linux/$PLATFORM \
        -t $ACR_REPO.azurecr.io/$MODULE_NAME_LOWER:0.0.1-arm32v7 \
        -f $MODULE_DIR/Dockerfile.$PLATFORM \
        $MODULE_DIR
done

# Push to the device
# similar to: az iot edge set-modules --hub-name my-iot-hub --device-id my-device --content ./deployment.debug.template.json --login "HostName=my-iot-hub.azure-devices.net;SharedAccessKeyName=iothubowner;SharedAccessKey=<SharedAccessKey>"
iotedgedev solution deploy --file config/deployment.arm32v7.json
💡 If you get "standard_init_linux.go:219: exec user process caused: exec format error" run docker run --rm --privileged multiarch/qemu-user-static --reset -p yes

The script above will deploy everything automatically to the devices.

Checking our deployment

When everything is deployed, we can log in on our device and check if everything is working. If correctly done so, you should see the following output

Summary

Personally, the iotedgedev tool is going the right way helping us create and deploy iot edge solutions more quickly. I just wish there was a way to develop locally more easily than what it offers now, but let's see what future will bring!