-
Notifications
You must be signed in to change notification settings - Fork 1
/
decoder.js
159 lines (136 loc) · 4.22 KB
/
decoder.js
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
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
/**
* Decoder for the "custom" data format send by a buoy, configured on "The Things Network".
*
* Developed by Benjamin Van der Smissen
* Modified by Brecht Van Eeckhoudt
*
* More documentation about these custom packets can be found in the
* software documentation in "/lora/lpp.c" for the following methods:
* - LPP_AddMeasurements
* - LPP_AddStormDetected
* - LPP_AddCableBroken
* - LPP_AddStatus
*
* Information gathered from:
* - https://dramco.be/tutorials/low-power-iot/ieee-sensors-2017/store-sensor-data-in-the-cloud
* - https://tago.elevio.help/en/articles/118-building-your-own-parser
*/
/**
* Function that does the decoding, calls other functions if necessary.
* @param {*} bytes The received "raw" bytes.
* @param {*} port The port the bytes were received on (not used...)
*/
function Decoder (bytes, port) {
var decoded = {};
decoded.BatteryVoltage = [];
decoded.InternalTemperature = [];
decoded.ExternalTemperature = [];
decoded.StormDetected = [];
decoded.CableBroken = [];
decoded.Status = [];
var count = 0;
var NR_of_Meas = bytes[0];
var type;
count++;
while (count < bytes.length) {
switch (bytes[count]) {
// 0x10 = Battery voltage channel
case 0x10:
count++;
if (bytes[count] === 0x02) { // 0x02 = Analog Input (Cayenne LPP datatype)
count++;
type = 0x02;
decoded.BatteryVoltage = bytesToArray2(bytes, NR_of_Meas, count, type);
count += NR_of_Meas*2;
}
break;
// 0x11 = Internal temperature channel
case 0x11:
count++;
if (bytes[count] === 0x67) { // 0x67 = Temperature (0.1 °C Signed MSB - Cayenne LPP datatype)
count++;
type = 0x67;
decoded.InternalTemperature = bytesToArray2(bytes, NR_of_Meas, count, type);
count += NR_of_Meas*2 ;
}
break;
// 0x12 = External temperature channel
case 0x12:
count++;
if (bytes[count] === 0x67) { // 0x67 = Temperature (0.1 °C Signed MSB - Cayenne LPP datatype)
count++;
type = 0x67;
decoded.ExternalTemperature = bytesToArray2(bytes, NR_of_Meas, count, type);
count += NR_of_Meas*2;
}
break;
// 0x13 = Storm detected channel
case 0x13:
count++;
if (bytes[count] === 0x00) { // 0x00 = Digital input (Cayenne LPP datatype)
count++;
decoded.StormDetected = bytesToArray1(bytes, NR_of_Meas, count);
count += NR_of_Meas;
}
break;
// 0x14 = Cable broken channel
case 0x14:
count++;
if (bytes[count] === 0x00) { // 0x00 = Digital input (Cayenne LPP datatype)
count++;
decoded.CableBroken = bytesToArray1(bytes, NR_of_Meas, count);
count += NR_of_Meas;
}
break;
// 0x15 = Status channel
case 0x15:
count++;
if (bytes[count] === 0x00) { // 0x00 = Digital input (Cayenne LPP datatype)
count++;
decoded.Status = bytesToArray1(bytes, NR_of_Meas, count);
count += NR_of_Meas;
}
break;
}
}
return decoded;
}
/**
* Function to convert bytes to an array when a specific Cayenne LPP datatype is given.
* @param {*} bytes The "raw" bytes to convert.
* @param {*} NR_of_Meas The number of measurements in the raw bytes.
* @param {*} count Counter value.
* @param {*} type The Cayenne LPP datatype.
*/
function bytesToArray2(bytes, NR_of_Meas, count, type) {
var data_size = 2;
var num_byte_el = bytes.length;
var readings = [];
for (var reading_id = 0; reading_id < NR_of_Meas; reading_id++) {
var value = ( ( (bytes[reading_id+count] << 8) | bytes[reading_id+count+1]) << 16) >> 16;
// Send float values are multiplied by 1000 (24.6 = 24600)
if (type === 0x67) readings.push(parseFloat(value)/10.0);
else readings.push(parseFloat(value)/100.0);
count += 1;
}
console.log(readings);
return readings;
}
/**
* Function to convert bytes to an array.
* @param {*} bytes The "raw" bytes to convert.
* @param {*} NR_of_Meas The number of measurements in the raw bytes.
* @param {*} count Counter value.
*/
function bytesToArray1(bytes, NR_of_Meas, count) {
var data_size = 1;
var num_byte_el = bytes.length;
var readings = [];
for (var reading_id = 0; reading_id < NR_of_Meas; reading_id++) {
var value = bytes[reading_id+count];
readings.push(parseInt(value));
count += 0;
}
console.log(readings);
return readings;
}