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'
Related
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
When running this list files there is not a nextPageToken there is just files[].
curl \
'https://www.googleapis.com/drive/v3/files?fields=files(id%2C%20name)&key=[YOUR_API_KEY]' \
--header 'Authorization: Bearer [YOUR_ACCESS_TOKEN]' \
--header 'Accept: application/json' \
--compressed
result:
{
"files": [
{
"id": "1",
"name": "1"
},
...
{
"id": "2",
"name": "2"
}
]
}
Leaving the fields parameter empty, the nextPageToken is returned.
curl \
'https://www.googleapis.com/drive/v3/files?key=[YOUR_API_KEY]' \
--header 'Authorization: Bearer [YOUR_ACCESS_TOKEN]' \
--header 'Accept: application/json' \
--compressed
result:
{
"kind": "drive#fileList",
"nextPageToken": "~!!~AI9FV7TN...",
"incompleteSearch": false,
"files": [
{
"kind": "drive#file",
"id": "1",
"name": "1",
"mimeType": "application/vnd.google-apps.spreadsheet"
},
...
Is this a bug or is there some way to get the nextPageToken and limit the fields returned? The doc page for fields implies that it should work:
Note: The Drive API supports query parameters for data pagination (maxResults and nextPageToken). For APIs that support these parameters, use these parameters to reduce the results of each query to a manageable size. Otherwise, the performance gains possible with partial response might not be realized.
When fields=files(id,name) is used for the method of "Files: list", the file ID and filename are returned. In this case, the values of fields are files.id and files.name. nextPageToken is not included in fields. By this, the page token is not returned. When fields is not used, it seems that fields of nextPageToken,incompleteSearch,kind,files(id,name,kind,mimeType) is the default value. So I thought that this is not a bug, and it might be the current specification.
So when you want to retrieve nextPageToken when you use https://www.googleapis.com/drive/v3/files?fields=files(id%2C%20name), please include nextPageToken in fields as follows.
Modified curl command:
curl \
'https://www.googleapis.com/drive/v3/files?fields=nextPageToken%2Cfiles%28id%2Cname%29&key=[YOUR_API_KEY]' \
--header 'Authorization: Bearer [YOUR_ACCESS_TOKEN]' \
--header 'Accept: application/json' \
--compressed
In this case, fields is nextPageToken,files(id,name).
Result:
When above curl command is run, the following result is returned.
{
"nextPageToken": "###",
"files": [
{"id": "###", "name": "###"},
{"id": "###", "name": "###"},
,
,
,
]
}
Reference:
Files: list
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.
I've been trying to use the Post references (https://developer.autodesk.com/en/docs/model-derivative/v2/reference/http/urn-references-POST/) to set up the reference between two files in forge but although I get a message "success" as result when I try it on the forge viewer I still see the files separately even after I translate the models. Has someone been through the same issue?
Without seeing you code it is hard to tell what is happening. Below I copied my bash script code which references/translate an obj with material and texture.
Au.obj
+- Au.mtl
+- Au.jpg
After upload, I got these
idObj="urn:adsk.objects:os.object:cyrillejcrja/Au.obj"
idMtl="urn:adsk.objects:os.object:cyrillejcrja/Au.mtl"
idJpg="urn:adsk.objects:os.object:cyrillejcrja/Au.jpg"
the code to set references, now
urn=$(xbase64encode $idObj)
job='{
"urn": "'${idObj}'",
"filename": "Au.obj",
"references": [{
"urn": "'${idMtl}'",
"relativePath": "./Au.mtl",
"filename": "Au.mtl",
"references": [{
"urn": "'${idJpg}'",
"relativePath": "./Au.jpg"
}]
}]
}'
response=$(curl -H "Content-Type: application/json" \
-H "Authorization: ${bearer}" \
-X POST ${ForgeHost}/modelderivative/v2/designdata/${urn}/references \
-k -s -d "${job}")
Here is got a reply like below which only means that the references are registered.
{
"result": "success"
}
Now, I do this to translate the obj and use the references
urn=$(xbase64encode $idObj)
job='{
"input": {
"urn": "'${urn}'",
"checkReferences": true
},
"output": {
"formats": [
{
"type": "svf",
"views": [
"2d",
"3d"
]
}
]
}
}'
response=$(curl -H "Content-Type: application/json" \
-H "Authorization: ${bearer}" \
-H "x-ads-force: true" \
-X POST ${ForgeHost}/modelderivative/v2/designdata/job \
-k -s -d "${job}")
Note the "checkReferences": true, as documented here.
Now, I can wait the translation to complete and see the result in the Viewer.
For reference the xbase64safeencode function used above
function xbase64safeencode () { local id64=$(echo -ne $1 | base64 $wrap_arg | tr -d '=' | tr '+/' '-_'); echo $id64; }
#Cyrille, this is my request:
curl -X 'POST' -H 'Authorization: Bearer eyJhbGciOiJIUzI1NiIsI' -H 'Content-Type: application/json' -v 'https://developer.api.autodesk.com/modelderivative/v2/designdata/{urn}/references' -d
'{
"urn": "urn:adsk.objects:os.object:bucket/non-existent.rvt",
"filename": "",
"references": [
{
"urn": "urn:adsk.objects:os.object:bucket/non-existent.rvt",
"relativePath": "",
"filename": ""
}
]
}'
I got as result:
'{
"result": "success"
}'
The point is I'm getting success as a result even when I do not have the specified file on the server, so I'd suggest few server-side validations, for example, when a model has been translated once we can't set as reference right so it should at least return an error. Thank you and I hope this helps.
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.