This repository is part of a training and project series for Azure IoT Central. The name of the series is "Raspberry Pi Gateway and Arduino Nano BLE Devices for Azure Iot Central" and is located at...
This project will enable a Raspberry Pi to act as a "Translation" Gateway and supports a number of scenarios...
- Protocol Translation - Translate the Bluetooth Notify and Charatertics Data into Json and send to Azure Iot Central.
- Protocol & Identity Translation - Translate the Bluetooth Notify and Charatertics Data into Json and send to Azure Iot Central and create Leaf Devices for each BLE Device.
- Opaque Gateway with Identity Translation - Translate the Bluetooth Notify and Charatertics Data into Json and send to Azure Iot Central and transparently Provision Devices for each BLE Device.
This project is primarly a training and education project that is fully realized and you take the project, components and build out your own working IoT system end to end.
You may want to try the supporting projects for the Nano BLE Devices if you landed here out of sequence.
Here is the link to the Github for the project "Arduino Nano BLE 33 for Azure IoT Central", you should also start and follow up to this point in the training link reference at the start of the Readme.
LINK: Arduino Nano BLE 33 for Azure IoT Central
We will be working with the following charactertics from our Nano BLE 33 Device and doing Protcol Translation to IoT Central...
- VERSION
- BATTERY CHARGED
- TELEMETRY FREQUENCY
- ACCELEROMETER
- GYROSCOPE
- MAGNETOMETER
- ORIENTATION
- RGB LED
Here is the link to the Github for the project "Arduino Nano BLE 33 SENSE for Azure IoT Central", you should also start and follow up to this point in the training link reference at the start of the Readme.
LINK: Arduino Nano BLE 33 SENSE for Azure IoT Central
We will be working with the following charactertics from our Nano BLE 33 SENSE Device and doing Protcol Translation to IoT Central...
- VERSION
- BATTERY CHARGED
- TELEMETRY FREQUENCY
- ACCELEROMETER
- GYROSCOPE
- MAGNETOMETER
- ORIENTATION
- RGB LED
- BAROMETER
- TEMPERATURE
- HUMIDITY
- MICROPHONE
- AMBIENTLIGHT
- COLOR
- PROXIMITY
- GESTURE
The code in this repository depends on Ardunio, Visual Studio Code and PlatformIO.
The development "toolchain" refers to all of the various tools, SDK's and bits we need to install on your machine to facilitate a smooth experience developing our BLE devices and the Raspberry Pi Gateway device. Our main development tool will be Visual Studio code. It has dependencies on tools from Arduino and other open source projects, but it will be the central place where all our development will occur making it easy to follow along regardless of which operating system you are working on.
- | Install These Tools |
---|---|
LINK: Python 3 Installation Page - Pyhon is the programming language we will use to build applications for the Raspberry Pi. | |
LINK: Visual Studio Code Installation Page - Visual Studio Code is a lightweight but powerful source code editor which runs on your desktop and is available for Windows, macOS and Linux. This is the IDE we will use to write code and deploy to the our BLE Devices and the Raspberry Pi Gateway. | |
LINK: Docker Desktop Install - Docker Desktop is an application for MacOS and Windows machines for the building and sharing of containerized applications. |
Pip is the package manager we will use to download packages
On Linux or macOS (Open Terminal):
pip install -U pip
On Windows (from a CMD window or Powershell):
python -m pip install -U pip
These are a set of tools we will use to develop our apps on the Raspberry Pi. You can open the Extensions sidebar with "Shift+Ctrl+X) or click the icon in the side navigator bar.
The Azure command-line interface (Azure CLI) is a set of commands used to create and manage Azure resources. The Azure CLI is available across Azure services and is designed to get you working quickly with Azure, with an emphasis on automation.
Click the link below and install on your Desktop environment.
LINK: Install the Azure CLI Tooling
We will need to setup our Raspberry Pi with all of the capabilities we will need to develop for our Protcol Translation Gateway.
We will be connecting to the Raspberry Pi using the remote SSH capability of Visual Studio Code that we installed as part of our development toolchain. When you set the RPi up, we enabled the device to connect to our Wifi network.
Now we want to find the IP address of our RPi and connect to via VS Code's Remote SSH tools. This will let us develop our code and test our application working remotely connected to the device.
-
Here is the documetnation on the extension for VS Code... LINK: Remote Development
-
Here is how we will connect to the Raspberry Pi... LINK: Remote development over SSH
-
Click on the green icon in the bottom left of Visual Studio Code, select "Remote-SSH:Connect to Host..."
-
Enter in the connection IP. It will be "pi@your IP Address". For example "[email protected]"
-
You maybe prompted the first time to indetify the Operationing System, choose "Linux"
-
Next, enter the Password for the Raspberry Pi, by default is is raspberry. You should change this right away!
-
Open our Home Folder on the Raspberry Pi
-
Click on left side of the main screen "Open Folder" and the navigation helper will open and default to "/home/pi/" press enter as that is right where we want to go!
- You maybe prompted re-enter your password (which is no longer raspberry, right?)
From the terminal, run these two commands to bring your Python environments to the latest versions...
sudo apt-get install python3
sudo apt-get install python3
If it all comes back as up to date, then goodness!
BlueZ is official Linux Bluetooth protocol stack.
We will be using the latest version of BlueZ. As of the last update to this repository, it was version 5.54. You should work with the latest, stable release in future as experimental features like BLE will stabilize and improve.
Visit the bluez download page and copy the link to the latest source release (under the User Space BlueZ Package section)
Latest version (5.54) since this documentation was updated. Bet sure to get the latest. http://www.bluez.org/
sudo apt-get install -y git bc libusb-dev libdbus-1-dev libglib2.0-dev libudev-dev libical-dev
sudo apt-get install -y libreadline-dev autoconf
cd ~
wget https://s3.amazonaws.com/json-c_releases/releases/json-c-0.13.tar.gz
tar -xvf json-c-0.13.tar.gz
cd json-c-0.13/
./configure --prefix=/usr --disable-static && make
sudo make install
cd ~
wget https://mirrors.edge.kernel.org/pub/linux/libs/ell/ell-0.6.tar.xz
tar -xvf ell-0.6.tar.xz
cd ell-0.6/
sudo ./configure --prefix=/usr
sudo make
sudo make install
cd ~
wget http://www.kernel.org/pub/linux/bluetooth/bluez-5.54.tar.xz
tar xvf bluez-5.54.tar.xz
cd bluez-5.54
sudo apt-get update
sudo apt-get install -y libusb-dev libdbus-1-dev libglib2.0-dev libudev-dev libical-dev libreadline-dev
./configure --enable-library --enable-mesh --prefix=/usr --mandir=/usr/share/man --sysconfdir=/etc --localstatedir=/var
sudo make
sudo make install
We now need to let the Rasp[berry Pi's Raspian OS know that we want to use our newly compiled BlueZ Bluetoothh stack and tell systemd to use the new bluetooth daemon:
After opening this file, bluetooth.service, make sure the ExecStart line points to your new daemon in /usr/libexec/bluetooth/bluetoothd, as shown in the screenshot below...
sudo vi /lib/systemd/system/bluetooth.service
You still need to create a symlink from the old bluetoothd to the new one. First, rename the old file for backup...
sudo cp /usr/lib/bluetooth/bluetoothd /usr/lib/bluetooth/bluetoothd-543.orig
cd /usr/lib/bluetooth/
ls -l
You should see this oputput...
Create the symlink using the commands below...
sudo ln -sf /usr/libexec/bluetooth/bluetoothd /usr/lib/bluetooth/bluetoothd
sudo systemctl daemon-reload
Finally; Let's double check the version of bluetoothd and meshctl...
bluetoothd -v
meshctl -v
You should see this oputput...
systemctl status bluetooth
sudo systemctl start bluetooth
Set to run automatically...
sudo systemctl enable bluetooth
One final configuration change you can make is to enable the bluetooth low energy features in bluez. These are special APIs that allow bluez to interact with bluetooth low energy devices, however they're still in development and put behind an experimental flag that must be enabled first.
To enable bluez's experimental features like BLE you can modify the bluez service configuration. Edit this configuration by running:
sudo nano /lib/systemd/system/bluetooth.service
Enable the experimental features by adding --experimental to the ExecStart line, for example the configuration should look like:
Save the file and exit the editor by pressing
- Ctrl-o
- Enter
- Ctrl-x.
Now tell systemd to reload its configuration files by running:
sudo systemctl daemon-reload
sudo systemctl restart bluetooth
Once the bluez service is running you can check the experimental features are enabled by running the status command again. You should see output similar to the following (notice the --experimental on the last line):
systemctl status bluetooth
hciconfig
hci0: Type: Primary Bus: UART
BD Address: DC:A6:32:B1:BD:39 ACL MTU: 1021:8 SCO MTU: 64:1
UP RUNNING
RX bytes:1710 acl:0 sco:0 events:118 errors:0
TX bytes:7521 acl:0 sco:0 commands:118 errors:0
Next up I started monitoring one of my Nano BLE 33 Devices in Advertising mode and ran this command...
sudo hcitool lescan
The Nano BLE Sense device is detected in the scan from the Raspberry Pi and we are up and working!
NOTE: If you get an error with LE Scan you can bring down the specific interface (i.e. hci0 = onboard bluetooth, hci1 = could a USB installed Bluetooth antennae, etc), try these commands...
sudo hciconfig hci0 down
sudo hciconfig hci0 up
Now that we have everything ready in our development tool chains and OS environments on our desktop and the Raspberry Pi, let's get started coding! We need to next clone the project and install libraries/dependancies.
cd ~
sudo apt-get install bluez python-bluez
sudo apt-get install libbluetooth-dev
wget https://github.com/pybluez/pybluez/archive/master.tar.gz
tar xvf master.tar.gz
cd pybluez-master
sudo python3 setup.py install
sudo apt-get install libbluetooth-dev
sudo apt-get install libglib2.0-dev
sudo pip3 install bluepy
sudo python3 setup.py install
sudo apt install libsdl2-dev libsdl2-image-dev libsdl2-mixer-dev libsdl2-ttf-dev \
pkg-config libgl1-mesa-dev libgles2-mesa-dev \
python-setuptools libgstreamer1.0-dev git-core \
gstreamer1.0-plugins-{bad,base,good,ugly} \
gstreamer1.0-{omx,alsa} python-dev libmtdev-dev \
xclip xsel libjpeg-dev libgpiod2
cd ~
cd Projects
git clone https://github.com/Larouex/IoTCRaspberryPiProtocolTranslationGateway.git
cd IoTCRaspberryPiProtocolTranslationGateway
pip3 install -r requirements.txt
We are now ready!
PROTIP! Consider all of the configuration work it took to prepare our Raspberry Pi, you may want to clone your SD card and tuck it away for ease of getting this point in future with a clean development state. Based on your OS, there are a number of tools out there to clobe the SD card image. You can then use your image backup with "balenaEtcher" to flash your card.
NOTE: You can skip this section if you do not plan to use Azure Key Vault to Store and Access secrets.
Azure IoT Central is what we using for capturing Telemetry and Managing out Gateway and Devices. It is a powerful SaaS offering and we will be using the tools and visualizations to build out a rich application for our scenario. In order to connect our devices and gateway to IoT Central, we need to manage a set of secrets and we will store those secrets in Azure Key Vault. I highly recommend that you do this so you do not make a mistake and expose access to your application, gateway or devices.
I am going to assume the following when we work with Azure and Azure Portal...
- That you already have an Azure Account (If you don't, get started here LINK: Create your Azure free account today)
- That you have sufficient permissions in your Azure account to create Resource Groups and Resources
- That you are familiar creating and using resources with the Azure CLI or the Azure Portal LINK: Azure Portal)
Name | Secret (IoT Central Admin [Device Connection] Page) | Content Type |
---|---|---|
raspberry-pi-protocol-translation-gateway-scopeid | Admin, Device Connection, Copy [ID scope] | Client Secret |
raspberry-pi-protocol-translation-gateway-saskey-device-primary | Admin, Device Connection, Devices, View Keys, Copy [Primary Key] | Client Secret |
raspberry-pi-protocol-translation-gateway-saskey-device-secondary | Admin, Device Connection, Devices, View Keys, Copy [Secondary Key] | Client Secret |
raspberry-pi-protocol-translation-gateway-saskey-gateway-primary | Admin, Device Connection, Azure Edge devices, View Keys, Copy [Primary Key] | Client Secret |
raspberry-pi-protocol-translation-gateway-saskey-gateway-secondary | Admin, Device Connection, Azure Edge devices, View Keys, Copy [Secondary Key] | Client Secret |
Once these are all created in Key Vault, your list should look like this...
https://docs.microsoft.com/en-us/azure/key-vault/certificates/quick-create-python
NOTE: You can skip this section if you do not plan to use Azure Key Vault to Store and Access secrets.
- Open a Terminal or Powershell session
- Login to the Azure CLI...
az login
- If the CLI can open your default browser, it will do so and load an Azure sign-in page.
- Otherwise, open a browser page at https://aka.ms/devicelogin and enter the authorization code displayed in your terminal.
- Sign in with your account credentials in the browser.
az ad sp create-for-rbac --name http://raspberry-pi-protocol-translation-gateway --skip-assignment
{
"appId": "<your appID>",
"displayName": "raspberry-pi-protocol-translation-gateway",
"name": "http://raspberry-pi-protocol-translation-gateway",
"password": "<your password>",
"tenant": "<your tenant>"
}
az keyvault set-policy --name larouex-prod-key-vault --spn "9afd63c4-91e2-4054-b068-aeb21dc291eb" --secret-permissions get set list delete backup recover restore purge
az keyvault set-policy --name <your key vault url> --spn <your password> --secret-permissions get set list delete backup recover restore purge
There is a file in the root folder of the project named "secrets_template.json" and this file outlines the shape of Json we use to retreive secrets. It supports Local Secrets and Key Vault usage. Copy the "secrets_template.json" to a new file named "secrets.json" in the root folder of the project. Open this file in Visual Studio Code and let's start configuring the options.
IMPORTANT: Make sure to check your .gitignore to verify that "secrets.json" is in the list so it does not get checked in! The file should be dithered in your Visual Studio Code Explorer window.
See the Json below the bullets for reference...
- Set "UseKeyVault" to true
- From the Azure Portal, Goto your Key Vault Resource
- Goto Secrets
- Click onto your secret for Scope ID that we set up previously
- Click the copy button next to the "Secret Identifier"
- Paste it into the "KeyVaultUri" in the "secrets.json" file.
- Highlight and cut the remainder of url after .../secrets/
- Paste into the ScopeId field
- Repeat for all the secrets we setup previously and put into the right fields!
Your file should look like this when completed...
{
"UseKeyVault": true,
"ProvisioningHost": "global.azure-devices-provisioning.net",
"LocalSecrets": {
"ScopeId": "",
"DeviceConnect":{
"SaSKeys":{
"Primary": "",
"Secondary": ""
}
},
"GatewayConnect":{
"SaSKeys":{
"Primary": "",
"Secondary": ""
}
}
},
"KeyVaultSecrets":{
"KeyVaultUri": "<Your Key Vault UIR>",
"TenantId":"<Your Tenant ID>",
"ClientId":"<Your Client ID>",
"ClientSecret":"<Your Client Secret>",
"ScopeId": "raspberry-pi-protocol-translation-gateway-scopeid",
"DeviceConnect":{
"SaSKeys":{
"Primary": "raspberry-pi-protocol-translation-gateway-saskey-device-primary",
"Secondary": "raspberry-pi-protocol-translation-gateway-saskey-device-secondary"
}
},
"GatewayConnect":{
"SaSKeys":{
"Primary": "raspberry-pi-protocol-translation-gateway-saskey-gateway-primary",
"Secondary": "raspberry-pi-protocol-translation-gateway-saskey-gateway-secondary"
}
}
}
}
Save the file and you can ignore the "LocalSecrets" section.
If you are working locally and do not want to implement the security and awesomeness of Key Vault, then go ahead and set "UseKeyVault" to false. Copy all our your SaS key values from the Admin, Device Connection page in IoT Central...
{
"UseKeyVault": false,
"ProvisioningHost": "global.azure-devices-provisioning.net",
"LocalSecrets": {
"ScopeId": "<Your Scope ID from IoT Central Device Connect Page>",
"DeviceConnect":{
"SaSKeys":{
"Primary": "<Your Primary Key from IoT Central Device Connect Page>",
"Secondary": "<Your Secondary Key from IoT Central Device Connect Page>"
}
},
"GatewayConnect":{
"SaSKeys":{
"Primary": "<Your Gateway Primary Key from IoT Central Device Connect Page>",
"Secondary": "<Your Gateway Secondary Key from IoT Central Device Connect Page>"
}
}
},
"KeyVaultSecrets":{
"KeyVaultUri": "",
"TenantId":"",
"ClientId":"",
"ClientSecret":"",
"ScopeId": "",
"DeviceConnect":{
"SaSKeys":{
"Primary": "",
"Secondary": ""
}
},
"GatewayConnect":{
"SaSKeys":{
"Primary": "",
"Secondary": ""
}
}
}
}
Save the file and you can ignore the "KeyVaultSecrets" section.
Let's go back to a terminal window and setup the variables on the Raspberry Pi. Use the values from the generated Jasn to set AZURE_CLIENT_ID ("appId"), AZURE_CLIENT_SECRET ("password") and AZURE_TENANT_ID ("tenant") environment variables.
export AZURE_CLIENT_ID="<your appId>"
export AZURE_CLIENT_SECRET="<your password>"
export AZURE_TENANT_ID="<your tenant>"
export AZURE_SUBSCRIPTION_ID="<your tenant>"
Authorize the service principal to perform key operations in your Key Vault:
https://www.bluetooth.com/specifications/assigned-numbers/generic-access-profile/
The next step is to turn on your BLE Devices and Scan for them using our Raspberry Pi Gateway. The scanning for BLE devices used BlueZ BLESCAN and this component requires SUDO access. I created the script to not require any installation of additional packages and also made it an external script to the primary gateway code.
In your project, there is a configuration file at the root of the project folder called "devicescache.json" LINK: devicescache.json and the structure of this file is shown below...
{
"DeviceCapabilityModels": [
{
"DeviceNamePrefix": "larouex-ble-sense-",
"DCM": "urn:larouexiot:nanoble33sense:1",
"DeviceInfoInterface": "urn:azureiot:DeviceManagement:DeviceInformation:1",
"DeviceInfoInterfaceInstanceName": "DeviceInformationInterface",
"NanoBLEInterface": "urn:larouexiot:nanoble33sense:NanoBLE33SenseInterface:1",
"NanoBLEInterfaceInstanceName": "NanoBLE33SenseInterface"
},
{
"DeviceNamePrefix": "larouex-ble-33-",
"DCM": "urn:larouexiot:nanoble33:1",
"DeviceInfoInterface": "urn:azureiot:DeviceManagement:DeviceInformation:1",
"DeviceInfoInterfaceInstanceName": "DeviceInformationInterface",
"NanoBLEInterface": "urn:larouexiot:nanoble33:NanoBLE33Interface:1",
"NanoBLEInterfaceInstanceName": "NanoBLE33Interface"
}
],
"Devices": [
{
"DeviceName": "Simulated Device",
"Address": "6A:6A:6A:6A:6A:6A",
"LastRSSI": "-91 dB",
"DCM": "urn:larouexiot:nanoble33:1",
"DeviceInfoInterface": "urn:larouexiot:nanoble33sense:NanoBLE33SenseInterface:1",
"DeviceInfoInterfaceInstanceName": "DeviceInformationInterface",
"NanoBLEInterface": "urn:larouexiot:nanoble33sense:NanoBLE33SenseInterface:1",
"NanoBLEInterfaceInstanceName": "NanoBLE33Interface",
"LastProvisioned": null
}
]
}
Let's review the file stucture...
This section is the "pattern" match for your BLE devices. Let's jump back (if you have not built out a Nano BLE device for this project, you should do that now or have a BLE simulation running using LightBlue, etc.) to our Nano BLE projects where we have a file that is global to the project called "Platform.ini" and in that file we have designated the following when building and deploying to the device...
[common_env_data]
build_flags =
-D VERSION=1.0.0.1
-D DCM="urn:larouexiot:nanoble33:1"
-D DEVICE_NAME="larouex-ble-33-0002"
-D SERVICE_UUID="6F165338-0001-43B9-837B-41B1A3C86EC1"
-D DEBUG=1
This section in "devicescache.json" identifies the pattern that your device advertises via BLE...
"DeviceCapabilityModels": [
{
"DeviceNamePrefix": "larouex-ble-sense-",
"DCM": "urn:larouexiot:nanoble33sense:1",
"DeviceInfoInterface": "urn:azureiot:DeviceManagement:DeviceInformation:1",
"DeviceInfoInterfaceInstanceName": "DeviceInformationInterface",
"NanoBLEInterface": "urn:larouexiot:nanoble33sense:NanoBLE33SenseInterface:1",
"NanoBLEInterfaceInstanceName": "NanoBLE33SenseInterface"
},
{
"DeviceNamePrefix": "larouex-ble-33-",
"DCM": "urn:larouexiot:nanoble33:1",
"DeviceInfoInterface": "urn:azureiot:DeviceManagement:DeviceInformation:1",
"DeviceInfoInterfaceInstanceName": "DeviceInformationInterface",
"NanoBLEInterface": "urn:larouexiot:nanoble33:NanoBLE33Interface:1",
"NanoBLEInterfaceInstanceName": "NanoBLE33Interface"
}
],
...
- DeviceNamePrefix - The naming pattern your BLE devices start with...
- DCM - The Device Capability Model Identity in IoT Central
The Devices section of the file is an array of devices that match your naming pattern. There is a "dummy" record for a Simulated device and this is there for reference and is ignored in all situations.
{
...
"Devices": [
{
"DeviceName": "Simulated Device",
"Address": "6A:6A:6A:6A:6A:6A",
"LastRSSI": "-91 dB",
"DCM": "urn:larouexiot:nanoble33:1",
"DeviceInfoInterface": "urn:larouexiot:nanoble33sense:NanoBLE33SenseInterface:1",
"DeviceInfoInterfaceInstanceName": "DeviceInformationInterface",
"NanoBLEInterface": "urn:larouexiot:nanoble33sense:NanoBLE33SenseInterface:1",
"NanoBLEInterfaceInstanceName": "NanoBLE33Interface",
"LastProvisioned": null
}
]
}
Let's run our scan devices Python script to find our advertising devices. I currently have two BLE devices up and adverstising before I executed the script...
- larouex-ble-sense-0001
- larouex-ble-33-0002
Here are the options for the Scan Device script that you can override...
- -h or --help - Print out this Help Information
- -v or --verbose - Debug Mode with lots of Data will be Output to Assist with Debugging
- -b or --btiface - Bluetooth Interface? '0' = Built in or '1' if you added a BT Device and Antenna, etc. (default=0)
- -r or --resethci - OS command to Reset the Bluetooth Interface (default=false)
- -s or --scanseconds - Number of Seconds the BLE Scan should Scan for Devices (default=10)
sudo python3 ./scandevices -v -r -b 0 -s 12
>>>
INFO: Verbose mode...
INFO: Bluetooth Interface Override...0
INFO: Scan Seconds Override...12
INFO: Bluetooth Reset Interface mode...
INFO: Loaded Config file: {'BluetoothInterface': 0, 'ScanSeconds': 10.0}
INFO: resethci: True
INFO: Bluetooth Interface: 0
INFO: Loaded Devices Cache file: {...}
INFO: hciconfig down...
INFO: hciconfig up...
WARNING: Please Wait: Scanning for BLE Devices Advertising...(12 Seconds)
WARNING: [FOUND NEW DEVICE] larouex-ble-33-0002
INFO: [DEVICE DCM] urn:larouexiot:nanoble33:1
WARNING: [FOUND NEW DEVICE] larouex-ble-sense-0001
INFO: [DEVICE DCM] urn:larouexiot:nanoble33sense:1
INFO: Updated Devices Cache file: {...}
Lot's of Information, let's run without the Debug INFO...
sudo python3 ./scandevices.py -r -b 0 -s 12
>>>
WARNING: Please Wait: Scanning for BLE Devices Advertising...(12 Seconds)
WARNING: [FOUND NEW DEVICE] larouex-ble-sense-0001
WARNING: [FOUND NEW DEVICE] larouex-ble-33-0002
Nice and terse. Let's run it again for Idempotency...
sudo python3 ./scandevices.py -r -b 0 -s 12
>>>
WARNING: Please Wait: Scanning for BLE Devices Advertising...(12 Seconds)
WARNING: [ALREADY DISCOVERED, SKIPPING] larouex-ble-sense-0001
WARNING: [ALREADY DISCOVERED, SKIPPING] larouex-ble-33-0002
Here is what our devicescache.json file looks like with all the data captured...
{
"DeviceCapabilityModels": [
{
"DeviceNamePrefix": "larouex-ble-sense-",
"DCM": "urn:larouexiot:nanoble33sense:1",
"DeviceInfoInterface": "urn:azureiot:DeviceManagement:DeviceInformation:1",
"DeviceInfoInterfaceInstanceName": "DeviceInformationInterface",
"NanoBLEInterface": "urn:larouexiot:nanoble33sense:NanoBLE33SenseInterface:1",
"NanoBLEInterfaceInstanceName": "NanoBLE33SenseInterface"
},
{
"DeviceNamePrefix": "larouex-ble-33-",
"DCM": "urn:larouexiot:nanoble33:1",
"DeviceInfoInterface": "urn:azureiot:DeviceManagement:DeviceInformation:1",
"DeviceInfoInterfaceInstanceName": "DeviceInformationInterface",
"NanoBLEInterface": "urn:larouexiot:nanoble33:NanoBLE33Interface:1",
"NanoBLEInterfaceInstanceName": "NanoBLE33Interface"
}
],
"Devices": [
{
"DeviceName": "Simulated Device",
"Address": "6A:6A:6A:6A:6A:6A",
"LastRSSI": "-91 dB",
"DCM": "urn:larouexiot:nanoble33:1",
"DeviceInfoInterface": "urn:larouexiot:nanoble33sense:NanoBLE33SenseInterface:1",
"DeviceInfoInterfaceInstanceName": "DeviceInformationInterface",
"NanoBLEInterface": "urn:larouexiot:nanoble33sense:NanoBLE33SenseInterface:1",
"NanoBLEInterfaceInstanceName": "NanoBLE33Interface",
"LastProvisioned": null
},
{
"DeviceName": "larouex-ble-sense-0001",
"Address": "c7:94:90:1c:8f:3c",
"LastRSSI": "-64 dB",
"DCM": "urn:larouexiot:nanoble33sense:1",
"DeviceInfoInterface": "urn:azureiot:DeviceManagement:DeviceInformation:1",
"DeviceInfoInterfaceInstanceName": "DeviceInformationInterface",
"NanoBLEInterface": "urn:larouexiot:nanoble33sense:NanoBLE33SenseInterface:1",
"NanoBLEInterfaceInstanceName": "NanoBLE33SenseInterface",
"LastProvisioned": null
},
{
"DeviceName": "larouex-ble-33-0002",
"Address": "fb:0a:8d:5f:79:e4",
"LastRSSI": "-59 dB",
"DCM": "urn:larouexiot:nanoble33:1",
"DeviceInfoInterface": "urn:azureiot:DeviceManagement:DeviceInformation:1",
"DeviceInfoInterfaceInstanceName": "DeviceInformationInterface",
"NanoBLEInterface": "urn:larouexiot:nanoble33:NanoBLE33Interface:1",
"NanoBLEInterfaceInstanceName": "NanoBLE33Interface",
"LastProvisioned": null
}
]
}
That is an overview of the purpose of scandevices.py: It finds advertising devices using BLEScan and and writes the data to the devicescache.json LINK: devicescache.json. That is all that is does, we have not provisioned our devices as of yet in Azure Iot Central and that is our next step!
I encourage you to look over the scandevices.py LINK: scandevices.py and the class that is uses to do all of the scanning and configuration LINK: classes/scanfordevices.py.
The next thing we get to do is work on our Device Template in Azure IoT Central. The first gateway type we are going to create for Provisioning is a "TRANSPARENT" gateway where it looks like our BLE devices are connected directly to IoT Central.
Let's get started at IoT Central and create an application LINK: Welcome to IoT Central
-
Click the "My Apps" on the sidebar
-
Select "+ New Application" from the main bar at the top
-
Click on the icon for "Custom apps"
-
Fill out the form with your application name and details and click "Create" button when done.
-
Next up, let's choose "Device templates" from the sidebar and Select "+ New" from the main bar at the top and you will be in the following page...
-
Click "IoT device" Icon and click "Next: Customize" button
-
Enter "NanoBLE33Sense" in the "Device template name" field click "Next: Review" button
-
Click "Create" button
-
Click the "Import capability model" Icon
-
Select the file named "nanoble33sense.json" from the location you cloned the project onto your desktop machine (i.e. ./IoTCRaspberryPiProtocolTranslationGateway/devicecapabilitymodels)
-
Now we have a full fidelity "Device Template" for our Nano BLE 33 Sense board. You can check out the board LINK: Github Project: IoTCNanoBLESense33
-
Click the "Publish" option on main bar at the top of the page and click the "Publish" button
CONGRATULATIONS We have created our IoT Central Application and Published our Device Template, we are ready to Provision our Devices using a TRANSPARENT GATEWAY technique.
Provisioning follows the same pattern as ScanDevices in that we have separated this script into a "stand-alone" operation.
There are excellent tutorials on connecting devices to IoT Central and using Device Provisioning Services online and we won't try to repeat that here. If you are not familar, take a break and visit these topics...
- LINK: Get connected to Azure IoT Central
- LINK: Tutorial: Create and connect a client application to your Azure IoT Central application (Python)
Provisioning in our Gateway project is one of key pillars of capabilities we have created and we have lots of options so you can try the various Gateway scenarios. Let's look at the options...
- -h or --help - Print out this Help Information
- -v or --verbose - Debug Mode with lots of Data will be Output to Assist with Debugging
- -p or --provisioningscope - Provisioning Scope give you fine grained control over the devices you want to provision.
- ALL - Re-Provision Every device listed in the DevicesCache.json file
- NEW - Only Provision Devices DevicesCache.json file that have "LastProvisioned=Null"
- device name - Provision a Specifc Device in DevicesCache.json file
- -g or --gatewaytype - Indicate the Type of Gateway Relationship
- OPAQUE - Devices will look like Stand-Alone Devices in IoT Central
- TRANSPARENT - Devices will look like Stand-Alone Devices in IoT Central
- PROTOCOL - IoT Central will show a Single Gateway and all Data is Associated with the Gateway
- PROTOCOLWITHIDENTITY - IoT Central will show a Single Gateway and Leaf Devices
Let's provision a specific device from our devicescache.json...
...
{
"DeviceName": "larouex-ble-sense-0001",
"Address": "c7:94:90:1c:8f:3c",
"LastRSSI": "-64 dB",
"DCM": "urn:larouexiot:nanoble33sense:1",
"DeviceInfoInterface": "urn:azureiot:DeviceManagement:DeviceInformation:1",
"DeviceInfoInterfaceInstanceName": "DeviceInformationInterface",
"NanoBLEInterface": "urn:larouexiot:nanoble33sense:NanoBLE33SenseInterface:1",
"NanoBLEInterfaceInstanceName": "NanoBLE33SenseInterface",
"LastProvisioned": null
},
...
Here is the command we are going to execute on our Raspberry Pi terminal...
python3 ./provisiondevices.py -v -p "larouex-ble-sense-0001" -g "TRANSPARENT"
The Device is Registered!