diff --git a/gitbook-docs/data_model.md b/gitbook-docs/data_model.md index 6d45e3933..519bd60d1 100644 --- a/gitbook-docs/data_model.md +++ b/gitbook-docs/data_model.md @@ -264,6 +264,42 @@ the value should be merged to the full model mounted where the delta‘s context } ``` [<]: # +## Delta Format For Metadata + +Metadata can also be updated via a delta within the `meta` key. + +Since meta data is not often updated it is only sent when there has been a change. See [Subscription Protocol](subscription_protocol.md) for details. + +[>]: # (mdpInsert ```json fsnip ../samples/delta/docs-data_model_meta_deltas.json --prettify 2 20) +```json +{ + "context": "vessels.urn:mrn:imo:mmsi:234567890", + "updates": [ + { + "timestamp": "2014-08-15T19:02:31.507Z", + "meta": [ + { + "path": "environment.wind.speedApparent", + "value": { + "units": "m/s", + "description": "Apparent wind speed", + "displayName": "Apparent Wind Speed", + "shortName": "AWS", + "zones": [ + { + "upper": 15.4333, + "state": "warn", + "message": "high wind speed" + } + ] + } + } + ] + } + ] +} +``` +[<]: # ## Data Quality Data transmitted in Signal K format is assumed to be corrected for known sensor inaccuracies such as wind angle offset diff --git a/gitbook-docs/subscription_protocol.md b/gitbook-docs/subscription_protocol.md index 184bcfe0e..61bf3301d 100644 --- a/gitbook-docs/subscription_protocol.md +++ b/gitbook-docs/subscription_protocol.md @@ -86,7 +86,7 @@ The following are optional, included above only for example as it uses defaults * `period=[millisecs]` becomes the transmission rate, e.g. every `period/1000` seconds. Default: 1000 * `format=[delta|full]` specifies delta or full format. Default: delta -* `policy=[instant|ideal|fixed]`. Default: ideal +* `policy=[instant|ideal|fixed]`. Default: ideal. (does not apply to meta - see below) * `instant` means send all changes as fast as they are received, but no faster than `minPeriod`. With this policy the client has an immediate copy of the current state of the server. * `ideal` means use `instant` policy, but if no changes are received before `period`, then resend the last known @@ -101,6 +101,13 @@ duplication as it prefers on a per connection basis. At the same time it is good connections necessary, for instance one WebSocket connection shared between an instrument panel with many gauges, rather then one WebSocket connection per gauge. +## Meta data +Meta is updated via the `meta` section within the delta message. As meta changes infrequently it is only sent when it has changed. + +Servers implementing the subscription model (ie. using deltas) SHOULD implement meta deltas. Where meta deltas are implemented, servers MUST only ever send full copies of the meta for a leaf, ie. they MUST NEVER send a partial meta. + +Upon receiving a new subscription a server MUST send the meta for each leaf subscribed to; this MAY be in the same JSON document as the values, or in a separate one prior to sending values for that leaf or leaves. Subsequently the server MUST resend the full meta for a leaf each time any item in that meta is changed. This is equivalent to the `instant` subscription for values. Therefore meta is never subscribed on an `ideal` or `fixed` policy, irrespective of the policy requested by the consumer (which applies to values only). + ## Multiple value handling in subscriptions A subscription to a key is for all the updates to that key. If there are multiple sources generating data for that key diff --git a/samples/delta/docs-data_model_meta_deltas.json b/samples/delta/docs-data_model_meta_deltas.json new file mode 100644 index 000000000..f683d158e --- /dev/null +++ b/samples/delta/docs-data_model_meta_deltas.json @@ -0,0 +1,25 @@ +{ + "context": "vessels.urn:mrn:imo:mmsi:234567890", + "updates": [ + { + "timestamp": "2014-08-15T19:02:31.507Z", + "meta": [ + { + "path": "environment.wind.speedApparent", + "value": { + "units": "m/s", + "description": "Apparent wind speed", + "displayName": "Apparent Wind Speed", + "shortName": "AWS", + "zones": [{ + "upper": 15.4333, + "state": "warn", + "message": "high wind speed" + } + ] + } + } + ] + } + ] +} \ No newline at end of file diff --git a/schemas/delta.json b/schemas/delta.json index c05ecde18..c4b056e7d 100644 --- a/schemas/delta.json +++ b/schemas/delta.json @@ -18,8 +18,23 @@ "description": "The updates", "items": { "type": "object", - "required": ["values"], - + "oneOf": [ + { + "required": ["values"], + "properties": {"$source":{}, "source": {}, "timestamp": {}, "values": {}}, + "additionalProperties": false + }, + { + "required": ["meta"], + "properties": {"$source":{}, "source": {}, "timestamp": {}, "meta": {}}, + "additionalProperties": false + }, + { + "required": ["values", "meta"], + "properties": {"$source":{}, "source": {}, "timestamp": {}, "values": {}, "meta": {}}, + "additionalProperties": false + } + ], "not": { "allOf": [{ "required": ["source"] @@ -64,6 +79,26 @@ } } } + }, + "meta": { + "type": "array", + "items": { + "type": "object", + "required": [ + "path", + "value" + ], + "properties": { + "path": { + "type": "string", + "description": "The local path to the data value", + "example": "navigation.courseOverGroundMagnetic" + }, + "value": { + "$ref": "./definitions.json#/definitions/meta" + } + } + } } } } diff --git a/test/data/delta-invalid/meta-missing-value.json b/test/data/delta-invalid/meta-missing-value.json new file mode 100644 index 000000000..65d83097e --- /dev/null +++ b/test/data/delta-invalid/meta-missing-value.json @@ -0,0 +1,12 @@ +{ + "context": "vessels.urn:mrn:imo:mmsi:234567890", + "updates": [ + { + "meta": [ + { + "path": "propulsion.0.revolutions" + } + ] + } + ] +} \ No newline at end of file diff --git a/test/data/delta-valid/meta-and-values.json b/test/data/delta-valid/meta-and-values.json new file mode 100644 index 000000000..608a8d2ab --- /dev/null +++ b/test/data/delta-valid/meta-and-values.json @@ -0,0 +1,29 @@ +{ + "context": "vessels.urn:mrn:imo:mmsi:234567890", + "updates": [ + { + "source": { + "label": "N2000-01", + "type": "NMEA2000", + "src": "017", + "pgn": 127488 + }, + "timestamp": "2013-10-08T15:47:28.263Z", + "meta": [ + { + "path": "propulsion.0.revolutions", + "value": { + "description": "Engine revolutions (x60 for RPM)", + "units": "Hz" + } + } + ], + "values": [ + { + "path": "propulsion.0.revolutions", + "value": 11 + } + ] + } + ] +} \ No newline at end of file diff --git a/test/data/delta-valid/meta-delta.json b/test/data/delta-valid/meta-delta.json new file mode 100644 index 000000000..3e41a653b --- /dev/null +++ b/test/data/delta-valid/meta-delta.json @@ -0,0 +1,25 @@ +{ + "context": "vessels.urn:mrn:imo:mmsi:234567890", + "updates": [ + { + "meta": [ + { + "path": "environment.depth.belowTransducer", + "value": { + "description": "Depth below Transducer", + "units": "m", + "timeout": 2.5, + "zones": [ + { + "upper": 5.0, + "state": "warn", + "message": "Shallow water" + } + ], + "warnMethod": ["sound"] + } + } + ] + } + ] +} \ No newline at end of file