Modify attribute on device by IOT-Agent Json - fiware

I am using IOT-agent JSON with MQTT binding
I have a sensor-actuator registered in orion using iot-agent and I created the subscription.
If a third party application modifies a sensor value, orion must send iot-agent information and iot-agent to the device.
for example, if I have 3 attributes inside the sensor and one of them controls a valve.
In orion that attribute is true or false.
if the attribute is modified in orion must be sent to iot-agent and iot-agent to the device to close or open the valve.
extra information:
The software is two component of Fiware Generic Enable.
iot-agent JSON: https://github.com/telefonicaid/iotagent-json
Fiware-orionCB: https://github.com/telefonicaid/fiware-orion
Is it possible?

There is no official tutorial connecting the JSON IoT Agent to a device over MQTT, but a very similar one exists for the Ultralight IoT Agent
IoT Devices are either:
sensors - reading measurements from the real world
actuators - altering the state of the world
or both
Your issue here is that you cannot get Orion to update the attribute/state of a sensor directly. The attributes of the entity in the Context Broker represent the incoming state of the sensor - i.e. the measurements from that sensor.
For example for the sensor reading the state of a valve it could be "open: "true"
In order to update an actuator, you will need to send a command, rather than alter the value.
You should set up the command when provisioning the device (it is assumed you have a service already):
curl -iX POST \
'http://localhost:4041/iot/devices' \
-H 'Content-Type: application/json' \
-H 'fiware-service: openiot' \
-H 'fiware-servicepath: /' \
-d '{
"devices": [
{
"device_id": "bell001",
"entity_name": "urn:ngsi-ld:Bell:001",
"entity_type": "Bell",
"protocol": "PDI-IoTA-UltraLight",
"transport": "MQTT",
"commands": [
{ "name": "ring", "type": "command" }
],
"static_attributes": [
{"name":"refStore", "type": "Relationship","value": "urn:ngsi-ld:Store:001"}
]
}
]
}
'
You can then send the command to do something (like ring a bell, open a valve etc.) by altering the state of the command attribute.
curl -iX PATCH \
'http://localhost:1026/v2/entities/urn:ngsi-ld:Bell:001/attrs' \
-H 'Content-Type: application/json' \
-H 'fiware-service: openiot' \
-H 'fiware-servicepath: /' \
-d '{
"ring": {
"type" : "command",
"value" : ""
}
}'
Depending upon how you have provisioned devices, you may also need to register the command - though this may not be necessary.

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

Cannot register commands in IoT Agent Fiware

I'm using IoT Agent with Ultralight run directly (not as a dockerized component). I'm able to register new device, which is mapped in Orion Context Broker. However I have an issue with registering Actuators which require commands within configuration data. I use:
curl -iX POST \
'http://MYIP:4061/iot/devices' \
-H 'Content-Type: application/json' \
-H 'fiware-service: openiot' \
-H 'fiware-servicepath: /' \
-d '{
"devices": [
{
"device_id": "lamp003",
"entity_name": "urn:ngsi-ld:Lamp:003",
"entity_type": "Lamp",
"protocol": "PDI-IoTA-UltraLight",
"transport": "MQTT",
"commands": [
{"name": "on","type": "command"},
{"name": "off","type": "command"}
]}
]
}
And in response I'm hit with:
op=IoTAgentNGSI.DeviceProvisioning | from=n/a | srv=n/a | subsrv=n/a |
msg=Device provisioning failed due to the following error: |
comp=IoTAgent Request error connecting to the Context Broker:
{"code":"400","reasonPhrase":"Bad Request","details":"missing isDomain
value for registration attribute"}
I tried adding "isDomain": "false" to elements of command table, but no luck. It used to work before and furthermore similar solution is presented on official guide.
isDomain part of the deprecated NGSI-v1 syntax. It is not used in NGSI-v2 or NGSI-LD
I think you may be running the IoT Agent as NGSI-v1. You'll need to set contextBroker.ngsiVersion in your config.js or set the following Env variable in Docker or Docker-compose.
IOTA_CB_NGSI_VERSION=v2
config.js
{
host: '192.168.56.101',
port: '1026',
ngsiVersion: 'v2'
}

FIWARE Orion, NGSIv2 subscription in attributes with structured values

I'm working with Orion Contex Broker and I need to receive notifications when a parameter in a structured attribute changes its value. An example:
Subscription:
curl -iX POST \
--url 'http://localhost:1026/v2/subscriptions' \
--header 'content-type: application/json' \
--data '{
"description":"Notify me of Store changes in street Address",
"subject":{
"entities":[
{
"idPattern":".*",
"type":"Store"
}
],
"condition":{
"attrs":[
"address.streetAddress"
]
}
},
"notification":{
"http":{
"url":"http://localhost:3000/subscription/store-change"
}
}
}'
Create entity:
curl -iX POST \
--url 'http://localhost:1026/v2/op/update' \
-H 'Content-Type: application/json' \
-d '{
"actionType":"append",
"entities":[
{
"type":"Store",
"id":"urn:ngsi-ld:Store:001",
"address":{
"type":"PostalAddress",
"value":{
"streetAddress":"Old",
"addressRegion":"Berlin"
}
},
"name":{
"type":"Text",
"value":"Bösebrücke Einkauf"
}
}
]
}'
Update the entity:
curl -iX PATCH \
--url 'http://localhost:1026/v2/entities/urn:ngsi-ld:Store:001/attrs' \
-H 'Content-Type: application/json' \
-d '{
"address":{
"type":"PostalAddress",
"value":{
"streetAddress":"Bornholmer"
}
}
}'
The expected result would be to receive a notification when the entity was created and update. Another possibility could be the "condition expressions". However one of kind: "q": "address.streetAddress!=${previousValue}" is not implemented yet.
Attributes within NGSI are usually numbers or strings - this typically leads to a very flat data model. In this case when the attribute value changes the subscription would be fired.
JSON objects (such as address above) are also supported, but the change occurs whenever the Object's value change and is not specifically bound to a sub attribute Hence
"attrs":[
"address.streetAddress"
]
Would need to be:
"attrs":[
"address"
]
However, the q parameter could be used to filter against a specific sub-attribute e.g. q=address.streetAddress!="Old" - and the listening interface could amend the subscription after it has fired.

FIWARE-IoT Agent: send command to device via MQTT

I am using the FIWARE IoT agent [1] to communicate with my devices using MQTT protocol, I create a command to be able to update my device value, Here is my request to create a device:
curl -X POST http://193.48.247.247:80/iot/devices \
-i \
-H "Content-Type: application/json" \
-H "Fiware-Service: egmsmartcity" \
-H "Fiware-ServicePath: /egmsmartcitypath" \
-d ' { "devices": [ { "device_id": "streetlight1",
"entity_name": "sensors:streetlight1",
"entity_type": "sensors",
"protocol": "PDI-IoTA-MQTT-UltraLight",
"timezone": "Europe/Paris",
"endpoint": "notUsed",
"commands": [{ "name": "streetlight1", "type": "command", "value": ""}] } ] }'
Since I am using MQTT, the filed endpoint is not used on my case but if I delete it the MQTT does not notify my device.
This request is working but is it the correct way to create a device to be able to send a command to my device via MQTT?
Thanks in advance for your help!
[1]https://github.com/telefonicaid/fiware-IoTAgent-Cplusplus
This field ("endpoint": "notUsed") comes from a previous functionality that is no longer implemented (it did not make sense in MQTT). Thus since recent versions onwards it is ignored and can be deleted. Perhaps you are using a previous version of the IoT Agent and this is why it is mandatory although not functional.
Thanks for using IDAS!

How I specify the Fiware-Service and Fiware-ServicePath fields at Orion that set the name of MySQL database and table in Cygnus?

So far I have configured ContextBroker to send data to Cygnus which in turn saves data by default names in database.
But what if I want to target a specific database with a specific table?
I know I have to set:
dbName=<fiware-service>
tableName=<fiware-servicePath>_<entityId>_<entityType>
I dont know where that file is, and I know it isnt in /etc/sysconfig/contextBroker because that folder doesnt exist.
EDIT1: here is my updatecontext:
(curl localhost:1026/NGSI10/updateContext -s -S --header 'Content-Type: application/json' --header 'Accept: application/json' --header 'Fiware-Service: FiwareDatabase' --header 'Fiware-ServicePath: /AllSensors' -d #- ) <<EOF
{
"contextElements": [
{
"type": "Television",
"isPattern": "false",
"id": "TV2",
"attributes": [
{
"name": "channel",
"type": "integer",
"value": "14"
},
{
"name": "volume",
"type": "float",
"value": "9"
}
]
}
],
"updateAction": "APPEND"
}
EOF
As I said the table does get automatically created but the database doesnt.
Fiware-Service and Fiware-ServicePath are set at entity creation time using HTTP headers in the entity creation REST request. Please have a look to the following sections in the Orion User Manual:
Service
Service path
UPDATE: for example, in order to create an entity in service "servA" and service path "/path1" you could use the example shown in the create entity section in the manual adding two additionals HTTP headers to the curl line:
(curl localhost:1026/v1/updateContext -s -S --header 'Content-Type: application/json' --header 'Accept: application/json' --header 'Fiware-Service: servA' --header 'Fiware-ServicePath: /path1' -d #- | python -mjson.tool) <<EOF
...
That would make to insert information in the following MySQL database/table (assuming that Cygnus is well configured, subscriptions are correct, etc.):
dbName=servA
tableName=path1_<entityId>_<entityType>
Note that the default behaviour is to store the information for each entity in a different table. That default behaviour can be changed, but if you are interested in that possibility, please create a new question in StackOverflow for dealing with that.