FIWARE-IoT Agent: send command to device via MQTT - fiware

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!

Related

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'
}

Can we used google drive's 'watch' API for polling data? How can we use 'watch' API to track changes?

I am using changes API to track my G-Drive changes, but it's not giving the complete resource data. Can I use 'watch' API to poll my resources?
Below is my request for changes API:
curl -X GET \
'https://www.googleapis.com/drive/v3/changes?pageToken=46' \
-H 'Accept: */*' \
-H 'Accept-Encoding: gzip, deflate' \
-H 'Authorization: Bearer <Token>' \
Here's the response:
"changes": [
{
"kind": "drive#change",
"type": "file",
"changeType": "file",
"time": "2019-10-10T09:15:12.313Z",
"removed": false,
"fileId": "<File_ID>",
"file": {
"kind": "drive#file",
"id": "<File_ID>",
"name": "shared",
"mimeType": "application/vnd.google-apps.folder"
}
}
]
But using this, I cannot decide the file is created or updated..
When you get a Changes resource, the response has a specific format.
You can see that the Changes has the property file that is of type Files.
What you want to do is inspect the Files resource returned by the change to monitor the state of the file between changes.
Hope this helps!

Method Not Allowed when patching registration

Recently some registrations of commands expired so I am trying to patch their "expires" attribute. However, I receive a 405 method not allowed message error.
Retrieving info about the registration:
curl -X GET \
http://localhost:1026/v2/registrations/5d3ff3e2ab1e270d7775a7bf \
-H 'Accept: application/json'
{
"id": "5d3ff3e2ab1e270d7775a7bf",
"expires": "2019-08-29T07:38:10.00Z",
"dataProvided": {
"entities": [
{
"id": "urn:ngsi-ld:ActuatorScreenshot:001",
"type": "Actuator"
}
],
"attrs": [
"Screen"
]
},
"provider": {
"http": {
"url": "http://localhost:4041"
},
"supportedForwardingMode": "all",
"legacyForwarding": true
},
"status": "active"
}
I attempted following the example from http://telefonicaid.github.io/fiware-orion/api/v2/stable/:
curl -X PATCH \
http://localhost:1026/v2/registrations/5d3ff3e2ab1e270d7775a7bf \
-d '{
"expires":"2040-10-04T00:00:00"
}'
But as I said I got the error message:
405 Method Not Allowed
Feel free to ask for more info.
The operation to modify registrations has not been yet implemented in Orion 2.2.0 (last version in the moment of writing this). As mentioned in Orion documentation:
Orion implements registration management as described in the NGSIv2
specification, except for the following aspects:
List item PATCH /v2/registration/<id> is not implemented. Thus, registrations cannot be updated directly. I.e., updates must be done
deleting and re-creating the registration. Please see this
issue about
this.
However, the workaround is pretty simple: delete the old registration and create a new one with the modified parameters.

Get JSON value from curl request

I have a Nexus Repository server where my artifacts are stored. I want to write a shell script to download artifacts from here. When using the curl request curl --user username:password -X GET "http://your_ip:your_port/service/rest/v1/search?repository=your_repository" -H "accept: application/json" I get a list of the items in my repository which looks like this:
{
"items": [
{
"id": "dGVzdC1hcHA6ZDM1MTBiN2FkMThkODJjZGU1NjNhMWVlMWFmOWIwMGQ",
"repository": "test-app",
"format": "maven2",
"group": "no.ahj",
"name": "test-app",
"version": "1.0-20190715.130341-2",
"assets": [
{
"downloadUrl": "http://192.168.56.2:8081/repository/test-app/no/ahj/test-app/1.0-SNAPSHOT/test-app-1.0-20190715.130341-2.pom",
"path": "no/ahj/test-app/1.0-SNAPSHOT/test-app-1.0-20190715.130341-2.pom",
"id": "dGVzdC1hcHA6Yzc3MDE2OWMwYjJlM2VkODU0MGMyOGEwOWQ0Njk4ZTQ",
"repository": "test-app",
"format": "maven2",
"checksum": {
"sha1": "5fd032774dd3ae6fbbd6484b3dc6ef2582d9b397",
"md5": "3a6aa8e295a734fdb8a8df782c0a14d5"
}
},
I would like my shell script to run this curl request, extract the value from the downloadURL field, store it in some variable and then use wget with this variable to download the file. So my question is this: How can I take the URL from downloadURL and store/use it in my shell script?
A way to parse it with likely no external dependencies (as python is installed by default on most Linux distributions) is just to use python:
user#host ~ % JSON=$(curl --user username:password -X GET "http://your_ip:your_port/service/rest/v1/search?repository=your_repository" -H "accept: application/json")
user#host ~ % echo $JSON | python -c 'import sys, json; print(json.load(sys.stdin)["items"][0]["assets"][0]["downloadUrl"])'
http://192.168.56.2:8081/repository/test-app/no/ahj/test-app/1.0-SNAPSHOT/test-app-1.0-20190715.130341-2.pom
If you are going to do a lot of JSON parsing in this script, it may be worth considering writing the entire script in Python, too, instead of shell script.

Modify attribute on device by IOT-Agent Json

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.