ESP32-PaxCounter/src/payload.cpp
2018-07-21 17:14:27 +02:00

251 lines
7.3 KiB
C++

#include "globals.h"
#include "payload.h"
PayloadConvert::PayloadConvert(uint8_t size) {
buffer = (uint8_t *)malloc(size);
cursor = 0;
}
PayloadConvert::~PayloadConvert(void) { free(buffer); }
void PayloadConvert::reset(void) { cursor = 0; }
uint8_t PayloadConvert::getSize(void) { return cursor; }
uint8_t *PayloadConvert::getBuffer(void) { return buffer; }
/* ---------------- plain format without special encoding ---------- */
#if PAYLOAD_ENCODER == 1
void PayloadConvert::addCount(uint16_t value1, uint16_t value2) {
buffer[cursor++] = value1 >> 8;
buffer[cursor++] = value1;
buffer[cursor++] = value2 >> 8;
buffer[cursor++] = value2;
}
#ifdef HAS_GPS
void PayloadConvert::addGPS(gpsStatus_t value) {
buffer[cursor++] = value.latitude >> 24;
buffer[cursor++] = value.latitude >> 16;
buffer[cursor++] = value.latitude >> 8;
buffer[cursor++] = value.latitude;
buffer[cursor++] = value.longitude >> 24;
buffer[cursor++] = value.longitude >> 16;
buffer[cursor++] = value.longitude >> 8;
buffer[cursor++] = value.longitude;
buffer[cursor++] = value.satellites;
buffer[cursor++] = value.hdop >> 8;
buffer[cursor++] = value.hdop;
buffer[cursor++] = value.altitude >> 8;
buffer[cursor++] = value.altitude;
}
#endif
void PayloadConvert::addConfig(configData_t value) {
buffer[cursor++] = value.lorasf;
buffer[cursor++] = value.txpower;
buffer[cursor++] = value.adrmode;
buffer[cursor++] = value.screensaver;
buffer[cursor++] = value.screenon;
buffer[cursor++] = value.countermode;
buffer[cursor++] = value.rssilimit >> 8;
buffer[cursor++] = value.rssilimit;
buffer[cursor++] = value.sendcycle;
buffer[cursor++] = value.wifichancycle;
buffer[cursor++] = value.blescantime;
buffer[cursor++] = value.blescan;
buffer[cursor++] = value.wifiant;
buffer[cursor++] = value.vendorfilter;
buffer[cursor++] = value.rgblum;
buffer[cursor++] = value.gpsmode;
memcpy(buffer + cursor, value.version, 10);
cursor += 10;
}
void PayloadConvert::addStatus(uint16_t voltage, uint64_t uptime,
float cputemp) {
buffer[cursor++] = voltage >> 8;
buffer[cursor++] = voltage;
buffer[cursor++] = uptime >> 56;
buffer[cursor++] = uptime >> 48;
buffer[cursor++] = uptime >> 40;
buffer[cursor++] = uptime >> 32;
buffer[cursor++] = uptime >> 24;
buffer[cursor++] = uptime >> 16;
buffer[cursor++] = uptime >> 8;
buffer[cursor++] = uptime;
buffer[cursor++] = (uint32_t)cputemp >> 24;
buffer[cursor++] = (uint32_t)cputemp >> 16;
buffer[cursor++] = (uint32_t)cputemp >> 8;
buffer[cursor++] = (uint32_t)cputemp;
}
/* ---------------- packed format with LoRa serialization Encoder ---------- */
// derived from
// https://github.com/thesolarnomad/lora-serialization/blob/master/src/LoraEncoder.cpp
#elif PAYLOAD_ENCODER == 2
void PayloadConvert::addCount(uint16_t value1, uint16_t value2) {
writeUint16(value1);
writeUint16(value2);
}
#ifdef HAS_GPS
void PayloadConvert::addGPS(gpsStatus_t value) {
writeLatLng(value.latitude, value.longitude);
writeUint8(value.satellites);
writeUint16(value.hdop);
writeUint16(value.altitude);
}
#endif
void PayloadConvert::addConfig(configData_t value) {
writeUint8(value.lorasf);
writeUint8(value.txpower);
writeUint16(value.rssilimit);
writeUint8(value.sendcycle);
writeUint8(value.wifichancycle);
writeUint8(value.blescantime);
writeUint8(value.rgblum);
writeBitmap(value.adrmode ? true : false, value.screensaver ? true : false,
value.screenon ? true : false, value.countermode ? true : false,
value.blescan ? true : false, value.wifiant ? true : false,
value.vendorfilter ? true : false, value.gpsmode ? true : false);
}
void PayloadConvert::addStatus(uint16_t voltage, uint64_t uptime,
float cputemp) {
writeUint16(voltage);
writeUptime(uptime);
writeTemperature(cputemp);
}
void PayloadConvert::intToBytes(uint8_t pos, int32_t i, uint8_t byteSize) {
for (uint8_t x = 0; x < byteSize; x++) {
buffer[x + pos] = (byte)(i >> (x * 8));
}
cursor += byteSize;
}
void PayloadConvert::writeUptime(uint64_t uptime) {
intToBytes(cursor, uptime, 8);
}
void PayloadConvert::writeLatLng(double latitude, double longitude) {
intToBytes(cursor, latitude, 4);
intToBytes(cursor, longitude, 4);
}
void PayloadConvert::writeUint16(uint16_t i) { intToBytes(cursor, i, 2); }
void PayloadConvert::writeUint8(uint8_t i) { intToBytes(cursor, i, 1); }
void PayloadConvert::writeHumidity(float humidity) {
int16_t h = (int16_t)(humidity * 100);
intToBytes(cursor, h, 2);
}
/**
* Uses a 16bit two's complement with two decimals, so the range is
* -327.68 to +327.67 degrees
*/
void PayloadConvert::writeTemperature(float temperature) {
int16_t t = (int16_t)(temperature * 100);
if (temperature < 0) {
t = ~-t;
t = t + 1;
}
buffer[cursor++] = (byte)((t >> 8) & 0xFF);
buffer[cursor++] = (byte)t & 0xFF;
}
void PayloadConvert::writeBitmap(bool a, bool b, bool c, bool d, bool e, bool f,
bool g, bool h) {
uint8_t bitmap = 0;
// LSB first
bitmap |= (a & 1) << 7;
bitmap |= (b & 1) << 6;
bitmap |= (c & 1) << 5;
bitmap |= (d & 1) << 4;
bitmap |= (e & 1) << 3;
bitmap |= (f & 1) << 2;
bitmap |= (g & 1) << 1;
bitmap |= (h & 1) << 0;
writeUint8(bitmap);
}
/* ---------------- Cayenne LPP format ---------- */
// http://community.mydevices.com/t/cayenne-lpp-2-0/7510
#elif (PAYLOAD_ENCODER == 3 || PAYLOAD_ENCODER == 4)
void PayloadConvert::addCount(uint16_t value1, uint16_t value2) {
uint16_t val1 = value1 * 100;
uint16_t val2 = value2 * 100;
#if (PAYLOAD_ENCODER == 3)
buffer[cursor++] = LPP_COUNT_WIFI_CHANNEL;
#endif
buffer[cursor++] = LPP_ANALOG_INPUT; // workaround, type meter not found?
buffer[cursor++] = val1 >> 8;
buffer[cursor++] = val1;
#if (PAYLOAD_ENCODER == 3)
buffer[cursor++] = LPP_COUNT_BLE_CHANNEL;
#endif
buffer[cursor++] = LPP_ANALOG_INPUT; // workaround, type meter not found?
buffer[cursor++] = val2 >> 8;
buffer[cursor++] = val2;
}
#ifdef HAS_GPS
void PayloadConvert::addGPS(gpsStatus_t value) {
int32_t lat = value.latitude / 100;
int32_t lon = value.longitude / 100;
int32_t alt = value.altitude * 100;
#if (PAYLOAD_ENCODER == 3)
buffer[cursor++] = LPP_GPS_CHANNEL;
#endif
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;
}
#endif
void PayloadConvert::addConfig(configData_t value) {
#if (PAYLOAD_ENCODER == 3)
buffer[cursor++] = LPP_ADR_CHANNEL;
#endif
buffer[cursor++] = LPP_DIGITAL_INPUT;
buffer[cursor++] = value.adrmode;
}
void PayloadConvert::addStatus(uint16_t voltage, uint64_t uptime,
float celsius) {
int16_t val = celsius * 10;
#if (PAYLOAD_ENCODER == 3)
buffer[cursor++] = LPP_BATT_CHANNEL;
#endif
buffer[cursor++] = LPP_ANALOG_INPUT;
buffer[cursor++] = voltage >> 8;
buffer[cursor++] = voltage;
#if (PAYLOAD_ENCODER == 3)
buffer[cursor++] = LPP_TEMP_CHANNEL;
#endif
buffer[cursor++] = LPP_TEMPERATURE;
buffer[cursor++] = (uint16_t)val >> 8;
buffer[cursor++] = (uint16_t)val;
}
#else
#error "No valid payload converter defined"
#endif