-
Notifications
You must be signed in to change notification settings - Fork 9
/
Copy pathDL-DLR2-012.erl
96 lines (75 loc) · 2.64 KB
/
DL-DLR2-012.erl
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
% https://www.decentlab.com/products/analog-or-digital-sensor-device-for-lorawan
-module(decentlab_decoder).
-define(PROTOCOL_VERSION, 2).
-export([decode/1, start/0]).
-define(SENSOR_DEFS,
[
#{
length => 2,
values => [
#{
name => <<"Strain gauge">>,
convert => fun(X) -> ((lists:nth(0 + 1, X) + lists:nth(1 + 1, X)*65536) / 8388608 - 1) / 64 * 4 / 2.02 * 1000000 end,
unit => <<"µm⋅m⁻¹"/utf8>>
}
]
},
#{
length => 1,
values => [
#{
name => <<"Battery voltage">>,
convert => fun(X) -> lists:nth(0 + 1, X) / 1000 end,
unit => <<"V"/utf8>>
}
]
}
]
).
decode(<<?PROTOCOL_VERSION, DeviceId:16,
Flags:16/bitstring, Bytes/binary>> = Binary) when is_binary(Binary) ->
Words = bytes_to_words(Bytes),
maps:merge(#{<<"Protocol version">> => ?PROTOCOL_VERSION,
<<"Device ID">> => DeviceId},
sensor(Words, Flags, ?SENSOR_DEFS));
decode(HexStr) ->
Binary = hex2bin(HexStr),
decode(Binary).
start() ->
io:format("~p~n", [decode("0217830003162e00870c33")]),
io:format("~p~n", [decode("02178300020c33")]).
%%%%%%%%%%%%%%%%%%%%%%%%%%%%% PRIVATE FUNCTIONS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
sensor(_Words, _Flags, []) -> #{};
sensor(Words, <<Flags:15, 0:1>>, [_Cur | Rest]) ->
sensor(Words, <<0:1, Flags:15>>, Rest);
sensor(Words, <<Flags:15, 1:1>>,
[#{length := Len, values := ValueDefs} | RestDefs]) ->
{X, RestWords} = lists:split(Len, Words),
Values = value(ValueDefs, X),
RestSensors = sensor(RestWords, <<0:1, Flags:15>>, RestDefs),
maps:merge(Values, RestSensors).
value([], _X) -> #{};
value([#{convert := Convert,
name := Name} = ValueDef | RestDefs], X) ->
Values = value(RestDefs, X),
Value = #{<<"value">> => Convert(X)},
Value2 = add_unit(Value, ValueDef),
maps:put(Name, Value2, Values);
value([_NoConvert | RestDefs], X) -> value(RestDefs, X).
add_unit(Value, #{unit := Unit}) ->
maps:put(<<"unit">>, Unit, Value);
add_unit(Value, _NoUnit) ->
Value.
hex2bin(HexStr) when is_binary(HexStr) -> hex2bin(binary_to_list(HexStr));
hex2bin(HexStr) -> hex2bin(HexStr, []).
hex2bin("", Bins) -> list_to_binary(lists:reverse(Bins));
hex2bin(HexStr, Bins) ->
Bytes = string:slice(HexStr, 0, 2),
Word = list_to_integer(Bytes, 16),
hex2bin(string:slice(HexStr, 2), [Word | Bins]).
bytes_to_words(Bytes) -> bytes_to_words(Bytes, []).
bytes_to_words(<<>>, Words) -> lists:reverse(Words);
bytes_to_words(<<Word:16, Rest/binary>>, Words) ->
bytes_to_words(Rest, [Word | Words]).
where(true, IfTrue, _IfFalse) -> IfTrue;
where(false, _IfTrue, IfFalse) -> IfFalse.