This article describes the design and implementation of the small tool, tester for exploring Azure IoT Central with Android Phone as a virtual Plug and Play Device (PnP Device).
Contents
- Android IoT Device simulator for Azure IoT Hub and Azure IoT Central
- Plug and Play Device model DTDL version 2
- Sending simulated telemetry data
- Re-sending a device telemetry data with an original timestamp
- IoT connectivity using the QR code
- Capability to provision and connect a new device with assigning its PnP model
- MQTT v3.1.1 protocol on port 8883
- Using the MQTT protocol directly based on the MSDN Doc
- No Device SDK
- Using M2Mqtt - MQTT Client library for .NET
Five years ago, I posted a little desktop tool called Azure IoT Hub Tester for simulation of the IoT devices connected to the Azure IoT Hub and later to the Azure IoT Central. Based on that and while moving to the Plug and Play device model (the conceptual point of the Azure IoT Central App), I can say that this article and its implementation is a natural extension to the tool Azure IoT Hub Tester for Android devices.
As the name of the article suggests, this implementation has focused on the Azure IoT Central platform, but it can also work with an Azure IoT Hub and/or without the device template model.
The following screen snippet shows a position of the IoTPnP Device such as an Android implementation of this article in the Azure IoT Central. Basically, the IoTPnP app is a MQTT device, which can be provisioned and/or connected to the Azure IoT Central App, including its device template as a sharable resource between them located in the well known repository of IoT models.
The IoTPnP device represents a fully transparent device to the real device connected to the Azure IoT Central using the same device model like a real device, can send manual telemetry data, device twin such as the readonly and writable properties, handle a direct method (command) and read the cloud-to-device messages. In other words, the IoTPnP device has implemented all features required for simulation of the plug and play device model.
Besides that, the IoTPnP device can obtain a time specific batch of telemetry data for any connected device and re-send them again with an original timestamp. Note that any payload for publishing by IoTPnP device can be edited manually or randomly updated based on the needs.
The IoTPnP device can be connected to the Azure IoT Hub/Central using the QR code containing necessary properties for creating a device connection string or just straight a standard text of the device connection string. Note, that all important config properties, states, etc. of the IoTPnP app are cached, so the application can be closed, minimized, etc. and reopen again with the cached config properties.
OK, let's describe the concept and design. I am assuming you have some knowledge of the Azure IoT Infrastructure, Azure IoT Central and working experience with my Azure IoT Hub Tester tool.
The concept and design of Azure IoT Central Tester and its Android implementation is driven by a device template model, the same way like it is done in the Azure IoT Central. The device model defines interactions between both ends such as the device and application. The device capabilities are grouped into the interfaces described by the collection of the properties
(readonly and writable), telemetry (D2C messages) and commands (sync and queued/C2D messages). The interfaces can be packaged into the component and reused across others device models and/or multiple times within the same device model, see the device model dtmi:com:example:TemperatureController;2, where the device model contains two thermostats with the same capabilities.
Based on the above concept, the design of the Azure IoT Central Tester is driven by component, so the IoTPnP device interacts with an Azure IoT Central only by capability of the selected component. The special case is if the device model has an interface in the root model, which is known as a default component.
So, as the above, the capability of the device is described by the following: telemetry, properties and command. The navigation between them is very simple like it is shown in the following screen snippets:
As you can see, above is the main page of the IoTPnP app, where on the top is the application bar for displaying a device name, selected device model and its component and the icon of the IoT connectivity status (green/red). Below this toolbar is the navigation bar for interface capabilities. Each selected navigation menu can be extended by clicking an optional menu on the right side of the app bar. The first four items of the navigation bar are related to the selected model component, the last one, on the right side has the name Model/Log and it is used for managing and logging IoTPnP application. Selecting this item and its settings option menu, we can handle IoT Connectivity, Device template, etc. More details about this will be described later on in the article.
The layout below the navigation bar is horizontally scrollable (except of the Model/Log item) like it is shown in the following screen snippets:
Basically, the second horizontal page is used for switching between the Subscriber and Publisher rsp. Model (Request) and Response. Note, that the Subscriber represents a readonly page where received message payload is displayed (from the Azure Iot Hub/Central). The other one, such as Publisher page represents a payload for publishing message on the shown topic. This page can be edited. Also, you can see on the bottom right side, there is a flat button to publish the page contents.
The following screen snippets show the Model item with selecting a Settings option menu:
OK, it's show time. Let's describe what this tiny tool can do for you. I am assuming you have some knowledge of the Azure IoT Hub/Central.
Before you start using the Azure IoT Central Tester, I am assuming you already have the Azure IoT Central Application. Note, that the tool will still work for features, where device connectivity to the Azure IoT Central App is not required, such as access to the PnP Models repository, etc.
Note, that this article has been written using the free trial for 7 days IoT Central Application - rk2021iotcfree
, so all QR codes are expired.
The following screen snippet shows a main page of the IoTPnP app on the Android phone, after clicking on the launcher icon:
The major part of the tool, which is representing a virtual MQTT device is its connectivity to the Azure IoT Central rsp. to the Azure IoT Hub. Basically, the IoT device is connected based on the device connection string. In the case of the Azure IoT Hub, we have available device connection string or we can very simply create one from the Azure IoT Hub Shared access policies. The other one, such as the Azure IoT Central App, we don't have a direct access to its underlying Azure IoT Hub. We must use a Device Provisioning Service (DPS), see more details about its REST APIs here.
The Azure IoT Central Tester supports only SAS token for device iot connectivity using:
- Device Provisioning Service
- Device connection string
The following steps show in detail how our virtual MQTT device (such as an android app IoTPnP) can be connected to the Azure IoT providers.
One more thing you should be aware of, that the device model represents a device implementation and its capabilities, so while the device is provisioning and connecting, this model id is passed to the IoT provider. In other words, based on this device modelId
, the Azure IoT Central app will assign or re-assign the device template for connected device(s) in the app.
Therefore, if we don't know about the assigned device template for the specific device, the tool should use the none
device model during the device provisioning and then after connectivity, we can select one based on the needs.
1. Connecting to the Azure IoT Central - Provisioned Device
This is the most common way for a device connectivity to the Azure IoT Central, where the app has already registered a device and assigned its device model for message data exchange.
The following screen snippet shows my rk2021iotcfree
application with all devices:
As you can see, the device1
is provisioned and interacted based on the IoT Plug and Play mobile model.
Let's connect our tool to this application as a device represented and interacted as a device1
, so select this device and click on the Connect
and then select QR code:
The Device connection QR code represents a JSON object with the following schema:
{
"scopeId":"0ne00461860",
"deviceId":"device1",
"deviceKey":"..."
}
I have tried to discuss with an Azure IoT Central team to add one additional optional property, such as a modelId
of the assigned device template, see this discussion here.
Note that this tool can accept this optional modelId
property and based on that, the IoTPnP
app can reselected, so both IoT ends are in the sync for their message data exchange interaction. It's up to you, to generate this optional device connection QR code using some 3rd party free tool, for instance QR Code Generator for Windows 10 by Snake Chia Labs.
OK, let's continue in our step to connect our tool with an Azure IoT Central as a provisioned device1
. This end is ready for scanning the device connection QR code.
The following screen snippets show how the IoTPnP app can be connected. Select the Model(Log) item in the navigation bar, then options menu Settings:
In the above menu, select the IoT Connection and you should get the phone scanner. Use the scanner for scanning a device connection QR code from your Azure IoT Central App screen. After a short vibration, you will see the JSON object from the QR code in the dialog, see the following screen snippet:
Pressing the OK button, the IoTPnP app will start processing the device provisioning service with your IoT application defined by scopeId
. Note, that this process takes some time and its successful result will show up in log and in the App bar, see the following screen snippet:
At this moment, we have our tool connected to the Azure IoT Central app, but we don't know anything about the message data exchange, how both IoT ends are going to interact. In other words, sending some telemetry data will show up as _unmodeleddata
, so we have to obtain an assigned modelId
of the provisioned device for assigned on the device side.
There is no direct support built-in the Azure IoT Central to get the modelId
assigned for specific device, we have to use multiple REST APIs calls and query the device template to get it. It looks like the Azure IoT Central team doesn't respect a device model driven architecture and they are using their own internal device template architecture with a different unique id.
This fact makes it difficult to query some sharable interfaces across multiple device template instances, etc.
Anyway, following are the steps of how to obtain a modelId
from the Azure IoT Central App. First of all, we have to generate an API Token and scan it by out tool for authorization header of the REST APIs:
The following screen snippet shows the QR code of the API token generated by Azure IoT Central App:
Now, on the device side, select the Model(Log)/Show device template to get the tool scanner:
After scanning and vibration, the dialog will show an ApiToken
, see the example on the following screen snippet:
Pressing the OK button, will start multiple REST calls to the Azure IoT Central App to figure out a device modelId
used for device1
.
The result of this process is the log message where we can see assigned device model at the Azure IoT Central App for the specific device1
. Note, that this modelId
is added to the cached list of the device models used by our tool:
1a. Get the Device Model from Repository
This step demonstrates how we can select a device model from the Repository. The entry point in our tool is Model(Log)/Settings/Device Template, see the following screen snippets:
You will get the dialog list of models already used by the tool. You have the following options in the dialog: clicking on the specific item, removing from the list by holding the specific item, pressing the Add button to add new one or just Cancel the dialog.
Note, there is a special none
item in the list, which is unassigning a model from the device, in other words, none device model is assigned to the device.
The following screen snippet shows the result when the dtmi:azureiot:PhoneAsADevice;2
has been selected:
Now, the IoTPnP virtual device with a capability of the device1 is ready to interact with connected Azure IoT Central App.
The following steps demonstrate other ways of how the IoTPnP virtual device can be connected to the IoT provider.
2. Create a New Device With a Device Model Assigning
This step demonstrates how to provision a new device, including its assigned model. The Azure IoT Central doesn't have (for this kind of device connectivity) built-in the QR code, so we have to create one. Basically, the QR code contains an application scopeId
and primary/secondary key of the Shared access signature. This information can be found in the Azure IoT Central, see the following screen snippet:
For generating a QR code for this JSON schema, we can use any free 3rd party program, like is shown in the following screen snippet:
{
"scopeId":"0ne00461860",
"deviceKey":"..."
}
Now, we need to start the scanner for IoT Connection, so select this menu like it is shown on the following screen snippet. Note, if the previous connection has been cached, you have to press the Cancel to clean it up and start over to bring up the phone scanner.
The prompt dialog shows the JSON object with required properties for DPS process, by pressing the OK button, you will be asked to type the device Id. Note, that the id must be in lowercase characters. I do recommend selecting the device model prior to this DPS process, so it can be passed to the Azure IoT Central for assigning to the device on the consumer side.
The following screen snippet shows the result, when the device1000 is in the collection of the connected devices:
Now, the IoTPnP device is ready to interact with connected Azure IoT Central App.
3. Using the Device Connection String
This step demonstrates how device connection string can be used to establish a connection to the Azure IoT Hub/Central.
The following screen shows a 3rd party generator of QR code for this text:
Recently, my Azure IoT Hub tester has been updated, so we can get a QR code of the device connection in the Log contents when the Copy ConnectionString
is selected:
By scanning the device connection string, QR code will pop up the following dialog and pressing the OK button will create a connectivity to the Azure IoT Hub/Central:
Now, the IoTPnP device is ready to interact with connected Azure IoT Central App.
4. Device Disconnecting/Reconnecting
This step demonstrates how we can disconnect or reconnect a device. The long click on the App bar will popup the menu for these features:
5. IoT Device Model Simulation
This step demonstrates the usage of the device model for interaction and message exchange patterns between the IoT ends such as this tool as a virtual device and connected application represented by the Azure IoT Central App.
Following the device model architecture where the device capabilities such as the telemetry, properties and commands are described in the device interface. Collection of the interfaces can be grouped into the reusable components. The special case of the device model is the model with a simple interface "hosted" in the model itself known as a root component or a default component.
The device, which is using the device model for interaction with the connected IoT application is known as a Plug and Play (PnP) device, that is upcoming name of our Android virtual app such as IoTPnP.
The device model (written by spec DTDL v2) represents a message exchange pattern between the IoT producer and its consumer. This is a common contract document stored in the shareable repository of models.
The PnP device model enables building an IoT solution using the Model First strategy the same way as we have a Contract First.
This article and its PnP device Android implementation is trying to demonstrate the Model First strategy, where the device side can interact with the iot application without the real implementation in the full transparent manner.
One more thing, IoTPnP device allows to simulate random numeric value based on the type value. Basically, the payload for publisher is based on the device model schema and the value is represented by a string
with a prefix '$
' character, for instance:
{
"battery":"$integer",
"accelerometer":{
"x":"$double",
"y":"$double",
"z":"$double"
}
}
Before publishing a payload, these aliases of values are replaced by random value based on the type. Note, that only a string
type is not randomized and its value is always abcd
.
The following steps are described in the details how IoTPnP device can interact with the connected IoT application based on the selected device model:
5a. Telemetry data (D2C Message)
This step demonstrates how we can send the telemetry data for selected component based on the device model to the IoT application.
The App bar of our tool shows three ids such as:
- deviceId: mobile1
- device display model name: IoT Plug and Play mobile
- Component name: sensors
Clicking on the Telemetry item of the navigation bar, we are in the place for publishing a payload on the topic, see the following screen snippet:
As you can see above, the model component sensors
have a capability to publish telemetry data, left scrolling the page will show the end of the topic, where is a property $.sub=sensors
indicates the component name.
The payload can be edited, or its values updated randomly, see the following screen snippet after selecting Edit
on the context menu:
and selecting an Update random:
Note, if you want to go back to the original payload, just select a menu item Telemetry. on the navigation bar.
So, now we are ready to Publish the payload as a telemetry data. In my demonstration example, I have clicked three times on the Publisher button, as you can see in the following screen snippet:
Let's look at the other side such as the Azure IoT Central App. The following screen snippet shows received Raw data:
That's great. We can see that the telemetry data has been accepted by Azure IoT Central App based on the common device model.
5aa. Getting the Raw Telemetry Data from the Azure IoT Central
The IoTPnP device has a feature to obtain a stream of telemetry data for specific device including the original timestamp. The following steps show how we can get back our published telemetry data on the device mobil1
. This feature requires a valid ApiToken
, otherwise we have to scan its QR code. I am assuming we have a valid ApiToken
, so we can press the OK button:
We need select a device mobil1
and then the TimeWindow
:
The following screen snippet shows a result of this operation. Note, that the process will take same time, as it requires to process the multiple REST calls:
Also, we can see some details about this process within the Model/Log page:
That's all for the demonstration of the publishing a telemetry data.
One more thing. Remember this step 5aa
for later discussion, when I will demonstrate the telemetry data batching, the feature for re-sending telemetry data from the real device.
5b. Readonly/Writable Properties (Reported/Desired Properties)
This step demonstrates how the device interacts with an Azure IoT Central for interface capability such as properties. I am assuming you have knowledge of the Azure IoT Central, Azure IoT Hub Device Twin and device PnP Model.
The device model contains basically two kinds of properties related to the IoT application end (Azure IoT Central App) such as writable
and readonly
properties. The IoT application can change only the writable properties. From the device facing side, these properties are in the opposite capability, so the device can readonly a writeable property, so on.
This characteristic is coming from the Azure IoT Hub Device Twin represented by reported and desired properties.
Capability to synchronize both IoT ends can be reached using a device twin such as the reported (readonly) and desired (writable) properties. The properties are event driven, so if their value has been changed, the IoT ends (device and IoT app) can receive these changes. This is very important behavior to simplify by synchronizations of the states between both ends.
Based on the above short description, the IoTPnP device implements the feature Twin, see the following entry point:
As you can see above, there are two hardcoded folders such as:
- /PATCH/properties/desired/#
- /res/#
These two folders represent two topics for subscribing (receiving) the MQTT messages from the IoT App. The first one is dedicated for receiving changes on the desired (writable) properties and the second one is for receiving a result of the publish request, for instance: Get the full device twin from the backend (IoT app).
From the device model point of the view, the first folder is related to the writable properties and the second one for readonly properties.
Note, if the component of the device model contains readonly and/or writable properties, the names of the folder are bolded.
As you can see above, the component sensors do not have any Readonly or Writable properties.
One more thing, every time when the item Twin on the navigation bar is clicked, the IoTPnP device is publishing request to get the device Twin from the IoT App, so when we select the Subscriber Tab, the page will show a present state of the desired and reported properties.
The following screen snippet shows an empty payload for publishing. We can publish some property to the IoT App, but this property is going to handle as _unmodeleddata
.
So, let's change the component for simulation where we have some properties. Click on the Model/Settings and select the Component Template. The device model offers the two other components such as the device_info
and default
(root component). Let's select the device_info
component:
Clicking on the Twin
navigation item, we can see the following differences in the Publisher Tab:
Clicking on the Subscriber Tab, we can see the current values of the device twin (reported and desired properties):
By the way, the above device_info
state is done from the real mobile.
The following screen snippets show simulation (publishing) any unmodeled properties on both IoT Ends (device and IoT Central):
Back to our device_info
readonly properties and we are going to publish random values to the IoT App:
Clicking on the Twin, we can refresh the Subscriber Tab page:
On the Azure IoT Central, we can see this update:
Let's select the last component such as a default
component. We can see, there is a simple one property readOnlyProp
. Pressing the Publish
button, the randomly updated property is sent to the Azure IoT Central:
You can see in the following screen snippet the value of the readOnlyProp
:
That's great, it is working well between these IoT ends based on the device model.
5ba. Message Exchange for Writable Property
Our device model has one writable property as it is shown in the following picture. Let's update its value for XYZ
. Clicking the Save
button, the event is generated and sent to the device:
The following screen snippet shows received PATCH
for this writable property and the Publisher Tab shows a format of the respond payload for this patch. Note, that the IoT Central continues waiting for acknowledge of this state from the device side:
We can click on the Publisher page to bring the Edit mode, acknowledge the property value and its version. The correct values are shown on a Subscriber page:
When the Publisher has been hit, the payload is sent to the Azure IoT Central and we can see the acknowledge state on the screen:
So, now we know both IoT ends have synchronized the writable property.
Clicking on the Twin navigation item, we can see the latest state of the device twin:
That's all for simulation of the device model properties.
5c. Commands (Direct Methods)
The device model used a command type for invoking a device behavior. The command message exchange pattern between the IoT App and device basically uses a request/response pattern, following the Azure IoT Hub Device Direct Method such as a synchronous call.
The command always requires a response from the device method. The invoker informs the device about the waiting time (responseTimeoutInSeconds
) for a response message and in the case of long running command, the device can respond immediately with a status 202 accepted
, otherwise the command failed if the time expired.
The following steps demonstrate an interaction of the command in the sensors component. Note, that the invoker of the command is not a device, it is an IoT App.
The following screen snippets show a situation before invoking a commnad at both IoT ends, such as an Azure IoT Central and next picture on the device:
As you can see above, by clicking on the Methods, we can see all methods defined in the specific component, that is the bolded name of the folder, where we can see the received request/response messages. Selecting the name of the command, the model of the request and response will show up on the horizontal scrollable page.
Let's make a command. The following screen snippet shows a selected command on the Azure IoT Central:
Pressing the above Run
button, the request message is sent to the device:
At this time, I was busy making the snippet for this request, so the responseTimeoutInSeconds (30sec)
has expired and invoker finished this command with a Failed status, see the command history:
Therefore, I made one more command with focusing on the immediate respond, such as publishing an empty payload:
As you can see, the following history of the command, we were successful in this interactions:
That's all for this sync(online) command which always requires a respond from the device, but there is one more command handled by IoT App explicitly, in other words, it is not defined by the device model. This command is processed offline and it is useful for disconnectable devices.
One more thing for this sync commands, the following screen snippet shows how we can start a long-running command. Clicking on the Accepted (202) item, we are accepting this command and the finally response will be used by sending a reported property with the name of the method:
5d. Queued/offline Commands (C2D Messages)
This command is known as a cloud-to-device messaging (C2D Messaging). More details about the offline command can be found here.
Our demonstrated model doesn't have an offline command, see the following screen snippet when we click on the Messages item:
Let's change the online (standard) command to the offline (queued) one. The following screen snippet shows how it can be done in the Azure IoT Central. Please, don't forget press the Save
button and then click on the Publish
to refresh this change in the application:
Now, we have an offline command, let's invoke it:
Clicking on the above Run
button, the C2D Message is sent to the device. We can see the no-bolded folder for this command and its received message:
Note, the above picture shows a message payload, but by horizontally scrolling this page, we can see all properties on the topic, including the method name.
The offline command sent the message to the queue of the underlying IoT Hub of the IoT Central App, so the respond is immediate, and it finished with a success state:
6. Advanced Features
Currently, the IoTPnP app has built-in only one advanced feature such as batching telemetry data which allows to replay already published telemetry data from the device. The batching telemetry data includes the original timestamp using the well-known properties, the _eventcreationtime
.
6a. Batching Telemetry Data
This step demonstrates batching telemetry data of the real device mobil1
and published by device device1
. First of all, we have to connect our IoTPnP device as a device1
and then selecting a Download Sample1
option:
Next, we need to select a device and the TimeWindow
for batching telemetry data:
The telemetry data from the selected device and the TimeWindow
will be show up in the Publisher
page of the device1
. Pressing on the Publisher button, the Batching process kicked off:
Note, that the Azure IoT Central currently doesn't support publishing telemetry data in the batch, where each event can have its own timestamp (_eventcreationtime
), we have to do it in the batch loop one by one.
The following screen snippet shows a Model/Log page after the batch process finished:
The Raw data of the batching telemetry data is shown in the following screen snippet of the IoT Central:
As you can see in the above, the device model accepted a property _eventcretiontime
.
That's all for the batching process.
First of all, the following are the prerequisites:
- Visual Studio 2019/2022
- M2Mqtt - MQTT Client Library for .NET version 4.3.0
- Microsoft Azure IoT Central Application (any tier, included a Free)
- Connectivity to the Internet
- Downloading package (source) for this article (option for creating .apk)
- Understand document Overview of Android development on Windows
The Android app project has been created from the Simple View App template as a starting point. The assembly name and namespace is simple as App6
, the application name is IoTPnP and the package name is com.pathcom.rkiss.IoTPnP
. Many parts of the code have been used from my proven article Azure IoT Hub Tester, for instance: PnP Model library, sasToken library, etc. and of course, thanks to 3rd parties such as the MQTT communication client library M2Mqtt and ZXing.Mobile for QR scanner.
The Android app is a MainActivity
driven app with the handlers, eventing and dialogs triggered by menu items in the navigation bar, options menu or context menu on the page. The multithreading coding is based on the ThreadPool.QueueUserWorkItem
method and async/await
pattern.
The following screen snippet (no code snippet) shows an example of the multithreading implementation usage in the background task of the dialogs, where the https communication is required and the workflow process is depended on the dialog select:
The above is a small code fragment from the MainActivity.cs implementation file. Please have a look at it, if you are interested in how this Android app has been implemented.
That's all for this article, I hope you enjoyed it.
This article gives to you a tiny mobile tester for Azure IoT Central App or Azure IoT Hub. It can be your helper while evaluating and exploring the Azure IoT Central App, for developing MQTT Devices, troubleshooting an IoT Data, or simulation of the telemetry data from the real device. One more thing, this mobile tiny tester interacts with the IoT Central as a Plug and Play device, it allows to simulate the telemetry, properties and commands of the device capabilities. I hope you will find it useful.
- 17th January, 2022: Initial version