O7/LoRaWAN/App/CayenneLpp.c

400 lines
12 KiB
C

/*!
* @file CayenneLpp.c
*
* @brief Implements the Cayenne Low Power Protocol
*
* \copyright Revised BSD License, see section \ref LICENSE.
*
* \code
* ______ _
* / _____) _ | |
* ( (____ _____ ____ _| |_ _____ ____| |__
* \____ \| ___ | (_ _) ___ |/ ___) _ \
* _____) ) ____| | | || |_| ____( (___| | | |
* (______/|_____)_|_|_| \__)_____)\____)_| |_|
* (C)2013-2018 Semtech
*
* \endcode
*
* \author Miguel Luis ( Semtech )
*/
/* Includes ------------------------------------------------------------------*/
#include "stm32_mem.h"
#include "CayenneLpp.h"
/* USER CODE BEGIN Includes */
/* USER CODE END Includes */
/* External variables ---------------------------------------------------------*/
/* USER CODE BEGIN EV */
/* USER CODE END EV */
/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */
/* USER CODE END PTD */
/* Private define ------------------------------------------------------------*/
#define CAYENNE_LPP_MAXBUFFER_SIZE 242
#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 Celsius degrees 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 degrees/s */
#define LPP_GPS 136 /* 3 byte lon/lat 0.0001 degrees, 3 bytes alt 0.01m */
/* Data ID + Data Type + Data Size */
#define LPP_DIGITAL_INPUT_SIZE 3
#define LPP_DIGITAL_OUTPUT_SIZE 3
#define LPP_ANALOG_INPUT_SIZE 4
#define LPP_ANALOG_OUTPUT_SIZE 4
#define LPP_LUMINOSITY_SIZE 4
#define LPP_PRESENCE_SIZE 3
#define LPP_TEMPERATURE_SIZE 4
#define LPP_RELATIVE_HUMIDITY_SIZE 3
#define LPP_ACCELEROMETER_SIZE 8
#define LPP_BAROMETRIC_PRESSURE_SIZE 4
#define LPP_GYROMETER_SIZE 8
#define LPP_GPS_SIZE 11
/* USER CODE BEGIN PD */
/* USER CODE END PD */
/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */
/* USER CODE END PM */
/* Private variables ---------------------------------------------------------*/
static uint8_t CayenneLppBuffer[CAYENNE_LPP_MAXBUFFER_SIZE];
static uint8_t CayenneLppCursor = 0;
/* USER CODE BEGIN PV */
/* USER CODE END PV */
/* Private function prototypes -----------------------------------------------*/
/* USER CODE BEGIN PFP */
/* USER CODE END PFP */
/* Exported functions --------------------------------------------------------*/
void CayenneLppInit(void)
{
CayenneLppCursor = 0;
/* USER CODE BEGIN CayenneLppCursor */
/* USER CODE END CayenneLppCursor */
}
void CayenneLppReset(void)
{
CayenneLppCursor = 0;
/* USER CODE BEGIN CayenneLppReset */
/* USER CODE END CayenneLppReset */
}
uint8_t CayenneLppGetSize(void)
{
/* USER CODE BEGIN CayenneLppGetSize */
/* USER CODE END CayenneLppGetSize */
return CayenneLppCursor;
}
uint8_t *CayenneLppGetBuffer(void)
{
/* USER CODE BEGIN CayenneLppGetBuffer */
/* USER CODE END CayenneLppGetBuffer */
return CayenneLppBuffer;
}
uint8_t CayenneLppCopy(uint8_t *dst)
{
/* USER CODE BEGIN CayenneLppCopy_1 */
/* USER CODE END CayenneLppCopy_1 */
UTIL_MEM_cpy_8(dst, CayenneLppBuffer, CayenneLppCursor);
/* USER CODE BEGIN CayenneLppCopy_2 */
/* USER CODE END CayenneLppCopy_2 */
return CayenneLppCursor;
}
uint8_t CayenneLppAddDigitalInput(uint8_t channel, uint8_t value)
{
/* USER CODE BEGIN CayenneLppAddDigitalInput_1 */
/* USER CODE END CayenneLppAddDigitalInput_1 */
if ((CayenneLppCursor + LPP_DIGITAL_INPUT_SIZE) > CAYENNE_LPP_MAXBUFFER_SIZE)
{
return 0;
}
CayenneLppBuffer[CayenneLppCursor++] = channel;
CayenneLppBuffer[CayenneLppCursor++] = LPP_DIGITAL_INPUT;
CayenneLppBuffer[CayenneLppCursor++] = value;
/* USER CODE BEGIN CayenneLppAddDigitalInput_2 */
/* USER CODE END CayenneLppAddDigitalInput_2 */
return CayenneLppCursor;
}
uint8_t CayenneLppAddDigitalOutput(uint8_t channel, uint8_t value)
{
/* USER CODE BEGIN CayenneLppAddDigitalOutput_1 */
/* USER CODE END CayenneLppAddDigitalOutput_1 */
if ((CayenneLppCursor + LPP_DIGITAL_OUTPUT_SIZE) > CAYENNE_LPP_MAXBUFFER_SIZE)
{
return 0;
}
CayenneLppBuffer[CayenneLppCursor++] = channel;
CayenneLppBuffer[CayenneLppCursor++] = LPP_DIGITAL_OUTPUT;
CayenneLppBuffer[CayenneLppCursor++] = value;
/* USER CODE BEGIN CayenneLppAddDigitalOutput_2 */
/* USER CODE END CayenneLppAddDigitalOutput_2 */
return CayenneLppCursor;
}
uint8_t CayenneLppAddAnalogInput(uint8_t channel, float value)
{
/* USER CODE BEGIN CayenneLppAddAnalogInput_1 */
/* USER CODE END CayenneLppAddAnalogInput_1 */
if ((CayenneLppCursor + LPP_ANALOG_INPUT_SIZE) > CAYENNE_LPP_MAXBUFFER_SIZE)
{
return 0;
}
int16_t val = (int16_t)(value * 100);
CayenneLppBuffer[CayenneLppCursor++] = channel;
CayenneLppBuffer[CayenneLppCursor++] = LPP_ANALOG_INPUT;
CayenneLppBuffer[CayenneLppCursor++] = val >> 8;
CayenneLppBuffer[CayenneLppCursor++] = val;
/* USER CODE BEGIN CayenneLppAddAnalogInput_2 */
/* USER CODE END CayenneLppAddAnalogInput_2 */
return CayenneLppCursor;
}
uint8_t CayenneLppAddAnalogOutput(uint8_t channel, float value)
{
/* USER CODE BEGIN CayenneLppAddAnalogOutput_1 */
/* USER CODE END CayenneLppAddAnalogOutput_1 */
if ((CayenneLppCursor + LPP_ANALOG_OUTPUT_SIZE) > CAYENNE_LPP_MAXBUFFER_SIZE)
{
return 0;
}
int16_t val = (int16_t)(value * 100);
CayenneLppBuffer[CayenneLppCursor++] = channel;
CayenneLppBuffer[CayenneLppCursor++] = LPP_ANALOG_OUTPUT;
CayenneLppBuffer[CayenneLppCursor++] = val >> 8;
CayenneLppBuffer[CayenneLppCursor++] = val;
/* USER CODE BEGIN CayenneLppAddAnalogOutput_2 */
/* USER CODE END CayenneLppAddAnalogOutput_2 */
return CayenneLppCursor;
}
uint8_t CayenneLppAddLuminosity(uint8_t channel, uint16_t lux)
{
/* USER CODE BEGIN CayenneLppAddLuminosity_1 */
/* USER CODE END CayenneLppAddLuminosity_1 */
if ((CayenneLppCursor + LPP_LUMINOSITY_SIZE) > CAYENNE_LPP_MAXBUFFER_SIZE)
{
return 0;
}
CayenneLppBuffer[CayenneLppCursor++] = channel;
CayenneLppBuffer[CayenneLppCursor++] = LPP_LUMINOSITY;
CayenneLppBuffer[CayenneLppCursor++] = lux >> 8;
CayenneLppBuffer[CayenneLppCursor++] = lux;
/* USER CODE BEGIN CayenneLppAddLuminosity_2 */
/* USER CODE END CayenneLppAddLuminosity_2 */
return CayenneLppCursor;
}
uint8_t CayenneLppAddPresence(uint8_t channel, uint8_t value)
{
/* USER CODE BEGIN CayenneLppAddPresence_1 */
/* USER CODE END CayenneLppAddPresence_1 */
if ((CayenneLppCursor + LPP_PRESENCE_SIZE) > CAYENNE_LPP_MAXBUFFER_SIZE)
{
return 0;
}
CayenneLppBuffer[CayenneLppCursor++] = channel;
CayenneLppBuffer[CayenneLppCursor++] = LPP_PRESENCE;
CayenneLppBuffer[CayenneLppCursor++] = value;
/* USER CODE BEGIN CayenneLppAddPresence_2 */
/* USER CODE END CayenneLppAddPresence_2 */
return CayenneLppCursor;
}
uint8_t CayenneLppAddTemperature(uint8_t channel, float celsius)
{
/* USER CODE BEGIN CayenneLppAddTemperature_1 */
/* USER CODE END CayenneLppAddTemperature_1 */
if ((CayenneLppCursor + LPP_TEMPERATURE_SIZE) > CAYENNE_LPP_MAXBUFFER_SIZE)
{
return 0;
}
int16_t val = (int16_t)(celsius * 10);
CayenneLppBuffer[CayenneLppCursor++] = channel;
CayenneLppBuffer[CayenneLppCursor++] = LPP_TEMPERATURE;
CayenneLppBuffer[CayenneLppCursor++] = val >> 8;
CayenneLppBuffer[CayenneLppCursor++] = val;
/* USER CODE BEGIN CayenneLppAddTemperature_2 */
/* USER CODE END CayenneLppAddTemperature_2 */
return CayenneLppCursor;
}
uint8_t CayenneLppAddRelativeHumidity(uint8_t channel, float rh)
{
/* USER CODE BEGIN CayenneLppAddRelativeHumidity_1 */
/* USER CODE END CayenneLppAddRelativeHumidity_1 */
if ((CayenneLppCursor + LPP_RELATIVE_HUMIDITY_SIZE) > CAYENNE_LPP_MAXBUFFER_SIZE)
{
return 0;
}
CayenneLppBuffer[CayenneLppCursor++] = channel;
CayenneLppBuffer[CayenneLppCursor++] = LPP_RELATIVE_HUMIDITY;
CayenneLppBuffer[CayenneLppCursor++] = (uint8_t)(rh * 2);
/* USER CODE BEGIN CayenneLppAddRelativeHumidity_2 */
/* USER CODE END CayenneLppAddRelativeHumidity_2 */
return CayenneLppCursor;
}
uint8_t CayenneLppAddAccelerometer(uint8_t channel, float x, float y, float z)
{
/* USER CODE BEGIN CayenneLppAddAccelerometer_1 */
/* USER CODE END CayenneLppAddAccelerometer_1 */
if ((CayenneLppCursor + LPP_ACCELEROMETER_SIZE) > CAYENNE_LPP_MAXBUFFER_SIZE)
{
return 0;
}
int16_t vx = (int16_t)(x * 1000);
int16_t vy = (int16_t)(y * 1000);
int16_t vz = (int16_t)(z * 1000);
CayenneLppBuffer[CayenneLppCursor++] = channel;
CayenneLppBuffer[CayenneLppCursor++] = LPP_ACCELEROMETER;
CayenneLppBuffer[CayenneLppCursor++] = vx >> 8;
CayenneLppBuffer[CayenneLppCursor++] = vx;
CayenneLppBuffer[CayenneLppCursor++] = vy >> 8;
CayenneLppBuffer[CayenneLppCursor++] = vy;
CayenneLppBuffer[CayenneLppCursor++] = vz >> 8;
CayenneLppBuffer[CayenneLppCursor++] = vz;
/* USER CODE BEGIN CayenneLppAddAccelerometer_2 */
/* USER CODE END CayenneLppAddAccelerometer_2 */
return CayenneLppCursor;
}
uint8_t CayenneLppAddBarometricPressure(uint8_t channel, float hpa)
{
/* USER CODE BEGIN CayenneLppAddBarometricPressure_1 */
/* USER CODE END CayenneLppAddBarometricPressure_1 */
if ((CayenneLppCursor + LPP_BAROMETRIC_PRESSURE_SIZE) > CAYENNE_LPP_MAXBUFFER_SIZE)
{
return 0;
}
int16_t val = (int16_t)(hpa * 10);
CayenneLppBuffer[CayenneLppCursor++] = channel;
CayenneLppBuffer[CayenneLppCursor++] = LPP_BAROMETRIC_PRESSURE;
CayenneLppBuffer[CayenneLppCursor++] = val >> 8;
CayenneLppBuffer[CayenneLppCursor++] = val;
/* USER CODE BEGIN CayenneLppAddBarometricPressure_2 */
/* USER CODE END CayenneLppAddBarometricPressure_2 */
return CayenneLppCursor;
}
uint8_t CayenneLppAddGyrometer(uint8_t channel, float x, float y, float z)
{
/* USER CODE BEGIN CayenneLppAddGyrometer_1 */
/* USER CODE END CayenneLppAddGyrometer_1 */
if ((CayenneLppCursor + LPP_GYROMETER_SIZE) > CAYENNE_LPP_MAXBUFFER_SIZE)
{
return 0;
}
int16_t vx = (int16_t)(x * 100);
int16_t vy = (int16_t)(y * 100);
int16_t vz = (int16_t)(z * 100);
CayenneLppBuffer[CayenneLppCursor++] = channel;
CayenneLppBuffer[CayenneLppCursor++] = LPP_GYROMETER;
CayenneLppBuffer[CayenneLppCursor++] = vx >> 8;
CayenneLppBuffer[CayenneLppCursor++] = vx;
CayenneLppBuffer[CayenneLppCursor++] = vy >> 8;
CayenneLppBuffer[CayenneLppCursor++] = vy;
CayenneLppBuffer[CayenneLppCursor++] = vz >> 8;
CayenneLppBuffer[CayenneLppCursor++] = vz;
/* USER CODE BEGIN CayenneLppAddGyrometer_2 */
/* USER CODE END CayenneLppAddGyrometer_2 */
return CayenneLppCursor;
}
uint8_t CayenneLppAddGps(uint8_t channel, float latitude, float longitude, float meters)
{
/* USER CODE BEGIN CayenneLppAddGps_1 */
/* USER CODE END CayenneLppAddGps_1 */
if ((CayenneLppCursor + LPP_GPS_SIZE) > CAYENNE_LPP_MAXBUFFER_SIZE)
{
return 0;
}
int32_t lat = (int32_t)(latitude * 10000);
int32_t lon = (int32_t)(longitude * 10000);
int32_t alt = (int32_t)(meters * 100);
CayenneLppBuffer[CayenneLppCursor++] = channel;
CayenneLppBuffer[CayenneLppCursor++] = LPP_GPS;
CayenneLppBuffer[CayenneLppCursor++] = lat >> 16;
CayenneLppBuffer[CayenneLppCursor++] = lat >> 8;
CayenneLppBuffer[CayenneLppCursor++] = lat;
CayenneLppBuffer[CayenneLppCursor++] = lon >> 16;
CayenneLppBuffer[CayenneLppCursor++] = lon >> 8;
CayenneLppBuffer[CayenneLppCursor++] = lon;
CayenneLppBuffer[CayenneLppCursor++] = alt >> 16;
CayenneLppBuffer[CayenneLppCursor++] = alt >> 8;
CayenneLppBuffer[CayenneLppCursor++] = alt;
/* USER CODE BEGIN CayenneLppAddGps_2 */
/* USER CODE END CayenneLppAddGps_2 */
return CayenneLppCursor;
}
/* USER CODE BEGIN EF */
/* USER CODE END EF */
/* Private Functions Definition -----------------------------------------------*/
/* USER CODE BEGIN PrFD */
/* USER CODE END PrFD */