Sending commands to devices in FIWARE Orion is not working - fiware

I am trying to provide a device on FIWARE and send commands. In my case, a lamp with commands ("on" and "off"). But, it's not working.
The steps to create a device and send command are:
Provide a device;
Create a service group;
Create a registration with commands;
Send a command.
I'm taking the fiware-tutorials following the steps, but don't work.
The code I have used was:
To create a device:
curl -iX POST \
'http://localhost:4041/iot/devices' \
-H 'Content-Type: application/json' \
-H 'fiware-service: openiot' \
-H 'fiware-servicepath: /' \
-d '{
"devices": [
{
"device_id": "lamp1",
"entity_name": "urn:ngsi-ld:Lamp:1",
"entity_type": "Lamp",
"protocol": "PDI-IoTA-UltraLight",
"transport": "HTTP",
"endpoint": "http://iot-sensors:3001/iot/lamp1",
"commands": [
{"name": "on","type": "command"},
{"name": "off","type": "command"}
],
"attributes": [
{"object_id": "s", "name": "state", "type":"Text"},
{"object_id": "l", "name": "luminosity", "type":"Integer"}
],
"static_attributes": [
{"name":"refStore", "type": "Relationship","value": "urn:ngsi-ld:Store:001"}
]
}
]
}
'
To create a service group:
curl -iX POST \
'http://localhost:4041/iot/services' \
-H 'Content-Type: application/json' \
-H 'fiware-service: openiot' \
-H 'fiware-servicepath: /' \
-d '{
"services": [
{
"apikey": "4jggokgpepnvsb2uv4s40d59ov",
"cbroker": "http://orion:1026",
"entity_type": "Thing",
"resource": "/iot/d"
}
]
}'
To create a registration for commands:
curl -iX POST \
'http://localhost:1026/v2/registrations' \
-H 'Content-Type: application/json' \
-H 'fiware-service: openiot' \
-H 'fiware-servicepath: /' \
-d '{
"description": "Lamp Commands",
"dataProvided": {
"entities": [
{
"id": "urn:ngsi-ld:Lamp:1","type": "Lamp"
}
],
"attrs": [ "on", "off" ]
},
"provider": {
"http": {"url": "http://orion:1026/v2"},
"legacyForwarding": true
}
}'
To send a "on" command:
curl -iX PATCH \
'http://localhost:1026/v2/entities/urn:ngsi-ld:Lamp:1/attrs' \
-H 'Content-Type: application/json' \
-H 'fiware-service: openiot' \
-H 'fiware-servicepath: /' \
-d '{
"on": {
"type" : "command",
"value" : ""
}
}'
Doing a HTTP get request to retrieve the entity:
curl -G -X GET \
'http://localhost:1026/v2/entities/urn:ngsi-ld:Lamp:1' \
-d 'type=Lamp' \
-d 'options=keyValues' \
-H 'fiware-service: openiot' \
-H 'fiware-servicepath: /'
I expect a output like:
{
"id": "urn:ngsi-ld:Lamp:001",
"type": "Lamp",
"TimeInstant": "2019-08-28T13:33:51.00Z",
"luminosity": "1115",
"off_info": " ",
"off_status": "UNKNOWN",
"on_info": " on OK",
"on_status": "OK",
"refStore": "urn:ngsi-ld:Store:001",
"state": "ON",
"on": "",
"off": ""
}
but I receive this:
{
"id": "urn:ngsi-ld:Lamp:1",
"type": "Lamp",
"TimeInstant": "2019-08-28T12:50:22.00Z",
"luminosity": " ",
"off_info": " ",
"off_status": "UNKNOWN",
"on_info": "There was an error in the response of a device to a command [404]: on NOT OK",
"on_status": "ERROR",
"refStore": "urn:ngsi-ld:Store:001",
"state": " ",
"on": "",
"off": ""
}

Assuming you are using the FIWARE Tutorial Dummy devices, then your provisioning steps are correct and the error message received (404) indicates that lamp1 is not responding to your command when sent.
When you are provisioning the device
"device_id": "lamp1",
"entity_name": "urn:ngsi-ld:Lamp:1",
"endpoint": "http://iot-sensors:3001/iot/lamp1",
You are stating that:
There exists a device (lamp1)
The device has an entity name in Orion (urn:ngsi-ld:Lamp:1)
The device is able to respond to commands on the url shown (http://iot-sensors:3001/iot/lamp1)
The final statement is incorrect.
The context-provider code sets up 4 dummy lamps:
lamp001
lamp002
lamp003
lamp004
But no lamp1 - therefore when an HTTP POST request is sent to http://iot-sensors:3001/iot/lamp1 the response is a 404 Not Found - which is correctly defined in your entity state in Orion.
BTW, #fgalan is entirely correct in stating that the registration is no longer necessary with more modern versions of the IoT Agents - it has been left in the tutorial purely for backwards compatibility with older versions.

Related

Events and actions in Fiware NGSI entities

Let assume we have an entity corresponding to an IoT controller device, let say a door controller.
We want to define an event that could cause an action (open/close). So we need to send a command to this device.
How would we make this happen? Add an attribute in the entity like for example setDoorStatus that can be written to via the NGSI API? And then have some IoT agent or command handler subscribe to this attribute?
Is there any example of a Data Model where this is done?
The easiest way to do this is to provision a device using any IoT Agent. IoT Agents have a standard API for device provisioning, where commands can be listed:
curl -L -X POST 'http://localhost:4041/iot/devices' \
-H 'fiware-service: openiot' \
-H 'fiware-servicepath: /' \
-H 'Content-Type: application/json' \
--data-raw '{
"devices": [
{
"device_id": "door001",
"entity_name": "urn:ngsi-ld:Door:001",
"entity_type": "Door",
"protocol": "PDI-IoTA-UltraLight",
"transport": "HTTP",
"endpoint": "http://context-provider:3001/iot/door001",
"commands": [
{"name": "unlock","type": "command"},
{"name": "open","type": "command"},
{"name": "close","type": "command"},
{"name": "lock","type": "command"}
],
"attributes": [
{"object_id": "s", "name": "state", "type":"Text"}
],
"static_attributes": [
{"name":"refStore", "type": "Relationship","value": "urn:ngsi-ld:Store:001"}
]
}
]
}
'
The IoT Agent node library defines a command paradigm for actuating devices through commands
In this case you have an attribute open which is registered on a context broker as coming from a device and you can actuate the device using the following request:
NGSI-v2
curl -L -X PATCH 'http://localhost:1026/v2/entities/urn:ngsi-ld:Door:001/attrs' \
-H 'fiware-service: openiot' \
-H 'fiware-servicepath: /' \
-H 'Content-Type: application/json' \
--data-raw '{
"open": {
"type" : "command",
"value" : ""
}
}'
NSGI-LD
curl -L -X PATCH 'http://localhost:4041/ngsi-ld/v1/entities/urn:ngsi-ld:Device:door001/attrs/open' \
-H 'NGSILD-Tenant: openiot' \
-H 'NGSILD-Path: /' \
-H 'Content-Type: application/json' \
-H 'Link: <http://context/ngsi-context.jsonld>; rel="http://www.w3.org/ns/json-ld#context"; type="application/ld+json"' \
--data-raw '{
"type": "Property",
"value": ""
}'
The relevant IoT Agent accepts the request and passes it down to the device using the appropriate device syntax. Once activated, additional special status and info attributes are added to the entity as soon as it has any information of the command progress.
Full examples can be found within the FIWARE Tutorials:
NGSI-v2
NGSI-LD

Context broker is ignoring value, fiware orion and iotagent

orion version : 2.3.0
iotagent-ul version : 1.12.0
I am using fiware and iotagent over mqtt. I want to send commands to some devices with different values. I have followed https://github.com/FIWARE/tutorials.IoT-over-MQTT and read some documentation.
After provisionning a service group (with apikey: 123456) and an actuator, I can send commands with values by following the iota URL :
curl -iX POST \
'http://localhost:4041/iot/devices' \
-H 'Content-Type: application/json' \
-H 'fiware-service: openiot' \
-H 'fiware-servicepath: /' \
-d '{
"devices": [
{
"device_id": "dev001",
"entity_name": "urn:ngsi-ld:Device:001",
"entity_type": "Device",
"protocol": "PDI-IoTA-UltraLight",
"transport": "MQTT",
"commands": [
{"name": "date","type": "command", "value": {"hour": 9, "minute": 31, "second": 0}}
]
}
]
}
'
iota publish a mqtt message to : /123456/dev001/cmd with payload dev001#date|hour=9|minute=31|second=0
But when using the context broker, the value is ignored :
curl -iX PATCH \
'http://localhost:1026/v2/entities/urn:ngsi-ld:Device:001/attrs' \
-H 'Content-Type: application/json' \
-H 'fiware-service: openiot' \
-H 'fiware-servicepath: /' \
-d '{
"date": {
"type" : "command",
"value" : {"hour": 9, "minute": 31, "second": 0}
}
}'
Here, iota publish a mqtt message to : /123456/dev001/cmd with payload dev001#date|
Why is it ignored ? Am I doing somthing wrong ?
sorry for my poor english.
I found a solution... adding the type in the url make the context take account of the value... weird.
The final url must be :
curl -iX PATCH \
'http://localhost:1026/v2/entities/urn:ngsi-ld:Device:001/attrs?type=Device' \
-H 'Content-Type: application/json' \
-H 'fiware-service: openiot' \
-H 'fiware-servicepath: /' \
-d '{
"date": {
"type" : "command",
"value" : {"hour": 9, "minute": 31, "second": 0}
}
}'
EDIT:
knowing the solution, I have tried to understand the problem and found this issue : https://github.com/telefonicaid/fiware-orion/issues/3647
According to CPrs and request forwarding documentation
On forwarding, any type of entity in the NGSIv2 update/query matches
registrations without entity type. However, the opposite doesn't work,
so if you have registrations with types, then you must use ?type in
NGSIv2 update/query in order to obtain a match. Otherwise you may
encounter problems, like the one described in this post at
StackOverflow.
EDIT 2:
This is a duplicate of : Orion CB doesn't update lazy attributes on IoT Agent

Provision device with JSON/MQTT IOT AGENT FIWARE

curl -X POST -vv -H "Fiware-Service: myHome" -H "Fiware-ServicePath: /environment" -H "Content-Type: application/json" -H "Cache-Control: no-cache" -d '{
"devices": [
{
"device_id": "0000000000000000",
"entity_name": "BedRoomSensor",
"entity_type": "multiSensor",
"attributes": [
{ "object_id": "t", "name": "Temperature", "type": "celsius" },
{ "object_id": "h", "name": "Humidity", "type": "degrees" }
]
}
]
} 'http://localhost:4041/iot/devices'
I execute the above curl commmand in order to provision my device.However it doesn't show anything and the command never ends.
What i missunderstood?
I have solved the problem following the first two steps of this guide:http://fiwaretourguide.readthedocs.io/en/latest/connection-to-the-internet-of-things/how-to-read-measures-captured-from-iot-devices/
In the step-by-step guide these steps weren't described.
In the second step i change the protocol fielde as "MQTT".
Now whenever i request the measures from my device i take the correct value.

curl with json array

The first command works and the second doesn't. What do I need to change to allow the json array to work? Thank you in advance.
command #1:
curl -d '{"uid":"TEST", "object":"TEST"}' \
-H "Content-Type: application/json" \
-X POST http://WEBSERVER/api/v1/inventory
command #2
curl -d '{"uid":"TEST","object":["server1", "server2", "server3"]}' \
-H "Content-Type: application/json" \
-X POST http://WEBSERVER/api/v1/inventory
Your curl syntax is fine, you could test by using httpbin.org, for example:
$ curl -d '{"uid":"TEST","object":["server1", "server2", "server3"]}' \
-H "Content-Type: application/json" \
-X POST http://httpbin.org/post
Returns:
{
"args": {},
"data": "{\"uid\":\"TEST\",\"object\":[\"server1\", \"server2\", \"server3\"]}",
"files": {},
"form": {},
"headers": {
"Accept": "*/*",
"Connection": "close",
"Content-Length": "57",
"Content-Type": "application/json",
"Host": "httpbin.org",
"User-Agent": "curl/7.54.0"
},
"json": {
"object": [
"server1",
"server2",
"server3"
],
"uid": "TEST"
},
"origin": "x.x.x.x",
"url": "http://httpbin.org/post"
}
You indeed could pipe the result and verify the output with your input:
$ curl -d '{"uid":"TEST","object":["server1", "server2", "server3"]}' \
-H "Content-Type: application/json" \
-X POST http://httpbin.org/post -s | jq -r '.data'
It will print:
{"uid":"TEST","object":["server1", "server2", "server3"]}
Probably the server you are using to post data don't accept your request, check the returned status code, could give a clue, maybe is a 400 (bad request) or a 406 (not acceptable) etc, just in case here is a list of possible status codes.

Why this orion subscription don't works as I want?

I have the following subscription in orion 1.2.1:
curl --include \
--header 'Content-Type: application/json' \
--request POST \
--data-binary '{
"description": "subscription",
"subject": {
"entities": [
{
"idPattern": "event-.*",
"type": "Event"
}
],
"condition": {
"attrs": [
"IdEvent",
"mFlag"
],
"expression": {
"q": "mFlag>0"
}
}
},
"notification": {
"attrsFormat":"legacy",
"http": {
"url" : "http://localhost:5050/notify"
},
"attrs": [
"IdEvent"
]
}
}' \
'http://localhost:1026/v2/subscriptions'
When I send an entity update like this one:
curl --include \
--request PATCH \
--header "Content-Type: application/json" \
--data-binary '{
"mFlag":{
"value":"5",
"type":"int"
}
}' \
'http://localhost:1026/v2/entities/event-2/attrs'
Orion is not notifiying and it is making me crazy don't know what is wrong. Any idea?
When I remove this part of the subscription:
"expression": {
"q": "mFlag>0"
}
it works but I need it to notify when any attribute is changed and the condition is satisfied.
Note that in NGSIv2 "5" is a string, not a number. Thus, in order to make the "q": "mFlag>0" filter works as expected, use the following update:
curl --include \
--request PATCH \
--header "Content-Type: application/json" \
--data-binary '{
"mFlag":{
"value":5,
"type":"int"
}
}' \
'http://localhost:1026/v2/entities/event-2/attrs'