How to process sensor time series data in batch (e.g. every 1 minute) to time series database (e.g. CrateDB) via FIWARE ORION CONTEXT BROKER? - fiware

I want to process sensor data into a time series database via FIWARE ORION CONTEXT BROKER. However, instead of writing each data individually, I want to write it collectively as a 1-minute time series. Is something like this possible?
Could you help me? What path should I follow?

You need to split this problem into separate parts. Firstly define the payload of your batch operation. If the device can collect a series of readings and then deliver them as NGSI you can use the /v2/op/update/ for NGSI-v2 or /ngsi-ld/v1/entityOperations/upsert for NGSI-LD
For NGSI-v2 it would be something like
curl -L -X POST 'http://localhost:1026/v2/op/update/' \
-H 'Content-Type: application/json' \
--data-raw '{
"actionType":"append",
"entities":[
{
"id": "urn:ngsi-ld:TemperatureSensor:002",
"type": "TemperatureSensor",
"temperature": {
"type": "Property",
"value": 21,
"metadata":{
"unitCode": "CEL",
"TimeInstant": {
"type": "DateTime",
"value": "XXXX-XXX-XXXXX"
}
}
}
},
{
"id": "urn:ngsi-ld:TemperatureSensor:003",
"type": "TemperatureSensor",
"temperature": {
"type": "Property",
"value": 27,
"metadata":{
"unitCode": "CEL",
"TimeInstant": {
"type": "DateTime",
"value": "XXXX-XXX-XXXXX"
}
}
}
}
]
}'
For NGSI-LD it would be something like this:
curl -L -X POST 'http://localhost:1026/ngsi-ld/v1/entityOperations/upsert' \
-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 '[
{
"id": "urn:ngsi-ld:TemperatureSensor:002",
"type": "TemperatureSensor",
"temperature": {
"type": "Property",
"value": 21,
"unitCode": "CEL",
"observedAt": "XXXXX-XXXX-XXXXXX"
}
},
{
"id": "urn:ngsi-ld:TemperatureSensor:003",
"type": "TemperatureSensor",
"temperature": {
"type": "Property",
"value": 27,
"unitCode": "CEL",
"observedAt": "XXXXX-XXXX-XXXXXX"
}
}
]'
The important thing here is to include the observedAt or TimeInstant in the payload so that it can be passed when creating a subscription into QuantumLeap (amend the fiware-service to the correct Tenant:
curl -iX POST \
'http://localhost:1026/v2/subscriptions/' \
-H 'Content-Type: application/json' \
-H 'fiware-service: openiot' \
-H 'fiware-servicepath: /' \
-d '{
"description": "Notify QuantumLeap of temperature changes",
"subject": {
"entities": [
{
"idPattern": "TemperatureSensor.*"
}
],
"condition": {
"attrs": [
"count"
]
}
},
"notification": {
"http": {
"url": "http://quantumleap:8668/v2/notify"
},
"attrs": [
"temperature"
],
"metadata": ["dateCreated", "TimeInstant"]
},
"throttling": 1
}'
Now it could be the case that you have a device writing to a file and periodically uploading a batch of readings. In this case you can create a Custom IoT Agent which deciphers the payload and transforms each reading into a batch upsert request - an example can be found in this FIWARE Video on YouTube.
The steps are always the same:
Ingest the payload holding the readings (in format X)
Transform format X to an in-memory representation.
Tweak the representation into the entities part of an NGSI request
Send the upsert to the context broker.
The subscription to QuantumLeap will persist the data to a database where you can make time-series queries. The FIWARE Tutorial will cover the steps.
Now if you are using NGSI-LD you can still use QuantumLeap, but you could also look at using the Temporal interface directly. More details in the video here

Related

Autodesk.Forge.DerivativesApi.GetManifest() failed status

I've trying to process a file that uploads+renders fine on the demo autodesk viewer (i.e. viewer.autodesk.com). The GetManifest result has a progress of "complete" but a status of "failed". If I dump the contents of the GetManifest() call I get the following which has Unrecoverable exit code from extractor: -1073741829 in the message. Wondering why it completes and renders on the online Autodesk viewer. The translation completes w\ "success", but when I try and get the manifest (so that I can download the derivatives), it fails on the GetManifest() call.
? manifest.ToString()
"{
\r\n "urn": "dXJuOmFkc2sub2JqZWN0czpvcy5vYmplY3Q6a2FodWFtb2RlbHMvOWNjNjA2Njg2NGIwNDViNDg5NjhhNDMxNjI1NmEzNTMuSUZD",
\r\n "derivatives": [
\r\n {
\r\n "hasThumbnail": "false",\r\n "name": "LMV Bubble",\r\n "progress": "complete",\r\n "messages": [
\r\n {\r\n "type": "error",
\r\n "message": "Unrecoverable exit code from extractor: -1073741829",
\r\n "code": "TranslationWorker-InternalFailure"\r\n }\r\n ],\r\n
"outputType": "svf",\r\n "status": "failed"\r\n }\r\n ],
\r\n "hasThumbnail": "false",\r\n "progress": "complete",\r\n "type": "manifest",\r\n "region": "US",\r\n "version": "1.0",\r\n "status": "failed"\r\n}"
Since this IFC model is IFC4, please use the modern conversion method instead.
curl --location --request POST 'https://developer.api.autodesk.com/modelderivative/v2/designdata/job' \
--header 'Authorization: Bearer ' \
--header 'Content-Type: application/json' \
--header 'x-ads-force: true' \
--data'{
"input": {
"urn": "{URN}"
},
"output": {
"formats": [
{
"type": "svf",
"views": [
"3d"
],
"advanced": {
"conversionMethod": "modern"
}
}
]
}
}'

No substitution in httpCustom payload

I would like to make a httpCustom payload in OCB but no replace info properly. I think i have tested all the ways i know but no results, someone who could help me. This is my code:
"notification": {
"httpCustom": {
"url": "http://xxxx.xxxx.xxxx:8080/api/v1/telemetry",
"payload": "[{ %22temperature%22: %22${id}%22, %22humidity%22: %22${humidity}%22, %22battery%22: %22${battery}%22 }]"
},
"attrs": [
"temperature","humidity","battery"
]
},
I have no error when i do subscription, but when i test in my end point no replace for the macros ${...}, the payload take object information compose but with no values.
I have test to write/send ${id} as then value of a field in payload and no substitution at all. Test it with URL encode and %22 and no success, I think could be disable substitution ? but i have check it and it has FALSE value.
This is a http response:
{
"method": "POST",
"path": "/",
"query": {},
"headers": {
"x-forwarded-for": "3.124.211.58",
"x-forwarded-proto": "https",
"x-forwarded-port": "443",
"host": "83efe9565d48d8bc8cf298d7786b8042.m.pipedream.net",
"x-amzn-trace-id": "Root=1-5f1bddce-7f2b4277458e77b98c0920d1",
"content-length": "54",
"user-agent": "orion/2.1.0 libcurl/7.29.0",
"fiware-service": "example",
"fiware-servicepath": "/example",
"accept": "application/json",
"content-type": "application/json",
"fiware-correlator": "a7fcfe32-ce47-11ea-9723-0242ac14000a",
"ngsiv2-attrsformat": "custom"
},
"bodyRaw": "[{ \"temperature\": \"\", \"humidity\": \"\", \"battery\": \"\" }]",
"body": [
{
"temperature": "",
"humidity": "",
"battery": ""
}
]
}
Orion VersiĆ³n: 2.1.0 and tested in 2.4.0
Any help ? Thanks in advance !!
I have done the following test, with Orion 2.4.0. Orion database is empty before starting the test.
First, create this subscription:
curl -v localhost:1026/v2/subscriptions -s -S -H 'Content-Type: application/json' -d #- <<EOF
{
"subject": {
"entities": [
{
"id": "Device1",
"type": "Device"
}
]
},
"notification": {
"httpCustom": {
"url": "http://localhost:1027/api/v1/telemetry",
"payload": "[{ %22temperature%22: %22\${id}%22, %22humidity%22: %22\${humidity}%22, %22battery%22: %22\${battery}%22 }]"},
"attrs": [
"temperature","humidity","battery"
]
}
}
EOF
Next, start a listining process at port 1027:
nc -l -p 1027
Next, create entity as follows (which triggers a notification):
curl localhost:1026/v2/entities -s -S -H 'Content-Type: application/json' -d #- <<EOF
{
"id": "Device1",
"type": "Device",
"temperature": {
"value": 23,
"type": "Number"
},
"humidity": {
"value": 99,
"type": "Number"
},
"battery": {
"value": 15,
"type": "Number"
}
}
EOF
What I get in nc is:
POST /api/v1/telemetry HTTP/1.1
Host: localhost:1027
User-Agent: orion/2.4.0 libcurl/7.52.1
Fiware-Servicepath: /
Accept: application/json
Content-Length: 65
Content-Type: text/plain; charset=utf-8
Fiware-Correlator: 4ae608b0-d248-11ea-81de-000c29df7908
Ngsiv2-AttrsFormat: custom
[{ "temperature": "Device1", "humidity": "99", "battery": "15" }]
which is the expected result, with replacements.
Next, restart the listening process and update the entity this way (triggering a new notification):
curl localhost:1026/v2/entities/Device1/attrs?options=forcedUpdate -s -S -H 'Content-Type: application/json' -d #- <<EOF
{
"temperature": {
"value": 32,
"type": "Number"
},
"humidity": {
"value": 79,
"type": "Number"
},
"battery": {
"value": 25,
"type": "Number"
}
}
EOF
and I get now in nc:
POST /api/v1/telemetry HTTP/1.1
Host: localhost:1027
User-Agent: orion/2.4.0 libcurl/7.52.1
Fiware-Servicepath: /
Accept: application/json
Content-Length: 65
Content-Type: text/plain; charset=utf-8
Fiware-Correlator: 66278dd8-d248-11ea-822d-000c29df7908
Ngsiv2-AttrsFormat: custom
[{ "temperature": "Device1", "humidity": "79", "battery": "25" }]
Conclusion: according my tests, Orion is working as expected.
I'd suggest to have a close look to the steps above and try to identify any possible diference comparing with your case. Note the \$ in the subscription creation payload: it is needed to avoid bash vars replacement in curl. Maybe you are facing a similar problem? You can check how your subscription is with GET /v2/subscriptions or checking directly in the database (csubs collection).

Potential Error in Forge Post Job Docs with destination

Looking at the documentation for the Forge Post Job. The examples show that region is a sub object of destination. However the docs seem to show that they are on the same level.
Doc was uploaded as image.
Curl Request Example:
curl -X 'POST' \
[![enter image description here][2]][2]-H 'Content-Type: application/json; charset=utf-8' \
-H 'Authorization: Bearer PtnrvrtSRpWwUi3407QhgvqdUVKL'
-v 'https://developer.api.autodesk.com/modelderivative/v2/designdata/job' \
-d
'{
"input": {
"urn": "dXJuOmFkc2sub2JqZWN0czpvcy5vYmplY3Q6bW9kZWxkZXJpdmF0aXZlL0E1LnppcA",
"compressedUrn": true,
"rootFilename": "A5.iam"
},
"output": {
"destination": {
"region": "us"
},
"formats": [
{
"type": "svf",
"views": [
"2d",
"3d"
]
}
]
}
}'
Thanks for reporting this.
I've let our Dev Portal team know to take a look and will get back to you once they fix this up. Thanks!

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.

Orion CB doesn't update lazy attributes on IoT Agent

I'm trying to use Orion CB as Contex Provider for an IoT Agent in which I have registred a device with lazy attributes only.
On the IoT Agent I need to handle updateContext requests so I did a handler for these requests like this:
iotAgentLib.setDataUpdateHandler(updateContextHandler);
And in the updateContextHandler function I have only one instruction:
console.log(attributes);
In order to see if all the values I want to update have been received correctly.
Now if I do an update on one of the attributes of the entity represented by the device:
curl -i -X POST \
-H "fiware-service:service1" \
-H "fiware-servicepath:/subservice1" \
-H "X-Auth-Token:wNRwDwqYlLoLD8U9sFkTAEE6PfYMbQ" \
-H "Content-Type:application/json" \
-d \
'{
"contextElements": [
{
"id": "ncc_estimate",
"attributes": [
{
"name": "arrival",
"type": "string",
"value": "some_value"
}
]
}
],
"updateAction": "UPDATE"
} ' \
'http://{orion_address}/v1/updateContext'
What I see on the IoT Agent output console is:
time=2018-01-09T08:14:59.539Z | lvl=DEBUG | corr=2f4fdb0c-f515-11e7-86b2-0242ac110003 | trans=6ac5c35d-d7bf-419c-8f64-bc843b991d47 | op=IoTAgentNGSI.GenericMiddlewares | srv=service1 | subsrv=/subservice1 | msg=Body:
{
"contextElements": [
{
"type": "nccestimate",
"isPattern": "false",
"id": "ncc_estimate",
"attributes": [
{
"name": "arrival",
"type": "string",
"value": ""
}
]
}
],
"updateAction": "UPDATE"
}
Where as you can see the value field is empty, as I can also see from the console.log() output in the UpdateHandler function that is:
[ { name: 'arrival', type: 'string', value: '' } ]
It seems that Orion is deleting the value before sending it to the IoT Agent. What could be the problem? Am I wrong doing something?
edit:
Here is the response for the call to: /v1/registry/contextEntities/ncc_estimate
{"contextRegistrationResponses":[
{"contextRegistration":
{"entities":[
{
"type":"nccestimate",
"isPattern":"false",
"id":"ncc_estimate"
}
],
"attributes":[
{
"name":"transport_type",
"type":"string",
"isDomain":"false"
},
{
"name":"arrival",
"type":"string",
"isDomain":"false"
}
],
"providingApplication":"http://192.168.199.151:4044"}
}
]}
edit2:
This is what Orion is sending to the iot agent when performing the updateContext operation described before:
POST //updateContext HTTP/1.1
User-Agent: orion/1.10.0-next libcurl/7.19.7
Host: 192.168.199.151:4044
fiware-service: service1
Fiware-ServicePath: /subservice1
X-Auth-Token: M62UkJc7yKX5aQwaHrsODfIrV4Ou85
Accept: application/json
Content-length: 169
Content-type: application/json; charset=utf-8
Fiware-Correlator: 42561e9a-f615-11e7-8610-0242ac110003
{"contextElements":[{"type":"nccestimate","isPattern":"false","id":"ncc_estimate","attributes":[{"name":"arrival","type":"string","value":""}]}],"updateAction":"UPDATE"}
As you can see the "value" field for the attribute is empty.
I'm using Orion version 1.10.0 and iot agent node lib version 2.5.1.
I have done the following test using CB same version as yours (i.e. 1.10.0)
First, create a registration as the one that IOTA would create:
(curl -s -S localhost:1026/v1/registry/registerContext -H "fiware-service:service1" -H "fiware-servicepath:/subservice1" -H 'Content-Type: application/json' -d #- | python -mjson.tool) <<EOF
{
"contextRegistrations": [
{
"entities": [
{
"type": "nccestimate",
"isPattern": "false",
"id": "ncc_estimate"
}
],
"attributes": [
{
"name": "transport_type",
"type": "string",
"isDomain": "false"
},
{
"name": "arrival",
"type": "string",
"isDomain": "false"
}
],
"providingApplication": "http://localhost:4044"
}
],
"duration": "P1M"
}
EOF
Next, check that it is exactly the same registration shown in the question post (except by the providingApplication, that points to localhost):
curl localhost:1026/v1/registry/contextEntities/ncc_estimate -s -S -H "fiware-service:service1" -H "fiware-servicepath:/subservice1" -H 'Accept: application/json' | python -mjson.tool
which response is
{
"contextRegistrationResponses": [
{
"contextRegistration": {
"attributes": [
{
"isDomain": "false",
"name": "transport_type",
"type": "string"
},
{
"isDomain": "false",
"name": "arrival",
"type": "string"
}
],
"entities": [
{
"id": "ncc_estimate",
"isPattern": "false",
"type": "nccestimate"
}
],
"providingApplication": "http://localhost:4044"
}
}
]
}
Next, run nc process at localhost on providingApplication port.
nc -l -p 4044
Once the setup is done, let's test first with an update based on the one in the question.
curl -s -S -X POST http://localhost:1026/v1/updateContext -H "fiware-service:service1" -H "fiware-servicepath:/subservice1" -H "Content-Type:application/json" -d #- <<EOF
{
"contextElements": [
{
"id": "ncc_estimate",
"attributes": [
{
"name": "arrival",
"type": "string",
"value": "some_value"
}
]
}
],
"updateAction": "UPDATE"
}
EOF
In this case, Orion doesn't recognized the registration and returns a Not Found response:
{
"contextResponses": [{
"contextElement": {
"type": "",
"isPattern": "false",
"id": "ncc_estimate",
"attributes": [{
"name": "arrival",
"type": "string",
"value": ""
}]
},
"statusCode": {
"code": "404",
"reasonPhrase": "No context element found",
"details": "ncc_estimate"
}
}]
}
In other words, Orion is not forwarding the response. I don't know why in your case is forwarded and leaves a trace in IOTA log file.
Next test uses the same request but adding a type field for the entity.
curl -s -S -X POST http://localhost:1026/v1/updateContext -H "fiware-service:service1" -H "fiware-servicepath:/subservice1" -H "Content-Type:application/json" -d #- <<EOF
{
"contextElements": [
{
"id": "ncc_estimate",
"type": "nccestimate",
"attributes": [
{
"name": "arrival",
"type": "string",
"value": "some_value"
}
]
}
],
"updateAction": "UPDATE"
}
EOF
In this case, the request is forwarded and I get this in the nc terminal.
POST //updateContext HTTP/1.1
User-Agent: orion/1.10.0 libcurl/7.38.0
Host: localhost:4044
fiware-service: service1
Fiware-ServicePath: /subservice1
Accept: application/json
Content-length: 179
Content-type: application/json; charset=utf-8
Fiware-Correlator: 42e75f8a-fa0d-11e7-93f1-000c29173617
{"contextElements":[{"type":"nccestimate","isPattern":"false","id":"ncc_estimate","attributes":[{"name":"arrival","type":"string","value":"some_value"}]}],"updateAction":"UPDATE"}
Note the some_value in the response. Orion seems to be progressing correctly the request in this case.
EDIT: according to user's feedback, entity type solved the problem. We are highlighting it in the documentation regarding Context Providers:
You should include entity type in the query/update in order for the ContextBroker to be able to forward to Context Providers