Closed benfrancis closed 6 years ago
There should probably be a readable equivalent for write-only properties. For example, X-10 modules are all write-only. There is no way to determine if a switch is currently set to the on or off setting.
Yeah, sorry we should really discuss "writable" in #38. That's just what the current W3C spec is doing. But I do find the concept of write only properties really weird and wonder whether that's something we actually want to expose. We could try caching the state in the gateway for Z-Wave.
From https://github.com/w3c/wot/issues/371:
If we we're not limited to JSON-LD syntax and semantic annotations are optional you could actually just rename @type
to @schema
.
Without semantic annotations you manually define the schema:
"properties": {
"on": {
"name": "On/Off",
"schema": {
"type": "boolean"
}
"writable": true,
"description": "Whether the lamp is turned on",
"href": "/things/lamp/properties/on"
}
With semantic annotations you could just refer to an external schema:
"@context": "https://iot.schema.org",
...
"properties": {
"on": {
"name": "On/Off",
"@schema": "OnOffProperty",
"writable": true,
"description": "Whether the lamp is turned on",
"href": "/things/lamp/properties/on"
}
...which kind of makes sense given the "schema" property is basically a JSON Schema!
IMHO, this move is highly needed indeed. The sooner the better. This spec will end up with hundreds of unique Web Thing Types, and still they may not cover all devices out there. So a "capability" kind of logic is much more suitable. Projects like https://iotdb.org already explored that topic in depth.
This is definitely needed. Many of the things I am working with have common attributes with wildly different core functions. For example, smart plugs from Aeon Labs have rgb-color light rings around the plug that are configurable.
It would be beneficial to have the capabilities be abstracted and queryable. A use case of this I am looking into is having the ability of setting an entire room to a color theme. If I could query things by location and by the "colorable" capability, this would be a very simple operation.
A less esoteric example might be devices that have a battery. It would be nice to be able to pull from a capability list to find all devices and their battery status, rather than needing to know in advance what devices are battery operated and what they call their remaining battery property.
@dhylands found a good example of a device where this is definitely needed, the "Aeotec ZW100 multi-sensor 6". This device includes many different sensors, and we definitely don't want to have to define a MotionTemperatureHumidityLuminanceUvVibrationBatterySensor
web thing type!
Here is an example of what a Thing Description could look like.
{
"name": "Aeotec ZW100 multi-sensor 6",
"description": "Multi-sensor measuring motion, temperature, humidity, luminance, UV, vibration and battery level",
"@context": "https://iot.mozilla.org/schemas",
"@type": ["MultiSensor", "MotionSensor", "TemperatureSensor", "HumiditySensor", "LuminanceSensor", "UVSensor", "VibrationSensor", "BatteryLevel"],
"properties": {
"motion": {
"name": "Motion",
"description": "Whether motion is currently being detected",
"@type": "BinaryMotionProperty",
"type": "boolean",
"href": "/properties/motion"
},
"temperature": {
"name": "Temperature",
"description": "Current temperature in celcius",
"@type": "TemperatureProperty",
"type": "number,
"unit": "celcius",
"href": "/properties/temperature"
},
"humidity": {
"name": "Humidity",
"description": "Current relative humidity",
"@type": "RelativeHumidityProperty",
"type": "number",
"unit": "percentage",
"href": "/properties/humidity"
},
"luminance": {
"name": "Luminance",
"description": "Current luminous intensity",
"@type": "LuminanceProperty",
"type": "number",
"unit": "candela per square metre",
"href": "/properties/luminance"
},
"uv": {
"name": "UV",
"description": "Current ultraviolet light intensity",
"@type": "UVLightIntensityProperty",
"type": "number",
"unit": "watts per square metre",
"href": "/properties/uv"
},
"vibration": {
"name": "Vibration",
"description": "Whether vibration is currently being detected",
"@type": "BinaryVibrationProperty",
"type": "boolean",
"href": "/properties/vibration"
},
"battery": {
"name": "Battery",
"description": "Current percentage battery life remaining",
"@type": "BatteryLevelProperty",
"type": "number",
"unit": "percentage",
"href": "/properties/battery"
}
}
This example includes a top level @type
as an array of capabilities the device has. One use case for this top level @type
array might be to present the user with a choice of default icons representing each of these capabilities, so they can choose which icon to use to represent the device depending on what they're using it for.
There are then also @type
s for individual properties which provide more semantic information than the primitive type
does. For example, a property with a boolean type
could be a BinaryMotionProperty
or BinaryVibrationProperty
, which provides more information to the client to help it determine how to represent this property in the UI. (The similarity between the type
and @type
terms is maybe a bit clunky).
An example which includes actions and events:
{
"name":"My Lamp",
"description": "A web connected lamp",
"@context": "https://iot.mozilla.org/schemas",
"@type": ["Lamp", "OnOffSwitch", "DimmerSwitch"],
"properties": {
"on": {
"name": "On/Off",
"description": "Whether the lamp is turned on",
"@type": "OnOffProperty",
"type": "boolean",
"href": "/things/lamp/properties/on"
},
"level" : {
"name": "Level",
"description": "The level of light from 0-100",
"@type": "LevelProperty",
"type": "number",
"minimum" : 0,
"maximum" : 100,
"href": "/things/lamp/properties/level"
}
},
"actions": {
"fade": {
"name": "Fade",
"description": "Fade the lamp to a given level",
"@type": "FadeAction",
"input": {
"type": "object",
"properties": {
"level": {
"name": "Level",
"description": "The level to fade to",
"@type": "LevelProperty",
"type": "number",
"minimum": 0,
"maximum": 100
},
"duration": {
"name": "Duration",
"description": "Duration of fade",
"@type": "DurationProperty",
"type": "number",
"unit": "milliseconds"
}
}
},
"href": "/things/lamp/actions/fade"
}
},
"events": {
"overheated": {
"@type": "OverHeatedEvent",
"type": "number",
"unit": "celsius",
"description": "The lamp has exceeded its safe operating temperature",
"href": "/things/lamp/events/overheated"
}
}
}
Actions and events can also have a @type
. If an action input or event payload is of type
"object" then its sub-properties
can also have a @type
, which may be shared with top level properties of the thing. E.g. a DimmerSwitch
can have a LevelProperty
as well as a FadeAction
which has a LevelProperty
as an input to tell it what level to fade to.
One thing I'm not sure about is to what extent @type
s should just provide semantic information, vs. enforce certain data structures. For example, does a LevelProperty
always have a type
of "number" with a minimum
of 0 and a maximum
of 100? Or does it just tell the client that this property is for setting a level? Does a FadeAction
always have a LevelProperty
and a DurationProperty
and does a TemperatureProperty
always have a unit
of "centigrade", or could it be "fahrenheit"?
What is defined by JSON Schema, and what is defined by JSON-LD style semantic annotations?
I like this direction for a more flexible way to define devices/things.
A thought for the @type
semantic field -- would it make sense to use it more in a way like classes in CSS? This would lend to having multiple @types
applied to a property/event/action (PEA), and could be consumed in several different ways.
e.g.
"properties": {
"on": {
"name": "On/Off",
"description": "Whether the lamp is turned on",
"@type": [ "OnOff", "Button" ],
"type": "boolean",
"href": "/things/lamp/properties/on"
}
}
or @type
could be: [ "OnOff", "Switch" ]
-- depending on what the author prefers/intends.
With regard to "default" semantic information for @types
-- I think that with the idea of tying it close to CSS classes, there could be "default" associations for the pre-defined types. So, for example, a property with @type
Temperature
would also have unit
default to (e.g.) "Celcius", unless another value is provided (or ""
-- blank).
IMO, this would lend to an even more flexible way to define how devices/things are presented even at the UI level too (imagine a device optionally providing a CSS file for theming/describing it's components for the UI).
type
-> datatype
?
@type
stays @type
?
@bhagman wrote:
This would lend to having multiple @types applied to a property/event/action (PEA), and could be consumed in several different ways.
This is what the current W3C specification does, although that's partly because they haven't separated out properties
, actions
and events
members yet so each "interaction" needs marking as a @type
of Property
, Action
or Event
in addition to a more granular type.
The downside of allowing multiple @type
s for properties, actions and events is the increased ambiguity for Web of Things clients which somehow need to decide how to represent each one. If user interaction is required to make that decision then the client could quickly become very hard to use. It also makes interoperability more difficult.
What is the difference between OnOff
and Switch
in your example? How does the client decide which to use?
type -> datatype
The term "type" is taken from JSON Schema and goes multiple levels deep. A property can be of type
"object" and have multiple sub-properties which also have a type
, e.g.:
{
...
"properties": {
"foo" {
"type": "object",
"properties": {
"bar": {
"type": "string"
},
"baz": {
"type": "number"
}
}
}
}
}
The term @type
comes from JSON-LD and is used along with @context
.
So we could change one or the other, but it would make us less compatible with those specifications.
Note that the current W3C spec has a schema
member for each property rather than a type
, and then the schema
has a type
, but I think that might go away once they change over to the Simplified TD proposal.
I think capabilities should err on the side of rigidity when defining required sets of properties, actions, and events. I definitely don't think it would be useful to have capabilities that are solely semantic hints. For example, if something has a capability OnOffSwitch but doesn't have a property "on" then what is it trying to accomplish? It's also more useful to an interface to know that "level" must be 0-100 (or at least must have a min/max). There can certainly be weak capabilities, but it makes sense for most of them to be strong to allow the creation of fine-tuned interfaces
OK, I've started to document a set of capability schemas for a Mozilla schema repository. My hope is that eventually we can use an external schema repository like iot.schema.org (current staging server at iotschema.org) once that matures a bit more and the Thing Description specification is a bit more solid. In the meantime a Mozilla schema repository gives us more flexibility to experiment and define data constraints for types.
The repository includes the following types:
A thing can implement multiple capabilities. A capability schema defines a set of properties, actions and events which can be expected for a thing which implements that capability - some of which are required and some of which are optional.
Property, Action and Event types describe data constraints for property values, action inputs (and possibly outputs) and event payloads. This defines what primitive data types, units, minimum and maximum values to expect in order to enable ad-hoc interoperability.
The idea is that a client can implement UI components for each known property, action and event type such that things can use any combination of those types, without having to stick to a single rigid top level thing type. The top level thing capability types provide additional information to a client to tell it what kinds of properties, actions and events to expect from a thing (as well as semantic information about what it does), without restricting that thing to a single top level type.
Below is an example of how capabilities might be used. A lamp implements the Light
, OnOffSwitch
and MultiLevelSwitch
capabilities. The OnOffSwitch
capability and MultiLevelSwitch
capability are subsets of the Light
capability, but the thing implements all three. This means a client which understands the OnOffSwitch
capability but not the Light
capability can still turn the light on and off for example.
This approach currently differs from the latest W3C proposals in that we only implement two of the three or four levels of "types" currently being discussed. We can add additional levels in future if we find they are necessary.
{
"@context": "https://iot.mozilla.org/schemas/",
"@type": ["Light", "OnOffSwitch", "MultiLevelSwitch"],
"name":"My Lamp",
"description": "A web connected lamp",
"properties": {
"on": {
"@type": "OnOffProperty",
"type": "boolean",
"description": "Whether the lamp is turned on",
"href": "/things/lamp/properties/on"
},
"level" : {
"@type": "LevelProperty",
"type": "number",
"description": "The level of light from 0-100",
"minimum" : 0,
"maximum" : 100,
"href": "/things/lamp/properties/level"
}
},
"actions": {
"fade": {
"@type": "FadeAction",
"description": "Fade the lamp to a given level",
"input": {
"type": "object",
"properties": {
"level": {
"type": "number",
"minimum": 0,
"maximum": 100
},
"duration": {
"type": "number",
"unit": "milliseconds"
}
}
},
"href": "/things/lamp/actions/fade"
}
},
"events": {
"overheated": {
"@type": "OverheatedEvent",
"type": "number",
"unit": "celsius",
"description": "The lamp has exceeded its safe operating temperature",
"href": "/things/lamp/events/overheated"
}
},
"links": [
{
"rel": "properties",
"href": "/things/lamp/properties"
},
{
"rel": "actions",
"href": "/things/lamp/actions"
},
{
"rel": "events",
"href": "/things/lamp/events"
},
{
"rel": "alternate",
"href": "wss://mywebthingserver.com/things/lamp"
},
{
"rel": "alternate",
"mediaType": "text/html",
"href": "/things/lamp"
}
]
}
In implementing this specification so far we've found that just defining top level "Web Thing Types" is quite inflexible and have discussed a "capabilities" type system for standardising types of properties, actions and events which can be mixed and matched between types.
Here is a proposed example where
DimmableLight
is a thing type andOnOffProperty
,LevelProperty
,ToggleAction
,FadeAction
andOverheatedEvent
are capabilities defined by an external context at iot.schema.org.You will notice that properties, actions and events also have a "schema", which is the latest W3C proposal for defining data types, and "writable" to define whether a property accepts a PUT request.