Introduction to Azure IoT for Beginners

1. What is IoT?

The Internet of Things (IoT) is a network of physical devices that connect to and exchange data with other devices and services over the Internet or other network. There are currently over ten billion connected devices in the world and more are added every year. Anything that can be embedded with the necessary sensors and software can be connected over the internet.

2. What is Azure IoT?


The Azure Internet of Things (IoT) is a collection of Microsoft-managed cloud services that connect, monitor, and control billions of IoT assets. In simpler terms, an IoT solution is made up of one or more IoT devices that communicate with one or more back-end services hosted in the cloud.

2.1. IoT devices

An IoT device is typically made up of a circuit board with sensors attached that use WiFi to connect to the internet. For example:

  • A pressure sensor on a remote oil pump.
  • Temperature and humidity sensors in an air-conditioning unit.
  • An accelerometer in an elevator.
  • Presence sensors in a room.

2.2. Back-end services

In an IoT solution, the back-end service provides functionality such as:

  • Receiving telemetry at scale from your devices, and determining how to process and store that data.
  • Analyzing the telemetry to provide insights, either in real time or after the fact.
  • Sending commands from the cloud to a specific device.
  • Provisioning devices and controlling which devices can connect to your infrastructure.
  • Controlling the state of your devices and monitoring their activities.
  • Managing the firmware installed on your devices.

2.3. Azure IoT Hub


Azure IoT Hub is a managed service hosted in the cloud that acts as a central message hub for communication between an IoT application and its attached devices. You can connect millions of devices and their backend solutions reliably and securely. Almost any device can be connected to an IoT hub.

You can integrate IoT Hub with other Azure services to build complete, end-to-end solutions. For example, use:

Azure Event Grid to enable your business to react quickly to critical events in a reliable, scalable, and secure manner.

Azure Logic Apps to automate business processes.

Azure Machine Learning to add machine learning and AI models to your solution.

Azure Stream Analytics to run real-time analytic computations on the data streaming from your devices.

IoT Hub supports:

  • Azure IoT SDK with some popular programming languages such as C, C#, Java, Python, Node.js.
  • Multiple protocols such as HTTPS, AMQP, MQTT.

2.4. Azure IoT Central


IoT Central is an IoT application platform as a service (aPaaS) that reduces the burden and cost of developing, managing, and maintaining enterprise-grade IoT solutions. If you choose to build with IoT Central, you'll have 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 quickly connect devices, 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.

IoT Central supports:

  • Industry specific app templates
  • No deep technical knowledge required
  • Highly secure, scalable and reliable
  • Built on top of the IoT Hub service and 30+ other services

2.5. Azure Sphere


Azure Sphere is a secured, high-level application platform with built-in communication and security features for internet-connected devices. It comprises a secured, connected, crossover microcontroller unit (MCU), a custom high-level Linux-based operating system (OS), and a cloud-based security service that provides continuous, renewable security.

The Azure Sphere MCU integrates real-time processing capabilities with the ability to run a high-level operating system. An Azure Sphere MCU, along with its operating system and application platform, enables the creation of secured, internet-connected devices that can be updated, controlled, monitored, and maintained remotely. A connected device that includes an Azure Sphere MCU, either alongside or in place of an existing MCUs, provides enhanced security, productivity, and opportunity. For example:

  • A secured application environment, authenticated connections, and opt-in use of peripherals minimizes security risks due to spoofing, rogue software, or denial-of-service attacks, among others.
  • Software updates can be automatically deployed from the cloud to any connected device to fix problems, provide new functionality, or counter emerging methods of attack, thus enhancing the productivity of support personnel.
  • Product usage data can be reported to the cloud over a secured connection to help in diagnosing problems and designing new products, thus increasing the opportunity for product service, positive customer interactions, and future development.

3. Demo

We will create a small application that uses Azure IoT Hub to control devices remotely over the internet on a Web interface that can be used on both PC and Smartphone.

Specifically, we will perform the control of a fan with infrared signals controlled by a Raspberry Pi device with LEDs that receive and send infrared signals.

3.1. Preparation

3.1.1. Azure subscription

  • Create an Azure IoT Hub used to send and receive messages from/to devices.
  • Creating Azure Function App specifically uses HttpTrigger to receive requests from users.

3.1.2. Raspberry Pi (Raspi)

  • The Raspi device has GPIO pins are able to connect LEDs to transmit and receive infrared signals.
  • The Raspi device will receive the message from the Azure IoT Hub and perform transmitting infrared signals corresponding to the request in the message.

3.1.3. Fan

  • A fan which can be controlled by infrared signal.

3.2. Implementation

3.2.1. Create Azure IoT Hub

  • Next, create a device as the following

3.2.2. Setting up the control circuit

Hardware Preparation
  • Raspberry Pi x 01
  • Breadboard x 01
  • IR Receiver(VS1838B) x 01
  • IR Sender x 01
  • Infrared Remote Controller of Fan x 01
  • Resistor(200Ω) x 02
  • Several jumper wires
  • T-Extension Board with 40-Pin Cable(Optional) x 01
Schematic diagram of IR Receiver and IR Sender with Raspberry Pi:

IR Receiver:

IR Sender:

In reality:

3.2.3. Setting up the remote controller for my fan on Raspberry Pi

LIRC (Linux Infrared Remote Control) Module Installation

The very first step is to install LIRC after setting up the Raspberry PI OS. Enter the command below to install LIRC.

sudo apt-get update -y && sudo apt-get upgrade -y
sudo apt-get install lirc -y
LIRC Module Configuration

Let's configure the LIRC module to send and receive the IR signal.

Bootloader Configuration
sudo vim /boot/config.txt

Uncomment the following lines and correct the pin number. The default values before being uncommented were 17 for gpio-ir and 18 for gpio-ir-tx. But it should be swapped (line #5-6).

# Uncomment this to enable infrared communication.
#dtoverlay=gpio-ir,gpio_pin=17
#dtoverlay=gpio-ir-tx,gpio_pin=18

dtoverlay=gpio-ir,gpio_pin=18
dtoverlay=gpio-ir-tx,gpio_pin=17
LIRC Module Hardware Configuration

Open the file below:

sudo vim /etc/lirc/hardware.conf

Then enter the following:

LIRCD_ARGS="--uinput --listen"
LOAD_MODULES=true
DRIVER="default"
DEVICE="/dev/lirc0"
MODULES="lirc_rpi"
LIRC Module Options Configuration
sudo vim /etc/lirc/lirc_options.conf

Change both driver and device values (line #3-4).

#driver         = devinput
#device         = auto
driver          = default
device          = /dev/lirc0

Once you've completed by now, reboot Raspberry PI to recognise the updated bootloader.

sudo reboot

Run this command to check the LIRC module working or not.

sudo /etc/init.d/lircd status

It's now working!

Manual Registration for Remote Controller

We need to create a configuration file to make a remote controller for our fan.
So, firstly, Raspberry PI should be double-checked whether the IR sensor on it captures the remote controller signal or not. First of all, stop the LIRC service.

sudo /etc/init.d/lircd stop

Run the following command to wait for the incoming IR signals.

sudo mode2 -m -d /dev/lirc0

You may get the following error message.

It's because both the IR sender and receiver are active at the same time. For this exercise, we only need the receiver, which is for capturing the IR signals. Disable the sender part. Open the bootloader.

sudo vim /boot/config.txt

We used to have both gpio-ir and gpio-ir-tx activated. As we don't need the sender part for now, update the file like below (line #5-6).

# Uncomment this to enable infrared communication.
#dtoverlay=gpio-ir,gpio_pin=17
#dtoverlay=gpio-ir-tx,gpio_pin=18

dtoverlay=gpio-ir,gpio_pin=18
#dtoverlay=gpio-ir-tx,gpio_pin=17

Once completed, reboot Raspberry PI using the command, sudo reboot. Once it's restarted, stop the LIRC server.
Then, run the following command so that you can confirm it works.

sudo mode2 -m -d /dev/lirc0

Now it's waiting for your IR signal input. Locate your remote controller close to Raspberry PI and punch some buttons. You'll find out the remote controller buttons are captured.

We confirm the incoming signals are properly captured. It's time to generate the remote controller file. Enter the following command:

sudo irrecord -d /dev/lirc0 --disable-namespace

Once running the command above, it gives you instructions to follow. Record your buttons by following the instruction. However, the recording application sometimes doesn't work as expected.
I had to use a different approach. Instead of using irrecord, I had to use mode2 to capture the button signals.

Record the button signals and write to configuration file (e.g., myfan.lircd.conf)


The number blocks in the red rectangle are the set of the controller button (ON_OFF button). As the last values of the box are an outlier, delete them. And remove all others except the number blocks. Let's add the followings around the number blocks.

Add begin remote ... begin raw_codes before the fist number block. They are from the random file on the database. I don't know what the exact value might look like. I just copied and pasted them to the file (line #1-13).

Give each number block a name like name ON_OFF. Each button has a different value represented by the number block. Therefore give those names extensively (line #15, 22).

Add the lines at the end of the final number block (line #29-30).

begin remote

  name   myfan
  flags RAW_CODES
  eps            25
  aeps          100

  ptrail          0
  repeat     0     0
  gap    20921


  begin raw_codes

    name ON_OFF
     1320      359     1335      358      494     1205
     1334      359     1335      359      493     1179
      515     1206      491     1205      491     1204
      ...
      489

    name TIME
     9000     4453      578      548      580      548
      578      549      556      572      552      576
      552     1683      577      551      550     1683
      ...
      573

  end raw_codes
end remote

A completed configuration file is as below:

begin remote

  name   myfan
  flags RAW_CODES
  eps            25
  aeps          100

  ptrail          0
  repeat     0     0
  gap    20921


  begin raw_codes

    name ON_OFF
     1319      359     1336      359      493     1208
     1329      360     1336      359      494     1179
      517     1205      490     1205      490     1208
      488     1206      490     1183     1356     7736
     1355      359     1335      359      495     1205
     1331      329     1377      349      495     1204
      491     1205      490     1206      490     1205
      490     1206      491     1179     1360     7730
     1362      357     1335      358      495     1180
     1358      359     1335      360      493     1209
      485     1205      491     1205      489     1205
      490     1206      490     1205     1334     7730
     1359      359     1338      359      499     1176
     1356      360     1336      360      492     1205
      490     1211      485     1206      489     1205
      491     1205      491     1205     1333     7735
     1355      360     1335      360      493     1206
     1333      362     1330      360      493     1206
      490     1204      492     1204      491     1205
      491     1205      488     1182     1360     7756
     1329      338     1358      365      487     1211
     1329      367     1331      361      487     1210
      486     1209      486     1210      485

    name TIME
     1318      358     1336      359      494     1180
     1358      358     1336      328     1370      356
      493     1205      491     1205      490     1206
     1333      358     1337      359      493     8575
     1360      361     1354      338      493     1206
     1332      360     1334      361     1334      360
      492     1188      508     1183      513     1180
     1358      360     1334      361      491     8580
     1354      360     1335      359      495     1204
     1334      357     1335      359     1336      326
      527     1204      489     1211      485     1205
     1333      357     1336      359      493     8570
     1361      360     1336      324      528     1205
     1341      323     1367      357     1335      358
      500     1201      488     1181      515     1204
     1339      355     1335      357      495     8573
     1359      359     1336      359      494     1205
     1333      359     1337      358     1339      356
      494     1204      491     1204      491

    name UP
     1345      361     1335      362      494     1204
     1331      328     1367      360      493     1207
      489     1182      513     1206     1331      373
      480     1215      481     1206      490     8632
     1355      360     1335      361      491     1207
     1336      356     1336      359      492     1206
      489     1207      489     1208     1330      361
      496     1202      490     1205      489     8584
     1401      361     1334      359      492     1207
     1331      361     1335      359      491     1207
      488     1181      514     1207     1331      361
      493     1182      513     1210      486     8629
     1359      358     1334      367      486     1206
     1331      361     1334      360      493     1206
      490     1205      490

    name DOWN
     1348      359     1336      358      493     1206
     1332      359     1336      359      493     1206
     1333      359      494     1207      488     1206
      490     1205      490     1206      490     8578
     1359      356     1336      358      494     1211
     1327      358     1336      358      495     1205
     1333      325      527     1180      515     1206
      489     1182      513     1205      491     8603
     1330      359     1336      359      494     1205
     1332      358     1342      352      494     1206
     1333      358      494     1205      491     1205
      491     1205      491     1204      491     8575
     1360      360     1333      358      493     1189
     1351      358     1335      359      494     1211
     1326      326      525     1205      491     1179
      515     1205      491     1204      491     8575
     1357      358     1340      321      528     1182
     1356      358     1336      358      494     1206
     1333      363      489     1205      491

    name SWING
     1346      359     1336      357      494     1207
     1333      359     1336      358      494     1206
      489     1207      490     1206      490     1206
      490     1182     1357      359      494     8581
     1355      358     1341      354      494     1205
     1334      358     1337      358      494     1205
      491     1206      491     1206      491     1205
      491     1182     1357      358      494     8601
     1334      359     1337      358      493     1185
     1355      359     1337      323      529     1179
      517     1205      490     1206      491     1205
      490     1206     1334      358      494     8575
     1359      359     1336      359      493     1206
     1334      358     1337      358      493     1206
      491     1179      516     1205      491     1204
      491     1206     1335      357      493     8578
     1361      356     1337      359      494     1206
     1334      359     1337      322      530     1205
      491     1205      491     1205      491     1204
      491     1205     1334      324      529     8575
     1359      359     1338      357      493     1206
     1334      358     1336      360      494     1205
      491     1186      509     1205      491

    name BABY
     1351      361     1334      360      492     1180
     1360      360     1335      326     1369      360
      492     1184      511     1207      489     1207
      490     1207     1331      362     1333     7731
     1358      364     1332      363      487     1210
     1329      364     1337      327     1363      362
      490     1209      487     1209      487     1209
      485     1210     1329      363     1331     7761
     1331      363     1331      365      487     1210
     1329      335     1360      365     1330      364
      488     1219      477     1210      486     1209
      487     1186     1352      366     1333     7732
     1356      364     1331      332      527     1183
     1350      365     1331      364     1331      364
      487     1188      509     1210      486     1184
      511     1211     1329      366     1330     7737
     1354      365     1329      366      487     1229
     1313      364     1331      364     1330      365
      487     1209      486     1211      486     1216
      480     1210     1329      366     1330     7722
     1369      364     1330      365      489     1187
     1352      365     1332      364     1330      363
      489     1208      487     1185      511

    name MEDIUM
     1397      362     1334      361      492     1207
     1332      361     1335      360      491     1207
      488     1207      490     1206      492     1204
     1333      359      492     1182      514     7833
     1464      362     1334      357      493     1206
     1332      360     1336      358      493     1206
      490     1206      489     1205      490     1206
     1333      360      491     1206      491     7845
     1456      354     1334      360      492     1207
     1332      361     1334      360      492     1213
      482     1182      514     1213      483     1205
     1331      361      492     1205      489     7903
     1391      361     1335      360      492     1207
     1330      361     1334      361      491     1207
      489     1206      489     1188      506     1207
     1332      360      492     1206      489     7833
     1463      361     1334      360      492     1207
     1332      360     1336      359      491     1207
      489     1206      489     1206      489

    name HIGH
     1348      359     1336      362      491     1206
     1333      360     1336      359      494     1204
      491     1206     1335      356      494     1206
      491     1180      516     1205      491     8492
     1359      352     1335      358      494     1205
     1340      317     1372      360      493     1179
      516     1206     1334      358      494     1205
      491     1204      491     1205      491     8486
     1358      359     1336      359      494     1206
     1332      359     1342      353      494     1204
      490     1206     1333      359      494     1203
      492     1205      490     1206      490     8483
     1363      321     1373      355      494     1206
     1333      358     1338      357      495     1211
      484     1205     1333      357      495     1205
      491     1205      490     1205      491     8485
     1362      357     1335      360      493     1208
     1328      362     1333      361      492     1209
      488     1206     1341      351      495     1205
      490     1205      492     1204      492     8484
     1356      357     1333      364      489     1188
     1354      363     1330      363      489     1185
      511     1209     1330      363      488

  end raw_codes
end remote

After this update, copy this file to the LIRC directory.

sudo cp myfan.lircd.conf /etc/lirc/lircd.conf.d/

Remote controllers have been registered. Open the bootloader for the update.

sudo vim /boot/config.txt

Reactivate the IR sender part by uncommenting the line (line #5-6).

# Uncomment this to enable infrared communication.
#dtoverlay=gpio-ir,gpio_pin=17
#dtoverlay=gpio-ir-tx,gpio_pin=18

dtoverlay=gpio-ir,gpio_pin=18
dtoverlay=gpio-ir-tx,gpio_pin=17

Run sudo reboot to reboot Raspberry PI. Check whether the LIRC module is working or not.

sudo /etc/init.d/lircd status

3.2.4. Controlling my fan on Raspberry Pi

Let's check which commands the remote controller on Raspberry PI have. Enter the following command to see the list of names that I can execute.

irsend LIST myfan ""

OK. Let's run the command.

irsend SEND_ONCE myfan ON_OFF

Although the terminal shows nothing, I actually turn on my fan.

Controlling my fan on Raspberry Pi by python source code

There is a wrapper of irsend command in python (also known as py_irsend), so, I will use it for coding.

  • Install py_irsend:
pip install py_irsend
  • Let's try py_irsend:
python
>>> from py_irsend import irsend
>>> irsend.list_remotes()
>>> irsend.list_codes('myfan')
>>> irsend.send_once('myfan', ['ON_OFF'])

3.2.5. Receiving requests from Azure IoT Hub on Raspberry Pi and controlling my fan

In order to able to receive requests (messages) from Azure IoT Hub, we need to install the azure-iot-device library.

sudo pip3 install azure-iot-device

I wrote a simple source code file in python to process receiving requests from Azure IoT Hub on Raspberry Pi and controlling my fan.

In the source code file, I hardcode a variable CONNECTION_STRING. You can find its value in the end of section 3.2.1. Create Azure IoT Hub at Primary Connection String of lioneldemo-raspberry-pi device.

# receivec2d.py
import time
from azure.iot.device import IoTHubDeviceClient
import myfan

CONNECTION_STRING = "HostName=lioneldemo-iot.azure-devices.net;DeviceId=lioneldemo-raspberry-pi;SharedAccessKey=FyzOwxwsK0wlkgQZpGPQIT2dLUCemi3btmbnzSd3DB8="

def message_handler(message):
    print("Message received:", message.data.decode('utf-8'))
    myfan.exe_cmd(message.data.decode('utf-8'))

def main():
    print ("Starting the Python IoT Hub C2D Messaging device sample...")

    # Instantiate the client
    client = IoTHubDeviceClient.create_from_connection_string(CONNECTION_STRING)

    # print ("Waiting for C2D messages, press Ctrl-C to exit")
    try:
        # Attach the handler to the client
        client.on_message_received = message_handler
        while True:
            selection = input("Press Q to quit\n")
            if selection == "Q" or selection == "q":
                print("Quitting...")
                break
    except KeyboardInterrupt:
        print("IoT Hub C2D Messaging device sample stopped")
    finally:
        # Graceful exit
        print("Shutting down IoT Hub Client")
        client.shutdown()

if __name__ == '__main__':
    main()

To controll my fan, I also imported myfan module. The source code of this module is as below:

# myfan.py
from py_irsend import irsend

DEVICE_KEY = "myfan"
CMD_LIST =  ["ON_OFF", "TIME", "UP", "DOWN", "SWING", "BABY", "MEDIUM", "HIGH"]

def exe_cmd(cmd_str = ""):
    if cmd_str == None:
        return
    cmd_str = cmd_str.upper()
    if cmd_str in CMD_LIST:
        irsend.send_once(DEVICE_KEY, [cmd_str])
  • Execute this source code file on Raspberry Pi
python receivec2d.py

3.2.5. Sending requests from Azure IoT Hub to Raspberry Pi

In order to control my fan over the internet, I need a simple Web UI where show command buttons to control as below.

So, I am going to use the Azure Function App with HttpTrigger type to implement that requirement.

Create Azure Function App in Azure Portal (e.g., lioneldemo-iot-func)

Create HttpTrigger function (e.g., IoTHttpTrigger)

  • Detail source code of the function is as below:
# __init__.py
import logging
import azure.functions as func
from azure.iot.hub import IoTHubRegistryManager

CONNECTION_STRING = "HostName=lioneldemo-iot.azure-devices.net;SharedAccessKeyName=device;SharedAccessKey=3CBwHsZyeHGtVIV8/KkqZosrqN4LfLfeKI+6jCok/Ss="
DEVICE_ID = "lioneldemo-raspberry-pi"

# Send a message (command) from cloud to device (C2D)
def send_cmd(cmd_str = ""):
    try:
        # Create IoTHubRegistryManager
        registry_manager = IoTHubRegistryManager(CONNECTION_STRING)
        data = cmd_str
        props={}
        registry_manager.send_c2d_message(DEVICE_ID, data, properties=props)
    except Exception as ex:
        print ( "Unexpected error {0}" % ex )
        return
    except KeyboardInterrupt:
        print ( "IoT Hub C2D Messaging service sample stopped" )

# Create UI (html source code) for client to control a device (fan)
def body_html():
    title = '<h1>[IoT] FAN REMOTE CONTROL BOARD</h1>'

    # Create CSS for button
    css = '<style>'\
        '.button {'\
        '  background-color: #008CBA;'\
        '  border: none;'\
        '  color: white;'\
        '  padding: 15px 32px;'\
        '  text-align: center;'\
        '  text-decoration: none;'\
        '  display: inline-block;'\
        '  margin: 4px 2px;'\
        '  cursor: pointer;'\
        '}'\
        '.button_size {font-size: 30px; width: 500px}'\
        '</style>'

    # Set content with CSS and Title
    content = css + title

    # A fan control button list
    CMD_LIST =  ["ON_OFF", "TIME", "UP", "DOWN", "SWING", "BABY", "MEDIUM", "HIGH"]

    # Set content with html buttons for each command above and return the content.
    count = 0
    for cmd in CMD_LIST:
        count += 1
        content  += f'<button type="button" class="button button_size" onclick="document.location = \'IoTHttpTrigger?cmd={cmd}\'">{cmd}</button>&nbsp;&nbsp;'
        # Create a new line of buttons when a row had 2 buttons
        if count == 2:
            count = 0
            content += '<br/><br/>'
    return content

def main(req: func.HttpRequest) -> func.HttpResponse:
    logging.info('Python HTTP trigger function processed a request.')

    cmd = req.params.get('cmd')
    if not cmd:
        try:
            req_body = req.get_json()
        except ValueError:
            pass
        else:
            cmd = req_body.get('cmd')

    content = body_html()

    # If there is a command is set, we will execute the command and update UI with the command is executed
    if cmd:
        text = f"<h3> Executed command: <strong>{cmd}</strong></h3>"
        content += f"<p>{text}</p>"
        send_cmd(cmd)

    # Return the html page
    return func.HttpResponse(
        body=content,
        status_code=200,
        headers=None,
        mimetype='html'
    )

In the source code file above, I hardcode a variable CONNECTION_STRING for IoT Hub. You can find its value by following the guide. See more detail here.

We also need to add azure-iot-hub library to \app\requirements.txt file to support sending a command (message) from cloud to device.

Now, I deploy the Azure function IoTHttpTrigger to Azure cloud, then I can control my fan over the internet by using a browser on PC or Smartphone.

Demo Video
[IoT] FAN REMOTE CONTROL BOARD

4. Summary

With the use of Azure IoT services, you can implement IoT applications more easily, quickly, and conveniently.

The Demo above is just a simple application to help beginners understand the basics of how the link of works between IoT devices and Azure IoT services.

5. References

  1. Azure IoT documentation
  2. AZ-900 Episode 14 | Azure IoT Services | IoT Hub, IoT Central, Azure Sphere
  3. Get started with device development on Azure IoT

Thank you!