I'm trying to register a Context Provider as source for several KPIs.
So far, it seems registering might be working, as GET http://{{orion}}/v2/registrations returns something similar to what I set in creation:
{
// each registering a new id is returned: "id": "60991a887032541f4539a71d",
"description": "City Inhabitants",
"dataProvided": {
"entities": [
{
"id": "city.inhabitants"
//,"type": "KeyPerformanceIndicator"
}
]
},
"provider": {
"http": {
"url": "http://myhost/v2/inhabitants"
}
//, "legacyForwarding": false //perhaps there's a bug, cause although unset or set to false, broker still returns true.
}
}
However GET http://{{orion}}/v2/entities/city.inhabitants results in:
{
"error": "BadRequest",
"description": "Service not found. Check your URL as probably it is wrong."
}
GET http://{{orion}}/v2/entities?type=KeyPerformanceIndicator returns [] and context-provider is not being invoked any way.
I'm coding a Node.js application from scratch, to better understand what's going on https://github.com/FIWARE/tutorials.Context-Providers, and using tutorial containers as actual Fiware Broker, so all stores/shelf/products are working but not my KPI.
Using the tutorial application where a microservice is listening on the http://context-provider:3000/random/weatherConditions POST endpoint.
The following registration:
curl -L -X POST 'http://localhost:1026/v2/registrations' \
-H 'Content-Type: application/json' \
--data-raw '{
"description": "Get Weather data for KPI 1",
"dataProvided": {
"entities": [
{
"id" : "urn:ngsi-ld:KPI:010",
"type": "KeyPerformanceIndicator"
}
],
"attrs": [
"temperature", "relativeHumidity"
]
},
"provider": {
"http": {
"url": "http://context-provider:3000/random/weatherConditions"
},
"legacyForwarding": false
},
"status": "active"
}'
Will forward and retrieve data for the following request:
curl -L -X GET 'http://localhost:1026/v2/entities/urn:ngsi-ld:KPI:010'
or
curl -L -X GET 'http://localhost:1026/v2/entities/?type=KeyPerformanceIndicator'
Returns:
{
"id": "urn:ngsi-ld:KPI:010",
"type": "KeyPerformanceIndicator",
"temperature": {
"type": "Number",
"value": 11,
"metadata": {}
},
"relativeHumidity": {
"type": "Number",
"value": 39,
"metadata": {}
}
}
The context broker is forwarding the request to the http://context-provider:3000/random/weatherConditions POST end-point with the following payload:
{
"entities": [
{
"id": "urn:ngsi-ld:KPI:010",
"type": "KeyPerformanceIndicator"
}
],
"attrs": [
"temperature",
"relativeHumidity"
]
}
Related
Is there a convenient way to subscribe to update an attribute, each time another attribute changes?
I have this entity on Orion:
{
"id": "Asset:001",
"type": "SomeType",
"Input": {
"type": "Text",
"value": "State",
"metadata": {}
},
"Output": {
"type": "Float",
"value": null,
"metadata": {}
}
}
I subscribe to notify value changes to Quantumleap:
curl -s -o /dev/null -X POST \
'http://orion:1026/v2/subscriptions/' \
-H 'Content-Type: application/json' \
-d '{
"description": "Orion notify Quantumleap on State changhes",
"subject": {
"entities": [
{
"idPattern": ".*",
"type": "Sometype"
}
],
"condition": {
"attrs": [
"state"
]
}
},
"notification": {
"http": {
"url": "http://quantumleap:8668/v2/notify"
},
"attrs": [
"State"
],
"metadata": []
}
}'
And I got my data on CrateDB where I made some calculation.
Then I would like to get the results of this computing, and put back as an attribute to the entity Asset:001.
Now I get this done by a script, but it would be nice to achieve the same result with a subscription, is this possible?
Thanks!!
The attributes in attrs within notification are the ones to be included in the notification. The attributes in attrs within condition are the ones which change trigger the notification.
You can use a different set of attributes in each array, so the use case you describe in covered.
For instance, changes in attribute A will notify the value of attribute B using something like this:
{
...
"subject": {
...
"condition": {
"attrs": [
"A"
]
}
},
"notification": {
...
"attrs": [
"B"
]
}
}
I have the curl request as shown below and also attached the response of curl request from the response how can I fetch the value which is under "status.azure.resource_name" and store it in some variable as I'm new to GitHub action facing some challenges if this is some programming api I could have resolved it
Request:
curl --location --request PUT $URL \
--header "$AUTH_HEADER" \
--header 'Content-Type: application/json' \
--data-raw "$PAYLOAD"
Response:
{
"labels": {},
"spec": {
"mysql": {
"version": "8.0",
"sku": {
"name": "GP_Gen5_4"
},
"storage_profile": {
"storage_mb": 5120
}
},
"key_vault": {
"access_policies": [
{
"name": "test",
"type": "group",
"project": null
}
]
}
},
"type": "azure-mysql",
"name": "mysql",
"id": "1234",
"created_at": "2012-03-04T10:00:05+00:00",
"updated_at": "2012-03-04T10:00:05+00:00",
"project": {
"id": "ae3dfa99",
"name": "Test",
"url": "www.google.com",
"geography": "in"
},
"links": {
"key_vault": {
"endpoint": {
"url": "",
"description": "test.",
"display_name": "test"
},
"azure_portal": {
"url": "test",
"description": "Link to the resource in the Azure portal.",
"display_name": "Key Vault Azure Portal"
}
},
"azure_portal": {
"url": "test",
"description": "Link to the resource in the Azure portal.",
"display_name": "Azure Portal"
},
"endpoint": {
"url": "test",
"description": "Azure resource endpoint.",
"display_name": "test"
}
},
"url": "test",
"tags": {
"cost_center_id": "471000",
"customer": "internal",
"product_group": "internal",
"environment_type": "test",
"budget_category": "",
"team": ""
},
"spiffe_id": "test",
"status": {
"ready": false,
"state": "reconciling",
"deployment": {
"steps": {}
},
"azure": {
"resource_name": "test",
"id": null,
"subscription_id": "test",
"resource_group": "test"
},
"key_vault": {
"access_policies": []
}
}
}
There are multiple ways to achieve that.
You can use directly jq and read variable in bash step.
You can use one of existing open source actions from marketplace:
- name: get nested property
id: format_script
uses: notiz-dev/github-action-json-property#release
with:
path: 'yourjson.json'
prop_path: 'status.azure.resource_name'
- run: echo ${{steps.format_script.outputs.prop}}
Download just one property from whole JSON if you don't need a file itself:
- uses: senmu/download-json-property-action#v1.0.0
with:
url: 'https://httpbin.org/json'
property_path: status.azure.resource_name
Error: String cannot be coerced to a nodeId
Hi,
I was busy setting up a connection between the Orion Broker and an PLC with OPC-UA Server using the opcua iotagent agent.
I managed to setup all parts and I am able to receive (test) data, but I am unable to follow the tutorial with regards to adding an entity to the Orion-Broker using a json file:
curl http://localhost:4001/iot/devices -H "fiware-service: plcservice" -H "fiware-servicepath: /demo" -H "Content-Type: application/json" -d #add_device.json
The expected result would be an added entity to the OrionBroker with the supplied data, but this only results in a error message:
{"name":"Error","message":"String cannot be coerced to a nodeId : ns*4:s*MAIN.mainVar"}
suspected Error
Is it possible that the iotagent does not work nicely with nested Variables?
steps taken
doublechecked availability of OPC Data:
OPC data changes every second, can be seen in Broker log
reduced complexity of setup to only include Broker and IOT-agent
additional information:
add_device.json file:
{
"devices": [
{
"device_id": "plc1",
"entity_name": "PLC1",
"entity_type": "plc",
"attributes": [
{
"object_id": "ns*4:s*MAIN.mainVar",
"name": "main",
"type": "Number"
}
],
"lazy": [
],
"commands" : []
}
]
}
config of IOT-agent (from localhost:4081/config):
{
"config": {
"logLevel": "DEBUG",
"contextBroker": {
"host": "orion",
"port": 1026
},
"server": {
"port": 4001,
"baseRoot": "/"
},
"deviceRegistry": {
"type": "memory"
},
"mongodb": {
"host": "iotmongo",
"port": "27017",
"db": "iotagent",
"retries": 5,
"retryTime": 5
},
"types": {
"plc": {
"service": "plcservice",
"subservice": "/demo",
"active": [
{
"name": "main",
"type": "Int16"
},
{
"name": "test1",
"type": "Int16"
},
{
"name": "test2",
"type": "Int16"
}
],
"lazy": [],
"commands": []
}
},
"browseServerOptions": null,
"service": "plc",
"subservice": "/demo",
"providerUrl": "http://iotage:4001",
"pollingExpiration": "200000",
"pollingDaemonFrequency": "20000",
"deviceRegistrationDuration": "P1M",
"defaultType": null,
"contexts": [
{
"id": "plc_1",
"type": "plc",
"service": "plcservice",
"subservice": "/demo",
"polling": false,
"mappings": [
{
"ocb_id": "test1",
"opcua_id": "ns=4;s=test.TestVar.test1",
"object_id": null,
"inputArguments": []
},
{
"ocb_id": "test2",
"opcua_id": "ns=4;s=test.TestVar.test2",
"object_id": null,
"inputArguments": []
},
{
"ocb_id": "main",
"opcua_id": "ns=4;s=MAIN.mainVar",
"object_id": null,
"inputArguments": []
}
]
}
]
}
}
I'm one of the maintainers of the iotagent-opcua repo, we have identified and fixed the bug you were addressing, please update your agent to the latest version (1.4.0)
If you haven't ever heard about it, starting from 1.3.8 we have introduced a new configuration property called "relaxTemplateValidation" which let you use previously forbidden characters (e.g. = and ; ). I suggest you to have a look at it on the configuration examples provided.
In version 1.7.0 of Orion CB running the docker version in Docker for Windows,
if I create a simple object doing POST http://localhost:1026/v1/updateContext
with the body:
{
"contextElements": [
{
"type": "Car",
"id": "myNewCar",
"attributes": [
{
"name": "maxSpeed",
"type": "integer",
"value": "220"
}
]
}
],
"updateAction": "APPEND"
}
I get the answer:
{
"contextResponses": [
{
"contextElement": {
"type": "Car",
"isPattern": "false",
"id": "myNewCar",
"attributes": [
{
"name": "maxSpeed",
"type": "integer",
"value": ""
}
]
},
"statusCode": {
"code": "200",
"reasonPhrase": "OK"
}
}
]
}
Then, if I do POST http://localhost:1026/v1/queryContext with the same headers and the same components with the body
{
"entities": [
{
"type": "Car",
"isPattern": "false",
"id": "myNewCar"
}
]
}
I get the following:
{
"errorCode": {
"code": "404",
"reasonPhrase": "No context element found"
}
}
Which shouldn't be problematic (I can query the entities with v2 API, for instance) if it wasn't needed for integration with data representation tools such as SpagoBI as documented in http://spagobi.readthedocs.io/en/latest/user/NGSI/README/
What can I do? I am doing something wrong with the context provision?
Thanks!
My problem was that I was using a imported Postman collection of the API (Downloaded from https://github.com/telefonicaid/fiware-orion/tree/develop/doc/apiary/v2) and accidentally I was using the header Fiware-Service.
You are right and your tests work properly.
Thanks for the prompt reply!!
EDIT 2
curl --include \
--header 'Content-Type: application/json' \
--request POST \
--data-binary '{
"description": "Day subscription",
"subject": {
"entities": [
{
"idPattern": "es-leon-.*",
"type": "Event"
}
],
"condition": {
"attrs": [
"Title",
"dFlag"
],
"expression": {
"q": "dFlag>0"
}
}
},
"notification": {
"http": {
"url" : "http://localhost:5050/notify"
},
"attrs": [
"Title",
"dFlag"
],
"attrsFormat":"legacy"
}
}' \
'http://localhost:1026/v2/subscriptions'
In Orion the subscription register ok (thanks for the tips in the comments) but I'm having the same issue as said in here even though I use "attrsFormat":"legacy"
I'm making something wrong? why orion is not using ngsiv1 to send the notification to cygnus?
The cygnus error trace.
Cygnus shows orion is responding this:
{
"subscriptionId": "574315e77775f31b8d3da719",
"data": [{
"id": "es-leon-0",
"type": "Event",
"Title": {
"type": "none",
"value": "pepe",
"metadata": {}
},
"dFlag": {
"type": "text",
"value": "1",
"metadata": {}
}
}]
}
When it has to respond the lines below to be in ngsiv1:
{
"subscriptionId": "5743178d7775f31b8d3da71a",
"originator": "localhost",
"contextResponses": [{
"contextElement": {
"type": "Event",
"isPattern": "false",
"id": "es-leon-0",
"attributes": [{
"name": "Title",
"type": "text",
"value": "pep"
}, {
"name": "dFlag",
"type": "text",
"value": "1"
}]
},
"statusCode": {
"code": "200",
"reasonPhrase": "OK"
}
}]
}
Original Question
As said in other question :
EDIT: note also that you can use NGSIv2 to create/update entities at
Orion and have notifications in NGSIv1 if you:
Create the subscription using NGSIv1 operations
Create the subscription using NGSIv2 operations with attrsFormat equal to legacy.
Have a look to more detailed information here.
So I made up this subscription:
curl --include \
--header 'Content-Type: application/json' \
--request POST \
--data-binary '{
"description": "Day subscription",
"subject": {
"entities": [
{
"idPattern": "es-leon-.*",
"type": "Event"
}
],
"condition": {
"attributes": [
"Title",
"dFlag"
],
"expression": {
"q": "dFlag > 0"
}
}
},
"notification": {
"callback": "http://localhost:5050/notify",
"attributes": [
"Title",
"dFlag"
]
}
}' \
'http://localhost:1026/v1/subscriptions'
but orion don't let me register it throwing this error:
HTTP/1.1 400 Bad Request
Connection: Keep-Alive
Content-Length: 67
Content-Type: application/json
Fiware-Correlator: 2ecdfc74-1c2f-11e6-82d7-000d3a23bf27
Date: Tue, 17 May 2016 12:59:25 GMT
{"error":"BadRequest","description":"no condition attrs specified"}
Is this the way to use legacy attributes so it can work with cygnus with NGSIv2?
Thanks for the help.
EDIT 1:
Following the answer the subscription should be like this: Right?
curl --include \
--header 'Content-Type: application/json' \
--request POST \
--data-binary '{
"description": "Day subscription",
"subject": {
"entities": [
{
"idPattern": "es-leon-.*",
"type": "Event"
}
],
"condition": {
"attributes": [
"Title",
"dFlag"
],
"expression": {
"q": "dFlag > 0"
}
}
},
"notification": {
"http": {
"url" : "http://localhost:5050/notify"
},
"attributes": [
"Title",
"dFlag"
],
"attrsFormat":"legacy"
}
}' \
'http://localhost:1026/v2/subscriptions'
But I'm still getting an error:
HTTP/1.1 100 Continue
HTTP/1.1 400 Bad Request
Connection: Keep-Alive
Content-Length: 67
Content-Type: application/json
Fiware-Correlator: 60a0a1d2-1ddf-11e6-8bd6-000d3a23bf27
Date: Thu, 19 May 2016 16:33:11 GMT
{"error":"BadRequest","description":"no condition attrs specified"}
Use attrs instead of attributes (both in subject.conditions and in notification).
In addition, note that callback is no longer used. You have to use:
"notification": {
"http": {
"url": "http://localhost:5050/notify"
},
..
}
In addition, if you want notifications to use NGSIv1 format you should include attrsFormat field with value legacy in notification as described in the documentation.
Finally, note that the rigth operation URL is /v2/subscriptions, not /v1/subscriptions as shown in your example.
EDIT 1: considering the new payload in EDIT 1 section in the question, note that:
You should use attrs inside condition, not attributes (the error message is complaining about that)
You should use attrs inside notification, not attributes
You should use "q": "dFlag>0" (i.e. no whitespaces in the query string). Look to the example in the NGSIv2 specification:
Eg:
"expression": {
"q": "temperature>40"
}
EDIT 2: Orion versions previous to 1.2 use attrsFormat outside notification field. Thus, if you are using Orion 1.1, try to use "attrsFormat": "legacy" as first level field in the subscription payload JSON.