Overview
IoTConnect platform provides various flavors of SDKs, however, it may be a case where these SDKs are not fit for your device due to memory limitation or hardware limation.
IoTConnect provides you to build your own SDKs using the protocol which IoTConnect SDKs are using. You can find detailed documentation on workflow and all minor things that you need to take care of while building your own SDKs.
Before you start, we recommend you read the below guidelines.
- IoTConnect underneath use Azure IoT Hub as MQTT broker and Azure IoT Hub only support MQTT v3.1.1 standard
- Only one MQTT connection getting created on a single device
- MQTT Connection must be destroyed and closed when not required
- Each D2C message should not create an MQTT Connection
- In case of failure of any API, the device should wait for sometime before retry
- Time format must be as per standard mentioned in the document
Below is the Developer Document to build your own SDK in any language that supports your device.
- High level Diagram
- Prerequisite
- Step 1 Call Discovery API to get access of Identity Endpoint
- Step 2 Call Identity Endpoint to get credentials and configurations details
- Root Attributes of Identity API response:
- Section 2.1 Json object return by Identity API
- Section 2.2 Object represents OTA information in ota tag
- Section 2.3 Object represents SDK Configuration in sc tag
- Section 2.4 Object represents Protocol information in p tag
- Section 2.5 Array of object represents Device information in d tag
- Section 2.6 Array of object represents Attribute(s) information in att tag
- Section 2.7 Array of object represents Setting/Twin(s) information in set tag
- Section 2.8 Array of object represents Rule information in r tag [Only for Edge Enabled device]
- Step 3 Send device to Cloud message
- Step 4 Receive Cloud to device message
- Step 5 Manage Device Twin Properties (Settings)
- General Guideline and SDK Options
High level Diagram
- Discovery and Identity (Agent) API are REST calls over HTTPS and returns JSON data, apart form these two API
- All IoTHub Device Events are over MQTTS
Note : Platform expect integration of only two REST API from Device. Integration of other API is not recommended. If device found making such calls then those Device will be marked as black listed and will be non-operational.
Prerequisite
Board should have following capability
- JSON Library
- MQTT Library
- HTTP/S Library (TLS)
- Internet Connectivity (WiFi / Lan / Cellular / LTE-M / NB-IoT)
- IoTConnect Account
- Azure SDK library (for TPM authorized device only)
- Azure DPS “scopeId” for TPM device provisioning (You can get “scopeId” from IoTConnect portal “Settings -> Key vault”)
Step 1: Call Discovery API to get access of Identity Endpoint
To start process you need to call discovery API by passing few parameters to fetch Identity Endpoint. For this you need CPID, IOTConnect supported language, version and environment
URL https://discovery.iotconnect.io/api/sdk/cpid/{CPID}/lang/{LANG}/ver/2.0/env/{ENV}
Type GET
CPID | A string represents your company id, you can get form IOTConnect Portal. |
---|---|
LANG | A string represents the language of firmware which is asking Identity API endpoint. Possible values are M_JAVA, M_C, M_Python, M_Node & M_C#. |
ENV | Connect with IoTConnect support for Instance or Environment. |
Step 2 Call Identity Endpoint to get credentials and configurations details
On success of Discovery API, it will give following Json contains base url and log information
{ "baseUrl": "", // A string represents the base url of identity API "logInfo": "" }
To get required configuration and credentials, need to make call to identity end point of base URL
URL [BASE_URL]/sync
Type POST
Header accept application/json
Header Content-Type application/json-patch+json
Body
{ "cpId": "string", // A string represents CPID of company "uniqueId": "string", // A string represents uniqueid of device "option": { "attribute": true, // true/false – to receive attribute information "setting": true, // true/false – to receive setting/twin information "rule": true, // true/false – to receive rule information [for Edge] "protocol": true, // true/false – to receive protocol information "device": true, // true/false – to receive device information "sdkConfig": true // true/false – to receive sdk configuration } }
Root Attributes of Identity API response
Section 2.1 JSON object return by Identity API
{ "dtg": "", // A unique identifier represents the Device Template guid [DTG] "cpId": "", // A string represents the CPID of company "rc": 0, // An integer represents the response code [Ref: Table 1] "ee": 1, // An integer represents if supports Edge is enabled or not [Ref: Table 2] "at": 1, // An integer represents the device authentication type [Ref: Table 3] "ota": {}, // An object represents the OTA information [Ref: Section 2.2] "sc": {}, // An object represents the SDK configuration [Ref: Section 2.3] "p": {}, // An object represents the Protocol information [Ref: Section 2.4] "d": [], // An array of object represents the Device(s) information [Ref: Section 2.5] "att": [], // An array of object represents the Attribute(s) information [Ref: Section 2.6] "set": [], // An array of object represents the Setting/Twin(s) information [Ref: Section 2.7] "r": [] // An array of object represents the Rules defined on template [Ref: Section 2.8] }
Reference Tables
Table 1 [Possible values for rc]
0 | OK |
---|---|
1 | DEVICE_NOT_REGISTERED |
2 | AUTO_REGISTER |
3 | DEVICE_NOT_FOUND |
4 | DEVICE_INACTIVE |
5 | OBJECT_MOVED |
6 | CPID_NOT_FOUND |
Table 2 [Possible values for ee]
0 | False |
---|---|
1 | True |
Table 3 [Possible values for at]
1 | Symantec Key |
---|---|
2 | CA Signed Certificate |
3 | Self-Signed Certificate |
4 | TPM |
Section 2.2 Object represents OTA information in ota tag
{ "force": false, // A Boolean value to identify if ota is force update or not "guid": "", // A unique identifier represents the ota update item guid "urls": [] // A string array represents the ota files }
Force OTA update
As platform IoTConnect have a feature that without getting the latest update device will not send data back to
cloud. For this “force” will be set to true and URLs for getting firmware update will be mentioned in “url”
tag.
As part of sending an acknowledgement of valid update, you need to send an acknowledgement back to
IoTConnect cloud to sync up the OTA status of the device in the cloud. Please refer this section on how to send
OTA Update status back to IoTConnect Cloud
Section 2.3 Object represents SDK Configuration in sc tag
{ "hb": { // Configuration to send Heart Beat "fq": 99, // An integer represents the frequency of sending heart beat "h": "", // A string represents mqtt host name "un": "", // A string represents mqtt user name to connect host "pwd": "", // A string represents mqtt password name to connect host "pub": "" // A string represents pub topic to send heart beat message }, "log": { // Configuration to send device log information "h": "", // A string represents mqtt host name "un": "", // A string represents mqtt user name to connect host "pwd": "", // A string represents mqtt password name to connect host "pub": "" // A string represents pub topic to send heart beat message }, "sf": 99, // A number represents the identity api call frequency. "df": 60 // A number represents the Data sednd frequency in seconds configured in template }
Above configuration are used to send additional information back to IoTConnect. In some case, device
wants to send a heartbeat or sending log files. They can use this information and send a message back to
IoTConnect. Sf will be number which stands of sync frequency like if sync call failed then what will next
time sync needs to be initiated again.
Section 2.4 Object represents Protocol information in p tag
{ "n": "", // A string represents the name of protocol [Ref: Table 4] "h": "" // A string represents the mqtt host name to connect "p": 8883 // A fixed integer represents port to connect mqtt host [ "id": "", // A string represents the mqtt client id "un": "", // A string represents the user name for mqtt connection "pwd": "", // A string represents the password for mqtt connection [Only AuthType 1] "pub": "", // A string represents mqtt publish topic to send D2C data [PUB_TOPIC] "sub": "" // A string represents mqtt publish topic to receive D2C data [SUB_TOPIC] }
Reference tables
Table 4 [Possible values for n]
mqtt | Device connection should use MQTT protocol |
---|---|
https | Device connection should use HTTPS protocol |
Section 2.5 Array of object represents Device information in d tag
{ "tg": "", // A string represents the device tag "id": "", // A string represents the device uniqueid / identity "s": 0 // A integer represents the device status [Ref: Table 5] }
Reference Tables
Table 5 [Possible values for s]
0 | OK |
---|---|
1 | DEVICE_NOT_REGISTERED |
2 | AUTO_REGISTER |
3 | DEVICE_NOT_FOUND |
4 | DEVICE_INACTIVE |
5 | OBJECT_MOVED |
Section 2.6 Array of object represents Attribute(s) information in att tag
{ "p": "", // A string represent the parent attribute name "dt": 0, // An integer represent data type of attribute [Ref: Table 6] "agt": 0, // An integer represents the aggregation type [Ref: Table 9] "tw": "", // A string represents the tumbling window [Ref: Table 10] "tg": "", // A string represents the tag of attribute "d": [] // An object contains child }
Reference tables
Table 6 [Possible values for dt]
null | Attribute have child elements without parent attribute |
---|---|
2 | Attribute have child elements with parent attribute |
Table 7 [Possible values for dt]
0 | Integer |
---|---|
1 | String |
Table 8 [Possible values for dv]
Type validation values and/or validation ranges separated by commas |
1, 2, 10 to 20: validate as 1, 2 or 10 to 20 |
-10 to -5, -15: validate as -10 to -5 or -15 |
Table 9 [Possible values for agt]
Sum of following integer.
1 | min |
---|---|
2 | max |
8 | sum |
16 | average |
32 | Latest Value |
If value is 14 then aggregation on Average, Sum & Max
If value is 20 then aggregation on Count & Sum
Table 10 [Possible values for tw]
Its represents time interval at which aggregation will happen, value should be 1 to 999 ending with h/m/s. |
If its 5h, then tumbling window is of 5 hr If its 5m, then tumbling window is of 5 min If its 5s, then tumbling window is of 5 sec |
Section 2.6.1 Array of object represents Attribute(s) information in d tag
{ "ln": "", // A string represents the local name of attribute "dt": 0, // An integer represents data type of attribute [Ref: Table 7] "dv": "", // A string contains the data validation [Ref: Table 8] "tg": "", // A string represents the tag of attribute "sq": 1, // An integer represents the sequence of attribute "agt": 0, // An integer represents the aggregation type [Ref: Table 9] "tw": "" // A string represents the tumbling window [Ref: Table 10] }
Section 2.7: Array of object represents Setting/Twin(s) information in set tag
{ "ln": "", // A string represents the name of Setting or Twin "dt": 0, // An integer represents the data type of Setting or Twin [Ref: Table 7] "dv": "" // A string represents the data validation for Setting or Twin [Ref: Table 8] }
Section 2.8: Array of object represents Rule information in r tag [Only for Edge Enabled device]
{ "g": "", // A unique identifier represents the rule guid "es": "", // A unique identifier represents the subscription guid "con": "", // A string represents the condition for rule evaluation "att": [ // An array of attribute guid, on which condition is going to applied { "g": [] } ], "cmd": "" // A string contains command to execute if rule matched }
Step 3 Send device to Cloud message
Once you receive authentication details you can keep a connection to host open and start sending data and receive commands. To send data you must create following json object and send to publish topic
Section 3.1: Object contains device telemetry
{ "cpId": "", // A string represents the cpid of company "dtg": "", // A unique identifier represents the device template guid [Ref: dtg] "sdk": { "l": "", // A string represents the language [Ref: Table 11] "v": "2.0", // A string represents the fixed number "e": "" // A string represents the environment of instance. Connect Support }, "t": "", // A string represents datetime [Ref: Table 12] "ts": 0, // Epoch time "mt": 0, // A integer represents the message type. [Ref: Table 13] "d": [] // An object contains device telemetry data [Ref: Section 3.1.1] }
Table 11 [Possible values for l]
M_JAVA | Java as language |
---|---|
M_C | C as language |
M_Python | Python as language |
M_Node | Node as language |
M_C# | C# as language |
Table 12 [Possible values for t]
Date time will be in ISO 8601 format Example: 2019-09-30T09:21:17.513Z |
Table 13 [Possible values for mt]
0 | Reporting telemetry message |
---|---|
1 | Reporting fault message |
2 | Reporting edge telemetry message |
3 | Reporting edge rule matched message |
5 | Acknowledgement message |
6 | OTA status message |
9 | Device created message [Only for TPM authentication type] |
Section 3.1.1: Object contains device telemetry data json
{ "id": "", // A string represents the uniqueid id of device "dt": "", // A string represents datetime [Ref: Table 12] "tg": "", // A string represents the device tag "d": [] // Array of objects contains attribute value as telemetry data }
Here d will contain the attribute data in key value pair. Examples
{ "gyro": { "x": "3", "z": "5" }, "humidity": "2" } { "temp": "2", "color":"red", "device_status":"on" }
Note: You can pass multiple telemetry data into “d” section. Make sure size of JSON should not
exceed to 3 KB.
Step 4 Receive Cloud to device message
On successful connection with mqtt host, you must add listener to subscriber topic if required.Whenever IOTConnect sends data to device you will find message in this topic with json format given bellow.
IoTConnect provide various types of command to be sent out to device. Majority there will be Device Command, Firmware Command and Module Commands. These are functional command which firmware must take care.
There are other commands which SDK needs to take care, like when there is any change in template, SDK needs to do sync back to IoTConnect and get update values. Like attribute change or child command list updated etc.
There is also Hard Stop command, which will make device get disconnected form IoTConnect.
{ "cpid": "", // A string represents the cpid for company "cmdType": "", // A string contains type of command received [Ref: Table 14] "ack": false, // A Boolean represents acknowledgement is required or not "command": "", // A string contains command that is received "urls": [“”], // A string array represents the firmware urls [0x02 & 0x04] [URLS] "uniqueId": "", // A string represents the unqiueid of device "ackId": "", // A string represents the uniqieidentifier of acknowledgment [ACKID] "guid": "" // A string represents the uniqieidentifier of device }
Table 14 [Possible values for cmdType]
0x01 | Device Command |
---|---|
0x02 | Firmware update command |
0x03 | Module update command |
0x10 | On change of attribute in portal; platform will send this command to re-sync attribute |
0x11 | On change of setting or twin in portal; platform will send this command to re-sync setting |
0x12 | Force device to change it password by calling sync with protocol set to true |
0x13 | On add or remove of child device in portal; platform will send this command to re-sync device |
0x15 | On add or remove of rule in portal; platform will send this command to re-sync rule [For Edge only] |
0x99 | Force device to stop calling sync and discovery and close open MQTT connection |
4.1 Device Command
As part of Template there will be commands which can be sent form Cloud to Device. This type of
command will be identified by cmdType as 0x01.
4.1.1 Device Command Acknowledgements
Each device command has facility to make sure that command is reached and executed on device. In this
case json property “ack” will be true. That means there IoTConnect is expecting acknowledgement back,
for that you must send acknowledgement message with following structure
{ "uniqueId": "", // A string represents device uniqueid "t": "", // A string represents datetime [Ref: Table 12] "ts": "", // Epoch time "mt": 5, // A number 5 represents command acknowledgement message type "cpId": "", // A string represents the CPID of company "d": { "ackId": "", // A string represents the acknowledgment guid [Ref: ACKID] "st": 0, // A number represents the status code [Ref: Table 15] "msg": "" // A string represents the status message }, "sdk": { "l": "", // A string represents the language [Ref: Table 11] "v": "", // A string represents the fixed number "e": "" // A string represents the environment of instance. Connect Support } }
Table 15 [Possible values for st]
4 | Command Failed with some reason |
---|---|
6 | Executed successfully |
4.2 Firmware Command
This is special command sent to device for firmware update. This type of command will be identified by cmdType as 0x02. One can add firmware command as part of Template. If no command defined at template level then IoTConnect will send ota as command texts.
Note: “urls” [Ref: URLs], will be string array as IoTConnect supports multiple firmware files to be sent out in single OTA Update.
4.2.1 Firmware command acknowledgement
Same as device command; Firmware commands also provide mechanism to give acknowledgement back go IoTConnect. To send firmware command acknowledgement following json structure will be sent to IoTConenct.
{ "uniqueId": "", // A string represents device uniqueid "t": "", // A string represents datetime [Ref: Table 12] "ts": "", // Epoch time "mt": 11, // A number 11 represents command acknowledgement message type "cpId": "", // A string represents the CPID of company "d": { "ackId": "", // A string represents the acknowledgment guid [Ref: ACKID] "st": 0, // A number represents the status code [Ref: Table 16] "msg": "", // A string represents the status message "childId": "" // Gateway's child device ID for OTA update only }, "sdk": { "l": "", // A string represents the language [Ref: Table 11] "v": "", // A string represents the fixed number "e": "" // A string represents the environment of instance. Connect Support } }
Table 16 [Possible values for st]
4 | Firmware command Failed with some reason |
---|---|
7 | Firmware command executed successfully |
4.3 Other Commands
These are command which SDK needs to take care to update device meta data. All these commands should initiate sync to get latest device meta data from IoTConnect. On receive of any of the command types form 0x10, 0x11, 0x12, 0x13, 0x15 should call sync again to update device meta data.
Step 5 Manage Device Twin Properties (Settings)
Azure IoT Hub provides meta data store called Device Twin. To update and get device twin, you need to consider additional topics as mentioned bellow
5.1 Get Device Twin
To get all whole device twin you need to publish blank message on $iothub/twin/GET/?$rid=0 topic, IoTConnect (iothub) will send whole device twin on $iothub/twin/res/# topic, so you need to subscribe $iothub/twin/res/# topic.
Typical json will look as bellow:
{ "desired": { "flow": 12, "speed": 10, "$version": 4 }, "reported": { "flow": "12", "$version": 2 } }
5.2 Receive Desired property change
On change of desired property for device, a message form IoTConnect (IotHub) will be published and you can receive it on $iothub/twin/PATCH/properties/desired/# topic. So, you need to subscribe to $iothub/twin/PATCH/properties/desired/# topic to receive desired value.
Typical json will look as bellow. I twill be simple json of key value
{ "speed": 10, "$version": 4 }
Note: Version will be auto increment done by IoTHub
5.3 Send Reported property update
Once you receive desired property update, you must send back your property update as reporting property back to IoTConnect (IoTHub). For this you have to send key-value base json to $iothub/twin/PATCH/properties/reported/?$rid=1 topic
Sample Json
{ "speed": 10 }
General Guideline and SDK Options
We suggest to have below options available to your SDK.
- Clean up resource: SDK should have method to disconnect existing mqtt connection clear all resources
- Change discovery url: SKD should have option to change the discovery url in order to avoid rebuild. There may be case discovery URL are different based on your instance. If there is change in default discovery url you can find from Key Vault
- Turn on Debug: SKD should have option to turn on debug, this will help you to capture additional log to troubleshoot the issue
- Internet check url: SDK should have option to change internet connectivity url, this will help in some region (like china) where google url is blocked
- Offline data: SDK should have option to save data to persistent storage in case of device is offline due to connectivity issue. Sending offline data needs to add additional tag “od”=1 in telemetry json
{ "cpId": "", "t": "", "mt": 0, "od": 1, .... ... ... }