telefonicaid / iotagent-json

IoT Agent for a JSON based protocol (with HTTP, MQTT and AMQP transports)
https://fiware-iotagent-json.rtfd.io/
GNU Affero General Public License v3.0
50 stars 89 forks source link

Differences between `explicitAttrs` behaviour at lib and at agent level #782

Open mapedraza opened 9 months ago

mapedraza commented 9 months ago

IoT Agent JSON version the issue has been seen with

latest

Bound or port used (API interaction)

Southbound (Devices data API)

NGSI version

NGSIv2

Are you running a container?

No, I am running it natively

Image type

None

Expected behaviour you didn't see

When using provisioning a group like this:

{
    resource: '/iot/json',
    apikey: globalEnv.apikey,
    entity_type: globalEnv.entity_type,
    explicitAttrs:
        "(a&&b)?['attr_a','attr_b']:a?['attr_a','static_b']:b?[{object_id:'b'},'c']:['static_a','static_b','d','c']",
    commands: [],
    lazy: [],
    attributes: [
        {
            name: 'attr_a',
            object_id: 'a',
            type: 'Number'
        },
        {
            name: 'attr_b',
            object_id: 'b',
            type: 'Number'
        },
        {
            object_id: 'c',
            type: 'Number'
        }
    ],
    static_attributes: [
        {
            name: 'static_a',
            type: 'Number',
            value: 3
        },
        {
            name: 'static_b',
            type: 'Number',
            value: 4
        }
    ]
}

sending:

{
    c: 3,
    d: 4
}

Unexpected behaviour you saw

It sends to CB (red is not expected)

{
      id: globalEnv.entity_name,
      type: globalEnv.entity_type,
      static_a: {
          value: 3,
          type: 'Number'
      },
      static_b: {
          value: 4,
          type: 'Number'
      }
-    c: {
-        type: 'Number'
-        value: 3
-   }
}

Since c is not provisioned, should not pass to the CB

Instead, in IoTA Node Lib, the behaviour is the oposite (c attribute does not appears)

mapedraza commented 9 months ago

Related: https://github.com/telefonicaid/iotagent-node-lib/pull/1529

AlvaroVega commented 9 months ago

explicitAttrs is not used or modified by iotagent-json; there is no code in iotagent-json that touch it.

mapedraza commented 9 months ago

This PR: https://github.com/telefonicaid/iotagent-node-lib/pull/1531 disables the tests for any other component than IoTA LIB. In other words, now is not executed in IOTA JSON CI, so no failures.

mrutid commented 9 months ago

The rationale behind this is that to be an explicit attribute you must be an actual ATTRIBUTE, in this way it must be provisioned as active or lazy.

The only way a raw/unprovisioned measure, like c, should be propagated is when explicittAttr==false. In any other case just a set/subset of Attrs will be taken into account.

AlvaroVega commented 9 months ago

Provisioning a group like:

        {
            "_id": "655f0d16ecd7dd58a107f483",
            "__v": 0,
            "iotagent": "http://172.17.0.1:4052",
            "apikey": "izc9cokegoy7kyfgdd6etipt6",
            "entity_type": "thing",
            "service_path": "/",
            "service": "smartcity",
            "resource": "/iot/json",
            "description": "miJSON",
            "protocol": "IoTA-JSON",
            "internal_attributes": [],
            "attributes": [
                {
                    "name": "attr_a",
                    "type": "Number",
                    "object_id": "a"
                },
                {
                    "name": "attr_b",
                    "type": "Number",
                    "object_id": "b"
                },
                {
                    "object_id": "c",
                    "name": "attr_c",
                    "type": "Number"
                }
            ],
            "lazy": [],
            "static_attributes": [
                {
                    "name": "static_a",
                    "type": "Number",
                    "value": 3
                },
                {
                    "name": "static_b",
                    "type": "Number",
                    "value": 4
                }
            ],
            "commands": [],
            "timestamp": false,
            "explicitAttrs": "(a&&b)?['attr_a','attr_b']:a?['attr_a','static_b']:b?[{object_id:'b'},'c']:['static_a','static_b','d','c']"
            }
    ],
    "count": 1
}

I've sending the following measure:

 curl -i -X POST 'http://localhost:7897/iot/json?i=dispNew&k=izc9cokegoy7kyfgdd6etipt6' -d '{ "c": 3, "d": 4}' -H 'content-type: application/json'

to a non provisioned device (dispNew), then I've see the following log:

from=n/a | srv=smartcity | subsrv=/ | msg=Options: {
    "url": "http://iot-orion:1026/v2/entities?options=upsert",
    "method": "POST",
    "headers": {
        "fiware-service": "smartcity",
        "fiware-servicepath": "/"
    },
    "json": {
        "id": "thing:dispNew",
        "type": "thing",
        "static_a": {
            "type": "Number",
            "value": 3
        },
        "static_b": {
            "type": "Number",
            "value": 4
        }
    }
} | comp=IoTAgent

Which seems right, isn't it?

AlvaroVega commented 9 months ago

Executing the same functional test, there are some differences between iotagent and library:

iota-json

msg=sendUpdateValueNgsi2 called with: entityName=TestType:TestDevice,  measures={"c":3,"d":4},  typeInformation={"id":"TestDevice","service":"smartgondor","subservice":"/gardens","type":"TestType","transport":"HTTP","apikey":"123456","name":"TestType:TestDevice","staticAttributes":[{"name":"static_a","type":"Number","value":3},{"name":"static_b","type":"Number","value":4}],"commands":[],"lazy":[],"active":[{"name":"attr_a","object_id":"a","type":"Number"},{"name":"attr_b","object_id":"b","type":"Number"},{"object_id":"c","type":"Number","name":"c"}],"subscriptions":[],"explicitAttrs":"(a&&b)?['attr_a','attr_b']:a?['attr_a','static_b']:b?[{object_id:'b'},'c']:['static_a','static_b','d','c']"}, initial jexlContext={"c":3,"d":4,"static_a":3,"static_b":4,"id":"TestDevice","type":"TestType","service":"smartgondor","subservice":"/gardens","entity_name":"TestType:TestDevice"}, timestamp=false with value=undefined

iota-node-lib

msg=sendUpdateValueNgsi2 called with: entityName=TestType:TestDevice,  measures={"c":3,"d":4},  typeInformation={"apikey":"123456","type":"TestType","explicitAttrs":"(a&&b)?['attr_a','attr_b']:a?['attr_a','static_b']:b?[{object_id:'b'},'c']:['static_a','static_b','d','c']","commands":[],"lazy":[],"active":[{"name":"attr_a","object_id":"a","type":"Number"},{"name":"attr_b","object_id":"b","type":"Number"},{"object_id":"c","type":"Number"}],"staticAttributes":[{"name":"static_a","type":"Number","value":3},{"name":"static_b","type":"Number","value":4}]}, initial jexlContext={"c":3,"d":4,"static_a":3,"static_b":4,"type":"TestType"}, timestamp=false with value=undefined

iotagent-json has entity_name, service and subservice in typeInformation and jexlContext, but iota-node-lib case no.