## 1. Introducing SNON
SNON 2.0 is the second generation of the Sensor Network Object Notation, a lightweight sensor data representation for interchange and storage. It is easy for humans to read and write. It is easy for machines to parse and generate. It is highly compressible to reduce storage and network usage. SNON is based on [JSON](http://json.org/), which is widely supported by most platforms and programming languages.
SNON is sensor independent, and uses conventions familiar to programmers who have worked with common sensor platforms. It is self-describing and extensible, with features only required when needed. These properties make SNON ideal for delivery of sensor data over lightweight message protocols such as [MQTT](http://mqtt.org/), summarization and aggregation of sensor data, and efficient storage in key/value and columnar time-series databases.
## 1.1 Why SNON?
SNON provides a simple yet powerful way to describe, aggregate, transfer, and relate sensor data. Security and internationalization is designed-in from the ground up.
Here are some of the ways that SNON is used:
### 1.1.1 Sensor Value Streaming
SNON provides a standardized representation for describing sensor measurements.
The following example shows temperature measurements taken by a temperature sensor:
Example 1.1
[
{"eID":"urn:uuid:cd9f930e-a3b4-423a-850b-3c81135f0f7e","v":["28.15"],"vT":["2014-08-20T14:32:57.126Z"]},
...
{"eID":"urn:uuid:cd9f930e-a3b4-423a-850b-3c81135f0f7e","v":["23.53"],"vT":["2014-08-20T15:30:23.524Z"]}
]
SNON fragments (the JSON object in the above array) can be sent over stream-based protocols, such as TCP/IP, HTTP long-polling, or Websockets. SNON collections (the JSON array and all contents) can be sent over message-based protocols, such as UDP, MQTT or various RT transports.
### 1.1.2 Sensor Value Bulk Transfer
SNON provides a standardized representation for batch transfer of sensor measurements, allowing efficient handling of bulk transport, synchronization and intermittent connectivity. Values can be aggregated spatially and temporally.
The following example shows a collection of ten temperature measurements:
Example 1.2
[
{
"eID":"urn:uuid:cd9f930e-a3b4-423a-850b-3c81135f0f7e",
"v":["28.15","28.14","28.15","28.15","28.14","28.14","28.13","28.13","28.12","28.11"],
"vT":["2014-08-20T14:32:57.126Z","/PT10S","/PT20S","/PT30S","/PT40S","/PT50S","/PT60S","/PT70S","/PT80S","/PT90S"]
}
]
The following example shows a collection of two different sensor values:
Example 1.3
[
{"eID":"urn:uuid:01ee0ac6-1dbc-4af0-8e20-f9b3e6a9082c","v":["-113.4"],"vT":["2014-08-20T15:30:23.524Z"]},
{"eID":"urn:uuid:cd9f930e-a3b4-423a-850b-3c81135f0f7e","v":["23.53"],"vT":["2014-08-20T15:30:23.524Z"]}
]
### 1.1.3 Sensor Description and Discovery
SNON provides a standardized representation for describing entities, such as sensors, devices and locations. A entity catalog can use SNON to enable discovery of sensors that match certain criteria, including sensor type, characteristics, and relationships with other entities.
The following example shows the definition for a simple temperature sensor:
Example 1.4
[
{
"entityID": "urn:uuid:cd9f930e-a3b4-423a-850b-3c81135f0f7e",
"entityType": "sensor",
"entityName": {
"jp": "冷却水の温度",
"*": "Cooling Water Temperature"
},
"measureUnit": "°C",
"measureDisplayUnit": {
"en-us": "°F",
"*": "°C"
},
"measureUnitPrefix": {
"jp": "摂氏"
},
"measureUnitSuffix": {
"jp": "度",
"en-us": " ℉",
"*": " ℃"
},
"measureUnitSuffixEx": {
"en-us": " degrees Fahrenheit",
"*": " degrees Celsius"
}
}
]
To allow common parts of sensor definitions to be used across many sensors, a sensor can inherit these fields from "template" sensor messages:
Example 1.5
[
{
"messageID": "urn:uuid:f4dfec0c-259b-4f1b-9eba-9070a4d64b7b",
"messageTime": "2014-08-20T14:32:56.125Z",
"message": {
"measureUnit": "°C",
"measureDisplayUnit": {
"en-us": "°F",
"*": "°C"
},
"measureUnitPrefix": {
"jp": "摂氏"
},
"measureUnitSuffix": {
"jp": "度",
"en-us": " ℉",
"*": " ℃"
},
"measureUnitSuffixEx": {
"en-us": " degrees Fahrenheit",
"*": " degrees Celsius"
}
}
},
{
"messageID": "urn:uuid:34f8e1f8-535e-4abb-a512-72bfd880b4ca",
"messageTime": "2014-08-20T14:32:56.532Z",
"message": {
"precedentID": "urn:uuid:f4dfec0c-259b-4f1b-9eba-9070a4d64b7b",
"entityID": "urn:uuid:cd9f930e-a3b4-423a-850b-3c81135f0f7e",
"entityType": "sensor",
"entityName": {
"jp": "冷却水の温度",
"*": "Cooling Water Temperature"
}
}
}
]
More examples can be found in section [3.0 SNON Examples](#examples).
## 1.2 Where does SNON Fit?
In a typical sensor system, physical values are measured by sensors, which are managed by gateways. Gateways use SNON as a representation to send over a protocol (MQTT and HTTP are common) to real-time processing engines, storage repositories, and display/HMI systems.

Figure 1 - SNON Data Flow
SNON allows all of these components to work together. For example, real-time post-processing of sensor data, such as quantization, summarization, filtering, and multi-sensor fusion can be performed on SNON data, with the resulting derived values again being represented as SNON data, and forwarded on to later processing elements.
## 2. The SNON Representation
SNON defines a JSON-based representation used to exchange data between entities within a sensor network:
1. At the outermost layer, an SNON collection (a JSON array) contains one or more SNON messages and/or SNON fragments
2. The middle layer, an SNON message, uniquely identifies a contained SNON fragment.
3. The innermost layer, an SNON fragment, contains information related to entities, measurements and/or values
SNON Collections can also hold JOSE JWE encrypted and/or JWS signed SNON Collections. See [Section 5](#security) for more details on how SNON works with JOSE.

Figure 2 - SNON JSON Model
SNON messages contain the following fields:
* [Message Fields](#mfields) - Outer encapsulation of SNON Fragments
SNON fragments contain the following fields:
* [Entity Fields](#dfields) - Entity Definitions
* [Measurement](#mefields) Fields - Measurement Definitions
* [Value Fields](#vfields) - Measured Values
## 2.1 Message SNON Fields
Each SNON message shall contain one or more of the following JSON fields:
| Field Name
(Short Name) | Data Type | Description | Mandatory |
| ------------- | ------------- | ------------- | --------- |
| messageID
(mID) | JSON String | Globally unique identifier of an SNON message.
Uniquely identifies the message, allowing message receivers to identify duplicates. Every message generator shall ensure that each Message ID is globally unique by using a technique such as random or MAC-based UUID generation, as described in [RFC 4112](https://tools.ietf.org/html/rfc4122)
The value of this field shall be formatted as an [RFC 8141](https://tools.ietf.org/html/rfc8141) URN.Example 2.1.1
{
"mID":"urn:uuid:cd9f930e-a3b4-423a-850b-3c81135f0f7e"
}
| Mandatory |
| messageTime
(mT) | JSON String | Creation time of an SNON message.
Indicates when an SNON message was created, allowing message receivers to determine if messages are missing or are received out of order.
The value of this field shall be formatted in [ISO 8601](https://www.iso.org/iso-8601-date-and-time-format.html) extended representation date/time format.Example 2.1.2
{
"mID":"urn:uuid:cd9f930e-a3b4-423a-850b-3c81135f0f7e",
"mT":"2014-08-20T14:32:57.126Z"
}
| Mandatory |
| message
(m) | JSON Objects | Contains an SNON Fragment to be included in the message.
Contains the SNON fragment included in the message.
The value of this field shall be a JSON Object containing SNON Device, Sensor, Measurement or Value fields.Example 2.1.4
{
"mID":"urn:uuid:c01ceb9ef-6e75-409d-be81-337609e58aa1",
"mT":"2014-08-20T14:32:57.126Z"
"m":{...}
}
| Mandatory |
Each SNON message is immutable once created.
## 2.2 Entity SNON Fields
A SNON Fragment may contain one or more of the following JSON fields:
| Field Name
(Short Name) | Data Type | Description | Mandatory |
| ------------- | ------------- | ------------- | --------- |
| entityID
(eID) | JSON String | Globally unique identifier of the entity.
Uniquely identifies the entity, allowing message receivers to determine which device the message contents or relation applies to. Every message generator shall ensure that each entity ID is globally unique by using a technique such as random or MAC-based UUID generation, as described in [RFC 4112](https://tools.ietf.org/html/rfc4122)
The value of this field shall be formatted as an [RFC 8141](https://tools.ietf.org/html/rfc8141) URN.Example 2.2.1
{
"entityID":"urn:uuid:cd9f930e-a3b4-423a-850b-3c81135f0f7e"
}
| Optional |
| entityClass
(eC) | JSON String | Entity type indicator.
Identifies what the entity represents.
The value of this field shall be contain one of the following:
a) "sensor"
b) device
c) "location"
If this field is not present, the default value shall be "sensor".Example 2.2.2
{
"entityClass":"device"
}
| Optional, requires entityID |
| entityName
(eN) | JSON Object | Descriptive Name of the entity.
Provides a set of human-readable names that describe the entity, allowing message receivers to list and identify the entity to end users.
The value of this field shall contain one or more JSON Strings, each with a name specifying the language tag as defined in [RFC 5646](https://tools.ietf.org/html/rfc5646), and a value containing a descriptive name of the entity in that language-region.
A name of "*" is used as a default language-region, as defined in [RFC 4647](https://tools.ietf.org/html/rfc4647).Example 2.3.2:
{
"entityName": {
"jp": "冷却水の温度",
"en": "Cooling Water Temperature"
}
}
| Optional, requires entityID |
| entityType
(eT) | JSON Object | Descriptive Name of the type of the entity.
Provides a set of human-readable names that describe the entity type, allowing message receivers to list and identify the device by type to end users.
The value of this field shall contain one or more JSON Strings, each with a name specifying the language tag as defined in [RFC 5646](https://tools.ietf.org/html/rfc5646), and a value containing a descriptive name of the sensor in that language-region.
A name of "*" is used as a default language-region, as defined in [RFC 4647](https://tools.ietf.org/html/rfc4647).Example 2.3.3:
{
"entityType": {
"jp": "温度センサー",
"en": "Temperature Sensor"
}
}
| Optional, requires entityID |
| entityRelations
(dR) | JSON Object containing JSON Arrays of JSON Strings | Globally unique identifiers of related entities.
Identifies relationships between entities. Each relationship is a JSON object with the name specifying the type of relationship, and the value containing an array of URIs specifying the related entities. Entity relationships are described in table 2.9.
The value of each ID shall be formatted as an [RFC 8141](https://tools.ietf.org/html/rfc8141) URN.Example 2.2.5
{
"entityRelations": {
"parent":["urn:uuid:cd9f930e-a3b4-423a-850b-3c81135f0f7e"]
}
}
| Optional, requires entityID |
| precedentID
(pID) | JSON String | Globally unique identifier of a preceding SNON message.
Identifies a prior message to inherit fields from, allowing message senders to reduce network traffic by not repeating fields already accessible to a message receiver. SNON messages with a precedentID do not need to repeat information that has not changed. If an omitted field is present in the precedent message, the field from the precedent is inherited, and treated as if it were directly included in the message.
The value of this field shall be formatted as an [RFC 8141](https://tools.ietf.org/html/rfc8141) URN.Example 2.2.6
{
"precedentID": "urn:uuid:cd9f930e-a3b4-423a-850b-3c81135f0f7e"
}
| Optional |
When a SNON Fragment contains a precedentID, the message sender should ensure that the message receiver has access to the specified message in order to permit the message to be "resolved". Fragments with a precedentID that cannot be accessed is "unresolvable", and shall not be used.
Figure 3 shows how fields from preceding messages are inherited:

Figure 3 - SNON Messages with Precedents
Figure 4 shows the corresponding resolved SNON messages. Message senders may optionally resolve messages before sending them, and message receivers may optionally resolve messages before storing them.

Figure 4 - Corresponding Resolved SNON Messages
When resolving a precedentID, the following conditions shall be handled:
* The message receiver shall convert short names into long names, or long names into short names, as required.
* The message receiver shall perform cycle detection. If a cycle is detected, the fragment is unresolvable.
## 2.4 Measurement SNON Fields
Measurement fields define the characteristics of the value being measured. These are typically used to determine how to process and store sensor values.
Each SNON Fragment may contain one or more of the following JSON fields:
| Field Name
(Short Name) | Data Type | Description | Mandatory |
| ------------- | ------------- | ------------- | --------- |
| measureUnit
(meU) | JSON String | Unit indicator for the value measured by the sensor.
Identifies what physical or calculated quantity is being measured.
The value of this field shall be formatted as either:
a) an [ISO 80000-1:2009](https://www.iso.org/standard/30669.html) special symbol (or [SI unit symbol](http://www.bipm.org/en/si/si_brochure/)),
b) a combination of symbols for units, as defined in 7.2.2 of [ISO 80000-1:2009](https://www.iso.org/standard/30669.html),
c) an empty string, representing a unitless value, or,
d) a custom (non-SI) value.
If this field is not present, the default value shall be an empty string.
NOTE: While SI prefix conversion may be performed for display (e.g. 27.8 m/s -> 100 km/h), SNON measureUnit fields should always specify units without metric prefixes.Example 2.4.1
{
"measureUnit": "m/s"
}
| Optional |
| measureType
(meT) | JSON String | Data type indicator for the value measured by the sensor.
Identifies what data type is stored in the value associated with a measurement.
The value of this field shall be contain one of the following:
a) "enumeration" – The sensor value shall contain a string representation of an integer, which corresponds to a string specified in the measureLabel field.
b) "numeric" – The sensor value shall contain a string representation of a number,
c) "string" – The sensor value shall consist of a UTF-8 string value, or,
d) "url" – The sensor value shall contain a string representation of a URL (including data URIs as defined in [RFC 2397](https://tools.ietf.org/html/rfc2397)).
If this field is not present, the default value shall be "numeric".Example 2.4.2
{
"measureType": "numeric"
}
| Optional |
| measureAcquire
(meAq) | JSON String | Data Acquisition indicator for the value measured by the sensor.
Identifies what method is used by the sensor to acquire a value.
The value of this field shall be contain one of the following:
a) "sample" – The value represents a measurement made at the start of valueTime.
b) "count" – The value represents an increasing count, measured the start of valueTime.
c) "triggered" – The value represents a measurement, captured at the end of valueTime.
d) "summary" – the value represents a summarization of measurements that occurred during the valueTime range.
e) "derived" – The value represents calculations of measurements, valid for the start of valueTime.
If this field is not present, the default value shall be "sample".Example 2.4.3
{
"measureType": "sample"
}
| Optional |
## 2.5 Measurement Descriptive SNON Fields
Measurement descriptive fields provide additional information about how the measurement made by the sensor is displayed and organized. These are typically used for sensor discovery and cataloging.
Each SNON Fragment may contain one or more of the following JSON fields:
| Field Name
(Short Name) | Data Type | Description | Mandatory |
| ------------- | ------------- | ------------- | --------- |
| measureUnitPrefix
(meUP) | JSON Object | Descriptive Name of the prefix to be displayed before the measured value.
Provides a set of human-readable prefixes that come before the value measured by the sensor, allowing message receivers to display sensor measurements to end users.
The value of this field shall contain one or more JSON Strings, each with a name specifying the language tag as defined in [RFC 5646](https://tools.ietf.org/html/rfc5646), and a value containing a prefix in that language-region, to be displayed before the value of the measurement.
A name of "*" is used as a default language-region, as defined in [RFC 4647](https://tools.ietf.org/html/rfc4647).Example 2.5.1
{
"measureUnitPrefix": {
"jp": "摂氏",
"*": ""
}
}
| Optional |
| measureUnitSuffix
(meUS) | JSON Object | Descriptive Name of the suffix to be displayed after the measured value.
Provides a set of human-readable suffixes that come after the value measured by the sensor, allowing message receivers to display sensor measurements to end users.
The value of this field shall contain one or more JSON Strings, each with a name specifying the language tag as defined in [RFC 5646](https://tools.ietf.org/html/rfc5646), and a value containing a suffix in that language-region, to be displayed before the value of the measurement.
A name of "*" is used as a default language-region, as defined in [RFC 4647](https://tools.ietf.org/html/rfc4647).Example 2.5.2
{
"measureUnitSuffix": {
"jp": "度",
"en-us": " ℉",
"*": " ℃"
}
}
| Optional |
| measureUnitPrefixEx
(meUPx) | JSON Object | Extended descriptive Name of the prefix to be displayed before the measured value.
Provides a long-form set of human-readable prefixes that come before the value measured by the sensor, allowing message receivers to display sensor measurements to end users.
The value of this field shall contain one or more JSON Strings, each with a name specifying the language tag as defined in [RFC 5646](https://tools.ietf.org/html/rfc5646), and a value containing a long-form prefix in that language-region, to be displayed before the value of the measurement.
A name of "*" is used as a default language-region, as defined in [RFC 4647](https://tools.ietf.org/html/rfc4647).Example 2.5.3
{
"measureUnitPrefixEx": {
"jp": "摂氏",
"*": ""
}
}
| Optional |
| measureUnitSuffixEx
(meUSx) | JSON Object | Extended descriptive Name of the suffix to be displayed after the measured value.
Provides a long-form set of human-readable suffixes that come after the value measured by the sensor, allowing message receivers to display sensor measurements to end users.
The value of this field shall contain one or more JSON Strings, each with a name specifying the language tag as defined in [RFC 5646](https://tools.ietf.org/html/rfc5646), and a value containing a long-form suffix in that language-region, to be displayed before the value of the measurement.
A name of "*" is used as a default language-region, as defined in [RFC 4647](https://tools.ietf.org/html/rfc4647).Example 2.5.4
{
"measureUnitSuffixEx": {
"jp": "度",
"en-us": " degrees Fahrenheit",
"*": " degrees Celsius"
}
}
| Optional |
| measureLabel
(meL) | JSON Object of JSON Objects | Descriptive Name of enumeration values.
Provides a set of human-readable values corresponding to enumerated values of a sensor of type "enumerated", allowing message receivers to display sensor measurements to end users.
The value of this field shall contain a JSON Object, with each object contained being a JSON Object containing one or more JSON Strings, each with a name specifying the language tag as defined in [RFC 5646](https://tools.ietf.org/html/rfc5646), and a value containing a long-form suffix in that language-region, to be displayed before the value of the measurement.
A name of "*" is used as a default language-region, as defined in [RFC 4647](https://tools.ietf.org/html/rfc4647).Example 2.5.5
{
"measureLabel": {
"0":{
"jp": "開弁",
"en-us": " Opened Valve"
},
"1":{
"jp": "閉鎖弁",
"en-us": " Closed Valve"
}
}
}
| Optional |
| measureSpanLow
(meSL) | JSON String | Indication of the minimum operating value.
Provides an indication of the lowest operating value where the sensor is rated to be within its normal error band.
The value of this field shall match the value specified in the sensor's measureType field.Example 2.5.6
{
"measureSpanLow":"-100"
}
| Optional |
| measureSpanHigh
(meSH) | JSON String | Indication of the maximum operating value.
Provides an indication of the highest operating value where the sensor is rated to be within its normal error band.
The value of this field shall match the value specified in the sensor's measureType field.Example 2.5.7
{
"measureSpanHigh":"100"
}
| Optional |
| measureDisplayLow
(meDL) | JSON String | Indication of the minimum value for display purposes.
Provides an indication of the lowest value the sensor is expected to return during normal operation. This permits a message receiver to size charts and other display outputs appropriately.
The value of this field shall match the value specified in the sensor's measureType field.Example 2.5.8
{
"measureDisplayLow":"0"
}
| Optional |
| measureDisplayHigh
(meDH) | JSON String | Indication of the maximum value for display purposes.
Provides an indication of the highest value the sensor is expected to return during normal operation. This permits a message receiver to size charts and other display outputs appropriately.
The value of this field shall match the value specified in the sensor's measureType field.Example 2.5.9
{
"measureDisplayHigh":"50"
}
| Optional |
| measureDisplayUnit
(meDU) | JSON Object | Indication of the unit used for display purposes.
Provides an indication of what unit should be used for display purposes. This permits a specific directive for how a message receiver should convert from SI base units.
The value of this field shall contain one or more JSON Strings, each with a name specifying the language tag as defined in [RFC 5646](https://tools.ietf.org/html/rfc5646), and a value containing either:
a) a combination of [ISO 80000-1:2009](https://www.iso.org/standard/30669.html) special symbol (or [SI unit symbol](http://www.bipm.org/en/si/si_brochure/)), optionally including SI prefixes,
b) an SI prefix, or,
c) a custom (non-SI) value.
A name of "*" is used as a default language-region, as defined in [RFC 4647](https://tools.ietf.org/html/rfc4647).Example 2.5.10
{
"measureUnit": "m/s",
"measureDisplayUnit": {
"en-us":"mile/hr",
"*":"km/hr"
}
}
| Optional |
| measureUpdateRate
(meUR) | JSON String | Indication of the maximum rate at which a sensor value will be updated.
Provides an indication of the shortest interval that a sensor value can be polled to obtain a new reading. This permits a message sender to determine the rate at which values should be generated.
The value of this field shall be a string containing a numeric value measured in seconds.Example 2.5.11
{
"measureUpdateRate":"0.1"
}
| Optional |
| measureTimeout
(meTo) | JSON String | Indication of the timeout associated with each measurement.
If the specified time duration since the valueTime has been exceeded, the corresponding value shall no longer be considered valid.
The value of this field shall be a string containing a numeric value measured in seconds.Example 2.5.12
{
"measureTimeout":"10"
}
| Optional |
| measureResolution
(meR) | JSON String | Indication of the smallest detectable change measurable by the sensor.
Provides an indication of the smallest detectable change of the value being measured that will result in a different value reading. This permits a message sender to determine significant figures.
The value of this field shall be a string containing a numeric value corresponding to the units defined for the sensor.Example 2.5.13
{
"measureResolution":"0.1"
}
| Optional
Only valid for sensors of type "numeric" |
| measureAccuracy
(meAc) | JSON String | Indication of range of possible measurement error.
Provides an indication of the largest difference (+/-) expected to exist between the measured value and the actual value. This permits a message sender to determine significant figures.
The value of this field shall be a string containing a positive numeric value corresponding to the units defined for the sensor. Accuracy shall be +/- the specified value.Example 2.5.14
{
"measureAccuracy":"0.1"
}
| Optional
Only valid for sensors of type "numeric" |
## 2.6 Value SNON Fields
Value fields carry information about measurements taken by a sensor.
Each SNON Fragment may contain the following value JSON fields:
| Field Name
(Short Name) | Data Type | Description | Mandatory |
| ------------- | ------------- | ------------- | --------- |
| valueTime
(vT) | JSON Array of JSON Strings | Indication of one or more times associated with measured values.
Provides an indication of when values were measured.
The value of this field shall contain one or more JSON Strings, with the contents of each string corresponding to the time a value was measured, in [ISO 8601](https://www.iso.org/iso-8601-date-and-time-format.html) extended representation date/time format ("YYYY-MM-DDTHH:MM:SS.MMMZ"), or time interval format ("/PTxx.xxxS"). All value array fields shall have the same number of entries, with the order consistent across fields. Example 2.6.1
{
"value": ["10", "11"],
"valueTime": ["2014-08-20T14:32:56.125Z", "/PT0.100S"]
}
| Optional, requires entityID |
| value
(v) | JSON Array of JSON Strings | Indication of one or more values measured from the sensor.
Provides an indication of a measured value at a given point in time.
The value of this field shall contain one or more JSON Strings, with the contents of each string corresponding to the type of the sensor. All value array fields shall have the same number of entries, with the order consistent across fields.
If a min and max are provided, the value represents the average value over the acquisition period specified in the valueTime field. Example 2.6.2
{
"value": ["10"],
"valueTime": ["2014-08-20T14:32:56.125Z"]
}
| Optional, requires valueTime |
| valueMax
(vMax) | JSON Array of JSON Strings | Indication of one or more maximum values measured from the sensor.
Provides an indication of a maximum measured value during a given interval in time. Min/Max/Average values are typically used when sensor samples a value at a higher rate then is reported, and when the envelope contains important information.
The value of this field shall contain one or more JSON Strings, with the contents of each string corresponding to the type of the sensor. All value array fields shall have the same number of entries, with the order consistent across fields.Example 2.6.3
{
"value": ["10"],
"valueMax": ["12"],
"valueMin": ["8"],
"valueTime": ["2014-08-20T14:32:56.125Z"]
}
| Optional, requires valueTime |
| valueMin
(vMin) | JSON Array of JSON Strings | Indication of one or more minimum values measured from the sensor.
Provides an indication of a minimum measured value during a given interval in time. Min/Max/Average values are typically used when sensor samples a value at a higher rate then is reported, and when the envelope contains important information.
The value of this field shall contain one or more JSON Strings, with the contents of each string corresponding to the type of the sensor. All value array fields shall have the same number of entries, with the order consistent across fields.Example 2.6.4
{
"value": ["10"],
"valueMax": ["12"],
"valueMin": ["8"],
"valueTime": ["2014-08-20T14:32:56.125Z"]
}
| Optional, requires valueTime |
| valueTimeout
(vTo) | JSON Array of JSON Strings | Indication of the timeout associated with each value.
Provides an measure of how long a given value should be considered valid. If the specified time duration since the valueTime has been exceeded, the corresponding value shall no longer be considered valid.
When present, this field overrides a measureTimeout field.
The value of this field shall contain one or more JSON Strings, with the contents of each string containing a numeric value measured in seconds.Example 2.6.5
{
"value": ["10"],
"valueTime": ["2014-08-20T14:32:56.125Z"],
"valueTimeout": ["0.1"]
}
| Optional, requires valueTime |
## 2.7 Value Descriptive SNON Fields
Value descriptive fields provide additional information about how specific value measurements made by the sensor are displayed and organized.
Each SNON Fragment may contain the following JSON field:
| Field Name
(Short Name) | Data Type | Description | Mandatory |
| ------------- | ------------- | ------------- | --------- |
| valueError
(vE) | JSON String | Indication that errors are present.
Provides an indication of errors associated with value or set of values.
The value of this field shall contain a string describing the error. The contents of the error string is sensor-dependent. Example 2.7.1
{
"value": ["10"],
"valueTime": ["2014-08-20T14:32:56.125Z"],
"valueError": "Out of Calibration"
}
| Optional, requires valueTime |
## 2.8 User-Defined SNON Fields
SNON permits arbitary user-defined fields to be added to fragments, under the "extensions" object.
Each SNON Fragment may contain the following JSON field:
| Field Name
(Short Name) | Data Type | Description | Mandatory |
| ------------- | ------------- | ------------- | --------- |
| extensions
(ext) | JSON Object | Contains user-defined fields extending a fragment.
These fields are inherited according to the same rules as other SNON fields.Example 2.8.1
{
"extensions": {
"modbus": {
"address": "7000"
}
}
}
| Optional |
## 2.9 Entity Relationships
### 2.9.1 Device to Device Relationships
The following relationships between entities of class "device" are defined:
| Relationship Name | Description |
| ------------- | ------------- |
| "parent" | This relationship is used to create composite devices. Each "parent" relationship indicates that a device has a organizational relationship with another device.
Figure 5 shows how parent relationships can be used to define composite devices, where bold entities are devices:
Figure 5 - SNON "parent" Relationships
|
| "timesource" | This relationship is used to indicate time distribution. Each "timesource" relationship indicates that a device acquires its time from another device.
Figure 6 shows an example of a timesource relationship:
Figure 6 - SNON "timesource" Relationships
|
| "powered_by" | This relationship is used to indicate source of power. Each "powered_by" relationship indicates that a specific device has power supplied by another device.
Figure 7 shows an example of a "powered_by" relationship, where bold entities are devices:
Figure 7 - SNON "powered_by" Relationships
|
| "connected_to"| This relationship is used to indicate network connectivity. Each "connected_to" relationship indicates that a specific device has a communication connection to another device.
Figure 8 shows an example of a "connected_to" relationship, where bold entities are devices:
Figure 8 - SNON "connected_to" Relationships
|
### 2.9.2 Sensor to Device Relationships
The following relationships between entities of class "sensor" and entities of class "device" are defined:
| Relationship Name | Description |
| ------------- | ------------- |
| "parent" | This relationship is used to create composite sensors. Each "parent" relationship indicates that a sensor has a organizational relationship with another device.
Figure 9 shows how parent sensor relationships can be used to define devices, where bold entities are devices:
Figure 9 - SNON "parent" Relationships
|
| "timesource" | This relationship is used to indicate time distribution. Each "timesource" relationship indicates that a sensor acquires its time from another device.
Figure 10 shows an example of a timesource relationship:
Figure 10 - SNON "timesource" Relationships
|
| "powered_by" | This relationship is used to indicate source of power. Each "powered_by" relationship indicates that a specific sensor has power supplied by by another device.
Figure 11 shows an example of a "powered_by" relationship, where bold entities are devices:
Figure 11 - SNON "powered_by" Relationships
|
| "connected_to"| This relationship is used to indicate network connectivity. Each "connected_to" relationship indicates that a specific sensor has a communication connection to another device.
Figure 12 shows an example of a "connected_to" relationship, where bold entities are devices:
Figure 12 - SNON "connected_to" Relationships
|
| "located_at" | This relationship is used to indicate absolute location. Each "located_at" relationship indicates that the specified entity is located at a specific location, as defined by a sensor.
Figure 13 shows an example of a "located_at" relationship, where bold entities are devices, bold+italic entities are locations, and non-bold entities are sensors:
Figure 13 - SNON "located_at" Relationships
|
### 2.9.3 Sensor to Sensor Relationships
The following relationships between entities of class "sensor" are defined:
| Relationship Name | Description |
| ------------- | ------------- |
| "health" | This relationship is used to indicate sensor health. Each "health" relationship indicates that the health of a specific sensor is indicated by a second sensor.
Figure 14 shows an example of a "health" relationship, where bold entities are devices:
Figure 14 - SNON "health" Relationships
|
| "setpoint" | This relationship is used to indicate the sensor setpoint. Each "setpoint" relationship indicates that the desired value/range of a specific sensor is indicated by a second sensor.
Figure 15 shows an example of a "setpoint" relationship, where bold entities are devices:
Figure 15 - SNON "setpoint" Relationships
|
| "alarms" | This relationship is used to indicate the sensor alarm thresholds. Each "alarms" relationship indicates that the desired high and/or low values where an alarm should be triggered is indicated by a second sensor.
Figure 16 shows an example of a "alarms" relationship, where bold entities are devices:
Figure 16 - SNON "alarms" Relationships
|
| "alarm_inhibit" | This relationship is used to indicate if a sensor alarm should be inhibited. Each "alarm_inhibit" relationship indicates that if alarm should be inhibited is indicated by a second sensor.
Figure 17 shows an example of a "alarm_inhibit" relationship, where bold entities are devices:
Figure 17 - SNON "alarm_inhibit" Relationships
|
| "indeterminate" | This relationship is used to indicate if a sensor value should be considered to be indeterminate, where indeterminate is defined to mean that the value is not known. Each "indeterminate" relationship indicates that the state of indeterminacy is indicated by a second sensor.
Figure 18 shows an example of a "indeterminate" relationship, where bold entities are devices:
Figure 18 - SNON "indeterminate" Relationships
|
| "flag" | This relationship is used to indicate flags (labels) associated with a sensor. Each "flag" relationship indicates that flags should be added when indicated by a second sensor.
Figure 19 shows an example of a "flags" relationship, where bold entities are devices:
Figure 19 - SNON "flags" Relationships
|
| "derived_from" | This relationship is used to indicate when a sensor value is derived from one or more other sensor values. Each "derived_from" relationship indicates the sources of information used to derive the sensor value.
Figure 20 shows an example of a "derived_from" relationship, where bold entities are devices:
Figure 20 - SNON "derived_from" Relationships
|
### 2.9.4 Location to Location Relationships
The following relationships to entities of class "location" are defined:
| Relationship Name | Description |
| ------------- | ------------- |
| "located_in" | This relationship is used to indicate relative location. Each "located_in" relationship indicates that the specified "location" is located within another "location" entity, which has an entityClass of "location", and an entityName describing the location.
Figure 21 shows an example of a "located_in" relationship, where bold+italic entities are locations:
Figure 21 - SNON "located_in" Relationships
|
### 2.9.5 Device to Location Relationships
The following relationships to entities of class "location" are defined:
| Relationship Name | Description |
| ------------- | ------------- |
| "located_in" | This relationship is used to indicate relative location. Each "located_in" relationship indicates that the specified device is located within a "location" entity, which has a deviceID, a deviceName describing the location, and a deviceType field of "location".
Figure 22 shows an example of a "located_in" relationship, where bold entities are devices, and bold+italic entities are locations:
Figure 22 - SNON "located_in" Relationships
|
### 2.9.6 Location to Device Relationships
The following relationships to entities of class "location" are defined:
| Relationship Name | Description |
| ------------- | ------------- |
| "located_at" | This relationship is used to indicate absolute location. Each "located_at" relationship indicates that the specified location is located at a specific location, as defined by a device.
Figure 23 shows an example of a "located_at" relationship, where bold entities are devices, bold+italic entities are locations, and non-bold entities are sensors:
Figure 23 - SNON "located_at" Relationships
|
### 2.9.7 Sensor to Location Relationships
The following relationships to entities of class "location" are defined:
| Relationship Name | Description |
| ------------- | ------------- |
| "located_in" | This relationship is used to indicate relative location. Each "located_in" relationship indicates that the specified entity is located within a "location" entity, which has an entityClass of "location", and an entityName describing the location.
Figure 24 shows an example of a "located_in" relationship, where bold entities are devices, and bold+italic entities are locations:
Figure 24 - SNON "located_in" Relationships
|
### 2.9.8 User-Defined Relationships
SNON permits arbitrary user-defined relationships to be defined. It is up to the implementer to manage the namespace of user-defined relationship names to prevent collisions.
## 3.0 SNON Examples
A single measured value from a sensor:
Example 3.1
[
{
"entityID": "urn:uuid:1635a44f-b770-4418-8f05-e721823e8e41",
"value" : ["29.3"],
"valueTime" : ["2014-08-20T14:32:46.125Z"]
}
]
Compact form of Example 3.1:
Example 3.2
[{"eID":"urn:uuid:1635a44f-b770-4418-8f05-e721823e8e41","v":["29.3"],"vT":["2014-08-20T14:32:56.125Z"]}]
Two additional values, measured at different times:
Example 3.3
[
{
"entityID": "urn:uuid:1635a44f-b770-4418-8f05-e721823e8e41",
"value" : ["29.3", "30.3"],
"valueTime" : ["2014-08-20T14:32:56.125Z", "2014-08-20T14:33:06.125Z"]
}
]
Two values, with the second time expressed as a duration since the first time:
Example 3.4
[
{
"entityID": "urn:uuid:e129c1d6-0ac9-474a-948e-813ff3dc4e31",
"value" : ["29.3", "30.3"],
"valueTime" : ["2014-08-20T14:32:56.125Z", "/PT10S"]
}
]
A single measured value from a sensor, including message ID and time:
Example 3.5
[
{
"messageID": "urn:uuid:d244c281-52a1-4265-952a-294f56af3a05",
"messageTime": "2014-08-20T14:32:56.125Z",
"message": {
"entityID": "urn:uuid:319e1420-fd4e-49e9-9d43-a24b2cf98486",
"value" : ["29.3"],
"valueTime" : ["2014-08-20T14:32:56.125Z"]
}
}
]
A single measured value from two sensors, sent atomically:
Example 3.6
[
{
"messageID": "urn:uuid:15b4615a-b736-4e55-9d19-35b2ec807439",
"messageTime": "2014-08-20T14:32:56.125Z",
"message": {
"entityID": "urn:uuid:319e1420-fd4e-49e9-9d43-a24b2cf98486",
"value" : ["29.3"],
"valueTime" : ["2014-08-20T14:32:56.125Z"]
}
},
{
"messageID": "urn:uuid:1c265c77-9baf-4b3d-ba39-6efd9f33bf41",
"messageTime": "2014-08-20T14:32:56.125Z",
"message": {
{
"entityID": "urn:uuid:322ea74e-d914-44be-a95f-bb97b60b140b",
"value" : ["-102.2"],
"valueTime" : ["2014-08-20T14:32:56.125Z"]
}
}
]
A self-describing sensor with a single measured value:
Example 3.7
[
{
"messageID": "urn:uuid:be422ea8-289d-49fa-bd39-6a48f4711c75",
"messageTime": "2014-08-20T14:32:56.125Z",
"message": {
"sentityID": "urn:uuid:8f5308d5-a1ca-4ad4-9a7f-3a70d4177551",
"entityName": {"*":"Temperature"},
"measureType" : "numeric",
"measureAcquire" : "sample",
"measureUnit" : "°C",
"value" : ["29.3"],
"valueTime" : ["2014-08-20T14:32:56.125Z"]
}
}
]
A value that will use the same sensor information defined in Example 3.7:
Example 3.8
[
{
"entityID": "urn:uuid:8f5308d5-a1ca-4ad4-9a7f-3a70d4177551",
"value" : ["28.8"],
"valueTime" : ["2014-08-20T14:32:57.126Z"]
}
]
An update to the sensor information defined in Example 3.7:
Example 3.9
[
{
"messageID": "urn:uuid:be422ea8-289d-49fa-bd39-6a48f4711c75",
"messageTime": "2014-08-20T14:32:56.125Z",
"message": {
"entityID": "urn:uuid:8f5308d5-a1ca-4ad4-9a7f-3a70d4177551",
"precedentID": "urn:uuid:be422ea8-289d-49fa-bd39-6a48f4711c75",
"sensorName": {"*":"Outside Temperature"}
}
}
]
A summary of a minute's worth of values from a temperature sensor:
Example 3.10
[
{
"messageID": "urn:uuid:75a82b1b-d617-4c06-9b27-db2abea3bb14",
"messageTime": "2014-08-20T14:32:56.125Z",
"message": {
"entityID": "urn:uuid:461bc368-0925-484b-ad96-c03fef490ece",
"entityName": {"*":"Temperature"},
"measureType" : "numeric",
"measureAcquire" : "summary",
"measureUnit" : "°C",
"value" : ["28.0"],
"valueMax" : ["29.1"],
"valueMin" : ["27.5"],
"valueTime" : ["2014-08-20T14:33:00.000Z/PT01M"]
}
}
]
Composite GPS device:
Example 3.11
[
{
"entityID": "urn:uuid:bd34facd-636f-4218-8a81-b99576d363ff",
"entityClass": "Device",
"entityName": {"*":"GPS"}
}
[
Status of a GPS sensor:
Example 3.12
[
{
"entityID": "urn:uuid:3459c049-c4fc-42ca-b3f1-b22f5667cd1b",
"entityClass": "sensor",
"entityRelations": {
"parent":["urn:uuid:bd34facd-636f-4218-8a81-b99576d363ff"]
},
"entityName": {"*":"GPS Status"},
"measureType" : "enumeration",
"measureAcquire" : "sample",
"measureLabel" : {"0":{"*":"Unlocked"}, "1":{"*":"Locked"}},
"value" : ["1"],
"valueTime" : ["2014-08-20T14:32:57.126Z"]
}
[
Latitude of a GPS sensor:
Example 3.13
[
{
"entityID": "urn:uuid:eb203e89-5d38-4d7b-a772-4188beac43b7",
"entityClass": "sensor",
"entityRelations": {
"parent":["urn:uuid:bd34facd-636f-4218-8a81-b99576d363ff"]
},
"entityName": {"*":"GPS Latitude"},
"measureType" : "enumeration",
"measureAcquire" : "sample",
"value" : ["34.017161"],
"valueTime" : ["2014-08-20T14:32:57.126Z"]
}
]
Longitude of a GPS sensor:
Example 3.14
[
{
"entityID": "urn:uuid:c195d9fe-625b-4597-9a3a-4cbcc8f4a0c4",
"entityClass": "sensor",
"entityRelations": {
"parent":["urn:uuid:bd34facd-636f-4218-8a81-b99576d363ff"]
},
"entityName": {"*":"GPS Longitude"},
"measureType" : "enumeration",
"measureAcquire" : "sample",
"value" : ["-118.269397"],
"valueTime" : ["2014-08-20T14:32:57.126Z"]
}
]
Heading sensor, linked to the GPS sensor:
Example 3.15
[
{
"entityID": "urn:uuid:2432dc10-877b-4506-bf85-6fe78cfb3633",
"entityClass": "sensor",
"entityRelations": {
"location":["urn:uuid:bd34facd-636f-4218-8a81-b99576d363ff"]
},
"entityName": {"*":"Heading Angle"},
"measureType" : "numeric",
"measureAcquire" : "sample",
"measureUnit" : "radian",
"value" : ["48.4"],
"valueTime" : ["2014-08-20T14:32:57.126Z"]
}
]
## 4.0 SNON Schema
SNON messages and fragments can be validated using the below [JSON schema](http://json-schema.org):
{
"$schema": "http://json-schema.org/draft-04/schema#",
"id": "http://snon.org/v2/snon-schema.json#",
"definitions": {
"message": {
"type": "object",
"properties": {
"messageID": { "$ref": "#/definitions/type_id" },
"mID": { "$ref": "#/definitions/type_id" },
"messageTime": { "$ref": "#/definitions/type_iso8601_time" },
"mT": { "$ref": "#/definitions/type_iso8601_time" },
"message": { "$ref": "#/definitions/fragment_long" },
"m": { "$ref": "#/definitions/fragment_short" }
},
"dependencies": {
"messageID": {"required": ["messageTime", "message"],
"not":{"anyOf":[
{"required":["mID"]},
{"required":["mT"]},
{"required":["m"]}
]}},
"mID": {"required": ["mT", "m"],
"not":{"anyOf":[
{"required":["messageID"]},
{"required":["messageTime"]},
{"required":["message"]}
]}},
"messageTime": ["messageID", "message"],
"mT": ["mID", "m"],
"message": ["messageID", "messageTime"],
"m": ["mID", "mT"]
},
"additionalProperties": false
},
"fragment_long": {
"type": "object",
"properties": {
"entityID": { "$ref": "#/definitions/type_id" },
"entityClass": { "type": "string" },
"entityName": { "$ref": "#/definitions/type_intl_name" },
"entityType": { "$ref": "#/definitions/type_intl_name" },
"entityRelations": { "$ref": "#/definitions/type_relations" },
"precedentID": { "$ref": "#/definitions/type_id" },
"measureUnit": { "type": "string" },
"measureType": { "type": "string" },
"measureAcquire": { "type": "string" },
"measureUnitPrefix": { "$ref": "#/definitions/type_intl_name" },
"measureUnitSuffix": { "$ref": "#/definitions/type_intl_name" },
"measureUnitPrefixEx": { "$ref": "#/definitions/type_intl_name" },
"measureUnitSuffixEx": { "$ref": "#/definitions/type_intl_name" },
"measureLabel": { "$ref": "#/definitions/type_intl_enum" },
"measureSpanLow": { "$ref": "#/definitions/type_numeric_string" },
"measureSpanHigh": { "$ref": "#/definitions/type_numeric_string" },
"measureDisplayLow": { "$ref": "#/definitions/type_numeric_string" },
"measureDisplayHigh": { "$ref": "#/definitions/type_numeric_string" },
"measureDisplayUnit": { "$ref": "#/definitions/type_intl_name" },
"measureUpdateRate": { "$ref": "#/definitions/type_numeric_string" },
"measureTimeout": { "$ref": "#/definitions/type_numeric_string" },
"measureResolution": { "$ref": "#/definitions/type_numeric_string" },
"measureAccuracy": { "$ref": "#/definitions/type_numeric_string" },
"valueTime": { "$ref": "#/definitions/type_ISO8601_timeduration_array" },
"value": { "$ref": "#/definitions/type_string_array" },
"valueMax": { "$ref": "#/definitions/type_string_array" },
"valueMin": { "$ref": "#/definitions/type_string_array" },
"valueTimeout": { "$ref": "#/definitions/type_numeric_string" },
"valueError": { "type": "string" },
"extensions": { "type": "object" }
},
"dependencies": {
"entityName": ["entityID"],
"entityClass": ["entityID"],
"entityRelations": ["entityID"],
"valueTime": ["entityID"],
"value": ["valueTime"],
"valueMax": ["valueTime"],
"valueMin": ["valueTime"],
"valueTimeout": ["valueTime"],
"valueError": ["valueTime"]
},
"additionalProperties": false
},
"fragment_short": {
"type": "object",
"properties": {
"eID": { "$ref": "#/definitions/type_id" },
"eC": { "type": "string" },
"eN": { "$ref": "#/definitions/type_intl_name" },
"eT": { "$ref": "#/definitions/type_intl_name" },
"eR": { "$ref": "#/definitions/type_relations" },
"pID": { "$ref": "#/definitions/type_id" },
"meU": { "type": "string" },
"meT": { "type": "string" },
"meAq": { "type": "string" },
"meUP": { "$ref": "#/definitions/type_intl_name" },
"meUS": { "$ref": "#/definitions/type_intl_name" },
"meUPx": { "$ref": "#/definitions/type_intl_name" },
"meUSx": { "$ref": "#/definitions/type_intl_name" },
"meL": { "$ref": "#/definitions/type_intl_enum" },
"meSL": { "$ref": "#/definitions/type_numeric_string" },
"meSH": { "$ref": "#/definitions/type_numeric_string" },
"meDL": { "$ref": "#/definitions/type_numeric_string" },
"meDH": { "$ref": "#/definitions/type_numeric_string" },
"meDU": { "$ref": "#/definitions/type_intl_name" },
"meUR": { "$ref": "#/definitions/type_numeric_string" },
"meTo": { "$ref": "#/definitions/type_numeric_string" },
"meR": { "$ref": "#/definitions/type_numeric_string" },
"meAc": { "$ref": "#/definitions/type_numeric_string" },
"vT": { "$ref": "#/definitions/type_ISO8601_timeduration_array" },
"v": { "$ref": "#/definitions/type_string_array" },
"vMax": { "$ref": "#/definitions/type_string_array" },
"vMin": { "$ref": "#/definitions/type_string_array" },
"vTo": { "$ref": "#/definitions/type_numeric_string" },
"vE": { "type": "string" },
"ext": { "type": "object" }
},
"dependencies": {
"eN": ["eID"],
"eC": ["eID"],
"eR": ["eID"],
"vT": ["eID"],
"v": ["vT"],
"vMax": ["vT"],
"vMin": ["vT"],
"vTo": ["vT"],
"vE": ["vT"]
},
"additionalProperties": false
},
"type_id": {
"type": "string"
},
"type_intl_name": {
"type": "object",
"minProperties": 1,
"additionalProperties": { "type": "string" }
},
"type_intl_enum": {
"type": "object",
"minProperties": 1,
"patternProperties": {
"^*": {
"$ref": "#/definitions/type_intl_name"
}
},
"additionalProperties": false
},
"type_iso8601_time": {
"type": "string",
"pattern": "^[1-9][0-9]{3}-(0[1-9]|1[0-2])-([0][1-9]|[1-2][0-9]|3[0-1])T([01][0-9]|2[0-3]):([0-5][0-9]):([0-5][0-9])([.,][0-9]{3})Z(/PT(([01][0-9]|2[0-3])H)?(([0-5][0-9])M)?(([0-9]*)([.,][0-9]{3})?S)?)?$"
},
"type_iso8601_duration": {
"type": "string",
"pattern": "^/PT(([01][0-9]|2[0-3])H)?(([0-5][0-9])M)?(([0-9]*)([.,][0-9]{3})?S)?$"
},
"type_ISO8601_time_array": {
"type": "array",
"minItems": 1,
"items": {
"$ref": "#/definitions/type_iso8601_time"
}
},
"type_ISO8601_duration_array": {
"type": "array",
"minItems": 1,
"items": {
"$ref": "#/definitions/type_iso8601_duration"
}
},
"type_ISO8601_timeduration_array": {
"type": "array",
"minItems": 1,
"items": {
"anyOf": [
{ "$ref": "#/definitions/type_iso8601_time" },
{ "$ref": "#/definitions/type_iso8601_duration" }
]
}
},
"type_numeric_string": {
"type": "string",
"pattern": "^[-+]?[0-9]*\\.?[0-9]+$"
},
"type_string_array": {
"type": "array",
"minItems": 1,
"items": {
"type": "string"
}
},
"type_relations": {
"type": "object",
"minProperties": 1,
"patternProperties": {
"^*": {
"type": "array",
"minItems": 1,
"items": {
"type": "string"
}
}
},
"additionalProperties": false
},
"jose_encrypted": {
"type": "object",
"required": ["protected", "ciphertext"],
"properties": {
"protected": { "type": "string" },
"iv": { "type": "string" },
"ciphertext": { "type": "string" },
"encrypted_key":{ "type": "string" },
"tag": { "type": "string" }
},
"additionalProperties": false
},
"jose_signed": {
"type": "object",
"required": ["payload", "protected", "signature"],
"properties": {
"header": {
"type": "object",
"properties": {
"kid": { "type": "string" }
},
"additionalProperties": false
},
"payload": { "type": "string" },
"protected": { "type": "string" },
"signature": { "type": "string" }
},
"additionalProperties": false
}
},
"type": "array",
"minItems": 1,
"items": {
"anyOf": [
{ "$ref": "#/definitions/message" },
{ "$ref": "#/definitions/fragment_long" },
{ "$ref": "#/definitions/fragment_short" },
{ "$ref": "#/definitions/jose_encrypted" },
{ "$ref": "#/definitions/jose_signed" }
]
}
}
The following constraints are not validated by this schema, and must be validated by the SNON receiver:
* Resolvability of precedentID
* Equal number of array items in valueTime, value, valueMax, valueMin and valueTimeout
* First item in valueTime must be an ISO 8601 time (subsequent items may be an ISO 8601 duration)
* If there is a valueTime, at least one of value, valueMax or valueMin must be present
* Contents of value, valueMax and valueMin must correspond to resolved measureType
* Validity of SNON fragments or messages contained within a JWS "payload" or JWE "ciphertext" field
## 5.0 SNON Security
Sensor data often must be encrypted to protect confidentiality, and signed to protect integrity and demonstrate the authenticity of the source of the data. SNON specifies the use of JSON Object Signing and Encryption (JOSE) as described in [RFC 7516](https://tools.ietf.org/html/rfc7516) and [RFC 7515](https://tools.ietf.org/html/rfc7515), although other encryption and signing standards may also be used.
An SNON collection shall be used as the plaintext, and JWE or JWS JSON Serialization shall be used for the encrypted or signed representation, as shown in the below example:
Original SNON collection:
Example 5.1
[{"entityID":"urn:uuid:fa164ee2-f1b7-43ee-8202-e61bc005db2b","value":["1"],"valueTime":["2017-11-29T03:32:03.752Z"]},{"entityID":"urn:uuid:c4c0b0b6-f1c5-4695-9370-d925f8370c07","value":["0"],"valueTime":["2017-11-29T03:32:03.752Z"]},{"entityID":"urn:uuid:d90526a1-4e62-493e-870c-6216216a03c8","value":["0"],"valueTime":["2017-11-29T03:32:03.752Z"]},{"entityID":"urn:uuid:12b976ea-4867-42b1-bcc6-f6b1d5e938e7","value":["0"],"valueTime":["2017-11-29T03:32:03.752Z"]}]
JWE representation when encrypted using RSA v1.5, according to [RFC 7520](https://tools.ietf.org/html/rfc7520#section-5.1):
Example 5.2
[{"tag":"5DlAaLHKrg5JBCh604TtfQ","protected":"eyJhbGciOiJSU0ExXzUiLCJlbmMiOiJBMTI4R0NNIn0","iv":"QIuWxaOOwgIfw6oo","ciphertext":"fwk4KeCiC6rItJ_TD5kn7ymRn7eX-Ckqi0k3N18sEsksF39f2KBezt609IeZQuIqxFBheeLWucwuWa-tpYiWv-zDVUkQ-AhDNwdzo1tPevLOiUytU2NkCjK0uX6yazdaBHxVXFUbwa1HDQ_9-8H_wbpF1pPMrs5kBXt2cHUBdjpTopSfn0Q_rD8iHgz0s7eyMjWjSGqM5Fhg7T79qMwvRtqlyWIuqHVR40U2Gmhk4gy9VOXomq_P7qHeYB507zlAAxggsbYSJvwq6biluilqW5lPbDCR9MSsWjYFggSPr_aGDw6VN-_kXjkVvnBqRkq1B2AU6aKwD47CuBYSCBJDqcHMhKdwQmJ_M4xyg4k0EYl2iwEd7UDKkylzlxi0kfQ4sClW6DHyc_tiymT1ntPkL0l5cerK47kr8CarmJyRCWlQk_kasXr9AXsB9w6mu7obXzdX80FBQJmjzgXYhPC_mcVj6gKQNIyXoFIhlr7ZIEKnYRAwddvtk04Y5amCgBw0sDpS1j-GDimGmZ3iVCV4wsLeih0Ybv5oEqbgE3HiOteLl-8Q4fqP034rTtgNfT0ZxkmnybZyres1C3hwrmfmu-Z1srZ5HsIQuOqovhFE_68i","encrypted_key":"fCeHnQCXO5KqBeYaoqoJ6iFuVTHRcvhh6p7k5LrS6iA3f9XhExjLybggze8v_QpJzLoVXbD31aT1uUTiAyQ93GzsswbMR1X7jWeZnehX8cUbccjkhW2udoXYHe1Du-QibCBgc2K-Psp2Mt17Wg1rqmgGkJ5R36V_uOyBKthY_8AbXabzhgGN9H-A8WwfD6-iB69WjeLrHlmE0psn6jF07cPNzFV2j8rgaED6ejULCE54y3qh6f-9AAMdNH1G2GyjYBhbEg2rSJC80-q95prpnscjUKrNspdV8QzTlg1_AVBEqOqLvEAwWschDMgIFU-Y1HWWSm1JeftxpHfERCySXQ"}]
JWS representation when signed using RSA v1.5, according to [RFC 7520](https://tools.ietf.org/html/rfc7520#section-4.1):
Example 5.3
[{"protected":"eyJhbGciOiJSUzI1NiJ9","signature":"EyRkR84B0GJiOtVETZI6tj2biUJzACY2MBcggz3NWu8uCm5FWYfndwJw0pI7ouGaAhpgre3YmK1XoFZhWDFlrPBAx5vKaAsiqIGPvaNX3PTjnw4auEaETSraW5bT1Zg9ZOCGg3o6jwWVVjQecGevZulqfCiEe3bKV48cRHu4WOQG_PoqYdHC4Jw1ugOgpiqCqzaRi34Fek2h3lisufD5dFBJG36UZStYfpSNComfbdhNxe-zQhl42hyE_SG_qUIIHVFmKCOiSLJMPM3TWXKKFWL-B3jNC1Gx79c0mPgfncuXZUCgK8YhD7qOlyR-HXtwdzJ2z7lja186uzdoTnoV9w","header":{"kid":"urn:uuid:bd8dd740-ccd9-4e80-aae9-f1c9ebea754f"},"payload":"W3siZW50aXR5SUQiOiJ1cm46dXVpZDpmYTE2NGVlMi1mMWI3LTQzZWUtODIwMi1lNjFiYzAwNWRiMmIiLCJ2YWx1ZSI6WyIxIl0sInZhbHVlVGltZSI6WyIyMDE3LTExLTI5VDAzOjMyOjAzLjc1MloiXX0seyJlbnRpdHlJRCI6InVybjp1dWlkOmM0YzBiMGI2LWYxYzUtNDY5NS05MzcwLWQ5MjVmODM3MGMwNyIsInZhbHVlIjpbIjAiXSwidmFsdWVUaW1lIjpbIjIwMTctMTEtMjlUMDM6MzI6MDMuNzUyWiJdfSx7ImVudGl0eUlEIjoidXJuOnV1aWQ6ZDkwNTI2YTEtNGU2Mi00OTNlLTg3MGMtNjIxNjIxNmEwM2M4IiwidmFsdWUiOlsiMCJdLCJ2YWx1ZVRpbWUiOlsiMjAxNy0xMS0yOVQwMzozMjowMy43NTJaIl19LHsiZW50aXR5SUQiOiJ1cm46dXVpZDoxMmI5NzZlYS00ODY3LTQyYjEtYmNjNi1mNmIxZDVlOTM4ZTciLCJ2YWx1ZSI6WyIwIl0sInZhbHVlVGltZSI6WyIyMDE3LTExLTI5VDAzOjMyOjAzLjc1MloiXX1d"}]
Nesting of signatures and encryption is defined in section 6 of [RFC 7520](https://tools.ietf.org/html/rfc7520#section-6).
When traversing relationships or resolving precedents, it is important to verify the signature of each message in the chain.
Since Sensor IDs are typically used as MQTT topic names, it is strongly recommended that these be opaque (or hashes) to ensure that information is not leaked. This is why the use of hierarchical MQTT topic names are not recommended, as this will leak information about relationships between sensors.
## 6.0 SNON License
Clear BSD License
Copyright (c) – 2017, NetApp, Inc. All rights reserved.
Redistribution and use in source and binary forms, with or without modification, are
permitted (subject to the limitations in the disclaimer below) provided that the
following conditions are met:
* Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
* Neither the name of NetApp, Inc. nor the names of its contributors may be used
to endorse or promote products derived from this software without specific prior
written permission.
NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED BY THIS LICENSE.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
## 7.0 SNON Changelog
SNON 2.0 2017-11-28

* Added JSON schema
* Specified where user-defined fields are allowed
* Relaxation of field restrictions to improve linked messages
* SNON Messages now can contain multiple SNON Fragments
* sensorHierarchy deprecated. Replaced by deviceID and sensorRelations/deviceRelations
* valueUncertainty, valueSequence, valueSession and valueHealth deprecated
* location field deprecated, replace with sensorRelations/deviceRelations
* Relations added for thresholds, setpoints, alarms, inhibit, indeterminate and flags
* Added Sensor Catalog use cases
* Internationalization support
[SNON 0.3 2015-08-04](v1/index.html)
* Added additional detail on how to use SNON with MQTT
* Retired messageHash and messageSignature in favor of [JOSE](https://tools.ietf.org/html/rfc7520)
* Addition of field short names for low-resource platforms
* Additional examples added
SNON 0.2 2015-07-05
* Addition of valueTimeout and valueSequence fields
* Clarification of measureUnit and measureLabel fields
SNON 0.1 2014-09-24
Please report errors, suggestions, etc, at https://github.com/dslik/snon-spec