A very simple text-based protocol for IoT devices, requiring very little configuration, intended to be broadcast in UDP packets.
By default, use UDP port 16378.
Messages consist of the line "#HELO
" optionally followed by a space and a resource path,
any message header lines, and, if there is non-empty payload, a blank line, and
then the message payload, which extends to the end of the packet and
can be in any format.
'resource path' indicates the name of the resource that this message is about.
It could be a URI, a device-local path starting with "/
",
or a UNC-like path of the form "//" + device name + "/" + path
.
If no path is given, it is implied to be "/
".
Message headers are of the form of any non-whitespace characters, and then, if there is any value, a space, and then the value. Values containing linefeeds can be represented by following the linefeed with a tab character. The tab will not be part of the value, but marks a continuation of the previous value (this is the same line continuation rule as used by TEF).
Lines are terminated by a single linefeed character (0x0A). The
"#HELO
" line and any message header lines should always
end with a linefeed, even if they are at the end of the message.
Lines beginning with "#
" are special directives.
For now, none are defined.
You just can't have headers that start with that character.
By convention, the payload is in the same format as the headers,
providing values for various device properties relative to the resource path.
e.g. if the resource path is "//my-cool-sensor/bus1/
" and
the payload contains "subdevice0/reading 123.45
",
then that can be interpreted as providing the value 123.45
for the fully-qualified property //my-cool-sensor/bus1/subdevice0/reading
.
Examples:
The simplest possible message, which just announces that there is a device:
#HELO
Hypothetical message from a combined temperature/humidity sensor + relay device, which uses its own MAC address as its name:
#HELO //ab-cd-ef-01-23-45/ temperature1 20C humidity1 35% temperature2 25C humidity2 33% switch1/state on switch2/state off
The following are suggestions. Nothing is 'standardized' yet.
Payload might contain some directive indicating whether this packet contains only a patch to be applied to the property-value map for this resource, or if it is comprehensive.
Let's say that "#clear
" should be interpreted as
'forget everything you know about this resource',
and everything else is implicitly a patch.
Could be accomplished by appending something to the "#HELO
" token. Maybe a slash followed by a version number?
Would have semantics similar to their HTTP cousins. GET
, PUT
, and PATCH
being especially useful.
The method could follow any version number in the initial token.
e.g. to tell a device to turn off a switch, you might send:
#HELO/1234/PUT /switch1 off
To prevent any old Joe Schmoe from turning your lights on and off, but to keep things simple, I would probably use some symmetric key-based authentication header, which might contain a hash of the rest of the message + a shared secret key. A minimum nonce would be sent by the device to prevent replay attacks. The exchange would look something like:
Broadcast from device:
#HELO /authentication /scheme FooAuth /min-nonce 12345
Sent to the device by someone wanting to turn on the switch:
#HELO/PUT /switch1/state authorization FooAuth 12346;asd234123 on
A status
header can mirror that of HTTP to respond to specific requests.
Request:
#HELO/GET /something reqid jeffk123
Response:
#HELO /something re-reqid jeffk123 status 404 There is no such resource as '/something' here!