Open hspaay opened 3 years ago
This is a really great question, and something which comes up a lot in WebThings where we have around 100 adapter add-ons bridging different protocols to the Web of Things.
I've always tried to be quite strict that properties should only represent external physical state of a device in the real world, not internal logical state or software/firmware settings. As you note, representing every configuration option or internal setting as a property quickly becomes unwieldy.
It has been difficult to enforce this however since there is no standards-based way to represent those internal logical values in thing descriptions or our Web Thing API. This led to the creation of a "visible" attribute on thing descriptions (not sure how they snuck that in without me noticing!) which configures whether or not a given property appears in the UI. But like your suggestions above that is a non-standard solution and it would be great to have a consensus on how to deal with this kind of thing.
Sorry for not seeing the StackOverflow post, even though I follow the tag I don't get any notifications...
I think at least a convention on this would be well appreciated. Semantic annotations could be one, annotating some properties as configuration so that most user interfaces can ignore them.
P.S. there is a separate way to get emails on SO, so I have enable them now too.
Indeed, this is a very interesting question. As @egekorkan mentioned you can use @type
for providing property's context / category. E.g.,
{
...
"properties": {
"sensor1": {
"@type": "sensors",
"title": "Temperature value",
"type" : "number"
...
},
"sensor2": {
"@type": "sensors",
"title": "Humidity value",
"type" : "number"
....
},
"parameter1": {
"@type": "configuration",
"title": "Sampling rate temperature sensor",
...
},
"parameter2": {
"@type": "configuration",
"title": "Sampling rate humidity sensor"",
....
},
"att1": {
"@type": "attributes",
...
},
"engine": {
"@type": "actuators",
...
},
...
}
If the consumer shares the same 'ZWave' context knowledge (typically announced in @context) then the consumer can simple sort / identify the properties by the specific category.
I'd also go with appropriate semantic annotations, hands down. What @sebastiankb is proposing is reasonable, I'd want to add that if you have a single endpoint to read/write those parameters you can offer a more compact interface:
{
"properties": {
"configuration": {
"@type": "zwave:Configuration",
"type": "object",
"properties": { /* describe here the parameters */}
"forms": [
{
/* your single endpoint here */
}
]
}
},
}
I think it goes along more with what you had in mind and if you have complete control on the API you could even maintain the ability to read/write only a subset of those values. For example, using uriVariables and not required properties in your data schema. Plus you are using the standard 😄
Sorry for not seeing the StackOverflow post, even though I follow the tag I don't get any notifications...
I don't get those either.... I also have the StackExchange app on my phone... I expected to get at least a phone notification. It seems that StackOverflow is more polite than it should 🤣
Thank you all for the great comments! If the goal is to have interoperability between Things and consumers there is probably a need to establish a standard.
@benfrancis "properties should only represent external physical state of a device"
Oh wow that is an eye opener! It does raise the question how would you represent device internal state and information if you stick to this constraint? It looks like this intent is not universally shared though.
@egekorkan Is a convention able to guarantee interoperability between Things and consumers? If it can still lead to different interpretations and methods of classifying properties then my concerns is that consumers must know all possible ways a convention is used in order for this too work. That is probably not going to happen.
@sebastiankb using "@type" is a good suggestion and can work well. Of course it does need a definition of what can be used as type but at the same time open ended enough to support other use cases. Without defining the common values it would have the same concern that consumers must be able to understand how to use other values. Can these values be defined as part of the standard with being open to extension?
@relu91 Using a single property for configuration is indeed another option. In this case the 'configuration' property name still needs to be standardized otherwise you run into interoperability issues with consumers.
Most importantly for interoperability, there should be a single way of identifying the intended purpose of a property to the consumer. How can this be accomplished?
As for SO, I find it is not really suitable for open discussions. Things get downvoted rather quickly to put it mildly. Are you open to enabling the discussion feature on github? (although I noticed that also doesn't notify...)
FYI, these are the property types that I've identified for use with the WoST Hub:
As mentioned before, this list is extensible, but these are the predefined values for "@type". (Assuming this is going to be the chosen convention)
@sebastiankb using "@type" is a good suggestion and can work well. Of course it does need a definition of what can be used as type but at the same time open ended enough to support other use cases. Without defining the common values it would have the same concern that consumers must be able to understand how to use other values. Can these values be defined as part of the standard with being open to extension?
@relu91 Using a single property for configuration is indeed another option. In this case the 'configuration' property name still needs to be standardized otherwise you run into interoperability issues with consumers.
Good points let me try to answer both. So about my comment, you would use the @type
value to understand the semantic of that property. No need to standardize the property name, I think it would be anti-pattern cause you can already use @type
.
Now about @type
, it is not just a random JSON property. I am assuming that you're not familiar with Semantic Web/Linked-Data technologies or JSON-LD, I'll be very brief just to have a common definition background. So, basically, in the semantic web, you can define what are called vocabularies (or more formally ontologies) which define a set of terms to be used in a particular context. As normal language vocabularies do, ontologies define the meaning of terms in a machine-understandable format. Usually, they are built from domain experts after long discussions with stakeholders and users. One example of such ontology is SSN which can even be used in our TDs to tag affordances or payloads (check this TD for example). The @type
keyword means that the object is an instance of the concept described in the reference vocabulary. Therefore taking again my example:
{ "properties": { "configuration": { "@type": "zwave:Configuration", "type": "object", "properties": { /* describe here the parameters */} "forms": [ { /* your single endpoint here */ } ] } }, }
Here what I am saying is that it exist one vocabulary called zwave
and in such vocabulary, it is defined the term Configuration
.
The take-away is that @type
values are not just a tag but they convey meaning which can be used to interpret the content of that ojbect. Notice that all of this is not coming from the WoT spec but rather from the JSON-LD community and the Semantic Web as whole.
Now you could say: "Well than we need to define a vocabulary that is well understood and accepted for the community. There we can define those common terms like configuration/state". That's right! I proposed a layered approach to extend the TD vocabulary with commonly used IoT terms a while ago. However, after the last vF2F, we learned that iotschema is recharting and @mjkoster asked the WoT community to actively contribute there, (right @mjkoster ? ). I would say that the list of terms you're proposing should be added to iotschema rather than the standard TD vocabulary so that it can be used even outside WoT contexts.
I hope it makes sense.
@relu91 Thank you for the explanation. I did indeed not delve into the rabbit hole details of JSON-LD.
The "@type" keyword means that the object is an instance of the concept described in the reference vocabulary. ... Here what I am saying is that it exist one vocabulary called zwave and in such vocabulary, it is defined the term Configuration.
Yes I now see what you mean, and the layered approach makes sense. The TD does not have knowledge what it is used for as that is expressed through the reference vocabulary that is identified with "@type" (and at the higher level with "@context" I assume). The TD is merely the framework to place this.
Does this also means that the TD is too abstract to be used directly to describe an IoT device? Does it require a standard like iotschema to be useful for this? It looks like the answer is yes.
As a side note, I looked at the FiWare project a while back, also based on JSON-LD and ran into the headache challenge of determining what schema to use. There seems to be little standardization with the schemas and many are incomplete. 'schema.org' being the obvious one but not aimed at IoT.
One more question if I may: since the purpose of the TD is to describe IoT 'Things' (correct me if that is wrong) and 'properties', 'actions' and 'events' are fundamental enough to IoT to be part of the TD vocabulary, why should the breakdown of Things into sensors, actuators, inputs, outputs, configuration and state be relegated to a schema vocabulary? Are they not also fundamental to any IoT device?
Thanks again for the explanations, it is much appreciated!
Does this also means that the TD is too abstract to be used directly to describe an IoT device? Does it require a standard like iotschema to be useful for this? It looks like the answer is yes.
I would also say yes.
Regarding the different types of interactions you list, we could have gone more granular in the beginning but the decision was not to. The hope is that all those interactions can be mapped to one of property, action, event. If it cannot be mapped, we have a problem 😅
@hspaay wrote:
FYI, these are the property types that I've identified for use with the WoST Hub:
* sensor - external state of Thing; readonly * actuator - external state of Thing, change with action; readonly * input - action property to pass parameters; or Thing input values; writable * output - Thing output value, when Thing is not a sensor or actuator; readonly
In WebThings we don't really differentiate between these types of property explicitly. Sensor values are read-only properties, whereas properties which represent actuator state may be writable. The data schema for the input of a property is modelled in its top level DataSchema
and the output can be modelled as an ExpectedResponse
in a form if different from the input. An action is only used to modify a property if setting the property with a writeproperty
operation is not sufficient on its own. Where actions are needed, the ActionAffordance
has input
and output
members.
If you want to explicitly tell a consumer that a device is a sensor or actuator then iotschema.org already have schemas for that which you could use in semantic annotations using @type
.
{
"@context": ["http://www.w3.org/ns/td", {"schema": "http://iotschema.org" }],
"id": "urn:dev:ops:32473-WoTTempSensor-1234",
"@type": "Sensor"
"title": "My Temperature Sensor",
"securityDefinitions": {
"basic_sc": {"scheme": "basic", "in": "header"}
},
"security": "basic_sc",
"properties": {
"temperature": {
"type": "number",
"readOnly": "true",
"forms": [{"href": "https://temperaturesensor.example.com/properties/temperature"}]
}
}
}
* state - dynamic Thing internal state; readonly * attr - static Thing descriptive attribute; readonly * configuration - Thing configuration; writable
These are all types of internal logical state which I try to avoid modelling as properties, because they can soon get out of hand and really clutter the representation of a thing in the UI. I agree there's a real need to differentiate these in some way.
If semantic annotations are the solution then there definitely needs to be a common schema for these (e.g. at iotschema.org), since if every implementation uses different @type
s then the problem is not really solved.
The only alternative I can think of is adding a separate list of affordances alongside properties which is called something else, e.g.
{
"@context": "http://www.w3.org/ns/td",
"id": "urn:dev:ops:32473-WoTLamp-1234",
"title": "MyLampThing",
"securityDefinitions": {
"basic_sc": {"scheme": "basic", "in": "header"}
},
"security": "basic_sc",
"properties": {
"on": {
"type": "string",
"forms": [{"href": "https://mylamp.example.com/properties/on"}]
}
},
"actions": {
"toggle": {
"forms": [{"href": "https://mylamp.example.com/actions/toggle"}]
}
},
"events":{
"overheated":{
"forms": [{
"href": "https://mylamp.example.com/events/overheated",
"subprotocol": "longpoll"
}]
}
},
"configuration": {
"staticIP": {
"type": "string",
"forms": [{"href": "https://mylamp.example.com/configuration/ip"}]
},
"subnetMask": {
"type": "string",
"forms": [{"href": "https://mylamp.example.com/configuration/subnet"}]
},
"defaultGateway": {
"type": "string",
"forms": [{"href": "https://mylamp.example.com/configuration/gateway"}]
},
"wifiSSID": {
"type": "string",
"forms": [{"href": "https://mylamp.example.com/configuration/ssid"}]
},
"wifiPassword": {
"type": "string",
"forms": [{"href": "https://mylamp.example.com/configuration/wifipassword"}]
},
"mDNSBroadcastEnabled": {
"type": "boolean",
"forms": [{"href": "https://mylamp.example.com/configuration/broadcast"}]
}
}
}
@egekorkan @benfrancis Thank you so much for your explanation. It clearly explains what is part of the TD and what is not. The various suggestions also help to add context and insight on how to build a TD. Since my objective is interoperability (after security) there is still work to do on the iotschema side to build a hub with plugins that are indeed interoperable. I've taken a look at iotschema.org (along with other schema definitions) and I have some difficulties to identify a vocabulary that would be a good common ground. I'll work with what I'm able to identify though.
My last thoughts on this is that: Unfortunately, any vocabulary that is considered out of scope for the TD lowers the changes of interoperability between Things and Consumers. 'if you ask a herd of cats to travel together then they will end up all over the place. Provide them with a single path to go and they might actually get there' :wink:
Thank you again, I much appreciate your willingness to explain.
I agree that we should take an approach of at least promoting a vocabulary while staying open for others to use other vocabularies
@egekorkan I'd welcome that. As I'm implementing a hub with protocol bindings I'm looking for a recommendation.
I've asked this on Stackoverflow but the rather underwhelming response made me ask this here.
There is a difference in how various properties in the TD are used, depending on what they describe. Sensor and actuator properties are presented to the user different from configuration options or Thing status attributes. Actuator and configuration properties are writable. So 'writable' cannot imply configuration. There is no difference in properties that contain sensor status or properties like 'manufacturer' and other such information. Yet they need to be presented differently to the consumer.
For example, a ZWave zw100 multi sensor has temperature, motion, light, vibration and humidity sensors, about 20 read-only attributes and about 40 configuration values. Presenting these to the consumer in a single flat list is obviously not an option.
It is easy enough to come up with my own way to differentiate them. To name a few:
How should these types of attributes be distinguished in a TD?