Open jboynes opened 7 years ago
PR for comments if that works better
I also started on a proof of concept, using a sketch for a Wifi-capable Arduino to send environment data to a UDP multicast group. Listening on that is a simple server application that processes hello
messages from the device to identify atoms, and then associates updates with other atoms in the vessel-wide portion of the model.
{"devices":{"acme-bme280-0ffbf1":{"_type":"http://devices.acme.example/signalk/bme280.json#/metadata","serialNumber":"0ffbf1","lastReading":{"temperature":295.60,"pressure":99752,"humidity":44.71}}}}
Processing update of [devices, acme-bme280-0ffbf1, lastReading]: {"temperature":295.60,"pressure":99752,"humidity":44.71}
Setting [vessels, 2309999, environment, inside, masterCabin] to {"temperature":295.60,"pressure":99752,"humidity":44.71}
Processing update of [vessels, 2309999, environment, inside, masterCabin]: {"temperature":295.60,"pressure":99752,"humidity":44.71}
{"devices":{"acme-bme280-0ffbf1":{"lastReading":{"temperature":295.60,"pressure":99752,"humidity":44.71}}}}
Processing update of [devices, acme-bme280-0ffbf1, lastReading]: {"temperature":295.60,"pressure":99752,"humidity":44.71}
Setting [vessels, 2309999, environment, inside, masterCabin] to {"temperature":295.60,"pressure":99752,"humidity":44.71}
Processing update of [vessels, 2309999, environment, inside, masterCabin]: {"temperature":295.60,"pressure":99752,"humidity":44.71}
It looks like it would be sensible for the hello message to be the same as the record of the device under the "device" node.
There is a lot of cross over with the thinking around sources as well which should probably be resolved.
Should there be standard strings for the SK specified message objects? something like "$schema": "_delta" "$schema": "_value" "$schema": "_full"
See http://json-ld.org/ We should try to incorporate existing standards as much as possible.
Also worth noting that adding to the schema should not be onerous for new use cases. Something like: 1) devise extension 2) publish on your own webserver, so others can access if required. 3) submit RFC or pull request 4) ...discussion...change..repeat 5) accept and merge in to dev 6) tag next sub version.
One of the key goals in signalk was to be extensible without breaking older clients - they simply ignore what they dont recognise, so adding a v1.2 device to a predominantly v1.1 system is fine.
Summary
SignalK provides an open model that allows for both commercial and amateur implementations. This RFC defines how each implementation can describe its data model, without needing a central repository for such definitions. It enables simple, config-free devices to be integrated into a holistic vessel-wide configuration in an automated manner.
Motivation
To allow interoperation between independently developed systems, a typical approach is to define a common standard to which implementations must conform. Such a standard may be controlled by a single vendor, by committee, or by a formal standards body. Regardless, any new functionality must be approved by the controlling entity and integrated into existing implementations before it can be used. This limits the pace of change and discourages innovation.
This RFC describes an open, federated data model that can be used by devices to describe the data they can provide and the commands that they can support. By defining a standard for a meta model it provides a mechanism that allows any other device to integrate with the new device's data using standardized configuration entries.
Although the model is fully open, we expect common patterns of use to emerge, and that implementers will prefer to use those patterns over proprietary definitions when possible. These common patterns will initially be defined by community working groups before maturing into group patterns defined by SIgnalK.
This issue was initially identified as a TODO item in the sensors group. This RFC refers to devices in preference to sensors to allow for other types of unit such as actuators or more complex systems.
Detailed Design
Put simply, this RFC defines patterns for describing the representation of JSON data using JSON Schema. A system need only support these patterns in order to integrate with any other system that uses them to describe its data model. Integration is performed by introspecting a JSON schema provided by a device that describes its data model, combined with schema annotations defined by this RFC that supplement the raw schema; an existing example of such an annotation is the
units
property used to specify the unit of measure for a JSON number.Device Data Model
In an open model, each device may potentially support an arbitrary set of data and messages used to exchange information with other systems. To support this, each device is required to provide a JSON schema that describes the data and messages; this schema may be defined by the device's creator, or may a reference to a common schema defined by other implementers or this project for use by similar devices.
The schema is responsible for defining:
Atoms
An atom is a non-decomposable fragment of data used for interaction with a device. This may be a single value (such as a voltage), or may be a structure containing multiple, closely coupled properties (such as a position comprised of latitude, longitude and an optional altitude). A atom is the smallest unit of information that may be exchanged between systems, although higher level messages may contain multiple atoms.
In addition to the actual value, an atom may contain meta information describing the format, source, timestamp, validity, or accuracy of the value. An atom is therefore defined to be a JSON
object
type whose schema is decorated with theatom
boolean property. A parent or child definition of a definition annotated withatom
MUST NOT be annotated withatom
.Atom Metadata
All property names beginning with
_
are reserved for atom metadata. Implementers SHOULD begin device property names with characters from the set[a-zA-Z0-9]
.Format
The content of an atom may be specified using a JSON schema reference i.e. a property named
$schema
containing valid JSON schema or a reference to a JSON schema definition.Example:
Atom ID
The
_id
property should contain a unique identifier for this atom. How this identifier is created is undefined; applications may use a sequence number, structured UUID, or random token. Systems receiving this id must treat as an opaque token.Examples:
Device ID
The "_deviceId" property may contain a unique identifier for the device that created this atom. Atoms should contain a device id when sent over a shared channel such as a UDP multicast group or message topic.
Example:
Timestamp
The
_timestamp
property may contain an estimation of the time at the source when the atom was created, expressed as an absolute time or a duration since the Unix epoch (1970-01-01T00:00:00Z).Examples:
Non-normative Examples
The atom for a voltage value could be defined as:
with a sample data point of
A position as
with a sample data point of
where the "Acme GPS01" device with serial number "5d34e7" uses time as a unique id and is able to provide an absolute timestamp.
Device Messages
Systems interact by exchanging messages containing zero or more atomic values. Each message is structured as a JSON object, described by a JSON schema supplemented with SignalK specific annotations.
Each message should include a
$schema
property at the root corresponding to the content of the message. Receiving devices may validate the message against that schema and may discard non-conforming messages without further processing.The message types a device can send and receive are listed in its device metadata.
Device Specific Model Space
Every SignalK device is allocated a portion of the model tree unique to it under the context path
/devices/{deviceId}
wheredeviceId
is the globally unique id for that device. From the example above, this location would be under the path/devices/acme-bme280-f1df70/...
This property must contain an object conforming to the SignalK type "#/definitions/device" including a "_type" property that contains the device metadata, either as a JSON object or as a reference to another JSON object.
For example, the device model
gives the unique id, serial number and last reading from this device. The linked metadata
http://devices.acme.example/signalk/bme280.json
contains:that shows the device sends a standard
hello
message, as well as its device specificdata
message every 10s.Device to Vessel Integration
This RFC describes application-level integration that occurs after a device has been installed, authorized to join a vessel's network, discovered, and been discovered, by other SignalK applications. It assumes that the messages defined by this RFC can be exchanged.
Examples of such integration include:
Each device announces its capabilities by sending a standard
hello
message containing a minimal copy of its device model including the device metadata and, optionally, the current device state. The minimal model is defined by thehttps://signalk.github.io/specification/schemas/messages.json#/hello
schema:The device responsible for integrating the new device into the vessel's data model creates an entry in its own model containing the new device's metadata, and performs any mapping needed to include the devices data into the vessel's model. For example, the an installer might enter location information indicating the environment sensor was located in the master's cabin thereby associating its readings with the
/vessels/2309999/environment/inside/masterCabin
path (or wherever the installer deemed most appropriate).Schema Distribution
The JSON schema documents associated with a device may be distributed in any way that allows them to be read by the integrating system.
A simple, albeit verbose, mechanism is to include them, by value, in messages sent by the device. This may be done during initial negotiation, for example, as part of a
hello
message.More typically, the schema would be referenced using its unique id (from the JSON schema definition). If this id is a dereferencable URL, any integrating device with internet access would be able to retrieve it directly; such devices should cache the copy locally for offline access. Other alternatives include:
Drawbacks
Although the device specific information is kept to a minimum, more work must be performed by the integrating device to retrieve and process the metadata objects and schemas. For example, the environmental sensor need only deal with simple messages containing its serial number (unique id) and atomic values. The rest of the information is static content that could kept on the device or sourced elsewhere. However, the integrating server needs to be able to retrieve or otherwise install that information.
A device manufacturer is responsible for producing the device metadata needed for automatic integration. However, it seems better to place the burden there rather than on end users.
Alternatives
We could maintain a central registry of device types and metadata groups. However, that means any new device type implementations would need to be defined here first, entered in the registry, and would not be usable until a new version of the schema and keys was published.
We could require every device to allow configuration that defined how it was associated with the vessel-wide model. That would require some form of user interface for the installer to use (although that could be some form of remote client) and would require all clients to have local persistent storage (e.g. EEPROM or flash) to store the association mapping. For example, the environment sensor would need to be configured to send its readings as part of the
/vessels/{vesselId}/{inside}/{cabin}
context.Unresolved Questions
The schema entries for this need still need to be fully defined, including more verbose descriptions.