No JSON object could be decoded- orion context broker - fiware

I am trying out orion context broker comunication on two CentOS 6.6 machines. On the target machine I did:
./accumulator-server.py 1028 /accumulate mywebpage.lan on
And on my local machine I did:
[DevF12#localhost ~]$ (curl mywebpage.lan:1028/v1/updateContext -s -S --header 'Content-Type: application/json' --header 'Accept: application/json' -d #- | python -mjson.tool ) <<EOF
> {
> "contextElements": [
> {
> "type": "Room",
> "isPattern": "false",
> "id": "Room2",
> "attributes": [
> {
> "name": "temperature",
> "type": "float",
> "value": "777"
> },
> {
> "name": "pressure",
> "type": "integer",
> "value": "711"
> }
> ]
> }
> ],
> "updateAction": "APPEND"
> }
> EOF
The result on the target machine is:
POST http://mywebpage.lan:1028/v1/updateContext
Content-Length: 456
User-Agent: curl/7.19.7 (x86_64-redhat-linux-gnu) libcurl/7.19.7 NSS/3.16.2.3 Basic ECC zlib/1.2.3 libidn/1.18 libssh2/1.4.2
Host: mywebpage.lan:1028
Accept: application/json
Content-Type: application/json
{ "contextElements": [ { "type": "Room", "isPattern": "false", "id": "Room2", "attributes": [ { "name": "temperature", "type": "float", "value": "777" }, { "name": "pressure", "type": "integer", "value": "711" } ] } ], "updateAction": "APPEND"}=======================================
192.168.1.11 - - [14/Apr/2015 15:07:36] "POST /v1/updateContext HTTP/1.1" 200 -
And the message I get from the local machine is:
No JSON object could be decoded
So, what does this all mean?
1. Is the 200 code saying that it is successfully creating Room2?
2. Why am I getting the could not decode JSON then?
3. All of this brings up another question, does this mean that the weather station described in my previous post also has to run on CentOS in order to send context broker messages?

I think there is a "conceptual" misunderstanding in your test. You are sending the updateContext to 1028 which is not the port of CB (the one supposed to process updateContext messages) but the accumulator port (which purpose is process notifyContext message sent by CB as a consequence of updateContext messages, but not processing updateContext messages themselves).
Typically, Orion Context Broker runs in port 1026 by default.
Taking into account this, the specific answers are:
Is the 200 code saying that it is successfully creating Room2? No. 200 reported by accumulator just mean that the accumulator has received and acknowledge a message (any message, given that accumulator is a "dummy" application just for testing, it is not doing any real processing of that).
Why am I getting the could not decode JSON then? Try to remove | python -mjson.tool in the curl command line.
All of this brings up another question, does this mean that the weather station described in my previous post also has to run on CentOS in order to send context broker messages? Not sure about the "weather station" in your case, but if you mean the client sending updateContext to CB, it doesn't need to run in CentOS. The only requirements for the client is to be compliant with Orion API and have network connectivity to that host (and port) where Orion is listening.

Related

Eclipse Ditto - Create a MQTT Connection - fails with invalid json 400 response

Establishing a connection to an MQTT 3.1.1 endpoint following the description here and
the Operating Devops Commands end up in an invalid json 400 response. Even the example MQTT-Bidirectional gets refused with a 400. So this is why i am posting this question here to get hints what i am currently doing wrong and what i can do to get it right to help others running in the same issue. Here is my curl request:
gd#gd:~/ditto/mosquitto$ curl -X POST 'http://{ditto-url}/devops/piggyback/connectivity?timeout=10000' -u devops:foobar -H 'Content-Type: application/json' -d createMQTT_connection.json
{"status":400,"error":"json.invalid","message":"Failed to parse JSON string 'createMQTT_connection.json'!","description":"Check if the JSON was valid (e.g. on https://jsonlint.com) and if it was in required format."}
The hint to check my json file gives back that my json is valid.
Here is how my json file currently looks like:
{
"targetActorSelection": "/system/sharding/connection",
"headers": {
"aggregate": false
},
"piggybackCommand": {
"type": "connectivity.commands:createConnection",
"connection": {
"id": "mqtt-example-connection-123",
"name": "mmqtt-example-connection-123",
"connectionType": "mqtt",
"connectionStatus": "open",
"failoverEnabled": true,
"uri": "tcp://{mqtt-broker-url}:1883",
"sources": [
{
"addresses": [
"{ditto-url}/#"
],
"authorizationContext": ["nginx:ditto"],
"qos": 0,
"filters": []
}
],
"targets": [
{
"address": "{ditto-url}/{{ thing:id }}",
"topics": [
"_/_/things/twin/events"
],
"authorizationContext": ["nginx:ditto"],
"qos": 0
}
]
}
}
}
Someone got an idea why this json is not valid?
Thanks for the support and hints to solve this issue!
[EDIT]
First of all a "-f" makes more sense for the curl request:
curl -X POST -u devops:foobar 'http://{ditto-url}:8080/devops/piggyback/connectivity?timeout=10000' -f createMQTT_connection_1.json
curl: (22) The requested URL returned error: 400 Bad Request
curl: (6) Could not resolve host: createMQTT_connection_1.json
Second here the update json (with the result shown above)
{
"targetActorSelection": "/system/sharding/connection",
"headers": {
"aggregate": false
},
"piggybackCommand": {
"type": "connectivity.commands:createConnection",
"connection": {
"id": "mqtt-example-connection-123",
"connectionType": "mqtt",
"connectionStatus": "open",
"failoverEnabled": true,
"uri": "tcp://{MQTT-Broker-url}:1883",
"sources": [{
"addresses": ["ditto-tutorial/#"],
"authorizationContext": ["nginx:ditto"],
"qos": 0,
"filters": []
}],
"targets": [{
"address": "ditto-tutorial/{{ thing:id }}",
"topics": [
"_/_/things/twin/events",
"_/_/things/live/messages"
],
"authorizationContext": ["nginx:ditto"],
"qos": 0
}]
}
}
}
I think the problem you face is curl related.
Please have a look here on how to send json data from a file: https://stackoverflow.com/a/18614411/5058051
Seems the # is missing in your case when specifying the file location.

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.

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

Send commands to Context Broker using iotagent-ul

I'm trying to send commands to the Orion Context Broker using iotagent-ul with HTTP protcol.
Context Broker and IoT Agent are in different servers (actually IoTA is in running in my laptop).
I've configured the necessary parameters in config.js file.
My request is as follows:
curl -L POST -H "Fiware-Service: myHome" -H "Fiware-ServicePath: /environment" -H "Content-Type: application/json" -H "Cache-Control: no-cache" -d '{
"devices": [
{
"device_id": "sensor01",
"entity_name": "LivingRoomSensor",
"entity_type": "multiSensor",
"attributes": [
{ "object_id": "t", "name": "Temperature", "type": "celsius" },
{ "object_id": "l", "name": "Luminosity", "type": "lumens" }
]
}
]
}
' 'http://localhost:4061/iot/devices'
It shows the following erros:
In IoTA terminal:
time=2017-02-14T15:06:14.832Z | lvl=ERROR | corr=88ed3729-6682-44ce-9b0a-28098e54c94e | trans=88ed3729-6682-44ce-9b0a-28098e54c94e | op=IoTAgentNGSI.DomainControl | srv=myHome | subsrv=/environment | msg=TypeError: Cannot read property 'findOne' of undefined | comp=IoTAgent
In "cURL terminal":
curl: (52) Empty reply from server
Please can you tell us what's the IoT Agent UL version you are using?
On the other hand, it seems you are missing the 'protocol' field in the payload, please check
http://fiwaretourguide.readthedocs.io/en/latest/connection-to-the-internet-of-things/how-to-read-measures-captured-from-iot-devices/
best

Sending nested JSON object using HTTPie

I am trying to use HTTPie to parse to send some nested JSON object, but I can not find how. It is pretty clear how to send a JSON object but not a nested one such as
{ "user": { "name": "john"
"age": 10 } }
Update for HTTPie 3.0 released in January 2022:
There’s now built-in support for nested JSON using the HTTPie language:
$ http pie.dev/post \
tool[name]=HTTPie \
tool[about][homepage]=httpie.io \
tool[about][mission]='Make APIs simple and intuitive' \
tool[platforms][]=terminal \
tool[platforms][]=desktop \
tool[platforms][]=web \
tool[platforms][]=mobile
{
"tool": {
"name": "HTTPie",
"about": {
"mission": "Make APIs simple and intuitive",
"homepage": "httpie.io"
},
"platforms": [
"terminal",
"desktop",
"web",
"mobile"
]
}
}
You can learn more about nested JSON in the docs: https://httpie.io/docs/cli/nested-json
Old answer for HTTPie older than 3.0:
You can pass the whole JSON via stdin:
$ echo '{ "user": { "name": "john", "age": 10 } }' | http httpbin.org/post
Or specify the raw JSON as value with :=:
$ http httpbin.org/post user:='{"name": "john", "age": 10 }'
I like this way:
$ http PUT localhost:8080/user <<<'{ "user": { "name": "john", "age": 10 }}'
It is preferrable because it has the same prefix as the related commands, and so it is convenient to find the commands with Ctrl+R in bash:
$ http localhost:8080/user/all
$ http GET localhost:8080/user/all # the same as the previous
$ http DELETE localhost:8080/user/234
If you have fishshell, which doesn't have Here Strings, I can propose the following workaround:
~> function tmp; set f (mktemp); echo $argv > "$f"; echo $f; end
~> http POST localhost:8080/user < (tmp '{ "user": { "name": "john", "age": 10 }}')
Another approach mentioned in the httpie docs is using a JSON file; this has worked well for me for payloads that are more verbose and deeply nested.
http POST httpbin.org/post < post.json
On Windows 10 (cmd.exe) the syntax is a little bit different due to quoting rules. Properties/strings need to be surrounded by double quotes.
http -v post https://postman-echo.com/post address:="{""city"":""london""}"
POST /post HTTP/1.1
Content-Type: application/json
Host: postman-echo.com
User-Agent: HTTPie/2.3.0
{
"address": {
"city": "london"
}
}
You can also send the whole object using echo, and without double quoting.
echo {"address": {"city":"london"} } | http -v post https://postman-echo.com/post