Message Layer (7Fh)
OSI: Session and Presentation Layers
Keywords: structured data presentation, data entry, host side processing, heterogeneous devices, profile-less, dynamic content, interoperability, rapid development, self-binding, very low communication overhead, sensors, internet of things, embedded systems, sensor networks
Scope
The scope of this document is to define the Isotropic Sensor Network Protocol Message Layer for broadcast and peer to peer connections in a distributed sensor area network, wired or wireless, low and high data rate devices, battery powered devices, short-range devices with short operational space, low-cost devices to support trivial sensors, besides the fully featured devices and rapid development of embedded hardware. The Message layer defines simple but powerful communication protocol for compact implementation designed to meet requirements of the next generation distributed Internet of Things (IoT) devices.
Purpose
The purpose of this specifications is to provide a standard for low complexity, low cost, and low power (aware) consumption devices (sensors).
Key features
Rapid Sensor Development
Rich Data Structures with very Low Transmission Overhead
Self Describing (Dynamic Content) Human Readable Output
Direct Mapping to rich Web JSON API
High Level Pre/Post-Processing (Math) Support
Advanced Value Presentation with Precision, Accuracy and Unit
Hand-Shaking for Transfer Reliability
Low-Cost and Compact Implementation
Overview
This document provides specifications of the Message Layer for use in information exchange between IoT devices themselves and devices and presentation sides. Applications cover sensors, sensor networks, development and debugging of embedded systems via simple UART interfaces to monitor and configure the application, in production environments used for testing, calibration and adjustments, and more. Whenever rapid development, low footprint implementation and dynamic message content is desired.
It provides a straight forward approach of data presentation, reduces CPU complexity and allows transfer of the measured values in their native format, without introducing rounding and other numerical errors. It represents a bi-directional communication where communication over-head and complexity is reduced to the minimum by:
splitting the description (the static part) from the arguments (the dynamic part) of the message, which need to be send only once, or on update.
description can also be loaded by presentation software, in which case, the device is only sending useful (arguments) data in its raw form,
contents is split among messages, where device can update multiple message at once,
and receive update in its natural format which means, that a math inverse is computed on the presentation, host side.
Definitions, Acronyms and Abbreviations
- arguments
device specific parameter in raw (typically native) form
- device
An entity containing this protocol implementation. Also referred as sensor device or just sensor or device.
- descriptor
holds a Sensor Message Layer typical format to describe a device and arguments
- frame
The format of aggregated bits that are transmitted together in time.
- identification descriptor, message
Zero-th message holds a so called global unique descriptor identifying one device only globally
- IoT
Internet of Things, and also as Isotel of Things
- host
typically referred to a presentation side of the information received from the sensor, and as user input to the sensor
- message
holding either descriptors or arguments
- packet
The format of aggregated bits that are transmitted together in time across the physical medium.
- LSB
least significant bit
- MSB
most significant bit
Packet Format
Frame Format
Fields |
Protocol ID |
Description Flag |
Message Number |
Message Body |
Bits |
8 |
1 |
7 |
length |
Value |
0x7F |
ARGS: 0, DESC: 1 |
MSGNUM: 0-127 |
Args or Description |
A 16-bit header is followed by an arbitrary length of payload, limited by encapsulating protocol. Header provides unique Protocol ID, followed by a Message Designation.
Message Designation is split into two parts:
Description Flag, which defines the content of the Message Body,
Message Number, with the first message starting from 0 ending at 127.
Based on Descriptor Flag, Message Body carries either:
ARGS: Raw Arguments,
DESC: Message Descriptor.
Arguments are specified by the Message descriptor, and when they’re send are encoded as described under section below Arguments Encoding.
The first message MSGNUM=0 is also called a Device Identification Descriptor. It must uniquely define a device by specifying product name, vendor, and version. Serial number and product specific numbers may be passed as arguments, however not the version or any other value that would mean a change in other message descriptors (MSGNUM>0) that would disallow unique and non-ambitious identification of a device. Based on this message hosts may cache the remaining message descriptors.
Hand-Shaking
Description Flag |
Message Body Length |
Command |
0 |
0 |
Request for Argument Update |
0 |
>0 |
Reply: Argument Update |
1 |
0 |
Request for Descriptor Update |
1 |
>0 |
Reply: Descriptor Update |
Hand-shaking is unidirectional with two requests for which only one possible reply exists, the content updates. Typically a device contains messages, transmits measurements and a host is a receiver, and user or machine input. However with the reverse direction hosts can serve as remote storage and can be asked by devices to serve input or stored data, configurations, passwords, etc.
Size of the message arguments and descriptors is limited by underlying layers as well as the number of concurrent requests.
Identifying and Setting up a Device
If a device receives an Argument Update for an unknown message then it sends back a Requests for Descriptor for the same message.
If a Descriptor Update is received but arguments are unknown then it sends back a Request for Argument Update for the same message.
For an unknown device, the first request issued is Request for Descriptor for Message Number, MSGNUM=0, to obtain Device Identification Descriptor and possibly re-use the cached content; if device is unknown to a host, then continues as follows:
Content is loaded by starting with the highest message number, sending Request for Descriptor with MSGNUM=0x7F Device replies by returning an Descriptor Update with the last possible message number.
Loading continues with last MSGNUM-1, MSGNUM-2, and stops at MSGNUM=1.
Information Directions and Acknowledging Changes
The message descriptor defines the I/O relations of some parameter, whether it is an output from a sensor only (Output only), can it be changed (I/O), or is it an input driven (Input Only) parameter.
These types define how an originator of a parameter, typically a device, manages and replies to a host.
Output Only Parameters
These cannot be changed, and a device receiving an update to a non-changeable parameter can be ignored without issuing a reply. However if network throughput permits a reply it is advisable that it resends the old value back to the host.
Host should disallow sending updates to such parameters to remove unwanted network traffic and loss of energy.
Input Only Parameters
These can be changed and are controlled by the host, however for this types of parameters host does not expect a reply. It is meant to enter information which does not need a reverse feedback, as password, streaming data to a speaker, etc.
Input and Output Parameters
These fall into the group of full acknowledgment cycle, which requires that a device replies with an updated value, in one of the following two methods:
same as input, or
not-same but different as before
to the host issuing a request. Which type of acknowledgment method is used is selected by the host input. It should follow the following specifications:
when user, or some machine requests to change a value by providing its exact value, or mnemonics, then the acknowledgment procedure selects method 1,
when input is prefixed by a ~ character, like “~1”, or “~Off”, then the 2nd method is selected.
Host must identify the correctness of the reply to give accurate report to a user or machine. It follows this procedure:
Sends Argument (Value Change) Request to a Device
Waits for a Message with the Desired Value Change:
If value received is OK (as per 1st or 2nd method), it reports Success.
otherwise it retries N times, before it reports an Error.
if no reply is received within a time frame, it retries N times, before it reports: Timeout
If device doesn’t send any kind of messages within some time period, device is declared as: Inactive
Device engaged in the above procedure should first serve requests, and then continue with the rest of the updates. This minimizes the number of retries in the network, and increases reaction time.
Device and hosts may send messages concurrently. It may happen that just after sending a request to change a value, a message with an argument update is received from the same device. Above procedure should handle such scenarios by sending a 2nd retry. If underlying protocol provides time synchronization then the message sequence becomes clear to remove redundant retries.
Message Descriptor Specification
Each of 128 available messages is described by a description. It is called a Message Descriptor and provides rich elements as structured text, parameters, data structures, simple expressions, rich math with cross-referencing between parameters, unit and accuracy specifiers, lists / enumerations, view modes and sections.
Text Elements
Typically interaction with a device is done on the variable - value pairs (parameters), however the text elements are used to provide basic descriptions of the device and help on parameters, in human understanding readable way for direct representation by a host.
General Rules
Text is sent as is to the output unless one of the following is used:
general escape character %… used to describe arguments and additional text elements,
expressions which start with { .. and end with }, immediately followed by optional unit […]
data structure that start with a name and followed by {, i.e. struct{ … }
Identifiers (Variable names, List elements, … ) should contain basic ASCII characters:
First character must be a letter or [“.”,”_”, “#”, “!”, “?”, “@”] character.
Other characters can also include digits and [“/”,”’”, “~”] characters.
For description elements using non-standard characters, element can be placed in quote using ` `
, example:
{:quote}={%hu?%<hu:` `,val0;val1;`$#%val`;`pm1V`}
Headings
%T0{…}: title segment, which should be present in the first message and only once per device or unit
%T1{…}: page
%T2{…}: section
%T3{…}: sub-section
Text Size
%t0{…}: size equal to title segment,
%t1{…}: size equal to heading level 1,
%t2{…}: size equal to heading level 2 and so forth
Advanced and Development Headings - Sections
Every heading can include an identifier to denote an advanced or a development section to control the device output level.
%Txa{…}: advanced section, x = 0,1,2… header level
%Txd{…}: development section, x = 0,1,2… header level
Inheritance from parent sections apply; for example, everything after %T2a{} header would fall under the advanced sections as long as another normal section as %T2{} or %T1{} is defined.
Line Breaking
New line can be requested by:
\n which denotes a new paragraph, as <p> …
\r denotes a new line, as <br> …
Spaces
A normal space generates a space at the output, but a space is also assumed at the end of each message, so a string from two messages will be shown as joined strings with a space in-between.
Tables
HTML Table View in either horizontal or vertical layout is supported by using \t identifier
Horizontal table form (headers on the left):
\t hdr1 {:row1[X]}... \r hdr2 {:row2[X]} ... } \r hdr3 {:row[X]} ... } \n
here t accounts for vertical table, so each vector is a simple row and n closes. Vectors convert to a simple <td> ..</td> very straight forward.
Vertical table form (headers on the top):
\t hdr1 {:col1[X]}... \t hdr2 {:col2[X]} ... } \t hdr3 {:col3[X]} ... } \n
where hdr is a normal string (%Tx are not allowed).
Hyperlinks
%tu{‘url’} adds an url link, clickable in html output
End-Of-Messages (EOM) indicator
%! (EOM) denotes end of device descriptions, for loading purposes. Shold be put at the end of last message
Other
%% is used to display %
Argument Specifiers
Argument specifiers define how raw arguments (ARGS) are represented in their native (binary) form, just as like in standard printf().
Argument specifier starts with a % followed by direction, length, and format.
Direction
%<.. denotes a read-only parameter that is send from a device and cannot be written
%>.. denotes a write-only parameter that can only be sent but not read (as pin/password codes)
%… denotes a read-write parameter that can be read and modified
Length
h: specifies short, an 8-bit byte
l: specifies long, a 32-bit word
L: specifies long long, a 64-bit word
Format
i: 16-bit signed integer
u: 16-bit unsigned integer
x: 16-bit hex
f: 32-bit floating point as per IEEE 754, lf stands for 64-bit, %hf for 16-bit half precision float (added in 1.2.0.3)
i,u,x,f: denote small endian
I,U,X,F: denote big endian format (capital letters)
Examples:
%u for 16-bit little endian format
%LU for 64-bit big endian format
%<Lx for 64-bit little endian read-only format printed in hex
Notes:
Floating point numbers support default %f which is 32-bit, long %lf 64-bit and half %hf 16-bit (added in 1.2.0.3)
Above specifiers are not limited to integers only but with the math expressions they represent also fixed-point arithmetic.
Omit the length specifier to preserve the default format’s length.
Variable Length
Maximum length for the above currently supported is 64 bit
Before version 1.2.0.1, variable length argument was supported only for %I and %i type arguments
From version 1.2.0.1 and up, variable length arguments are also supported for U,u,J,j,K,k,X,x types
Before version 1.2.0.1, variable length had to be byte sized len%8==0 (ie. %i16,%I24,%i40)
From version 1.2.0.6 and up, arbitrary variable length arguments are also supported (ie. %i5,%I27,%i55)
Non-Aligned arguments
Arbitrary length variables can cause for the argument field to shift and lose its byte alignment There are some rules regardning endianness handling in case of misaligned bit arguments:
Misaligned section is defined as part of argument field from the start of first non-byte aligned argument and until byte alignment is restored
When misaligned bit argument is detected, endianness is now calculated across entire misaligned section
For this reason in a given misaligned section, all arguments should have the same endianness, mixing little and big endian can produce invalid values
Example:
{:test1}={%x4}{:test2}={%x16}{:test3}={%x12}{:test4}={%x}
Here we have misaligned field of 4 bytes containing test1-3 parameters. test4 is again byte aligned. Argument field in this case is preprocessed/reordered:
[0, 1, 2, 3, 4,5] > [3, 2, 1, 0, 4, 5]
Parameters test1-3 are then processed as if they were big endian. test4 is still processed as before.
A convenient way to restore byte alignment is by adding padding bits described in next section
Argument padding
Variable length arguments support bit padding specifier, by using comma ‘,’ and padding bit length after argument length.
Padding is appended after the argument fields
Example:
%I5,3 5-bit argument, 3 bit padding
To prepend padding bits, zero length argument can be specified
Example
%I0,3 3-bit padding
Format with an additional Not-a-Number (NaN) state
The use of NaN has potential in sensors to denote that a measurement is yet invalid or state undefined. Unsigned and signed specifiers are provided:
j,J: same as signed integer i,I, but with -MAX (i.e. for %hj value of −128) value denoting the NaN value
k,K: same as unsigned integer u,U, but with 0 denoting NaN value
The NaN can be assigned any value, see Lists (Enumeration) below.
NaN value in idm output is shown as “—”
Arguments Encoding and Granularity Size
Integers:
8-bit, as a single byte.
16-bit, two bytes ordered either in little/big endian
32-bit, 4 bytes ordered either in little/big endian
Default granularity size is 8-bit. Some CPU’s have bus widths of 16-bit thus granularity size of one word. These different encoding can be enabled by putting a specifier in a description (usually in msg 0, before the arguments)
Specifiers:
%e for 16-bit mode
%E for 32-bit mode
String Arguments
Currently supported string argument type:
%c{length} - standard 8-bit ASCII character encoding
Example:
{:test1}={%c20}
length denotes maximum number of characters in string
0x00 byte is regarded as terminator denoting the end of string, bytes including and after terminator are excluded from output
Cross Referencing
%v:<msgnum>$<argnum>: where <msgnum> is message id=0,1,2.. and <argnum> is consecutive argument number 1,2,3.. in the message given by <msgnum>
%v:<parameter>: where <parameter> consists of <scope><parameter name>. Scope can be declared in following ways:
a full or partial data structure hierarchy path i.e. device.sensor.<parameter name>
number of dots ‘.’, representing the number of levels back in the hierarchy where parameter is searched, starting from the level where cross reference is located. i.e. .var will look for parameter var in current scope, while …var will also look two levels higher in the hierarchy
if scope is omitted, parameter is searched globally. The first parameter with the corresponding <parameter name> is returned
<parameter>: inside expressions, ‘%v:’ can be omitted. Other rules still apply
Expressions
Expressions represent math objects that are post-process after received by the host. When used in conjunction with variables (parameters) these also define the math-inverse process when changing their values.
General form is given by brackets:
{math:description}
where:
math elements include standard operators, arguments, and can directly reference other variables by their full name
description is an optional part describing the expression itself, and may provide accuracy, value descriptions (lists/enumeration), or as a set of conditions under which expression is valid or combination of above.
Math Operators and Functions
The following arithmetic/bitwise operators are supported (by descending precedence):
Operator |
Symbol |
Exponential |
** |
Multiplicative |
* / % |
Additive |
+ - |
Shift |
<< >> |
Bitwise AND |
& |
Bitwise XOR |
^ |
Bitwise OR |
| |
Supported are the following standard math functions: abs, acos, asin, atan, cbrt, cos, cosh, exp, expm1, log, log10, sin, sinh, sqrt, tan, tanh, round
Example:
{:tsqrt}={sqrt(%U+1)}
{:tsin}={sin(%U*0.001)}
{:tns}={sqrt(log10(%U))}
Math Resolution / Precision
Resolution is automatically determined by the least accurate argument within the expression, i.e. an 8-bit value by itself determines 3 digits, and the decimal point is derived from the equation itself. Resolution then determines the number of digits and decimals to be displayed.
Developers may align the device readings in such a way that output bytes, words, directly denote precision of some measurement.
For instance, the following:
{%hu>>2}
does not apply reduction in resolution or precision, but is simply adding fixed point bits to the output. Word must be properly aligned in the raw arguments after the i.e. A/D reading.
Confidence Interval - Accuracy
An optional argument, besides the precision, is accuracy, which determines the interval of confidence. It can be assigned besides the argument specifier or on the expression level in the description part.
Example, both giving final accuracy of +-0.3:
{%U+-3/10}
{%U/10:+-0.3}
the character +- can be replaced by the single character according to the ASCII extended ±
{%U±3/10}
{%U/10:±0.3}
Accuracy is computed among entire expression and all arguments to derive the final accuracy, displayed as: value ± error
Accuracy can also be a dynamic expression, in which case it need to be defined in parentheses to separate from main expression
{%i:+-(%hu*0.1)}
Lists (Enumeration)
The Math Description specifies how values are translated into lists.
{%hu:item0,item1,item2}
{%hi:A=-23,B=59,C=70}
where:
item0, item1 are assigned default values 0,1,2,..
if description for given value does not exists, a value is printed out.
The NaN keyword is reserved for integer Not a Number, so {%hu:NaN=0} is equal to {%hk}, see also the two predefined specifiers
Enumeration elements severity can be defined using !~_ characters at the start of element
_ info
~ warning
! error
Example:
{%hu:_Info,~Warning,!Error}
Enumeration Options with Masking
A device may expose several configurations, which may sometimes be present or not. Number of number of options can be limited in the following way:
{%hu?%<hu:val1;val2;val3;...}
{%hu?%<hu:val1=1,val2=3,val3=5;...}
; denotes binary counting for the next item, so Off gets 0 as before but as it is followed by ; it jumps to the next rounding value so 1, 2, 4, … so simply use ; to jump to next 2^n. The ; reduces manual assignments of numbers which can take lots of space.
, denotes explicitly given numeric values for enumeration elements
Data Structures
Data structure is declared as:
data{ ... }
where:
data{ can open the structure in any message, while } can close it in the same or any message after.
any degree of nesting is allowed.
Data structure limitations
if datastructure spans multiple descriptions, it should be defined at the end of previous descriptions and ended at the end of last containing description, so whole descriptions are contained in datastructure
Examples:
Invalid:
"{:var1}={%u}",
"struct{{:var2}={%u}",
"{:var2}={%u}} {:var4}={%u}",
Valid:
“{:var1}={%u} struct{“, “{:var2}={%u}”, “{:var3}={%u}{:var4}={%u}}”,
Variable - Value Pair Assignments (Parameters)
Variable is syntactically derived from an expression with given list description:
{:variable}=...
and can only exists in pairs with expressions, in the following form, followed by an expression, and with optional, recommended, unit specifier:
{:variable}={math:description}[unit]
where:
where a math object can contain one or more arguments,
if at least one is of Input/Output direction then variable may be changed by calculating its inverse, and sending raw arguments back to a device.
Unit specifier should comply with the International System of Units.
Examples:
{:variable}={1}[V] // a constant
{:variable}={%<I*0.123}[mA] // represents a read-only current in mA with some gain factor
{:variable}={%hu:off,on} // an 8-bit value is used to display state, that may be modified by user
There should be an empty space between a text entry and an expression/assignment, for example:
"Variable description {:var1}={%U}[kWh]" --correct
"Variable description{:var1}={%U}[kWh]" --incorrect
As on the other hand, data structures are declared without an empty space:
"data{....}"
Base Units with Scaling Prefixes
m meter |
T tera 10^12 |
g gram |
G giga 10^9 |
s second |
M mega 10^6 |
A ampere |
k kilo 10^3 |
K kelvin |
d deci 10^−1 |
mol mole |
m mili 10^−3 |
cd candela |
μ micro 10^−6 |
n nano 10^-9 |
|
p piko 10^−12 |
|
f femto 10^−15 |
Derived Units
rad radian |
sr steradian |
Hz hertz |
N newtoon |
Pa pascal |
J joule |
W Watt |
C coloumb |
V volt |
F farad |
Ω Ohm |
S siemens |
Wb weber |
T tesla |
H henry |
°C degree celsius |
lm lumen |
lx lux |
Bq backuerel |
Gy gray |
Sv sievert |
kat katal |
Vectors
Vectors can be defined in the following ways:
General form:
{:vector[n:m]}={...}
[n:m] defines the range of vector.
For example:
{:vec[2:5]}={%u}
which defines a vector of 3 same expressions, and 3 arguments.
Vectors can be defined also with different expressions as:
{:Ir}={%hu/2,%hu*2,%hu+2}[%]
in which case the number of columns is determined by the comas.
if vector size is defined as in:
{:Ir[3]}={%hu,%hu,%hu}[%]
It must match the number of elements, otherwise error is reported.
Vector Index References
When cross referencing vector parameters, matching indexes can be defined using notation:
- {parameter_name}[] : matching index, example G[]
- {parameter_name}[{constant}] : fixed index, example G[2]
- {parameter_name}[{offset}:] : offset index, example G[2:]
Examples:
{:G[1:16]}={%hu}
{:ad1[8]}={%lI/757760/256*G[]}
{:ad2[8]}={%lI/757760/256*G[9:]}
Multi-Message Descriptors
When underlying protocol prohibits the use of long descriptors, then multiple message numbers may be used to form a larger Message Descriptor by placing a plus character ‘+’ at the beginning of successive messages. Arguments below to the first message, and the remaining message numbers are skipped when sending/receiving arguments.
Example:
msg 1: "First {:var11}={%hu}[kWh] in {:var12}={%hu};"
msg 2: "+Second {:var21}={%hu}[kWh] in {:var22}={%hu};"
msg 3: "+Third {:var31}={%hu}[kWh] in {:var32}={%hu};"
Creates a longer descriptor for MSGNUM=1, from which same message arguments are read when displaying or updating a message.
Multi-Message Updates
It is desired that messages aren’t too long with too many arguments to offer fine grained control over configuration parameters, or individual updates. However on the other side there are multi-message updates to reduce network overhead and at the same time permitting fine grained control.
Multi-message update is formed with an argument field containig arguments of several messages, starting from the given message number to which it is targeted to, say MSGNUM. The remaining arguments are passed to the following messages MSGNUM+1, MSGNUM+2, etc.
Example:
msg 1: "MultiArg1 {:m1}={%hu+%hu}"
msg 2: "MultiArg2 {:m2}={%hu+%hu}"
msg 3: "MultiArg3 {:m3}={%hu+%hu}"
A 6-byte long argument update for msg 1 would in this case update all three messages.
Examples
Basic
Basic descriptors contain basic headers, data structures, expressions and text elements.
msg0: "%T0{Company Device}V1.1.08 dev{"
msg1: "%T1{First header}\r Temperature {:T}={%li/100}[oC]\r"
msg2: "Enumeration {:state}={%hu:Off,On,Error}"
msg3: "Structure str{{:I_A}={2.174*%hu}[mA] {:M_B}={%u+12}}\r"
msg4: "%T1{Second header}\r"
msg5: "{:ChA}={%u} {:ChB}={%lu}"
msg6: "Final section ending the main structure {:t}={%lU}[UTC]}}"
Advanced
Advanced descriptors contain more complex expressions, advanced headers and cross references.
msg0: "%T0{Company Device}V1.1.08 dev{"
msg1: "%T1{First header}\r Expression with accuracy {:T}={%li/100:+-10}[oC]\r"
msg2: "Enumeration with defined values {:state}={%hu:Off=0,On=4,Error=8}"
msg3: "Structure spanning two messages below\r"
msg4: "str{{:I_A}={2.174*%hu+(12/%u)}[mA] {:M_B}={%u&%u}"
msg5: "Variable cross reference {:ref}={%u*1.3} {:relativeRef}={2.174*ref} {:absoluteRef}={2.174*dev.str.ref}}\r"
msg6: "%T1a{Advanced section header}\r Read only {:ChA}={%<hu} write only {:ChB}={%>hu}"
msg7: "Hex and shift expressions {:hexVar}={%lx} {:phaseShift}={((%U<<8)+%hu)}\r
msg8: "%T1d{Development section header}\r
msg9: "Web Link %tu{isotel.eu}"
msg10: "Final section ending the main structure {:t}={%lU}[UTC]}}"
Complex
Complex descriptors contain multiple cross references, over multiple messages, more complex expressions, hidden variables and table.
msg0: "%T0{Company Device with hidden serial id and 16bit endian encoding rule}V1.1.09 %e {#sid}={%Lx} dev{"
msg1: "%T1{First header}\r Expression with changing accuracy {:T}={%li/100:+-(%u/100)}[oC]\r"
msg2: "Enumeration with non-integer values {:state}={%hi*0.2:val1=-0.8,val2=4.2,val3=12}"
msg3: "Structure spanning two messages below\r"
msg4: "str{{:I_A}={2.174*%hu+(12/%u)}[mA] NaN arguments {:J_B}={%j}{:K_B}={%k}"
msg5: "Multiple cross reference {:ref}={%u*1.3} {:relativeRef}={2.174*ref} {:absoluteRef}={2.174*dev.str.ref} {:multiRef}={1.2*ref*absoluteRef}}\r"
msg6: "Argument cross reference {:argref}={%4:2*1.3}\r"
msg7: "%T1a{Advanced section header}\r"
msg8: "Read only {:ChA}={%<hu} write only {:ChB}={%>hu} continues to multi-msg description"
msg9: "+Hex and shift expressions {:hexVar}={%<lx} {:phaseShift}={((%U<<8)+%hu)}\r
msg10: "%T1d{Development section header}\r
msg11: "String variable {:str}={%c20} Web Link %tu{isotel.eu}"
msg12: "Table \t pin{{:pin[14]}={%<u}\t"
msg13: "{:function[14]}={%u?%<u:val1;val2;val3;val4}\t
msg14: "{:value[0:6]}={%<j+-(%<k)/%<j'0} {:value[7:13]}={%<j+-(%<k)/%<j'0}\t
msg15: "{:unit[14]}={%<hu?0:``,V,mV,A,mA,oC,`mV/V`,uA,g,dps}\n
msg16: "Final section ending the main structure {:t}={%lU}[UTC]}}"
msg17: "EOM %!"
Document Changes
Date |
Release |
Changes |
February 23, 2006 |
0.1 |
Initial Message Layer |
November 23, 2006 |
0.2 |
Revised for first implementations. |
July 10, 2010 |
0.3 |
Public version. |
December 18,2011 |
0.4 |
Simplified version of Message Layer derived |
January 23, 2012 |
0.5 |
Alignment with first IoT release |
February 14, 2016 |
1.0 |
Public version of Renewed Sensor Message Layer |
February 25, 2017 |
1.1 |
Added 32/64-bit floating point specifier |
March 31, 2022 |
1.2 |
Updated enumeration masking, variable length, line breaking, quote strings |
April 1, 2022 |
1.2 |
Added tables, updated variable length descriptions |
April 6, 2022 |
1.2 |
Updated float point specs, added string args, enum severity, Nan, vector indexing, datastructure limitations |
April 14, 2022 |
1.2 |
Updated examples, limitations |
May 19, 2022 |
1.2.0.3 |
Updated version specific descriptions for half precision float, variable length argument for u,j,k,x types |
August 12, 2022 |
1.2.0.6 |
Added arbirary length variable descriptions |
References
Standards:
http://en.wikipedia.org/wiki/International_System_of_Units International System of Units
http://people.csail.mit.edu/jaffer/MIXF/CMIXF-11 Representation of currency and SI units in character strings for information interchanges
http://www.jamesebechtold.com/WikiJB/ascii.html ASCII Standard and Extended Tables
Documents:
Tine Kavcic, “Implementacija sporocilnega nivoja Sensor Network Prototcol v Javi”, Dimplomsko delo, FRI, Ljubljana 2011