Skip to content

Commit 664f146

Browse files
committed
lora: sensor-lorawan: Initial commit
Signed-off-by: Alistair Francis <[email protected]>
1 parent 7f8181d commit 664f146

File tree

9 files changed

+1152
-1
lines changed

9 files changed

+1152
-1
lines changed

RadioLib/RadioLib

Submodule RadioLib updated 147 files
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
radioConfig.h
Lines changed: 217 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,217 @@
1+
/* SPDX-License-Identifier: GPL-3.0 */
2+
/*
3+
* The Cayenne Low Power Payload (LPP) provides a convenient and
4+
* easy way to send data over LPWAN networks such as LoRaWAN. The Cayenne LPP
5+
* is compliant with the payload size restriction, which can be lowered down to
6+
* 11 bytes, and allows the device to send multiple sensor data at one time.
7+
*
8+
* CayenneLPP is also support by TTN:
9+
* https://www.thethingsindustries.com/docs/integrations/payload-formatters/cayenne/
10+
*
11+
* This code is direct from: https://github.com/myDevicesIoT/CayenneLPP
12+
*
13+
* GPL-3.0 license, see `LICENSE.GPL`
14+
* See https://github.com/myDevicesIoT/CayenneLPP for license details
15+
*/
16+
17+
#include "CayenneLPP.h"
18+
19+
CayenneLPP::CayenneLPP(uint8_t size) : maxsize(size) {
20+
buffer = (uint8_t*) malloc(size);
21+
cursor = 0;
22+
}
23+
24+
CayenneLPP::~CayenneLPP(void) {
25+
free(buffer);
26+
}
27+
28+
void CayenneLPP::reset(void) {
29+
cursor = 0;
30+
}
31+
32+
uint8_t CayenneLPP::getSize(void) {
33+
return cursor;
34+
}
35+
36+
uint8_t* CayenneLPP::getBuffer(void) {
37+
return buffer;
38+
}
39+
40+
uint8_t CayenneLPP::copy(uint8_t* dst) {
41+
memcpy(dst, buffer, cursor);
42+
return cursor;
43+
}
44+
45+
uint8_t CayenneLPP::addDigitalInput(uint8_t channel, uint8_t value) {
46+
if ((cursor + LPP_DIGITAL_INPUT_SIZE) > maxsize) {
47+
return 0;
48+
}
49+
buffer[cursor++] = channel;
50+
buffer[cursor++] = LPP_DIGITAL_INPUT;
51+
buffer[cursor++] = value;
52+
53+
return cursor;
54+
}
55+
56+
uint8_t CayenneLPP::addDigitalOutput(uint8_t channel, uint8_t value) {
57+
if ((cursor + LPP_DIGITAL_OUTPUT_SIZE) > maxsize) {
58+
return 0;
59+
}
60+
buffer[cursor++] = channel;
61+
buffer[cursor++] = LPP_DIGITAL_OUTPUT;
62+
buffer[cursor++] = value;
63+
64+
return cursor;
65+
}
66+
67+
uint8_t CayenneLPP::addAnalogInput(uint8_t channel, float value) {
68+
if ((cursor + LPP_ANALOG_INPUT_SIZE) > maxsize) {
69+
return 0;
70+
}
71+
72+
int16_t val = value * 100;
73+
buffer[cursor++] = channel;
74+
buffer[cursor++] = LPP_ANALOG_INPUT;
75+
buffer[cursor++] = val >> 8;
76+
buffer[cursor++] = val;
77+
78+
return cursor;
79+
}
80+
81+
uint8_t CayenneLPP::addAnalogOutput(uint8_t channel, float value) {
82+
if ((cursor + LPP_ANALOG_OUTPUT_SIZE) > maxsize) {
83+
return 0;
84+
}
85+
int16_t val = value * 100;
86+
buffer[cursor++] = channel;
87+
buffer[cursor++] = LPP_ANALOG_OUTPUT;
88+
buffer[cursor++] = val >> 8;
89+
buffer[cursor++] = val;
90+
91+
return cursor;
92+
}
93+
94+
uint8_t CayenneLPP::addLuminosity(uint8_t channel, uint16_t lux) {
95+
if ((cursor + LPP_LUMINOSITY_SIZE) > maxsize) {
96+
return 0;
97+
}
98+
buffer[cursor++] = channel;
99+
buffer[cursor++] = LPP_LUMINOSITY;
100+
buffer[cursor++] = lux >> 8;
101+
buffer[cursor++] = lux;
102+
103+
return cursor;
104+
}
105+
106+
uint8_t CayenneLPP::addPresence(uint8_t channel, uint8_t value) {
107+
if ((cursor + LPP_PRESENCE_SIZE) > maxsize) {
108+
return 0;
109+
}
110+
buffer[cursor++] = channel;
111+
buffer[cursor++] = LPP_PRESENCE;
112+
buffer[cursor++] = value;
113+
114+
return cursor;
115+
}
116+
117+
uint8_t CayenneLPP::addTemperature(uint8_t channel, float celsius) {
118+
if ((cursor + LPP_TEMPERATURE_SIZE) > maxsize) {
119+
return 0;
120+
}
121+
int16_t val = celsius * 10;
122+
buffer[cursor++] = channel;
123+
buffer[cursor++] = LPP_TEMPERATURE;
124+
buffer[cursor++] = val >> 8;
125+
buffer[cursor++] = val;
126+
127+
return cursor;
128+
}
129+
130+
uint8_t CayenneLPP::addRelativeHumidity(uint8_t channel, float rh) {
131+
if ((cursor + LPP_RELATIVE_HUMIDITY_SIZE) > maxsize) {
132+
return 0;
133+
}
134+
buffer[cursor++] = channel;
135+
buffer[cursor++] = LPP_RELATIVE_HUMIDITY;
136+
buffer[cursor++] = rh * 2;
137+
138+
return cursor;
139+
}
140+
141+
uint8_t CayenneLPP::addAccelerometer(uint8_t channel, float x, float y, float z) {
142+
if ((cursor + LPP_ACCELEROMETER_SIZE) > maxsize) {
143+
return 0;
144+
}
145+
int16_t vx = x * 1000;
146+
int16_t vy = y * 1000;
147+
int16_t vz = z * 1000;
148+
149+
buffer[cursor++] = channel;
150+
buffer[cursor++] = LPP_ACCELEROMETER;
151+
buffer[cursor++] = vx >> 8;
152+
buffer[cursor++] = vx;
153+
buffer[cursor++] = vy >> 8;
154+
buffer[cursor++] = vy;
155+
buffer[cursor++] = vz >> 8;
156+
buffer[cursor++] = vz;
157+
158+
return cursor;
159+
}
160+
161+
uint8_t CayenneLPP::addBarometricPressure(uint8_t channel, float hpa) {
162+
if ((cursor + LPP_BAROMETRIC_PRESSURE_SIZE) > maxsize) {
163+
return 0;
164+
}
165+
int16_t val = hpa * 10;
166+
167+
buffer[cursor++] = channel;
168+
buffer[cursor++] = LPP_BAROMETRIC_PRESSURE;
169+
buffer[cursor++] = val >> 8;
170+
buffer[cursor++] = val;
171+
172+
return cursor;
173+
}
174+
175+
uint8_t CayenneLPP::addGyrometer(uint8_t channel, float x, float y, float z) {
176+
if ((cursor + LPP_GYROMETER_SIZE) > maxsize) {
177+
return 0;
178+
}
179+
int16_t vx = x * 100;
180+
int16_t vy = y * 100;
181+
int16_t vz = z * 100;
182+
183+
buffer[cursor++] = channel;
184+
buffer[cursor++] = LPP_GYROMETER;
185+
buffer[cursor++] = vx >> 8;
186+
buffer[cursor++] = vx;
187+
buffer[cursor++] = vy >> 8;
188+
buffer[cursor++] = vy;
189+
buffer[cursor++] = vz >> 8;
190+
buffer[cursor++] = vz;
191+
192+
return cursor;
193+
}
194+
195+
uint8_t CayenneLPP::addGPS(uint8_t channel, float latitude, float longitude, float meters) {
196+
if ((cursor + LPP_GPS_SIZE) > maxsize) {
197+
return 0;
198+
}
199+
int32_t lat = latitude * 10000;
200+
int32_t lon = longitude * 10000;
201+
int32_t alt = meters * 100;
202+
203+
buffer[cursor++] = channel;
204+
buffer[cursor++] = LPP_GPS;
205+
206+
buffer[cursor++] = lat >> 16;
207+
buffer[cursor++] = lat >> 8;
208+
buffer[cursor++] = lat;
209+
buffer[cursor++] = lon >> 16;
210+
buffer[cursor++] = lon >> 8;
211+
buffer[cursor++] = lon;
212+
buffer[cursor++] = alt >> 16;
213+
buffer[cursor++] = alt >> 8;
214+
buffer[cursor++] = alt;
215+
216+
return cursor;
217+
}
Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
/* SPDX-License-Identifier: GPL-3.0 */
2+
/*
3+
* The Cayenne Low Power Payload (LPP) provides a convenient and
4+
* easy way to send data over LPWAN networks such as LoRaWAN. The Cayenne LPP
5+
* is compliant with the payload size restriction, which can be lowered down to
6+
* 11 bytes, and allows the device to send multiple sensor data at one time.
7+
*
8+
* CayenneLPP is also support by TTN:
9+
* https://www.thethingsindustries.com/docs/integrations/payload-formatters/cayenne/
10+
*
11+
* This code is direct from: https://github.com/myDevicesIoT/CayenneLPP
12+
*
13+
* GPL-3.0 license, see `LICENSE.GPL`
14+
* See https://github.com/myDevicesIoT/CayenneLPP for license details
15+
*/
16+
17+
#ifndef _CAYENNE_LPP_H_
18+
#define _CAYENNE_LPP_H_
19+
20+
#include <cstdint>
21+
#include <stdlib.h>
22+
#include <cstring>
23+
24+
#define LPP_DIGITAL_INPUT 0 // 1 byte
25+
#define LPP_DIGITAL_OUTPUT 1 // 1 byte
26+
#define LPP_ANALOG_INPUT 2 // 2 bytes, 0.01 signed
27+
#define LPP_ANALOG_OUTPUT 3 // 2 bytes, 0.01 signed
28+
#define LPP_LUMINOSITY 101 // 2 bytes, 1 lux unsigned
29+
#define LPP_PRESENCE 102 // 1 byte, 1
30+
#define LPP_TEMPERATURE 103 // 2 bytes, 0.1°C signed
31+
#define LPP_RELATIVE_HUMIDITY 104 // 1 byte, 0.5% unsigned
32+
#define LPP_ACCELEROMETER 113 // 2 bytes per axis, 0.001G
33+
#define LPP_BAROMETRIC_PRESSURE 115 // 2 bytes 0.1 hPa Unsigned
34+
#define LPP_GYROMETER 134 // 2 bytes per axis, 0.01 °/s
35+
#define LPP_GPS 136 // 3 byte lon/lat 0.0001 °, 3 bytes alt 0.01 meter
36+
37+
38+
// Data ID + Data Type + Data Size
39+
#define LPP_DIGITAL_INPUT_SIZE 3 // 1 byte
40+
#define LPP_DIGITAL_OUTPUT_SIZE 3 // 1 byte
41+
#define LPP_ANALOG_INPUT_SIZE 4 // 2 bytes, 0.01 signed
42+
#define LPP_ANALOG_OUTPUT_SIZE 4 // 2 bytes, 0.01 signed
43+
#define LPP_LUMINOSITY_SIZE 4 // 2 bytes, 1 lux unsigned
44+
#define LPP_PRESENCE_SIZE 3 // 1 byte, 1
45+
#define LPP_TEMPERATURE_SIZE 4 // 2 bytes, 0.1°C signed
46+
#define LPP_RELATIVE_HUMIDITY_SIZE 3 // 1 byte, 0.5% unsigned
47+
#define LPP_ACCELEROMETER_SIZE 8 // 2 bytes per axis, 0.001G
48+
#define LPP_BAROMETRIC_PRESSURE_SIZE 4 // 2 bytes 0.1 hPa Unsigned
49+
#define LPP_GYROMETER_SIZE 8 // 2 bytes per axis, 0.01 °/s
50+
#define LPP_GPS_SIZE 11 // 3 byte lon/lat 0.0001 °, 3 bytes alt 0.01 meter
51+
52+
53+
class CayenneLPP {
54+
public:
55+
CayenneLPP(uint8_t size);
56+
~CayenneLPP();
57+
58+
void reset(void);
59+
uint8_t getSize(void);
60+
uint8_t* getBuffer(void);
61+
uint8_t copy(uint8_t* buffer);
62+
63+
uint8_t addDigitalInput(uint8_t channel, uint8_t value);
64+
uint8_t addDigitalOutput(uint8_t channel, uint8_t value);
65+
66+
uint8_t addAnalogInput(uint8_t channel, float value);
67+
uint8_t addAnalogOutput(uint8_t channel, float value);
68+
69+
uint8_t addLuminosity(uint8_t channel, uint16_t lux);
70+
uint8_t addPresence(uint8_t channel, uint8_t value);
71+
uint8_t addTemperature(uint8_t channel, float celsius);
72+
uint8_t addRelativeHumidity(uint8_t channel, float rh);
73+
uint8_t addAccelerometer(uint8_t channel, float x, float y, float z);
74+
uint8_t addBarometricPressure(uint8_t channel, float hpa);
75+
uint8_t addGyrometer(uint8_t channel, float x, float y, float z);
76+
uint8_t addGPS(uint8_t channel, float latitude, float longitude, float meters);
77+
78+
private:
79+
uint8_t *buffer;
80+
uint8_t maxsize;
81+
uint8_t cursor;
82+
};
83+
84+
85+
#endif

0 commit comments

Comments
 (0)