Using IoT-Ignite MQTT Client Library
MQ Telemetry Transport, or MQTT, is a messaging protocol that is gaining popularity as a solution to connect low-powered devices. Although MQTT was originally designed for communications based on the pub/sub architecture, it can be used as a general-purpose “machine-to-machine” (M2M) communication protocol.
For the ease of use, we developed MQTT Client Library that you can use it on your projects. Since it’s open source you can develop your own client too. IoT-Ignite MQTT Client library and sample usage source codes are available on Github. Clone library from Github and open it with your favorite editor. The library includes 4 projects. These projects are:
- mqtt-client-wrapper: MQTT core connection library, this library provides connection to IoT Ignite Platform.
- sensor-agent: MQTT sample agent for getting sensor values from internal or external components.
- content-agent: Another MQTT sample agent for downloading contents which provided by IoT Ignite Platform.
- linux-wrapper: The executable project which runs projects above. To create your own MQTT client you can start modifying from this project.
We have a tutorial for using this library: Using IoT-Ignite MQTT Client
mqtt-client-wrapper
The core library of IoT Ignite Platform MQTT client. This library initiates sessions publishes messages to IoT Ignite and gets responses from the IoT-Ignite cloud. There are 3 services in this library:
- SessionService: This service manages a session with given credentials. It can initiate, recover and destroy sessions.
- CloudMessageService: This service works as a message router. It catches all messages from the cloud and sends them to registered agents. If an agent wants to listen to a specific type of message from the cloud it should register to this service when initiated with method addListener or if an agent wants to listen to the response of its published messages it should register to this service with addResponseListener with the topic wanted to listen.
- MessagePublisherService: This service deals with publishing client messages. There are 3 methods for sending a message to the platform.
- publishLevel2Response: Publishes response message to notify platform whether sent message routed to a proper agent or not. This method will be called automatically after message routed to a proper agent by CloudMessageService.
- publishLevel3Message: Response message to notify platform whether requested operation was done successfully or not. This method should be called by an agent after operation with the result. Optionally detailed response can be sent.
- publishMessage: This method will be used for sending data to Platform services. In this example, we will use it for sending sensor data.
IoT Ignite Platform Topic Structure
IoT Ignite Platform MQTT broker uses 2 topic structure for all messaging between client and broker and all topics are private for a single client. No other client can subscribe to another clients topic. Topic structures are:
- {deviceId}/subscribe/EXAMPLE_TOPIC
- {devıceId}/publish/EXAMPLE_TOPIC
Every topic involves one-way communication. Subscribe topics are for getting data from IoT Ignite platform to Client, Publish topics are for sending data from the client to IoT Ignite Platform. When the session initiated MQTT Broker of IoT Ignite Platform automatically subscribes client to all of its topics so no need to subscribe each topic from the client side. Also since topic names always start with {deviceId}/subscribe and {deviceId}/publish, agents don’t need to specify this part of topics when communicating with Platform.
Providing Sensor Inventory
Each client should provide its sensor inventory at least once to the IoT Ignite Platform. Providing inventory enables the platform to display sensor data in the dashboard. Sensor Inventory message format is given below:
{
"data": [
{
"nodeId": {NodeId},
"things": [
{
"id": {SensorId},
"dataType": {INTEGER|FLOAT|STRING},
"vendor": VENDOR_NAME,
"actuator": {true|false},
"type": SENSOR_TYPE
}
]
}
]
}
Node is a physical or virtual device that can have sensors and actuators on it. A client can have multiple nodes that have sensors and actuators. Nodes should be specified in “data” array with “nodeId” and “things” array.
- “things” array includes all sensors and actuators of a node. Sensors are physical or virtual data collectors and actuators are things that can do operations according to input from platform or client itself.
- “id” of a sensor is unique for both node and client. It can be anything meaningful for users who will use sensor value.
- “dataType” indicates the data type of the sensor’s generated data.
- “vendor” is an informational label for users. It can be the name of the manufacturer of a sensor.
- “actuator” is a boolean value that indicates if this thing is a sensor or actuator. For sensors it is false.
- “type” is sensors or actuators common type. (Ex: Temperature Sensor, GPS, etc.)
Example Inventory message for a single node and single sensor device is given below:
{
"data":[
{
"nodeId": "Built-in Sensors",
"things": [
{
"id": "RoomTemperature",
"dataType": "INTEGER",
"vendor": "ARDIC",
"actuator": false,
"type": "Temperature"
}
]
}
]
}
In this example Device has only one node named Built-in Sensors, On this node, there is a Temperature sensor made by ARDIC named RoomTemperature which sends INTEGER data. Since it is a sensor, not an actuator, actuator value is false.
Inventory message should be published to topic “{deviceId}/publish/DeviceProfile/Status/DeviceNodeInventory”. When sensor inventory message published, it deletes all of its previous sensors (if exist) and rewrites all inventory. Sensors’ historical data will not be deleted but they cannot be accessed by APIs or Dashboard. If agent should send Sensor Inventory it must be assured that all sensors are in the Sensor Inventory Message before sending.
Publishing Node and Sensor Connection Statuses
Nodes’ and sensors’ connection statuses should be provided from the device. Sensor connection statuses are shown as “Unknown” until connection status message provided. This message named as “DeviceNodePresence”. Device Node Presence message format is given below:
{
"data":[
{
"nodeId": {NodeId},
"descrtiption":NODE_SENSOR_DESCRIPTION,
"connected":{1|0}
},
{
"nodeId": {NodeId},
"thingId": {SensorId},
"descrtiption":NODE_SENSOR_DESCRIPTION,
"connected":{1|0}
}
]
}
In presence message, each node and sensor connection status should be given separately. “DeviceNodePresence” messages parameters defined as:
- nodeId: Node Unique Id
- thingId: Sensor Unique Id
- description: Human readable identifier or description of node or sensor. (Optional)
- connected: Connection status of node or sensor. 1: online, 0: offline
Example DeviceNodePresence message given below:
{
"data":[
{
"nodeId": "Built-in Sensors",
"descrtiption": "OnBoard Sensors Node",
"connected":1
},
{
"nodeId": "Built-in Sensors",
"thingId": "RoomTemperature",
"descrtiption":"Room Temperature Sensor"
"connected":1
}
]
}
This example is the compatible example with the Inventory message given in the previous title.
This message should be published to topic “{deviceId}/publish/DeviceProfile/Status/DeviceNodePresence”. After publishing connection statuses you can see sensor and node statuses as “Online” on Devzone Dashboard.
Dealing With Sensor Data
MQTT Client should send its sensor data to the topic: {deviceId}/publish/DeviceProfile/{nodeId}/{sensorId}. IoT Ignite MQTT Broker writes the response of this call to {deviceId}/subscribe/DeviceProfile/{nodeId}/{sensorId} topic. MQTT Client library automatically deals with {deviceId}/publish and {deviceId}/subscribe parts so in this project we will only deal with “DeviceProfile/{nodeId}/{sensorId}”.
nodeId and sensorId are unique keys to identify our sensor. You can use anything for these IDs but be sure to use same identity values every time sending data from the same sensor.
IoT Ignite services are working with JSON format. Sensor data message format is given below:
{
"data":{
"sensorData":[
{
"date":TIME_IN_EPOCH_TIME_FORMAT,
"values":[value1,value2,...,valuen]
},
{
"date":TIME_IN_EPOCH_TIME_FORMAT,
"values":[value1,value2,...,valuen]
}
]
}
}
More than one measurement value can be sent in one message. For example, if measurement rate is 2 seconds, you can send 30 value in one message for each minute. In this case, you can save bandwidth. IoT Ignite platform supports sensor values more than 1 dimension. If you want to save GPS coordinates value should look like [longitude, latitude, altitude] or for temperature value it is only [temperatureInCelcius].