How to inject data into a bitstream

Hi!

I need to send a UDP message to an IoT devices and I need to calculate the checksum over the payload and add it back to the payload to a specific index.

Let say this is a minimalistic version of the payload:

iex(31)> payload
<<9, 1, 2, 3, 0, 0, 6>>

I run the checksum adding up all the bytes and now I need to add the result to the payload and replace those two 0’s (zeros) bytes, at position 4 and 5.

If the checksum is <<0xa, 0xb>>
the resulting payload should be:

<<9, 1, 2, 3, 0xa, 0xb, 6>>

How this can be done without converting the binary to a List, replacing bytes 4 and 5, and then converting it back to binary.

Can this be accessed by index?
I would to something like this in other language:

payload[4] = checksum[0]
payload[5] = checksum[1]

Thank you in advance.

You can use :binary.part to extract the parts you want to keep. Then create a list of all the new parts. That’s considered iodata or an iolist. Most code sending data can deal with that directly. If you really need a binary then IO.iodata_to_binary can convert back into a binary. If you can you should probably avoid that though.

4 Likes

You can also split the binary using pattern matching, something like

bbc = 4 # bytes before checksum
bc = 2 # bytes checksum

<<data_before::binary-size(bbc), _::binary-size(bc), rest::binary>> = payload
payload = data_before <> checksum <> rest

Keep in mind LostKobrakai’s answer and don’t convert it back to a binary if you can avoid it.
If your send function supports IOData you can probably send it directly

send_to_device([data_before, checksum, rest])

4 Likes