Search code examples
fiwarefiware-orion

Can IoT device with different protocols use IoT Agents to "talk" with each other?


I'm playing around with FIWARE Orion, IoT Agent JSON, and IoT Agent OPC UA. I'm wondering that since all the IoT Agents connect with Orion and map different IoT protocols into NGSI, is it possible for devices using different protocols to communicate with each other without adding any additional application logic?

Let's consider a MQTT device A and an OPC UA server B, For example, is it possible for:

  1. B reports its measurements to the Orion Context Broker, A subscribe to that attribute. Some thing like B-->IoT Agent OPC UA-->Orion-->IoT Agent JSON-->mosquitto-->A (I tried to make a context provider registration. However, the url of the B entity attributes(orion:1026/v2/B/attrs/XXX) obviously doesn't work since Orion will send POST to an orion:1026/v2/B/attrs/XXX/op/query which doesn't exist), and the provided attribute is not provisioned at IoT Agent JSON...I feel like I'm taking the totally wrong direction)

  2. A and B access the same entity and report their measurements to that entity in the Orion. Since A and B both need their own IoT Agents, and the same entity can not be provisioned at each agent due to duplicated...

Is it a super bad idea that trying to mess up one entity with several protocols' devices...Thank you so much for answering my doubts in advance!!!


Solution

  • Each NGSI entity should map to something that has state in the real world. In your case your data models should be based on Device and you should have a separate OPC-UA-based Device entity and a second separate JSON Device entity. These are the low level entities within your system, which would hold readings from the IoT Devices and would also hold additional data (such as battery-level or a link to the documentation or whatever).

    If you want to model the state of a second aggregated entity then you can do that as well - just subscribe to changes in context in the device and Upsert the values and metadata over to the other entity.

    curl --location --request POST 'http://localhost:1027/v2/subscriptions/' \
    --header 'Content-Type: application/json' \
    --header 'fiware-service: openiot' \
    --data-raw '{
      "description": "Notify Subscription Listener of Lamp context changes",
      "subject": {
        "entities": [
          {
            "idPattern": "Lamp.*"
          }
        ],
        "condition": {
          "attrs": ["luminosity"]
        }
      },
      "notification": {
        "http": {
          "url": "http://tutorial:3000/device/subscription/luminosity"
        },
        "attrs": ["luminosity", "controlledAsset", "supportedUnits"]
      },
      "throttling": 5
    }'
    

    Sample code to do the work from the listening endpoint ( /device/subscription/luminosity ) can be found here - it is a tutorial which is still a work-in-progress, so the full documentation is currently missing.

    function shadowDeviceMeasures(req, res) {
      const attrib = req.params.attrib;
    
      async function copyAttributeData(device, index) {
        await upsertDeviceEntityAsLD(device);
        if (device[attrib]) {
          await upsertLinkedAttributeDataAsLD(device, 'controlledAsset', attrib);
        }
      }
    
      req.body.data.forEach(copyAttributeData);
      res.status(204).send();
    }
    

    The point here is that you can (and should) think of data entities at different levels -

    • I have a thermometer Device - it is sending temperature readings. It has a temperature attribute
    • I have a Building - it has a thermometer in it - the Building has a temperature attribute and metadata.providedBy linking back to the Device

    Depending on your use case you may only need to consider entities at one layer or you may need to use both.