1
0
mirror of https://github.com/XeonSquared/OC-Copper.git synced 2024-11-14 13:58:05 +11:00
OC-Copper/oc/app/protocol.iot

89 lines
3.7 KiB
Plaintext

The IoT Protocol
- 20kdc, 2017
One of the core uses of Copper is network-connected small devices.
These have a set list of requirements:
1. The device itself can't be forced to do much in the way of work,
at least for simple cases.
2. The protocol needs to be relatively flexible.
The protocol is written here as 3 parts.
"The device" refers to the server / controllable object.
"The client" refers to the client.
Another thing to note is that due to the "cannot do much work" requirement,
only one device per hostname is supported via this protocol.
Part 1. General Mainport Packet Description
The "Main port" is port 4.
This port is the port via which most data exchange happens.
First things first - in case of error, do nothing at all.
If it's possible to just ignore a protocol violation, do so.
For example, a get request with data should be treated as a get request without it.
Secondly, it is allowed for the device to present different 'faces' depending on which client is accessing it.
However, all 'faces' must have the same descriptor (variable 0).
This is useful for devices which have some state, like a concurrent storage server
(allowing the download of different 1499-byte 'parts'),
but still keeping enough consistency for the device to be uniquely identifiable.
In all packets on the main port,
the first byte's upper 2 bits indicate what kind of packet this is -
the lower 6 bits is the 'variable number'.
The remainder of the packet is the parameter data.
00: Request: Get. This has no further data.
This must only be sent by the client to the device.
If valid, the device responds with the standard reliability-layer acknowledgement,
and a Response: Get packet to the client.
If invalid, the device only responds with acknowledgement.
01: Request: Set. The data is the new variable contents.
This must only be sent by the client to the device.
The device only responds with the standard reliability-layer acknowledgement.
Success is determined by checking acknowledgement, then performing a Get.
10: Perform Action. The data is the parameter.
This must only be sent by the client to the device.
The device only responds with the standard reliability-layer acknowledgement.
11: Response: Get. The data is the variable contents.
This must only be sent by the device to the client.
The client only responds with the standard reliability-layer acknowledgement.
Part 2. Variable Types
Variable types indicate to the program what values are expected in variables.
Firstly, the upper bit being set indicates an Action - only the lower bits actually give the variable type-code.
Secondly, if it's not an Action, the second-to-upper bit indicates if it can be set.
They are, as follows:
0: Void (Only useful for Actions. Think 'ignore anything out of here'.
1: Human-Readable String (Generic string that a user could feasibly type. No special characters.)
2: Boolean ("false" means false, "true" means true, anything else is disallowed.)
3: Float (See Human-Readable String, but translated to a number by the device.)
4: Descriptor (See Part 3.)
Part 3. Discovery & Description
Upon the receipt of any packet on port 1 that is addressed to "*" or the IoT device name,
it should send a packet back on port 4 formatted as a Get response packet for variable 0.
Variable 0 is always the Descriptor, which describes the variables and actions available.
The Descriptor is simply a list of variable types and 7-byte variable names,
starting from variable index 1 (as 0 is always the descriptor)
It's recommended the variable names are in camel-case.
Example descriptor for a networked lightbulb:
"\x42lActive"
Example descriptor for a networked turtle (Lua-escaped):
"\x80turnLft\x80turnRgt\x80forward\x80backwrd\x02fwd!air"