Go Down

Topic: Storing things in a hex string (Read 320 times) previous topic - next topic

supersecretsecretforgot

I've got a LoRa-based project, where a small device collects some values (temperature, humidity, and so forth), and then pushes it over LoRa to a specific endpoint. Due to some constraints, the payload can only be a single hex string.

So far, I've defined the hex string as:
Code: [Select]
uint8_t payload[16];


Which results in a hex string of 10 characters. I got some example code, which tells me to do the following:
Code: [Select]
  payload[0] = type, HEX;
  payload[1] = lightLevel, HEX;
  payload[2] = temperature, HEX;
  payload[3] = humidity, HEX;


But I think this'll result in only storing a single digit. Is there a way to store the full value in pre-determined spots?

For example:
Code: [Select]
type = 1
Lightlevel = 912
temperature = 23.8
humidity = 55


The resulting payload would then be something like:
Code: [Select]
1f00912f0238f055
with the `f` separating the different value types. Is this doable? If so, how do I concat these strings? Is there another, easier way?

TheMemberFormerlyKnownAsAWOL

#1
Aug 27, 2019, 02:07 pm Last Edit: Aug 27, 2019, 02:12 pm by TheMemberFormerlyKnownAsAWOL
'f' is a valid hex digit.
You can't use it as a separator in a hex string.

Have you got some prejudice against commas?
Please don't PM technical questions - post them on the forum, then everyone benefits/suffers equally

Delta_G

#2
Aug 27, 2019, 02:58 pm Last Edit: Aug 27, 2019, 03:00 pm by Delta_G
Code: [Select]
payload[0] = type, HEX;
  payload[1] = lightLevel, HEX;
  payload[2] = temperature, HEX;
  payload[3] = humidity, HEX;


If you found example code that told you to do this then you should avoid any other examples by that author.  This just stores the number 16 in each of those variables.  If you want to convert a number to a hex string in ascii then use itoa or sprintf. 

To assemble it all together in one string with separators use sprintf.
|| | ||| | || | ||  ~Woodstock

Please do not PM with technical questions or comments.  Keep Arduino stuff out on the boards where it belongs.

gfvalvo

Use a struct and send all the sensor data in binary.
No technical questions via PM. They will be ignored. Post your questions in the forum so that all may learn.

ardly

Your current code will not compile, you should provide a full listing that gives a clean compile.

As @tmfkaawol said you cannot use 'f' as a separator.
If you cannot use a comma then consider using fixed width fields.
Start by deciding what type each variable is and then the range of possible values it can take.
You can then either represent the binary value of the variable as hexadecimal or you can consider the variable as a string of characters and use the hex value of each of the ASCII characters in the string.
"Facts do not cease to exist because they are ignored" - Aldous Huxley

jremington

#5
Aug 27, 2019, 05:04 pm Last Edit: Aug 27, 2019, 05:14 pm by jremington
Quote
So far, I've defined the hex string as:
You have defined a character or byte array capable of storing 16 bytes.  If you are defining a fixed format payload to be transmitted to another device, there is no need for separators. Just choose the correct size for each of the variables and be consistent between transmitter and receiver.  Example: 1 byte for light level, two bytes for temperature, one byte for humidity.


Quote
This just stores the number 16 in each of those variables
I thought that too (as a result of the comma operator), but one of the forum C++ pros corrected me.

The "=" has higher precedence, so the ",HEX" does nothing unless parentheses dictate otherwise.  Agreed, though, avoid anything else by the author of that code.

Try this:
Code: [Select]
void setup() {
  Serial.begin(9600);
  int x;
  x = 100, HEX;
  Serial.print(" x = "); Serial.println(x);
  x = (101, HEX);
  Serial.print(" x = "); Serial.println(x);
}

void loop() {
}

supersecretsecretforgot

Well, I'm comforted by the fact that I'm not the only one reading the example code with a raised eyebrow!

The payload format can be fixed by me, and I can even set the length of the payload (with some oddly chosen potential lengths, but still). So then I can use fixed width for the different elements of the payload (and, apologies for the f; I realized this would not provide any form of flexibility, would likely backfire, and wasn't really needed anyway).

Right now I'm storing the values as uint, but it's the combining that's got me puzzled. The (somehow) working example code combines values in an uint8_t array, and I've established the supportive library does not approve of using chars.

So, my question works as follows:
I have a set of uint values, of pre-determined length. How do I combine them as a single uint8_t array with pre-defined field widths?

The only thing I can come up with is a large and unflexible horror that adds hex digits one by one to an empty array, but then I'm stuck at how to get a single digit. Also, I'm hoping something more elegant is possible.

gfvalvo

Also, I'm hoping something more elegant is possible.
One more try:
Use a struct and send all the sensor data in binary.
No technical questions via PM. They will be ignored. Post your questions in the forum so that all may learn.

TheMemberFormerlyKnownAsAWOL

Right now I'm storing the values as uint,

...apart from that temperature value with decimals.
Please don't PM technical questions - post them on the forum, then everyone benefits/suffers equally

jremington

#9
Aug 27, 2019, 09:21 pm Last Edit: Aug 27, 2019, 09:22 pm by jremington
Forget all about using "hex digits", they are for humans to read.

supersecretsecretforgot

...apart from that temperature value with decimals.
I just multiply by a hundred, and the values come through okay.

I'm not entirely clear on how a struct works, and I've neglected reading up on it (which I'm fixing now). It feels like the Matlab struct, which is this magical catch-all for whatever data structure you've got going on, but I suspect that implementation generates quite a bit of overhead.

Also, I'm seeing an example of pushing a struct over a serial bus, but unfortunately I'm working with a library that only accepts a hex array (and I'm not allowed, or likely capable enough, to poke at it).

How does one make an union of a struct?
Code: [Select]
(byte*)&payloadStruct, sizeof(payloadStruct))
or do I do something with typedef union?

TheMemberFormerlyKnownAsAWOL

Hopefully you are aware that temperatures can exceed 25.5 degrees as well as go negative?
Please don't PM technical questions - post them on the forum, then everyone benefits/suffers equally

gfvalvo

but unfortunately I'm working with a library that only accepts a hex array (and I'm not allowed, or likely capable enough, to poke at it).
Perhaps you'd be so kind as to share your full code and this library?
No technical questions via PM. They will be ignored. Post your questions in the forum so that all may learn.

supersecretsecretforgot

Perhaps you'd be so kind as to share your full code and this library?
The library is not supposed to be shared at the moment, regrettably. I'm tempted to read your response as "can't be done, change the library is the only option.". Is that the case?

Hopefully you are aware that temperatures can exceed 25.5 degrees as well as go negative?
Depending on the range of temperature variation, this may not be an issue. And aside from multiplying by a hundred, one can also multiply by other values, and even subtract, if that transformation would fit the value of whatever you're interested in to the range of possible values allowed.

gfvalvo

The library is not supposed to be shared at the moment, regrettably.
Then I suggest you pay someone to fix your problem after signing an NDA.
No technical questions via PM. They will be ignored. Post your questions in the forum so that all may learn.

Go Up