-
Notifications
You must be signed in to change notification settings - Fork 89
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
lora: sensor-lorawan: Initial commit
Signed-off-by: Alistair Francis <[email protected]>
- Loading branch information
1 parent
e0ddbe6
commit 1a6ee32
Showing
6 changed files
with
464 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,219 @@ | ||
/* | ||
* The Cayenne Low Power Payload (LPP) provides a convenient and | ||
* easy way to send data over LPWAN networks such as LoRaWAN. The Cayenne LPP | ||
* is compliant with the payload size restriction, which can be lowered down to | ||
* 11 bytes, and allows the device to send multiple sensor data at one time. | ||
* | ||
* CayenneLPP is also support by TTN: | ||
* https://www.thethingsindustries.com/docs/integrations/payload-formatters/cayenne/ | ||
* | ||
* This code is direct from: https://github.com/myDevicesIoT/CayenneLPP | ||
* | ||
* GPL-3.0 license | ||
* See https://github.com/myDevicesIoT/CayenneLPP for license details | ||
*/ | ||
|
||
#include "CayenneLPP.h" | ||
|
||
CayenneLPP::CayenneLPP(uint8_t size) : maxsize(size) { | ||
buffer = (uint8_t*) malloc(size); | ||
cursor = 0; | ||
} | ||
|
||
CayenneLPP::~CayenneLPP(void) { | ||
free(buffer); | ||
} | ||
|
||
void CayenneLPP::reset(void) { | ||
cursor = 0; | ||
} | ||
|
||
uint8_t CayenneLPP::getSize(void) { | ||
return cursor; | ||
} | ||
|
||
uint8_t* CayenneLPP::getBuffer(void) { | ||
// uint8_t[cursor] result; | ||
// memcpy(result, buffer, cursor); | ||
// return result; | ||
return buffer; | ||
} | ||
|
||
uint8_t CayenneLPP::copy(uint8_t* dst) { | ||
memcpy(dst, buffer, cursor); | ||
return cursor; | ||
} | ||
|
||
uint8_t CayenneLPP::addDigitalInput(uint8_t channel, uint8_t value) { | ||
if ((cursor + LPP_DIGITAL_INPUT_SIZE) > maxsize) { | ||
return 0; | ||
} | ||
buffer[cursor++] = channel; | ||
buffer[cursor++] = LPP_DIGITAL_INPUT; | ||
buffer[cursor++] = value; | ||
|
||
return cursor; | ||
} | ||
|
||
uint8_t CayenneLPP::addDigitalOutput(uint8_t channel, uint8_t value) { | ||
if ((cursor + LPP_DIGITAL_OUTPUT_SIZE) > maxsize) { | ||
return 0; | ||
} | ||
buffer[cursor++] = channel; | ||
buffer[cursor++] = LPP_DIGITAL_OUTPUT; | ||
buffer[cursor++] = value; | ||
|
||
return cursor; | ||
} | ||
|
||
uint8_t CayenneLPP::addAnalogInput(uint8_t channel, float value) { | ||
if ((cursor + LPP_ANALOG_INPUT_SIZE) > maxsize) { | ||
return 0; | ||
} | ||
|
||
int16_t val = value * 100; | ||
buffer[cursor++] = channel; | ||
buffer[cursor++] = LPP_ANALOG_INPUT; | ||
buffer[cursor++] = val >> 8; | ||
buffer[cursor++] = val; | ||
|
||
return cursor; | ||
} | ||
|
||
uint8_t CayenneLPP::addAnalogOutput(uint8_t channel, float value) { | ||
if ((cursor + LPP_ANALOG_OUTPUT_SIZE) > maxsize) { | ||
return 0; | ||
} | ||
int16_t val = value * 100; | ||
buffer[cursor++] = channel; | ||
buffer[cursor++] = LPP_ANALOG_OUTPUT; | ||
buffer[cursor++] = val >> 8; | ||
buffer[cursor++] = val; | ||
|
||
return cursor; | ||
} | ||
|
||
uint8_t CayenneLPP::addLuminosity(uint8_t channel, uint16_t lux) { | ||
if ((cursor + LPP_LUMINOSITY_SIZE) > maxsize) { | ||
return 0; | ||
} | ||
buffer[cursor++] = channel; | ||
buffer[cursor++] = LPP_LUMINOSITY; | ||
buffer[cursor++] = lux >> 8; | ||
buffer[cursor++] = lux; | ||
|
||
return cursor; | ||
} | ||
|
||
uint8_t CayenneLPP::addPresence(uint8_t channel, uint8_t value) { | ||
if ((cursor + LPP_PRESENCE_SIZE) > maxsize) { | ||
return 0; | ||
} | ||
buffer[cursor++] = channel; | ||
buffer[cursor++] = LPP_PRESENCE; | ||
buffer[cursor++] = value; | ||
|
||
return cursor; | ||
} | ||
|
||
uint8_t CayenneLPP::addTemperature(uint8_t channel, float celsius) { | ||
if ((cursor + LPP_TEMPERATURE_SIZE) > maxsize) { | ||
return 0; | ||
} | ||
int16_t val = celsius * 10; | ||
buffer[cursor++] = channel; | ||
buffer[cursor++] = LPP_TEMPERATURE; | ||
buffer[cursor++] = val >> 8; | ||
buffer[cursor++] = val; | ||
|
||
return cursor; | ||
} | ||
|
||
uint8_t CayenneLPP::addRelativeHumidity(uint8_t channel, float rh) { | ||
if ((cursor + LPP_RELATIVE_HUMIDITY_SIZE) > maxsize) { | ||
return 0; | ||
} | ||
buffer[cursor++] = channel; | ||
buffer[cursor++] = LPP_RELATIVE_HUMIDITY; | ||
buffer[cursor++] = rh * 2; | ||
|
||
return cursor; | ||
} | ||
|
||
uint8_t CayenneLPP::addAccelerometer(uint8_t channel, float x, float y, float z) { | ||
if ((cursor + LPP_ACCELEROMETER_SIZE) > maxsize) { | ||
return 0; | ||
} | ||
int16_t vx = x * 1000; | ||
int16_t vy = y * 1000; | ||
int16_t vz = z * 1000; | ||
|
||
buffer[cursor++] = channel; | ||
buffer[cursor++] = LPP_ACCELEROMETER; | ||
buffer[cursor++] = vx >> 8; | ||
buffer[cursor++] = vx; | ||
buffer[cursor++] = vy >> 8; | ||
buffer[cursor++] = vy; | ||
buffer[cursor++] = vz >> 8; | ||
buffer[cursor++] = vz; | ||
|
||
return cursor; | ||
} | ||
|
||
uint8_t CayenneLPP::addBarometricPressure(uint8_t channel, float hpa) { | ||
if ((cursor + LPP_BAROMETRIC_PRESSURE_SIZE) > maxsize) { | ||
return 0; | ||
} | ||
int16_t val = hpa * 10; | ||
|
||
buffer[cursor++] = channel; | ||
buffer[cursor++] = LPP_BAROMETRIC_PRESSURE; | ||
buffer[cursor++] = val >> 8; | ||
buffer[cursor++] = val; | ||
|
||
return cursor; | ||
} | ||
|
||
uint8_t CayenneLPP::addGyrometer(uint8_t channel, float x, float y, float z) { | ||
if ((cursor + LPP_GYROMETER_SIZE) > maxsize) { | ||
return 0; | ||
} | ||
int16_t vx = x * 100; | ||
int16_t vy = y * 100; | ||
int16_t vz = z * 100; | ||
|
||
buffer[cursor++] = channel; | ||
buffer[cursor++] = LPP_GYROMETER; | ||
buffer[cursor++] = vx >> 8; | ||
buffer[cursor++] = vx; | ||
buffer[cursor++] = vy >> 8; | ||
buffer[cursor++] = vy; | ||
buffer[cursor++] = vz >> 8; | ||
buffer[cursor++] = vz; | ||
|
||
return cursor; | ||
} | ||
|
||
uint8_t CayenneLPP::addGPS(uint8_t channel, float latitude, float longitude, float meters) { | ||
if ((cursor + LPP_GPS_SIZE) > maxsize) { | ||
return 0; | ||
} | ||
int32_t lat = latitude * 10000; | ||
int32_t lon = longitude * 10000; | ||
int32_t alt = meters * 100; | ||
|
||
buffer[cursor++] = channel; | ||
buffer[cursor++] = LPP_GPS; | ||
|
||
buffer[cursor++] = lat >> 16; | ||
buffer[cursor++] = lat >> 8; | ||
buffer[cursor++] = lat; | ||
buffer[cursor++] = lon >> 16; | ||
buffer[cursor++] = lon >> 8; | ||
buffer[cursor++] = lon; | ||
buffer[cursor++] = alt >> 16; | ||
buffer[cursor++] = alt >> 8; | ||
buffer[cursor++] = alt; | ||
|
||
return cursor; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,86 @@ | ||
/* | ||
* The Cayenne Low Power Payload (LPP) provides a convenient and | ||
* easy way to send data over LPWAN networks such as LoRaWAN. The Cayenne LPP | ||
* is compliant with the payload size restriction, which can be lowered down to | ||
* 11 bytes, and allows the device to send multiple sensor data at one time. | ||
* | ||
* CayenneLPP is also support by TTN: | ||
* https://www.thethingsindustries.com/docs/integrations/payload-formatters/cayenne/ | ||
* | ||
* This code is direct from: https://github.com/myDevicesIoT/CayenneLPP | ||
* | ||
* GPL-3.0 license | ||
* See https://github.com/myDevicesIoT/CayenneLPP for license details | ||
*/ | ||
|
||
#ifndef _CAYENNE_LPP_H_ | ||
#define _CAYENNE_LPP_H_ | ||
|
||
#include <cstdint> | ||
#include <stdlib.h> | ||
#include <cstring> | ||
|
||
#define LPP_DIGITAL_INPUT 0 // 1 byte | ||
#define LPP_DIGITAL_OUTPUT 1 // 1 byte | ||
#define LPP_ANALOG_INPUT 2 // 2 bytes, 0.01 signed | ||
#define LPP_ANALOG_OUTPUT 3 // 2 bytes, 0.01 signed | ||
#define LPP_LUMINOSITY 101 // 2 bytes, 1 lux unsigned | ||
#define LPP_PRESENCE 102 // 1 byte, 1 | ||
#define LPP_TEMPERATURE 103 // 2 bytes, 0.1°C signed | ||
#define LPP_RELATIVE_HUMIDITY 104 // 1 byte, 0.5% unsigned | ||
#define LPP_ACCELEROMETER 113 // 2 bytes per axis, 0.001G | ||
#define LPP_BAROMETRIC_PRESSURE 115 // 2 bytes 0.1 hPa Unsigned | ||
#define LPP_GYROMETER 134 // 2 bytes per axis, 0.01 °/s | ||
#define LPP_GPS 136 // 3 byte lon/lat 0.0001 °, 3 bytes alt 0.01 meter | ||
|
||
|
||
// Data ID + Data Type + Data Size | ||
#define LPP_DIGITAL_INPUT_SIZE 3 // 1 byte | ||
#define LPP_DIGITAL_OUTPUT_SIZE 3 // 1 byte | ||
#define LPP_ANALOG_INPUT_SIZE 4 // 2 bytes, 0.01 signed | ||
#define LPP_ANALOG_OUTPUT_SIZE 4 // 2 bytes, 0.01 signed | ||
#define LPP_LUMINOSITY_SIZE 4 // 2 bytes, 1 lux unsigned | ||
#define LPP_PRESENCE_SIZE 3 // 1 byte, 1 | ||
#define LPP_TEMPERATURE_SIZE 4 // 2 bytes, 0.1°C signed | ||
#define LPP_RELATIVE_HUMIDITY_SIZE 3 // 1 byte, 0.5% unsigned | ||
#define LPP_ACCELEROMETER_SIZE 8 // 2 bytes per axis, 0.001G | ||
#define LPP_BAROMETRIC_PRESSURE_SIZE 4 // 2 bytes 0.1 hPa Unsigned | ||
#define LPP_GYROMETER_SIZE 8 // 2 bytes per axis, 0.01 °/s | ||
#define LPP_GPS_SIZE 11 // 3 byte lon/lat 0.0001 °, 3 bytes alt 0.01 meter | ||
|
||
|
||
class CayenneLPP { | ||
public: | ||
CayenneLPP(uint8_t size); | ||
~CayenneLPP(); | ||
|
||
void reset(void); | ||
uint8_t getSize(void); | ||
uint8_t* getBuffer(void); | ||
uint8_t copy(uint8_t* buffer); | ||
|
||
uint8_t addDigitalInput(uint8_t channel, uint8_t value); | ||
uint8_t addDigitalOutput(uint8_t channel, uint8_t value); | ||
|
||
uint8_t addAnalogInput(uint8_t channel, float value); | ||
uint8_t addAnalogOutput(uint8_t channel, float value); | ||
|
||
uint8_t addLuminosity(uint8_t channel, uint16_t lux); | ||
uint8_t addPresence(uint8_t channel, uint8_t value); | ||
uint8_t addTemperature(uint8_t channel, float celsius); | ||
uint8_t addRelativeHumidity(uint8_t channel, float rh); | ||
uint8_t addAccelerometer(uint8_t channel, float x, float y, float z); | ||
uint8_t addBarometricPressure(uint8_t channel, float hpa); | ||
uint8_t addGyrometer(uint8_t channel, float x, float y, float z); | ||
uint8_t addGPS(uint8_t channel, float latitude, float longitude, float meters); | ||
|
||
private: | ||
uint8_t *buffer; | ||
uint8_t maxsize; | ||
uint8_t cursor; | ||
|
||
|
||
}; | ||
|
||
|
||
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
# Makefile for user application | ||
|
||
# Specify this directory relative to the current application. | ||
TOCK_USERLAND_BASE_DIR = ../../../ | ||
|
||
STACK_SIZE = 4096 | ||
|
||
# Which files to compile. | ||
CXX_SRCS := $(wildcard *.cc) | ||
|
||
# Include the core RadioLib headers | ||
override CPPFLAGS += -isystem $(TOCK_USERLAND_BASE_DIR)/libradio/RadioLib/src | ||
|
||
# Include the Tock specific headers | ||
override CPPFLAGS += -isystem $(TOCK_USERLAND_BASE_DIR)/libradio/RadioLib/examples/NonArduino/Tock | ||
|
||
# Include the base of libtock-c to fix the libtock/ includes from RadioLib | ||
override CPPFLAGS += -I$(TOCK_USERLAND_BASE_DIR)/ -DRADIOLIB_CLOCK_DRIFT_MS=9 | ||
|
||
# Use the libtock-c Make system | ||
LIBS_cortex-m0 += $(TOCK_USERLAND_BASE_DIR)/libradio/RadioLib/build/cortex-m0/RadioLib.a | ||
LIBS_cortex-m3 += $(TOCK_USERLAND_BASE_DIR)/libradio/RadioLib/build/cortex-m3/RadioLib.a | ||
LIBS_cortex-m4 += $(TOCK_USERLAND_BASE_DIR)/libradio/RadioLib/build/cortex-m4/RadioLib.a | ||
LIBS_cortex-m7 += $(TOCK_USERLAND_BASE_DIR)/libradio/RadioLib/build/cortex-m7/RadioLib.a | ||
|
||
LIBS_rv32imc += $(TOCK_USERLAND_BASE_DIR)/libradio/RadioLib/build/rv32imc/RadioLib.a | ||
LIBS_rv32imac += $(TOCK_USERLAND_BASE_DIR)/libradio/RadioLib/build/rv32imac/RadioLib.a | ||
|
||
EXTERN_LIBS := $(TOCK_USERLAND_BASE_DIR)/libradio/RadioLib | ||
include $(TOCK_USERLAND_BASE_DIR)/libradio/Makefile | ||
|
||
include $(TOCK_USERLAND_BASE_DIR)/AppMakefile.mk |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
Sensor LoRaWAN Transmitter | ||
========================== | ||
|
||
This example builds an application to transmit sensor data via LoRaWAN. | ||
|
||
See https://github.com/jgromes/RadioLib/blob/master/examples/LoRaWAN/LoRaWAN_Starter/notes.md | ||
for notes on setting up the LoRaWAN device. The most important part is modifying | ||
main.cc with the secrets from your LoRaWAN server and any country specific | ||
settings. | ||
|
||
This has been tested against The Things Network. Before changing settings | ||
make sure you consider regulatory duty cycles and TTN's Fair Usage Policy, | ||
for example don't drop the delay in the loop, otherwise you will break the | ||
TTN Fair Usage Policy. |
Oops, something went wrong.