Take this post as my stream of thoughts, I started to thing about shortening JSON but then realized this is not the way, bu I keep all my thoughts flow here so you can learn…
JSON isn’t really ideal format or needed in this usage. I checked that twr_radio_sub_pt_t
unfortunatelly does not have plain binary format. for the other way from node to dongle there is option to send raw buffer which arrives as array of numbers in MQTT twr_radio_pub_buffer
.
So we would need to use string to send settings, but do it more efficiently.
Addressing
since you would like to configure one or many channels by single message, I would suggest just single topic for all data, let’s say led-pwm/-/config/set
.
And in the string I would use by bit masking which of eight PWM channels this received configuration applies. Lets name it mask
. So for 8 channels it will be 8 bit number and when you send value 0b00000001
then only first channel will be set with incoming configuration, when the value is 0b10000001
= 129 decimal then then first and eight channel will be configured by received parameter.
led-pwm/-/config/set: {mask: 129,toBase: 90, toMax: 1800, toStep: 10, trOn: 1.5, trOff: 5, trCh: 0.5, br: 1}
The address will be a decimal number 0-255 in your message, which will be explained below.
Efficient string encoding
JSON is really terrible. I see that you would like send different parameters, so you would like to have possibility to send only few attributes, but you will need to really shorten them.
led-pwm/-/config/set: {toBase: 90, toMax: 1800, toStep: 10, trOn: 1.5, trOff: 5, trCh: 0.5, br: 1}
- get rid of spaces, for example here
toBase: 90
is extra space, also after every ,
coma is space.
- shorten names to less letters
- make sure that if you set the highest number value to all parameters (worst-case), you will fit into that 45-50 bytes of radio message.
So your message can be
led-pwm/-/config/set: {tBs:90,tMx:1800,tSt:10,trOn:1.5,trOff:5,trCh:0.5,br:1}
Also it does not makes sense for me to send the {}
symbols
76 letters becomes 53… which is still too much. So I would suggest completely get rid of JSONs
Comma separated values & positional parameters
if you have 7 parameters and some of them are optional we can use comas to separate them and if the parameter should not be changed, just place two commas ,,
.
So this (let say we wouldn’t like to set toMax parameter)
{mask: 129,toBase: 90, /*toMax: 1800*/, toStep: 10, trOn: 1.5, trOff: 5, trCh: 0.5, br: 1}
could look like this
129,90,,10,1.5,5,0.5,1
notice the two commas above ,,
for the missing toMax
parameter.
This way we have 22 characters.
So you use strchar()
function in loop to find all the ,
symbols and if there is some string in between ,
you parse them from string to numbers atoi()
or atof()
.
Since I don’t know the range of each value, you have to be careful whether you send big float values like 2 000 000 000
, if you send them 7x then you have 70 characters.
If you send some big values, you can also give them coefficients, so you send lets say 10 times smaller value and in the node you multiply it again. It depends how much precision you need.
Another improvement could be that you encode the numbers to hexadecimal, which takes less characters. So uint16_t with biggest value 65535 will have FFFF. Bit since I don’t know the ranges of your parameters it might not help much.
You can also send completely binary data in string, using base64 encoding. You can use twr_base64_decode
function in SDK. But this might be more complicated.
You can read my article of efficient coding of values. It gets to the protobuffers, but the first part is generic for any transfer and can help you with some decisions.
https://www.hardwario.com/cs/blog/2021-05-12-protobuffers/