# SenML

{% hint style="warning" %}
For Freemium projects, the way KPN Things processes device data to SenML changed (per December 13th 2022). Read all the details about the [Changes in KPN SenML](https://docs.kpnthings.com/kpn-things/building-blocks/data-processing/thingsml-and-senml/senml/changes-in-kpn-senml).
{% endhint %}

SenML is the default data format for device data in KPN Things. Currently KPN Things only supports SenML in JSON. We plan to support SenML in CBOR in the future.

## Introduction

A SenML message is officially called a SenML pack. One SenML pack consists of one or more SenML records. One SenML record expresses a single measurement. That way a SenML pack expresses a set of measurements

The first record in a SenML pack always contains base information. Base information expresses from which device the measurements are from (base name) and the moment the measurements were taken (base time).&#x20;

There are different type of SenML records:

* **Number record** - for communicating a number measurement
* **Boolean record** - for communicating an on/off measurement
* **String record** - for communicating a string measurement
* **Data record** - for communicating raw data measurement

Below you find a non-exhaustive example of a SenML pack:

{% code title="SenML example (explanation below)" %}

```javascript
[
  {"bn": "urn:dev:DEVEUI:0123456789ABCDEF:", "bt": 1.58565075E9, 
   "n": "temperature", "v": 20.5, "u": "Cel"},
  {"n": "batteryVoltage", "v": 3.6, "u": "V", "t": 10},
  {"n": "active", "vb": true},
  {"n": "modus", "vs": "Active"},
  {"n": "image", "vd": "aGFsbG9vb29vISE="}
]
```

{% endcode %}

| Line nr. | Explanation                                                                |
| -------- | -------------------------------------------------------------------------- |
| 2        | First line with base attributes, stating measurement source and timestamp. |
| 3        | Number record                                                              |
| 4        | Number record with relative time                                           |
| 5        | Boolean record                                                             |
| 6        | String record                                                              |
| 7        | Data record                                                                |

## Attributes

This section explains the attributes you can use to express your measurements in SenML

### Base values

When the [base name](#base-name-bn-required-in-pack) and/or [base time](#base-time-bt-optional-in-pack) values are present in the pack, they are available in the first measurement of the pack and applicable for all the measurements in the pack.

### Base name - bn - required in pack

The base name of a SenML pack states which device the measurements are from. It should contain a [unique resource name](https://en.wikipedia.org/wiki/Uniform_Resource_Name). The parts of the base name, which are colon separated, are as following:

* `urn` stands for *unique resource name*.
* `dev` means we are identifying a device.
* `DEVEUI` is the type of device identifier used to identify the device.
* `01234567890ABCDEF` is the DevEUI, the device identifier.

In the example above we identify a LoRa device by its DEVEUI. If we would have an M2M device, we would identify it by its IMEI and the base name would be as following: `urn:dev:IMEI:0123456789012345:`.

{% hint style="warning" %}
A base name always ends with a colon `:`!
{% endhint %}

### Base time - bt - optional in pack

The timestamp of the measurement in [UNIX timestamp](https://www.unixtimestamp.com/) format. If KPN Things receives a measurement without base time, the time of receiving the measurement is taken as base time. SenML being sent by KPN Things will always contain a base time.

### Name - n - required in record

Name of the individual measurement.

> &#x20;The> &#x20;(..) name MUST consist only of characters out of the set "A"> &#x20;to "Z", "a" to "z", and "0" to "9", as well as "-", ":", ".", "/",> &#x20;and "\_"; furthermore, it MUST start with a character out of the set> &#x20;"A" to "Z", "a" to "z", or "0" to "9".\
> \- The SenML spec, [RFC8428 section 4.5.1](https://tools.ietf.org/html/rfc8428#section-4.5.1)

{% hint style="warning" %}
When designing your SenML measurement format for M2M and Internet devices, you should take into account our [Common measurements list](https://docs.kpnthings.com/kpn-things/building-blocks/data-processing/decoders-and-encoders/common-measurements-list). By using as much name and unit pairs from that list, you achieve higher compatibility with current and future data processing features.
{% endhint %}

### Unit - u - optional in record

Unit of the measurement. Write your `u`-values in camel case, so start with a lower case character.

### Time - t - optional in record

The timestamp of an individual record relative to the base time in seconds.

{% hint style="info" %}

#### Example

You have a SenML pack with `"bt": 1600185600` (*2020-09-15T16:00:00+00:00*) and the pack contains a measurement with `"t": -60`.

The timestamp of that measurement is then *2020-09-15T15:59:00+00:00*, so one minute earlier then the base time.
{% endhint %}

### Number value - v - required in number record

Value of the number measurement.

### Boolean value - vb - required in boolean record

Boolean value for a boolean measurement. Should be `true` or `false`.

### String value - vs - required in string record

String value for a string measurement.&#x20;

### Data value - vd - required in data record

Data value for a data measurement. Should be a [base64 ](https://en.wikipedia.org/wiki/Base64)encoded string.

### And more...

There are more attributes in the SenML specification, but these values are not used by KPN Things. You can read about them in the Sensor Measurements Lists specification:

{% embed url="<https://tools.ietf.org/html/rfc8428>" %}
RFC 8428 - Sensor Measurement Lists (SenML)
{% endembed %}

## Client libraries

For easier integration with KPN Things we have created client libraries in C and Python for you to use in your devices.

{% embed url="<https://kpn-iot.github.io/senml-library/?c--arduino>" %}
Client libraries for SenML in JSON and CBOR format
{% endembed %}

## ThingsML, a SenML extension with extra compression

To make SenML more suitable for communication over LoRa, we have introduced [ThingsML](https://docs.kpnthings.com/kpn-things/building-blocks/data-processing/thingsml-and-senml/thingsml). ThingsML is a valid extension of SenML that introduces measurement indices. We have [listed several common measurements](https://docs.kpnthings.com/kpn-things/building-blocks/data-processing/decoders-and-encoders/common-measurements-list), allowing you to only send the measurement index number instead of sending the complete name and unit of the measurement. [Learn more about ThingsML](https://docs.kpnthings.com/kpn-things/building-blocks/data-processing/thingsml-and-senml/thingsml).
