2
votes

I am trying to send a command to a device using Orion + Ultralight 2.0. The device is registered and I can send measures easily. I want to work in the pooling mode in order to execute commands, but when I execute the updateContext operation, IDAS doesn't found the entity. Here are the configuration and the logs:

Configuration:

var config = {};

config.mqtt = {
    host: 'mosquitto',
    port: 1883
};

config.http = {
    port: 7896
};

config.iota = {
    logLevel: 'DEBUG',
    timestamp: true,
    contextBroker: {
        host: 'MY_IP',
        port: '1026'
    },
    server: {
        port: 4041
    },
    deviceRegistry: {
        type: 'mongodb'
    },
    mongodb: {
        host: 'mongo',
        port: '27017',
        db: 'iotagentul'
    },
    types: {},
    service: 'howtoService',
    subservice: '/howto',
    providerUrl: 'http://YIP:4041',
    deviceRegistrationDuration: 'P1M',
    defaultType: 'Thing'
};

config.defaultKey = 'TEF';

module.exports = config;

I have tried different IP's and routes, and at the end i tried with the public IP, assuring that there is communication from the outside to those ports.

Device registration:

curl -X POST \
  http://MYIP:4041/iot/devices \
  -H 'cache-control: no-cache' \
  -H 'content-type: application/json' \
  -H 'fiware-service: howtoService' \
  -H 'fiware-servicepath: /howto' \
  -d '{
    "devices": [{
        "device_id": "muvone",
        "protocol": "IoTA-UL",
        "entity_name": "muvone",
        "entity_type": "Thing",
        "attributes": [{
            "object_id": "t",
            "name": "temperature",
            "type": "Float"
        }],
        "commands": [{
            "name":"blink",
            "type": "command",
            "value": "muvone@blink|%s"
        }],
        "static_attributes": []
    }]
}'

Then I send some observations from a physical device and from POSTMAN:

curl -X POST \
  'http://MYIP:7896/iot/d?i=muvone&k=TEF&getCmd=1' \
  -H 'cache-control: no-cache' \
  -H 'fiware-service: howtoService' \
  -H 'fiware-servicepath: /howto' \
  -d 'temperature|16'

Which actually updates the entity correctly, as can be seen in Orion Context Broker: Query:

curl -X GET \
  http://MYIP:1026/v2/entities \
  -H 'cache-control: no-cache' \
  -H 'fiware-service: howtoService' \
  -H 'fiware-servicepath: /howto' \

Response:

[
  {
    "id": "muvone",
    "type": "Thing",
    "TimeInstant": {
      "type": "ISO8601",
      "value": "2017-06-01T11:37:52.537Z",
      "metadata": {}
    },
    "blink_info": {
      "type": "commandResult",
      "value": " ",
      "metadata": {}
    },
    "blink_status": {
      "type": "commandStatus",
      "value": "UNKNOWN",
      "metadata": {}
    },
    "temperature": {
      "type": "Float",
      "value": "16",
      "metadata": {
        "TimeInstant": {
          "type": "ISO8601",
          "value": "2017-06-01T11:37:52.537Z"
        }
      }
    }
  }
]

So now, If I want to send a command, I have done it in a lot of ways. I tried following this guide:

http://fiware-iot-stack.readthedocs.io/en/master/topics/device_connection/index.html

So I tried to use the following request:

curl -X PUT \
  http://MYIP:1026/v2/entities \
  -H 'cache-control: no-cache' \
  -H 'content-type: application/json' \
  -H 'fiware-service: howtoService' \
  -H 'fiware-servicepath: /howto' \
  -d '{
  "id": "muvone",
  "type": "Thing",
  "blink": {
    "type" : "command",
    "value" : "true"
  }
}'

Which response is:

{
  "error": "MethodNotAllowed",
  "description": "method not allowed"
}

So I tried updating a single attribute, in this case the blink attribute, which is a command. This should trigger that the Orion Context Broker acts as a NGSI proxy and passes the request to the IoTAgent, which occurs. But the problem is that the IoTAgent doesn't find the entity, as it can be seen in the logs:

curl -X PUT \
  'http://MYIP:1026/v2/entities/muvone/attrs/blink?type=Thing' \
  -H 'cache-control: no-cache' \
  -H 'content-type: application/json' \
  -H 'fiware-service: howtoService' \
  -H 'fiware-servicepath: /howto' \
  -d '{
    "type": "command",
    "value": "true"
}' 

or

curl -X PUT \
  'http://MYIP:1026/v2/entities/muvone/attrs/blink?type=Thing' \
  -H 'cache-control: no-cache' \
  -H 'content-type: application/json' \
  -H 'fiware-service: howtoService' \
  -H 'fiware-servicepath: /howto' \
  -H 'postman-token: 6b42d06d-2a9f-3081-e315-bd9919aeded5' \
  -d '{
    "value": "true"
}'

Responds with:

{
  "error": "NotFound",
  "description": "The requested entity has not been found. Check type and id"
}

Edit: The get v2/entities to orion result, after issuing these requests is:

[
  {
    "id": "muvone",
    "type": "Thing",
    "TimeInstant": {
      "type": "ISO8601",
      "value": "2017-06-02T10:26:32.212Z",
      "metadata": {}
    },
    "blink_info": {
      "type": "commandResult",
      "value": " ",
      "metadata": {}
    },
    "blink_status": {
      "type": "commandStatus",
      "value": "UNKNOWN",
      "metadata": {}
    },
    "temperature": {
      "type": "Float",
      "value": "26",
      "metadata": {
        "TimeInstant": {
          "type": "ISO8601",
          "value": "2017-06-02T10:26:32.212Z"
        }
      }
    }
  }
]

Now, having a look at Orion and IoTAgent logs, it can be seen that IoTAgent doesn't find the entity:

Orion logs to the request:

time=Thursday 01 Jun 12:10:13 2017.880Z | lvl=INFO | corr=446f4532-46c3-11e7-b1a4-0242ac110003 | trans=1496315963-946-00000000039 | from=pending | srv=pending | subsrv=pending | comp=Orion | op=logMsg.h[1832]:lmTransactionStart | msg=Starting transaction from 91.126.73.210:2880/v2/entities/muvone/attrs/blink
time=Thursday 01 Jun 12:10:13 2017.880Z | lvl=INFO | corr=446f4532-46c3-11e7-b1a4-0242ac110003 | trans=1496315963-946-00000000039 | from=91.126.73.210 | srv=pending | subsrv=/howto | comp=Orion | op=rest.cpp[872]:servicePathSplit | msg=Service Path 0: '/howto'
time=Thursday 01 Jun 12:10:13 2017.881Z | lvl=INFO | corr=446f4532-46c3-11e7-b1a4-0242ac110003 | trans=1496315963-946-00000000039 | from=91.126.73.210 | srv=howtoservice | subsrv=/howto | comp=Orion | op=connectionOperations.cpp[237]:collectionCount | msg=Database Operation Successful (count: { _id.id: "muvone", _id.type: "Thing", _id.servicePath: { $in: [ /^/howto$/ ] } })
time=Thursday 01 Jun 12:10:13 2017.881Z | lvl=INFO | corr=446f4532-46c3-11e7-b1a4-0242ac110003 | trans=1496315963-946-00000000039 | from=91.126.73.210 | srv=howtoservice | subsrv=/howto | comp=Orion | op=connectionOperations.cpp[92]:collectionQuery | msg=Database Operation Successful (query: { _id.id: "muvone", _id.type: "Thing", _id.servicePath: { $in: [ /^/howto$/ ] } })
time=Thursday 01 Jun 12:10:13 2017.881Z | lvl=INFO | corr=446f4532-46c3-11e7-b1a4-0242ac110003 | trans=1496315963-946-00000000039 | from=91.126.73.210 | srv=howtoservice | subsrv=/howto | comp=Orion | op=connectionOperations.cpp[175]:collectionRangedQuery | msg=Database Operation Successful (query: { query: { $or: [ { contextRegistration.entities: { $in: [ { id: "muvone", type: "Thing" }, { type: "Thing", id: "muvone" } ] } }, { contextRegistration.entities.id: { $in: [] } } ], expiration: { $gt: 1496319013 }, contextRegistration.attrs.name: { $in: [ "blink" ] }, servicePath: { $in: [ /^/howto$/ ] } }, orderby: { _id: 1 } })
time=Thursday 01 Jun 12:10:13 2017.882Z | lvl=INFO | corr=446f4532-46c3-11e7-b1a4-0242ac110003 | trans=1496315963-946-00000000040 | from=pending | srv=pending | subsrv=pending | comp=Orion | op=logMsg.h[1832]:lmTransactionStart | msg=Starting transaction to http://MYIP:4041//updateContext
time=Thursday 01 Jun 12:10:13 2017.882Z | lvl=INFO | corr=446f4532-46c3-11e7-b1a4-0242ac110003 | trans=1496315963-946-00000000040 | from=pending | srv=pending | subsrv=pending | comp=Orion | op=httpRequestSend.cpp[577]:httpRequestSendWithCurl | msg=Sending message 14 to HTTP server: sending message of 558 bytes to HTTP server
time=Thursday 01 Jun 12:10:13 2017.886Z | lvl=INFO | corr=446f4532-46c3-11e7-b1a4-0242ac110003 | trans=1496315963-946-00000000040 | from=pending | srv=pending | subsrv=pending | comp=Orion | op=httpRequestSend.cpp[598]:httpRequestSendWithCurl | msg=Notification Successfully Sent to http://MYIP:4041//updateContext
time=Thursday 01 Jun 12:10:13 2017.886Z | lvl=INFO | corr=446f4532-46c3-11e7-b1a4-0242ac110003 | trans=1496315963-946-00000000040 | from=pending | srv=pending | subsrv=pending | comp=Orion | op=logMsg.h[1916]:lmTransactionEnd | msg=Transaction ended
time=Thursday 01 Jun 12:10:13 2017.886Z | lvl=WARN | corr=N/A | trans=N/A | from=N/A | srv=N/A | subsrv=N/A | comp=Orion | op=postUpdateContext.cpp[225]:updateForward | msg=Internal Error (error parsing reply from prov app: )
time=Thursday 01 Jun 12:10:13 2017.886Z | lvl=INFO | corr=N/A | trans=N/A | from=N/A | srv=N/A | subsrv=N/A | comp=Orion | op=logMsg.h[1916]:lmTransactionEnd | msg=Transaction ended

IDAS log:

time=2017-06-01T12:10:13.882Z | lvl=DEBUG | corr=446f4532-46c3-11e7-b1a4-0242ac110003 | trans=8dcc19e7-e3ce-472a-a1bb-c7983dad7025 | op=IoTAgentNGSI.GenericMiddlewares | srv=howtoservice | subsrv=/howto | msg=Request for path [//updateContext] from [MYIP:4041] | comp=IoTAgent
time=2017-06-01T12:10:13.882Z | lvl=DEBUG | corr=446f4532-46c3-11e7-b1a4-0242ac110003 | trans=8dcc19e7-e3ce-472a-a1bb-c7983dad7025 | op=IoTAgentNGSI.GenericMiddlewares | srv=howtoservice | subsrv=/howto | msg=Body:

{
    "contextElements": [
        {
            "type": "Thing",
            "isPattern": "false",
            "id": "muvone",
            "attributes": [
                {
                    "name": "blink",
                    "type": "command",
                    "value": "true"
                }
            ]
        }
    ],
    "updateAction": "UPDATE"
}

 | comp=IoTAgent
time=2017-06-01T12:10:13.883Z | lvl=DEBUG | corr=446f4532-46c3-11e7-b1a4-0242ac110003 | trans=8dcc19e7-e3ce-472a-a1bb-c7983dad7025 | op=IoTAgentNGSI.ContextServer | srv=howtoservice | subsrv=/howto | msg=Handling update from [MYIP:4041] | comp=IoTAgent
time=2017-06-01T12:10:13.883Z | lvl=DEBUG | corr=446f4532-46c3-11e7-b1a4-0242ac110003 | trans=8dcc19e7-e3ce-472a-a1bb-c7983dad7025 | op=IoTAgentNGSI.ContextServer | srv=howtoservice | subsrv=/howto | msg=[object Object] | comp=IoTAgent
time=2017-06-01T12:10:13.883Z | lvl=DEBUG | corr=446f4532-46c3-11e7-b1a4-0242ac110003 | trans=8dcc19e7-e3ce-472a-a1bb-c7983dad7025 | op=IoTAgentNGSI.MongoDBDeviceRegister | srv=howtoservice | subsrv=/howto | msg=Looking for entity with name [muvone]. | comp=IoTAgent
time=2017-06-01T12:10:13.883Z | lvl=DEBUG | corr=446f4532-46c3-11e7-b1a4-0242ac110003 | trans=8dcc19e7-e3ce-472a-a1bb-c7983dad7025 | op=IoTAgentNGSI.MongoDBDeviceRegister | srv=howtoservice | subsrv=/howto | msg=Entity [muvone] not found. | comp=IoTAgent
time=2017-06-01T12:10:13.884Z | lvl=DEBUG | corr=446f4532-46c3-11e7-b1a4-0242ac110003 | trans=8dcc19e7-e3ce-472a-a1bb-c7983dad7025 | op=IoTAgentNGSI.ContextServer | srv=howtoservice | subsrv=/howto | msg=There was an error handling the update action: [object Object]. | comp=IoTAgent
time=2017-06-01T12:10:13.884Z | lvl=DEBUG | corr=446f4532-46c3-11e7-b1a4-0242ac110003 | trans=8dcc19e7-e3ce-472a-a1bb-c7983dad7025 | op=IoTAgentNGSI.ContextServer | srv=howtoservice | subsrv=/howto | msg=Update error [ENTITY_NOT_FOUND] handing request: The entity with the requested id [muvone] was not found. | comp=IoTAgent
time=2017-06-01T12:10:13.884Z | lvl=DEBUG | corr=446f4532-46c3-11e7-b1a4-0242ac110003 | trans=8dcc19e7-e3ce-472a-a1bb-c7983dad7025 | op=IoTAgentNGSI.DomainControl | srv=howtoservice | subsrv=/howto | msg=response-time: 2 | comp=IoTAgent

In the mongo database, it can be seen that the registrations, entities and everything is set up correctly.

I have worked around this issue for days with no result. Any help will be appreciated. Thanks in advance

UPDATE

After using the v1 of the Orion API, the result is the same that the given by v2:

curl -X POST \
  http://MYIP:1026/v1/updateContext \
  -H 'cache-control: no-cache' \
  -H 'content-type: application/json' \
  -H 'fiware-service: howtoService' \
  -H 'fiware-servicepath: /howto' \
  -d '{
    "contextElements": [
        {
            "type": "Thing",
            "isPattern": "false",
            "id": "muvone",
            "attributes": [
                {
                    "name": "blink",
                    "type": "command",
                    "value": "true"
                }
            ]
        }
    ],
    "updateAction": "UPDATE"
} '

Result:

{
  "errorCode": {
    "code": "404",
    "reasonPhrase": "No context element found"
  }
}

2nd UPDATE I have a service that sends the commands that I issue to the context broker. The difference is that if the command is defined in the device, it responses with the 404 error, but if it is not defined in the preprovision, it responds with the code 472:

Undefined command

curl -X POST \
  http://localhost:3000/api/devices/1111/sendCommand/update_firmware \
  -H 'cache-control: no-cache' \
  -H 'content-type: application/json' \
  -d '{
    "value":"example value"
}'

472:

{
  "contextResponses": [
    {
      "contextElement": {
        "type": "Thing",
        "isPattern": "false",
        "id": "muvone",
        "attributes": [
          {
            "name": "update_firmware",
            "type": "command",
            "value": ""
          }
        ]
      },
      "statusCode": {
        "code": "472",
        "reasonPhrase": "request parameter is invalid/not allowed",
        "details": "action: UPDATE - entity: [muvone, Thing] - offending attribute: update_firmware"
      }
    }
  ]
}

Defined command:

curl -X POST \
  http://localhost:3000/api/devices/1111/sendCommand/blink \
  -H 'cache-control: no-cache' \
  -H 'content-type: application/json' \
  -d '{
    "value":"asd"
}'

404:

{
  "errorCode": {
    "code": "404",
    "reasonPhrase": "No context element found"
  }
}
2
could you edit your question post to include the GET /v2/entities result after you do the PUT /v2/entities/muvone/attrs/blink?type=Thing, please? Thx!fgalan
Updated and edited. The result doesn't show any different information that I can noticeJoseBenitez
New update. Defined command gives a 404 and undefined command gives 472JoseBenitez

2 Answers

2
votes

I found the solution to this issue, and I think it must be considered as a bug. It was a problem with camelcases. In my case, I was using the headers howtoService for the Fiware-service header, and in the database was stored correctly:

{ "_id" : ObjectId("5935316c4cfcb20001ec6181"), "polling" : true, "transport" : "HTTP", "protocol" : "IoTA-UL", "internalId" : null, "registrationId" : "5935316c5937ac933167d477", "subservice" : "/howto", "service" : "howtoService", "name" : "muvone", "type" : "Thing", "id" : "muvone", "creationDate" : ISODate("2017-06-05T10:24:44.336Z"), "subscriptions" : [ ], "staticAttributes" : [ ], "commands" : [ { "object_id" : "blink", "value" : "muvone@blink|%s", "type" : "command", "name" : "blink" } ], "active" : [ { "type" : "Float", "name" : "temperature", "object_id" : "ta" } ], "__v" : 0 }

But, when the operation from the IOTAgent comes, it uses lowercase, resulting in a Not found operation from mongo filters:

{ "op" : "query", "ns" : "iotagentul.devices", "query" : { "find" : "devices", "filter" : { "subservice" : "/howto", "service" : "howtoservice", "name" : "muvone" }, "projection" : { "__v" : 0 }, "limit" : 1, "batchSize" : 1, "singleBatch" : true }, "keysExamined" : 0, "docsExamined" : 1, "cursorExhausted" : true, "keyUpdates" : 0, "writeConflicts" : 0, "numYield" : 0, "locks" : { "Global" : { "acquireCount" : { "r" : NumberLong(2) } }, "Database" : { "acquireCount" : { "r" : NumberLong(1) } }, "Collection" : { "acquireCount" : { "r" : NumberLong(1) } } }, "nreturned" : 0, "responseLength" : 124, "protocol" : "op_query", "millis" : 0, "execStats" : { "stage" : "LIMIT", "nReturned" : 0, "executionTimeMillisEstimate" : 0, "works" : 3, "advanced" : 0, "needTime" : 2, "needYield" : 0, "saveState" : 0, "restoreState" : 0, "isEOF" : 1, "invalidates" : 0, "limitAmount" : 1, "inputStage" : { "stage" : "PROJECTION", "nReturned" : 0, "executionTimeMillisEstimate" : 0, "works" : 3, "advanced" : 0, "needTime" : 2, "needYield" : 0, "saveState" : 0, "restoreState" : 0, "isEOF" : 1, "invalidates" : 0, "transformBy" : { "__v" : 0 }, "inputStage" : { "stage" : "COLLSCAN", "filter" : { "$and" : [ { "name" : { "$eq" : "muvone" } }, { "service" : { "$eq" : "howtoservice" } }, { "subservice" : { "$eq" : "/howto" } } ] }, "nReturned" : 0, "executionTimeMillisEstimate" : 0, "works" : 3, "advanced" : 0, "needTime" : 2, "needYield" : 0, "saveState" : 0, "restoreState" : 0, "isEOF" : 1, "invalidates" : 0, "direction" : "forward", "docsExamined" : 1 } } }, "ts" : ISODate("2017-06-05T10:40:37.401Z"), "client" : "172.17.0.4", "allUsers" : [ ], "user" : "" }

After updating in database the howtoService to howtoservice, the command works properly

0
votes

Not sure what I'm going to say would solve your problem, but some things to take into account, after reading your question:

  • It is normal that PUT /v2/entities results in "Method not allowed". Take into account that according to the NGSIv2 specification, the /v2/entities URL only accept to verbs: GET (to retrieve a list of entities) and POST (to create new entities). This is not the way of updating existing entities.
  • Regarding the "Not found" error you get upon PUT /v2/entities/muvone/attrs/blink?type=Thing, please have a look to this issue report. According to that information, the command is progressed and, in fact, that is happening in your case (as the second line in the IOTA log shows).