Every device that runs the library holds an instance of MiletusDevice.
Traits are loaded from a JSON description. The user has to load a provider instance to the libMiletus instance. The user also loads one or more instances of communication interfaces. A list containing the name of traits is used to “load” a new component.
Components are abstractions to hold a set of one or more Traits.
A Trait describes specific characteristics from modules of the device.
Traits have Commands, exposing procedures that can be invoked. This commands can have arguments, that is passed as a parameter.
Each parameter has a name and a set of properties like type, range.
Traits also have States, which is described on the trait JSON. This description contains the type of the value and can include the range of possible values. Components expose the current value of a State.
Exemplifying an air conditioning system that contains a display. For this device we have the components:
The control Component holds the Trait onOff and temperature. The environment Component has temperature and humidity as Traits. The display Component has Traits for brightness, contrast, and also has the Trait onOff
For example, the Trait temperature of the Component control has Commands to increase, decrease, and set a specific temperature. The State of this Trait exposes the current set temperature.
An abstract example of the device is represented in JSON format bellow.
{
"Device": {
"AirConditioning": {
"components": {
"Control": {
"traits": {
"onOff": {
"commands": {
"onOff": {}
},
"states": {
"isTurnedOn": {
"type": "boolean",
"currentValue": true
}
}
},
"temperature": {
"commands": {
"setTemperature": {
"parameters": {
"temperature": {
"type": "number",
"maximum": 30,
"minimum": 17
}
}
},
"increaseTemperature": {},
"decreaseTemperature": {}
},
"states": {
"temperature": {
"unity": "celsius",
"type": "number",
"maximum": 30,
"minimum": 17,
"currentValue": 23
}
}
}
}
},
"Environment": {
"traits": {
"temperature": {
"states": {
"temperature": {
"unity": "celsius",
"type": "number",
"maximum": 30,
"minimum": 17,
"currentValue": 23
}
}
},
"humidity": {
"states": {
"humidity": {
"unity": "percentage",
"type": "number",
"maximum": 100,
"minimum": 0,
"currentValue": 58
}
}
},
"lightness": {
"state": {
"lightness": {
"unity": "lux",
"type": "number",
"maximum": 20000,
"minimum": 0.0001,
"currentValue": 348.57
}
}
}
}
},
"Display": {
"traits": {
"onOff": {
"commands": {
"onOff": {}
},
"states": {
"isTurnedOn": {
"type": "boolean",
"currentValue": true
}
}
},
"brightness": {
"commands": {
"setBrilightness": {
"parameters": {
"brightness": {
"type": "number",
"maximum": 100,
"minimum": 0
}
}
}
},
"states": {
"brightness": {
"unity": "percentage",
"type": "number",
"maximum": 100,
"minimum": 0,
"currentValue": 50
}
}
},
"contrast": {
"commands": {
"setContrast": {
"parameters": {
"brightness": {
"type": "number",
"maximum": 100,
"minimum": 0
}
}
}
},
"states": {
"contrast": {
"unity": "percentage",
"type": "number",
"maximum": 100,
"minimum": 0,
"currentValue": 50
}
}
}
}
}
}
}
}
}
All information from the device is retrieved as from requests.
An overview information about the device connection capabilities is retrieved by the request info.
In Linux/Unix, you can use the command curl in the IP of the device to retrieve this information.
curl 192.168.0.11/info
The response comes in the JSON format. An example is shown below.
{
"Id": "1c9c1b5d",
"Name": "Example_Device",
"Description": "",
"ModelManifestId": "LIBMI"
}
All of the descriptions of device capabilities is exposed by traits. The traits can be retrieved in the same form as was described in the device. Using this information you can know information about the device states, retrieved in a component request or execute a command.
curl 192.168.0.11/traits
{
"fingerprint": 135246,
"traits": {
"room": {
"commands": {
"onOff": {
"parameters": {
"lightparam": {
"type": "boolean"
}
}
}
},
"state": {
"light": {
"isRequired": true,
"type": "boolean"
},
"temperature": {
"isRequired": true,
"type": "number"
},
"humidity": {
"isRequired": true,
"type": "number"
}
}
}
}
}
curl 192.168.0.11/components
{
"fingerprint": 135246,
"components": {
"RoomA": {
"traits": [
"room"
],
"state": {
"room": {
"light": true,
"temperature": 25,
"humidity": 33
}
}
}
}
}
curl -H "Content-Type: application/json" -X POST -d
'{"name":"room.onOff","component":"RoomA","parameters":{"lightparam":true}}'
192.168.0.11/commands/execute
{
"state": "done",
"results": {
"actualBrilightness": 48
}
}
{
"state": "error",
"error": {
"code": "invalidBrilightness"
}
}
Traits, Info, and Components are retained in the broker. Its values are published at the startup of the device and on each update.
A message from the IoT device to the client is published in the "out" subtopic. At the opposite way, it is published in "in" subtopic.
In each subtopic is published a command or a status always complaining the libMiletus JSON format.
(The scratches mean that they have not yet been implemented)
DeviceID/{in/out}/commands/execute
DeviceID/{in/out}/commands/status
DeviceID/{in/out}/commands/list
DeviceID/{in/out}/commands/cancel
DeviceID/{out}/traits
DeviceID/{out}/info
DeviceID/{out}/components
{
"Id": "Room_B",
"Name": "Room_B",
"Description": "Meeting room device",
"ModelManifestId": "LIBMI"
}
{
"fingerprint": "00000000",
"traits": {
"room": {
"commands": {
"onOff": {
"minimalRole": "user",
"parameters": {}
},
"sendTVCommand": {
"minimalRole": "user",
"parameters": {
"TVCommand": {
"type": "string",
"enum": [
"mute",
"onOff",
"up",
"down",
"right",
"left",
"ok",
"menu",
"source",
"exit",
"vol_up",
"vol_down"
]
}
}
}
},
"state": {
"lightness": {
"isRequired": true,
"type": "number"
},
"temperature": {
"isRequired": true,
"type": "number"
},
"humidity": {
"isRequired": true,
"type": "number"
}
}
}
}
}
{
"fingerprint": "00015FB3",
"components": {
"RoomB": {
"traits": [
"room"
],
"state": {
"room": {
"humidity": 44,
"lightness": 1.973048,
"temperature": 24
}
}
}
}
}
{
"component": "Room",
"name": "room.onOff",
"parameters": {}
}
{
"state": "done"
}
In the main screen menu, there is the option "MQTT Settings", that gives access to the two firsts screenshots below.
The first one shows the status "Not connected", and in the second one shows the status "Connection OK".
The third one show the dialog where you can add a device (to show it, just press the "+" in the red circle).
To add, just write the device name, that you can find it in the source code (macro DEVICE_NAME).
Info Command Communication (BLE only)
Source |
Packet |
Destination |
client |
length=0018B |
libMiletus |
client |
/info?offset=0018B |
libMiletus |
libMiletus |
length=1234B |
client |
libMiletus |
json={...}&offset=1234B |
client |
Execute Command Communication (BLE only)
Source |
Packet |
Destination |
client |
length=0107B |
libMiletus |
client |
/execute/command?application=json&value={...}&offset=0107B |
libMiletus |
libMiletus |
length=4321B |
client |
libMiletus |
json={...}&offset=4321B |
client |