payload converter enhanced
This commit is contained in:
parent
12c6dcb0ff
commit
7c03c22765
34
README.md
34
README.md
@ -106,6 +106,8 @@ Legend for RGB LED (LoPy/LoPy4/FiPy/Lolin32 only):
|
|||||||
|
|
||||||
# Payload
|
# Payload
|
||||||
|
|
||||||
|
All data is represented in big-endian-format, as long not otherwise stated.
|
||||||
|
|
||||||
**LoRaWAN Port #1:**
|
**LoRaWAN Port #1:**
|
||||||
|
|
||||||
Paxcounter data
|
Paxcounter data
|
||||||
@ -140,11 +142,11 @@ function Decoder(bytes, port) {
|
|||||||
decoded.wifi = (bytes[i++] << 8) | bytes[i++];
|
decoded.wifi = (bytes[i++] << 8) | bytes[i++];
|
||||||
decoded.ble = (bytes[i++] << 8) | bytes[i++];
|
decoded.ble = (bytes[i++] << 8) | bytes[i++];
|
||||||
if (bytes.length > 4) {
|
if (bytes.length > 4) {
|
||||||
decoded.latitude = ( (bytes[i++]) | (bytes[i++] << 8) | (bytes[i++] << 16) | bytes[i++] << 24 );
|
decoded.latitude = ( (bytes[i++] << 24) | (bytes[i++] << 16) | (bytes[i++] << 8) | bytes[i++] );
|
||||||
decoded.longitude = ( (bytes[i++]) | (bytes[i++] << 8) | (bytes[i++] << 16) | bytes[i++] << 24 );
|
decoded.longitude = ( (bytes[i++] << 24) | (bytes[i++] << 16) | (bytes[i++] << 8) | bytes[i++] );
|
||||||
decoded.sats = ( bytes[i++] | (bytes[i++] << 8) );
|
decoded.sats = ( bytes[i++] );
|
||||||
decoded.hdop = ( bytes[i++] | (bytes[i++] << 8) );
|
decoded.hdop = ( bytes[i++] << 8) | (bytes[i++] );
|
||||||
decoded.altitude = ( bytes[i++] | (bytes[i++] << 8) );
|
decoded.altitude = ( bytes[i++] << 8) | (bytes[i++] );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -264,7 +266,7 @@ Note: all settings are stored in NVRAM and will be reloaded when device starts.
|
|||||||
|
|
||||||
0x80 get device configuration
|
0x80 get device configuration
|
||||||
|
|
||||||
device answers with it's current configuration. The configuration is a C structure declared in file [globals.h](src/globals.h#L32-L50) with the following definition:
|
device answers with it's current configuration. The configuration is a C structure declared in file [main.h](src/main.h#L13-L31) with the following definition:
|
||||||
|
|
||||||
byte 1: Lora SF (7..12) [default 9]
|
byte 1: Lora SF (7..12) [default 9]
|
||||||
byte 2: Lora TXpower (2..15) [default 15]
|
byte 2: Lora TXpower (2..15) [default 15]
|
||||||
@ -283,25 +285,19 @@ device answers with it's current configuration. The configuration is a C structu
|
|||||||
byte 16: GPS send data mode (1=on, 0=ff) [default 1]
|
byte 16: GPS send data mode (1=on, 0=ff) [default 1]
|
||||||
bytes 17-27: Software version (ASCII format, terminating with zero)
|
bytes 17-27: Software version (ASCII format, terminating with zero)
|
||||||
|
|
||||||
0x81 get device uptime
|
0x81 get device status
|
||||||
|
|
||||||
bytes 1-8: Uptime in seconds (little endian format)
|
bytes 1-2: Battery voltage in millivolt, 0 if unreadable
|
||||||
|
bytes 3-10: Uptime in seconds
|
||||||
0x82 get device cpu temperature
|
bytes 11-14: Chip temperature in degrees celsius
|
||||||
|
|
||||||
bytes 1-4: Chip temperature in degrees celsius (little endian format)
|
|
||||||
|
|
||||||
0x83 get device battery voltage
|
|
||||||
|
|
||||||
bytes 1-2: Battery voltage in millivolt, 0 if unreadable (little endian format)
|
|
||||||
|
|
||||||
0x84 get device GPS status
|
0x84 get device GPS status
|
||||||
|
|
||||||
bytes 1-4: Latitude
|
bytes 1-4: Latitude
|
||||||
bytes 5-8: Longitude
|
bytes 5-8: Longitude
|
||||||
byte 9-10: Number of satellites
|
byte 9: Number of satellites
|
||||||
byte 11-12: HDOP
|
byte 10-11: HDOP
|
||||||
bytes 13-14: altidute [meter]
|
bytes 12-13: altidute [meter]
|
||||||
|
|
||||||
# License
|
# License
|
||||||
|
|
||||||
|
@ -27,6 +27,8 @@ description = Paxcounter is a proof-of-concept ESP32 device for metering passeng
|
|||||||
[common_env_data]
|
[common_env_data]
|
||||||
platform_espressif32 = espressif32@>=1.0.2
|
platform_espressif32 = espressif32@>=1.0.2
|
||||||
board_build.partitions = no_ota.csv
|
board_build.partitions = no_ota.csv
|
||||||
|
lib_deps_all =
|
||||||
|
LoRa Serialization@>=3.0.0
|
||||||
lib_deps_display =
|
lib_deps_display =
|
||||||
U8g2@>=2.22.14
|
U8g2@>=2.22.14
|
||||||
lib_deps_rgbled =
|
lib_deps_rgbled =
|
||||||
@ -55,6 +57,7 @@ board_build.partitions = ${common_env_data.board_build.partitions}
|
|||||||
monitor_speed = 115200
|
monitor_speed = 115200
|
||||||
upload_speed = 115200
|
upload_speed = 115200
|
||||||
lib_deps =
|
lib_deps =
|
||||||
|
${common_env_data.lib_deps_all}
|
||||||
${common_env_data.lib_deps_display}
|
${common_env_data.lib_deps_display}
|
||||||
build_flags =
|
build_flags =
|
||||||
${common_env_data.build_flags}
|
${common_env_data.build_flags}
|
||||||
@ -68,6 +71,7 @@ board_build.partitions = ${common_env_data.board_build.partitions}
|
|||||||
monitor_speed = 115200
|
monitor_speed = 115200
|
||||||
upload_speed = 115200
|
upload_speed = 115200
|
||||||
lib_deps =
|
lib_deps =
|
||||||
|
${common_env_data.lib_deps_all}
|
||||||
${common_env_data.lib_deps_display}
|
${common_env_data.lib_deps_display}
|
||||||
build_flags =
|
build_flags =
|
||||||
${common_env_data.build_flags}
|
${common_env_data.build_flags}
|
||||||
@ -81,6 +85,7 @@ board_build.partitions = ${common_env_data.board_build.partitions}
|
|||||||
monitor_speed = 115200
|
monitor_speed = 115200
|
||||||
upload_speed = 921600
|
upload_speed = 921600
|
||||||
lib_deps =
|
lib_deps =
|
||||||
|
${common_env_data.lib_deps_all}
|
||||||
${common_env_data.lib_deps_display}
|
${common_env_data.lib_deps_display}
|
||||||
build_flags =
|
build_flags =
|
||||||
${common_env_data.build_flags}
|
${common_env_data.build_flags}
|
||||||
@ -94,6 +99,7 @@ board_build.partitions = ${common_env_data.board_build.partitions}
|
|||||||
monitor_speed = 115200
|
monitor_speed = 115200
|
||||||
upload_speed = 921600
|
upload_speed = 921600
|
||||||
lib_deps =
|
lib_deps =
|
||||||
|
${common_env_data.lib_deps_all}
|
||||||
${common_env_data.lib_deps_display}
|
${common_env_data.lib_deps_display}
|
||||||
build_flags =
|
build_flags =
|
||||||
${common_env_data.build_flags}
|
${common_env_data.build_flags}
|
||||||
@ -107,6 +113,7 @@ board_build.partitions = ${common_env_data.board_build.partitions}
|
|||||||
monitor_speed = 115200
|
monitor_speed = 115200
|
||||||
upload_speed = 921600
|
upload_speed = 921600
|
||||||
lib_deps =
|
lib_deps =
|
||||||
|
${common_env_data.lib_deps_all}
|
||||||
${common_env_data.lib_deps_gps}
|
${common_env_data.lib_deps_gps}
|
||||||
build_flags =
|
build_flags =
|
||||||
${common_env_data.build_flags}
|
${common_env_data.build_flags}
|
||||||
@ -120,6 +127,7 @@ board_build.partitions = ${common_env_data.board_build.partitions}
|
|||||||
monitor_speed = 115200
|
monitor_speed = 115200
|
||||||
upload_speed = 921600
|
upload_speed = 921600
|
||||||
lib_deps =
|
lib_deps =
|
||||||
|
${common_env_data.lib_deps_all}
|
||||||
${common_env_data.lib_deps_rgbled}
|
${common_env_data.lib_deps_rgbled}
|
||||||
build_flags =
|
build_flags =
|
||||||
${common_env_data.build_flags}
|
${common_env_data.build_flags}
|
||||||
@ -133,6 +141,7 @@ board_build.partitions = ${common_env_data.board_build.partitions}
|
|||||||
monitor_speed = 115200
|
monitor_speed = 115200
|
||||||
upload_speed = 921600
|
upload_speed = 921600
|
||||||
lib_deps =
|
lib_deps =
|
||||||
|
${common_env_data.lib_deps_all}
|
||||||
${common_env_data.lib_deps_rgbled}
|
${common_env_data.lib_deps_rgbled}
|
||||||
build_flags =
|
build_flags =
|
||||||
${common_env_data.build_flags}
|
${common_env_data.build_flags}
|
||||||
@ -146,6 +155,7 @@ board_build.partitions = ${common_env_data.board_build.partitions}
|
|||||||
monitor_speed = 115200
|
monitor_speed = 115200
|
||||||
upload_speed = 921600
|
upload_speed = 921600
|
||||||
lib_deps =
|
lib_deps =
|
||||||
|
${common_env_data.lib_deps_all}
|
||||||
${common_env_data.lib_deps_rgbled}
|
${common_env_data.lib_deps_rgbled}
|
||||||
build_flags =
|
build_flags =
|
||||||
${common_env_data.build_flags}
|
${common_env_data.build_flags}
|
||||||
@ -159,6 +169,7 @@ board_build.partitions = ${common_env_data.board_build.partitions}
|
|||||||
monitor_speed = 115200
|
monitor_speed = 115200
|
||||||
upload_speed = 256000
|
upload_speed = 256000
|
||||||
lib_deps =
|
lib_deps =
|
||||||
|
${common_env_data.lib_deps_all}
|
||||||
${common_env_data.lib_deps_rgbled}
|
${common_env_data.lib_deps_rgbled}
|
||||||
build_flags =
|
build_flags =
|
||||||
${common_env_data.build_flags}
|
${common_env_data.build_flags}
|
||||||
@ -172,6 +183,7 @@ board_build.partitions = ${common_env_data.board_build.partitions}
|
|||||||
monitor_speed = 115200
|
monitor_speed = 115200
|
||||||
upload_speed = 921600
|
upload_speed = 921600
|
||||||
lib_deps =
|
lib_deps =
|
||||||
|
${common_env_data.lib_deps_all}
|
||||||
${common_env_data.lib_deps_rgbled}
|
${common_env_data.lib_deps_rgbled}
|
||||||
build_flags =
|
build_flags =
|
||||||
${common_env_data.build_flags}
|
${common_env_data.build_flags}
|
||||||
|
@ -28,38 +28,7 @@
|
|||||||
#include "rgb_led.h"
|
#include "rgb_led.h"
|
||||||
#include "macsniff.h"
|
#include "macsniff.h"
|
||||||
#include "main.h"
|
#include "main.h"
|
||||||
|
#include "payload.h"
|
||||||
// Struct holding devices's runtime configuration
|
|
||||||
typedef struct {
|
|
||||||
uint8_t lorasf; // 7-12, lora spreadfactor
|
|
||||||
uint8_t txpower; // 2-15, lora tx power
|
|
||||||
uint8_t adrmode; // 0=disabled, 1=enabled
|
|
||||||
uint8_t screensaver; // 0=disabled, 1=enabled
|
|
||||||
uint8_t screenon; // 0=disabled, 1=enabled
|
|
||||||
uint8_t countermode; // 0=cyclic unconfirmed, 1=cumulative, 2=cyclic confirmed
|
|
||||||
int16_t rssilimit; // threshold for rssilimiter, negative value!
|
|
||||||
uint8_t sendcycle; // payload send cycle [seconds/2]
|
|
||||||
uint8_t wifichancycle; // wifi channel switch cycle [seconds/100]
|
|
||||||
uint8_t blescantime; // BLE scan cycle duration [seconds]
|
|
||||||
uint8_t blescan; // 0=disabled, 1=enabled
|
|
||||||
uint8_t wifiant; // 0=internal, 1=external (for LoPy/LoPy4)
|
|
||||||
uint8_t vendorfilter; // 0=disabled, 1=enabled
|
|
||||||
uint8_t rgblum; // RGB Led luminosity (0..100%)
|
|
||||||
uint8_t gpsmode; // 0=disabled, 1=enabled
|
|
||||||
char version[10]; // Firmware version
|
|
||||||
} configData_t;
|
|
||||||
|
|
||||||
#ifdef HAS_GPS
|
|
||||||
typedef struct {
|
|
||||||
uint32_t latitude;
|
|
||||||
uint32_t longitude;
|
|
||||||
uint8_t satellites;
|
|
||||||
uint16_t hdop;
|
|
||||||
uint16_t altitude;
|
|
||||||
} gpsStatus_t;
|
|
||||||
extern gpsStatus_t gps_status; // struct for storing gps data
|
|
||||||
extern TinyGPSPlus gps; // Make TinyGPS++ instance globally availabe
|
|
||||||
#endif
|
|
||||||
|
|
||||||
extern configData_t cfg;
|
extern configData_t cfg;
|
||||||
extern uint64_t uptimecounter;
|
extern uint64_t uptimecounter;
|
||||||
@ -70,5 +39,19 @@ extern uint16_t macs_total, macs_wifi, macs_ble; // MAC counters
|
|||||||
extern std::set<uint16_t> macs;
|
extern std::set<uint16_t> macs;
|
||||||
extern hw_timer_t
|
extern hw_timer_t
|
||||||
*channelSwitch; // hardware timer used for wifi channel switching
|
*channelSwitch; // hardware timer used for wifi channel switching
|
||||||
extern xref2u1_t rcmd_data; // buffer for rcommand results size
|
|
||||||
extern u1_t rcmd_data_size; // buffer for rcommand results size
|
#ifdef HAS_GPS
|
||||||
|
extern gpsStatus_t gps_status; // struct for storing gps data
|
||||||
|
extern TinyGPSPlus gps; // Make TinyGPS++ instance globally availabe
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// payload encoder
|
||||||
|
#if (PAYLOAD_ENCODER == 3)
|
||||||
|
// externe CayenneLPP payload;
|
||||||
|
#elif (PAYLOAD_ENCODER == 2)
|
||||||
|
extern TTNserialized payload;
|
||||||
|
#elif (PAYLOAD_ENCODER == 1)
|
||||||
|
extern TTNplain payload;
|
||||||
|
#else
|
||||||
|
#error "No valid payload converter defined"
|
||||||
|
#endif
|
@ -117,42 +117,28 @@ void do_send(osjob_t *j) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// prepare payload with sum of unique WIFI MACs seen
|
// Prepare payload with counter and, if applicable, gps data
|
||||||
static uint8_t mydata[4];
|
payload.reset();
|
||||||
|
|
||||||
mydata[0] = (macs_wifi & 0xff00) >> 8;
|
|
||||||
mydata[1] = macs_wifi & 0xff;
|
|
||||||
|
|
||||||
if (cfg.blescan) {
|
if (cfg.blescan) {
|
||||||
// append sum of unique BLE MACs seen to payload
|
payload.addCount(macs_wifi, macs_ble);
|
||||||
mydata[2] = (macs_ble & 0xff00) >> 8;
|
|
||||||
mydata[3] = macs_ble & 0xff;
|
|
||||||
} else {
|
} else {
|
||||||
mydata[2] = 0;
|
payload.addCount(macs_wifi, 0);
|
||||||
mydata[3] = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef HAS_GPS
|
#ifdef HAS_GPS
|
||||||
static uint8_t gpsdata[18];
|
if ((cfg.gpsmode) && (gps.location.isValid())) {
|
||||||
if (cfg.gpsmode && gps.location.isValid()) {
|
|
||||||
gps_read();
|
gps_read();
|
||||||
memcpy(gpsdata, mydata, 4);
|
payload.addGPS(gps_status);
|
||||||
memcpy(gpsdata + 4, &gps_status, sizeof(gps_status));
|
|
||||||
ESP_LOGI(TAG, "lat=%.6f / lon=%.6f | %u Sats | HDOP=%.1f | Altitude=%u m",
|
|
||||||
gps_status.latitude / (float)1000000,
|
|
||||||
gps_status.longitude / (float)1000000, gps_status.satellites,
|
|
||||||
gps_status.hdop / (float)100, gps_status.altitude);
|
|
||||||
LMIC_setTxData2(COUNTERPORT, gpsdata, sizeof(gpsdata),
|
|
||||||
(cfg.countermode & 0x02));
|
|
||||||
ESP_LOGI(TAG, "%d bytes queued to send", sizeof(gpsdata));
|
|
||||||
} else {
|
} else {
|
||||||
#endif
|
ESP_LOGI(TAG, "No valid GPS position or GPS disabled");
|
||||||
LMIC_setTxData2(COUNTERPORT, mydata, sizeof(mydata),
|
|
||||||
(cfg.countermode & 0x02));
|
|
||||||
ESP_LOGI(TAG, "%d bytes queued to send", sizeof(mydata));
|
|
||||||
#ifdef HAS_GPS
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// send payload
|
||||||
|
LMIC_setTxData2(COUNTERPORT, payload.getBuffer(), payload.getSize(),
|
||||||
|
(cfg.countermode & 0x02));
|
||||||
|
ESP_LOGI(TAG, "%d bytes queued to send", payload.getSize());
|
||||||
sprintf(display_lmic, "PACKET QUEUED");
|
sprintf(display_lmic, "PACKET QUEUED");
|
||||||
|
|
||||||
// clear counter if not in cumulative counter mode
|
// clear counter if not in cumulative counter mode
|
||||||
|
@ -76,7 +76,7 @@ bool mac_add(uint8_t *paddr, int8_t rssi, bool sniff_type) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Log scan result
|
// Log scan result
|
||||||
ESP_LOGI(TAG,
|
ESP_LOGD(TAG,
|
||||||
"%s %s RSSI %ddBi -> MAC %s -> Hash %04X -> WiFi:%d BLTH:%d -> "
|
"%s %s RSSI %ddBi -> MAC %s -> Hash %04X -> WiFi:%d BLTH:%d -> "
|
||||||
"%d Bytes left",
|
"%d Bytes left",
|
||||||
added ? "new " : "known",
|
added ? "new " : "known",
|
||||||
|
30
src/main.cpp
30
src/main.cpp
@ -57,8 +57,6 @@ hw_timer_t *displaytimer =
|
|||||||
NULL; // configure hardware timer used for cyclic display refresh
|
NULL; // configure hardware timer used for cyclic display refresh
|
||||||
hw_timer_t *channelSwitch =
|
hw_timer_t *channelSwitch =
|
||||||
NULL; // configure hardware timer used for wifi channel switching
|
NULL; // configure hardware timer used for wifi channel switching
|
||||||
xref2u1_t rcmd_data; // buffer for rcommand results size
|
|
||||||
u1_t rcmd_data_size; // buffer for rcommand results size
|
|
||||||
|
|
||||||
#ifdef HAS_GPS
|
#ifdef HAS_GPS
|
||||||
gpsStatus_t gps_status; // struct for storing gps data
|
gpsStatus_t gps_status; // struct for storing gps data
|
||||||
@ -72,6 +70,19 @@ portMUX_TYPE timerMux =
|
|||||||
std::set<uint16_t> macs; // associative container holds total of unique MAC
|
std::set<uint16_t> macs; // associative container holds total of unique MAC
|
||||||
// adress hashes (Wifi + BLE)
|
// adress hashes (Wifi + BLE)
|
||||||
|
|
||||||
|
// select payload encoder
|
||||||
|
#if (PAYLOAD_ENCODER == 3)
|
||||||
|
// CayenneLPP payload(PAYLOAD_BUFFER_SIZE);
|
||||||
|
#elif (PAYLOAD_ENCODER == 2)
|
||||||
|
TTNserialized payload(PAYLOAD_BUFFER_SIZE);
|
||||||
|
#elif (PAYLOAD_ENCODER == 1)
|
||||||
|
TTNplain payload(PAYLOAD_BUFFER_SIZE);
|
||||||
|
#else
|
||||||
|
#error "No valid payload converter defined"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// TTNplain payload(PAYLOAD_BUFFER_SIZE);
|
||||||
|
|
||||||
// this variables will be changed in the ISR, and read in main loop
|
// this variables will be changed in the ISR, and read in main loop
|
||||||
static volatile int ButtonPressedIRQ = 0, DisplayTimerIRQ = 0,
|
static volatile int ButtonPressedIRQ = 0, DisplayTimerIRQ = 0,
|
||||||
ChannelTimerIRQ = 0;
|
ChannelTimerIRQ = 0;
|
||||||
@ -674,11 +685,22 @@ void loop() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#ifdef HAS_GPS
|
#ifdef HAS_GPS
|
||||||
// log NMEA status every 30 seconds, useful for debugging GPS connection
|
// log NMEA status every 60 seconds, useful for debugging GPS connection
|
||||||
if ((uptime() % 30000) == 0)
|
if ((uptime() % 60000) == 0) {
|
||||||
ESP_LOGI(TAG, "GPS NMEA data: passed %d / failed: %d / with fix: %d",
|
ESP_LOGI(TAG, "GPS NMEA data: passed %d / failed: %d / with fix: %d",
|
||||||
gps.passedChecksum(), gps.failedChecksum(),
|
gps.passedChecksum(), gps.failedChecksum(),
|
||||||
gps.sentencesWithFix());
|
gps.sentencesWithFix());
|
||||||
|
if ((cfg.gpsmode) && (gps.location.isValid())) {
|
||||||
|
gps_read();
|
||||||
|
ESP_LOGI(TAG,
|
||||||
|
"lat=%.6f | lon=%.6f | %u Sats | HDOP=%.1f | Altitude=%um",
|
||||||
|
gps_status.latitude / (float)1000000,
|
||||||
|
gps_status.longitude / (float)1000000, gps_status.satellites,
|
||||||
|
gps_status.hdop / (float)100, gps_status.altitude);
|
||||||
|
} else {
|
||||||
|
ESP_LOGI(TAG, "No valid GPS position or GPS disabled");
|
||||||
|
}
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
vTaskDelay(1 / portTICK_PERIOD_MS); // reset watchdog
|
vTaskDelay(1 / portTICK_PERIOD_MS); // reset watchdog
|
||||||
|
34
src/main.h
34
src/main.h
@ -5,11 +5,43 @@
|
|||||||
|
|
||||||
// program version - note: increment version after modifications to configData_t
|
// program version - note: increment version after modifications to configData_t
|
||||||
// struct!!
|
// struct!!
|
||||||
#define PROGVERSION "1.3.81" // use max 10 chars here!
|
#define PROGVERSION "1.3.82" // use max 10 chars here!
|
||||||
#define PROGNAME "PAXCNT"
|
#define PROGNAME "PAXCNT"
|
||||||
|
|
||||||
//--- Declarations ---
|
//--- Declarations ---
|
||||||
|
|
||||||
|
// Struct holding devices's runtime configuration
|
||||||
|
typedef struct {
|
||||||
|
uint8_t lorasf; // 7-12, lora spreadfactor
|
||||||
|
uint8_t txpower; // 2-15, lora tx power
|
||||||
|
uint8_t adrmode; // 0=disabled, 1=enabled
|
||||||
|
uint8_t screensaver; // 0=disabled, 1=enabled
|
||||||
|
uint8_t screenon; // 0=disabled, 1=enabled
|
||||||
|
uint8_t countermode; // 0=cyclic unconfirmed, 1=cumulative, 2=cyclic confirmed
|
||||||
|
int16_t rssilimit; // threshold for rssilimiter, negative value!
|
||||||
|
uint8_t sendcycle; // payload send cycle [seconds/2]
|
||||||
|
uint8_t wifichancycle; // wifi channel switch cycle [seconds/100]
|
||||||
|
uint8_t blescantime; // BLE scan cycle duration [seconds]
|
||||||
|
uint8_t blescan; // 0=disabled, 1=enabled
|
||||||
|
uint8_t wifiant; // 0=internal, 1=external (for LoPy/LoPy4)
|
||||||
|
uint8_t vendorfilter; // 0=disabled, 1=enabled
|
||||||
|
uint8_t rgblum; // RGB Led luminosity (0..100%)
|
||||||
|
uint8_t gpsmode; // 0=disabled, 1=enabled
|
||||||
|
char version[10]; // Firmware version
|
||||||
|
} configData_t;
|
||||||
|
|
||||||
|
#ifdef HAS_GPS
|
||||||
|
typedef struct {
|
||||||
|
uint32_t latitude;
|
||||||
|
uint32_t longitude;
|
||||||
|
uint8_t satellites;
|
||||||
|
uint16_t hdop;
|
||||||
|
uint16_t altitude;
|
||||||
|
} gpsStatus_t;
|
||||||
|
extern gpsStatus_t gps_status; // struct for storing gps data
|
||||||
|
extern TinyGPSPlus gps; // Make TinyGPS++ instance globally availabe
|
||||||
|
#endif
|
||||||
|
|
||||||
enum led_states { LED_OFF, LED_ON };
|
enum led_states { LED_OFF, LED_ON };
|
||||||
|
|
||||||
#if defined(CFG_eu868)
|
#if defined(CFG_eu868)
|
||||||
|
@ -35,15 +35,17 @@
|
|||||||
#define WIFI_CHANNEL_SWITCH_INTERVAL 50 // [seconds/100] -> 0,5 sec.
|
#define WIFI_CHANNEL_SWITCH_INTERVAL 50 // [seconds/100] -> 0,5 sec.
|
||||||
|
|
||||||
// LoRa payload send cycle --> take care of duty cycle of LoRaWAN network! <--
|
// LoRa payload send cycle --> take care of duty cycle of LoRaWAN network! <--
|
||||||
#define SEND_SECS 120 // [seconds/2] -> 240 sec.
|
//#define SEND_SECS 120 // [seconds/2] -> 240 sec.
|
||||||
|
#define SEND_SECS 30 // [seconds/2] -> 60 sec.
|
||||||
#define MEM_LOW 2048 // [Bytes] low memory threshold triggering a send cycle
|
#define MEM_LOW 2048 // [Bytes] low memory threshold triggering a send cycle
|
||||||
#define RETRANSMIT_RCMD 5 // [seconds] wait time before retransmitting rcommand results
|
#define RETRANSMIT_RCMD 5 // [seconds] wait time before retransmitting rcommand results
|
||||||
|
#define PAYLOAD_ENCODER 2 // select payload encoder: 1 = Plain [default], 2 = Lora-hserialized, 3 = Cayenne LPP
|
||||||
|
#define PAYLOAD_BUFFER_SIZE 51 // maximum size of payload block per transmit
|
||||||
|
|
||||||
// Default LoRa Spreadfactor
|
// Default LoRa Spreadfactor
|
||||||
#define LORASFDEFAULT 9 // 7 ... 12 SF, according to LoRaWAN specs
|
#define LORASFDEFAULT 9 // 7 ... 12 SF, according to LoRaWAN specs
|
||||||
#define MAXLORARETRY 500 // maximum count of TX retries if LoRa busy
|
#define MAXLORARETRY 500 // maximum count of TX retries if LoRa busy
|
||||||
#define RCMDPORT 2 // LoRaWAN Port on which device listenes for remote commands
|
#define RCMDPORT 2 // LoRaWAN Port on which device listenes for remote commands
|
||||||
#define GPSPORT 3 // LoRaWAN Port on which device sends gps data
|
|
||||||
#define COUNTERPORT 1 // LoRaWAN Port on which device sends counts
|
#define COUNTERPORT 1 // LoRaWAN Port on which device sends counts
|
||||||
|
|
||||||
// Default RGB LED luminosity (in %)
|
// Default RGB LED luminosity (in %)
|
||||||
|
@ -2,7 +2,9 @@
|
|||||||
#include "globals.h"
|
#include "globals.h"
|
||||||
#include "payload.h"
|
#include "payload.h"
|
||||||
|
|
||||||
TTNplain::TTNplain(uint8_t size) : maxsize(size) {
|
/* ---------------- plain format without special encoding ---------- */
|
||||||
|
|
||||||
|
TTNplain::TTNplain(uint8_t size) {
|
||||||
buffer = (uint8_t *)malloc(size);
|
buffer = (uint8_t *)malloc(size);
|
||||||
cursor = 0;
|
cursor = 0;
|
||||||
}
|
}
|
||||||
@ -13,28 +15,16 @@ void TTNplain::reset(void) { cursor = 0; }
|
|||||||
|
|
||||||
uint8_t TTNplain::getSize(void) { return cursor; }
|
uint8_t TTNplain::getSize(void) { return cursor; }
|
||||||
|
|
||||||
uint8_t *TTNplain::getBuffer(void) {
|
uint8_t *TTNplain::getBuffer(void) { return buffer; }
|
||||||
// uint8_t[cursor] result;
|
|
||||||
// memcpy(result, buffer, cursor);
|
|
||||||
// return result;
|
|
||||||
return buffer;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8_t TTNplain::copy(uint8_t *dst) {
|
|
||||||
memcpy(dst, buffer, cursor);
|
|
||||||
return cursor;
|
|
||||||
}
|
|
||||||
|
|
||||||
void TTNplain::addCount(uint16_t value1, uint16_t value2) {
|
void TTNplain::addCount(uint16_t value1, uint16_t value2) {
|
||||||
cursor = TTN_PAYLOAD_COUNTER;
|
buffer[cursor++] = value1 >> 8;
|
||||||
buffer[cursor] = (macs_wifi & 0xff00) >> 8;
|
buffer[cursor++] = value1;
|
||||||
buffer[cursor++] = macs_wifi & 0xff;
|
buffer[cursor++] = value2 >> 8;
|
||||||
buffer[cursor++] = (macs_ble & 0xff00) >> 8;
|
buffer[cursor++] = value2;
|
||||||
buffer[cursor++] = macs_ble & 0xff;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void TTNplain::addGPS(gpsStatus_t value) {
|
void TTNplain::addGPS(gpsStatus_t value) {
|
||||||
cursor = TTN_PAYLOAD_GPS;
|
|
||||||
buffer[cursor++] = value.latitude >> 24;
|
buffer[cursor++] = value.latitude >> 24;
|
||||||
buffer[cursor++] = value.latitude >> 16;
|
buffer[cursor++] = value.latitude >> 16;
|
||||||
buffer[cursor++] = value.latitude >> 8;
|
buffer[cursor++] = value.latitude >> 8;
|
||||||
@ -51,7 +41,6 @@ void TTNplain::addGPS(gpsStatus_t value) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void TTNplain::addConfig(configData_t value) {
|
void TTNplain::addConfig(configData_t value) {
|
||||||
cursor = TTN_PAYLOAD_CONFIG;
|
|
||||||
buffer[cursor++] = value.lorasf;
|
buffer[cursor++] = value.lorasf;
|
||||||
buffer[cursor++] = value.adrmode;
|
buffer[cursor++] = value.adrmode;
|
||||||
buffer[cursor++] = value.screensaver;
|
buffer[cursor++] = value.screensaver;
|
||||||
@ -68,10 +57,10 @@ void TTNplain::addConfig(configData_t value) {
|
|||||||
buffer[cursor++] = value.rgblum;
|
buffer[cursor++] = value.rgblum;
|
||||||
buffer[cursor++] = value.gpsmode;
|
buffer[cursor++] = value.gpsmode;
|
||||||
memcpy(buffer + cursor, value.version, 10);
|
memcpy(buffer + cursor, value.version, 10);
|
||||||
|
cursor += 10;
|
||||||
}
|
}
|
||||||
|
|
||||||
void TTNplain::addStatus(uint16_t voltage, uint64_t uptime, float cputemp) {
|
void TTNplain::addStatus(uint16_t voltage, uint64_t uptime, float cputemp) {
|
||||||
cursor = TTN_PAYLOAD_STATUS;
|
|
||||||
buffer[cursor++] = voltage >> 8;
|
buffer[cursor++] = voltage >> 8;
|
||||||
buffer[cursor++] = voltage;
|
buffer[cursor++] = voltage;
|
||||||
buffer[cursor++] = uptime >> 56;
|
buffer[cursor++] = uptime >> 56;
|
||||||
@ -79,11 +68,65 @@ void TTNplain::addStatus(uint16_t voltage, uint64_t uptime, float cputemp) {
|
|||||||
buffer[cursor++] = uptime >> 40;
|
buffer[cursor++] = uptime >> 40;
|
||||||
buffer[cursor++] = uptime >> 32;
|
buffer[cursor++] = uptime >> 32;
|
||||||
buffer[cursor++] = uptime >> 24;
|
buffer[cursor++] = uptime >> 24;
|
||||||
buffer[cursor++] = uptime >> 32;
|
|
||||||
buffer[cursor++] = uptime >> 16;
|
buffer[cursor++] = uptime >> 16;
|
||||||
buffer[cursor++] = uptime >> 8;
|
buffer[cursor++] = uptime >> 8;
|
||||||
|
buffer[cursor++] = uptime;
|
||||||
buffer[cursor++] = (uint32_t)cputemp >> 24;
|
buffer[cursor++] = (uint32_t)cputemp >> 24;
|
||||||
buffer[cursor++] = (uint32_t)cputemp >> 16;
|
buffer[cursor++] = (uint32_t)cputemp >> 16;
|
||||||
buffer[cursor++] = (uint32_t)cputemp >> 8;
|
buffer[cursor++] = (uint32_t)cputemp >> 8;
|
||||||
buffer[cursor++] = (uint32_t)cputemp;
|
buffer[cursor++] = (uint32_t)cputemp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ---------------- packed format with LoRa serialization Encoder ---------- */
|
||||||
|
|
||||||
|
TTNserialized::TTNserialized(uint8_t size) {
|
||||||
|
buffer = (uint8_t *)malloc(size);
|
||||||
|
LoraEncoder message(buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
TTNserialized::~TTNserialized(void) { free(buffer); }
|
||||||
|
|
||||||
|
void TTNserialized::reset(void) { }
|
||||||
|
|
||||||
|
uint8_t TTNserialized::getSize(void) { return sizeof(buffer); }
|
||||||
|
|
||||||
|
uint8_t *TTNserialized::getBuffer(void) { return buffer; }
|
||||||
|
|
||||||
|
void TTNserialized::addCount(uint16_t value1, uint16_t value2) {
|
||||||
|
LoraEncoder message(buffer);
|
||||||
|
message.writeUint16(value1);
|
||||||
|
message.writeUint16(value2);
|
||||||
|
}
|
||||||
|
|
||||||
|
void TTNserialized::addGPS(gpsStatus_t value) {
|
||||||
|
LoraEncoder message(buffer);
|
||||||
|
message.writeLatLng(value.latitude, value.longitude);
|
||||||
|
message.writeUint8(value.satellites);
|
||||||
|
message.writeUint16(value.hdop);
|
||||||
|
message.writeUint16(value.altitude);
|
||||||
|
}
|
||||||
|
|
||||||
|
void TTNserialized::addConfig(configData_t value) {
|
||||||
|
LoraEncoder message(buffer);
|
||||||
|
message.writeUint8(value.lorasf);
|
||||||
|
message.writeUint16(value.rssilimit);
|
||||||
|
message.writeUint8(value.sendcycle);
|
||||||
|
message.writeUint8(value.wifichancycle);
|
||||||
|
message.writeUint8(value.blescantime);
|
||||||
|
message.writeUint8(value.rgblum);
|
||||||
|
message.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 TTNserialized::addStatus(uint16_t voltage, uint64_t uptime,
|
||||||
|
float cputemp) {
|
||||||
|
LoraEncoder message(buffer);
|
||||||
|
message.writeUint16(voltage);
|
||||||
|
message.writeUnixtime(uptime);
|
||||||
|
message.writeTemperature(cputemp);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ---------------- Cayenne LPP format ---------- */
|
@ -3,11 +3,7 @@
|
|||||||
#define _PAYLOAD_H_
|
#define _PAYLOAD_H_
|
||||||
|
|
||||||
#include <Arduino.h>
|
#include <Arduino.h>
|
||||||
|
#include "LoraEncoder.h"
|
||||||
#define TTN_PAYLOAD_COUNTER 0
|
|
||||||
#define TTN_PAYLOAD_GPS 4
|
|
||||||
#define TTN_PAYLOAD_CONFIG 0
|
|
||||||
#define TTN_PAYLOAD_STATUS 0
|
|
||||||
|
|
||||||
class TTNplain {
|
class TTNplain {
|
||||||
public:
|
public:
|
||||||
@ -17,7 +13,6 @@ public:
|
|||||||
void reset(void);
|
void reset(void);
|
||||||
uint8_t getSize(void);
|
uint8_t getSize(void);
|
||||||
uint8_t *getBuffer(void);
|
uint8_t *getBuffer(void);
|
||||||
uint8_t copy(uint8_t *buffer);
|
|
||||||
|
|
||||||
// application payloads
|
// application payloads
|
||||||
void addCount(uint16_t value1, uint16_t value2);
|
void addCount(uint16_t value1, uint16_t value2);
|
||||||
@ -33,4 +28,27 @@ private:
|
|||||||
uint8_t cursor;
|
uint8_t cursor;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class TTNserialized {
|
||||||
|
public:
|
||||||
|
TTNserialized(uint8_t size);
|
||||||
|
~TTNserialized();
|
||||||
|
|
||||||
|
void reset(void);
|
||||||
|
uint8_t getSize(void);
|
||||||
|
uint8_t *getBuffer(void);
|
||||||
|
|
||||||
|
// application payloads
|
||||||
|
void addCount(uint16_t value1, uint16_t value2);
|
||||||
|
void addGPS(gpsStatus_t value);
|
||||||
|
|
||||||
|
// payloads for get rcommands
|
||||||
|
void addConfig(configData_t value);
|
||||||
|
void addStatus(uint16_t voltage, uint64_t uptime, float cputemp);
|
||||||
|
|
||||||
|
private:
|
||||||
|
uint8_t *buffer;
|
||||||
|
LoraEncoder message(byte *buffer);
|
||||||
|
//LoraEncoder(byte *buffer);
|
||||||
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
@ -27,7 +27,7 @@ void antenna_select(const uint8_t _ant);
|
|||||||
|
|
||||||
// function defined in adcread.cpp
|
// function defined in adcread.cpp
|
||||||
#ifdef HAS_BATTERY_PROBE
|
#ifdef HAS_BATTERY_PROBE
|
||||||
uint32_t read_voltage(void);
|
uint16_t read_voltage(void);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// function sends result of get commands to LoRaWAN network
|
// function sends result of get commands to LoRaWAN network
|
||||||
@ -40,20 +40,13 @@ void do_transmit(osjob_t *j) {
|
|||||||
os_setTimedCallback(&rcmdjob, os_getTime() + sec2osticks(RETRANSMIT_RCMD),
|
os_setTimedCallback(&rcmdjob, os_getTime() + sec2osticks(RETRANSMIT_RCMD),
|
||||||
do_transmit);
|
do_transmit);
|
||||||
}
|
}
|
||||||
LMIC_setTxData2(RCMDPORT, rcmd_data, rcmd_data_size,
|
// send payload
|
||||||
0); // send data unconfirmed on RCMD Port
|
LMIC_setTxData2(RCMDPORT, payload.getBuffer(), payload.getSize(),
|
||||||
ESP_LOGI(TAG, "%d bytes queued to send", rcmd_data_size);
|
(cfg.countermode & 0x02));
|
||||||
|
ESP_LOGI(TAG, "%d bytes queued to send", payload.getSize());
|
||||||
sprintf(display_lmic, "PACKET QUEUED");
|
sprintf(display_lmic, "PACKET QUEUED");
|
||||||
}
|
}
|
||||||
|
|
||||||
// help function to transmit result of get commands, since callback function
|
|
||||||
// do_transmit() cannot have params
|
|
||||||
void transmit(xref2u1_t mydata, u1_t mydata_size) {
|
|
||||||
rcmd_data = mydata;
|
|
||||||
rcmd_data_size = mydata_size;
|
|
||||||
do_transmit(&rcmdjob);
|
|
||||||
}
|
|
||||||
|
|
||||||
// help function to assign LoRa datarates to numeric spreadfactor values
|
// help function to assign LoRa datarates to numeric spreadfactor values
|
||||||
void switch_lora(uint8_t sf, uint8_t tx) {
|
void switch_lora(uint8_t sf, uint8_t tx) {
|
||||||
if (tx > 20)
|
if (tx > 20)
|
||||||
@ -292,41 +285,33 @@ void set_lorapower(uint8_t val) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
void get_config(uint8_t val) {
|
void get_config(uint8_t val) {
|
||||||
ESP_LOGI(TAG, "Remote command: get configuration");
|
ESP_LOGI(TAG, "Remote command: get device configuration");
|
||||||
transmit((byte *)&cfg, sizeof(cfg));
|
payload.reset();
|
||||||
|
payload.addConfig(cfg);
|
||||||
|
do_transmit(&rcmdjob);
|
||||||
};
|
};
|
||||||
|
|
||||||
void get_uptime(uint8_t val) {
|
void get_status(uint8_t val) {
|
||||||
ESP_LOGI(TAG, "Remote command: get uptime");
|
ESP_LOGI(TAG, "Remote command: get device status");
|
||||||
transmit((byte *)&uptimecounter, sizeof(uptimecounter));
|
|
||||||
};
|
|
||||||
|
|
||||||
void get_cputemp(uint8_t val) {
|
|
||||||
ESP_LOGI(TAG, "Remote command: get cpu temperature");
|
|
||||||
float temp = temperatureRead();
|
|
||||||
transmit((byte *)&temp, sizeof(temp));
|
|
||||||
};
|
|
||||||
|
|
||||||
void get_voltage(uint8_t val) {
|
|
||||||
ESP_LOGI(TAG, "Remote command: get battery voltage");
|
|
||||||
#ifdef HAS_BATTERY_PROBE
|
#ifdef HAS_BATTERY_PROBE
|
||||||
uint16_t voltage = read_voltage();
|
uint16_t voltage = read_voltage();
|
||||||
#else
|
#else
|
||||||
uint16_t voltage = 0;
|
uint16_t voltage = 0;
|
||||||
#endif
|
#endif
|
||||||
transmit((byte *)&voltage, sizeof(voltage));
|
payload.reset();
|
||||||
|
payload.addStatus(voltage, uptimecounter, temperatureRead());
|
||||||
|
do_transmit(&rcmdjob);
|
||||||
};
|
};
|
||||||
|
|
||||||
void get_gps(uint8_t val) {
|
void get_gps(uint8_t val) {
|
||||||
ESP_LOGI(TAG, "Remote command: get gps status");
|
ESP_LOGI(TAG, "Remote command: get gps status");
|
||||||
#ifdef HAS_GPS
|
#ifdef HAS_GPS
|
||||||
gps_read();
|
gps_read();
|
||||||
transmit((byte *)&gps_status, sizeof(gps_status));
|
payload.reset();
|
||||||
ESP_LOGI(TAG, "lat=%f / lon=%f | Sats=%u | HDOP=%u | Alti=%u",
|
payload.addGPS(gps_status);
|
||||||
gps_status.latitude / 1000000, gps_status.longitude / 1000000,
|
do_transmit(&rcmdjob);
|
||||||
gps_status.satellites, gps_status.hdop, gps_status.altitude);
|
|
||||||
#else
|
#else
|
||||||
ESP_LOGE(TAG, "GPS not present");
|
ESP_LOGW(TAG, "GPS function not supported");
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -341,8 +326,7 @@ cmd_t table[] = {{0x01, set_rssi, true}, {0x02, set_countmode, true},
|
|||||||
{0x0b, set_wifichancycle, true}, {0x0c, set_blescantime, true},
|
{0x0b, set_wifichancycle, true}, {0x0c, set_blescantime, true},
|
||||||
{0x0d, set_vendorfilter, false}, {0x0e, set_blescan, true},
|
{0x0d, set_vendorfilter, false}, {0x0e, set_blescan, true},
|
||||||
{0x0f, set_wifiant, true}, {0x10, set_rgblum, true},
|
{0x0f, set_wifiant, true}, {0x10, set_rgblum, true},
|
||||||
{0x80, get_config, false}, {0x81, get_uptime, false},
|
{0x80, get_config, false}, {0x81, get_status, false},
|
||||||
{0x82, get_cputemp, false}, {0x83, get_voltage, false},
|
|
||||||
{0x84, get_gps, false}};
|
{0x84, get_gps, false}};
|
||||||
|
|
||||||
// check and execute remote command
|
// check and execute remote command
|
||||||
|
Loading…
Reference in New Issue
Block a user