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.
CBOR encoding/decoding requires the cbor2 package.
Classes
- class senml.SenmlPack(name: str, callback=None)
Represents a SenML pack – a collection of
SenmlRecordinstances and optionally other childSenmlPackobjects. 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_cborwhenever an inbound record names a previously-unknown sensor; the newSenmlRecordis passed as the first argument and (for nested packs) the originating device pack is passed asdevice=.... It is typically used to handle actuator commands.SenmlPackinstances 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.- 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 raisesException.
- base_unit: str | None
Optional base unit (
bu) – typically a value fromSenmlUnits.
- 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
SenmlRecordor anotherSenmlPackand must not already belong to a different parent; otherwiseExceptionis raised.
- remove(item: SenmlRecord | SenmlPack) None
Remove item from this pack.
Exceptionis 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.
- 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:
value –
bool,int,float,strorbytearray. Other types raiseException.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
SenmlRecordas its only argument.
SenmlRecordmay be used as a context manager so that on exit it removes itself from its parent pack.- value
The current value. Re-assigning checks the type; only
bool, numbers,strandbytearrayare accepted. To control the rendered precision of a float value, round before assignment, e.g.record.value = round(x, 2).
- update_time: int | float | None
Maximum time before the sensor will provide an updated reading (
ut).
- actuate
The callback supplied at construction time. May be re-assigned at runtime.
- class senml.SenmlBase
Common base class shared by
SenmlPackandSenmlRecord. It exposes no public API of its own; it exists soSenmlPack.add()can validate that an item belongs to the SenML hierarchy.
- class senml.SenmlUnits
Enumeration object whose attributes are the SenML unit symbols defined by RFC 8428. Each attribute resolves to the unit’s string code, suitable for assignment to
SenmlRecord.unitorSenmlPack.base_unit.Examples of available unit attributes:
SENML_UNIT_METER->"m"SENML_UNIT_KILOGRAM->"kg"SENML_UNIT_SECOND->"s"SENML_UNIT_AMPERE->"A"SENML_UNIT_KELVIN->"K"SENML_UNIT_DEGREES_CELSIUS->"Cel"SENML_UNIT_HERTZ->"Hz"SENML_UNIT_VOLT->"V"SENML_UNIT_WATT->"W"SENML_UNIT_PASCAL->"Pa"SENML_UNIT_LUX->"lx"SENML_UNIT_RELATIVE_HUMIDITY->"%RH"SENML_UNIT_VELOCITY->"m/s"SENML_UNIT_ACCELERATION->"m/s2"SENML_UNIT_DEGREES_LATITUDE->"lat"SENML_UNIT_DEGREES_LONGITUDE->"lon"SENML_UNIT_BIT_PER_SECOND->"bit/s"SENML_UNIT_COUNTER->"count"SENML_UNIT_RATIO->"//"SENML_UNIT_BPM->"beat/min"
See the SenML unit registry in RFC 8428 Section 12.1 for the complete list.
Examples
from senml import SenmlPack, SenmlRecord, SenmlUnits
pack = SenmlPack("urn:dev:mac:0024befffe804ff1")
temp = SenmlRecord("temperature", unit=SenmlUnits.SENML_UNIT_DEGREES_CELSIUS, value=23.4)
hum = SenmlRecord("humidity", unit=SenmlUnits.SENML_UNIT_RELATIVE_HUMIDITY, value=51.2)
pack.add(temp)
pack.add(hum)
print(pack.to_json())