# Raspberry Pi Azure IoT Hub Dashboard with CircuitPython

## Overview

![](https://cdn-learn.adafruit.com/assets/assets/000/114/386/medium800/temperature___humidity_edited_P1380683.jpg?1660851506)

https://youtube.com/shorts/NQb0DeUhcjg

In this project, you'll visualize all of your Azure IoT Hub devices' telemetry data on a Raspberry Pi-powered display. The Raspberry Pi runs Python code combining [Azure's Python SDK](https://aka.ms/adafruit/tutorial3/AzurePythonSDK) and [Blinka](https://learn.adafruit.com/circuitpython-on-raspberrypi-linux/circuitpython-raspi), the CircuitPython compatibility library for single-board computers running Linux. The code shows three different ways to retrieve data from IoT Hub with Python: a built-in endpoint, the Azure REST API and an Azure Device Twin.

IoT Hub is one of the two IoT options from Azure. It allows for two-way communication, which makes this project possible. It can be more complicated to setup and configure than IoT Central, but this guide will walk you through everything you need to get up and running.

The Raspberry Pi dashboard uses the [Blinka\_Displayio\_PyGameDisplay](https://github.com/FoamyGuy/Blinka_Displayio_PyGameDisplay) library to utilize **displayio** elements over HDMI rather than a discrete display over I2C or SPI.

![temperature___humidity_piFullScreen.jpg](https://cdn-learn.adafruit.com/assets/assets/000/114/355/medium640/temperature___humidity_piFullScreen.jpg?1660769583)

The dashboard updates every time a device sends telemetry data to IoT Hub. It also logs the last device to check-in with a timestamp so you always know the connection status of your devices.

![temperature___humidity_deviceChange.gif](https://cdn-learn.adafruit.com/assets/assets/000/114/397/medium640thumb/temperature___humidity_deviceChange.jpg?1660852874)

By using a dashboard, you have a centralized place where you can easily visualize your various devices' status at a glance. That way you can place your devices exactly where you want them around your space.

![temperature___humidity_edited_P1380717.jpg](https://cdn-learn.adafruit.com/assets/assets/000/114/387/medium640/temperature___humidity_edited_P1380717.jpg?1660851555)

## Prerequisite Guides
[Getting Started with Microsoft Azure and CircuitPython](https://learn.adafruit.com/getting-started-with-microsoft-azure-and-circuitpython/overview)
[CircuitPython Libraries on Linux and Raspberry Pi](https://learn.adafruit.com/circuitpython-on-raspberrypi-linux/overview)
[Adafruit ESP32-S2 TFT Feather](https://learn.adafruit.com/adafruit-esp32-s2-tft-feather)
[Adafruit QT Py ESP32-S2](https://learn.adafruit.com/adafruit-qt-py-esp32-s2)
[Adafruit SCD-40 and SCD-41](https://learn.adafruit.com/adafruit-scd-40-and-scd-41)
[Adafruit BME680](https://learn.adafruit.com/adafruit-bme680-humidity-temperature-barometic-pressure-voc-gas)
## Parts
### Raspberry Pi 4 Model B - 4 GB RAM

[Raspberry Pi 4 Model B - 4 GB RAM](https://www.adafruit.com/product/4296)
The Raspberry Pi 4 Model B is the newest Raspberry Pi computer made, and the Pi Foundation knows you can always make a good thing _better_! And what could make the Pi 4 better than the 3? How about a&nbsp;_faster_ processor, USB 3.0 ports, and updated Gigabit Ethernet chip with...

In Stock
[Buy Now](https://www.adafruit.com/product/4296)
[Related Guides to the Product](https://learn.adafruit.com/products/4296/guides)
![Angled shot of Raspberry Pi 4](https://cdn-shop.adafruit.com/640x480/4296-11.jpg)

### Adafruit ESP32-S2 TFT Feather - 4MB Flash, 2MB PSRAM, STEMMA QT

[Adafruit ESP32-S2 TFT Feather - 4MB Flash, 2MB PSRAM, STEMMA QT](https://www.adafruit.com/product/5300)
We've got a new machine here at Adafruit, it can uncover your deepest desires. Don't believe me? I'll turn it on right now to prove it to you! What, you want unlimited mozzarella sticks? OK well, that's not something we can provide. But we can provide your...

Out of Stock
[Buy Now](https://www.adafruit.com/product/5300)
[Related Guides to the Product](https://learn.adafruit.com/products/5300/guides)
![Adafruit ESP32-S2 TFT Feather powered on by a USB- C power source displaying the product tittle in a red, yellow, green, white and blue. ](https://cdn-shop.adafruit.com/640x480/5300-06.jpg)

### Adafruit QT Py ESP32-S2 WiFi Dev Board with STEMMA QT

[Adafruit QT Py ESP32-S2 WiFi Dev Board with STEMMA QT](https://www.adafruit.com/product/5325)
What has your favorite Espressif WiFi microcontroller, comes with&nbsp;[our favorite connector - the STEMMA QT](http://adafruit.com/stemma), a chainable I2C port, and has lots of Flash and RAM memory for your next IoT project? What will make your next IoT project flyyyyy? What a...

Out of Stock
[Buy Now](https://www.adafruit.com/product/5325)
[Related Guides to the Product](https://learn.adafruit.com/products/5325/guides)
![Angled shot of small square purple dev board.](https://cdn-shop.adafruit.com/640x480/5325-12.jpg)

### Adafruit SCD-40 - True CO2, Temperature and Humidity Sensor

[Adafruit SCD-40 - True CO2, Temperature and Humidity Sensor](https://www.adafruit.com/product/5187)
Take a deep breath in...now slowly breathe out. Mmm isn't it wonderful? All that air around us, which we bring into our lungs, extracts oxygen from and then breathes out carbon dioxide. CO2 is essential for life on this planet we call Earth - we and plants&nbsp;take turns using and...

Out of Stock
[Buy Now](https://www.adafruit.com/product/5187)
[Related Guides to the Product](https://learn.adafruit.com/products/5187/guides)
![Angled shot of Adafruit SCD-40 - NDIR CO2 Temperature and Humidity Sensor.](https://cdn-shop.adafruit.com/640x480/5187-08.jpg)

### Adafruit BME688 - Temperature, Humidity, Pressure and Gas Sensor

[Adafruit BME688 - Temperature, Humidity, Pressure and Gas Sensor](https://www.adafruit.com/product/5046)
The long-awaited BME688 from Bosch gives you&nbsp;_all the environmental sensing you want_&nbsp;in one small package. This little sensor contains&nbsp; **temperature** ,&nbsp; **humidity** ,&nbsp; **barometric pressure,** &nbsp;and&nbsp; **VOC...**

In Stock
[Buy Now](https://www.adafruit.com/product/5046)
[Related Guides to the Product](https://learn.adafruit.com/products/5046/guides)
![Angled shot of BME688 sensor breakout.](https://cdn-shop.adafruit.com/640x480/5046-05.jpg)

### STEMMA QT / Qwiic JST SH 4-Pin Cable - 50mm Long

[STEMMA QT / Qwiic JST SH 4-Pin Cable - 50mm Long](https://www.adafruit.com/product/4399)
This 4-wire cable is&nbsp;50mm / 1.9" long and fitted with JST SH female 4-pin connectors on both ends. Compared with the chunkier JST PH these are 1mm pitch instead of 2mm, but still have a nice latching feel, while being easy to insert and remove.

<a...></a...>

Out of Stock
[Buy Now](https://www.adafruit.com/product/4399)
[Related Guides to the Product](https://learn.adafruit.com/products/4399/guides)
![Angled of of JST SH 4-Pin Cable.](https://cdn-shop.adafruit.com/640x480/4399-00.jpg)

### Part: Lithium Ion Polymer Battery - 3.7v 2500mAh
quantity: 1
2500mAh battery
[Lithium Ion Polymer Battery - 3.7v 2500mAh](https://www.adafruit.com/product/328)

### Part: Official Raspberry Pi Power Supply 5.1V 3A with USB C
quantity: 1
USB C power supply
[Official Raspberry Pi Power Supply 5.1V 3A with USB C](https://www.adafruit.com/product/4298)

### Part: Official Raspberry Pi Micro HDMI to HDMI Cable - 1 meter long
quantity: 1
Micro HDMI to HDMI Cable
[Official Raspberry Pi Micro HDMI to HDMI Cable - 1 meter long](https://www.adafruit.com/product/4302)

### Part: Pink and Purple Woven USB A to USB C Cable - 1 meter long
quantity: 1
USB A to USB C cable
[Pink and Purple Woven USB A to USB C Cable - 1 meter long](https://www.adafruit.com/product/5153)

# Raspberry Pi Azure IoT Hub Dashboard with CircuitPython

## Create a Microsoft Azure Account

Before you can get started with Microsoft Azure, you need to create an account. There are multiple tiers of accounts, including a free version.&nbsp;

Go to the [Microsoft Azure website](https://aka.ms/adafruit/tutorial3/AzureSignup) and click on Try Azure for Free.

![temperature___humidity_freeAccount.png](https://cdn-learn.adafruit.com/assets/assets/000/112/187/medium640/temperature___humidity_freeAccount.png?1654115181)

Click on Start Free to proceed in creating a free account.

![temperature___humidity_startFree.png](https://cdn-learn.adafruit.com/assets/assets/000/112/188/medium640/temperature___humidity_startFree.png?1654115270)

You can create a new account, sign-in with your Microsoft account or sign-in with your GitHub account.

![temperature___humidity_InkeduseMicrosoftAccount_LI.jpg](https://cdn-learn.adafruit.com/assets/assets/000/112/190/medium640/temperature___humidity_InkeduseMicrosoftAccount_LI.jpg?1654115351)

![temperature___humidity_signInOptions.png](https://cdn-learn.adafruit.com/assets/assets/000/112/191/medium640/temperature___humidity_signInOptions.png?1654115366)

After signing in, you'll be prompted to enter your information.

![temperature___humidity_createAccount.png](https://cdn-learn.adafruit.com/assets/assets/000/112/192/medium640/temperature___humidity_createAccount.png?1654115425)

Even with the free account, you do need to enter a payment method. Nothing is charged unless you change settings later.

![temperature___humidity_enterCard.png](https://cdn-learn.adafruit.com/assets/assets/000/112/193/medium640/temperature___humidity_enterCard.png?1654115453)

After entering all of your information, your Azure account setup will be complete. You can navigate to the Azure portal to get started with creating an application.

![temperature___humidity_setupComplete.png](https://cdn-learn.adafruit.com/assets/assets/000/112/194/medium640/temperature___humidity_setupComplete.png?1654115529)

# Raspberry Pi Azure IoT Hub Dashboard with CircuitPython

## Create an IoT Hub

![](https://cdn-learn.adafruit.com/assets/assets/000/114/305/medium800/temperature___humidity_iotHubDataHero.jpg?1660749094)

Navigate to your Azure portal at [portal.azure.com](portal.azure.com). In the search bar, search for **"IoT Hub"**. On the IoT Hub page, click **+ Create**.

![temperature___humidity_createHub.jpg](https://cdn-learn.adafruit.com/assets/assets/000/114/296/medium640/temperature___humidity_createHub.jpg?1660747614)

On the IoT Hub setup page, **select your subscription and resource group** from the dropdown menu. Then, name your new IoT Hub in the **IoT Hub name** box.

![temperature___humidity_newHub1.jpg](https://cdn-learn.adafruit.com/assets/assets/000/114/297/medium640/temperature___humidity_newHub1.jpg?1660747744)

Under Management, **select your pricing tier**. There are a variety of tiers with various features. There is also a free tier (F1) with basic features.

![temperature___humidity_newHub2.jpg](https://cdn-learn.adafruit.com/assets/assets/000/114/298/medium640/temperature___humidity_newHub2.jpg?1660747877)

Then, click the **Review + create tab**. This will validate your new IoT Hub's settings. Once your IoT Hub is validated, you can click the blue **Create button** to finish setup.

![temperature___humidity_newHub3.jpg](https://cdn-learn.adafruit.com/assets/assets/000/114/299/medium640/temperature___humidity_newHub3.jpg?1660748008)

![temperature___humidity_newHub4.jpg](https://cdn-learn.adafruit.com/assets/assets/000/114/300/medium640/temperature___humidity_newHub4.jpg?1660748020)

After creating your IoT Hub, it will appear on the IoT Hub default directory homepage. You can **click your IoT Hub's name** to go to its overview page.

![temperature___humidity_newHub5.jpg](https://cdn-learn.adafruit.com/assets/assets/000/114/301/medium640/temperature___humidity_newHub5.jpg?1660748260)

On the overview page, you can view basic IoT Hub information, like your Subscription ID, and general usage data, such as the number of messages that have been sent.

![temperature___humidity_newHub6.jpg](https://cdn-learn.adafruit.com/assets/assets/000/114/302/medium640/temperature___humidity_newHub6.jpg?1660748886)

![temperature___humidity_newHub7.jpg](https://cdn-learn.adafruit.com/assets/assets/000/114/306/medium640/temperature___humidity_newHub7.jpg?1660749133)

# Raspberry Pi Azure IoT Hub Dashboard with CircuitPython

## Add IoT Hub Devices

On your IoT Hub's page, select **Devices** under Device management. Then click **+ Add Device** to begin adding a new device to your IoT Hub.

![temperature___humidity_devices1.jpg](https://cdn-learn.adafruit.com/assets/assets/000/114/307/medium640/temperature___humidity_devices1.jpg?1660749667)

Enter your device's name into the **Device ID field**. Then, click **Save** to create your device. Your device will show-up in the Device ID list on the Devices page.

![temperature___humidity_devices2.jpg](https://cdn-learn.adafruit.com/assets/assets/000/114/308/medium640/temperature___humidity_devices2.jpg?1660749898)

![temperature___humidity_devices3.jpg](https://cdn-learn.adafruit.com/assets/assets/000/114/309/medium640/temperature___humidity_devices3.jpg?1660750084)

If you click on your **device's name** , you'll be brought to that device's page. There you can access its security keys and manage settings. The **Primary Connection String** is used by the CircuitPython IoT Hub library to connect to Azure.

![temperature___humidity_devices4.jpg](https://cdn-learn.adafruit.com/assets/assets/000/114/310/medium640/temperature___humidity_devices4.jpg?1660750221)

# Raspberry Pi Azure IoT Hub Dashboard with CircuitPython

## Setup the IoT Hub Devices with CircuitPython

![](https://cdn-learn.adafruit.com/assets/assets/000/114/391/medium800/temperature___humidity_edited_P1380666.jpg?1660851716)

For this project, there are two example devices that you can build to send data to your IoT hub. The first is based on the project for the [Getting Started with Microsoft Azure and CircuitPython guide](https://learn.adafruit.com/getting-started-with-microsoft-azure-and-circuitpython). It uses a ESP32-S2 TFT Feather with a STEMMA BME688 sensor to monitor ambient temperature, humidity and air pressure data. The only difference in the code is that instead of it being an IoT Central device, it is setup as an IoT Hub device.

The second device is a QT Py ESP32-S2 with a STEMMA SCD40 sensor for monitoring CO2 data.

The Raspberry Pi display is setup to show two instances of the environment monitor and one instance of the CO2 monitor.

![temperature___humidity_piFullScreen.jpg](https://cdn-learn.adafruit.com/assets/assets/000/114/311/medium640/temperature___humidity_piFullScreen.jpg?1660751360)

# Raspberry Pi Azure IoT Hub Dashboard with CircuitPython

## ESP32-S2 TFT Feather Environment Monitor Setup

## Wiring the ESP32-S2 TFT Feather Environment Monitor
Use a STEMMA QT cable to connect a STEMMA BME688 board to the ESP32-S2 TFT Feather.

![temperature___humidity_featherTFTBME680_bb.png](https://cdn-learn.adafruit.com/assets/assets/000/114/398/medium640/temperature___humidity_featherTFTBME680_bb.png?1660853235)

## 3D Printed Mount

You can refer to the [3D Printing page](https://learn.adafruit.com/getting-started-with-microsoft-azure-and-circuitpython/3d-printing) in the Getting Started with Microsoft Azure and CircuitPython guide to print a mount for the Feather and BME688.

## Coding the ESP32-S2 TFT Feather Environment Monitor
First, [setup your Feather ESP32-S2 TFT with CircuitPython](https://learn.adafruit.com/getting-started-with-microsoft-azure-and-circuitpython/circuitpython). Then, you can access the code and necessary libraries by downloading the Project Bundle.

To do this, click on the **&nbsp;Download Project Bundle** &nbsp;button in the window below. It will download as a zipped folder.

https://github.com/adafruit/Adafruit_Learning_System_Guides/blob/main/Raspberry_Pi_Azure_IoT_Hub_Dashboard/featherTft_bme680/code.py

## Upload the Code and Libraries to the ESP32-S2 TFT Feather

After downloading the Project Bundle, plug your ESP32-S2 TFT Feather into the computer's USB port with a known good USB data+power cable. You should see a new flash drive appear in the computer's File Explorer or Finder (depending on your operating system) called&nbsp; **CIRCUITPY**. Unzip the folder and copy the following items to the ESP32-S2 TFT Feather's&nbsp; **CIRCUITPY** &nbsp;drive.&nbsp;

- **lib** &nbsp;folder
- **roundedHeavy-26.bdf**
- **bmeTFT.bmp**
- **code.py**

Your ESP32-S2 TFT Feather&nbsp; **CIRCUITPY&nbsp;** drive should look like this after copying the&nbsp; **lib** &nbsp;folder, the&nbsp; **bmeTFT.bmp** &nbsp;image file, the&nbsp; **roundedHeavy-26.bdf** &nbsp;bitmap font file, and the&nbsp; **code.py&nbsp;** file.

![CIRCUITPY](https://adafruit.github.io/Adafruit_Learning_System_Guides/Raspberry_Pi_Azure_IoT_Hub_Dashboard_featherTft_bme680.png )

## **settings.toml**

You will need to create and add a **settings.toml** file to your&nbsp; **CIRCUITPY** &nbsp;drive. Your **settings.toml** file will need to include the following information:

```python
CIRCUITPY_WIFI_SSID="your-wifi-ssid"
CIRCUITPY_WIFI_PASSWORD="your-wifi-password"
device_connection_string="YOUR-DEVICE-CONNECTION-STRING-HERE"
```

You'll locate your **Primary Connection String** from your devices page in your IoT Hub. Make sure to refer to the&nbsp;[Add IoT Hub Devices](https://learn.adafruit.com/raspberry-pi-iot-dashboard-with-azure-and-circuitpython/add-iot-hub-devices?#step-3124428) page in this guide to see the process for accessing the Primary Connection String.

# Raspberry Pi Azure IoT Hub Dashboard with CircuitPython

## QT Py ESP32-S2 CO2 Monitor Setup

## Wiring the QT Py ESP32-S2 CO2 Monitor
Use a STEMMA QT cable to connect a STEMMA SCD40 board to the QT Py ESP32-S2.

![temperature___humidity_qtPySCD_bb.png](https://cdn-learn.adafruit.com/assets/assets/000/114/399/medium640/temperature___humidity_qtPySCD_bb.png?1660853263)

## 3D Printed Case

You can refer to the [3D Printing page](https://learn.adafruit.com/disconnected-co2-data-logger/3d-printing) in the [Disconnected CO2 Data Logger guide](https://learn.adafruit.com/disconnected-co2-data-logger/overview) to print a case with mounting holes for the SCD40.

## Coding the QT Py ESP32-S2 CO2 Monitor

First, [setup your QT Py ESP32-S2 with CircuitPython](https://learn.adafruit.com/adafruit-qt-py-esp32-s2/circuitpython). Then, you can access the code and necessary libraries by downloading the Project Bundle.

To do this, click on the **&nbsp;Download Project Bundle** &nbsp;button in the window below. It will download as a zipped folder.

https://github.com/adafruit/Adafruit_Learning_System_Guides/blob/main/Raspberry_Pi_Azure_IoT_Hub_Dashboard/qtPyEsp32S2_co2/code.py

## Upload the Code and Libraries to the QT Py ESP32-S2

After downloading the Project Bundle, plug your QT Py ESP32-S2 into the computer's USB port with a known good USB data+power cable. You should see a new flash drive appear in the computer's File Explorer or Finder (depending on your operating system) called&nbsp; **CIRCUITPY**. Unzip the folder and copy the following items to the QT Py ESP32-S2's&nbsp; **CIRCUITPY** &nbsp;drive.&nbsp;

- **lib** &nbsp;folder
- **code.py**

Your QT Py ESP32-S2&nbsp; **CIRCUITPY&nbsp;** drive should look like this after copying the&nbsp; **lib** &nbsp;folder and the&nbsp; **code.py&nbsp;** file.

![CIRCUITPY](https://adafruit.github.io/Adafruit_Learning_System_Guides/Raspberry_Pi_Azure_IoT_Hub_Dashboard_qtPyEsp32S2_co2.png )

## **settings.toml**

You will need to create and add a **settings.toml** file to your&nbsp; **CIRCUITPY** &nbsp;drive. Your **settings.toml** file will need to include the following information:

```python
CIRCUITPY_WIFI_SSID="your-wifi-ssid"
CIRCUITPY_WIFI_PASSWORD="your-wifi-password"
device_connection_string="YOUR-DEVICE-CONNECTION-STRING-HERE"
```

You'll locate your **Primary Connection String** from your devices page in your IoT Hub. Make sure to refer to the&nbsp;[Add IoT Hub Devices](https://learn.adafruit.com/raspberry-pi-iot-dashboard-with-azure-and-circuitpython/add-iot-hub-devices?#step-3124428) page in this guide to see the process for accessing the Primary Connection String.

# Raspberry Pi Azure IoT Hub Dashboard with CircuitPython

## Prepare Your Raspberry Pi

![](https://cdn-learn.adafruit.com/assets/assets/000/114/390/medium800/temperature___humidity_edited_P1380663.jpg?1660851655)

First, install the latest version of Raspberry Pi OS onto an SD card. You can refer to the&nbsp;[CircuitPython Libraries on Linux and Raspberry Pi](https://learn.adafruit.com/circuitpython-on-raspberrypi-linux/installing-circuitpython-on-raspberry-pi)&nbsp;guide for more help setting it up.

Once you have everything set up, you will need to open a terminal and install Blinka. Refer to the&nbsp;[Installing CircuitPython Libraries on Raspberry Pi](https://learn.adafruit.com/circuitpython-on-raspberrypi-linux/installing-circuitpython-on-raspberry-pi)&nbsp;page to quickly get up and running.

## Install Azure CLI
[Azure CLI](https://docs.microsoft.com/en-us/cli/azure/install-azure-cli-linux?pivots=apt) is a command line tool that you can use on Linux computers, like the Raspberry Pi, to access various Azure functions and information. In this instance, you'll use Azure CLI to generate a Bearer token to authenticate while making an HTTP request in the **code.py** file.

To install Azure CLI, open a terminal window and enter the following command:

```terminal
sudo apt-get install azure-cli
```

This will run through the Azure CLI installation process. After installation finishes, log into your Azure account with:

```terminal
az login
```

This opens a browser and prompts you to log into your Microsoft Azure account.

![temperature___humidity_logIntoAzure.jpg](https://cdn-learn.adafruit.com/assets/assets/000/114/312/medium640/temperature___humidity_logIntoAzure.jpg?1660753832)

After logging in, the browser will let you know that the login was successful and then navigate to the Azure CLI documentation page.

![temperature___humidity_successfulLogin.jpg](https://cdn-learn.adafruit.com/assets/assets/000/114/313/medium640/temperature___humidity_successfulLogin.jpg?1660753870)

![temperature___humidity_azureCLIdocumentation.jpg](https://cdn-learn.adafruit.com/assets/assets/000/114/314/medium640/temperature___humidity_azureCLIdocumentation.jpg?1660753887)

In the terminal, you'll see a printout of your Azure subscription information. This information is sensitive so you may want to close out of the terminal after viewing.

![temperature___humidity_azureCLIprintout.jpg](https://cdn-learn.adafruit.com/assets/assets/000/114/315/medium640/temperature___humidity_azureCLIprintout.jpg?1660753999)

## Hide the Taskbar
To allow the dashboard display window to take up the full Raspberry Pi display, you'll want to hide the top taskbar when it isn't in use.

**Right-click** on the taskbar and **select Panel Preferences**. In the Panel Preferences window, go to the **Advanced tab** and **check off "Minimize panel when not in use"**. Then, **click Close**.

![temperature___humidity_minimizePanel.jpg](https://cdn-learn.adafruit.com/assets/assets/000/114/316/medium640/temperature___humidity_minimizePanel.jpg?1660754259)

# Raspberry Pi Azure IoT Hub Dashboard with CircuitPython

## Code the Raspberry Pi IoT Dashboard

## Install the Required Libraries

You will need to have a few libraries installed before the script will run on your Raspberry Pi.

Install the required CircuitPython libraries with the terminal:

```terminal
pip3 install adafruit-circuitpython-bitmap-font
pip3 install adafruit-circuitpython-display-shapes
pip3 install adafruit-circuitpython-display-text
pip3 install adafruit-circuitpython-imageload
pip3 install adafruit-blinka-displayio
pip3 install blinka-displayio-pygamedisplay
```

Then, install the required Python libraries with the terminal:

```terminal
pip3 install subprocess
pip3 install datetime
pip3 install pygame
pip3 install recordclass
pip3 install requests
```

Finally, install the required Azure IoT Python libraries with the terminal:

```terminal
pip3 install azure-iot-hub
pip3 install azure-event-hub
```

## Download the Code, Image and Font Files

Once you've finished setting up your Raspberry Pi with Blinka and the library dependencies, you can access the Python code, bitmap image file and two font files by downloading the Project Bundle.

To do this, click on the **&nbsp;Download Project Bundle** &nbsp;button in the window below. It will download as a zipped folder.

https://github.com/adafruit/Adafruit_Learning_System_Guides/blob/main/Raspberry_Pi_Azure_IoT_Hub_Dashboard/azure_pi/code.py

After downloading the Project Bundle, move the folder to your **/home/pi** directory. Then, unzip the folder. Your Raspberry Pi should have the following files in the **/home/pi/**** azure\_pi**&nbsp;folder:

- **code.py**
- **piBG\_0.bmp**
- **OstrichSans-Heavy-88.bdf**
- **OstrichSans-Heavy-60.bdf**

![temperature___humidity_azurePiFolder.jpg](https://cdn-learn.adafruit.com/assets/assets/000/114/317/medium640/temperature___humidity_azurePiFolder.jpg?1660755142)

## Add Your IoT Hub Information

At the top of the **code.py** file, you'll see six variables that need to be updated with your IoT hub information.

```auto
#  UPDATE THESE VARIABLES WITH YOUR IOT HUB INFORMATION

#  event hub compatible end point from the built-in endpoints page
event_connection = "YOUR-EVENT-HUB-CONNECTION-STRING-HERE"
#  Primary Connection String with registry read and service connect rights
#  managed on shared access polices page
status_connection = "YOUR-STATUS-CONNECTION-STRING-HERE"

#  iot hub subscription ID
#  found on the overview of your iot hub
#  format: ########-####-####-############
subscription_id = "YOUR-SUBSCRIPTION-ID-HERE"

#  device id's (device names in iot hub)
qt_py = "YOUR-QT-PY-DEVICE-HERE"
tft_feather = "YOUR-TFT-FEATHER-DEVICE-HERE"
s3_feather = "YOUR-S3-FEATHER-DEVICE-HERE"
```

`event_connection` is your Event Hub compatible endpoint. It is located on the Built-in endpoints page of your IoT Hub.

![temperature___humidity_builtInEndpoint.jpg](https://cdn-learn.adafruit.com/assets/assets/000/114/323/medium640/temperature___humidity_builtInEndpoint.jpg?1660756087)

`status_connection` is the Primary connection string from a Shared Access Policy (SAP) that has Registry Read and Service Connect permissions.

You can setup this SAP by going to the **Shared access policies page** of your IoT Hub and then clicking on **+ Add shared access policy**. Then, name the SAP in the **Access policy name box** and check off **Registry Read** and **Service Connect**. Click **Add** to create the SAP.

You access the Primary connection string by **clicking on the SAP's name** to view the security keys. Then, copy and paste the **Primary connection string** into the **code.py** file as `status_connection`.

![temperature___humidity_addSAP.jpg](https://cdn-learn.adafruit.com/assets/assets/000/114/325/medium640/temperature___humidity_addSAP.jpg?1660756543)

![temperature___humidity_addSAP1.jpg](https://cdn-learn.adafruit.com/assets/assets/000/114/326/medium640/temperature___humidity_addSAP1.jpg?1660756561)

![temperature___humidity_SAPkeys.jpg](https://cdn-learn.adafruit.com/assets/assets/000/114/327/medium640/temperature___humidity_SAPkeys.jpg?1660756573)

`subscription_id` is located at the top of your IoT Hub's Overview page.

![temperature___humidity_newHub6.jpg](https://cdn-learn.adafruit.com/assets/assets/000/114/328/medium640/temperature___humidity_newHub6.jpg?1660756635)

Finally, your Device IDs are the plain text names of your devices setup in your IoT hub. These can be found on the Devices page in your IoT hub.

![temperature___humidity_devices3.jpg](https://cdn-learn.adafruit.com/assets/assets/000/114/329/medium640/temperature___humidity_devices3.jpg?1660756682)

## How the Code Works

The [Blinka\_Displayio\_PyGameDisplay](https://github.com/FoamyGuy/Blinka_Displayio_PyGameDisplay) library lets you use CircuitPython `displayio` elements over HDMI on the Raspberry Pi's main display. There are text elements that update with the incoming device telemetry from IoT Hub.

```python
#  living room data
lr_temp = label.Label(font, text = "72°F", color = 0xFFFFFF, x = 90, y = 424)
lr_humid = label.Label(font, text = "52%", color = 0xFFFFFF, x = 405, y = 424)
lr_press = label.Label(font, text = "1005", color = 0xFFFFFF, x = 715, y = 424)

...

#  if the device is the tft feather
if string_device == tft_feather:
    #  update living room sensor text
    lr_temp.text = "%s°F" % str(telemetry['Temperature'])
    lr_humid.text = "%s%%" % str(telemetry['Humidity'])
    lr_press.text = str(telemetry['Pressure'])
```

The code is accessing your IoT Hub information with three different methods: built-in endpoints, Azure REST API and device twin. The following pages will detail how each of these methods are being used.

# Raspberry Pi Azure IoT Hub Dashboard with CircuitPython

## Using the IoT Hub's Built-in Endpoint

Each IoT Hub has a built-in endpoint to receive incoming data. By default, all device telemetry is received via this endpoint and it can be accessed by Azure's Event Hub library. This is the method being used in **code.py** to get the devices' incoming telemetry from their sensors.

`client` is created as an `EventHubConsumerClient` with the `event_connection` Event Hub Compatible endpoint.

```python
#  connect to event hub
client = EventHubConsumerClient.from_connection_string(
    conn_str = event_connection,
    consumer_group = "$default",
)
```

In the loop, `receive_batch()` is called, which listens to incoming events.

```python
try:
        #  recieve incoming events
        client.receive_batch(
            on_event_batch = on_event_batch,
            on_error = on_error
        )
```

The `on_event_batch()` function iterates through the incoming events. From this incoming feed, the code gets the timestamp with `event.enqueued_time` and encodes the feed as a JSON to grab the device name from the `event`.

A series of `if` statements checks to see which device is sending telemetry data in the `event` and updates the text objects with the telemetry data.

```python
#  iterates through incoming events
    for event in events:
        #  gets timestamp for event
        clock = utc_to_local(event.enqueued_time)
        
        ...
        
        #  gets the incoming event as a JSON feed
        telemetry = event.body_as_json()
        #  grabs the device ID from the JSON
        device = event.system_properties[b'iothub-connection-device-id']
        #  converts the device ID to a string
        string_device = device.decode("utf-8")
        #  updates last device text
        lastDevice_text.text = string_device
        #  if the device is the qt_py
        if string_device == qt_py:
            #  update co2 text
            co2_text.text = str(telemetry['CO2'])
        #  if the device is the tft feather
        if string_device == tft_feather:
            #  update living room sensor text
            lr_temp.text = "%s°F" % str(telemetry['Temperature'])
            lr_humid.text = "%s%%" % str(telemetry['Humidity'])
            lr_press.text = str(telemetry['Pressure'])
        #  if the device is the s3 feather
        if string_device == s3_feather:
            #  update bedroom sensor text
            bd_temp.text = "%s°F" % str(telemetry['Temperature'])
            bd_humid.text = "%s%%" % str(telemetry['Humidity'])
            bd_press.text = str(telemetry['Pressure'])
```

# Raspberry Pi Azure IoT Hub Dashboard with CircuitPython

## Using the Azure REST API

The [Azure REST API](https://aka.ms/adafruit/tutorial3/azureRestAPI) allows you to use the Python `requests` library to get information from IoT Hub in the form of an HTTP request. An HTTP request is the source of the total cost information for the dashboard.

## Bearer Token

To make a GET HTTP request using the Azure REST API, you need a Bearer token to be included in the header for the request. The Bearer token is only viable for one hour. In order to always be sure you have a valid token,&nbsp;the [Azure CLI](https://aka.ms/adafruit/tutorial3/AzureCLI) is run using the `Popen()` function from the `subprocess` Python library.

The `subprocess` library allows for terminal commands to be run in the background. The output from the terminal can be brought into the Python script. In this case, `az account get-access-token` is run and its output is converted to a JSON feed. The `'accessToken'` JSON item contains the Bearer token and is added to `headers`.

```python
output = Popen(['az', 'account', 'get-access-token'], stdout=PIPE)
#  parses the output into a json and grabs the bearer token
bear = json.loads(output.communicate()[0].decode('utf-8').strip())
#  creates headers to include with GET HTTP request for cost data
headers = {'Authorization': 'Bearer ' + bear['accessToken'], 'Content-Type': 'application/json'}
```

The URL request needs your subscription ID added to it. This is accomplished using `.format()` and inserting `{}` in the required location of the URL for the subscription ID. The `url` and `headers` are packed into a `requests.get()` function that is returned as a JSON feed with `response.json()`. `cost` holds the `'costInBillingCurrency'` JSON item that has the daily cost for your cloud services.

```auto
#  updates request URL with your subscription ID
url = "https://management.azure.com/subscriptions/{}/providers/Microsoft.Consumption/usageDetails?api-version=2021-10-01".format(subscription_id)
#  makes HTTP request
response = requests.get(url, headers=headers)
#  packs the HTTP response into a JSON
feed = response.json()
#  grabs the cost per day from the JSON feed
cost = feed['value'][cost_json_index]['properties']['costInBillingCurrency']
```

# Raspberry Pi Azure IoT Hub Dashboard with CircuitPython

## Using an Azure Device Twin

An [Azure device twin](https://aka.ms/adafruit/tutorial3/AzureDeviceTwin) is a JSON document that stores all of the information about a device. Each device in your IoT Hub has a device twin that you can access. In **code.py** , device twins are used to check the connection status of each device. The connection status is represented by circles in the top right-hand corners of each device's telemetry box on the Raspberry Pi's display.

![](https://cdn-learn.adafruit.com/assets/assets/000/114/341/medium800/temperature___humidity_onlineSensor.jpg?1660762662)

![](https://cdn-learn.adafruit.com/assets/assets/000/114/342/medium800/temperature___humidity_offlineSensor.jpg?1660762668)

`IoTHubRegistryManager()` is used to authenticate access to the IoT Hub's device twins.

```python
#  connect to device twin
status_client = IoTHubRegistryManager(status_connection)
```

A device twin is accessed for each of the three devices using a `for` statement. If the device is connected, then it's circle is updated to be green. If the device is disconnected, then its circle is updated to be red.

```python
#  iterate through the status circles
for d in range(0, 3):
  #  get connection status of all 3 devices using device twin
  twin = status_client.get_twin(devices[d])
  #  if a device is connected, make the status circle green
  if twin.connection_state == 'Connected':
    status_circles[d].fill = 0x00FF00
  #  if a device is disconnected, make the status circle red
  if twin.connection_state == 'Disconnected':
    status_circles[d].fill = 0xFF0000
```

# Raspberry Pi Azure IoT Hub Dashboard with CircuitPython

## Setup the Code to Run on Boot

![](https://cdn-learn.adafruit.com/assets/assets/000/114/393/medium800thumb/temperature___humidity_startOnBoot.jpg?1660852253)

To run the IoT Hub Dashboard when the Raspberry Pi boots up, you need to make the **code.py** file an executable. To do this, add a _shebang_ to the first line of **code.py** , above the SPDX license.

```python
#!/usr/bin/env python3

# SPDX-FileCopyrightText: 2022 Liz Clark for Adafruit Industries
#
# SPDX-License-Identifier: MIT
```

Then, in a terminal, change directories to the **/azure\_pi** folder and mark the **code.py** file as an executable using `chmod`.

```terminal
cd /home/pi/azure_pi
chmod a+x code.py
```

The **code.py** file needs both the graphical interface and a network connection to properly run. As a result, that needs to be considered when deciding on a method to have it run on boot. To make sure the GUI and network connections are ready before trying to run **code.py** , a **.desktop** file is going to be used in the `autostart` system.

To create this file, in a terminal create a directory called **/autostart** in the **/.config** folder **.**

```terminal
mkdir /home/pi/.config/autostart
```

Then, create the **.desktop** file using the `nano` text editor. This file will be called **azure-pi.desktop**.

```terminal
nano /home/pi/.config/autostart/azure-pi.desktop
```

In the text editor, enter the following text to run **code.py**.

```terminal
[Desktop Entry]
Type=Application
Name=Azure-Pi
Exec=/usr/bin/python /home/pi/azure_pi/code.py
```

Exit and save the new **azure-pi.desktop** file. Then, try rebooting your Raspberry Pi. After loading the desktop, you should see the **code.py** `PyGameDisplay` window begin running.

# Raspberry Pi Azure IoT Hub Dashboard with CircuitPython

## Usage

![](https://cdn-learn.adafruit.com/assets/assets/000/114/392/medium800/temperature___humidity_edited_P1380680.jpg?1660851763)

Boot up your Raspberry Pi to run the IoT Hub Dashboard code. Then, power-up your IoT Hub devices. They will begin sending their telemetry to IoT Hub and that telemetry will populate the Raspberry Pi's dashboard.

Info: 

The dashboard will display all of the received telemetry from the IoT Hub devices, as well as connection status, the name of the last device to send telemetry, the timestamp that telemetry was received and the current month's cloud cost.

![temperature___humidity_piFullScreen.jpg](https://cdn-learn.adafruit.com/assets/assets/000/114/354/medium640/temperature___humidity_piFullScreen.jpg?1660765750)

The current month's cost is displayed on the dashboard to easily track usage.

![temperature___humidity_piFullScreen.jpg](https://cdn-learn.adafruit.com/assets/assets/000/114/347/medium640/temperature___humidity_piFullScreen.jpg?1660765358)

![temperature___humidity_costResource.jpg](https://cdn-learn.adafruit.com/assets/assets/000/114/349/medium640/temperature___humidity_costResource.jpg?1660765405)

A device's connection status is represented with a green or red circle.

![temperature___humidity_onlineOffline.gif](https://cdn-learn.adafruit.com/assets/assets/000/114/395/medium640thumb/temperature___humidity_onlineOffline.jpg?1660852713)

The last device to send telemetry data, along with the timestamp, is logged on the dashboard.

![temperature___humidity_deviceChange.gif](https://cdn-learn.adafruit.com/assets/assets/000/114/394/medium640thumb/temperature___humidity_deviceChange.jpg?1660852546)

## Going Further

You can create a custom bitmap background to better suite your devices and sensors that you want to monitor. You could also add hardware to the Raspberry Pi, like buttons, to make the dashboard have menus or modes.&nbsp;


## Featured Products

### Raspberry Pi 4 Model B - 4 GB RAM

[Raspberry Pi 4 Model B - 4 GB RAM](https://www.adafruit.com/product/4296)
The Raspberry Pi 4 Model B is the newest Raspberry Pi computer made, and the Pi Foundation knows you can always make a good thing _better_! And what could make the Pi 4 better than the 3? How about a&nbsp;_faster_ processor, USB 3.0 ports, and updated Gigabit Ethernet chip with...

In Stock
[Buy Now](https://www.adafruit.com/product/4296)
[Related Guides to the Product](https://learn.adafruit.com/products/4296/guides)
### Adafruit ESP32-S2 TFT Feather - 4MB Flash, 2MB PSRAM, STEMMA QT

[Adafruit ESP32-S2 TFT Feather - 4MB Flash, 2MB PSRAM, STEMMA QT](https://www.adafruit.com/product/5300)
We've got a new machine here at Adafruit, it can uncover your deepest desires. Don't believe me? I'll turn it on right now to prove it to you! What, you want unlimited mozzarella sticks? OK well, that's not something we can provide. But we can provide your...

Out of Stock
[Buy Now](https://www.adafruit.com/product/5300)
[Related Guides to the Product](https://learn.adafruit.com/products/5300/guides)
### Adafruit QT Py ESP32-S2 WiFi Dev Board with STEMMA QT

[Adafruit QT Py ESP32-S2 WiFi Dev Board with STEMMA QT](https://www.adafruit.com/product/5325)
What has your favorite Espressif WiFi microcontroller, comes with&nbsp;[our favorite connector - the STEMMA QT](http://adafruit.com/stemma), a chainable I2C port, and has lots of Flash and RAM memory for your next IoT project? What will make your next IoT project flyyyyy? What a...

Out of Stock
[Buy Now](https://www.adafruit.com/product/5325)
[Related Guides to the Product](https://learn.adafruit.com/products/5325/guides)
### Adafruit SCD-40 - True CO2, Temperature and Humidity Sensor

[Adafruit SCD-40 - True CO2, Temperature and Humidity Sensor](https://www.adafruit.com/product/5187)
Take a deep breath in...now slowly breathe out. Mmm isn't it wonderful? All that air around us, which we bring into our lungs, extracts oxygen from and then breathes out carbon dioxide. CO2 is essential for life on this planet we call Earth - we and plants&nbsp;take turns using and...

Out of Stock
[Buy Now](https://www.adafruit.com/product/5187)
[Related Guides to the Product](https://learn.adafruit.com/products/5187/guides)
### Adafruit BME688 - Temperature, Humidity, Pressure and Gas Sensor

[Adafruit BME688 - Temperature, Humidity, Pressure and Gas Sensor](https://www.adafruit.com/product/5046)
The long-awaited BME688 from Bosch gives you&nbsp;_all the environmental sensing you want_&nbsp;in one small package. This little sensor contains&nbsp; **temperature** ,&nbsp; **humidity** ,&nbsp; **barometric pressure,** &nbsp;and&nbsp; **VOC...**

In Stock
[Buy Now](https://www.adafruit.com/product/5046)
[Related Guides to the Product](https://learn.adafruit.com/products/5046/guides)
### STEMMA QT / Qwiic JST SH 4-Pin Cable - 50mm Long

[STEMMA QT / Qwiic JST SH 4-Pin Cable - 50mm Long](https://www.adafruit.com/product/4399)
This 4-wire cable is&nbsp;50mm / 1.9" long and fitted with JST SH female 4-pin connectors on both ends. Compared with the chunkier JST PH these are 1mm pitch instead of 2mm, but still have a nice latching feel, while being easy to insert and remove.

<a...></a...>

Out of Stock
[Buy Now](https://www.adafruit.com/product/4399)
[Related Guides to the Product](https://learn.adafruit.com/products/4399/guides)
### Lithium Ion Polymer Battery - 3.7v 2500mAh

[Lithium Ion Polymer Battery - 3.7v 2500mAh](https://www.adafruit.com/product/328)
Lithium-ion polymer (also known as 'lipo' or 'lipoly') batteries are thin, light, and powerful. The output ranges from 4.2V when completely charged to 3.7V. This battery has a capacity of **2500mAh** for a total of about 10 Wh. If you need a smaller battery, <a...></a...>

In Stock
[Buy Now](https://www.adafruit.com/product/328)
[Related Guides to the Product](https://learn.adafruit.com/products/328/guides)
### Official Raspberry Pi Power Supply 5.1V 3A with USB C

[Official Raspberry Pi Power Supply 5.1V 3A with USB C](https://www.adafruit.com/product/4298)
The official Raspberry Pi USB-C power supply is here! And of course, we have 'em in classic Adafruit black! Superfast with just the right amount of cable length to get your Pi 4 projects up and running!

Best for use with Pi 4 series, [Pi...](https://www.adafruit.com/product/5814)

In Stock
[Buy Now](https://www.adafruit.com/product/4298)
[Related Guides to the Product](https://learn.adafruit.com/products/4298/guides)

## Related Guides

- [Adafruit BME680](https://learn.adafruit.com/adafruit-bme680-humidity-temperature-barometic-pressure-voc-gas.md)
- [Raspberry Pi Care and Troubleshooting](https://learn.adafruit.com/raspberry-pi-care-and-troubleshooting.md)
- [Adafruit SCD-40 and SCD-41](https://learn.adafruit.com/adafruit-scd-40-and-scd-41.md)
- [Adafruit QT Py ESP32-S2 and QT Py ESP32-S2 with uFL Antenna](https://learn.adafruit.com/adafruit-qt-py-esp32-s2.md)
- [Adafruit ESP32-S2 TFT Feather](https://learn.adafruit.com/adafruit-esp32-s2-tft-feather.md)
- [IoT Food Scale with Azure and CircuitPython](https://learn.adafruit.com/iot-food-scale-with-azure-and-circuitpython.md)
- [DeviceScript, TypeScript for Microcontrollers](https://learn.adafruit.com/devicescript.md)
- [Star Fragment IoT Lamp](https://learn.adafruit.com/star-fragment-iot-lamp.md)
- [No-Code Snowfall Tracker with WipperSnapper and Adafruit IO](https://learn.adafruit.com/no-code-snow-tracker-with-wippersnapper-and-adafruit-io.md)
- [Super Simple Sunrise Lamp](https://learn.adafruit.com/super-simple-sunrise-lamp.md)
- [Adafruit IO Basics: Color](https://learn.adafruit.com/adafruit-io-basics-color.md)
- [IoT Filament Sensor](https://learn.adafruit.com/iot-filament-sensor.md)
- [RPi Stock Alert Alarm](https://learn.adafruit.com/rpi-stock-alert-alarm.md)
- [Integrating Color Sensors with itsaSNAP and HomeKit](https://learn.adafruit.com/integrating-color-sensors-with-itsasnap-and-homekit.md)
- [Cheekmate - a Wireless Haptic Communication System](https://learn.adafruit.com/cheekmate-wireless-haptic-communication.md)
- [Wireless ESP32-S2 Touch Screen Controller for Pure Data](https://learn.adafruit.com/wireless-esp32-s2-controller-for-pure-data.md)
- [DIY Trinkey No-Soldering USB Air Quality Monitor](https://learn.adafruit.com/diy-trinkey-no-solder-air-quality-monitor.md)
- [PyLeap ESP32-S3 TFT Boxing Glove Tracker w/ Adafruit IO](https://learn.adafruit.com/esp32-s2-tft-boxing-glove-tracker-w-adafruit-io.md)
