#Event – “Let’s code a drone to follow faces syncing everything with Azure IoT” at the Codegen 2021, Verona, Italy. Session Resources

Buy Me A Coffee

Hi !

I had a great time early in the day with some friend from Italy.

drone telemetry in azure IoT

As usual, time for slides and code:

Slides

Code

https://github.com/elbruno/events/tree/main/2021%2002%2013%20CodeGen%20Verona%20Italy%20Drone%20Azure%20IoT

My Session – Video

All Sessions – Videos

All +40 sessions here http://codegen2021.azurewebsites.net/videos

Resources

Happy coding!

Greetings

El Bruno


#Coding4Fun – How to control your #drone ✈ with 20 lines of code! (24/N) #AzureIoT

Buy Me A Coffee

Hi !

Final post, so let’s recap

We have a device template representing a drone, tracking accelerometer, battery and temperature values.

We have created a new device to twin our drone in Azure IoT Central. And, copy the connect information: ScopeId, DeviceId and Key.

Let’s use a “get data from drone demo” and publish this information to Azure IoT Central.

I’ll share the complete file below, however let’s take a look at the main app code.

  • The following code block iterates 300 times while is reading drone information.
  • In each iteration, it send to the drone devices the accelerometer values. These are drone telemetry capabilities.
  • Every 10 iterations, it also update other drone capabilities: battery and temperature. These are drone properties.
# MAIN APP
battery = 0
agx     = 0
agy     = 0
agz     = 0
temph   = 0
templ   = 0

i = 0
while i < 300:
    i = i + 1
    sendReadCommand('battery?')
    await drone.send_telemetry(agx, agy, agz)
    if (i % 10) == 0:
        await drone.send_properties(temph, templ, battery)
    time.sleep(1)

Once we run the app, Azure IoT Central dashboard will show the real-time information from the drone. If the drone is flying and reporting accelerometer values, the agx, agy, agz chart will display the values related to axis x, y and z.

drone azure iot central out of battery

Disclaimer: I declared the temperature unit as Celsius. You can quickly realize that the values are in Farenheight.

And as promised here is the full code for this demo.

# Copyright (c) 2020
# Author: Bruno Capuano
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
#
# ———————————————–
# 70 AZURE IOT HUB Sample
# ———————————————–
import socket
import time
import threading
import iotc
import provision_service
import asyncio
import json
import datetime
from drone_device import Drone_Device
# ———————————————–
# RECEIVE DATA FUNCTIONS
# ———————————————–
def receiveData():
global response, clientSocket
while True:
try:
response, _ = clientSocket.recvfrom(1024)
except:
break
def readStates():
global battery, agx, agy, agz, temph, templ
global response, response_state, clientSocket, stateSocket, address
while True:
try:
response_state, _ = stateSocket.recvfrom(256)
if response_state != 'ok':
response_state = response_state.decode('ASCII')
list = response_state.replace(';', ':').split(':')
battery = int(list[21])
agx = float(list[27])
agy = float(list[29])
agz = float(list[31])
temph = int(list[15])
templ = int(list[13])
# except:
# break
except Exception as e:
print(f'exc: {e}')
pass
# ———————————————–
# SEND COMMAND FUNCTIONS
# ———————————————–
def sendCommand(command):
global response, clientSocket, address
timestamp = int(time.time() * 1000)
clientSocket.sendto(command.encode('utf-8'), address)
while response is None:
if (time.time() * 1000) timestamp > 5 * 1000:
return False
return response
def sendReadCommand(command):
global response
response = sendCommand(command)
try:
response = str(response)
except:
pass
return response
def sendControlCommand(command):
global response, response_state, clientSocket, stateSocket, address
response = None
for i in range(0, 5):
response = sendCommand(command)
if response == 'OK' or response == 'ok':
return True
return False
# ———————————————–
# AZURE IOT CENTRAL
# ———————————————–
async def init_drone_AzureIoT():
global drone
iothub = ""
scope = "Azure IoT Central Device Connect Scope ID goes here"
device_id = "Azure IoT Central Device Connect Device ID goes here"
key = "Azure IoT Central Device Connect KEY goes here"
drone = Drone_Device(scope, device_id, key)
await drone.init_azureIoT()
# ———————————————–
# 35 CAMERA
# APP DISPLAY CAMERA WITH OPENCV and FPS
# ———————————————–
async def main():
global battery, agx, agy, agz, temph, templ
global response, response_state, clientSocket, stateSocket, address
global drone
await init_drone_AzureIoT()
# CONNECTION TO THE DRONE
# connection info
UDP_IP = '192.168.10.1'
UDP_PORT = 8889
last_received_command = time.time()
STATE_UDP_PORT = 8890
address = (UDP_IP, UDP_PORT)
response = None
response_state = None
clientSocket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
clientSocket.bind(('', UDP_PORT))
stateSocket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
stateSocket.bind(('', STATE_UDP_PORT))
# LISTENER THREADS
# start threads
recThread = threading.Thread(target=receiveData)
recThread.daemon = True
recThread.start()
stateThread = threading.Thread(target=readStates)
stateThread.daemon = True
stateThread.start()
# START DRONE CONNECTION
# connect to drone
response = sendControlCommand("command")
print(f'command response: {response}')
response = sendControlCommand("streamon")
print(f'streamon response: {response}')
# MAIN APP
# drone information
battery = 0
agx = 0
agy = 0
agz = 0
temph = 0
templ = 0
i = 0
while i < 300:
i = i + 1
sendReadCommand('battery?')
await drone.send_telemetry(agx, agy, agz)
if (i % 10) == 0:
await drone.send_properties(temph, templ, battery)
time.sleep(1)
if __name__ == "__main__":
asyncio.run(main())

In the next post we will connect everything together !

Happy coding!

Greetings

El Bruno


References


¿Con ganas de ponerte al día?

En Lemoncode te ofrecemos formación online impartida por profesionales que se baten el cobre en consultoría:

#Coding4Fun – How to control your #drone ✈ with 20 lines of code! (23/N) #AzureIoT

Buy Me A Coffee

Hi !

Now that we have a device template created, we can create a new device in our Azure IoT Central portal and start to send information to Azure IoT.

We start by creating a new device based on the previous template and it’s time to copy and paste the connection information for this device:

  • ID scope
  • Device ID
  • Primary Key
drone connect information

And, based on the official Python SDK documentation, I created this full class to send information to Azure IoT Central. A couple of notes

  • The class needs scopeID, deviceID and key in the constructor to create the device connection string
  • There are 2 main functions to showcase how to send telemetry and update properties
  • Telemetry (send_telemetry) uses the predefined device capabilities: agx, agy and agz
  • Properties (send_properties) uses the predefined device capabilities: battery, templ and temph
# Copyright (c) 2020
# Author: Bruno Capuano
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
#
import os
import datetime
import asyncio
import json
from azure.iot.device.aio import IoTHubDeviceClient
from azure.iot.device import MethodResponse
from azure.iot.device.aio import ProvisioningDeviceClient
class Drone_Device():
def __init__(self, scope, device_id, key, iothub : str = ""):
self.scope = scope
self.device_id = device_id
self.key = key
self.iothub = iothub
async def init_azureIoT(self):
cnn_str = await self.get_connection_string()
self.device_client = IoTHubDeviceClient.create_from_connection_string(cnn_str)
await self.device_client.connect()
async def __register_device(self):
provisioning_device_client = ProvisioningDeviceClient.create_from_symmetric_key(
provisioning_host='global.azure-devices-provisioning.net',
registration_id=self.device_id,
id_scope=self.scope,
symmetric_key=self.key,
)
return await provisioning_device_client.register()
async def get_connection_string(self):
if(self.iothub == None or self.iothub == ""):
print(f'{datetime.datetime.now()}: No IOTHUB specified. Attempting to resolve via global.azure-devices-provisioning.net')
results = await asyncio.gather(self.__register_device())
print(results)
registration_result = results[0]
cnn_str = 'HostName=' + registration_result.registration_state.assigned_hub + \
';DeviceId=' + self.device_id + \
';SharedAccessKey=' + self.key
else:
cnn_str = 'HostName=' + self.iothub + \
';DeviceId=' + self.device_id + \
';SharedAccessKey=' + self.key
print(f'{datetime.datetime.now()}: Connection String = {cnn_str}')
return cnn_str
async def send_telemetry(self, agx, agy, agz):
try:
payload:str = ""
data = {
"agx": agx,
"agy": agy,
"agz": agz
}
payload = json.dumps(data)
print(f"{datetime.datetime.now()}: telemetry: {payload}")
await self.device_client.send_message(payload)
except Exception as e:
print(f"{datetime.datetime.now()}: Exception during sending metrics: {e}")
async def send_properties(self, bat, temph, templ):
try:
data = {
'bat': bat,
'templ': templ,
'temph': temph
}
propertiesToUpdate = data
print(f"{datetime.datetime.now()}: properties: {propertiesToUpdate}")
await self.device_client.patch_twin_reported_properties(propertiesToUpdate)
except Exception as e:
print(f"{datetime.datetime.now()}: Exception during sending metrics: {e}")

In the next post we will connect everything together !

Happy coding!

Greetings

El Bruno


References


¿Con ganas de ponerte al día?

En Lemoncode te ofrecemos formación online impartida por profesionales que se baten el cobre en consultoría:

#Coding4Fun – How to control your #drone ✈ with 20 lines of code! (22/N) #AzureIoT

Buy Me A Coffee

Hi !

In my the live events where I explain how to code to control the drone, I show a scenario where drone information is sent to Azure IoT Central. I just realized that I never wrote about it, so here is post 1 of N to describe this scenario.

Azure IoT Central

As usual let’s start with the official description for this Azure Service

IoT Central is an IoT application platform that reduces the burden and cost of developing, managing, and maintaining enterprise-grade IoT solutions. Choosing to build with IoT Central gives you the opportunity to focus time, money, and energy on transforming your business with IoT data, rather than just maintaining and updating a complex and continually evolving IoT infrastructure.

The web UI lets you monitor device conditions, create rules, and manage millions of devices and their data throughout their life cycle. Furthermore, it enables you to act on device insights by extending IoT intelligence into line-of-business applications.

What is Azure IoT Central ? see references

In the final output of this demo, we will have a device definition on Azure IoT central tracking

  • Realtime values for the drone accelerator (axis x, y, z)
  • Drone temperature (lowest and highest)
  • Battery charge, in %

Something similar to this 👇

drone azure iot central out of battery

Drone Template

My 1st step is to create a device template. I was testing different configurations, and at the end I finalize with the 4th iteration of my drone template: DroneTemplate v4

drone device template list

This template defines the following capabilities

  • Telemetry
    • agx
    • agy
    • agz
  • Properties
    • temph
    • templ
    • bat
drone template capabilities

Important: we can use custom data types, like Vector for accelerometer. However in this sample, all the properties and telemetry are defined as Integer values.

Now it’s time to create a view to display some of the device properties. In this scenario I added a chart with the telemetry agx, agy and agz. And 2 separate viewers for the battery and temperature.

In the temperature tile, I added a conditional formatting to display the battery value in different colors depending of the device battery charge.

And that’s it! With this simple device definition I can start to connect my test drone with the Azure IoT Central portal.

Happy coding!

Greetings

El Bruno


References


¿Con ganas de ponerte al día?

En Lemoncode te ofrecemos formación online impartida por profesionales que se baten el cobre en consultoría:

#RaspberryPi – Putting all together to display device temperature using #AzureIoT and #docker. Privilege permissions and other lessons learned

Hi!

Today challenge was based on an easy one

How do I get a Raspberry Pi temperature using Python?

The lines to do this are quite simple, with the following lines we can get the absolute value for the device temperature, in Celsius (of course!)

import os
def getCPUtemperature():
res = os.popen('vcgencmd measure_temp').readline()
return(res.replace("temp=","").replace("'C\n",""))
print(getCPUtemperature())

Easy! My next step was to add a new [Device Property] to my [Device Template] in Azure IoT. I’ll store this as a temp string, so this is fine.

azure iot device template for raspberry pi with the temperature as device property

The lines to send the temperature as a device property are part of the following code sample. I also track the temperature as telemetry so I can work with the history of the device temp

import os
import iotc
def getCPUtemperature():
res = os.popen('vcgencmd measure_temp').readline()
return(res.replace("temp=","").replace("'C\n",""))
def sendTempAndConnectionDate():
print("Sending temp and connection date ..")
propJson = "{\"rpiTemp\": \"" + str(getCPUtemperature()) + "\"}"
iotc.sendProperty(propJson)
telemetryMessage = "{\"temp\": " + str(getCPUtemperature()) + "}"
iotc.sendTelemetry(telemetryMessage)

So far, so good!

Now it was time to package all this in a docker image and run it from a container. I got an ugly surprise when I realize that I got an exception trying to get the device temperature

VCHI Initialization failed

Time to read and learn more about docker and containers on Raspberry Pi.

In the official documentation of [Docker Run, see references] I found a couple of options which may help me. There are 2 options to allow me access to the device temperature

  • Run the container with the specific path to the device I want to grant privileged access for my container
  • Run the container with the [–privileged] argument to enable access to all devices on the host

Of course, the 2nd one is easier, but much more dangerous

When the operator executes docker run –privileged, Docker will enable access to all devices on the host as well as set some configuration in AppArmor or SELinux to allow the container nearly all the same access to the host as processes running outside containers on the host. Additional information about running with –privileged is available on the Docker Blog.

I didn’t think twice and run my image with the [–privileged] argument.

sudo docker run --privileged -p 80:80 <Image ID>

And now I can get an amazing history and track of information using docker, containers and Azure IoT with a Raspberry Pi

azure iot dashboard displaying temperature history as a telemetry

Happy coding!

References

#Azure – Sending custom Telemetry and Event information from a #RaspberryPi device to #AzureIoT Central

Hi!

Azure IoT Central is one of the amazing services we can use on Azure. I was wondering how easy is to use a Raspberry Pi using Raspbian and Azure IoT and here is my experience.

Let’s assume we had a device up to date using Raspbian, our next step will be to create an Azure IoT Central application. The official step by step is the main resource for this

Create an
Azure IoT Central application (see references)

Once we have our application, we can quickly create a new Raspberry Pi device and use it. However, I’ll do an extra step, lessons learned as a handsome developer

Create a Device Template

Go to [Device Templates] and create a new template

azure iot central create new device template

For Raspberry Pi, I’ll name this [Raspberry Pi Dev]

azure iot central create new device template raspberry pi dev

So now, I can add a new real device, in the Devices section from the left menu

azure iot central raspberry pi dev add new real device

Once you create a new real device, is important to copy and save for later the connection information. To access this, go to the top right [Connect] button

azure iot central raspberry pi dev real device connect information

Almost there, there is an official tutorial that explain how to send random telemetry information with a Python script in a Raspberry Pi. I’ll use it as base for this scenario.

Connect a
Raspberry Pi to your Azure IoT Central application (Python) (see references)

For this demo, I’ll add a custom telemetry property and a custom event to the device. Since I won’t use the device to track temperature, accelerometer, and more, I think it make sense to track some custom information.

So, I’ll go back to my Device Template definition and I’ll add a new Telemetry, named [t1], with the following information.

azure iot central raspberry pi dev new telemetry information

And now, I can run a custom version of my script that will send new telemetry information, for [t1]. Sample in line 18

# Copyright (c) Microsoft. All rights reserved.
# Licensed under the MIT license.
# Based on
# https://raw.githubusercontent.com/Azure/iot-central-firmware/master/RaspberryPi/app.py
while iotc.isConnected():
iotc.doNext() # do the async work needed to be done for MQTT
if gCanSend == True:
if gCounter % 20 == 0:
gCounter = 0
print("Sending telemetry..")
telemetryJson = "{\"temp\": " + str(randint(20, 45)) + ", \
\"accelerometerX\": " + str(randint(2, 15)) + ", \
\"accelerometerY\": " + str(randint(3, 9)) + ", \
\"accelerometerZ\": " + str(randint(3, 9)) + ", \
\"t1\": " + str(float(random.random()*100)) + "}"
print(telemetryJson)
iotc.sendTelemetry(telemetryJson)
gCounter += 1

After a couple of minutes running the sample script, I can see the telemetry information for T1. In this view, I enabled [Temperature] and [T1] to display the timeline.

azure iot central raspberry pi dev real device dashboard telemetry

And, next step will be to add an event, which is also a very important uses case in Azure IoT. Back in the Device Template, I add a new event named [event1]

azure iot central raspberry pi dev new event information

And added some extra lines of code to send also an event between telemetry, Line 22

# Copyright (c) Microsoft. All rights reserved.
# Licensed under the MIT license.
# Based on
# https://raw.githubusercontent.com/Azure/iot-central-firmware/master/RaspberryPi/app.py
while iotc.isConnected():
iotc.doNext() # do the async work needed to be done for MQTT
if gCanSend == True:
if gCounter % 20 == 0:
gCounter = 0
print("Sending telemetry..")
telemetryJson = "{\"temp\": " + str(randint(20, 45)) + ", \
\"accelerometerX\": " + str(randint(2, 15)) + ", \
\"accelerometerY\": " + str(randint(3, 9)) + ", \
\"accelerometerZ\": " + str(randint(3, 9)) + ", \
\"t1\": " + str(float(random.random()*100)) + "}"
print(telemetryJson)
iotc.sendTelemetry(telemetryJson)
if gCounter % 60 == 0:
print("Sending event ..")
eventJson = "{\"event1\": \"data " + str(float(random.random()*100)) + "\"}"
print(eventJson)
iotc.sendEvent(eventJson)
gCounter += 1

In the following image, we can see how the events appears in the timeline, and we can also get some extra details clicking on each event.

azure iot central raspberry pi dev real device dashboard telemetry and events

Very cool! Next steps will be to integrate this with some image recognition scenarios.

Happy Coding!

Greetings @ Burlington

El Bruno

References