lorawan-server
lorawan-server copied to clipboard
2-byte float in parser (need help)
I have a sensor uploading measurements in 2-byte float. Can someone tell me how to code this in the parser in Erlang. I tried to use <afloat:16/float> and got error, since I guess it requires larger storage.
If you are parsing the data, please note that the "variables" need to start with uppercase. Hence:
<<AFloat:16/float>>
Thanks for the quick reply. Yes, I was actually used the uppercase letters.
Today I tried the online erlang compiler with <ACcX:16/float> and got "helloworld.erl:5: Warning: bad float bit size"
In fact, I tried 16, 24, 32 bits, only the 32/float does not give me an error on this compiler.
So, my question is: Can someone suggest a workaround to parse this type? Thanks.
The https://github.com/yjh0502/cbor-erlang (BSD license) uses the following code to parse half-precision floats:
decode_hf(<<0:1, 0:5, 0:10>>) -> 0.0;
decode_hf(<<1:1, 0:5, 0:10>>) -> -0.0;
decode_hf(<<Sign:1, 0:5, Frac:10>>) ->
{Frac2, Count} = hf_norm(Frac, 0),
<<Value:32/float>> = <<Sign:1, (-14-Count+127):8, Frac2:10, 0:13>>, Value;
decode_hf(<<0:1, 31:5, 0:10>>) -> inf;
decode_hf(<<1:1, 31:5, 0:10>>) -> neginf;
decode_hf(<<_:1, 31:5, _:10>>) -> nan;
decode_hf(<<Sign:1, Exp:5, Frac:10>>) ->
Exp32 = Exp - 15 + 127,
<<Value:32/float>> = <<Sign:1, Exp32:8, Frac:10, 0:13>>, Value.
To define a fun
inside a fun
you need a little trick, so the entire workaround looks like this:
HFNorm = fun
(Frac, Count, HN) when Frac < 1024 -> HN(Frac * 2, Count+1, HN);
(Frac, Count, _) -> {Frac, Count}
end,
Decode = fun
(<<0:1, 0:5, 0:10>>, _) -> 0.0;
(<<1:1, 0:5, 0:10>>, _) -> -0.0;
(<<Sign:1, 0:5, Frac:10>>, HN) ->
{Frac2, Count} = HN(Frac, 0),
<<Value:32/float>> = <<Sign:1, (-14-Count+127):8, Frac2:10, 0:13>>, Value;
(<<0:1, 31:5, 0:10>>, _) -> inf;
(<<1:1, 31:5, 0:10>>, _) -> neginf;
(<<_:1, 31:5, _:10>>, _) -> nan;
(<<Sign:1, Exp:5, Frac:10>>, _) ->
Exp32 = Exp - 15 + 127,
<<Value:32/float>> = <<Sign:1, Exp32:8, Frac:10, 0:13>>, Value
end,
A = Decode(<<0,0>>, HFNorm),
Thanks again for the fast reply. I shall try them out later.
Hi Did you succeed with the code? I need to implement same for my sensor which sends data in float16 format. The sensor sends the following HEX message 20000041fc. I tried to parse it as following without success: fun(Fields, <<A, B:16, C:16/float>>) -> Fields#{'object' => #{data_type=> A, data_status=> B==0, temp=> C}} end.
How should I embed the functions HFNorm and Decode into my code in order to present correct temp value? Thanks in advance