diff --git a/binprot.c b/binprot.c new file mode 100644 index 0000000..4c730fa --- /dev/null +++ b/binprot.c @@ -0,0 +1,68 @@ +#include +#include +#include + +/* + * Example binary protocol for passing small, statically sized messages. + * + * These messages are efficient and easily serializable. Since there is no variable length payload in the message, no + * parsing is required, and a simple cast into whatever reciever buffer you're using, or a memcpy into a preallocated + * CommandMessage, is enough. Keep in mind; the largest member of the data union determines the size of the struct. + */ + +// clang-format off +typedef enum { + CMD_SET_LEVEL = 1, + CMD_SET_LIGHTS = 2, + CMD_SET_DISTANCE_FACTOR = 3 +} CommandType; + +typedef struct __attribute__((__packed__)) { + uint8_t type; + union { + struct { uint8_t level; } set_level; + struct { uint8_t on; } set_lights; // 1 = on, 0 = off + struct { float factor; } set_distance; + } data; + /* NOTE: Consider adding crc checksum here, or in a wrapper struct */ +} CommandMessage; +// clang-format on + +void print_command(CommandMessage *m) { + switch (m->type) { + case CMD_SET_LEVEL: + printf("Type: SetLevel\nPayload: %d\n", m->data.set_level.level); + break; + case CMD_SET_LIGHTS: + printf("Type: SetLights\nPayload: %d\n", m->data.set_lights.on); + break; + case CMD_SET_DISTANCE_FACTOR: + printf("Type: SetDistanceFactor\nPayload: %.2f\n", m->data.set_distance.factor); + break; + } +} + +char buf[sizeof(CommandMessage)]; + +int main(void) { + CommandMessage m = {CMD_SET_LIGHTS, .data.set_lights.on = 1}; + memcpy(buf, &m, sizeof(CommandMessage)); + + /* Here we can send buf through a socket, to uart, wherever */ + + CommandMessage r = {0}; + memcpy(&r, &buf, sizeof(CommandMessage)); + + /* We can then dispatch based on the message type */ + print_command(&r); + + m.type = CMD_SET_LEVEL; + m.data.set_level.level = 10; + print_command(&m); + + m.type = CMD_SET_DISTANCE_FACTOR; + m.data.set_distance.factor = 1337.42; + print_command(&m); + + return 0; +}