A new Struct-to-JSON Pipelines transformer is now generally available to Golioth users. This transformer takes structured binary data, such as that created using packed C structs, and converts it into JSON according to a user provided schema. To see this transformer in action, check out the example in our documentation or watch our recent Hackday recap stream.
Compact and Low Overhead
Historically, many IoT devices have sent structured binary data to cloud applications, which then needed to unpack that data and serialize it into a format that downstream services can understand. It’s easier and faster to populate a struct than it is to serialize data into a common format in C, and the data is often significantly more compact, which is especially important for devices using constrained transports such as cellular, Bluetooth, or LoRA. As embedded devices have gotten more powerful and efficient, many of these devices have started using serialization formats like CBOR, JSON, or Protocol Buffers, which are easier for cloud applications to work with. These serialization formats have significant advantages over packed C structs in terms of flexibility and interoperability, and for most cases that’s what we recommend our customers use.
But there are still cases where sending raw binary data could make sense. If the structure of your data is well-defined, a widely accepted standard, and/or unlikely to change, the overhead of a flexible serialization format may not yield any practical advantages. If it’s important to squeeze every single byte out of a low bandwidth link, it’s hard to beat a packed C struct. If you’re working with legacy systems where updating them to use a new serialization format involves all kinds of dependencies, it may simply be easier to stick with the status quo. Golioth now supports these use cases through the new Struct-to-JSON transformer.
To use the transformer, you need to describe the structure of the data in your Pipeline YAML. The transformer currently supports standard integer sizes from 8 to 64 bits (signed and unsigned), single and double precision floating point numbers, and fixed- and variable-length strings. Here’s an example of setting up the transformer for a float and a couple strings:
transformer: type: struct-to-json version: v1 parameters: members: - name: temperature type: float - name: string1 type: string length: 5 - name: string2_len type: u8 - name: string2 type: string length: string2_len
We can create a packed struct in C that matches the schema:
struct my_struct { float temperature; char string1[5]; uint8_t string2_len; char string2[]; } __attribute__((packed)); struct my_struct *s = malloc(sizeof(struct my_struct) + strlen("Golioth!")); s->temperature = 23.5f; s->string2_len = strlen("Golioth!"); memcpy(s->string1, "hello", strlen("hello")); memcpy(s->string2, "Golioth!", strlen("Golioth!"));
Sending that struct through the transformer gives us the following JSON:
{ "temperature": 23.5, "string1": "Hello", "string2_len": 8, "string2": "Golioth!" }
mallinfo()
Monitoring Heap Usage with Monitoring heap usage is a great way to gain insight into the performance of your embedded device. Many C standard library implementations provide a mallinfo()
(or its newer analogue mallinfo2()
) API that returns information about the current state of the heap. As this data is in a well-defined, standard format and unlikely to change, it’s a good candidate for sending directly to Golioth without any additional serialization. We can use the following pipeline to transform the struct returned by a call to mallinfo2()
on a 64-bit Linux system to JSON and send it to LightDB Stream:
filter: path: "/mallinfo" content_type: application/octet-stream steps: - name: step0 transformer: type: struct-to-json version: v1 parameters: members: - name: arena type: u64 - name: ordblks type: u64 - name: smblks type: u64 - name: hblks type: u64 - name: hblkhd type: u64 - name: usmblks type: u64 - name: fsmblks type: u64 - name: uordblks type: u64 - name: fordblks type: u64 - name: keepcost type: u64 destination: type: lightdb-stream version: v1
Click here to use this Pipeline.
See it in action
What’s Next
Stay tuned for additional Pipelines transformers and destinations to be released in the coming weeks. If you have a use-case that is not currently well supported by Pipelines, or an idea for a new transformer or destination, please reach out on the forum!
No comments yet! Start the discussion at forum.golioth.io