Master branch | Develop branch |
---|---|
This repo contains a set of libraries to manipulate sensor Objects.
An sensor Object contains the following conceptual fields:
M
: MAC address of the device creating the ObjectT
: timestamp of when the Object was createdt
: type of Object, a numberL
: the length of the valueV
: Object value, a opaque string of bytes
We refer to this format as the MTtlv format. It is a generalization of the well-known "Type-Length-Value" (TLV) format.
Download source:
git clone https://github.com/realms-team/sol.git
http://realms-sol.readthedocs.io
See registry.
The SOL Objects are manipulated in groups. Each group of Objects can be represented in binary, JSON or HTTP format.
This representation is used for:
- sending data in packets
- writing data to a file
Each group of Objects consists of the following fields:
| SOL header | Objects list |
Some rules:
- all multi-byte value are encoded "big endian" (a.k.a "network order")
- when saving Objects in a binary file, each Object MUST be framed using HDLC.
0 1 2 3 4 5 6 7
+-+-+-+-+-+-+-+-+
| V |T|M|S|Y| L |
+-+-+-+-+-+-+-+-+
V
: Version of the Object:- Only value
b00
is defined in this document. Other values for the 2 first bits are reserved and may be defined in later revisions of this document.
- Only value
T
: Type of MTtlv Object:0
: single-MTtlv Object1
: multi-MTtlv Object (MTNtlv) this implies the 1st byte next to timestamp is N: number of Objects
M
: MAC address encoding:0
: no MAC address present1
: 8-byte MAC address present
S
: timestamp encoding0
: timestamp is a 4-byte Linux epoch in UTC (1-second granularity)1
: timestamp is elided, and recovered from the timestamp field present in the SmartMesh IP header
Y
: type encoding0
: 1-byte type field1
: 2-byte type field
L
: length encodingb00
: use well-known value. No length field presentb01
: 1-byte length field presentb10
: 2-byte length field presentb11
: elided. The length is recovered from the length of the packet or HDLC frame.
According to the header flags, the Object list structure can vary.
- If the T flag is
0
then the message will have the following structure:
|| SOL Header || MT | tlv |
- If the T flag is
1
then the message will have the following structure:
|| SOL Header || MT | N | tlv | tlv | ...
Example 1. transmitting a single 2-byte temperature sensor reading, taken in the past:
[1B]
SOL HeaderV
=00
(version 0)T
=0
(Type of MTtlv Object)M
=0
(no MAC address)S
=0
(epoch)Y
=0
(1-byte type)L
=b00
(well-known value, no length field)
[--]
MAC: elided[4B]
Timestamp:0x........
[1B]
type=b..
(temperature)[--]
length: elided[2B]
value:0x....
Total 8 bytes.
Example 2. transmitting a single 2-byte temperature sensor reading, taken just now:
[1B]
SOL HeaderV
=00
(version 0)T
=0
(Type of MTtlv Object)M
=0
(no MAC address)S
=1
(elided)Y
=0
(1-byte type)L
=b00
(well-known value, no length field)
[3B]
sensor reading 1[--]
MAC: elided[--]
Timestamp: elided[1B]
type=b..
(temperature)[--]
length: elided[2B]
value:0x....
Total: 4 bytes.
Example 3. Transmitting 3 sensor readings from 3 different sensors with well-known length, taken at the same time in the past:
[1B]
SOL HeaderV
=00
(version 0)T
=1
(Type of MTtlv Object)M
=0
(no MAC address)S
=0
(epoch)Y
=0
(1-byte type)L
=b00
(well-known value, no length field)
[--]
MAC: elided[4B]
Timestamp:0x........
[1B]
Number of Objects = 3[3B]
sensor reading 1[--]
MAC: elided[--]
Timestamp: elided[1B]
type=b..
(temperature)[--]
length: elided[2B]
value:0x....
[3B]
sensor reading 2[--]
MAC: elided[--]
Timestamp: elided[1B]
type=b..
(RH)[--]
length: elided[2B]
value:0x....
[3B]
sensor reading 3[--]
MAC: elided[--]
Timestamp: elided[1B]
type=b..
(solar)[--]
length: elided[2B]
value:0x....
Total: 15 bytes.
The assumption is that a binary file is stored on some hard/flash drive with orders of magnitude more space than a packet. The driving design choice are hence made to allow:
- simple parsing
- recoverable file in case parts of it get corrupted.
The following rules hence apply when saving to a binary file:
- sensor Object chaining is NOT allowed (except on Neomote SD card level)
- each sensor Object MUST be framed using HDLC framing (RFC1662)
- the length field MUST be elided, and the
L
bit in the start header set tob11
A JSON representation is used:
- when the Objects are stored in a database
- when manipulating Objects
We use clean indentation for easier readability in these examples. An efficient implementation SHOULD represent the entire JSON string on a single line.
The following is the general format of a JSON representation of sensor Objects:
{
"mac": "00-17-0d-00-00-12-34-56",
"timestamp": 12345678890,
"type": 39,
"value": {
'temperature': 0x0a33,
},
}
- "mac"
- represented exactly like in the example above, lowercase hex bytes (exactly 2 characters per byte), separated by
-
.
- represented exactly like in the example above, lowercase hex bytes (exactly 2 characters per byte), separated by
- "timestamp"
- an integer representing the epoch
- "type"
- an integer, per the registry above
- "value"
- a dictionary of values
This representation is used for minimal communication overhead (when data transists).
{
"v": 0,
"o": [
ew0KICAgIm1hYyI6ICAg,
ICAgICIwMC0xNy0wZC0w,
...
1NiIsDQogICAidGltZXw,
]
}
v
: the version of the representation. Only version0
is defined in this specification. Other values SHOULD NOT be used. Future revisions of this document MIGHT define further versions.o
: an array of representations. Each representation is a string representing the binary representation of one or more sensor Objects.- the string MUST be a Base64 encoding of the binary representation of exactly one sensor Objects.