w3c / wot-thing-description

Web of Things (WoT) Thing Description
http://w3c.github.io/wot-thing-description/
Other
131 stars 63 forks source link

Supporting complex/structured types in simple protocols #1936

Open egekorkan opened 9 months ago

egekorkan commented 9 months ago

Relates to #1930.

Some devices do not support complex/structured types but device manufacturers do some "adjustments" to accommodate that. Something we see in Modbus devices is that object-like data is split into multiple registers where one set contains one "key" of the object and the other contains another "key". There is an example at the end where 3 registers contain the voltage value and another 3 contain a timestamp in Unix time.

This is part of the data mapping discussion, but we need an object data schema that maps one key to one set of registers and the other key to the others.

modbus-complex

Also available publicly at https://cache.industry.siemens.com/dl/files/595/34261595/att_951630/v1/manual_pac4200_en-US_en-US.pdf on page 161 (Table A- 17)

lu-zero commented 9 months ago

This is a good example of a data map in the read direction, if we consider adding an expression-filter on top of mapping we could provide conversions from bytes to float and integer.

Kaz040 commented 8 months ago

This issue is being discussed in relations to PROFINET also. a resource in a profinet device can be an object. the definition of the object payload is always provided in the device manual. an example is this SITOP device, https://cache.industry.siemens.com/dl/files/415/84977415/att_906547/v1/A5E37775406-7-76_MANUAL_SITOP-UPS1600-UPS1100_en-US.pdf on page 130.

The first parameter --> Buffering parameters

image

is a complex payload. inside it are parameters defined in the table below

image.

so to be able to capture what each byte or byte stream from the payload mean, terms like profinet : offset, profinet : byte or profinet : length (decision not made yet on term name) and profinet : bit, can be profinet : bitmask are to be introduced. To do this, the definition has to be at dataSchema level.

My question now is, should these terms be protocol specific or generic for payloads in byte streams?

relu91 commented 8 months ago

My question now is, should these terms be protocol specific or generic for payloads in byte streams?

My gut feeling is that we can find some generic way to support this across different protocols and collecting usecase/examples in from different stacks should help us achieve that. On the other hand, generalizing has its own drawbacks which we should be aware of and instruct the TD user about.

Btw I want to mention that in node-wot we are starting to explore this feature. Right now it is very rough, we accepted one PR where we introduced a way to encode objects in octet-stream content-types and we are about to accept a second one. We are taking a bottom-up approach to see something moving. I'm not saying that this is the right solution, but it is just to link the issues and let the community be aware of our steps.

lu-zero commented 8 months ago

My question now is, should these terms be protocol specific or generic for payloads in byte streams?

We have the protocol driving the in-wire serialization, the contentType that should describe the format from the bytes (with contentCoding if we have some compression in the middle) and then we have the dataschema that describes the structure once-de/serialized according to the format (e.g. from json/yaml/xml/etc).

I'm wary of adding our custom contentTypes and I'd rather reuse the datamapper concept even for this purpose since it is a special case of extracting from the logic schema and mapping items to the various side/main channels.

Kaz040 commented 3 months ago

As an update. The example below shows how a resource with complex/object payload is handled in profinet binding. all protocol specific definition have now being moved to forms.

{
    "@context": [
      "https://www.w3.org/2019/wot/td/v1",
      {
        "profv" : "https://profinet_vocabulary_context"
      }
    ],
    "@type": "tm:ThingModel",
    "title": "Soft starters switching devices",
    "id": "{{ID}}",
    "base": "profinet://192.168.0.100",
    "securityDefinitions": {
      "nosec_sc": {
        "scheme": "nosec"
      }
    },
    "security": "nosec_sc",
    "properties": {
      "DataSet 131-141-151": {
      "title": "Parameter basic functions",
      "type": "object",
      "properties" : {
        "Rated operational current": {
            "type" :  "integer",
            "unit" : "A"
            },
        "Non volatile tripping status9": {
          "type" :  "integer" 
          },
        "Response to overload thermal motor model": {
          "type" :  "integer"
          },
        "Response to faulty main power": {
          "type" :  "integer"
          },
        "Tripping class": {
          "type" :  "integer",
          "enum" : [0,1,2,3,15]
          },
        "Recovery time9": {
          "type" :  "integer",
          "unit" : "s",
          "minimum" : 2,
          "maximum" : 60
          }
      },
      "forms": [
        {
          "op": [
            "writeproperty",
            "readproperty"
          ],
          "href": "profinet://127.0.0.1/0/1?api=0&index=1&datalength=200",
          "profv:type": "complex",
          "profv:pollingTime": 200,
          "profv:caching" : 1000,
          "profv:payloadMapping" : {
            "Tripping class": {
              "profv:type": "Integer8",
              "profv:offset": 19,
              "profv:byte" : 1,
              "profv:enumeratedValue":[    
                  {
                    "profv:encondedPayload" : 0,
                    "profv:decodedPayload" : "CLASS 10E"
                  },
                  {
                    "profv:encondedPayload" : 1,
                    "profv:decodedPayload" : "CLASS 20E"
                  },
                  {
                    "profv:encondedPayload" : 2,
                    "profv:decodedPayload" : "CLASS 30E"
                  },
                  {
                    "profv:encondedPayload" : 3,
                    "profv:decodedPayload" : "CLASS 10A"
                  },
                  {
                    "profv:encondedPayload" : 15,
                    "profv:decodedPayload" : "CLASS OFF"
                  }
                ]
              }
          }
        }
      ]
       }
    }
}

The properties of object property affordance shows all parameters that can exist in the object payload. The payloadMapping parameter defined in forms shows the interested parameter(s) from the list of parameters in the payload. The enumeratedValue shows the encoded and decoded logic of the payload.

My question now is, should these terms be protocol specific or generic for payloads in byte streams?

about this, in my opinion, because these protocols (mostly field level protocols) define their data types in different form, I think generalizing might bring data types problem in the future.

Any opinion on if this is good or if there is a better way to do it? I think this same issue will also exist for Modbus since some Modbus devices provide complex or struct types as @egekorkan shown in the first comment.

lu-zero commented 3 months ago

One of my wishes for wot 2.0 is to have a clear way to describe both the affordance logical data schema and how it maps to at the protocol level. Profinet seems a good use-case for it.

danielpeintner commented 2 months ago

Sidenote: related to this @derwehr implemented support for "objects" in octet-stream codec in node-wot (see also README).