(This question is not strictly limited to wireless, as my need is for application layer, although the link/transport layer involves nRF24L01+.)
What are viable, preferably standardized, options and alternatives for application layer telemetry and remote control?
Interface Raspberry Pi controller with sensors/remotes, with main constraints being on ATmega side in terms of sketch size and RAM usage. RPi will send commands to, and receive notifications and telemetry from, these ATmegas.
Application layer communication is what I need. Data is validated in previous layers. Only correct and valid data will be parsed.
I aim to build sensors based on ATmega (currently Arduino pro mini) and nRF24L01+. Some will also have remote controllable devices connected, such as lights.
My communication will be mainly toward Raspberry Pi, running Python (preferably), interfacing nRF24L01+ over hardware driven SPI.
I'm using AES-256 for CBC-encryption and SipHash-2-4 as MAC to protect the data over the air from eavesdropping, MITM and replay attacks. (May sound like overkill but it's been fairly straight forward and simple.)
nRF24L01+ can send at most 32 bytes per transmission, so my initial 32-byte package will contain an 8-bytes start sequence including number of encrypted blocks, a 16-byte initialization vector for AES, and an 8-byte MAC for the first 24 bytes.
After this initial package, each transmission will contain a counter for the current block, a 16-byte encrypted block, and an 8-byte MAC (of the first 17 bytes), for a total of 25 bytes. I will only decrypt that which has a valid MAC.
Also, as a learning experience, I have been building the AVR application with a task manager at its core. All tasks have been possible to split up into smaller chunks and no single block takes more than one millisecond to execute before it yields and potentially lets other ready-to-execute code run. (With the exception of the odd case where multiple debug printouts follow one another.)
My largest sketch so far, with most debugging code disabled, takes up roughly 17 / 30 kB program storage and 1.4 / 2 kB RAM (including 320 byte data buffer which will shrink once I know the final size requirement). It is mostly done, and already using as many of the intended function calls to external libraries as possible for a complete picture, although I have not yet implemented everything in detail.
Preferably the incoming data should be possible to process as a stream, up to 16 or 32 bytes at a time. If I can avoid parsing everything at once, I require less buffer space. (RAM is precious on the ATmega.)
- Google Protocol Buffers using nanopb - adds roughly 7 kB program storage for encode (3 kB) and decode (4 kB) of simple sensor data.
Benchmarks indicate the stack usage is potentially too high for me, although they do claim to use a very large message with all different types represented.
The overhead is very high, but this is otherwise a very tempting and flexible option.
- Roll-my-own type, with simple (and rigid) data structure.
Will require a little bit more effort to design and implement for both ATmega and Python on Raspberry Pi.