Multiple Values for a Key

There are two use cases for multiple values for a single data point

  • Multiple instances of a common device-e.g. two engines or multiple batteries.
  • Multiple devices providing duplicate data-multiple values for the same Signal K key from different sensors. This is fairly common as most boats have multiple sensors capable of generating the same data (but not necessarily the same value). For example, course over ground (COG) may come from both a compass and GPS or a boat may be equipped with multiple depth sounders.

Multiple Instances of a Common Device

Some parts of the Signal K schema are device oriented.

For example, many boats have multiple batteries. However each battery has multiple, common quantities like voltage, current and temperature. In this case, it makes more sense for these values to be organized by instance. Therefore, in the Signal K model, each battery bank is it’s own instance: for example electrical.batteries.starter and electrical.batteries.house. Then beneath that prefix there are the various properties for each battery.

This organisation allows a user interface to organise the individual readings in meaningful groups and allows consumers to query all the values related to that piece of equipment via the REST API. Furthermore, this structure maintains the primary requirement that a given data value have a fixed and unique URI, but gives flexibility in the structure and complexities of data.

The same device centric organisation is used within the propulsion subschema, to support the common use case of two engines via propulsion.port and propulsion.starboard.

The values starter, house, port and starboard are examples and not specified in the schema. You are free to use application specific values within the regexp specified in the JSON schema.

Multiple Devices Providing Duplicate Data

It is quite possible for a key value to come from more than one device. Many modern devices have a built in GPS receiver and as a result on any given boat there may be several sources of position, speed over ground, and heading. Multiple depth sounders are also common, often installed to port and starboard on monohull sailboats or in each hull of a catamaran.

Given that the validity of these various sources of data may change in a context-specific way, Signal K provides a mechanism for these values to be grouped together so that the consumer of the data may choose which value (or values) to display1.

When dealing with multiple sources of data, it becomes important to know where the data is coming from. Signal K provides a mechanism for that in the form of the sources top level object and references into that object via the $source property. See sources for detailed information on the structure of the sources object and how it is referenced by the $source property.

The first source of a particular data point becomes the default source for that data and a normal Signal K object is created.

{
  "self": "urn:mrn:signalk:uuid:c0d79334-4e25-4245-8892-54e8ccc8021d",
  "version": "0.9.0",
  "vessels": {
    "urn:mrn:signalk:uuid:c0d79334-4e25-4245-8892-54e8ccc8021d": {
      "uuid": "urn:mrn:signalk:uuid:c0d79334-4e25-4245-8892-54e8ccc8021d",
      "navigation": {
        "courseOverGroundTrue": {
          "value": 3.61562407843144,
          "$source": "ttyUSB0.GP",
          "timestamp": "2017-04-03T06:14:04.451Z"
        }
      }
    }
  }
}

It has come from device sources.ttyUSB0.GP, where further details can be found.

If another value with different source arrives, the Signal K server will add the values attribute with values from both the first and second sources. The initial source‘s data will continue to populate the value property in the key.

{
  "self": "urn:mrn:signalk:uuid:c0d79334-4e25-4245-8892-54e8ccc8021d",
  "version": "0.9.0",
  "vessels": {
    "urn:mrn:signalk:uuid:c0d79334-4e25-4245-8892-54e8ccc8021d": {
      "uuid": "urn:mrn:signalk:uuid:c0d79334-4e25-4245-8892-54e8ccc8021d",
      "navigation": {
        "courseOverGroundTrue": {
          "value": 3.615624078431440,
          "$source": "ttyUSB0.GP",
          "timestamp": "2017-04-03T06:14:04.451Z",
          "values":{
            "ttyUSB0.GP.RMC":{
              "value": 3.615624078431440,
              "timestamp": "2017-04-03T06:14:04.451Z"
            },
            "n2k.ikommunicate.128267":{
              "value": 3.615624078431453,
              "timestamp": "2017-04-03T06:14:04.451Z"
            }
          }
        }
      }
    }
  },
  "sources":{
    "ttyUSB0": {
      "GP": {
        "sentences": {
          "RMC": "2017-04-03T06:14:04.451Z"
        }
      }
    },
    "ikommunicate": {
      "2": {
        "n2k": {
          "src": "2",
          "pgns": {
            "128267": "2017-04-03T06:14:05.221Z"
          }
        }
      }
    }
  }
}

Multiple Values in Delta Messages

When a client subscribes to navigation.courseOverGroundTrue, they receive all the values held. The update message does not include the values path, the case above looks like:

{
  "context": "vessels.urn:mrn:signalk:uuid:c0d79334-4e25-4245-8892-54e8ccc8021d",
  "updates": [
    {
      "source": {
        "label": "GPS-1",
        "type": "NMEA0183",
        "talker": "GP",
        "sentence": "RMC"
      },
      "timestamp": "2017-04-03T06:14:04.451Z",
      "values": [
        {
          "path": "navigation.courseOverGroundTrue",
          "value": 3.615624078431440
        }
      ]
    },
    {
      "source": {
        "label": "actisense",
        "type": "NMEA2000",
        "src": "115",
        "pgn": 128267
      },
      "timestamp": "2017-04-03T06:14:04.451Z",
      "values": [
        {
          "path": "navigation.courseOverGroundTrue",
          "value": 3.615624078431453
        }
      ]
    }
  ]
}

Individual updates can be distinguished by their source.

If a client wants only the values of a specific source it should subscribe to a path that includes the full path under values including the source reference key of the source. The source reference should be enclosed in square brackets: navigation.courseOverGroundTrue.values[n2k./dev/ikommunicate.128267]. The client can retrieve the relevant data via REST API.

Note: The exact format of the update message is affected by the subscription policy. A policy of instant will result in changes being sent immediately, so typically one item in values per update. A policy of fixed will result in periodic updates which may contain many items in values.

The update allows grouping values by source.


[1] Specifying preferred sources is still an under-development enhancement to the Node server.

results matching ""

    No results matching ""