senml — Sensor Markup Language#

This module implements a small encoder/decoder for the Sensor Markup Language (SenML, RFC 8428). SenML is a media-type for sensor measurements and device parameters: each “pack” is a list of “records”, where every record carries a name, unit, value, timestamp, and optional sum.

The implementation supports both the JSON and CBOR representations and allows packs to be nested so that a single root pack can describe a gateway fronting multiple devices. Inbound payloads can drive actuator callbacks on existing records.

Example usage:

from senml import SenmlPack, SenmlRecord, SenmlUnits

# A pack collects readings for one device, identified by URN.
pack = SenmlPack("urn:dev:mac:0024befffe804ff1")

# Add a temperature reading in degrees Celsius.
pack.add(SenmlRecord(
    "temperature",
    unit=SenmlUnits.SENML_UNIT_DEGREES_CELSIUS,
    value=23.4,
))

# Add a humidity reading in %RH.
pack.add(SenmlRecord(
    "humidity",
    unit=SenmlUnits.SENML_UNIT_RELATIVE_HUMIDITY,
    value=51.2,
))

# Render the pack as a SenML/JSON document.
print(pack.to_json())

Classes#

class senml.SenmlPack(name: str, callback=None)#

Represents a SenML pack – a collection of SenmlRecord instances and optionally other child SenmlPack objects. When a pack only contains records it represents a single device; when it contains other packs it acts as a gateway.

name is the SenML base name (bn) used for every record contained in this pack.

callback is invoked from from_json / from_cbor whenever an inbound record names a previously-unknown sensor; the new SenmlRecord is passed as the first argument and (for nested packs) the originating device pack is passed as device=.... It is typically used to handle actuator commands.

SenmlPack instances are iterable – iteration yields each record in insertion order – and may be used as a context manager so that on exit the pack removes itself from its parent.

name: str#

The pack’s base name (bn).

base_value: int | float | None#

Optional base value (bv) added to each record’s numeric value when encoding and subtracted on decoding. Setting a non-numeric value raises Exception.

base_time: int | float | None#

Optional base time (bt) added to each record’s timestamp.

base_sum: int | float | None#

Optional base sum (bs) added to each record’s sum field.

base_unit: str | None#

Optional base unit (bu) – typically a value from SenmlUnits.

actuate#

The callback supplied at construction time. May be re-assigned at runtime.

add(item: SenmlRecord | SenmlPack) None#

Append item to this pack. item must be a SenmlRecord or another SenmlPack and must not already belong to a different parent; otherwise Exception is raised.

remove(item: SenmlRecord | SenmlPack) None#

Remove item from this pack. Exception is raised if item is not a child of this pack.

clear() None#

Remove every record/sub-pack from this pack and detach them from their parent reference.

from_json(data: str) None#

Parse a SenML/JSON document and merge the records into this pack. Records that already exist (matched by name) trigger SenmlRecord.do_actuate(); new records are appended and the pack-level callback is invoked.

to_json() str#

Render the pack and its children to a SenML/JSON string.

from_cbor(data: bytes) None#

Parse a SenML/CBOR byte string and merge the records into this pack.

to_cbor() bytes#

Render the pack and its children to a SenML/CBOR byte string.

do_actuate(raw: dict, naming_map: dict, device: SenmlPack | None = None) None#

Internal helper invoked while parsing inbound data when no existing record matches an entry. Adds a new SenmlRecord to device (or to this pack) and forwards it to the callback.

class senml.SenmlRecord(name: str, **kwargs)#

Represents a single measurement inside a SenmlPack.

name is the SenML record name (n).

The following keyword arguments are accepted:

  • valuebool, int, float, str or bytearray. Other types raise Exception.

  • time – numeric timestamp (t).

  • unit – a unit string, typically a member of SenmlUnits.

  • sum – numeric integrated sum (s).

  • update_time – maximum time before the sensor will provide a fresh reading (ut).

  • callback – function invoked when an inbound payload updates this record. It receives the SenmlRecord as its only argument.

SenmlRecord may be used as a context manager so that on exit it removes itself from its parent pack.

name: str#

Record name (n).

value#

The current value. Re-assigning checks the type; only bool, numbers, str and bytearray are accepted. To control the rendered precision of a float value, round before assignment, e.g. record.value = round(x, 2).

unit: str | None#

Unit string (u).

time: int | float | None#

Timestamp associated with this measurement (t).

update_time: int | float | None#

Maximum time before the sensor will provide an updated reading (ut).

sum: int | float | None#

Integrated sum field (s).

actuate#

The callback supplied at construction time. May be re-assigned at runtime.

do_actuate(raw: dict, naming_map: dict) None#

Update this record from a raw inbound SenML dictionary and, if present, invoke the actuate callback.

class senml.SenmlBase#

Common base class shared by SenmlPack and SenmlRecord. It exposes no public API of its own; it exists so SenmlPack.add() can validate that an item belongs to the SenML hierarchy.

class senml.SenmlUnits#

Namespace class whose class attributes are the SenML unit symbols defined by RFC 8428. Each attribute resolves to the unit’s string code, suitable for assignment to SenmlRecord.unit or SenmlPack.base_unit.

SENML_UNIT_METER: str#

"m" – metre.

SENML_UNIT_KILOGRAM: str#

"kg" – kilogram.

SENML_UNIT_GRAM: str#

"g" – gram.

SENML_UNIT_SECOND: str#

"s" – second.

SENML_UNIT_AMPERE: str#

"A" – ampere.

SENML_UNIT_KELVIN: str#

"K" – kelvin.

SENML_UNIT_CANDELA: str#

"cd" – candela.

SENML_UNIT_MOLE: str#

"mol" – mole.

SENML_UNIT_HERTZ: str#

"Hz" – hertz.

SENML_UNIT_RADIAN: str#

"rad" – radian.

SENML_UNIT_STERADIAN: str#

"sr" – steradian.

SENML_UNIT_NEWTON: str#

"N" – newton.

SENML_UNIT_PASCAL: str#

"Pa" – pascal.

SENML_UNIT_JOULE: str#

"J" – joule.

SENML_UNIT_WATT: str#

"W" – watt.

SENML_UNIT_COULOMB: str#

"C" – coulomb.

SENML_UNIT_VOLT: str#

"V" – volt.

SENML_UNIT_FARAD: str#

"F" – farad.

SENML_UNIT_OHM: str#

"Ohm" – ohm.

SENML_UNIT_SIEMENS: str#

"S" – siemens.

SENML_UNIT_WEBER: str#

"Wb" – weber.

SENML_UNIT_TESLA: str#

"T" – tesla.

SENML_UNIT_HENRY: str#

"H" – henry.

SENML_UNIT_DEGREES_CELSIUS: str#

"Cel" – degrees Celsius.

SENML_UNIT_LUMEN: str#

"lm" – lumen.

SENML_UNIT_LUX: str#

"lx" – lux.

SENML_UNIT_BECQUEREL: str#

"Bq" – becquerel.

SENML_UNIT_GRAY: str#

"Gy" – gray.

SENML_UNIT_SIEVERT: str#

"Sv" – sievert.

SENML_UNIT_KATAL: str#

"kat" – katal.

SENML_UNIT_SQUARE_METER: str#

"m2" – square metre.

SENML_UNIT_CUBIC_METER: str#

"m3" – cubic metre.

SENML_UNIT_LITER: str#

"l" – litre.

SENML_UNIT_VELOCITY: str#

"m/s" – velocity.

SENML_UNIT_ACCELERATION: str#

"m/s2" – acceleration.

SENML_UNIT_CUBIC_METER_PER_SECOND: str#

"m3/s" – volumetric flow rate.

SENML_UNIT_LITER_PER_SECOND: str#

"l/s" – litre per second.

SENML_UNIT_WATT_PER_SQUARE_METER: str#

"W/m2" – irradiance.

SENML_UNIT_CANDELA_PER_SQUARE_METER: str#

"cd/m2" – luminance.

SENML_UNIT_BIT: str#

"bit" – bit.

SENML_UNIT_BIT_PER_SECOND: str#

"bit/s" – bit per second.

SENML_UNIT_DEGREES_LATITUDE: str#

"lat" – degrees latitude.

SENML_UNIT_DEGREES_LONGITUDE: str#

"lon" – degrees longitude.

SENML_UNIT_PH: str#

"pH" – acidity (pH).

SENML_UNIT_DECIBEL: str#

"db" – decibel.

SENML_UNIT_DECIBEL_RELATIVE_TO_1_W: str#

"dBW" – decibel relative to 1 W.

SENML_UNIT_BEL: str#

"Bspl" – bel (sound pressure level).

SENML_UNIT_COUNTER: str#

"count" – counter.

SENML_UNIT_RATIO: str#

"//" – ratio (dimensionless).

SENML_UNIT_RELATIVE_HUMIDITY: str#

"%RH" – relative humidity.

SENML_UNIT_PERCENTAGE_REMAINING_BATTERY_LEVEL: str#

"%EL" – remaining battery level as a percentage.

SENML_UNIT_SECONDS_REMAINING_BATTERY_LEVEL: str#

"EL" – remaining battery level in seconds.

SENML_UNIT_EVENT_RATE_PER_SECOND: str#

"1/s" – event rate per second.

SENML_UNIT_EVENT_RATE_PER_MINUTE: str#

"1/min" – event rate per minute.

SENML_UNIT_BPM: str#

"beat/min" – beats per minute.

SENML_UNIT_BEATS: str#

"beats" – beats.

SENML_UNIT_SIEMENS_PER_METER: str#

"S/m" – siemens per metre (electrical conductivity).