EdgeX in Action, Part 3: Sending Commands and Events
This is the third article in series “EdgeX in Action”, and in this article we will see how to send commands to devices (downlink) and events from devices (uplink).
We at Mainflux are building one of the world’s first EdgeX-compliant IoT gateways called MFX-1. Our vision is producing end-to-end open-source IoT system — from the edge to the cloud — where fleets of MFX-1 EdgeX gateways are connected to Mainflux IoT cloud and managed via web applications.
In the second article, “EdgeX in Action, Part 2: Provisioning”, we have covered the system provisioning. Now you should have your system configured and ready to send some commands and receive some events.
There are 2 kinds of messages in EdgeX:
- Commands — downlink messages, EdgeX -> device. Commands can be of type
PUT
(push data to device) orGET
(issue the read command and get data from device). They can be observed similar to CoAP protocol, where device is a small server with internal resources, and application doesGET
to get a reading from device (just that in the case of EdgeX there is aDevice Service
in betweenCore Data
and aDevice
, andDevice Service
is a full-blown HTTP server). - Events — uplink messages, device -> EdgeX
Typically events will be sent by sensors, as a result of some measurement readings (for example temperature readings), and commands will be issued from applications (either from a cloud or on the EdgeX itself).
Events
We’ll start with Events, as those are easier to figure out. Events are sent from the devices towards EdgeX, asynchronously.
Let’s create a few events, i.e. simulate requests that would be sent by Device Service
to the Core Service
:
We can check that we have really sent these events:
drasko@Marx:~$ curl http://localhost:48080/api/v1/event/count
2
To retrieve these 2 last events:
drasko@Marx:~$ curl -sS http://localhost:48080/api/v1/event/device/countcamera1/2 | jsonpp
[
{
"id": "5b8aeaaa6b950a5e3b2b6d5e",
"pushed": 0,
"device": "countcamera1",
"created": 1535830698712,
"modified": 0,
"origin": 0,
"schedule": null,
"event": null,
"readings": [
{
"id": "5b8aeaaa6b950a5e3b2b6d5f",
"pushed": 0,
"created": 1535830698712,
"origin": 0,
"modified": 0,
"device": "countcamera1",
"name": "humancount",
"value": "5"
},
{
"id": "5b8aeaaa6b950a5e3b2b6d60",
"pushed": 0,
"created": 1535830698712,
"origin": 0,
"modified": 0,
"device": "countcamera1",
"name": "caninecount",
"value": "3"
}
]
},
{
"id": "5b8aeb3d6b950a5e3b2b6d61",
"pushed": 0,
"device": "countcamera1",
"created": 1535830845051,
"modified": 0,
"origin": 1471806386919,
"schedule": null,
"event": null,
"readings": [
{
"id": "5b8aeb3d6b950a5e3b2b6d62",
"pushed": 0,
"created": 1535830845051,
"origin": 1471806386919,
"modified": 0,
"device": "countcamera1",
"name": "humancount",
"value": "1"
},
{
"id": "5b8aeb3d6b950a5e3b2b6d63",
"pushed": 0,
"created": 1535830845051,
"origin": 1471806386919,
"modified": 0,
"device": "countcamera1",
"name": "caninecount",
"value": "0"
}
]
}
]
And to retrieve last 2 humancount
readings associated to the countcamera1
Device (i.e. — get readings by Value Descriptor
):
drasko@Marx:~$ curl -sS http://localhost:48080/api/v1/reading/name/humancount/2 | jsonpp
[
{
"id": "5b8aeaaa6b950a5e3b2b6d5f",
"pushed": 0,
"created": 1535830698712,
"origin": 0,
"modified": 0,
"device": "countcamera1",
"name": "humancount",
"value": "5"
},
{
"id": "5b8aeb3d6b950a5e3b2b6d62",
"pushed": 0,
"created": 1535830845051,
"origin": 1471806386919,
"modified": 0,
"device": "countcamera1",
"name": "humancount",
"value": "1"
}
]
Commands
Commands are sent from EdgeX towards connected devices, but there can be two types of commands:
PUT
— which is a push of data from EdgeX towards a deviceGET
— which is used to pull data from device
Issue:
curl -sS http://localhost:48082/api/v1/device/name/countcamera1 | jsonpp
and you will get a list of commands associated with this device:
The important filed here to note is "url"
. You will notice that it is formatted in the following pattern:
http://localhost:48082/api/v1/device/<device_id>/command/<cmd_id>
In order to send a particular command to the particular device — in this case ScanDepth
command to a device countcamera1
, send a following reqest:
In the log on the STDOUT
you should see something like:
INFO: 2018/09/05 02:56:39 Issuing PUT command to: http://172.17.0.1:49977/api/v1/devices/5b8ae4da6b950a5e3c029f6f/scandepth
Note that
172.17.0.1:49977
is an URL thatDevice Service
left when it was calling theCore Data
to create anAddressable
(and we simulated this by executingPOST
tohttp://localhost:48081/api/v1/addressable
in our previous article, “EdgeX in Action, Part 2: Provisioning”).
However, we are currently not running Device Service
service (there is not yet one written in Go), so this request end up with an error:
ERROR: 2018/09/05 02:56:39 Put http://172.17.0.1:49977/api/v1/devices/5b8ae4da6b950a5e3c029f6f/scandepth: dial tcp 172.17.0.1:49977: connect: connection refused
Additionally, if we query core-command
logs, we will observe that the PUT
command was sent:
drasko@Marx:~/go/src/github.com/edgexfoundry/edgex-go$ curl -sS http://localhost:48061/api/v1/logs/logLevels/INFO/originServices/edgex-core-command/0/9000000000000/100 | jsonpp
[
{
"logLevel": "INFO",
"labels": [],
"originService": "edgex-core-command",
"message": "Starting edgex-core-command 0.7.0 ",
"created": 1536194913239
},
{
"logLevel": "INFO",
"labels": [],
"originService": "edgex-core-command",
"message": "Service dependencies resolved...",
"created": 1536194913241
},
{
"logLevel": "INFO",
"labels": [
""
],
"originService": "edgex-core-command",
"message": "This is the Core Command Micro Service",
"created": 1536194913241
},
{
"logLevel": "INFO",
"labels": [
""
],
"originService": "edgex-core-command",
"message": "Service started in: 445.838µs",
"created": 1536194913240
},
{
"logLevel": "INFO",
"labels": [
""
],
"originService": "edgex-core-command",
"message": "Listening on port: 48082",
"created": 1536194913241
},
{
"logLevel": "INFO",
"labels": [],
"originService": "edgex-core-command",
"message": "Issuing PUT command to: http://172.17.0.1:49977/api/v1/devices/5b8ae4da6b950a5e3c029f6f/scandepth",
"created": 1536194918406
}
]
Note that for this remote logging to be enabled, you need to put
EnableRemoteLogging = true
in the config file of thecore-command
service (incmd/core-command/res/configuration.toml
).
For now what is important for us is just to see the flow and understand how services communicate. Once we have device service installed, it will receive the command and forward it to device via appropriate protocol (we usually have one device service per protocol — mqtt
, coap
, modbus
, 6lowpan
, and so on).
That’s all I have for you today. In the next article, “EdgeX in Action, Part 4: Exporting Data”, we’ll look how to send this data from an EdgeX gateway to a remote server in the cloud using EdgeX Export Services. Stay tuned.
To learn more about Mainflux and how we’re building the world’s most sophisticated open-source Industrial IoT cloud, visit our website and follow us on Twitter!