1
+ /**
2
+ * Cayenne Low-power Payload Library
3
+ *
4
+ * @author Pasakorn Tiwatthanont
5
+
6
+ *
7
+ * @link https://htmlcheatsheet.com/js/
8
+ */
9
+ // console.log('Node.js version: ' + process.version)
10
+ format = require ( 'string-format' )
11
+
12
+ /**
13
+ * Byte stream to fixed-point decimal word.
14
+ *
15
+ * @param stream: array of bytes.
16
+ * @return : word of the bytes in big-endian format.
17
+ */
18
+ function arrayToDecimal ( stream , is_signed = false , decimal_point = 0 ) {
19
+ var value = 0 ;
20
+ for ( var i = 0 ; i < stream . length ; i ++ ) {
21
+ if ( stream [ i ] > 0xFF )
22
+ throw 'Byte value overflow!' ;
23
+ value = ( value << 8 ) | stream [ i ] ;
24
+ }
25
+
26
+ if ( is_signed ) {
27
+ edge = 1 << ( stream . length ) * 8 ; // 0x1000..
28
+ max = ( edge - 1 ) >> 1 ; // 0x0FFF.. >> 1
29
+ value = ( value > max ) ? value - edge : value ;
30
+ }
31
+
32
+ if ( decimal_point ) {
33
+ value /= Math . pow ( 10 , decimal_point ) ;
34
+ }
35
+
36
+ return value ;
37
+ }
38
+
39
+ /**
40
+ * Cayenne Low-power Payload Decoder
41
+ *
42
+ * @param payload: array of bytes.
43
+ * @return : JSON
44
+ */
45
+ function decode ( payload ) {
46
+
47
+ if ( payload == null )
48
+ payload = [
49
+ 0x01 , 0x67 , 0x00 , 0xE1 , // "temperature_1" : 22.5 (fixed point)
50
+ 0x02 , 0x73 , 0x29 , 0xEC , // "barometric_pressure_2": 1073.2 (fixed point)
51
+ 0x03 , 0x88 , // "gps_3":
52
+ 0x02 , 0xDD , 0xFC , // { "latitude" : 18.79,
53
+ 0x0F , 0x1A , 0x68 , // "longitude": 98.98,
54
+ 0x00 , 0x79 , 0x18 , // "altitude" : 310 }
55
+ ]
56
+
57
+ /**
58
+ * @reference https://github.com/myDevicesIoT/cayenne-docs/blob/master/docs/LORA.md
59
+ *
60
+ * Type IPSO LPP Hex Data Size Data Resolution per bit
61
+ * Digital Input 3200 0 0 1 1
62
+ * Digital Output 3201 1 1 1 1
63
+ * Analog Input 3202 2 2 2 0.01 Signed
64
+ * Analog Output 3203 3 3 2 0.01 Signed
65
+ * Illuminance Sensor 3301 101 65 2 1 Lux Unsigned MSB
66
+ * Presence Sensor 3302 102 66 1 1
67
+ * Temperature Sensor 3303 103 67 2 0.1 °C Signed MSB
68
+ * Humidity Sensor 3304 104 68 1 0.5 % Unsigned
69
+ * Accelerometer 3313 113 71 6 0.001 G Signed MSB per axis
70
+ * Barometer 3315 115 73 2 0.1 hPa Unsigned MSB
71
+ * Gyrometer 3334 134 86 6 0.01 °/s Signed MSB per axis
72
+ * GPS Location 3336 136 88 9 Latitude : 0.0001 ° Signed MSB
73
+ * Longitude : 0.0001 ° Signed MSB
74
+ * Altitude : 0.01 meter Signed MSB
75
+ */
76
+ var sensor_types = {
77
+ 0 : { 'size' : 1 , 'name' : 'Digital Input' , 'signed' : false , 'decimal_point' : 0 , } ,
78
+ 1 : { 'size' : 1 , 'name' : 'Digital Output' , 'signed' : false , 'decimal_point' : 0 , } ,
79
+ 2 : { 'size' : 2 , 'name' : 'Analog Input' , 'signed' : true , 'decimal_point' : 2 , } ,
80
+ 3 : { 'size' : 2 , 'name' : 'Analog Output' , 'signed' : true , 'decimal_point' : 2 , } ,
81
+ 101 : { 'size' : 2 , 'name' : 'Illuminance Sensor' , 'signed' : false , 'decimal_point' : 0 , } ,
82
+ 102 : { 'size' : 1 , 'name' : 'Presence Sensor' , 'signed' : false , 'decimal_point' : 0 , } ,
83
+ 103 : { 'size' : 2 , 'name' : 'Temperature Sensor' , 'signed' : true , 'decimal_point' : 1 , } ,
84
+ 104 : { 'size' : 1 , 'name' : 'Humidity Sensor' , 'signed' : false , 'decimal_point' : 1 , } ,
85
+ 113 : { 'size' : 6 , 'name' : 'Accelerometer' , 'signed' : true , 'decimal_point' : 3 , } ,
86
+ 115 : { 'size' : 2 , 'name' : 'Barometer' , 'signed' : false , 'decimal_point' : 1 , } ,
87
+ 134 : { 'size' : 6 , 'name' : 'Gyrometer' , 'signed' : true , 'decimal_point' : 2 , } ,
88
+ 136 : { 'size' : 9 , 'name' : 'GPS Location' , 'signed' : false , 'decimal_point' : [ 4 , 4 , 2 ] , } , } ;
89
+
90
+ var sensors = { } ;
91
+ var i = 0 ;
92
+ while ( i < payload . length ) {
93
+ // console.log(i);
94
+ // console.log(typeof payload[i])
95
+ // console.log(payload[i].toString())
96
+ s_no = payload [ i ++ ] ;
97
+ s_type = payload [ i ++ ] ;
98
+ if ( typeof sensor_types [ s_type ] == 'undefined' )
99
+ throw format ( 'Sensor type error!: {}' , s_type ) ;
100
+ s_size = sensor_types [ s_type ] . size ;
101
+ s_name = sensor_types [ s_type ] . name ;
102
+
103
+ switch ( s_type ) {
104
+ case 0 : // Digital Input
105
+ case 1 : // Digital Output
106
+ case 2 : // Analog Input
107
+ case 3 : // Analog Output
108
+ case 101 : // Illuminance Sensor
109
+ case 102 : // Presence Sensor
110
+ case 103 : // Temperature Sensor
111
+ case 104 : // Humidity Sensor
112
+ case 113 : // Accelerometer
113
+ case 115 : // Barometer
114
+ case 134 : // Gyrometer
115
+ s_value = arrayToDecimal ( payload . slice ( i , i + s_size ) ,
116
+ is_signed = sensor_types [ s_type ] . signed ,
117
+ decimal_point = sensor_types [ s_type ] . decimal_point ) ;
118
+ //console.log(format('no:{} size:{} type:{} value:{}', s_no, s_size, s_name, s_value));
119
+ break ;
120
+ case 136 : // GPS Location
121
+ s_value = {
122
+ 'latitude' : arrayToDecimal ( payload . slice ( i + 0 , i + 3 ) , is_signed = sensor_types [ s_type ] . signed , decimal_point = sensor_types [ s_type ] . decimal_point [ 0 ] ) ,
123
+ 'longitude' : arrayToDecimal ( payload . slice ( i + 3 , i + 6 ) , is_signed = sensor_types [ s_type ] . signed , decimal_point = sensor_types [ s_type ] . decimal_point [ 1 ] ) ,
124
+ 'altitude' : arrayToDecimal ( payload . slice ( i + 6 , i + 9 ) , is_signed = sensor_types [ s_type ] . signed , decimal_point = sensor_types [ s_type ] . decimal_point [ 2 ] ) , } ;
125
+ //console.log(format('no:{} size:{} type:{} lat:{} lon:{} alt:{}', s_no, s_size, s_name, s_value.lat, s_value.lon, s_value.alt));
126
+ break ;
127
+ }
128
+
129
+ sensors [ s_no ] = { 'type' : s_type , 'type_name' : s_name , 'value' : s_value } ;
130
+ i += s_size ;
131
+ }
132
+
133
+ return sensors ;
134
+ }
135
+
136
+ /**
137
+ * Test
138
+ */
139
+ function test ( ) {
140
+ // Test arrayToDecimal()
141
+ arrTest = [ 0xFF ] ;
142
+ console . log ( arrayToDecimal ( arrTest ) + ' -> ' + arrayToDecimal ( arrTest , is_signed = true ) ) ; // -1
143
+ arrTest = [ 0xFF , 0xFF ] ;
144
+ console . log ( arrayToDecimal ( arrTest ) + ' -> ' + arrayToDecimal ( arrTest , is_signed = true ) ) ; // -1
145
+
146
+ // Test decode()
147
+ console . log ( decode ( ) ) ;
148
+ }
149
+
150
+ test ( )
0 commit comments