1 /*!
2 * \file CayenneLpp.c
3 *
4 * \brief Implements the Cayenne Low Power Protocol
5 *
6 * \copyright Revised BSD License, see section \ref LICENSE.
7 *
8 * \code
9 * ______ _
10 * / _____) _ | |
11 * ( (____ _____ ____ _| |_ _____ ____| |__
12 * \____ \| ___ | (_ _) ___ |/ ___) _ \
13 * _____) ) ____| | | || |_| ____( (___| | | |
14 * (______/|_____)_|_|_| \__)_____)\____)_| |_|
15 * (C)2013-2018 Semtech
16 *
17 * \endcode
18 *
19 * \author Miguel Luis ( Semtech )
20 */
21 #include <stdint.h>
22
23 #include "utilities.h"
24 #include "CayenneLpp.h"
25
26 #define CAYENNE_LPP_MAXBUFFER_SIZE 242
27
28 static uint8_t CayenneLppBuffer[CAYENNE_LPP_MAXBUFFER_SIZE];
29 static uint8_t CayenneLppCursor = 0;
30
CayenneLppInit(void)31 void CayenneLppInit( void )
32 {
33 CayenneLppCursor = 0;
34 }
35
CayenneLppReset(void)36 void CayenneLppReset( void )
37 {
38 CayenneLppCursor = 0;
39 }
40
CayenneLppGetSize(void)41 uint8_t CayenneLppGetSize( void )
42 {
43 return CayenneLppCursor;
44 }
45
CayenneLppGetBuffer(void)46 uint8_t* CayenneLppGetBuffer( void )
47 {
48 return CayenneLppBuffer;
49 }
50
CayenneLppCopy(uint8_t * dst)51 uint8_t CayenneLppCopy( uint8_t* dst )
52 {
53 memcpy1( dst, CayenneLppBuffer, CayenneLppCursor );
54
55 return CayenneLppCursor;
56 }
57
58
CayenneLppAddDigitalInput(uint8_t channel,uint8_t value)59 uint8_t CayenneLppAddDigitalInput( uint8_t channel, uint8_t value )
60 {
61 if( ( CayenneLppCursor + LPP_DIGITAL_INPUT_SIZE ) > CAYENNE_LPP_MAXBUFFER_SIZE )
62 {
63 return 0;
64 }
65 CayenneLppBuffer[CayenneLppCursor++] = channel;
66 CayenneLppBuffer[CayenneLppCursor++] = LPP_DIGITAL_INPUT;
67 CayenneLppBuffer[CayenneLppCursor++] = value;
68
69 return CayenneLppCursor;
70 }
71
CayenneLppAddDigitalOutput(uint8_t channel,uint8_t value)72 uint8_t CayenneLppAddDigitalOutput( uint8_t channel, uint8_t value )
73 {
74 if( ( CayenneLppCursor + LPP_DIGITAL_OUTPUT_SIZE ) > CAYENNE_LPP_MAXBUFFER_SIZE )
75 {
76 return 0;
77 }
78 CayenneLppBuffer[CayenneLppCursor++] = channel;
79 CayenneLppBuffer[CayenneLppCursor++] = LPP_DIGITAL_OUTPUT;
80 CayenneLppBuffer[CayenneLppCursor++] = value;
81
82 return CayenneLppCursor;
83 }
84
85
CayenneLppAddAnalogInput(uint8_t channel,float value)86 uint8_t CayenneLppAddAnalogInput( uint8_t channel, float value )
87 {
88 if( ( CayenneLppCursor + LPP_ANALOG_INPUT_SIZE ) > CAYENNE_LPP_MAXBUFFER_SIZE )
89 {
90 return 0;
91 }
92
93 int16_t val = ( int16_t ) ( value * 100 );
94 CayenneLppBuffer[CayenneLppCursor++] = channel;
95 CayenneLppBuffer[CayenneLppCursor++] = LPP_ANALOG_INPUT;
96 CayenneLppBuffer[CayenneLppCursor++] = val >> 8;
97 CayenneLppBuffer[CayenneLppCursor++] = val;
98
99 return CayenneLppCursor;
100 }
101
CayenneLppAddAnalogOutput(uint8_t channel,float value)102 uint8_t CayenneLppAddAnalogOutput( uint8_t channel, float value )
103 {
104 if( ( CayenneLppCursor + LPP_ANALOG_OUTPUT_SIZE ) > CAYENNE_LPP_MAXBUFFER_SIZE )
105 {
106 return 0;
107 }
108 int16_t val = ( int16_t ) ( value * 100 );
109 CayenneLppBuffer[CayenneLppCursor++] = channel;
110 CayenneLppBuffer[CayenneLppCursor++] = LPP_ANALOG_OUTPUT;
111 CayenneLppBuffer[CayenneLppCursor++] = val >> 8;
112 CayenneLppBuffer[CayenneLppCursor++] = val;
113
114 return CayenneLppCursor;
115 }
116
117
CayenneLppAddLuminosity(uint8_t channel,uint16_t lux)118 uint8_t CayenneLppAddLuminosity( uint8_t channel, uint16_t lux )
119 {
120 if( ( CayenneLppCursor + LPP_LUMINOSITY_SIZE ) > CAYENNE_LPP_MAXBUFFER_SIZE )
121 {
122 return 0;
123 }
124 CayenneLppBuffer[CayenneLppCursor++] = channel;
125 CayenneLppBuffer[CayenneLppCursor++] = LPP_LUMINOSITY;
126 CayenneLppBuffer[CayenneLppCursor++] = lux >> 8;
127 CayenneLppBuffer[CayenneLppCursor++] = lux;
128
129 return CayenneLppCursor;
130 }
131
CayenneLppAddPresence(uint8_t channel,uint8_t value)132 uint8_t CayenneLppAddPresence( uint8_t channel, uint8_t value )
133 {
134 if( ( CayenneLppCursor + LPP_PRESENCE_SIZE ) > CAYENNE_LPP_MAXBUFFER_SIZE )
135 {
136 return 0;
137 }
138 CayenneLppBuffer[CayenneLppCursor++] = channel;
139 CayenneLppBuffer[CayenneLppCursor++] = LPP_PRESENCE;
140 CayenneLppBuffer[CayenneLppCursor++] = value;
141
142 return CayenneLppCursor;
143 }
144
CayenneLppAddTemperature(uint8_t channel,float celsius)145 uint8_t CayenneLppAddTemperature( uint8_t channel, float celsius )
146 {
147 if( ( CayenneLppCursor + LPP_TEMPERATURE_SIZE ) > CAYENNE_LPP_MAXBUFFER_SIZE )
148 {
149 return 0;
150 }
151 int16_t val = ( int16_t) ( celsius * 10 );
152 CayenneLppBuffer[CayenneLppCursor++] = channel;
153 CayenneLppBuffer[CayenneLppCursor++] = LPP_TEMPERATURE;
154 CayenneLppBuffer[CayenneLppCursor++] = val >> 8;
155 CayenneLppBuffer[CayenneLppCursor++] = val;
156
157 return CayenneLppCursor;
158 }
159
CayenneLppAddRelativeHumidity(uint8_t channel,float rh)160 uint8_t CayenneLppAddRelativeHumidity( uint8_t channel, float rh )
161 {
162 if( ( CayenneLppCursor + LPP_RELATIVE_HUMIDITY_SIZE ) > CAYENNE_LPP_MAXBUFFER_SIZE )
163 {
164 return 0;
165 }
166 CayenneLppBuffer[CayenneLppCursor++] = channel;
167 CayenneLppBuffer[CayenneLppCursor++] = LPP_RELATIVE_HUMIDITY;
168 CayenneLppBuffer[CayenneLppCursor++] = (uint8_t ) ( rh * 2 );
169
170 return CayenneLppCursor;
171 }
172
CayenneLppAddAccelerometer(uint8_t channel,float x,float y,float z)173 uint8_t CayenneLppAddAccelerometer( uint8_t channel, float x, float y, float z )
174 {
175 if( ( CayenneLppCursor + LPP_ACCELEROMETER_SIZE ) > CAYENNE_LPP_MAXBUFFER_SIZE )
176 {
177 return 0;
178 }
179 int16_t vx = ( int16_t ) ( x * 1000 );
180 int16_t vy = ( int16_t ) ( y * 1000 );
181 int16_t vz = ( int16_t ) ( z * 1000 );
182
183 CayenneLppBuffer[CayenneLppCursor++] = channel;
184 CayenneLppBuffer[CayenneLppCursor++] = LPP_ACCELEROMETER;
185 CayenneLppBuffer[CayenneLppCursor++] = vx >> 8;
186 CayenneLppBuffer[CayenneLppCursor++] = vx;
187 CayenneLppBuffer[CayenneLppCursor++] = vy >> 8;
188 CayenneLppBuffer[CayenneLppCursor++] = vy;
189 CayenneLppBuffer[CayenneLppCursor++] = vz >> 8;
190 CayenneLppBuffer[CayenneLppCursor++] = vz;
191
192 return CayenneLppCursor;
193 }
194
CayenneLppAddBarometricPressure(uint8_t channel,float hpa)195 uint8_t CayenneLppAddBarometricPressure( uint8_t channel, float hpa )
196 {
197 if( ( CayenneLppCursor + LPP_BAROMETRIC_PRESSURE_SIZE ) > CAYENNE_LPP_MAXBUFFER_SIZE )
198 {
199 return 0;
200 }
201 int16_t val = ( int16_t ) ( hpa * 10 );
202
203 CayenneLppBuffer[CayenneLppCursor++] = channel;
204 CayenneLppBuffer[CayenneLppCursor++] = LPP_BAROMETRIC_PRESSURE;
205 CayenneLppBuffer[CayenneLppCursor++] = val >> 8;
206 CayenneLppBuffer[CayenneLppCursor++] = val;
207
208 return CayenneLppCursor;
209 }
210
CayenneLppAddGyrometer(uint8_t channel,float x,float y,float z)211 uint8_t CayenneLppAddGyrometer( uint8_t channel, float x, float y, float z )
212 {
213 if( ( CayenneLppCursor + LPP_GYROMETER_SIZE ) > CAYENNE_LPP_MAXBUFFER_SIZE )
214 {
215 return 0;
216 }
217 int16_t vx = ( int16_t ) ( x * 100 );
218 int16_t vy = ( int16_t ) ( y * 100 );
219 int16_t vz = ( int16_t ) ( z * 100 );
220
221 CayenneLppBuffer[CayenneLppCursor++] = channel;
222 CayenneLppBuffer[CayenneLppCursor++] = LPP_GYROMETER;
223 CayenneLppBuffer[CayenneLppCursor++] = vx >> 8;
224 CayenneLppBuffer[CayenneLppCursor++] = vx;
225 CayenneLppBuffer[CayenneLppCursor++] = vy >> 8;
226 CayenneLppBuffer[CayenneLppCursor++] = vy;
227 CayenneLppBuffer[CayenneLppCursor++] = vz >> 8;
228 CayenneLppBuffer[CayenneLppCursor++] = vz;
229
230 return CayenneLppCursor;
231 }
232
CayenneLppAddGps(uint8_t channel,float latitude,float longitude,float meters)233 uint8_t CayenneLppAddGps( uint8_t channel, float latitude, float longitude, float meters )
234 {
235 if( ( CayenneLppCursor + LPP_GPS_SIZE ) > CAYENNE_LPP_MAXBUFFER_SIZE )
236 {
237 return 0;
238 }
239 int32_t lat = ( int32_t ) ( latitude * 10000 );
240 int32_t lon = ( int32_t ) ( longitude * 10000 );
241 int32_t alt = ( int32_t ) ( meters * 100 );
242
243 CayenneLppBuffer[CayenneLppCursor++] = channel;
244 CayenneLppBuffer[CayenneLppCursor++] = LPP_GPS;
245
246 CayenneLppBuffer[CayenneLppCursor++] = lat >> 16;
247 CayenneLppBuffer[CayenneLppCursor++] = lat >> 8;
248 CayenneLppBuffer[CayenneLppCursor++] = lat;
249 CayenneLppBuffer[CayenneLppCursor++] = lon >> 16;
250 CayenneLppBuffer[CayenneLppCursor++] = lon >> 8;
251 CayenneLppBuffer[CayenneLppCursor++] = lon;
252 CayenneLppBuffer[CayenneLppCursor++] = alt >> 16;
253 CayenneLppBuffer[CayenneLppCursor++] = alt >> 8;
254 CayenneLppBuffer[CayenneLppCursor++] = alt;
255
256 return CayenneLppCursor;
257 }
258