# Digital Matter

Digital Matter has a broad range of both wired and battery powered GPS trackers.

{% hint style="info" %}
All types are supported by the same decoder. Therefore there's no specific page per device type. However not every message and field is decoded for each type and not every device is able to generate every field.
{% endhint %}

{% hint style="warning" %}
Currently KPN does not support adding your own Digital Matter devices.&#x20;
{% endhint %}

* Supported network type(s): `KPNM2M`
* Device Specification ID: `digital-matter`
* Device Specification UUID: `3cd3d4cd-1eb5-42ed-8ed0-6be9160f8b6d`

| Decoders                 | decoderSpecificationUUID               | Description                                                     |
| ------------------------ | -------------------------------------- | --------------------------------------------------------------- |
| Digital Matter           | `25179211-a3b6-567f-ad9a-f9a83ac0a17e` | Decoder for Digital Matter devices.                             |
| Digital Matter Debugging | `48b93005-1719-599d-8f43-c56471c8c644` | Decoder for Digital Matter devices with extra debug information |

### Decoded Data for Digital Matter

Decoder for Digital Matter devices.

Digital Matter devices have a flexible message layout. Depending on the device-type, the device configuration and state at a given time some SenML records may be present or not.&#x20;

The message includes blocks of SenML records that are named with a prefix. In some cases, a block of SenML records is sent multiple times within a message. When this occurs, an index is included in the record name.

For example, in the case of a Wi-Fi scan result, the signal strength of each scanned Wi-Fi access point is sent, and the names of the records are made unique using an index (`wifiscan:macs:<index>:signalStrength`), with an index of 0 for the first Wi-Fi scan result. The corresponding MAC address can then be found in another SenML record with the same prefix (`wifiscan:macs:<index>:mac`).

#### Implementation considerations

* SenML can be structured in different ways, and we do not guarantee the examples below will look the same as what you will receive on your Destination. To make sure you can handle the SenML optimally, take a look at our documentation about [Understanding and Interpreting SenML Data](https://docs.kpnthings.com/kpn-things/building-blocks/data-processing/thingsml-and-senml/senml/understanding-and-interpreting-senml-data).
* Devices may output different types of information depending on their type and configuration. Not all the details below may apply to every device.
* Digital Matter devices can generate a large volume of data, which may result in the output being split across multiple messages at the destination. To handle this correctly, the receiving system may need a buffering mechanism to combine these messages into a single logical unit.
* Devices supporting multiple localization methods (e.g., GPS and WiFi) might report both. To determine which is more recent, compare the `gps:timestamp` with the `ts` of the WiFi data. Since devices always send their last known GPS location, the `gps:timestamp` reflects when the GPS fix was obtained, while the message `ts` shows when it was sent.
* If both GPS and WiFi data have recent timestamps, use the `radius` field to compare their accuracy.
* Sometimes it's not possible to resolve the WiFi access points to a reliable location. We make this transparent through the `extLocationResolveStatusCode`.&#x20;
* When multiple devices scan for Bluetooth tags, they may report the same tag. If it's important to establish a relationship between a specific device and a tag, implement logic to determine which device should be associated with which tag.

#### Generic Data

All messages contain fields that identify the device, indicate the timestamp and the message sequence number.

| name           | type   | unit    | example | description                                                                                       |
| -------------- | ------ | ------- | ------- | ------------------------------------------------------------------------------------------------- |
| timeOrigin     | string |         |         | Can be 'DEVICE' if the timestamp in this record is originated by the device or 'NETWORK'          |
| sequenceNumber | number | `count` |         | Contains the messages record number that is incremented for a group of records within the message |

Example:

```json
[
    {
        "n": "timeOrigin",
        "vs": "NETWORK",
        "bt": 1720702306,
        "bn": "urn:dev:IMEI:981157598401234:"
    },
    { "n": "timeOrigin", "vs": "DEVICE", "bt": 1720702306.924 },
    { "n": "sequenceNumber", "u": "count", "v": 24924 },
    ...
]
```

#### **GPS Data (gps:)**

| name                                     | type    | unit  | example            | description                                |
| ---------------------------------------- | ------- | ----- | ------------------ | ------------------------------------------ |
| gps:logReason                            | string  |       | Start of trip      | Indicates a reason for reporting this data |
| gps:time                                 | number  |       | 1724758046         | Seconds since 1/1/1970                     |
| gps:latitude                             | number  | `lat` | 51.9071025         |                                            |
| gps:longitude                            | number  | `lon` | 4.4891488          |                                            |
| gps:altitude                             | number  | `m`   | 54                 |                                            |
| gps:speed                                | number  | `m/s` | 1                  |                                            |
| gps:speed:accuracyEstimate               | number  | `m/s` | 0.013              |                                            |
| gps:heading                              | number  | `rad` | 1.5707963267948966 |                                            |
| gps:accuracy:positionDilutionOfPrecision | number  | `/`   | 0.5                |                                            |
| gps:accuracy:radius                      | number  | `m`   | 65                 |                                            |
| gps:fix:valid                            | boolean |       | true               |                                            |
| gps:fix:threeDimensional                 | boolean |       | true               |                                            |
| gps:fix:reused                           | boolean |       | false              |                                            |

Example:

```json
[
    ...
    { "n": "gps:logReason", "vs": "Start of trip" },
    { "n": "gps:time", "v": 1724758046 },
    { "n": "gps:latitude", "u": "lat", "v": 51.9071025 },
    { "n": "gps:longitude", "u": "lon", "v": 4.4891488 },
    { "n": "gps:altitude", "u": "m", "v": 54 },
    { "n": "gps:speed", "u": "m/s", "v": 1 },
    { "n": "gps:speed:accuracyEstimate", "u": "m/s", "v": 0.013000000000000001 },
    { "n": "gps:heading", "u": "rad", "v": 1.5707963267948966 },
    { "n": "gps:accuracy:positionDilutionOfPrecision", "u": "/", "v": 0.5 },
    { "n": "gps:accuracy:radius", "u": "m", "v": 65 },
    { "n": "gps:fix:valid", "vb": true },
    { "n": "gps:fix:threeDimensional", "vb": true },
    { "n": "gps:fix:reused", "vb": false }
    ...
]
```

#### Digital Data (digitalData:)

| name                                       | type    | unit | example         | description                                |
| ------------------------------------------ | ------- | ---- | --------------- | ------------------------------------------ |
| digitalData:logReason                      | string  |      | `Start of trip` | Indicates a reason for reporting this data |
| digitalData:inputs                         | string  |      | `01010001...`   | Bitstring of 32 bits                       |
| digitalData:outputs                        | string  |      | `01010001...`   | Bitstring of 16 bits                       |
| digitalData:flags:tripStatus               | boolean |      | `true`          |                                            |
| digitalData:flags:internalBatteryGood      | boolean |      | `true`          |                                            |
| digitalData:flags:externalPowerGood        | boolean |      | `true`          |                                            |
| digitalData:flags:connectedToGsm           | boolean |      | `true`          |                                            |
| digitalData:flags:shuntingPowerFromBattery | boolean |      | `true`          |                                            |
| digitalData:flags:externalPowerEnabled     | boolean |      | `true`          |                                            |
| digitalData:flags:magnetAbsent             | boolean |      | `true`          |                                            |
| digitalData:flags:recoveryModeActive       | boolean |      | `true`          |                                            |
| digitalData:flags:deviceSpecificBits       | string  |      | `01010001`      | Bistring containing 8 device specific bits |

Example:

```json
[
    ...
    {
        "n": "digitalData:logReason",
        "vs": "Bluetooth Tag Data (update found lost reason covered in tag data)"
    },
    { "n": "digitalData:inputs", "vs": "00000000000000000000000000000000" },
    { "n": "digitalData:outputs", "vs": "0000000000000000" },
    { "n": "digitalData:flags:tripStatus", "vb": false },
    { "n": "digitalData:flags:internalBatteryGood", "vb": false },
    { "n": "digitalData:flags:externalPowerGood", "vb": false },
    { "n": "digitalData:flags:connectedToGSM", "vb": false },
    { "n": "digitalData:flags:shuntingPowerFromBattery", "vb": false },
    { "n": "digitalData:flags:externalPowerEnabled", "vb": false },
    { "n": "digitalData:flags:magnetAbsent", "vb": false },
    { "n": "digitalData:flags:recoveryModeActive", "vb": false },
    { "n": "digitalData:flags:deviceSpecificBits", "vs": "00000000" },
    ...
]
```

#### Analogue Data (analogueData:)

| name                                    | type   | unit | example         | description                                  |
| --------------------------------------- | ------ | ---- | --------------- | -------------------------------------------- |
| analogueData:logReason                  | string |      | `Start of trip` | Indicates a reason for reporting this data   |
| analogueData:internalBatteryVoltage     | number | V    | `3.3`           |                                              |
| analogueData:externalBatteryVoltage     | number | V    | `12`            |                                              |
| analogueData:internalTemperature        | number | Cel  | `25`            |                                              |
| analogueData:gsmSignalStrength          | number | dBW  | `40`            |                                              |
| analogueData:loadedBatteryVoltage       | number | V    | `11.5`          |                                              |
| analogueData:remainingBatteryPercentage | number | V    | `85`            |                                              |
| analogueData:\<analogueNumber>          | number |      | `1234`          | Unknown analogue data reported by the device |

Example:

```json
[
    ...
    {
        "n": "analogueData:logReason",
        "vs": "Bluetooth Tag Data (update found lost reason covered in tag data)"
    },
    { "n": "analogueData:internalBatteryVoltage", "u": "V", "v": 4.328 },
    { "n": "analogueData:internalTemperature", "u": "Cel", "v": 24 },
    { "n": "analogueData:gsmSignalStrength", "u": "dBW", "v": -10 },
    { "n": "analogueData:loadedBatteryVoltage", "u": "V", "v": 4.308 },
    ...
]
```

#### WiFi Location Scan (wifiscan:)

| name                                  | type   | unit | example         | description                                |
| ------------------------------------- | ------ | ---- | --------------- | ------------------------------------------ |
| wifiscan:logReason                    | string |      | `Start of trip` | Indicates a reason for reporting this data |
| wifiscan:macs:\<index>:mac            | string |      | `001122334455`  | The mac address of the Wifi Access Point   |
| wifiscan:macs:\<index>:signalStrength | number | dBW  | `-80`           | The measured signal strength               |
| wifiscan:macs:\<index>:channel        | string |      | `1`             | The Wifi channel                           |

Example:

```json
[
    ...
    { "n": "wifiscan:logReason", "vs": "Heartbeat" },
    { "n": "wifiscan:0:mac", "vs": "11aabb334455" },
    { "n": "wifiscan:0:signalStrenth", "u": "dBW", "v": -106 },
    { "n": "wifiscan:0:channel", "vs": "1" },
    ...
]
```

#### Cell Tower Scan (celltowerscan:)

Some Digital Matter devices are capable of scanning for nearby cell towers. This data can be combined with other information to approximate the current location of the device. When the device provides a cell tower scan report, the decoder will generate SenML records similar to the following:

| name                                     | type   | unit | example         | description                                |
| ---------------------------------------- | ------ | ---- | --------------- | ------------------------------------------ |
| celltowerscan:logReason                  | string |      | `Start of trip` | Indicates a reason for reporting this data |
| celltowerscan:\<index>:cellId            | string |      | `123456789`     | Cell ID                                    |
| celltowerscan:\<index>:locationAreaCode  | string |      | `1234`          | Location Area Code                         |
| celltowerscan:\<index>:mobileCountryCode | string |      | `204`           | Mobile Country Code (MCC)                  |
| celltowerscan:\<index>:mobileNetworkCode | string |      | `69`            | Mobile Network Code (MNC)                  |

Example:

```json
[
    ...
    { "n": "celltowerscan:logReason", "vs": "Start of trip" },
    { "n": "celltowerscan:1:cellId", "vs": "123456789" },
    { "n": "celltowerscan:1:locationAreaCode", "vs": "52224" },
    { "n": "celltowerscan:1:mobileCountryCode", "vs": "999" },
    { "n": "celltowerscan:1:mobileNetworkCode", "vs": "999" },
    ...
]
```

#### Bluetooth Tag List (tag:)

There are many types of Bluetooth tags (vendors of tags), and depending on the tag type, records may or may not be present in the device messages. For the following tag types, all reported records are decoded:

* Apple iBeacon
* Eddystone
* EddystoneTLM
* Generic Tag
* Teltonika Eye Beacon / Sensor (reported as Teltonika Eye Beacon)
* Digital Matter beacon format (reported as Guppy)

This list may be extended in future versions of the decoder. For these tags, the following SenML records are forwarded:

| name                                 | type    | unit  | example              | tag-types                                       | description                                                            |
| ------------------------------------ | ------- | ----- | -------------------- | ----------------------------------------------- | ---------------------------------------------------------------------- |
| tag:logReason                        | string  |       | `Start of trip`      |                                                 | Indicates a reason for reporting this data                             |
| tag:\<index>:tagLogReason            | string  |       | `Tag Found`          |                                                 | Indicates a reason for reporting this tags data                        |
| tag:\<index>:type                    | string  |       | `Eddystone`          |                                                 | Type bluetooth tag                                                     |
| tag:\<index>:type:id                 | string  |       |                      | Generic Tag                                     | Type Id for Generic Tag                                                |
| tag:\<index>:data                    | string  |       |                      | Generic Tag                                     | Undecoded data bytes, if any                                           |
| tag:\<index>:rssi                    | number  | dBW   | `-45`                | All                                             |                                                                        |
| tag:\<index>:mac                     | string  |       | `665544332211`       | All                                             |                                                                        |
| tag:\<index>:txPower                 | number  | dBW   | `54`                 | iBeacon, Eddystone, Teltonika Eye Beacon, Guppy |                                                                        |
| tag:\<index>:uuid                    | string  |       |                      | iBeacon                                         |                                                                        |
| tag:\<index>:id:major                | string  |       |                      | iBeacon                                         |                                                                        |
| tag:\<index>:id:minor                | string  |       |                      | iBeacon                                         |                                                                        |
| tag:\<index>:namespaceId             | string  |       | `001122334455667899` | Eddystone,Teltonika Eye Beacon                  |                                                                        |
| tag:\<index>:instanceId              | string  |       | `889977665544`       | Eddystone,Teltonika Eye Beacon                  |                                                                        |
| tag:\<index>:batteryVoltage          | number  | V     |                      | EddystoneTLM,Teltonika Eye Beacon, Guppy        |                                                                        |
| tag:\<index>:temperature             | number  | Cel   |                      | EddystoneTLM,Teltonika Eye Beacon, Guppy        | In case of Teltonika only reported by the Teltonika Eye Sensor variant |
| tag:\<index>:advertisementFrameCount | number  | count |                      | EddystoneTLM                                    |                                                                        |
| tag:\<index>:timeSinceLastBoot       | number  | s     |                      | EddystoneTLM                                    |                                                                        |
| tag:\<index>:humidity                | number  | %RH   |                      | Teltonika Eye Beacon                            | Only reported by the Teltonika Eye Sensor variant                      |
| tag:\<index>:magneticFieldDetected   | boolean |       |                      | Teltonika Eye Beacon                            | Only reported by the Teltonika Eye Sensor variant                      |
| tag:\<index>:movementDetected        | boolean |       |                      | Teltonika Eye Beacon                            | Only reported by the Teltonika Eye Sensor variant                      |
| tag:\<index>:movementCounter         | number  | count |                      | Teltonika Eye Beacon                            | Only reported by the Teltonika Eye Sensor variant                      |
| tag:\<index>:devicePitch             | number  | rad   |                      | Teltonika Eye Beacon                            | Only reported by the Teltonika Eye Sensor variant                      |
| tag:\<index>:deviceRoll              | number  | rad   |                      | Teltonika Eye Beacon                            | Only reported by the Teltonika Eye Sensor variant                      |
| tag:\<index>:batteryLow              | boolean |       |                      | Teltonika Eye Beacon                            |                                                                        |
| tag:\<index>:serial                  | string  |       | `112233`             | Guppy                                           |                                                                        |
| tag:\<index>:gps:time                | number  |       |                      |                                                 | Not always reported by the device                                      |
| tag:\<index>:gps:latitude            | number  | lat   |                      |                                                 | Not always reported by the device                                      |
| tag:\<index>:gps:longitude           | number  | lon   |                      |                                                 | Not always reported by the device                                      |
| tag:\<index>:gps:accuracy:radius     | number  | m     |                      |                                                 | Not always reported by the device                                      |

Example:

```json
[
    ...
    {
        "n": "tag:logReason",
        "vs": "Bluetooth Tag Data (update found lost reason covered in tag data)"
    },
    { "n": "tag:0:tagLogReason", "vs": "Tag Found" },
    { "n": "tag:0:type", "vs": "Eddystone" },
    { "n": "tag:0:rssi", "u": "dBW", "v": -111 },
    { "n": "tag:0:mac", "vs": "11aabb334455" },
    { "n": "tag:0:txPower", "u": "dBW", "v": -60 },
    { "n": "tag:0:namespaceId", "vs": "020430eee2bbffaaadae" },
    { "n": "tag:0:instanceId", "vs": "771234567fff" },
    ...
]
```

For the other tag types, raw data is forwarded:

| name              | type   | unit | example            | description                                |
| ----------------- | ------ | ---- | ------------------ | ------------------------------------------ |
| tag:logReason     | string |      | `Start of trip`    | Indicates a reason for reporting this data |
| tag:\<index>:type | string |      | `Ingics iBS04 Tag` | Type bluetooth tag                         |
| tag:\<index>:data | string |      |                    | Undecoded data bytes, if any               |

Example:

```json
[
    ...
    {
        "n": "tag:logReason",
        "vs": "Bluetooth Tag Data (update found lost reason covered in tag data)"
    },
    { "n": "tag:0:type", "vs": "Ingics iBS04 Tag" },
    { "n": "tag:0:data", "vs": "010325232" },
    ...
]
```

#### GNSS Location Scan (GNSSLocationScan:)

| name                       | type   | unit | example         | description                                   |
| -------------------------- | ------ | ---- | --------------- | --------------------------------------------- |
| GNSSLocationScan:logReason | string |      | `Start of trip` | Indicates a reason for reporting this data    |
| GNSSLocationScan:data      | string |      | `01020304`      | Undecoded data bytes, if any. Else: 'No data' |

Example:

```json
[
    ...
    { "n": "GNSSLocationScan:logReason", "vs": "Heartbeat" },
    { "n": "GNSSLocationScan:data", "vs": "No data" },
    ...
]
```

#### Detailed Cell Tower Scan (detailedCellTowerScan:)

| name                                            | type   | unit  | example              | description                                |
| ----------------------------------------------- | ------ | ----- | -------------------- | ------------------------------------------ |
| detailedCellTowerScan:logReason                 | string |       | `Start of trip`      | Indicates a reason for reporting this data |
| detailedCellTowerScan:cellTowerType             | string |       | `CAT-M1 cell towers` |                                            |
| detailedCellTowerScan:cellId                    | string |       | `10517016`           |                                            |
| detailedCellTowerScan:locationAreaCode          | string |       | `3190`               |                                            |
| detailedCellTowerScan:mobileCountryCode         | string |       | `204`                |                                            |
| detailedCellTowerScan:mobileNetworkCode         | string |       | `8`                  |                                            |
| detailedCellTowerScan:timingAdvanceTs           | number | count | `123`                |                                            |
| detailedCellTowerScan:\<index>:downlinkEARFCN   | string |       | `1575`               |                                            |
| detailedCellTowerScan:\<index>:physicalCellID   | string |       | `513`                |                                            |
| detailedCellTowerScan:\<index>:rsrp             | number | dBW   | `153`                | Received Signal Reference Power            |
| detailedCellTowerScan:\<index>:rsrq             | number | dBW   | `-39`                | Received Signal Reference Quality          |
| detailedCellTowerScan:\<index>:timingDifference | number | ms    | `54`                 |                                            |

Example:

```json
[
    ...
    { "n": "detailedCellTowerScan:logReason", "vs": "Heartbeat" },
    {
        "n": "detailedCellTowerScan:cellTowerType",
        "vs": "CAT-M1 cell towers"
    },
    { "n": "detailedCellTowerScan:cellId", "vs": "20134693" },
    { "n": "detailedCellTowerScan:locationAreaCode", "vs": "31903" },
    { "n": "detailedCellTowerScan:mobileCountryCode", "vs": "204" },
    { "n": "detailedCellTowerScan:mobileNetworkCode", "vs": "8" },
    { "n": "detailedCellTowerScan:timingAdvanceTs", "u": "count", "v": 0 },
    { "n": "detailedCellTowerScan:0:downlinkEARFCN", "vs": "1300" },
    { "n": "detailedCellTowerScan:0:physicalCellID", "vs": "197" },
    { "n": "detailedCellTowerScan:0:rsrp", "u": "dBW", "v": -106 },
    { "n": "detailedCellTowerScan:0:rsrq", "u": "dBW", "v": -37 },
    { "n": "detailedCellTowerScan:0:timingDifference", "u": "ms", "v": 0 },
    ...
]
```

#### WiFi resolving

For devices that report WiFi access points, KPN Things automatically determines the corresponding geographic location. The resulting location information is then added to the SenML record. If the device is configured to fall back to cell-tower data, KPN Things will also attempt to resolve this information to a location whenever possible. In some cases, the provided data cannot be translated into a reliable position. When this occurs, the location resolution process fails, which can be identified by checking the returned status code.

| name                         | type   | unit | example | description                                                                                                                                                                                                                                                                                                                                       |
| ---------------------------- | ------ | ---- | ------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| extLocationResolveStatusCode | string |      | 200     | <p>Status code of the location resolving service.</p><p>-1 - Resolving service unavailable or insufficient input data<br>200 - OK<br>400/404 - Could not resolve location based on the input measurements<br>401/403/405/413/414/415/429 - Failed to resolve location, internal error<br>500/503 - Failed to resolve location, internal error</p> |
| latitude                     | number | lat  |         | Latitude as resolved                                                                                                                                                                                                                                                                                                                              |
| longitude                    | number | lon  |         | Longitude as resolved                                                                                                                                                                                                                                                                                                                             |
| radius                       | number | m    |         | Expected accuracy of resolved location                                                                                                                                                                                                                                                                                                            |
| locOrigin                    | string |      | `WIFI`  | <p><code>WIFI</code> if only based on wlan information<br><code>CELLTOWER</code> if no wlan information is present and the location could be resolved based on celltower<br><code>WIFI+CELLTOWER</code> if a combination is used</p>                                                                                                              |

Example:

```json
[
    ...
  {
    "bn": "urn:dev:IMEI:353760970612345:",
    "n": "extLocationResolveStatusCode",
    "vs": "200"
  } 
  {
    "n": "latitude",
    "u": "lat",
    "v": 51.00000000
  },
  {
    "n": "longitude",
    "u": "lon",
    "v": 4.00000000
  },
  {
    "n": "radius",
    "u": "m",
    "v": 48
  },
  {
    "n": "locOrigin",
    "vs": "WIFI"
  },
    ...
]
```

#### Other undecoded data

For some fields, decoder logic has not yet been implemented but can be added in future versions. The data is forwarded as an undecoded hex string, allowing for customer-side decoding. This applies to the following fields:

* driverOperatorID
* sdi12DeviceIdentification
* sdi12Measurement
* int32AnalogueData
* blobNotification
* device3rdPartyAsyncMessage
* projectCode
* tripTypeCode
* consoleData
* rfTagData
* rfTagLost
* deviceTripTypeAndData
* garminFmiStopResponse
* accidentData
* accelerometerTraceHeader
* accelerometerTraceSamples
* v5RFMessage
* handHeldRadioGpsData
* highGEvent
* tripDistanceTripDuration
* deviceOdometerRunHours
* imageData
* sdi12Measurement2
* swarmGpsData
* multiCellTowerScan
* accelerometerSampleData
* fieldId:\<fieldId> (unrecognized field)

| name                   | type    | unit | example         | description                                       |
| ---------------------- | ------- | ---- | --------------- | ------------------------------------------------- |
| \<fieldName>:logReason | string  |      | `Start of trip` | Indicates a reason for reporting this data        |
| \<fieldName>:decoded   | boolean |      | `false`         | Flag to indicate the data has been decoded or not |
| \<fieldName>:data      | string  |      | `01020304`      | Undecoded data bytes                              |

Example output for an undecoded field (specific devices only):

```json
[
    ...
    { "n": "multiCellTowerScan:logReason", "vs": "Heartbeat" },
    { "n": "multiCellTowerScan:decoded", "vb": false },
    { "n": "multiCellTowerScan:data", "vs": "01020304" },
    ...
]
```
