Skip to content

Commit 55bb231

Browse files
committed
lora: sensor-lorawan: Initial commit
Signed-off-by: Alistair Francis <[email protected]>
1 parent b17e1a9 commit 55bb231

File tree

9 files changed

+1141
-1
lines changed

9 files changed

+1141
-1
lines changed

.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
11
build/
22
.vscode/
3+
examples/lora/sensor-lorawan/radioConfig.h

RadioLib/RadioLib

Submodule RadioLib updated 147 files
+220
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,220 @@
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+
// uint8_t[cursor] result;
38+
// memcpy(result, buffer, cursor);
39+
// return result;
40+
return buffer;
41+
}
42+
43+
uint8_t CayenneLPP::copy(uint8_t* dst) {
44+
memcpy(dst, buffer, cursor);
45+
return cursor;
46+
}
47+
48+
uint8_t CayenneLPP::addDigitalInput(uint8_t channel, uint8_t value) {
49+
if ((cursor + LPP_DIGITAL_INPUT_SIZE) > maxsize) {
50+
return 0;
51+
}
52+
buffer[cursor++] = channel;
53+
buffer[cursor++] = LPP_DIGITAL_INPUT;
54+
buffer[cursor++] = value;
55+
56+
return cursor;
57+
}
58+
59+
uint8_t CayenneLPP::addDigitalOutput(uint8_t channel, uint8_t value) {
60+
if ((cursor + LPP_DIGITAL_OUTPUT_SIZE) > maxsize) {
61+
return 0;
62+
}
63+
buffer[cursor++] = channel;
64+
buffer[cursor++] = LPP_DIGITAL_OUTPUT;
65+
buffer[cursor++] = value;
66+
67+
return cursor;
68+
}
69+
70+
uint8_t CayenneLPP::addAnalogInput(uint8_t channel, float value) {
71+
if ((cursor + LPP_ANALOG_INPUT_SIZE) > maxsize) {
72+
return 0;
73+
}
74+
75+
int16_t val = value * 100;
76+
buffer[cursor++] = channel;
77+
buffer[cursor++] = LPP_ANALOG_INPUT;
78+
buffer[cursor++] = val >> 8;
79+
buffer[cursor++] = val;
80+
81+
return cursor;
82+
}
83+
84+
uint8_t CayenneLPP::addAnalogOutput(uint8_t channel, float value) {
85+
if ((cursor + LPP_ANALOG_OUTPUT_SIZE) > maxsize) {
86+
return 0;
87+
}
88+
int16_t val = value * 100;
89+
buffer[cursor++] = channel;
90+
buffer[cursor++] = LPP_ANALOG_OUTPUT;
91+
buffer[cursor++] = val >> 8;
92+
buffer[cursor++] = val;
93+
94+
return cursor;
95+
}
96+
97+
uint8_t CayenneLPP::addLuminosity(uint8_t channel, uint16_t lux) {
98+
if ((cursor + LPP_LUMINOSITY_SIZE) > maxsize) {
99+
return 0;
100+
}
101+
buffer[cursor++] = channel;
102+
buffer[cursor++] = LPP_LUMINOSITY;
103+
buffer[cursor++] = lux >> 8;
104+
buffer[cursor++] = lux;
105+
106+
return cursor;
107+
}
108+
109+
uint8_t CayenneLPP::addPresence(uint8_t channel, uint8_t value) {
110+
if ((cursor + LPP_PRESENCE_SIZE) > maxsize) {
111+
return 0;
112+
}
113+
buffer[cursor++] = channel;
114+
buffer[cursor++] = LPP_PRESENCE;
115+
buffer[cursor++] = value;
116+
117+
return cursor;
118+
}
119+
120+
uint8_t CayenneLPP::addTemperature(uint8_t channel, float celsius) {
121+
if ((cursor + LPP_TEMPERATURE_SIZE) > maxsize) {
122+
return 0;
123+
}
124+
int16_t val = celsius * 10;
125+
buffer[cursor++] = channel;
126+
buffer[cursor++] = LPP_TEMPERATURE;
127+
buffer[cursor++] = val >> 8;
128+
buffer[cursor++] = val;
129+
130+
return cursor;
131+
}
132+
133+
uint8_t CayenneLPP::addRelativeHumidity(uint8_t channel, float rh) {
134+
if ((cursor + LPP_RELATIVE_HUMIDITY_SIZE) > maxsize) {
135+
return 0;
136+
}
137+
buffer[cursor++] = channel;
138+
buffer[cursor++] = LPP_RELATIVE_HUMIDITY;
139+
buffer[cursor++] = rh * 2;
140+
141+
return cursor;
142+
}
143+
144+
uint8_t CayenneLPP::addAccelerometer(uint8_t channel, float x, float y, float z) {
145+
if ((cursor + LPP_ACCELEROMETER_SIZE) > maxsize) {
146+
return 0;
147+
}
148+
int16_t vx = x * 1000;
149+
int16_t vy = y * 1000;
150+
int16_t vz = z * 1000;
151+
152+
buffer[cursor++] = channel;
153+
buffer[cursor++] = LPP_ACCELEROMETER;
154+
buffer[cursor++] = vx >> 8;
155+
buffer[cursor++] = vx;
156+
buffer[cursor++] = vy >> 8;
157+
buffer[cursor++] = vy;
158+
buffer[cursor++] = vz >> 8;
159+
buffer[cursor++] = vz;
160+
161+
return cursor;
162+
}
163+
164+
uint8_t CayenneLPP::addBarometricPressure(uint8_t channel, float hpa) {
165+
if ((cursor + LPP_BAROMETRIC_PRESSURE_SIZE) > maxsize) {
166+
return 0;
167+
}
168+
int16_t val = hpa * 10;
169+
170+
buffer[cursor++] = channel;
171+
buffer[cursor++] = LPP_BAROMETRIC_PRESSURE;
172+
buffer[cursor++] = val >> 8;
173+
buffer[cursor++] = val;
174+
175+
return cursor;
176+
}
177+
178+
uint8_t CayenneLPP::addGyrometer(uint8_t channel, float x, float y, float z) {
179+
if ((cursor + LPP_GYROMETER_SIZE) > maxsize) {
180+
return 0;
181+
}
182+
int16_t vx = x * 100;
183+
int16_t vy = y * 100;
184+
int16_t vz = z * 100;
185+
186+
buffer[cursor++] = channel;
187+
buffer[cursor++] = LPP_GYROMETER;
188+
buffer[cursor++] = vx >> 8;
189+
buffer[cursor++] = vx;
190+
buffer[cursor++] = vy >> 8;
191+
buffer[cursor++] = vy;
192+
buffer[cursor++] = vz >> 8;
193+
buffer[cursor++] = vz;
194+
195+
return cursor;
196+
}
197+
198+
uint8_t CayenneLPP::addGPS(uint8_t channel, float latitude, float longitude, float meters) {
199+
if ((cursor + LPP_GPS_SIZE) > maxsize) {
200+
return 0;
201+
}
202+
int32_t lat = latitude * 10000;
203+
int32_t lon = longitude * 10000;
204+
int32_t alt = meters * 100;
205+
206+
buffer[cursor++] = channel;
207+
buffer[cursor++] = LPP_GPS;
208+
209+
buffer[cursor++] = lat >> 16;
210+
buffer[cursor++] = lat >> 8;
211+
buffer[cursor++] = lat;
212+
buffer[cursor++] = lon >> 16;
213+
buffer[cursor++] = lon >> 8;
214+
buffer[cursor++] = lon;
215+
buffer[cursor++] = alt >> 16;
216+
buffer[cursor++] = alt >> 8;
217+
buffer[cursor++] = alt;
218+
219+
return cursor;
220+
}
+85
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)