From c8f8b7c1a473ba958bf14c79c514fba2166cbf56 Mon Sep 17 00:00:00 2001 From: Klaus K Wilting Date: Thu, 1 Oct 2020 15:39:54 +0200 Subject: [PATCH 01/44] fix issue#649 --- src/configmanager.cpp | 110 +++++++++++++++++++++--------------------- src/rcommand.cpp | 2 +- 2 files changed, 56 insertions(+), 56 deletions(-) diff --git a/src/configmanager.cpp b/src/configmanager.cpp index a3c9babb..9787c2a3 100644 --- a/src/configmanager.cpp +++ b/src/configmanager.cpp @@ -80,8 +80,8 @@ void saveConfig() { ESP_LOGI(TAG, "Storing settings in NVS"); open_storage(); if (err == ESP_OK) { - int8_t flash8 = 0; - int16_t flash16 = 0; + uint8_t flash8 = 0; + uint16_t flash16 = 0; size_t required_size; uint8_t bsecstate_buffer[BSEC_MAX_STATE_BLOB_SIZE + 1]; char storedversion[10]; @@ -98,73 +98,73 @@ void saveConfig() { strcmp(storedversion, cfg.version) != 0) nvs_set_str(my_handle, "version", cfg.version); - if (nvs_get_i8(my_handle, "loradr", &flash8) != ESP_OK || + if (nvs_get_u8(my_handle, "loradr", &flash8) != ESP_OK || flash8 != cfg.loradr) - nvs_set_i8(my_handle, "loradr", cfg.loradr); + nvs_set_u8(my_handle, "loradr", cfg.loradr); - if (nvs_get_i8(my_handle, "txpower", &flash8) != ESP_OK || + if (nvs_get_u8(my_handle, "txpower", &flash8) != ESP_OK || flash8 != cfg.txpower) - nvs_set_i8(my_handle, "txpower", cfg.txpower); + nvs_set_u8(my_handle, "txpower", cfg.txpower); - if (nvs_get_i8(my_handle, "adrmode", &flash8) != ESP_OK || + if (nvs_get_u8(my_handle, "adrmode", &flash8) != ESP_OK || flash8 != cfg.adrmode) - nvs_set_i8(my_handle, "adrmode", cfg.adrmode); + nvs_set_u8(my_handle, "adrmode", cfg.adrmode); - if (nvs_get_i8(my_handle, "screensaver", &flash8) != ESP_OK || + if (nvs_get_u8(my_handle, "screensaver", &flash8) != ESP_OK || flash8 != cfg.screensaver) - nvs_set_i8(my_handle, "screensaver", cfg.screensaver); + nvs_set_u8(my_handle, "screensaver", cfg.screensaver); - if (nvs_get_i8(my_handle, "screenon", &flash8) != ESP_OK || + if (nvs_get_u8(my_handle, "screenon", &flash8) != ESP_OK || flash8 != cfg.screenon) - nvs_set_i8(my_handle, "screenon", cfg.screenon); + nvs_set_u8(my_handle, "screenon", cfg.screenon); - if (nvs_get_i8(my_handle, "countermode", &flash8) != ESP_OK || + if (nvs_get_u8(my_handle, "countermode", &flash8) != ESP_OK || flash8 != cfg.countermode) - nvs_set_i8(my_handle, "countermode", cfg.countermode); + nvs_set_u8(my_handle, "countermode", cfg.countermode); - if (nvs_get_i8(my_handle, "sendcycle", &flash8) != ESP_OK || + if (nvs_get_u8(my_handle, "sendcycle", &flash8) != ESP_OK || flash8 != cfg.sendcycle) - nvs_set_i8(my_handle, "sendcycle", cfg.sendcycle); + nvs_set_u8(my_handle, "sendcycle", cfg.sendcycle); - if (nvs_get_i8(my_handle, "wifichancycle", &flash8) != ESP_OK || + if (nvs_get_u8(my_handle, "wifichancycle", &flash8) != ESP_OK || flash8 != cfg.wifichancycle) - nvs_set_i8(my_handle, "wifichancycle", cfg.wifichancycle); + nvs_set_u8(my_handle, "wifichancycle", cfg.wifichancycle); - if (nvs_get_i8(my_handle, "blescantime", &flash8) != ESP_OK || + if (nvs_get_u8(my_handle, "blescantime", &flash8) != ESP_OK || flash8 != cfg.blescantime) - nvs_set_i8(my_handle, "blescantime", cfg.blescantime); + nvs_set_u8(my_handle, "blescantime", cfg.blescantime); - if (nvs_get_i8(my_handle, "blescanmode", &flash8) != ESP_OK || + if (nvs_get_u8(my_handle, "blescanmode", &flash8) != ESP_OK || flash8 != cfg.blescan) - nvs_set_i8(my_handle, "blescanmode", cfg.blescan); + nvs_set_u8(my_handle, "blescanmode", cfg.blescan); - if (nvs_get_i8(my_handle, "wifiscanmode", &flash8) != ESP_OK || + if (nvs_get_u8(my_handle, "wifiscanmode", &flash8) != ESP_OK || flash8 != cfg.wifiscan) - nvs_set_i8(my_handle, "wifiscanmode", cfg.wifiscan); + nvs_set_u8(my_handle, "wifiscanmode", cfg.wifiscan); - if (nvs_get_i8(my_handle, "wifiant", &flash8) != ESP_OK || + if (nvs_get_u8(my_handle, "wifiant", &flash8) != ESP_OK || flash8 != cfg.wifiant) - nvs_set_i8(my_handle, "wifiant", cfg.wifiant); + nvs_set_u8(my_handle, "wifiant", cfg.wifiant); - if (nvs_get_i8(my_handle, "vendorfilter", &flash8) != ESP_OK || + if (nvs_get_u8(my_handle, "vendorfilter", &flash8) != ESP_OK || flash8 != cfg.vendorfilter) - nvs_set_i8(my_handle, "vendorfilter", cfg.vendorfilter); + nvs_set_u8(my_handle, "vendorfilter", cfg.vendorfilter); - if (nvs_get_i8(my_handle, "rgblum", &flash8) != ESP_OK || + if (nvs_get_u8(my_handle, "rgblum", &flash8) != ESP_OK || flash8 != cfg.rgblum) - nvs_set_i8(my_handle, "rgblum", cfg.rgblum); + nvs_set_u8(my_handle, "rgblum", cfg.rgblum); - if (nvs_get_i8(my_handle, "payloadmask", &flash8) != ESP_OK || + if (nvs_get_u8(my_handle, "payloadmask", &flash8) != ESP_OK || flash8 != cfg.payloadmask) - nvs_set_i8(my_handle, "payloadmask", cfg.payloadmask); + nvs_set_u8(my_handle, "payloadmask", cfg.payloadmask); - if (nvs_get_i8(my_handle, "monitormode", &flash8) != ESP_OK || + if (nvs_get_u8(my_handle, "monitormode", &flash8) != ESP_OK || flash8 != cfg.monitormode) - nvs_set_i8(my_handle, "monitormode", cfg.monitormode); + nvs_set_u8(my_handle, "monitormode", cfg.monitormode); - if (nvs_get_i16(my_handle, "rssilimit", &flash16) != ESP_OK || + if (nvs_get_u16(my_handle, "rssilimit", &flash16) != ESP_OK || flash16 != cfg.rssilimit) - nvs_set_i16(my_handle, "rssilimit", cfg.rssilimit); + nvs_set_u16(my_handle, "rssilimit", cfg.rssilimit); err = nvs_commit(my_handle); nvs_close(my_handle); @@ -195,8 +195,8 @@ void loadConfig() { saveConfig(); } // saves factory settings to NVRAM else { - int8_t flash8 = 0; - int16_t flash16 = 0; + uint8_t flash8 = 0; + uint16_t flash16 = 0; size_t required_size; // check if configuration stored in NVRAM matches PROGVERSION @@ -223,7 +223,7 @@ void loadConfig() { ESP_LOGI(TAG, "bsecstate = %d", cfg.bsecstate[BSEC_MAX_STATE_BLOB_SIZE]); }; - if (nvs_get_i8(my_handle, "loradr", &flash8) == ESP_OK) { + if (nvs_get_u8(my_handle, "loradr", &flash8) == ESP_OK) { cfg.loradr = flash8; ESP_LOGI(TAG, "loradr = %d", flash8); } else { @@ -231,7 +231,7 @@ void loadConfig() { saveConfig(); } - if (nvs_get_i8(my_handle, "txpower", &flash8) == ESP_OK) { + if (nvs_get_u8(my_handle, "txpower", &flash8) == ESP_OK) { cfg.txpower = flash8; ESP_LOGI(TAG, "txpower = %d", flash8); } else { @@ -239,7 +239,7 @@ void loadConfig() { saveConfig(); } - if (nvs_get_i8(my_handle, "adrmode", &flash8) == ESP_OK) { + if (nvs_get_u8(my_handle, "adrmode", &flash8) == ESP_OK) { cfg.adrmode = flash8; ESP_LOGI(TAG, "adrmode = %d", flash8); } else { @@ -247,7 +247,7 @@ void loadConfig() { saveConfig(); } - if (nvs_get_i8(my_handle, "screensaver", &flash8) == ESP_OK) { + if (nvs_get_u8(my_handle, "screensaver", &flash8) == ESP_OK) { cfg.screensaver = flash8; ESP_LOGI(TAG, "screensaver = %d", flash8); } else { @@ -255,7 +255,7 @@ void loadConfig() { saveConfig(); } - if (nvs_get_i8(my_handle, "screenon", &flash8) == ESP_OK) { + if (nvs_get_u8(my_handle, "screenon", &flash8) == ESP_OK) { cfg.screenon = flash8; ESP_LOGI(TAG, "screenon = %d", flash8); } else { @@ -263,7 +263,7 @@ void loadConfig() { saveConfig(); } - if (nvs_get_i8(my_handle, "countermode", &flash8) == ESP_OK) { + if (nvs_get_u8(my_handle, "countermode", &flash8) == ESP_OK) { cfg.countermode = flash8; ESP_LOGI(TAG, "countermode = %d", flash8); } else { @@ -271,7 +271,7 @@ void loadConfig() { saveConfig(); } - if (nvs_get_i8(my_handle, "sendcycle", &flash8) == ESP_OK) { + if (nvs_get_u8(my_handle, "sendcycle", &flash8) == ESP_OK) { cfg.sendcycle = flash8; ESP_LOGI(TAG, "sendcycle = %d", flash8); } else { @@ -279,7 +279,7 @@ void loadConfig() { saveConfig(); } - if (nvs_get_i8(my_handle, "wifichancycle", &flash8) == ESP_OK) { + if (nvs_get_u8(my_handle, "wifichancycle", &flash8) == ESP_OK) { cfg.wifichancycle = flash8; ESP_LOGI(TAG, "wifichancycle = %d", flash8); } else { @@ -287,7 +287,7 @@ void loadConfig() { saveConfig(); } - if (nvs_get_i8(my_handle, "wifiant", &flash8) == ESP_OK) { + if (nvs_get_u8(my_handle, "wifiant", &flash8) == ESP_OK) { cfg.wifiant = flash8; ESP_LOGI(TAG, "wifiantenna = %d", flash8); } else { @@ -295,7 +295,7 @@ void loadConfig() { saveConfig(); } - if (nvs_get_i8(my_handle, "vendorfilter", &flash8) == ESP_OK) { + if (nvs_get_u8(my_handle, "vendorfilter", &flash8) == ESP_OK) { cfg.vendorfilter = flash8; ESP_LOGI(TAG, "vendorfilter = %d", flash8); } else { @@ -303,7 +303,7 @@ void loadConfig() { saveConfig(); } - if (nvs_get_i8(my_handle, "rgblum", &flash8) == ESP_OK) { + if (nvs_get_u8(my_handle, "rgblum", &flash8) == ESP_OK) { cfg.rgblum = flash8; ESP_LOGI(TAG, "rgbluminosity = %d", flash8); } else { @@ -311,7 +311,7 @@ void loadConfig() { saveConfig(); } - if (nvs_get_i8(my_handle, "blescantime", &flash8) == ESP_OK) { + if (nvs_get_u8(my_handle, "blescantime", &flash8) == ESP_OK) { cfg.blescantime = flash8; ESP_LOGI(TAG, "blescantime = %d", flash8); } else { @@ -319,7 +319,7 @@ void loadConfig() { saveConfig(); } - if (nvs_get_i8(my_handle, "blescanmode", &flash8) == ESP_OK) { + if (nvs_get_u8(my_handle, "blescanmode", &flash8) == ESP_OK) { cfg.blescan = flash8; ESP_LOGI(TAG, "BLEscanmode = %d", flash8); } else { @@ -327,7 +327,7 @@ void loadConfig() { saveConfig(); } - if (nvs_get_i8(my_handle, "wifiscanmode", &flash8) == ESP_OK) { + if (nvs_get_u8(my_handle, "wifiscanmode", &flash8) == ESP_OK) { cfg.wifiscan = flash8; ESP_LOGI(TAG, "WIFIscanmode = %d", flash8); } else { @@ -335,7 +335,7 @@ void loadConfig() { saveConfig(); } - if (nvs_get_i16(my_handle, "rssilimit", &flash16) == ESP_OK) { + if (nvs_get_u16(my_handle, "rssilimit", &flash16) == ESP_OK) { cfg.rssilimit = flash16; ESP_LOGI(TAG, "rssilimit = %d", flash16); } else { @@ -343,7 +343,7 @@ void loadConfig() { saveConfig(); } - if (nvs_get_i8(my_handle, "payloadmask", &flash8) == ESP_OK) { + if (nvs_get_u8(my_handle, "payloadmask", &flash8) == ESP_OK) { cfg.payloadmask = flash8; ESP_LOGI(TAG, "payloadmask = %hhu", flash8); } else { @@ -351,7 +351,7 @@ void loadConfig() { saveConfig(); } - if (nvs_get_i8(my_handle, "monitormode", &flash8) == ESP_OK) { + if (nvs_get_u8(my_handle, "monitormode", &flash8) == ESP_OK) { cfg.monitormode = flash8; ESP_LOGI(TAG, "Monitor mode = %d", flash8); } else { diff --git a/src/rcommand.cpp b/src/rcommand.cpp index adb61a49..225b6f17 100644 --- a/src/rcommand.cpp +++ b/src/rcommand.cpp @@ -48,7 +48,7 @@ void set_rssi(uint8_t val[]) { void set_sendcycle(uint8_t val[]) { cfg.sendcycle = val[0]; - // update send cycle interrupt [seconds + // update send cycle interrupt [seconds / 2] sendcycler.attach(cfg.sendcycle * 2, sendcycle); ESP_LOGI(TAG, "Remote command: set send cycle to %d seconds", cfg.sendcycle * 2); From a7b4298c0dcebdf425ecae56d5511d3a58638a35 Mon Sep 17 00:00:00 2001 From: Klaus K Wilting Date: Thu, 1 Oct 2020 15:40:28 +0200 Subject: [PATCH 02/44] v2.0.16 --- platformio_orig.ini | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/platformio_orig.ini b/platformio_orig.ini index 0edbc702..cc15b7ab 100644 --- a/platformio_orig.ini +++ b/platformio_orig.ini @@ -46,7 +46,7 @@ description = Paxcounter is a device for metering passenger flows in realtime. I [common] ; for release_version use max. 10 chars total, use any decimal format like "a.b.c" -release_version = 2.0.15 +release_version = 2.0.16 ; DEBUG LEVEL: For production run set to 0, otherwise device will leak RAM while running! ; 0=None, 1=Error, 2=Warn, 3=Info, 4=Debug, 5=Verbose debug_level = 3 @@ -61,7 +61,7 @@ display_library = ; set by build.py and taken from hal file lib_deps_lora = mcci-catena/MCCI LoRaWAN LMIC library @ ^3.2.0 lib_deps_display = - bitbank2/OneBitDisplay @ 1.5.0 + bitbank2/OneBitDisplay @ 1.7.2 ricmoo/QRCode @ ^0.0.1 bodmer/TFT_eSPI @ ^2.2.20 lib_deps_ledmatrix = From 963d9dbb5f1b1f9d3b0b755e2532481e343c3f87 Mon Sep 17 00:00:00 2001 From: Klaus K Wilting Date: Thu, 1 Oct 2020 22:33:33 +0200 Subject: [PATCH 03/44] correction to bugfix issue#649 --- src/configmanager.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/configmanager.cpp b/src/configmanager.cpp index 9787c2a3..13e3ed7a 100644 --- a/src/configmanager.cpp +++ b/src/configmanager.cpp @@ -81,7 +81,7 @@ void saveConfig() { open_storage(); if (err == ESP_OK) { uint8_t flash8 = 0; - uint16_t flash16 = 0; + int16_t flash16 = 0; size_t required_size; uint8_t bsecstate_buffer[BSEC_MAX_STATE_BLOB_SIZE + 1]; char storedversion[10]; @@ -162,9 +162,9 @@ void saveConfig() { flash8 != cfg.monitormode) nvs_set_u8(my_handle, "monitormode", cfg.monitormode); - if (nvs_get_u16(my_handle, "rssilimit", &flash16) != ESP_OK || + if (nvs_get_i16(my_handle, "rssilimit", &flash16) != ESP_OK || flash16 != cfg.rssilimit) - nvs_set_u16(my_handle, "rssilimit", cfg.rssilimit); + nvs_set_i16(my_handle, "rssilimit", cfg.rssilimit); err = nvs_commit(my_handle); nvs_close(my_handle); @@ -196,7 +196,7 @@ void loadConfig() { } // saves factory settings to NVRAM else { uint8_t flash8 = 0; - uint16_t flash16 = 0; + int16_t flash16 = 0; size_t required_size; // check if configuration stored in NVRAM matches PROGVERSION @@ -335,7 +335,7 @@ void loadConfig() { saveConfig(); } - if (nvs_get_u16(my_handle, "rssilimit", &flash16) == ESP_OK) { + if (nvs_get_i16(my_handle, "rssilimit", &flash16) == ESP_OK) { cfg.rssilimit = flash16; ESP_LOGI(TAG, "rssilimit = %d", flash16); } else { From dd9917856faf80694ef3e705828e1cf2f74e06f7 Mon Sep 17 00:00:00 2001 From: Klaus K Wilting Date: Fri, 2 Oct 2020 22:57:48 +0200 Subject: [PATCH 04/44] platformio_orig.ini: lib version update --- platformio_orig.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platformio_orig.ini b/platformio_orig.ini index cc15b7ab..80087854 100644 --- a/platformio_orig.ini +++ b/platformio_orig.ini @@ -72,7 +72,7 @@ lib_deps_gps = mikalhart/TinyGPSPlus @ ^1.0.2 lib_deps_sensors = adafruit/Adafruit Unified Sensor @ ^1.1.4 - adafruit/Adafruit BME280 Library @ ^2.1.0 + adafruit/Adafruit BME280 Library @ ^2.1.1 adafruit/Adafruit BMP085 Library @ ^1.1.0 boschsensortec/BSEC Software Library @ 1.5.1474 https://github.com/ricki-z/SDS011.git From 31765e3b65b37887d8a6d8cb2603470d5efa7989 Mon Sep 17 00:00:00 2001 From: Klaus K Wilting Date: Fri, 2 Oct 2020 22:58:41 +0200 Subject: [PATCH 05/44] paxcounter_orig.conf: default countermode corr'd --- src/paxcounter_orig.conf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/paxcounter_orig.conf b/src/paxcounter_orig.conf index a174d819..06a1e624 100644 --- a/src/paxcounter_orig.conf +++ b/src/paxcounter_orig.conf @@ -12,7 +12,7 @@ // Payload send cycle and encoding #define SENDCYCLE 30 // payload send cycle [seconds/2], 0 .. 255 #define PAYLOAD_ENCODER 2 // payload encoder: 1=Plain, 2=Packed, 3=Cayenne LPP dynamic, 4=Cayenne LPP packed -#define COUNTERMODE 1 // 0=cyclic, 1=cumulative, 2=cyclic confirmed +#define COUNTERMODE 0 // 0=cyclic, 1=cumulative, 2=cyclic confirmed // Set this to include BLE counting and vendor filter functions, or to switch off WIFI counting #define VENDORFILTER 0 // set to 0 if you want to scan all devices, not filtering smartphone OUIs From ef84966917041561a4d584e1f3f19c26a6f3ac78 Mon Sep 17 00:00:00 2001 From: Klaus K Wilting Date: Fri, 2 Oct 2020 23:07:24 +0200 Subject: [PATCH 06/44] rewrite configmanager (experimental) --- include/configmanager.h | 8 +- include/globals.h | 4 +- src/configmanager.cpp | 407 +++++++--------------------------------- 3 files changed, 79 insertions(+), 340 deletions(-) diff --git a/include/configmanager.h b/include/configmanager.h index 373cc1af..8da2e83c 100644 --- a/include/configmanager.h +++ b/include/configmanager.h @@ -1,11 +1,11 @@ #ifndef _CONFIGMANAGER_H #define _CONFIGMANAGER_H -#include -#include +#include +#include "globals.h" -void eraseConfig(void); -void saveConfig(void); +void saveConfig(bool erase = false); void loadConfig(void); +void eraseConfig(void); #endif \ No newline at end of file diff --git a/include/globals.h b/include/globals.h index 14ca8221..0f5ec4c8 100644 --- a/include/globals.h +++ b/include/globals.h @@ -60,7 +60,7 @@ enum runmode_t { }; // Struct holding devices's runtime configuration -typedef struct { +typedef struct __attribute__((packed)) { uint8_t loradr; // 0-15, lora datarate uint8_t txpower; // 2-15, lora tx power uint8_t adrmode; // 0=disabled, 1=enabled @@ -80,8 +80,10 @@ typedef struct { uint8_t runmode; // 0=normal, 1=update uint8_t payloadmask; // bitswitches for payload data char version[10]; // Firmware version +#ifdef HAS_BME680 uint8_t bsecstate[BSEC_MAX_STATE_BLOB_SIZE + 1]; // BSEC state for BME680 sensor +#endif } configData_t; // Struct holding payload for data send queue diff --git a/src/configmanager.cpp b/src/configmanager.cpp index 13e3ed7a..78b63b3c 100644 --- a/src/configmanager.cpp +++ b/src/configmanager.cpp @@ -4,362 +4,99 @@ #include "configmanager.h" // Local logging tag -static const char TAG[] = "flash"; +static const char TAG[] = __FILE__; -nvs_handle my_handle; -esp_err_t err; +#define PAYLOADMASK \ + ((GPS_DATA | ALARM_DATA | MEMS_DATA | COUNT_DATA | SENSOR1_DATA | \ + SENSOR2_DATA | SENSOR3_DATA) & \ + (~BATT_DATA)) -#define PAYLOADMASK \ - ((GPS_DATA | ALARM_DATA | MEMS_DATA | COUNT_DATA | \ - SENSOR1_DATA | SENSOR2_DATA | SENSOR3_DATA) & \ - (~BATT_DATA) ) +// namespace for device runtime preferences +#define DEVCONFIG "paxcntcfg" -// populate cfg vars with factory settings -void defaultConfig() { - cfg.loradr = LORADRDEFAULT; // 0-15, lora datarate, see paxcounter.conf - cfg.txpower = LORATXPOWDEFAULT; // 0-15, lora tx power - cfg.adrmode = 1; // 0=disabled, 1=enabled - cfg.screensaver = 0; // 0=disabled, 1=enabled - cfg.screenon = 1; // 0=disabled, 1=enabled - cfg.countermode = COUNTERMODE; // 0=cyclic, 1=cumulative, 2=cyclic confirmed - cfg.rssilimit = 0; // threshold for rssilimiter, negative value! - cfg.sendcycle = SENDCYCLE; // payload send cycle [seconds/2] - cfg.wifichancycle = +Preferences nvram; + +// populate runtime config with factory settings +void defaultConfig(configData_t *myconfig) { + char version[10]; + snprintf(version, 10, "%-10s", PROGVERSION); + + myconfig->loradr = LORADRDEFAULT; // 0-15, lora datarate, see paxcounter.conf + myconfig->txpower = LORATXPOWDEFAULT; // 0-15, lora tx power + myconfig->adrmode = 1; // 0=disabled, 1=enabled + myconfig->screensaver = 0; // 0=disabled, 1=enabled + myconfig->screenon = 1; // 0=disabled, 1=enabled + myconfig->countermode = + COUNTERMODE; // 0=cyclic, 1=cumulative, 2=cyclic confirmed + myconfig->rssilimit = 0; // threshold for rssilimiter, negative value! + myconfig->sendcycle = SENDCYCLE; // payload send cycle [seconds/2] + myconfig->wifichancycle = WIFI_CHANNEL_SWITCH_INTERVAL; // wifi channel switch cycle [seconds/100] - cfg.blescantime = + myconfig->blescantime = BLESCANINTERVAL / 10; // BT channel scan cycle [seconds/100], default 1 (= 10ms) - cfg.blescan = 1; // 0=disabled, 1=enabled - cfg.wifiscan = 1; // 0=disabled, 1=enabled - cfg.wifiant = 0; // 0=internal, 1=external (for LoPy/LoPy4) - cfg.vendorfilter = VENDORFILTER; // 0=disabled, 1=enabled - cfg.rgblum = RGBLUMINOSITY; // RGB Led luminosity (0..100%) - cfg.monitormode = 0; // 0=disabled, 1=enabled - cfg.payloadmask = PAYLOADMASK; // all payload switched on - cfg.bsecstate[BSEC_MAX_STATE_BLOB_SIZE] = { - 0}; // init BSEC state for BME680 sensor - - strncpy(cfg.version, PROGVERSION, sizeof(cfg.version) - 1); -} - -void open_storage() { - err = nvs_flash_init(); - if (err == ESP_ERR_NVS_NO_FREE_PAGES) { - // NVS partition was truncated and needs to be erased - // Retry nvs_flash_init - ESP_ERROR_CHECK(nvs_flash_erase()); - err = nvs_flash_init(); - } - ESP_ERROR_CHECK(err); - - // Open - ESP_LOGI(TAG, "Opening NVS"); - err = nvs_open("config", NVS_READWRITE, &my_handle); - if (err != ESP_OK) - ESP_LOGI(TAG, "Error (%d) opening NVS handle", err); - else - ESP_LOGI(TAG, "Done"); -} - -// erase all keys and values in NVRAM -void eraseConfig() { - ESP_LOGI(TAG, "Clearing settings in NVS"); - open_storage(); - if (err == ESP_OK) { - nvs_erase_all(my_handle); - nvs_commit(my_handle); - nvs_close(my_handle); - ESP_LOGI(TAG, "Done"); - } else { - ESP_LOGW(TAG, "NVS erase failed"); - } + myconfig->blescan = 1; // 0=disabled, 1=enabled + myconfig->wifiscan = 1; // 0=disabled, 1=enabled + myconfig->wifiant = 0; // 0=internal, 1=external (for LoPy/LoPy4) + myconfig->vendorfilter = VENDORFILTER; // 0=disabled, 1=enabled + myconfig->rgblum = RGBLUMINOSITY; // RGB Led luminosity (0..100%) + myconfig->monitormode = 0; // 0=disabled, 1=enabled + myconfig->payloadmask = PAYLOADMASK; // all payload switched on + memcpy(myconfig->version, version, 10); // Firmware version [exactly 10 chars] +#ifdef HAS_BME680 + // initial BSEC state for BME680 sensor + myconfig->bsecstate[BSEC_MAX_STATE_BLOB_SIZE] = {0}; +#endif } // save current configuration from RAM to NVRAM -void saveConfig() { - ESP_LOGI(TAG, "Storing settings in NVS"); - open_storage(); - if (err == ESP_OK) { - uint8_t flash8 = 0; - int16_t flash16 = 0; - size_t required_size; - uint8_t bsecstate_buffer[BSEC_MAX_STATE_BLOB_SIZE + 1]; - char storedversion[10]; +void saveConfig(bool erase) { + ESP_LOGI(TAG, "Storing settings in NVRAM"); - if (nvs_get_blob(my_handle, "bsecstate", bsecstate_buffer, - &required_size) != ESP_OK || - memcmp(bsecstate_buffer, cfg.bsecstate, BSEC_MAX_STATE_BLOB_SIZE + 1) != - 0) - nvs_set_blob(my_handle, "bsecstate", cfg.bsecstate, - BSEC_MAX_STATE_BLOB_SIZE + 1); + nvram.begin(DEVCONFIG, false); - if (nvs_get_str(my_handle, "version", storedversion, &required_size) != - ESP_OK || - strcmp(storedversion, cfg.version) != 0) - nvs_set_str(my_handle, "version", cfg.version); - - if (nvs_get_u8(my_handle, "loradr", &flash8) != ESP_OK || - flash8 != cfg.loradr) - nvs_set_u8(my_handle, "loradr", cfg.loradr); - - if (nvs_get_u8(my_handle, "txpower", &flash8) != ESP_OK || - flash8 != cfg.txpower) - nvs_set_u8(my_handle, "txpower", cfg.txpower); - - if (nvs_get_u8(my_handle, "adrmode", &flash8) != ESP_OK || - flash8 != cfg.adrmode) - nvs_set_u8(my_handle, "adrmode", cfg.adrmode); - - if (nvs_get_u8(my_handle, "screensaver", &flash8) != ESP_OK || - flash8 != cfg.screensaver) - nvs_set_u8(my_handle, "screensaver", cfg.screensaver); - - if (nvs_get_u8(my_handle, "screenon", &flash8) != ESP_OK || - flash8 != cfg.screenon) - nvs_set_u8(my_handle, "screenon", cfg.screenon); - - if (nvs_get_u8(my_handle, "countermode", &flash8) != ESP_OK || - flash8 != cfg.countermode) - nvs_set_u8(my_handle, "countermode", cfg.countermode); - - if (nvs_get_u8(my_handle, "sendcycle", &flash8) != ESP_OK || - flash8 != cfg.sendcycle) - nvs_set_u8(my_handle, "sendcycle", cfg.sendcycle); - - if (nvs_get_u8(my_handle, "wifichancycle", &flash8) != ESP_OK || - flash8 != cfg.wifichancycle) - nvs_set_u8(my_handle, "wifichancycle", cfg.wifichancycle); - - if (nvs_get_u8(my_handle, "blescantime", &flash8) != ESP_OK || - flash8 != cfg.blescantime) - nvs_set_u8(my_handle, "blescantime", cfg.blescantime); - - if (nvs_get_u8(my_handle, "blescanmode", &flash8) != ESP_OK || - flash8 != cfg.blescan) - nvs_set_u8(my_handle, "blescanmode", cfg.blescan); - - if (nvs_get_u8(my_handle, "wifiscanmode", &flash8) != ESP_OK || - flash8 != cfg.wifiscan) - nvs_set_u8(my_handle, "wifiscanmode", cfg.wifiscan); - - if (nvs_get_u8(my_handle, "wifiant", &flash8) != ESP_OK || - flash8 != cfg.wifiant) - nvs_set_u8(my_handle, "wifiant", cfg.wifiant); - - if (nvs_get_u8(my_handle, "vendorfilter", &flash8) != ESP_OK || - flash8 != cfg.vendorfilter) - nvs_set_u8(my_handle, "vendorfilter", cfg.vendorfilter); - - if (nvs_get_u8(my_handle, "rgblum", &flash8) != ESP_OK || - flash8 != cfg.rgblum) - nvs_set_u8(my_handle, "rgblum", cfg.rgblum); - - if (nvs_get_u8(my_handle, "payloadmask", &flash8) != ESP_OK || - flash8 != cfg.payloadmask) - nvs_set_u8(my_handle, "payloadmask", cfg.payloadmask); - - if (nvs_get_u8(my_handle, "monitormode", &flash8) != ESP_OK || - flash8 != cfg.monitormode) - nvs_set_u8(my_handle, "monitormode", cfg.monitormode); - - if (nvs_get_i16(my_handle, "rssilimit", &flash16) != ESP_OK || - flash16 != cfg.rssilimit) - nvs_set_i16(my_handle, "rssilimit", cfg.rssilimit); - - err = nvs_commit(my_handle); - nvs_close(my_handle); - if (err == ESP_OK) { - ESP_LOGI(TAG, "Done"); - } else { - ESP_LOGW(TAG, "NVS config write failed"); - } - } else { - ESP_LOGW(TAG, "Error (%d) opening NVS handle", err); + if (erase) { + ESP_LOGI(TAG, "Resetting NVRAM to factory settings"); + nvram.clear(); + defaultConfig(&cfg); } -} -// set and save cfg.version -void migrateVersion() { - snprintf(cfg.version, 10, "%s", PROGVERSION); - ESP_LOGI(TAG, "version set to %s", cfg.version); - saveConfig(); + // Copy device runtime config cfg to byte array + const size_t cfgLen = sizeof(configData_t); + char buffer[cfgLen]; + memcpy(buffer, &cfg, cfgLen); + + // save byte array to NVRAM + nvram.putBytes(DEVCONFIG, buffer, cfgLen); + nvram.end(); } // load configuration from NVRAM into RAM and make it current void loadConfig() { - defaultConfig(); // start with factory settings - ESP_LOGI(TAG, "Reading settings from NVS"); - open_storage(); - if (err != ESP_OK) { - ESP_LOGW(TAG, "Error (%d) opening NVS handle, storing defaults", err); - saveConfig(); - } // saves factory settings to NVRAM - else { - uint8_t flash8 = 0; - int16_t flash16 = 0; - size_t required_size; - // check if configuration stored in NVRAM matches PROGVERSION - if (nvs_get_str(my_handle, "version", NULL, &required_size) == ESP_OK) { - nvs_get_str(my_handle, "version", cfg.version, &required_size); - ESP_LOGI(TAG, "NVRAM settings version = %s", cfg.version); - if (strcmp(cfg.version, PROGVERSION)) { - ESP_LOGI(TAG, "migrating NVRAM settings to new version %s", - PROGVERSION); - nvs_close(my_handle); - migrateVersion(); - } - } else { - ESP_LOGI(TAG, "new version %s, deleting NVRAM settings", PROGVERSION); - nvs_close(my_handle); + ESP_LOGI(TAG, "Loading runtime settings from NVS"); + + if (!nvram.begin(DEVCONFIG, true)) { + ESP_LOGI(TAG, "Initializing NVRAM"); + eraseConfig(); + } else { + // simple check that runtime config data matches + const size_t cfgLen = nvram.getBytesLength(DEVCONFIG); + + if (cfgLen % sizeof(configData_t)) { + ESP_LOGW(TAG, "NVRAM settings invalid"); eraseConfig(); - migrateVersion(); - } - - // populate pre set defaults with current values from NVRAM - - if (nvs_get_blob(my_handle, "bsecstate", NULL, &required_size) == ESP_OK) { - nvs_get_blob(my_handle, "bsecstate", cfg.bsecstate, &required_size); - ESP_LOGI(TAG, "bsecstate = %d", cfg.bsecstate[BSEC_MAX_STATE_BLOB_SIZE]); - }; - - if (nvs_get_u8(my_handle, "loradr", &flash8) == ESP_OK) { - cfg.loradr = flash8; - ESP_LOGI(TAG, "loradr = %d", flash8); } else { - ESP_LOGI(TAG, "loradr set to default %d", cfg.loradr); - saveConfig(); - } - if (nvs_get_u8(my_handle, "txpower", &flash8) == ESP_OK) { - cfg.txpower = flash8; - ESP_LOGI(TAG, "txpower = %d", flash8); - } else { - ESP_LOGI(TAG, "txpower set to default %d", cfg.txpower); - saveConfig(); - } + // load device runtime config from nvram and copy it to byte array + char *buffer = new char[cfgLen]; + nvram.getBytes(DEVCONFIG, buffer, cfgLen); + nvram.end(); - if (nvs_get_u8(my_handle, "adrmode", &flash8) == ESP_OK) { - cfg.adrmode = flash8; - ESP_LOGI(TAG, "adrmode = %d", flash8); - } else { - ESP_LOGI(TAG, "adrmode set to default %d", cfg.adrmode); - saveConfig(); + // copy the byte array into runtime cfg struct + memcpy(&cfg, buffer, cfgLen); } - - if (nvs_get_u8(my_handle, "screensaver", &flash8) == ESP_OK) { - cfg.screensaver = flash8; - ESP_LOGI(TAG, "screensaver = %d", flash8); - } else { - ESP_LOGI(TAG, "screensaver set to default %d", cfg.screensaver); - saveConfig(); - } - - if (nvs_get_u8(my_handle, "screenon", &flash8) == ESP_OK) { - cfg.screenon = flash8; - ESP_LOGI(TAG, "screenon = %d", flash8); - } else { - ESP_LOGI(TAG, "screenon set to default %d", cfg.screenon); - saveConfig(); - } - - if (nvs_get_u8(my_handle, "countermode", &flash8) == ESP_OK) { - cfg.countermode = flash8; - ESP_LOGI(TAG, "countermode = %d", flash8); - } else { - ESP_LOGI(TAG, "countermode set to default %d", cfg.countermode); - saveConfig(); - } - - if (nvs_get_u8(my_handle, "sendcycle", &flash8) == ESP_OK) { - cfg.sendcycle = flash8; - ESP_LOGI(TAG, "sendcycle = %d", flash8); - } else { - ESP_LOGI(TAG, "Payload send cycle set to default %d", cfg.sendcycle); - saveConfig(); - } - - if (nvs_get_u8(my_handle, "wifichancycle", &flash8) == ESP_OK) { - cfg.wifichancycle = flash8; - ESP_LOGI(TAG, "wifichancycle = %d", flash8); - } else { - ESP_LOGI(TAG, "WIFI channel cycle set to default %d", cfg.wifichancycle); - saveConfig(); - } - - if (nvs_get_u8(my_handle, "wifiant", &flash8) == ESP_OK) { - cfg.wifiant = flash8; - ESP_LOGI(TAG, "wifiantenna = %d", flash8); - } else { - ESP_LOGI(TAG, "WIFI antenna switch set to default %d", cfg.wifiant); - saveConfig(); - } - - if (nvs_get_u8(my_handle, "vendorfilter", &flash8) == ESP_OK) { - cfg.vendorfilter = flash8; - ESP_LOGI(TAG, "vendorfilter = %d", flash8); - } else { - ESP_LOGI(TAG, "Vendorfilter mode set to default %d", cfg.vendorfilter); - saveConfig(); - } - - if (nvs_get_u8(my_handle, "rgblum", &flash8) == ESP_OK) { - cfg.rgblum = flash8; - ESP_LOGI(TAG, "rgbluminosity = %d", flash8); - } else { - ESP_LOGI(TAG, "RGB luminosity set to default %d", cfg.rgblum); - saveConfig(); - } - - if (nvs_get_u8(my_handle, "blescantime", &flash8) == ESP_OK) { - cfg.blescantime = flash8; - ESP_LOGI(TAG, "blescantime = %d", flash8); - } else { - ESP_LOGI(TAG, "BLEscantime set to default %d", cfg.blescantime); - saveConfig(); - } - - if (nvs_get_u8(my_handle, "blescanmode", &flash8) == ESP_OK) { - cfg.blescan = flash8; - ESP_LOGI(TAG, "BLEscanmode = %d", flash8); - } else { - ESP_LOGI(TAG, "BLEscanmode set to default %d", cfg.blescan); - saveConfig(); - } - - if (nvs_get_u8(my_handle, "wifiscanmode", &flash8) == ESP_OK) { - cfg.wifiscan = flash8; - ESP_LOGI(TAG, "WIFIscanmode = %d", flash8); - } else { - ESP_LOGI(TAG, "WIFIscanmode set to default %d", cfg.wifiscan); - saveConfig(); - } - - if (nvs_get_i16(my_handle, "rssilimit", &flash16) == ESP_OK) { - cfg.rssilimit = flash16; - ESP_LOGI(TAG, "rssilimit = %d", flash16); - } else { - ESP_LOGI(TAG, "rssilimit set to default %d", cfg.rssilimit); - saveConfig(); - } - - if (nvs_get_u8(my_handle, "payloadmask", &flash8) == ESP_OK) { - cfg.payloadmask = flash8; - ESP_LOGI(TAG, "payloadmask = %hhu", flash8); - } else { - ESP_LOGI(TAG, "payloadmask set to default %hhu", cfg.payloadmask); - saveConfig(); - } - - if (nvs_get_u8(my_handle, "monitormode", &flash8) == ESP_OK) { - cfg.monitormode = flash8; - ESP_LOGI(TAG, "Monitor mode = %d", flash8); - } else { - ESP_LOGI(TAG, "Monitor mode set to default %d", cfg.monitormode); - saveConfig(); - } - - nvs_close(my_handle); - ESP_LOGI(TAG, "Done"); } -} // loadConfig() +} + +void eraseConfig(void) { saveConfig(true); } From 85c235573b8f565893e65f285571df9f2b2d6d05 Mon Sep 17 00:00:00 2001 From: Klaus K Wilting Date: Sat, 3 Oct 2020 12:14:07 +0200 Subject: [PATCH 07/44] configmanager .cpp: some corrections after rewrite --- src/configmanager.cpp | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/src/configmanager.cpp b/src/configmanager.cpp index 78b63b3c..48bf991a 100644 --- a/src/configmanager.cpp +++ b/src/configmanager.cpp @@ -16,11 +16,14 @@ static const char TAG[] = __FILE__; Preferences nvram; +static const size_t cfgLen = sizeof(cfg); + // populate runtime config with factory settings void defaultConfig(configData_t *myconfig) { char version[10]; snprintf(version, 10, "%-10s", PROGVERSION); + // factory settings myconfig->loradr = LORADRDEFAULT; // 0-15, lora datarate, see paxcounter.conf myconfig->txpower = LORATXPOWDEFAULT; // 0-15, lora tx power myconfig->adrmode = 1; // 0=disabled, 1=enabled @@ -38,11 +41,12 @@ void defaultConfig(configData_t *myconfig) { myconfig->blescan = 1; // 0=disabled, 1=enabled myconfig->wifiscan = 1; // 0=disabled, 1=enabled myconfig->wifiant = 0; // 0=internal, 1=external (for LoPy/LoPy4) - myconfig->vendorfilter = VENDORFILTER; // 0=disabled, 1=enabled - myconfig->rgblum = RGBLUMINOSITY; // RGB Led luminosity (0..100%) - myconfig->monitormode = 0; // 0=disabled, 1=enabled - myconfig->payloadmask = PAYLOADMASK; // all payload switched on + myconfig->vendorfilter = VENDORFILTER; // 0=disabled, 1=enabled + myconfig->rgblum = RGBLUMINOSITY; // RGB Led luminosity (0..100%) + myconfig->monitormode = 0; // 0=disabled, 1=enabled + myconfig->payloadmask = PAYLOADMASK; // all payload switched on memcpy(myconfig->version, version, 10); // Firmware version [exactly 10 chars] + #ifdef HAS_BME680 // initial BSEC state for BME680 sensor myconfig->bsecstate[BSEC_MAX_STATE_BLOB_SIZE] = {0}; @@ -62,7 +66,6 @@ void saveConfig(bool erase) { } // Copy device runtime config cfg to byte array - const size_t cfgLen = sizeof(configData_t); char buffer[cfgLen]; memcpy(buffer, &cfg, cfgLen); @@ -81,9 +84,7 @@ void loadConfig() { eraseConfig(); } else { // simple check that runtime config data matches - const size_t cfgLen = nvram.getBytesLength(DEVCONFIG); - - if (cfgLen % sizeof(configData_t)) { + if (nvram.getBytesLength(DEVCONFIG) != cfgLen) { ESP_LOGW(TAG, "NVRAM settings invalid"); eraseConfig(); } else { From a0a041b1d17844063bb0eab3f279c8944158493a Mon Sep 17 00:00:00 2001 From: Klaus K Wilting Date: Sat, 3 Oct 2020 12:33:41 +0200 Subject: [PATCH 08/44] globals.h: comment added --- include/globals.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/globals.h b/include/globals.h index 0f5ec4c8..ba9319ff 100644 --- a/include/globals.h +++ b/include/globals.h @@ -60,6 +60,7 @@ enum runmode_t { }; // Struct holding devices's runtime configuration +// using packed to avoid compiler padding, because struct will be memcpy'd to byte array typedef struct __attribute__((packed)) { uint8_t loradr; // 0-15, lora datarate uint8_t txpower; // 2-15, lora tx power From c7fcf438e666275cd4e897af869f0ef2debf793a Mon Sep 17 00:00:00 2001 From: Klaus K Wilting Date: Sat, 3 Oct 2020 12:41:35 +0200 Subject: [PATCH 09/44] configmanager.cpp cleanup --- src/configmanager.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/configmanager.cpp b/src/configmanager.cpp index 48bf991a..6c2efc4b 100644 --- a/src/configmanager.cpp +++ b/src/configmanager.cpp @@ -17,6 +17,7 @@ static const char TAG[] = __FILE__; Preferences nvram; static const size_t cfgLen = sizeof(cfg); +static char buffer[cfgLen]; // populate runtime config with factory settings void defaultConfig(configData_t *myconfig) { @@ -66,7 +67,6 @@ void saveConfig(bool erase) { } // Copy device runtime config cfg to byte array - char buffer[cfgLen]; memcpy(buffer, &cfg, cfgLen); // save byte array to NVRAM @@ -90,7 +90,6 @@ void loadConfig() { } else { // load device runtime config from nvram and copy it to byte array - char *buffer = new char[cfgLen]; nvram.getBytes(DEVCONFIG, buffer, cfgLen); nvram.end(); From 502434abc432069b7432f3c01f7ac166f1c4d35e Mon Sep 17 00:00:00 2001 From: Klaus K Wilting Date: Sun, 4 Oct 2020 13:15:17 +0200 Subject: [PATCH 10/44] configmanager: improved error handling --- include/configmanager.h | 2 +- src/configmanager.cpp | 52 +++++++++++++++++++++++++++-------------- src/main.cpp | 2 +- 3 files changed, 36 insertions(+), 20 deletions(-) diff --git a/include/configmanager.h b/include/configmanager.h index 8da2e83c..e7d26438 100644 --- a/include/configmanager.h +++ b/include/configmanager.h @@ -5,7 +5,7 @@ #include "globals.h" void saveConfig(bool erase = false); -void loadConfig(void); +bool loadConfig(void); void eraseConfig(void); #endif \ No newline at end of file diff --git a/src/configmanager.cpp b/src/configmanager.cpp index 6c2efc4b..b74f4e0d 100644 --- a/src/configmanager.cpp +++ b/src/configmanager.cpp @@ -16,11 +16,12 @@ static const char TAG[] = __FILE__; Preferences nvram; -static const size_t cfgLen = sizeof(cfg); -static char buffer[cfgLen]; +static const char cfgMagicBytes[] = {0x21, 0x76, 0x87, 0x32, 0xf3}; +static const size_t cfgLen = sizeof(cfg), cfgLen2 = sizeof(cfgMagicBytes); +static char buffer[cfgLen + cfgLen2]; // populate runtime config with factory settings -void defaultConfig(configData_t *myconfig) { +static void defaultConfig(configData_t *myconfig) { char version[10]; snprintf(version, 10, "%-10s", PROGVERSION); @@ -56,45 +57,60 @@ void defaultConfig(configData_t *myconfig) { // save current configuration from RAM to NVRAM void saveConfig(bool erase) { - ESP_LOGI(TAG, "Storing settings in NVRAM"); + ESP_LOGI(TAG, "Storing settings to NVRAM..."); nvram.begin(DEVCONFIG, false); if (erase) { - ESP_LOGI(TAG, "Resetting NVRAM to factory settings"); + ESP_LOGI(TAG, "Resetting device to factory settings"); nvram.clear(); defaultConfig(&cfg); } - // Copy device runtime config cfg to byte array + // Copy device runtime config cfg to byte array, padding it with magicBytes memcpy(buffer, &cfg, cfgLen); + memcpy(buffer + cfgLen, &cfgMagicBytes, cfgLen2); + + // save byte array to NVRAM, padding with cfg magicbyes + if (nvram.putBytes(DEVCONFIG, buffer, cfgLen + cfgLen2)) + ESP_LOGI(TAG, "Device settings saved"); + else + ESP_LOGE(TAG, "NVRAM Error, device settings not saved"); - // save byte array to NVRAM - nvram.putBytes(DEVCONFIG, buffer, cfgLen); nvram.end(); } // load configuration from NVRAM into RAM and make it current -void loadConfig() { +bool loadConfig() { - ESP_LOGI(TAG, "Loading runtime settings from NVS"); + ESP_LOGI(TAG, "Loading device runtime configuration from NVRAM..."); if (!nvram.begin(DEVCONFIG, true)) { - ESP_LOGI(TAG, "Initializing NVRAM"); + ESP_LOGW(TAG, "NVRAM initialized, device starts with factory settings"); eraseConfig(); + return true; + } else { // simple check that runtime config data matches - if (nvram.getBytesLength(DEVCONFIG) != cfgLen) { - ESP_LOGW(TAG, "NVRAM settings invalid"); - eraseConfig(); + if (nvram.getBytesLength(DEVCONFIG) != (cfgLen + cfgLen2)) { + ESP_LOGE(TAG, "configuration invalid"); + return false; + } else { - // load device runtime config from nvram and copy it to byte array - nvram.getBytes(DEVCONFIG, buffer, cfgLen); + nvram.getBytes(DEVCONFIG, buffer, cfgLen + cfgLen2); nvram.end(); + // validate configuration by checking magic bytes at end of array + if (memcmp(buffer + cfgLen, &cfgMagicBytes, cfgLen2) != 0) { + ESP_LOGW(TAG, "No configuration found"); + return false; - // copy the byte array into runtime cfg struct - memcpy(&cfg, buffer, cfgLen); + } else { + // copy byte array into runtime cfg struct + memcpy(&cfg, buffer, cfgLen); + ESP_LOGI(TAG, "Runtime configuration loaded"); + return true; + } } } } diff --git a/src/main.cpp b/src/main.cpp index 175e78f0..e31b2b59 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -196,7 +196,7 @@ void setup() { #endif // read (and initialize on first run) runtime settings from NVRAM - loadConfig(); // includes initialize if necessary + assert(loadConfig()); // includes initialize if necessary // now that we are powered, we scan i2c bus for devices i2c_scan(); From 1186b000b61cd48f9426fa5a78b738a573ce9a52 Mon Sep 17 00:00:00 2001 From: Klaus K Wilting Date: Sun, 4 Oct 2020 14:29:57 +0200 Subject: [PATCH 11/44] some function renames for better code readability --- include/bmesensor.h | 2 +- include/cyclic.h | 4 ++-- include/mqttclient.h | 2 +- include/senddata.h | 4 ++-- include/timekeeper.h | 2 +- src/bmesensor.cpp | 4 ++-- src/cyclic.cpp | 4 ++-- src/main.cpp | 27 +++++++++++++++++---------- src/mqttclient.cpp | 4 ++-- src/rcommand.cpp | 4 ++-- src/senddata.cpp | 4 ++-- src/timekeeper.cpp | 10 +++++----- src/timesync.cpp | 2 +- 13 files changed, 40 insertions(+), 33 deletions(-) diff --git a/include/bmesensor.h b/include/bmesensor.h index d8ffaa7b..c0d17475 100644 --- a/include/bmesensor.h +++ b/include/bmesensor.h @@ -61,7 +61,7 @@ const uint8_t bsec_config_iaq[454] = { // Helper functions declarations int bme_init(); -void bmecycle(void); +void setBMEIRQ(void); void bme_storedata(bmeStatus_t *bme_store); int checkIaqSensorStatus(void); void loadState(void); diff --git a/include/cyclic.h b/include/cyclic.h index 0fdf38b1..6bd9b2a7 100644 --- a/include/cyclic.h +++ b/include/cyclic.h @@ -11,9 +11,9 @@ #include "sds011read.h" #include "sdcard.h" -extern Ticker housekeeper; +extern Ticker cyclicTimer; -void housekeeping(void); +void setCyclicIRQ(void); void doHousekeeping(void); uint64_t uptime(void); void reset_counters(void); diff --git a/include/mqttclient.h b/include/mqttclient.h index 5f942aa3..9b7ac649 100644 --- a/include/mqttclient.h +++ b/include/mqttclient.h @@ -26,7 +26,7 @@ extern TaskHandle_t mqttTask; void mqtt_enqueuedata(MessageBuffer_t *message); void mqtt_queuereset(void); -void mqtt_irq(void); +void setMqttIRQ(void); void mqtt_loop(void); void mqtt_client_task(void *param); int mqtt_connect(const char *my_host, const uint16_t my_port); diff --git a/include/senddata.h b/include/senddata.h index f1a43867..42686688 100644 --- a/include/senddata.h +++ b/include/senddata.h @@ -10,12 +10,12 @@ #include "sdcard.h" #include "corona.h" -extern Ticker sendcycler; +extern Ticker sendTimer; void SendPayload(uint8_t port, sendprio_t prio); void sendData(void); void checkSendQueues(void); void flushQueues(); -void sendcycle(void); +void setSendIRQ(void); #endif // _SENDDATA_H_ diff --git a/include/timekeeper.h b/include/timekeeper.h index 035cec6a..f9455746 100644 --- a/include/timekeeper.h +++ b/include/timekeeper.h @@ -17,7 +17,7 @@ void IRAM_ATTR CLOCKIRQ(void); void clock_init(void); void clock_loop(void *pvParameters); void timepulse_start(void); -void timeSync(void); +void setTimeSyncIRQ(void); uint8_t timepulse_init(void); time_t timeIsValid(time_t const t); void calibrateTime(void); diff --git a/src/bmesensor.cpp b/src/bmesensor.cpp index 8e3f57ba..2cedc35d 100644 --- a/src/bmesensor.cpp +++ b/src/bmesensor.cpp @@ -44,7 +44,7 @@ Adafruit_BMP085 bmp; // I2C #endif -void bmecycle() { xTaskNotify(irqHandlerTask, BME_IRQ, eSetBits); } +void setBMEIRQ() { xTaskNotify(irqHandlerTask, BME_IRQ, eSetBits); } // initialize BME680 sensor int bme_init(void) { @@ -133,7 +133,7 @@ int bme_init(void) { finish: I2C_MUTEX_UNLOCK(); // release i2c bus access if (rc) - bmecycler.attach(BMECYCLE, bmecycle); + bmecycler.attach(BMECYCLE, setBMEIRQ); return rc; } // bme_init() diff --git a/src/cyclic.cpp b/src/cyclic.cpp index 96521a61..b9c450a3 100644 --- a/src/cyclic.cpp +++ b/src/cyclic.cpp @@ -7,13 +7,13 @@ // Local logging tag static const char TAG[] = __FILE__; -Ticker housekeeper; +Ticker cyclicTimer; #if (HAS_SDS011) extern boolean isSDS011Active; #endif -void housekeeping() { +void setCyclicIRQ() { xTaskNotifyFromISR(irqHandlerTask, CYCLIC_IRQ, eSetBits, NULL); } diff --git a/src/main.cpp b/src/main.cpp index e31b2b59..bcecd934 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -55,17 +55,24 @@ So don't do it if you do not own a digital oscilloscope. // Interrupt routines ------------------------------------------------------------------------------- +irqHandlerTask (Core 1), see irqhandler.cpp + fired by hardware -DisplayIRQ -> esp32 timer 0 -> irqHandlerTask (Core 1) -CLOCKIRQ -> esp32 timer 1 -> ClockTask (Core 1) -ButtonIRQ -> external gpio -> irqHandlerTask (Core 1) -PMUIRQ -> PMU chip gpio -> irqHandlerTask (Core 1) +DisplayIRQ -> esp32 timer 0 +ButtonIRQ -> external gpio +PMUIRQ -> PMU chip gpio fired by software (Ticker.h) -TIMESYNC_IRQ -> timeSync() -> irqHandlerTask (Core 1) -CYCLIC_IRQ -> housekeeping() -> irqHandlerTask (Core 1) -SENDCYCLE_IRQ -> sendcycle() -> irqHandlerTask (Core 1) -BME_IRQ -> bmecycle() -> irqHandlerTask (Core 1) +TIMESYNC_IRQ -> setTimeSyncIRQ() +CYCLIC_IRQ -> setCyclicIRQ() +SENDCYCLE_IRQ -> setSendIRQ() +BME_IRQ -> setBMEIRQ() +MQTT_IRQ -> setMqttIRQ() + +ClockTask (Core 1), see timekeeper.cpp + +fired by hardware +CLOCKIRQ -> esp32 timer 1 // External RTC timer (if present) @@ -478,8 +485,8 @@ void setup() { #endif // HAS_BUTTON // cyclic function interrupts - sendcycler.attach(SENDCYCLE * 2, sendcycle); - housekeeper.attach(HOMECYCLE, housekeeping); + sendTimer.attach(cfg.sendcycle * 2, setSendIRQ); + cyclicTimer.attach(HOMECYCLE, setCyclicIRQ); #if (TIME_SYNC_INTERVAL) diff --git a/src/mqttclient.cpp b/src/mqttclient.cpp index e9333c8a..9eb2567f 100644 --- a/src/mqttclient.cpp +++ b/src/mqttclient.cpp @@ -33,7 +33,7 @@ esp_err_t mqtt_init(void) { SEND_QUEUE_SIZE * PAYLOAD_BUFFER_SIZE); ESP_LOGI(TAG, "Starting MQTTloop..."); - mqttTimer.attach(MQTT_KEEPALIVE, mqtt_irq); + mqttTimer.attach(MQTT_KEEPALIVE, setMqttIRQ); xTaskCreate(mqtt_client_task, "mqttloop", 4096, (void *)NULL, 1, &mqttTask); return ESP_OK; @@ -183,6 +183,6 @@ void mqtt_loop(void) { } void mqtt_queuereset(void) { xQueueReset(MQTTSendQueue); } -void mqtt_irq(void) { xTaskNotify(irqHandlerTask, MQTT_IRQ, eSetBits); } +void setMqttIRQ(void) { xTaskNotify(irqHandlerTask, MQTT_IRQ, eSetBits); } #endif // HAS_MQTT \ No newline at end of file diff --git a/src/rcommand.cpp b/src/rcommand.cpp index 225b6f17..335eef9c 100644 --- a/src/rcommand.cpp +++ b/src/rcommand.cpp @@ -49,7 +49,7 @@ void set_rssi(uint8_t val[]) { void set_sendcycle(uint8_t val[]) { cfg.sendcycle = val[0]; // update send cycle interrupt [seconds / 2] - sendcycler.attach(cfg.sendcycle * 2, sendcycle); + sendTimer.attach(cfg.sendcycle * 2, setSendIRQ); ESP_LOGI(TAG, "Remote command: set send cycle to %d seconds", cfg.sendcycle * 2); } @@ -330,7 +330,7 @@ void get_time(uint8_t val[]) { void set_time(uint8_t val[]) { ESP_LOGI(TAG, "Timesync requested by timeserver"); - timeSync(); + setTimeSyncIRQ(); }; void set_flush(uint8_t val[]) { diff --git a/src/senddata.cpp b/src/senddata.cpp index a9ca74ea..53b5dc7f 100644 --- a/src/senddata.cpp +++ b/src/senddata.cpp @@ -1,9 +1,9 @@ // Basic Config #include "senddata.h" -Ticker sendcycler; +Ticker sendTimer; -void sendcycle() { +void setSendIRQ() { xTaskNotifyFromISR(irqHandlerTask, SENDCYCLE_IRQ, eSetBits, NULL); } diff --git a/src/timekeeper.cpp b/src/timekeeper.cpp index 21513a05..b0a23e93 100644 --- a/src/timekeeper.cpp +++ b/src/timekeeper.cpp @@ -23,7 +23,7 @@ HardwareSerial IF482(2); // use UART #2 (#1 may be in use for serial GPS) Ticker timesyncer; -void timeSync() { xTaskNotify(irqHandlerTask, TIMESYNC_IRQ, eSetBits); } +void setTimeSyncIRQ() { xTaskNotify(irqHandlerTask, TIMESYNC_IRQ, eSetBits); } void calibrateTime(void) { ESP_LOGD(TAG, "[%0.3f] calibrateTime, timeSource == %d", millis() / 1000.0, @@ -104,11 +104,11 @@ void IRAM_ATTR setMyTime(uint32_t t_sec, uint16_t t_msec, setTime(time_to_set); // set the time on top of second timeSource = mytimesource; // set global variable - timesyncer.attach(TIME_SYNC_INTERVAL * 60, timeSync); + timesyncer.attach(TIME_SYNC_INTERVAL * 60, setTimeSyncIRQ); ESP_LOGI(TAG, "[%0.3f] Timesync finished, time was set | source: %c", millis() / 1000.0, timeSetSymbols[mytimesource]); } else { - timesyncer.attach(TIME_SYNC_INTERVAL_RETRY * 60, timeSync); + timesyncer.attach(TIME_SYNC_INTERVAL_RETRY * 60, setTimeSyncIRQ); ESP_LOGI(TAG, "[%0.3f] Timesync failed, invalid time fetched | source: %c", millis() / 1000.0, timeSetSymbols[mytimesource]); } @@ -167,8 +167,8 @@ void timepulse_start(void) { #endif // start cyclic time sync - timeSync(); // init systime by RTC or GPS or LORA - timesyncer.attach(TIME_SYNC_INTERVAL * 60, timeSync); + setTimeSyncIRQ(); // init systime by RTC or GPS or LORA + timesyncer.attach(TIME_SYNC_INTERVAL * 60, setTimeSyncIRQ); } // interrupt service routine triggered by either pps or esp32 hardware timer diff --git a/src/timesync.cpp b/src/timesync.cpp index 088ff59f..373e55ca 100644 --- a/src/timesync.cpp +++ b/src/timesync.cpp @@ -151,7 +151,7 @@ void IRAM_ATTR timesync_processReq(void *taskparameter) { Fail: // set retry timer - timesyncer.attach(TIME_SYNC_INTERVAL_RETRY * 60, timeSync); + timesyncer.attach(TIME_SYNC_INTERVAL_RETRY * 60, setTimeSyncIRQ); Finish: // end of time critical section: release app irq lock From 1cbf0d7124ee1e000338357ce538d2c8d632d6df Mon Sep 17 00:00:00 2001 From: Klaus K Wilting Date: Sun, 4 Oct 2020 14:50:24 +0200 Subject: [PATCH 12/44] readme.md enhanced instructions to make the code --- README.md | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 93b11a8d..6d4d0492 100644 --- a/README.md +++ b/README.md @@ -83,12 +83,16 @@ By default bluetooth sniffing not installed (#define *BLECOUNTER* 0 in paxcounte # Preparing +## Install Platformio + +Install PlatformIO IDE for embedded development to make this project. Platformio integrates with your favorite IDE, choose eg. Visual Studio, Atom, Eclipse etc. + Compile time configuration is spread across several files. Before compiling the code, edit or create the following files: -## platformio_orig.ini -Edit `platformio_orig.ini` and select desired hardware target in section boards. To add a new board, create an appropriate hardware abstraction layer file in hal subdirectory, and add a pointer to this file in sections board. Copy or rename to `platformio.ini`. +## platformio.ini +Edit `platformio_orig.ini` and select desired hardware target in section boards. To add a new board, create an appropriate hardware abstraction layer file in hal subdirectory, and add a pointer to this file in sections board. Copy or rename to `platformio.ini` in the root directory of the project. Now start Platformio. Note: Platformio is looking for `platformio.ini` in the root directory and won't start if it does not find this file. -## src/paxcounter_orig.conf +## src/paxcounter.conf Edit `src/paxcounter_orig.conf` and tailor settings in this file according to your needs and use case. Please take care of the duty cycle regulations of the LoRaWAN network you're going to use. Copy or rename to `src/paxcounter.conf`. If your device has a **real time clock** it can be updated bei either LoRaWAN network or GPS time, according to settings *TIME_SYNC_INTERVAL* and *TIME_SYNC_LORAWAN* in `paxcounter.conf`. From a90f3d07da14ad455fd067e0d8ed4e2e69673d6b Mon Sep 17 00:00:00 2001 From: Chrisotph Schultz Date: Sun, 4 Oct 2020 15:42:38 +0200 Subject: [PATCH 13/44] updated bord comment to //ttgo-lora32-v21new --- src/hal/ttgov21new.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/hal/ttgov21new.h b/src/hal/ttgov21new.h index 4b08748d..f4583bdc 100644 --- a/src/hal/ttgov21new.h +++ b/src/hal/ttgov21new.h @@ -1,6 +1,6 @@ // clang-format off // upload_speed 921600 -// board esp32dev +// board ttgo-lora32-v21new #ifndef _TTGOV21NEW_H #define _TTGOV21NEW_H From 414bc414048609d2b8d5edd21f4d9b323966bf24 Mon Sep 17 00:00:00 2001 From: Klaus K Wilting Date: Sun, 4 Oct 2020 19:10:36 +0200 Subject: [PATCH 14/44] configmanager: enhancements for version migration --- include/configmanager.h | 3 +- include/globals.h | 5 +- include/ota.h | 4 +- src/configmanager.cpp | 104 +++++++++++++++++++++++++++------------- src/ota.cpp | 18 ------- 5 files changed, 78 insertions(+), 56 deletions(-) diff --git a/include/configmanager.h b/include/configmanager.h index e7d26438..d196e6ab 100644 --- a/include/configmanager.h +++ b/include/configmanager.h @@ -1,11 +1,12 @@ #ifndef _CONFIGMANAGER_H #define _CONFIGMANAGER_H -#include #include "globals.h" +#include void saveConfig(bool erase = false); bool loadConfig(void); void eraseConfig(void); +int version_compare(const String v1, const String v2); #endif \ No newline at end of file diff --git a/include/globals.h b/include/globals.h index ba9319ff..af963f77 100644 --- a/include/globals.h +++ b/include/globals.h @@ -60,8 +60,10 @@ enum runmode_t { }; // Struct holding devices's runtime configuration -// using packed to avoid compiler padding, because struct will be memcpy'd to byte array +// using packed to avoid compiler padding, because struct will be memcpy'd to +// byte array typedef struct __attribute__((packed)) { + char version[10]; // Firmware version uint8_t loradr; // 0-15, lora datarate uint8_t txpower; // 2-15, lora tx power uint8_t adrmode; // 0=disabled, 1=enabled @@ -80,7 +82,6 @@ typedef struct __attribute__((packed)) { uint8_t monitormode; // 0=disabled, 1=enabled uint8_t runmode; // 0=normal, 1=update uint8_t payloadmask; // bitswitches for payload data - char version[10]; // Firmware version #ifdef HAS_BME680 uint8_t bsecstate[BSEC_MAX_STATE_BLOB_SIZE + 1]; // BSEC state for BME680 sensor diff --git a/include/ota.h b/include/ota.h index 900ef530..9e53cae1 100644 --- a/include/ota.h +++ b/include/ota.h @@ -6,17 +6,15 @@ #include "globals.h" #include "led.h" #include "display.h" +#include "configmanager.h" #include #include #include #include -#include -#include int do_ota_update(); void start_ota_update(); -int version_compare(const String v1, const String v2); void ota_display(const uint8_t row, const std::string status, const std::string msg); void show_progress(unsigned long current, unsigned long size); diff --git a/src/configmanager.cpp b/src/configmanager.cpp index b74f4e0d..7c1c2dd0 100644 --- a/src/configmanager.cpp +++ b/src/configmanager.cpp @@ -16,16 +16,20 @@ static const char TAG[] = __FILE__; Preferences nvram; -static const char cfgMagicBytes[] = {0x21, 0x76, 0x87, 0x32, 0xf3}; +static const uint8_t cfgMagicBytes[] = {0x21, 0x76, 0x87, 0x32, 0xf4}; static const size_t cfgLen = sizeof(cfg), cfgLen2 = sizeof(cfgMagicBytes); -static char buffer[cfgLen + cfgLen2]; +static uint8_t buffer[cfgLen + cfgLen2]; -// populate runtime config with factory settings +// populate runtime config with device factory settings static void defaultConfig(configData_t *myconfig) { - char version[10]; - snprintf(version, 10, "%-10s", PROGVERSION); + // char version[10]; + // snprintf(version, 10, "%-10s", PROGVERSION); + // memcpy(myconfig->version, version, 10); // Firmware version [exactly 10 + // chars] + memcpy(myconfig->version, &PROGVERSION, + 10); // Firmware version [exactly 10 chars] - // factory settings + // device factory settings myconfig->loradr = LORADRDEFAULT; // 0-15, lora datarate, see paxcounter.conf myconfig->txpower = LORATXPOWDEFAULT; // 0-15, lora tx power myconfig->adrmode = 1; // 0=disabled, 1=enabled @@ -43,11 +47,10 @@ static void defaultConfig(configData_t *myconfig) { myconfig->blescan = 1; // 0=disabled, 1=enabled myconfig->wifiscan = 1; // 0=disabled, 1=enabled myconfig->wifiant = 0; // 0=internal, 1=external (for LoPy/LoPy4) - myconfig->vendorfilter = VENDORFILTER; // 0=disabled, 1=enabled - myconfig->rgblum = RGBLUMINOSITY; // RGB Led luminosity (0..100%) - myconfig->monitormode = 0; // 0=disabled, 1=enabled - myconfig->payloadmask = PAYLOADMASK; // all payload switched on - memcpy(myconfig->version, version, 10); // Firmware version [exactly 10 chars] + myconfig->vendorfilter = VENDORFILTER; // 0=disabled, 1=enabled + myconfig->rgblum = RGBLUMINOSITY; // RGB Led luminosity (0..100%) + myconfig->monitormode = 0; // 0=disabled, 1=enabled + myconfig->payloadmask = PAYLOADMASK; // all payload switched on #ifdef HAS_BME680 // initial BSEC state for BME680 sensor @@ -55,6 +58,15 @@ static void defaultConfig(configData_t *myconfig) { #endif } +// migrate runtime config from earlier version to current +static void migrateConfig(void) { + // currently no migration rules are implemented, we just reset config to + // factory settings + ESP_LOGI(TAG, "Migrating device configuration from %s to %s", cfg.version, + PROGVERSION); + eraseConfig(); +} + // save current configuration from RAM to NVRAM void saveConfig(bool erase) { ESP_LOGI(TAG, "Storing settings to NVRAM..."); @@ -89,30 +101,58 @@ bool loadConfig() { ESP_LOGW(TAG, "NVRAM initialized, device starts with factory settings"); eraseConfig(); return true; + } - } else { - // simple check that runtime config data matches - if (nvram.getBytesLength(DEVCONFIG) != (cfgLen + cfgLen2)) { - ESP_LOGE(TAG, "configuration invalid"); - return false; + // simple check that runtime config data matches + if (nvram.getBytesLength(DEVCONFIG) != (cfgLen + cfgLen2)) { + ESP_LOGE(TAG, "Configuration invalid"); + return false; + } - } else { - // load device runtime config from nvram and copy it to byte array - nvram.getBytes(DEVCONFIG, buffer, cfgLen + cfgLen2); - nvram.end(); - // validate configuration by checking magic bytes at end of array - if (memcmp(buffer + cfgLen, &cfgMagicBytes, cfgLen2) != 0) { - ESP_LOGW(TAG, "No configuration found"); - return false; + // load device runtime config from nvram and copy it to byte array + nvram.getBytes(DEVCONFIG, buffer, cfgLen + cfgLen2); + nvram.end(); - } else { - // copy byte array into runtime cfg struct - memcpy(&cfg, buffer, cfgLen); - ESP_LOGI(TAG, "Runtime configuration loaded"); - return true; - } - } + // validate loaded configuration by checking magic bytes at end of array + if (memcmp(buffer + cfgLen, &cfgMagicBytes, cfgLen2) != 0) { + ESP_LOGW(TAG, "No configuration found"); + return false; + } + + // copy loaded configuration into runtime cfg struct + memcpy(&cfg, buffer, cfgLen); + ESP_LOGI(TAG, "Runtime configuration v%s loaded", cfg.version); + + // check if config version matches current firmware version + switch (version_compare(PROGVERSION, cfg.version)) { + case -1: // device configuration belongs to newer than current firmware + ESP_LOGE(TAG, "Incompatible device configuration, aborting"); + return false; + case 1: // device configuration belongs to older than current firmware + ESP_LOGW(TAG, "Device was updated, migrating device configuration"); + migrateConfig(); + return true; + default: // device configuration version matches current firmware version + return true; } } -void eraseConfig(void) { saveConfig(true); } +// helper function to convert strings into lower case +bool comp(char s1, char s2) { return (tolower(s1) < tolower(s2)); } + +// helper function to lexicographically compare two versions. Returns 1 if v2 +// is smaller, -1 if v1 is smaller, 0 if equal +int version_compare(const String v1, const String v2) { + + if (v1 == v2) + return 0; + + const char *a1 = v1.c_str(), *a2 = v2.c_str(); + + if (std::lexicographical_compare(a1, a1 + strlen(a1), a2, a2 + strlen(a2), comp)) + return -1; + else + return 1; +} + +void eraseConfig(void) { saveConfig(true); } \ No newline at end of file diff --git a/src/ota.cpp b/src/ota.cpp index 95d780f8..c256559e 100644 --- a/src/ota.cpp +++ b/src/ota.cpp @@ -328,22 +328,4 @@ void show_progress(unsigned long current, unsigned long size) { #endif } -// helper function to convert strings into lower case -bool comp(char s1, char s2) { return tolower(s1) < tolower(s2); } - -// helper function to lexicographically compare two versions. Returns 1 if v2 is -// smaller, -1 if v1 is smaller, 0 if equal -int version_compare(const String v1, const String v2) { - - if (v1 == v2) - return 0; - - const char *a1 = v1.c_str(), *a2 = v2.c_str(); - - if (lexicographical_compare(a1, a1 + strlen(a1), a2, a2 + strlen(a2), comp)) - return -1; - else - return 1; -} - #endif // USE_OTA \ No newline at end of file From ad72fa9e41c77c622c35196adecfff3b0cf57e31 Mon Sep 17 00:00:00 2001 From: Klaus K Wilting Date: Sun, 4 Oct 2020 19:25:49 +0200 Subject: [PATCH 15/44] configmanager cleanups --- src/configmanager.cpp | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/src/configmanager.cpp b/src/configmanager.cpp index 7c1c2dd0..52439a1e 100644 --- a/src/configmanager.cpp +++ b/src/configmanager.cpp @@ -58,12 +58,10 @@ static void defaultConfig(configData_t *myconfig) { #endif } -// migrate runtime config from earlier version to current +// migrate runtime configuration from earlier to current version static void migrateConfig(void) { // currently no migration rules are implemented, we just reset config to // factory settings - ESP_LOGI(TAG, "Migrating device configuration from %s to %s", cfg.version, - PROGVERSION); eraseConfig(); } @@ -95,10 +93,10 @@ void saveConfig(bool erase) { // load configuration from NVRAM into RAM and make it current bool loadConfig() { - ESP_LOGI(TAG, "Loading device runtime configuration from NVRAM..."); + ESP_LOGI(TAG, "Loading device configuration from NVRAM..."); if (!nvram.begin(DEVCONFIG, true)) { - ESP_LOGW(TAG, "NVRAM initialized, device starts with factory settings"); + ESP_LOGI(TAG, "NVRAM initialized, device starts with factory settings"); eraseConfig(); return true; } @@ -126,10 +124,10 @@ bool loadConfig() { // check if config version matches current firmware version switch (version_compare(PROGVERSION, cfg.version)) { case -1: // device configuration belongs to newer than current firmware - ESP_LOGE(TAG, "Incompatible device configuration, aborting"); + ESP_LOGE(TAG, "Incompatible device configuration"); return false; case 1: // device configuration belongs to older than current firmware - ESP_LOGW(TAG, "Device was updated, migrating device configuration"); + ESP_LOGW(TAG, "Device was updated, attempt to migrate configuration"); migrateConfig(); return true; default: // device configuration version matches current firmware version @@ -149,7 +147,8 @@ int version_compare(const String v1, const String v2) { const char *a1 = v1.c_str(), *a2 = v2.c_str(); - if (std::lexicographical_compare(a1, a1 + strlen(a1), a2, a2 + strlen(a2), comp)) + if (std::lexicographical_compare(a1, a1 + strlen(a1), a2, a2 + strlen(a2), + comp)) return -1; else return 1; From 5dc44a02fbdf96a376fdac7ea9601401d1f09a3c Mon Sep 17 00:00:00 2001 From: Klaus K Wilting Date: Sun, 4 Oct 2020 19:32:22 +0200 Subject: [PATCH 16/44] configmanager comments added --- src/configmanager.cpp | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/src/configmanager.cpp b/src/configmanager.cpp index 52439a1e..d75bc8bd 100644 --- a/src/configmanager.cpp +++ b/src/configmanager.cpp @@ -21,13 +21,14 @@ static const size_t cfgLen = sizeof(cfg), cfgLen2 = sizeof(cfgMagicBytes); static uint8_t buffer[cfgLen + cfgLen2]; // populate runtime config with device factory settings +// +// configuration frame structure in NVRAM; +// 1. version header [10 bytes, containing version string] +// 2. user settings [cfgLen bytes, containing default runtime settings (configData_t cfg)] +// 3. magicByte [cfgLen2 bytes, containing a fixed identifier] + static void defaultConfig(configData_t *myconfig) { - // char version[10]; - // snprintf(version, 10, "%-10s", PROGVERSION); - // memcpy(myconfig->version, version, 10); // Firmware version [exactly 10 - // chars] - memcpy(myconfig->version, &PROGVERSION, - 10); // Firmware version [exactly 10 chars] + memcpy(myconfig->version, &PROGVERSION, 10); // Firmware version // device factory settings myconfig->loradr = LORADRDEFAULT; // 0-15, lora datarate, see paxcounter.conf From cae92514bb250471629a5122a841d9af6354ba01 Mon Sep 17 00:00:00 2001 From: Chrisotph Schultz Date: Sun, 4 Oct 2020 22:58:29 +0200 Subject: [PATCH 17/44] adding Set ENS counter on/off via rcomd 0x18 00|01 --- README.md | 4 +++ include/cyclic.h | 2 +- include/globals.h | 1 + src/blecsan.cpp | 7 +++-- src/configmanager.cpp | 1 + src/cyclic.cpp | 2 +- src/display.cpp | 15 +++++----- src/hal/ttgov21new.h | 2 +- src/main.cpp | 2 +- src/rcommand.cpp | 70 ++++++++++++++++++++++++++++++------------- src/sensor.cpp | 6 ++-- 11 files changed, 74 insertions(+), 38 deletions(-) diff --git a/README.md b/README.md index 93b11a8d..33c6c2bb 100644 --- a/README.md +++ b/README.md @@ -504,6 +504,10 @@ Send for example `8386` as Downlink on Port 2 to get battery status and time/dat 0 = disabled 1 = enabled [default] + +0x18 set ENS counter on/off + 0 = disabled (default) + 1 = enabled 0x80 get device configuration diff --git a/include/cyclic.h b/include/cyclic.h index 6bd9b2a7..732f2843 100644 --- a/include/cyclic.h +++ b/include/cyclic.h @@ -11,7 +11,7 @@ #include "sds011read.h" #include "sdcard.h" -extern Ticker cyclicTimer; +extern Ticker housekeeper; void setCyclicIRQ(void); void doHousekeeping(void); diff --git a/include/globals.h b/include/globals.h index ba9319ff..fddbc9fc 100644 --- a/include/globals.h +++ b/include/globals.h @@ -80,6 +80,7 @@ typedef struct __attribute__((packed)) { uint8_t monitormode; // 0=disabled, 1=enabled uint8_t runmode; // 0=normal, 1=update uint8_t payloadmask; // bitswitches for payload data + uint8_t enscount; // 0=disabled 1= enabled char version[10]; // Firmware version #ifdef HAS_BME680 uint8_t diff --git a/src/blecsan.cpp b/src/blecsan.cpp index 288757a0..c7085276 100644 --- a/src/blecsan.cpp +++ b/src/blecsan.cpp @@ -168,11 +168,12 @@ IRAM_ATTR void gap_callback_handler(esp_gap_ble_cb_event_t event, mac_add((uint8_t *)p->scan_rst.bda, p->scan_rst.rssi, MAC_SNIFF_BLE); -#if (COUNT_ENS) + if (cfg.enscount){ // check for ens signature - if (NULL != strstr((const char *)p->scan_rst.ble_adv, ensMagicBytes)) + if (NULL != strstr((const char *)p->scan_rst.ble_adv, ensMagicBytes)) cwa_mac_add(hashedmac); -#endif + } + /* to be improved in vendorfilter if: // you can search for elements in the payload using the diff --git a/src/configmanager.cpp b/src/configmanager.cpp index b74f4e0d..ef53fd29 100644 --- a/src/configmanager.cpp +++ b/src/configmanager.cpp @@ -47,6 +47,7 @@ static void defaultConfig(configData_t *myconfig) { myconfig->rgblum = RGBLUMINOSITY; // RGB Led luminosity (0..100%) myconfig->monitormode = 0; // 0=disabled, 1=enabled myconfig->payloadmask = PAYLOADMASK; // all payload switched on + myconfig->enscount =0; // 0= disabled, 1 = enabled memcpy(myconfig->version, version, 10); // Firmware version [exactly 10 chars] #ifdef HAS_BME680 diff --git a/src/cyclic.cpp b/src/cyclic.cpp index b9c450a3..0b484065 100644 --- a/src/cyclic.cpp +++ b/src/cyclic.cpp @@ -7,7 +7,7 @@ // Local logging tag static const char TAG[] = __FILE__; -Ticker cyclicTimer; +Ticker housekeeper; #if (HAS_SDS011) extern boolean isSDS011Active; diff --git a/src/display.cpp b/src/display.cpp index aa2289ee..c8d88694 100644 --- a/src/display.cpp +++ b/src/display.cpp @@ -265,11 +265,10 @@ void dp_drawPage(time_t t, bool nextpage) { else dp_printf("WIFI:off"); if (cfg.blescan) -#if (!COUNT_ENS) - dp_printf("BLTH:%-5d", macs_ble); -#else + if (!cfg.enscount) + dp_printf("BLTH:%-5d", macs_ble); + else dp_printf(" CWA:%-5d", cwa_report()); -#endif else dp_printf(" BLTH:off"); #elif ((WIFICOUNTER) && (!BLECOUNTER)) @@ -280,10 +279,10 @@ void dp_drawPage(time_t t, bool nextpage) { #elif ((!WIFICOUNTER) && (BLECOUNTER)) if (cfg.blescan) { dp_printf("BLTH:%-5d", macs_ble); -#if (COUNT_ENS) - dp_printf("(CWA:%d)", cwa_report()); -#endif - } else + if (cfg.enscount) + dp_printf("(CWA:%d)", cwa_report()); + } + else dp_printf("BLTH:off"); #else dp_printf("Sniffer disabled"); diff --git a/src/hal/ttgov21new.h b/src/hal/ttgov21new.h index f4583bdc..4b08748d 100644 --- a/src/hal/ttgov21new.h +++ b/src/hal/ttgov21new.h @@ -1,6 +1,6 @@ // clang-format off // upload_speed 921600 -// board ttgo-lora32-v21new +// board esp32dev #ifndef _TTGOV21NEW_H #define _TTGOV21NEW_H diff --git a/src/main.cpp b/src/main.cpp index bcecd934..cf70f79d 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -486,7 +486,7 @@ void setup() { // cyclic function interrupts sendTimer.attach(cfg.sendcycle * 2, setSendIRQ); - cyclicTimer.attach(HOMECYCLE, setCyclicIRQ); + housekeeper.attach(HOMECYCLE, setCyclicIRQ); #if (TIME_SYNC_INTERVAL) diff --git a/src/rcommand.cpp b/src/rcommand.cpp index 335eef9c..58bc8ca7 100644 --- a/src/rcommand.cpp +++ b/src/rcommand.cpp @@ -339,27 +339,55 @@ void set_flush(uint8_t val[]) { // used to open receive window on LoRaWAN class a nodes }; -// assign previously defined functions to set of numeric remote commands -// format: opcode, function, #bytes params, -// flag (true = do make settings persistent / false = don't) -// -static const cmd_t table[] = { - {0x01, set_rssi, 1, true}, {0x02, set_countmode, 1, true}, - {0x03, set_gps, 1, true}, {0x04, set_display, 1, true}, - {0x05, set_loradr, 1, true}, {0x06, set_lorapower, 1, true}, - {0x07, set_loraadr, 1, true}, {0x08, set_screensaver, 1, true}, - {0x09, set_reset, 1, false}, {0x0a, set_sendcycle, 1, true}, - {0x0b, set_wifichancycle, 1, true}, {0x0c, set_blescantime, 1, true}, - {0x0d, set_vendorfilter, 1, false}, {0x0e, set_blescan, 1, true}, - {0x0f, set_wifiant, 1, true}, {0x10, set_rgblum, 1, true}, - {0x11, set_monitor, 1, true}, {0x12, set_beacon, 7, false}, - {0x13, set_sensor, 2, true}, {0x14, set_payloadmask, 1, true}, - {0x15, set_bme, 1, true}, {0x16, set_batt, 1, true}, - {0x17, set_wifiscan, 1, true}, {0x80, get_config, 0, false}, - {0x81, get_status, 0, false}, {0x83, get_batt, 0, false}, - {0x84, get_gps, 0, false}, {0x85, get_bme, 0, false}, - {0x86, get_time, 0, false}, {0x87, set_time, 0, false}, - {0x99, set_flush, 0, false}}; +void set_enscount(uint8_t val[]) { + ESP_LOGI(TAG, "Remote command: set ENS_COUNT to %s", + val[0] ? "on" : "off"); + cfg.enscount = val[0] ? 1 : 0; + if (val[0]) + cfg.payloadmask |= SENSOR1_DATA; + else + cfg.payloadmask &= ~SENSOR1_DATA; + + +} + + // assign previously defined functions to set of numeric remote commands + // format: opcode, function, #bytes params, + // flag (true = do make settings persistent / false = don't) + // + static const cmd_t table[] = { + {0x01, set_rssi, 1, true}, + {0x02, set_countmode, 1, true}, + {0x03, set_gps, 1, true}, + {0x04, set_display, 1, true}, + {0x05, set_loradr, 1, true}, + {0x06, set_lorapower, 1, true}, + {0x07, set_loraadr, 1, true}, + {0x08, set_screensaver, 1, true}, + {0x09, set_reset, 1, false}, + {0x0a, set_sendcycle, 1, true}, + {0x0b, set_wifichancycle, 1, true}, + {0x0c, set_blescantime, 1, true}, + {0x0d, set_vendorfilter, 1, false}, + {0x0e, set_blescan, 1, true}, + {0x0f, set_wifiant, 1, true}, + {0x10, set_rgblum, 1, true}, + {0x11, set_monitor, 1, true}, + {0x12, set_beacon, 7, false}, + {0x13, set_sensor, 2, true}, + {0x14, set_payloadmask, 1, true}, + {0x15, set_bme, 1, true}, + {0x16, set_batt, 1, true}, + {0x17, set_wifiscan, 1, true}, + {0x18, set_enscount, 1, true}, + {0x80, get_config, 0, false}, + {0x81, get_status, 0, false}, + {0x83, get_batt, 0, false}, + {0x84, get_gps, 0, false}, + {0x85, get_bme, 0, false}, + {0x86, get_time, 0, false}, + {0x87, set_time, 0, false}, + {0x99, set_flush, 0, false}}; static const uint8_t cmdtablesize = sizeof(table) / sizeof(table[0]); // number of commands in command table diff --git a/src/sensor.cpp b/src/sensor.cpp index 3b5f9e2d..a8901505 100644 --- a/src/sensor.cpp +++ b/src/sensor.cpp @@ -56,16 +56,18 @@ uint8_t *sensor_read(uint8_t sensor) { // insert user specific sensor data frames here // note: Sensor1 fields are used for ENS count, if ENS detection enabled -#if (COUNT_ENS) +#if COUNT_ENS +if (cfg.enscount) payload.addCount(cwa_report(), MAC_SNIFF_BLE_CWA); #else + if(!cfg.enscount) buf[0] = length; buf[1] = 0x01; buf[2] = 0x02; buf[3] = 0x03; + #endif break; - case 2: buf[0] = length; From b0d3dfebb57c110aaccccee6cdbe7dff3189ea94 Mon Sep 17 00:00:00 2001 From: Klaus K Wilting Date: Sun, 4 Oct 2020 23:13:17 +0200 Subject: [PATCH 18/44] gpsread.cpp: NMEA ZDA processing improved --- src/gpsread.cpp | 33 ++++++++++++++++----------------- 1 file changed, 16 insertions(+), 17 deletions(-) diff --git a/src/gpsread.cpp b/src/gpsread.cpp index 5589f4b2..b6395384 100644 --- a/src/gpsread.cpp +++ b/src/gpsread.cpp @@ -12,7 +12,10 @@ static const char TAG[] = __FILE__; // thus precision is only +/- 1 second TinyGPSPlus gps; -TinyGPSCustom gpstime(gps, "GPZDA", 1); // field 1 = UTC time +TinyGPSCustom gpstime(gps, "GPZDA", 1); // field 1 = UTC time (hhmmss.ss) +TinyGPSCustom gpsday(gps, "GPZDA", 2); // field 2 = day (01..31) +TinyGPSCustom gpsmonth(gps, "GPZDA", 3); // field 3 = month (01..12) +TinyGPSCustom gpsyear(gps, "GPZDA", 4); // field 4 = year (4-digit) static const String ZDA_Request = "$EIGPQ,ZDA*39\r\n"; TaskHandle_t GpsTask; @@ -102,34 +105,30 @@ time_t get_gpstime(uint16_t *msec) { #ifdef GPS_SERIAL GPS_Serial.print(ZDA_Request); // wait for gps NMEA answer - vTaskDelay(tx_Ticks(NMEA_FRAME_SIZE, GPS_SERIAL)); + // vTaskDelay(tx_Ticks(NMEA_FRAME_SIZE, GPS_SERIAL)); #elif defined GPS_I2C Wire.print(ZDA_Request); #endif - // did we get a current time? - if (gpstime.isUpdated() && gpstime.isValid()) { + // did we get a current date & time? + if (gpstime.isUpdated() && gpstime.isValid() && gpsday.isValid()) { tmElements_t tm; - String rawtime = gpstime.value(); - uint32_t time_bcd = rawtime.toFloat() * 100; + uint32_t time_bcd = atof(gpstime.value()) * 100; uint32_t delay_ms = gpstime.age() + nmea_txDelay_ms + NMEA_COMPENSATION_FACTOR; - uint8_t year = - CalendarYrToTm(gps.date.year()); // year offset from 1970 in microTime.h - - ESP_LOGD(TAG, "time [bcd]: %u", time_bcd); tm.Second = (time_bcd / 100) % 100; // second tm.Minute = (time_bcd / 10000) % 100; // minute tm.Hour = time_bcd / 1000000; // hour - tm.Day = gps.date.day(); // day - tm.Month = gps.date.month(); // month - tm.Year = year; // year + tm.Day = atoi(gpsday.value()); // day + tm.Month = atoi(gpsmonth.value()); // month + tm.Year = CalendarYrToTm( + atoi(gpsyear.value())); // year offset from 1970 in microTime.h // add protocol delay to time with millisecond precision - time_sec = makeTime(tm) + delay_ms / 1000; + time_sec = makeTime(tm) + delay_ms / 1000 - 1; *msec = (delay_ms % 1000) ? delay_ms % 1000 : 0; } @@ -165,13 +164,13 @@ void gps_loop(void *pvParameters) { // if time hasn't been synchronised yet, and we have a valid GPS time, // update time from GPS. - if (timeSource == _unsynced && gpstime.isUpdated() && gpstime.isValid()) { + if (timeSource == _unsynced && gpstime.isUpdated() && gpstime.isValid() && + gpsday.isValid()) calibrateTime(); - } } // if - // show NMEA data in verbose mode, useful for debugging GPS, bu tvery noisy + // show NMEA data in verbose mode, useful only for debugging GPS, very noisy // ESP_LOGV(TAG, "GPS NMEA data: passed %u / failed: %u / with fix: %u", // gps.passedChecksum(), gps.failedChecksum(), // gps.sentencesWithFix()); From b34f6f892c671df238d1d8acdf30630f205d7f70 Mon Sep 17 00:00:00 2001 From: Klaus K Wilting Date: Sun, 4 Oct 2020 23:17:39 +0200 Subject: [PATCH 19/44] gpsread.cpp: comments edited --- src/gpsread.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/gpsread.cpp b/src/gpsread.cpp index b6395384..158b3e17 100644 --- a/src/gpsread.cpp +++ b/src/gpsread.cpp @@ -96,7 +96,7 @@ bool gps_hasfix() { gps.altitude.age() < 4000); } -// function to fetch current time from struct; note: this is costly +// function to poll current time from GPS data; note: this is costly time_t get_gpstime(uint16_t *msec) { time_t time_sec = 0; @@ -162,8 +162,8 @@ void gps_loop(void *pvParameters) { } #endif - // if time hasn't been synchronised yet, and we have a valid GPS time, - // update time from GPS. + // (only) while device time is not set or unsynched, and we have a valid GPS + // time, we trigger a device time update to poll time from GPS if (timeSource == _unsynced && gpstime.isUpdated() && gpstime.isValid() && gpsday.isValid()) calibrateTime(); From eece72cef013808a1c2b3f447f0c4c82aba393f7 Mon Sep 17 00:00:00 2001 From: Klaus K Wilting Date: Sun, 4 Oct 2020 23:22:48 +0200 Subject: [PATCH 20/44] v2.0.17 --- platformio_orig.ini | 2 +- src/configmanager.cpp | 7 +-- src/platformio_orig.ini | 135 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 139 insertions(+), 5 deletions(-) create mode 100644 src/platformio_orig.ini diff --git a/platformio_orig.ini b/platformio_orig.ini index 80087854..4dd2263d 100644 --- a/platformio_orig.ini +++ b/platformio_orig.ini @@ -46,7 +46,7 @@ description = Paxcounter is a device for metering passenger flows in realtime. I [common] ; for release_version use max. 10 chars total, use any decimal format like "a.b.c" -release_version = 2.0.16 +release_version = 2.0.17 ; DEBUG LEVEL: For production run set to 0, otherwise device will leak RAM while running! ; 0=None, 1=Error, 2=Warn, 3=Info, 4=Debug, 5=Verbose debug_level = 3 diff --git a/src/configmanager.cpp b/src/configmanager.cpp index d75bc8bd..51ccae59 100644 --- a/src/configmanager.cpp +++ b/src/configmanager.cpp @@ -24,7 +24,8 @@ static uint8_t buffer[cfgLen + cfgLen2]; // // configuration frame structure in NVRAM; // 1. version header [10 bytes, containing version string] -// 2. user settings [cfgLen bytes, containing default runtime settings (configData_t cfg)] +// 2. user settings [cfgLen bytes, containing default runtime settings +// (configData_t cfg)] // 3. magicByte [cfgLen2 bytes, containing a fixed identifier] static void defaultConfig(configData_t *myconfig) { @@ -61,9 +62,7 @@ static void defaultConfig(configData_t *myconfig) { // migrate runtime configuration from earlier to current version static void migrateConfig(void) { - // currently no migration rules are implemented, we just reset config to - // factory settings - eraseConfig(); + // currently no configuration migration rules are implemented } // save current configuration from RAM to NVRAM diff --git a/src/platformio_orig.ini b/src/platformio_orig.ini new file mode 100644 index 00000000..80087854 --- /dev/null +++ b/src/platformio_orig.ini @@ -0,0 +1,135 @@ +; PlatformIO Project Configuration File +; NOTE: PlatformIO v4 is needed! +; +; Please visit documentation for the other options and examples +; http://docs.platformio.org/page/projectconf.html + + +; ---> SELECT THE TARGET PLATFORM HERE! <--- +[board] +halfile = generic.h +;halfile = ebox.h +;halfile = eboxtube.h +;halfile = ecopower.h +;halfile = heltec.h +;halfile = heltecv2.h +;halfile = ttgov1.h +;halfile = ttgov2.h +;halfile = ttgov21old.h +;halfile = ttgov21new.h +;halfile = ttgofox.h +;halfile = ttgobeam.h +;halfile = ttgobeam10.h +;halfile = fipy.h +;halfile = lopy.h +;halfile = lopy4.h +;halfile = lolin32litelora.h +;halfile = lolin32lora.h +;halfile = lolin32lite.h +;halfile = wemos32oled.h +;halfile = wemos32matrix.h +;halfile = octopus32.h +;halfile = tinypico.h +;halfile = tinypicomatrix.h +;halfile = m5core.h +;halfile = m5fire.h +;halfile = olimexpoeiso.h + +[platformio] +; upload firmware to board with usb cable +default_envs = usb +; upload firmware to a jfrog bintray repository +;default_envs = ota +; use latest versions of libraries +;default_envs = dev +description = Paxcounter is a device for metering passenger flows in realtime. It counts how many mobile devices are around. + +[common] +; for release_version use max. 10 chars total, use any decimal format like "a.b.c" +release_version = 2.0.16 +; DEBUG LEVEL: For production run set to 0, otherwise device will leak RAM while running! +; 0=None, 1=Error, 2=Warn, 3=Info, 4=Debug, 5=Verbose +debug_level = 3 +extra_scripts = pre:build.py +otakeyfile = ota.conf +lorakeyfile = loraconf.h +lmicconfigfile = lmic_config.h +platform_espressif32 = espressif32@2.0.0 +monitor_speed = 115200 +upload_speed = 115200 ; set by build.py and taken from hal file +display_library = ; set by build.py and taken from hal file +lib_deps_lora = + mcci-catena/MCCI LoRaWAN LMIC library @ ^3.2.0 +lib_deps_display = + bitbank2/OneBitDisplay @ 1.7.2 + ricmoo/QRCode @ ^0.0.1 + bodmer/TFT_eSPI @ ^2.2.20 +lib_deps_ledmatrix = + seeed-studio/Ultrathin_LED_Matrix @ ^1.0.0 +lib_deps_rgbled = + roboticsbrno/SmartLeds @ ^1.2.1 +lib_deps_gps = + mikalhart/TinyGPSPlus @ ^1.0.2 +lib_deps_sensors = + adafruit/Adafruit Unified Sensor @ ^1.1.4 + adafruit/Adafruit BME280 Library @ ^2.1.1 + adafruit/Adafruit BMP085 Library @ ^1.1.0 + boschsensortec/BSEC Software Library @ 1.5.1474 + https://github.com/ricki-z/SDS011.git +lib_deps_basic = + bblanchon/ArduinoJson @ <6 + jchristensen/Timezone @ ^1.2.4 + makuna/RTC @ ^2.3.5 + spacehuhn/SimpleButton + lewisxhe/AXP202X_Library @ ^1.1.2 + geeksville/esp32-micro-sdcard @ ^0.1.1 + 256dpi/MQTT @ ^2.4.7 +lib_deps_all = + ${common.lib_deps_basic} + ${common.lib_deps_lora} + ${common.lib_deps_display} + ${common.lib_deps_rgbled} + ${common.lib_deps_gps} + ${common.lib_deps_sensors} + ${common.lib_deps_ledmatrix} +build_flags_basic = + -include "src/hal/${board.halfile}" + -include "src/paxcounter.conf" + -w + '-DCORE_DEBUG_LEVEL=${common.debug_level}' + '-DLOG_LOCAL_LEVEL=${common.debug_level}' + '-DPROGVERSION="${common.release_version}"' +build_flags_sensors = + -Llib/Bosch-BSEC/src/esp32/ + -lalgobsec +build_flags_all = + ${common.build_flags_basic} + ${common.build_flags_sensors} + -mfix-esp32-psram-cache-issue + +[env] +lib_ldf_mode = deep ; #632 Fixes compiler error with OneBitDisplay library +framework = arduino +board = esp32dev +board_build.partitions = min_spiffs.csv +upload_speed = ${common.upload_speed} +;upload_port = COM8 +platform = ${common.platform_espressif32} +lib_deps = ${common.lib_deps_all} +build_flags = ${common.build_flags_all} +upload_protocol = ${common.upload_protocol} +extra_scripts = ${common.extra_scripts} +monitor_speed = ${common.monitor_speed} +monitor_filters = time, esp32_exception_decoder, default + +[env:ota] +upload_protocol = custom + +[env:usb] +upload_protocol = esptool + +[env:dev] +upload_protocol = esptool +build_type = debug +platform = https://github.com/platformio/platform-espressif32.git#develop +platform_packages = framework-arduinoespressif32 @ https://github.com/espressif/arduino-esp32.git From 98c2ad38382575e4bd09358e11a76f20d910a1ff Mon Sep 17 00:00:00 2001 From: Chrisotph Schultz Date: Mon, 5 Oct 2020 12:40:33 +0200 Subject: [PATCH 21/44] corrected some errors --- include/globals.h | 4 +--- src/configmanager.cpp | 8 ++------ 2 files changed, 3 insertions(+), 9 deletions(-) diff --git a/include/globals.h b/include/globals.h index b4395c38..fb3aae7b 100644 --- a/include/globals.h +++ b/include/globals.h @@ -82,10 +82,8 @@ typedef struct __attribute__((packed)) { uint8_t monitormode; // 0=disabled, 1=enabled uint8_t runmode; // 0=normal, 1=update uint8_t payloadmask; // bitswitches for payload data - uint8_t enscount; // 0=disabled 1= enabled - char version[10]; // Firmware version - + #ifdef HAS_BME680 uint8_t bsecstate[BSEC_MAX_STATE_BLOB_SIZE + 1]; // BSEC state for BME680 sensor #endif diff --git a/src/configmanager.cpp b/src/configmanager.cpp index 1b4dab82..221ee8be 100644 --- a/src/configmanager.cpp +++ b/src/configmanager.cpp @@ -28,10 +28,8 @@ static uint8_t buffer[cfgLen + cfgLen2]; // (configData_t cfg)] // 3. magicByte [cfgLen2 bytes, containing a fixed identifier] -static void defaultConfig(configData_t *myconfig) { +static void defaultConfig(configData_t *myconfig) { //device factory settings memcpy(myconfig->version, &PROGVERSION, 10); // Firmware version - - // device factory settings myconfig->loradr = LORADRDEFAULT; // 0-15, lora datarate, see paxcounter.conf myconfig->txpower = LORATXPOWDEFAULT; // 0-15, lora tx power myconfig->adrmode = 1; // 0=disabled, 1=enabled @@ -44,8 +42,7 @@ static void defaultConfig(configData_t *myconfig) { myconfig->wifichancycle = WIFI_CHANNEL_SWITCH_INTERVAL; // wifi channel switch cycle [seconds/100] myconfig->blescantime = - BLESCANINTERVAL / - 10; // BT channel scan cycle [seconds/100], default 1 (= 10ms) + BLESCANINTERVAL /10; // BT channel scan cycle [seconds/100], default 1 (= 10ms) myconfig->blescan = 1; // 0=disabled, 1=enabled myconfig->wifiscan = 1; // 0=disabled, 1=enabled myconfig->wifiant = 0; // 0=internal, 1=external (for LoPy/LoPy4) @@ -54,7 +51,6 @@ static void defaultConfig(configData_t *myconfig) { myconfig->monitormode = 0; // 0=disabled, 1=enabled myconfig->payloadmask = PAYLOADMASK; // all payload switched on myconfig->enscount =0; // 0= disabled, 1 = enabled - memcpy(myconfig->version, version, 10); // Firmware version [exactly 10 chars] #ifdef HAS_BME680 // initial BSEC state for BME680 sensor From 0e2a4e6893a9ce3fb214fc6eb99e1535374a21fe Mon Sep 17 00:00:00 2001 From: Chrisotph Schultz Date: Mon, 5 Oct 2020 12:49:54 +0200 Subject: [PATCH 22/44] Revert " corrected some errors" This reverts commit 98c2ad38382575e4bd09358e11a76f20d910a1ff. --- include/globals.h | 4 +++- src/configmanager.cpp | 8 ++++++-- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/include/globals.h b/include/globals.h index fb3aae7b..b4395c38 100644 --- a/include/globals.h +++ b/include/globals.h @@ -82,8 +82,10 @@ typedef struct __attribute__((packed)) { uint8_t monitormode; // 0=disabled, 1=enabled uint8_t runmode; // 0=normal, 1=update uint8_t payloadmask; // bitswitches for payload data + uint8_t enscount; // 0=disabled 1= enabled - + char version[10]; // Firmware version + #ifdef HAS_BME680 uint8_t bsecstate[BSEC_MAX_STATE_BLOB_SIZE + 1]; // BSEC state for BME680 sensor #endif diff --git a/src/configmanager.cpp b/src/configmanager.cpp index 221ee8be..1b4dab82 100644 --- a/src/configmanager.cpp +++ b/src/configmanager.cpp @@ -28,8 +28,10 @@ static uint8_t buffer[cfgLen + cfgLen2]; // (configData_t cfg)] // 3. magicByte [cfgLen2 bytes, containing a fixed identifier] -static void defaultConfig(configData_t *myconfig) { //device factory settings +static void defaultConfig(configData_t *myconfig) { memcpy(myconfig->version, &PROGVERSION, 10); // Firmware version + + // device factory settings myconfig->loradr = LORADRDEFAULT; // 0-15, lora datarate, see paxcounter.conf myconfig->txpower = LORATXPOWDEFAULT; // 0-15, lora tx power myconfig->adrmode = 1; // 0=disabled, 1=enabled @@ -42,7 +44,8 @@ static void defaultConfig(configData_t *myconfig) { //device factory settings myconfig->wifichancycle = WIFI_CHANNEL_SWITCH_INTERVAL; // wifi channel switch cycle [seconds/100] myconfig->blescantime = - BLESCANINTERVAL /10; // BT channel scan cycle [seconds/100], default 1 (= 10ms) + BLESCANINTERVAL / + 10; // BT channel scan cycle [seconds/100], default 1 (= 10ms) myconfig->blescan = 1; // 0=disabled, 1=enabled myconfig->wifiscan = 1; // 0=disabled, 1=enabled myconfig->wifiant = 0; // 0=internal, 1=external (for LoPy/LoPy4) @@ -51,6 +54,7 @@ static void defaultConfig(configData_t *myconfig) { //device factory settings myconfig->monitormode = 0; // 0=disabled, 1=enabled myconfig->payloadmask = PAYLOADMASK; // all payload switched on myconfig->enscount =0; // 0= disabled, 1 = enabled + memcpy(myconfig->version, version, 10); // Firmware version [exactly 10 chars] #ifdef HAS_BME680 // initial BSEC state for BME680 sensor From d3bf77d1e706ba45c044afbfa72b3359847e0214 Mon Sep 17 00:00:00 2001 From: Chrisotph Schultz Date: Mon, 5 Oct 2020 12:58:05 +0200 Subject: [PATCH 23/44] added rcmd 0x18 for switching off/on ENS --- include/globals.h | 3 +-- src/configmanager.cpp | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/include/globals.h b/include/globals.h index b4395c38..73245469 100644 --- a/include/globals.h +++ b/include/globals.h @@ -84,8 +84,7 @@ typedef struct __attribute__((packed)) { uint8_t payloadmask; // bitswitches for payload data uint8_t enscount; // 0=disabled 1= enabled - char version[10]; // Firmware version - + #ifdef HAS_BME680 uint8_t bsecstate[BSEC_MAX_STATE_BLOB_SIZE + 1]; // BSEC state for BME680 sensor #endif diff --git a/src/configmanager.cpp b/src/configmanager.cpp index 1b4dab82..45bb36e7 100644 --- a/src/configmanager.cpp +++ b/src/configmanager.cpp @@ -54,7 +54,7 @@ static void defaultConfig(configData_t *myconfig) { myconfig->monitormode = 0; // 0=disabled, 1=enabled myconfig->payloadmask = PAYLOADMASK; // all payload switched on myconfig->enscount =0; // 0= disabled, 1 = enabled - memcpy(myconfig->version, version, 10); // Firmware version [exactly 10 chars] + #ifdef HAS_BME680 // initial BSEC state for BME680 sensor From d093e7120f7bb5907329c34300ee8195ec84d6dd Mon Sep 17 00:00:00 2001 From: Christoph Schultz Date: Mon, 5 Oct 2020 13:04:18 +0200 Subject: [PATCH 24/44] Update README.md --- README.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 265f5578..4941e2de 100644 --- a/README.md +++ b/README.md @@ -510,8 +510,9 @@ Send for example `8386` as Downlink on Port 2 to get battery status and time/dat 1 = enabled [default] 0x18 set ENS counter on/off - 0 = disabled (default) - 1 = enabled + + 0 = disabled (default) + 1 = enabled 0x80 get device configuration From 80b26022583af9fdd144e560b2f934e0d636e54d Mon Sep 17 00:00:00 2001 From: Christoph Schultz Date: Mon, 5 Oct 2020 13:05:35 +0200 Subject: [PATCH 25/44] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 4941e2de..cfb9080e 100644 --- a/README.md +++ b/README.md @@ -512,7 +512,7 @@ Send for example `8386` as Downlink on Port 2 to get battery status and time/dat 0x18 set ENS counter on/off 0 = disabled (default) - 1 = enabled + 1 = enabled 0x80 get device configuration From b58688b132dfe4a6bec2cc66301a014558537dae Mon Sep 17 00:00:00 2001 From: Christoph Schultz Date: Mon, 5 Oct 2020 13:07:11 +0200 Subject: [PATCH 26/44] Update README.md --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index cfb9080e..9b452fb3 100644 --- a/README.md +++ b/README.md @@ -511,8 +511,8 @@ Send for example `8386` as Downlink on Port 2 to get battery status and time/dat 0x18 set ENS counter on/off - 0 = disabled (default) - 1 = enabled + 0 = disabled (default) + 1 = enabled 0x80 get device configuration From 69235b94d714f9628923e49dff670d8613fb166c Mon Sep 17 00:00:00 2001 From: Klaus K Wilting Date: Mon, 5 Oct 2020 13:40:22 +0200 Subject: [PATCH 27/44] gps time sync improvements --- src/gpsread.cpp | 45 +++++++++++++++++++++++++-------------------- src/timekeeper.cpp | 6 +++--- 2 files changed, 28 insertions(+), 23 deletions(-) diff --git a/src/gpsread.cpp b/src/gpsread.cpp index 158b3e17..a20a6456 100644 --- a/src/gpsread.cpp +++ b/src/gpsread.cpp @@ -99,8 +99,6 @@ bool gps_hasfix() { // function to poll current time from GPS data; note: this is costly time_t get_gpstime(uint16_t *msec) { - time_t time_sec = 0; - // poll NMEA ZDA sentence #ifdef GPS_SERIAL GPS_Serial.print(ZDA_Request); @@ -111,28 +109,36 @@ time_t get_gpstime(uint16_t *msec) { #endif // did we get a current date & time? - if (gpstime.isUpdated() && gpstime.isValid() && gpsday.isValid()) { + if (gpstime.isValid() && gpsday.isValid()) { + time_t t = 0; tmElements_t tm; - - uint32_t time_bcd = atof(gpstime.value()) * 100; uint32_t delay_ms = gpstime.age() + nmea_txDelay_ms + NMEA_COMPENSATION_FACTOR; + uint32_t zdatime = atof(gpstime.value()); - tm.Second = (time_bcd / 100) % 100; // second - tm.Minute = (time_bcd / 10000) % 100; // minute - tm.Hour = time_bcd / 1000000; // hour - tm.Day = atoi(gpsday.value()); // day - tm.Month = atoi(gpsmonth.value()); // month - tm.Year = CalendarYrToTm( - atoi(gpsyear.value())); // year offset from 1970 in microTime.h + // convert time to maketime format and make time + tm.Second = zdatime % 100; // second + tm.Minute = (zdatime / 100) % 100; // minute + tm.Hour = zdatime / 10000; // hour + tm.Day = atoi(gpsday.value()); // day + tm.Month = atoi(gpsmonth.value()); // month + tm.Year = CalendarYrToTm(atoi(gpsyear.value())); // year offset from 1970 + t = makeTime(tm); - // add protocol delay to time with millisecond precision - time_sec = makeTime(tm) + delay_ms / 1000 - 1; - *msec = (delay_ms % 1000) ? delay_ms % 1000 : 0; + ESP_LOGD(TAG, "GPS time/date = %2d:%2d:%2d / %2d.%2d.%2d", tm.Hour, + tm.Minute, tm.Second, tm.Day, tm.Month, tm.Year + 1970); + + // add protocol delay with millisecond precision + t += delay_ms / 1000 - 1; // whole seconds + *msec = delay_ms % 1000; // fractional seconds + + return t; } - return timeIsValid(time_sec); + ESP_LOGD(TAG, "no valid GPS time"); + + return 0; } // get_gpstime() @@ -162,10 +168,9 @@ void gps_loop(void *pvParameters) { } #endif - // (only) while device time is not set or unsynched, and we have a valid GPS - // time, we trigger a device time update to poll time from GPS - if (timeSource == _unsynced && gpstime.isUpdated() && gpstime.isValid() && - gpsday.isValid()) + // (only) while device time is not set or unsynched, and we have a valid + // GPS time, we trigger a device time update to poll time from GPS + if (timeSource == _unsynced && gpstime.isUpdated()) calibrateTime(); } // if diff --git a/src/timekeeper.cpp b/src/timekeeper.cpp index b0a23e93..051f77c3 100644 --- a/src/timekeeper.cpp +++ b/src/timekeeper.cpp @@ -85,7 +85,7 @@ void IRAM_ATTR setMyTime(uint32_t t_sec, uint16_t t_msec, vTaskDelay(pdMS_TO_TICKS(1000 - t_msec % 1000)); } - ESP_LOGD(TAG, "[%0.3f] UTC time: %d.%03d sec", millis() / 1000.0, + ESP_LOGI(TAG, "[%0.3f] UTC time: %d.%03d sec", millis() / 1000.0, time_to_set, t_msec % 1000); // if we have got an external timesource, set RTC time and shift RTC_INT pulse @@ -105,11 +105,11 @@ void IRAM_ATTR setMyTime(uint32_t t_sec, uint16_t t_msec, timeSource = mytimesource; // set global variable timesyncer.attach(TIME_SYNC_INTERVAL * 60, setTimeSyncIRQ); - ESP_LOGI(TAG, "[%0.3f] Timesync finished, time was set | source: %c", + ESP_LOGD(TAG, "[%0.3f] Timesync finished, time was set | source: %c", millis() / 1000.0, timeSetSymbols[mytimesource]); } else { timesyncer.attach(TIME_SYNC_INTERVAL_RETRY * 60, setTimeSyncIRQ); - ESP_LOGI(TAG, "[%0.3f] Timesync failed, invalid time fetched | source: %c", + ESP_LOGD(TAG, "[%0.3f] Timesync failed, invalid time fetched | source: %c", millis() / 1000.0, timeSetSymbols[mytimesource]); } } From 092842a4c0eb71b8ef7184a92a50b26b0e7e0daf Mon Sep 17 00:00:00 2001 From: Klaus K Wilting Date: Mon, 5 Oct 2020 13:56:41 +0200 Subject: [PATCH 28/44] PR #653 merged and added some corrections --- include/cyclic.h | 2 +- include/globals.h | 6 ++-- src/blecsan.cpp | 9 +++--- src/configmanager.cpp | 11 +++---- src/cyclic.cpp | 4 +-- src/hal/ttgov21new.h | 2 +- src/main.cpp | 2 +- src/rcommand.cpp | 71 ++++++++++++++++--------------------------- src/sensor.cpp | 8 ++--- 9 files changed, 47 insertions(+), 68 deletions(-) diff --git a/include/cyclic.h b/include/cyclic.h index 732f2843..6bd9b2a7 100644 --- a/include/cyclic.h +++ b/include/cyclic.h @@ -11,7 +11,7 @@ #include "sds011read.h" #include "sdcard.h" -extern Ticker housekeeper; +extern Ticker cyclicTimer; void setCyclicIRQ(void); void doHousekeeping(void); diff --git a/include/globals.h b/include/globals.h index 73245469..324c5328 100644 --- a/include/globals.h +++ b/include/globals.h @@ -82,11 +82,11 @@ typedef struct __attribute__((packed)) { uint8_t monitormode; // 0=disabled, 1=enabled uint8_t runmode; // 0=normal, 1=update uint8_t payloadmask; // bitswitches for payload data - uint8_t enscount; // 0=disabled 1= enabled - + #ifdef HAS_BME680 - uint8_t bsecstate[BSEC_MAX_STATE_BLOB_SIZE + 1]; // BSEC state for BME680 sensor + uint8_t + bsecstate[BSEC_MAX_STATE_BLOB_SIZE + 1]; // BSEC state for BME680 sensor #endif } configData_t; diff --git a/src/blecsan.cpp b/src/blecsan.cpp index c7085276..9a60e456 100644 --- a/src/blecsan.cpp +++ b/src/blecsan.cpp @@ -168,12 +168,13 @@ IRAM_ATTR void gap_callback_handler(esp_gap_ble_cb_event_t event, mac_add((uint8_t *)p->scan_rst.bda, p->scan_rst.rssi, MAC_SNIFF_BLE); - if (cfg.enscount){ - // check for ens signature +#if (COUNT_ENS) + if (cfg.enscount) { + // check for ens signature if (NULL != strstr((const char *)p->scan_rst.ble_adv, ensMagicBytes)) - cwa_mac_add(hashedmac); + cwa_mac_add(hashedmac); } - +#endif /* to be improved in vendorfilter if: // you can search for elements in the payload using the diff --git a/src/configmanager.cpp b/src/configmanager.cpp index 45bb36e7..edbca433 100644 --- a/src/configmanager.cpp +++ b/src/configmanager.cpp @@ -49,12 +49,11 @@ static void defaultConfig(configData_t *myconfig) { myconfig->blescan = 1; // 0=disabled, 1=enabled myconfig->wifiscan = 1; // 0=disabled, 1=enabled myconfig->wifiant = 0; // 0=internal, 1=external (for LoPy/LoPy4) - myconfig->vendorfilter = VENDORFILTER; // 0=disabled, 1=enabled - myconfig->rgblum = RGBLUMINOSITY; // RGB Led luminosity (0..100%) - myconfig->monitormode = 0; // 0=disabled, 1=enabled - myconfig->payloadmask = PAYLOADMASK; // all payload switched on - myconfig->enscount =0; // 0= disabled, 1 = enabled - + myconfig->vendorfilter = VENDORFILTER; // 0=disabled, 1=enabled + myconfig->rgblum = RGBLUMINOSITY; // RGB Led luminosity (0..100%) + myconfig->monitormode = 0; // 0=disabled, 1=enabled + myconfig->payloadmask = PAYLOADMASK; // all payload switched on + myconfig->enscount = 0; // 0=disabled, 1=enabled #ifdef HAS_BME680 // initial BSEC state for BME680 sensor diff --git a/src/cyclic.cpp b/src/cyclic.cpp index 0b484065..c57a0863 100644 --- a/src/cyclic.cpp +++ b/src/cyclic.cpp @@ -7,7 +7,7 @@ // Local logging tag static const char TAG[] = __FILE__; -Ticker housekeeper; +Ticker cyclicTimer; #if (HAS_SDS011) extern boolean isSDS011Active; @@ -150,7 +150,7 @@ uint32_t getFreeRAM() { void reset_counters() { #if ((WIFICOUNTER) || (BLECOUNTER)) - macs.clear(); // clear all macs container + macs.clear(); // clear all macs container macs_wifi = 0; macs_ble = 0; #ifdef HAS_DISPLAY diff --git a/src/hal/ttgov21new.h b/src/hal/ttgov21new.h index 4b08748d..f4583bdc 100644 --- a/src/hal/ttgov21new.h +++ b/src/hal/ttgov21new.h @@ -1,6 +1,6 @@ // clang-format off // upload_speed 921600 -// board esp32dev +// board ttgo-lora32-v21new #ifndef _TTGOV21NEW_H #define _TTGOV21NEW_H diff --git a/src/main.cpp b/src/main.cpp index cf70f79d..bcecd934 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -486,7 +486,7 @@ void setup() { // cyclic function interrupts sendTimer.attach(cfg.sendcycle * 2, setSendIRQ); - housekeeper.attach(HOMECYCLE, setCyclicIRQ); + cyclicTimer.attach(HOMECYCLE, setCyclicIRQ); #if (TIME_SYNC_INTERVAL) diff --git a/src/rcommand.cpp b/src/rcommand.cpp index 58bc8ca7..eb15dd0d 100644 --- a/src/rcommand.cpp +++ b/src/rcommand.cpp @@ -340,54 +340,35 @@ void set_flush(uint8_t val[]) { }; void set_enscount(uint8_t val[]) { - ESP_LOGI(TAG, "Remote command: set ENS_COUNT to %s", - val[0] ? "on" : "off"); + ESP_LOGI(TAG, "Remote command: set ENS_COUNT to %s", val[0] ? "on" : "off"); cfg.enscount = val[0] ? 1 : 0; - if (val[0]) - cfg.payloadmask |= SENSOR1_DATA; - else - cfg.payloadmask &= ~SENSOR1_DATA; - - + if (val[0]) + cfg.payloadmask |= SENSOR1_DATA; + else + cfg.payloadmask &= ~SENSOR1_DATA; } - // assign previously defined functions to set of numeric remote commands - // format: opcode, function, #bytes params, - // flag (true = do make settings persistent / false = don't) - // - static const cmd_t table[] = { - {0x01, set_rssi, 1, true}, - {0x02, set_countmode, 1, true}, - {0x03, set_gps, 1, true}, - {0x04, set_display, 1, true}, - {0x05, set_loradr, 1, true}, - {0x06, set_lorapower, 1, true}, - {0x07, set_loraadr, 1, true}, - {0x08, set_screensaver, 1, true}, - {0x09, set_reset, 1, false}, - {0x0a, set_sendcycle, 1, true}, - {0x0b, set_wifichancycle, 1, true}, - {0x0c, set_blescantime, 1, true}, - {0x0d, set_vendorfilter, 1, false}, - {0x0e, set_blescan, 1, true}, - {0x0f, set_wifiant, 1, true}, - {0x10, set_rgblum, 1, true}, - {0x11, set_monitor, 1, true}, - {0x12, set_beacon, 7, false}, - {0x13, set_sensor, 2, true}, - {0x14, set_payloadmask, 1, true}, - {0x15, set_bme, 1, true}, - {0x16, set_batt, 1, true}, - {0x17, set_wifiscan, 1, true}, - {0x18, set_enscount, 1, true}, - {0x80, get_config, 0, false}, - {0x81, get_status, 0, false}, - {0x83, get_batt, 0, false}, - {0x84, get_gps, 0, false}, - {0x85, get_bme, 0, false}, - {0x86, get_time, 0, false}, - {0x87, set_time, 0, false}, - {0x99, set_flush, 0, false}}; +// assign previously defined functions to set of numeric remote commands +// format: opcode, function, #bytes params, +// flag (true = do make settings persistent / false = don't) +// +static const cmd_t table[] = { + {0x01, set_rssi, 1, true}, {0x02, set_countmode, 1, true}, + {0x03, set_gps, 1, true}, {0x04, set_display, 1, true}, + {0x05, set_loradr, 1, true}, {0x06, set_lorapower, 1, true}, + {0x07, set_loraadr, 1, true}, {0x08, set_screensaver, 1, true}, + {0x09, set_reset, 1, false}, {0x0a, set_sendcycle, 1, true}, + {0x0b, set_wifichancycle, 1, true}, {0x0c, set_blescantime, 1, true}, + {0x0d, set_vendorfilter, 1, false}, {0x0e, set_blescan, 1, true}, + {0x0f, set_wifiant, 1, true}, {0x10, set_rgblum, 1, true}, + {0x11, set_monitor, 1, true}, {0x12, set_beacon, 7, false}, + {0x13, set_sensor, 2, true}, {0x14, set_payloadmask, 1, true}, + {0x15, set_bme, 1, true}, {0x16, set_batt, 1, true}, + {0x17, set_wifiscan, 1, true}, {0x18, set_enscount, 1, true}, + {0x80, get_config, 0, false}, {0x81, get_status, 0, false}, + {0x83, get_batt, 0, false}, {0x84, get_gps, 0, false}, + {0x85, get_bme, 0, false}, {0x86, get_time, 0, false}, + {0x87, set_time, 0, false}, {0x99, set_flush, 0, false}}; static const uint8_t cmdtablesize = sizeof(table) / sizeof(table[0]); // number of commands in command table diff --git a/src/sensor.cpp b/src/sensor.cpp index a8901505..bb34030e 100644 --- a/src/sensor.cpp +++ b/src/sensor.cpp @@ -56,16 +56,14 @@ uint8_t *sensor_read(uint8_t sensor) { // insert user specific sensor data frames here // note: Sensor1 fields are used for ENS count, if ENS detection enabled -#if COUNT_ENS -if (cfg.enscount) - payload.addCount(cwa_report(), MAC_SNIFF_BLE_CWA); +#if (COUNT_ENS) + if (cfg.enscount) + payload.addCount(cwa_report(), MAC_SNIFF_BLE_CWA); #else - if(!cfg.enscount) buf[0] = length; buf[1] = 0x01; buf[2] = 0x02; buf[3] = 0x03; - #endif break; case 2: From 5b43a1d98674be95a8c98165e45c50e201c4f0f9 Mon Sep 17 00:00:00 2001 From: Klaus K Wilting Date: Mon, 5 Oct 2020 14:02:03 +0200 Subject: [PATCH 29/44] readme.md typos corrected --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 9b452fb3..bdaf1223 100644 --- a/README.md +++ b/README.md @@ -209,9 +209,9 @@ Follow all steps so far for preparing the device, use the packed payload format. There in the sensor configuration select "TheThingsNetwork" and set Decoding Profil to "LoRa serialization", enter your TTN Application and Device Id. Decoding option has to be [{"decoder":"latLng"},{"decoder":"uint16","sensor_id":"yoursensorid"}] -# Covid-19 Exposure Notification System beacon detection (Germany: "Corona Warn App counter") +# Covid-19 Exposure Notification System beacon detection -Bluetooth low energy service UUID 0xFD6F, used by Google/Apple COVID-19 Exposure Notification System, can be monitored and counted. By comparing with the total number of observed devices this gives an indication how many people staying in proximity are using Apps for tracing COVID-19 exposures, e.g. in Germany the "Corona Warn App". To achive best resulta withs this funcion, use following settings in [paxcounter.conf](src/paxcounter.conf): +Bluetooth low energy service UUID 0xFD6F, used by Google/Apple COVID-19 Exposure Notification System, can be monitored and counted. By comparing with the total number of observed devices this gives an indication how many people staying in proximity are using Apps for tracing COVID-19 exposures, e.g. in Germany the "Corona Warn App". To achive best results with this funcion, use following settings in [paxcounter.conf](src/paxcounter.conf): #define COUNT_ENS 1 // enable ENS monitoring function #define VENDORFILTER 0 // disable OUI filter (scans ALL device MACs) @@ -511,7 +511,7 @@ Send for example `8386` as Downlink on Port 2 to get battery status and time/dat 0x18 set ENS counter on/off - 0 = disabled (default) + 0 = disabled [default] 1 = enabled 0x80 get device configuration From b28a86c9a2b594225225ad5bd472abdff2be61da Mon Sep 17 00:00:00 2001 From: Klaus K Wilting Date: Mon, 5 Oct 2020 14:07:19 +0200 Subject: [PATCH 30/44] revert change in ttgov21new.h (not yet functional) --- src/hal/ttgov21new.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/hal/ttgov21new.h b/src/hal/ttgov21new.h index f4583bdc..4b08748d 100644 --- a/src/hal/ttgov21new.h +++ b/src/hal/ttgov21new.h @@ -1,6 +1,6 @@ // clang-format off // upload_speed 921600 -// board ttgo-lora32-v21new +// board esp32dev #ifndef _TTGOV21NEW_H #define _TTGOV21NEW_H From d5301871304d8ef9da307dcde988a82907b25add Mon Sep 17 00:00:00 2001 From: Klaus K Wilting Date: Mon, 5 Oct 2020 15:41:49 +0200 Subject: [PATCH 31/44] configmanager bugfix --- src/configmanager.cpp | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/src/configmanager.cpp b/src/configmanager.cpp index edbca433..c55bd7ef 100644 --- a/src/configmanager.cpp +++ b/src/configmanager.cpp @@ -63,7 +63,9 @@ static void defaultConfig(configData_t *myconfig) { // migrate runtime configuration from earlier to current version static void migrateConfig(void) { - // currently no configuration migration rules are implemented + // currently no configuration migration rules are implemented, we reset to + // factory settings instead + eraseConfig(); } // save current configuration from RAM to NVRAM @@ -99,24 +101,23 @@ bool loadConfig() { if (!nvram.begin(DEVCONFIG, true)) { ESP_LOGI(TAG, "NVRAM initialized, device starts with factory settings"); eraseConfig(); - return true; } // simple check that runtime config data matches - if (nvram.getBytesLength(DEVCONFIG) != (cfgLen + cfgLen2)) { - ESP_LOGE(TAG, "Configuration invalid"); - return false; - } + // if (nvram.getBytesLength(DEVCONFIG) != (cfgLen + cfgLen2)) { + // ESP_LOGE(TAG, "Configuration invalid"); + // return false; + //} // load device runtime config from nvram and copy it to byte array nvram.getBytes(DEVCONFIG, buffer, cfgLen + cfgLen2); nvram.end(); // validate loaded configuration by checking magic bytes at end of array - if (memcmp(buffer + cfgLen, &cfgMagicBytes, cfgLen2) != 0) { - ESP_LOGW(TAG, "No configuration found"); - return false; - } + // if (memcmp(buffer + cfgLen, &cfgMagicBytes, cfgLen2) != 0) { + // ESP_LOGW(TAG, "No configuration found"); + // return false; + //} // copy loaded configuration into runtime cfg struct memcpy(&cfg, buffer, cfgLen); From 551e97796b21651a527cddc6d1ea4141c795bd4a Mon Sep 17 00:00:00 2001 From: Klaus K Wilting Date: Mon, 5 Oct 2020 16:51:18 +0200 Subject: [PATCH 32/44] readme.md: Link added --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index bdaf1223..3940f6c8 100644 --- a/README.md +++ b/README.md @@ -211,7 +211,7 @@ There in the sensor configuration select "TheThingsNetwork" and set Decoding Pro # Covid-19 Exposure Notification System beacon detection -Bluetooth low energy service UUID 0xFD6F, used by Google/Apple COVID-19 Exposure Notification System, can be monitored and counted. By comparing with the total number of observed devices this gives an indication how many people staying in proximity are using Apps for tracing COVID-19 exposures, e.g. in Germany the "Corona Warn App". To achive best results with this funcion, use following settings in [paxcounter.conf](src/paxcounter.conf): +Bluetooth low energy service UUID 0xFD6F, used by Google/Apple COVID-19 Exposure Notification System, can be monitored and counted. By comparing with the total number of observed devices this gives an indication how many people staying in proximity are using Apps for tracing COVID-19 exposures, e.g. in Germany the "Corona Warn App". To achive best results with this funcion, use following settings in [paxcounter.conf](src/paxcounter.conf): #define COUNT_ENS 1 // enable ENS monitoring function #define VENDORFILTER 0 // disable OUI filter (scans ALL device MACs) From 4286e4b8b3b766e6f50c155b1d88c159df196751 Mon Sep 17 00:00:00 2001 From: Klaus K Wilting Date: Mon, 5 Oct 2020 21:57:45 +0200 Subject: [PATCH 33/44] small code sanitizations --- src/gpsread.cpp | 4 ++-- src/timesync.cpp | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/gpsread.cpp b/src/gpsread.cpp index a20a6456..d37990ff 100644 --- a/src/gpsread.cpp +++ b/src/gpsread.cpp @@ -126,8 +126,8 @@ time_t get_gpstime(uint16_t *msec) { tm.Year = CalendarYrToTm(atoi(gpsyear.value())); // year offset from 1970 t = makeTime(tm); - ESP_LOGD(TAG, "GPS time/date = %2d:%2d:%2d / %2d.%2d.%2d", tm.Hour, - tm.Minute, tm.Second, tm.Day, tm.Month, tm.Year + 1970); + //ESP_LOGD(TAG, "GPS time/date = %2d:%2d:%2d / %2d.%2d.%2d", tm.Hour, + // tm.Minute, tm.Second, tm.Day, tm.Month, tm.Year + 1970); // add protocol delay with millisecond precision t += delay_ms / 1000 - 1; // whole seconds diff --git a/src/timesync.cpp b/src/timesync.cpp index 373e55ca..ffc1bcd3 100644 --- a/src/timesync.cpp +++ b/src/timesync.cpp @@ -81,7 +81,7 @@ void IRAM_ATTR timesync_processReq(void *taskparameter) { for (uint8_t i = 0; i < TIME_SYNC_SAMPLES; i++) { // send timesync request -#if (TIME_SYNC_LORASERVER) // aks user's timeserver (for LoRAWAN < 1.0.3) +#if (TIME_SYNC_LORASERVER) // ask user's timeserver (for LoRAWAN < 1.0.3) payload.reset(); payload.addByte(time_sync_seqNo); SendPayload(TIMEPORT, prio_high); From 287e8dbc20d659089065b952299268d22ec7b89d Mon Sep 17 00:00:00 2001 From: Klaus K Wilting Date: Fri, 9 Oct 2020 16:42:53 +0200 Subject: [PATCH 34/44] fix issue #659 --- src/configmanager.cpp | 3 ++- src/payload.cpp | 9 +-------- 2 files changed, 3 insertions(+), 9 deletions(-) diff --git a/src/configmanager.cpp b/src/configmanager.cpp index c55bd7ef..c8fecc2d 100644 --- a/src/configmanager.cpp +++ b/src/configmanager.cpp @@ -6,6 +6,7 @@ // Local logging tag static const char TAG[] = __FILE__; +// default settings for device data to be sent #define PAYLOADMASK \ ((GPS_DATA | ALARM_DATA | MEMS_DATA | COUNT_DATA | SENSOR1_DATA | \ SENSOR2_DATA | SENSOR3_DATA) & \ @@ -52,7 +53,7 @@ static void defaultConfig(configData_t *myconfig) { myconfig->vendorfilter = VENDORFILTER; // 0=disabled, 1=enabled myconfig->rgblum = RGBLUMINOSITY; // RGB Led luminosity (0..100%) myconfig->monitormode = 0; // 0=disabled, 1=enabled - myconfig->payloadmask = PAYLOADMASK; // all payload switched on + myconfig->payloadmask = PAYLOADMASK; // payloads as defined in default myconfig->enscount = 0; // 0=disabled, 1=enabled #ifdef HAS_BME680 diff --git a/src/payload.cpp b/src/payload.cpp index 7517e9d5..112a544d 100644 --- a/src/payload.cpp +++ b/src/payload.cpp @@ -181,14 +181,7 @@ void PayloadConvert::addConfig(configData_t value) { value.blescan ? true : false, value.wifiant ? true : false, value.vendorfilter ? true : false, value.monitormode ? true : false); - writeBitmap(value.payloadmask && GPS_DATA ? true : false, - value.payloadmask && ALARM_DATA ? true : false, - value.payloadmask && MEMS_DATA ? true : false, - value.payloadmask && COUNT_DATA ? true : false, - value.payloadmask && SENSOR1_DATA ? true : false, - value.payloadmask && SENSOR2_DATA ? true : false, - value.payloadmask && SENSOR3_DATA ? true : false, - value.payloadmask && BATT_DATA ? true : false); + writeUint8(value.payloadmask); writeVersion(value.version); } From 56521fe9fb6f6e93a4df586812a591d2a794942f Mon Sep 17 00:00:00 2001 From: Klaus K Wilting Date: Fri, 9 Oct 2020 18:50:43 +0200 Subject: [PATCH 35/44] configmanager.cpp: ENS count default added --- src/configmanager.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/configmanager.cpp b/src/configmanager.cpp index c8fecc2d..f947f383 100644 --- a/src/configmanager.cpp +++ b/src/configmanager.cpp @@ -54,7 +54,7 @@ static void defaultConfig(configData_t *myconfig) { myconfig->rgblum = RGBLUMINOSITY; // RGB Led luminosity (0..100%) myconfig->monitormode = 0; // 0=disabled, 1=enabled myconfig->payloadmask = PAYLOADMASK; // payloads as defined in default - myconfig->enscount = 0; // 0=disabled, 1=enabled + myconfig->enscount = COUNT_ENS; // 0=disabled, 1=enabled #ifdef HAS_BME680 // initial BSEC state for BME680 sensor From e3858eceef7605e5e8bd5346109f8c269e23affd Mon Sep 17 00:00:00 2001 From: Klaus K Wilting Date: Fri, 9 Oct 2020 19:56:29 +0200 Subject: [PATCH 36/44] Don't clear ENS count in cumulative mode --- src/senddata.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/senddata.cpp b/src/senddata.cpp index 53b5dc7f..1cc09503 100644 --- a/src/senddata.cpp +++ b/src/senddata.cpp @@ -154,7 +154,8 @@ void sendData() { payload.addSensor(sensor_read(1)); SendPayload(SENSOR1PORT, prio_normal); #if (COUNT_ENS) - cwa_clear(); + if (cfg.countermode != 1) + cwa_clear(); #endif break; #endif From 2375d4943ead6334c572c3df4b8018c305631a42 Mon Sep 17 00:00:00 2001 From: Klaus K Wilting Date: Fri, 9 Oct 2020 21:43:53 +0200 Subject: [PATCH 37/44] fix control flow for time sync sequence indexing --- src/timesync.cpp | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/timesync.cpp b/src/timesync.cpp index ffc1bcd3..9269bd80 100644 --- a/src/timesync.cpp +++ b/src/timesync.cpp @@ -29,7 +29,7 @@ static uint32_t timesync_timestamp[TIME_SYNC_SAMPLES][no_of_timestamps]; static TaskHandle_t timeSyncProcTask; // create task for timeserver handshake processing, called from main.cpp -void timesync_init() { +void timesync_init(void) { xTaskCreatePinnedToCore(timesync_processReq, // task function "timesync_proc", // name of task 2048, // stack size of task @@ -69,8 +69,12 @@ void IRAM_ATTR timesync_processReq(void *taskparameter) { // wait for kickoff ulTaskNotifyTake(pdFALSE, portMAX_DELAY); + + // initialize flag and counters timeSyncPending = true; time_offset_ms = sample_idx = 0; + if (++time_sync_seqNo > TIME_SYNC_MAX_SEQNO) + time_sync_seqNo = 0; // wait until we are joined if we are not while (!LMIC.devaddr) { @@ -111,9 +115,7 @@ void IRAM_ATTR timesync_processReq(void *taskparameter) { timesync_timestamp[sample_idx][timesync_tx]; #endif - // increment sample_idx and time_sync_seqNo, keeping it in range - if (++time_sync_seqNo > TIME_SYNC_MAX_SEQNO) - time_sync_seqNo = 0; + // increment sample index sample_idx++; // if we are not in last cycle, pause until next cycle From d34b164537d2f3accf423e92e4d150533aa48d09 Mon Sep 17 00:00:00 2001 From: Klaus K Wilting Date: Fri, 9 Oct 2020 22:44:52 +0200 Subject: [PATCH 38/44] fix issue #655 --- src/lorawan.cpp | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/src/lorawan.cpp b/src/lorawan.cpp index 5b673074..34cc4a0b 100644 --- a/src/lorawan.cpp +++ b/src/lorawan.cpp @@ -527,22 +527,16 @@ void myRxCallback(void *pUserData, uint8_t port, const uint8_t *pMsg, // rcommand received -> call interpreter case RCMDPORT: rcommand(pMsg, nMsg); + break; // timeserver answer -> call timesync processor #if (TIME_SYNC_LORASERVER) case TIMEPORT: // get and store gwtime from payload timesync_serverAnswer(const_cast(pMsg), nMsg); + break; #endif - // decode any piggybacked downlink MAC commands if we want to print those - default: -#if (VERBOSE) - if (LMIC.dataBeg > 1) - mac_decode(LMIC.frame, LMIC.dataBeg - 1, true); -#endif // VERBOSE - - break; } // switch } From 93408a9e816aefaa53ad12b56ace4b2c67b096da Mon Sep 17 00:00:00 2001 From: Klaus K Wilting Date: Fri, 9 Oct 2020 22:45:44 +0200 Subject: [PATCH 39/44] fix for gps time sync --- src/gpsread.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/gpsread.cpp b/src/gpsread.cpp index d37990ff..75206e59 100644 --- a/src/gpsread.cpp +++ b/src/gpsread.cpp @@ -126,7 +126,7 @@ time_t get_gpstime(uint16_t *msec) { tm.Year = CalendarYrToTm(atoi(gpsyear.value())); // year offset from 1970 t = makeTime(tm); - //ESP_LOGD(TAG, "GPS time/date = %2d:%2d:%2d / %2d.%2d.%2d", tm.Hour, + // ESP_LOGD(TAG, "GPS time/date = %2d:%2d:%2d / %2d.%2d.%2d", tm.Hour, // tm.Minute, tm.Second, tm.Day, tm.Month, tm.Year + 1970); // add protocol delay with millisecond precision @@ -170,8 +170,10 @@ void gps_loop(void *pvParameters) { // (only) while device time is not set or unsynched, and we have a valid // GPS time, we trigger a device time update to poll time from GPS - if (timeSource == _unsynced && gpstime.isUpdated()) + if (timeSource == _unsynced && gpstime.isUpdated()) { + now(); calibrateTime(); + } } // if From 0d7683fdcc9ea2786e2a303180915d93844a50a6 Mon Sep 17 00:00:00 2001 From: Klaus K Wilting Date: Fri, 9 Oct 2020 22:46:45 +0200 Subject: [PATCH 40/44] fix missing clearance of timesync pending flag --- src/timesync.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/timesync.cpp b/src/timesync.cpp index 9269bd80..b91ae2d7 100644 --- a/src/timesync.cpp +++ b/src/timesync.cpp @@ -154,9 +154,11 @@ void IRAM_ATTR timesync_processReq(void *taskparameter) { Fail: // set retry timer timesyncer.attach(TIME_SYNC_INTERVAL_RETRY * 60, setTimeSyncIRQ); + // intentionally fallthrough to Finish here Finish: // end of time critical section: release app irq lock + timeSyncPending = false; unmask_user_IRQ(); } // infinite while(1) @@ -181,6 +183,7 @@ void IRAM_ATTR timesync_serverAnswer(void *pUserData, int flag) { // mask application irq to ensure accurate timing mask_user_IRQ(); + // return code: 0 = failed / 1 = success int rc = 0; // cast back void parameter to a pointer uint8_t *p = (uint8_t *)pUserData, rcv_seqNo = *p; From 0f1ab7e89e35d680d883856f4aaf11f22dee6b1a Mon Sep 17 00:00:00 2001 From: Klaus K Wilting Date: Fri, 9 Oct 2020 22:47:04 +0200 Subject: [PATCH 41/44] small code sanitizations --- src/irqhandler.cpp | 2 +- src/rcommand.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/irqhandler.cpp b/src/irqhandler.cpp index 528a8187..a169f4b1 100644 --- a/src/irqhandler.cpp +++ b/src/irqhandler.cpp @@ -84,7 +84,7 @@ void irqHandler(void *pvParameters) { } // do we have a power event? -#if (HAS_PMU) +#ifdef HAS_PMU if (InterruptStatus & PMU_IRQ) { AXP192_powerevent_IRQ(); InterruptStatus &= ~PMU_IRQ; diff --git a/src/rcommand.cpp b/src/rcommand.cpp index eb15dd0d..75899eca 100644 --- a/src/rcommand.cpp +++ b/src/rcommand.cpp @@ -329,7 +329,7 @@ void get_time(uint8_t val[]) { }; void set_time(uint8_t val[]) { - ESP_LOGI(TAG, "Timesync requested by timeserver"); + ESP_LOGI(TAG, "Remote command: timesync requested"); setTimeSyncIRQ(); }; From ac82a5f19eed2c9187642a71581b0657a96ac68e Mon Sep 17 00:00:00 2001 From: Klaus K Wilting Date: Fri, 9 Oct 2020 22:48:15 +0200 Subject: [PATCH 42/44] packed decoder modified for fix issue #659 --- src/TTN/packed_decoder.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/TTN/packed_decoder.js b/src/TTN/packed_decoder.js index 97dfbcde..fef75870 100644 --- a/src/TTN/packed_decoder.js +++ b/src/TTN/packed_decoder.js @@ -257,7 +257,7 @@ var bitmap2 = function (byte) { } var i = bytesToInt(byte); var bm = ('00000000' + Number(i).toString(2)).substr(-8).split('').map(Number).map(Boolean); - return ['gps', 'alarm', 'bme', 'counter', 'sensor1', 'sensor2', 'sensor3', 'battery'] + return ['battery', 'sensor3', 'sensor2', 'sensor1', 'counter', 'bme', 'alarm', 'gps'] .reduce(function (obj, pos, index) { obj[pos] = +bm[index]; return obj; From 92eb55b001b5156f576ffa919f4333b176fbe027 Mon Sep 17 00:00:00 2001 From: Klaus K Wilting Date: Fri, 9 Oct 2020 23:02:36 +0200 Subject: [PATCH 43/44] time sync protocol: handling of end mark 0xff --- src/Timeserver/Nodered-Timeserver.json | 76 +++++++++++++------------- src/Timeserver/timeserver.java | 7 ++- src/timesync.cpp | 2 +- 3 files changed, 45 insertions(+), 40 deletions(-) diff --git a/src/Timeserver/Nodered-Timeserver.json b/src/Timeserver/Nodered-Timeserver.json index a9e3c58a..7cbd398c 100644 --- a/src/Timeserver/Nodered-Timeserver.json +++ b/src/Timeserver/Nodered-Timeserver.json @@ -1,41 +1,4 @@ [ - { - "id": "b8bd33fd.61caa", - "type": "function", - "z": "449c1517.e25f4c", - "name": "Timeserver Logic", - "func": "/* LoRaWAN Timeserver\n\nVERSION: 1.3\n\nconstruct 6 byte timesync_answer from gateway timestamp and node's time_sync_req\n\nbyte meaning\n1 sequence number (taken from node's time_sync_req)\n2..5 current second (from GPS epoch starting 1980)\n6 1/250ths fractions of current second\n\n*/\n\nfunction timecompare(a, b) {\n \n const timeA = a.time;\n const timeB = b.time;\n\n let comparison = 0;\n if (timeA > timeB) {\n comparison = 1;\n } else if (timeA < timeB) {\n comparison = -1;\n }\n return comparison;\n}\n\nlet confidence = 1000; // max millisecond diff gateway time to server time\n\n// guess if we have received a valid time_sync_req command\nif (msg.payload.payload_raw.length != 1)\n return;\n\nvar deviceMsg = { payload: msg.payload.dev_id };\nvar seqNo = msg.payload.payload_raw[0];\nvar seqNoMsg = { payload: seqNo };\nvar gateway_list = msg.payload.metadata.gateways;\n\n// filter all gateway timestamps that have milliseconds part (which we assume have a \".\")\nvar gateways = gateway_list.filter(function (element) {\n return (element.time.includes(\".\"));\n});\n\nvar gateway_time = gateways.map(gw => {\n return {\n time: new Date(gw.time),\n eui: gw.gtw_id,\n }\n });\nvar server_time = new Date(msg.payload.metadata.time);\n\n// validate all gateway timestamps against lorawan server_time (which is assumed to be recent)\nvar gw_timestamps = gateway_time.filter(function (element) {\n return ((element.time > (server_time - confidence) && element.time <= server_time));\n});\n\n// if no timestamp left, we have no valid one and exit\nif (gw_timestamps.length === 0) {\n var notavailMsg = { payload: \"n/a\" };\n var notimeMsg = { payload: 0xff }; \n var buf2 = Buffer.alloc(1);\n msg.payload = new Buffer(buf2.fill(0xff));\n msg.port = 9; // Paxcounter TIMEPORT\n return [notavailMsg, notavailMsg, deviceMsg, seqNoMsg, msg];}\n\n// sort time array in ascending order to find most recent timestamp for time answer\ngw_timestamps.sort(timecompare);\n\nvar timestamp = gw_timestamps[0].time;\nvar eui = gw_timestamps[0].eui;\nvar offset = server_time - timestamp;\n\nvar seconds = Math.floor(timestamp/1000);\nvar fractions = (timestamp % 1000) / 4;\n\nlet buf = new ArrayBuffer(6);\nnew DataView(buf).setUint8(0, seqNo);\nnew DataView(buf).setUint32(1, seconds);\nnew DataView(buf).setUint8(5, fractions);\n\nmsg.payload = new Buffer(new Uint8Array(buf));\nmsg.port = 9; // Paxcounter TIMEPORT\nvar euiMsg = { payload: eui };\nvar offsetMsg = { payload: offset };\n\nreturn [euiMsg, offsetMsg, deviceMsg, seqNoMsg, msg];", - "outputs": 5, - "noerr": 0, - "x": 330, - "y": 327, - "wires": [ - [ - "c9a83ac9.50fd18", - "6aeb3720.a89618", - "6ac55bbe.12ac54" - ], - [ - "de908e66.b6fd3" - ], - [ - "d5a35bab.44cb18" - ], - [ - "3a661f0a.c61b1" - ], - [ - "9b4f492d.fbfd18" - ] - ], - "outputLabels": [ - "gw_eui", - "offset_ms", - "device", - "seq_no", - "time_sync_ans" - ] - }, { "id": "9b4f492d.fbfd18", "type": "change", @@ -214,12 +177,49 @@ "id": "15980d22.6f4663", "type": "comment", "z": "449c1517.e25f4c", - "name": "LoRaWAN Timeserver v1.3", + "name": "LoRaWAN Timeserver v1.4", "info": "PLEASE NOTE: There is a patent filed for the time sync algorithm used in the\ncode of this file. The shown implementation example is covered by the\nrepository's licencse, but you may not be eligible to deploy the applied\nalgorithm in applications without granted license by the patent holder.", "x": 150, "y": 47, "wires": [] }, + { + "id": "b8bd33fd.61caa", + "type": "function", + "z": "449c1517.e25f4c", + "name": "Timeserver Logic", + "func": "/* LoRaWAN Timeserver\n\nVERSION: 1.4\n\nconstruct 6 byte timesync_answer from gateway timestamp and node's time_sync_req\n\nbyte meaning\n1 sequence number (taken from node's time_sync_req)\n2..5 current second (from GPS epoch starting 1980)\n6 1/250ths fractions of current second\n\n*/\n\nfunction timecompare(a, b) {\n \n const timeA = a.time;\n const timeB = b.time;\n\n let comparison = 0;\n if (timeA > timeB) {\n comparison = 1;\n } else if (timeA < timeB) {\n comparison = -1;\n }\n return comparison;\n}\n\nlet confidence = 1000; // max millisecond diff gateway time to server time\nlet TIME_SYNC_END_FLAG = 255;\n\n// guess if we have received a valid time_sync_req command\nif (msg.payload.payload_raw.length != 1)\n return;\n\nvar deviceMsg = { payload: msg.payload.dev_id };\nvar seqNo = msg.payload.payload_raw[0];\nvar seqNoMsg = { payload: seqNo };\nvar gateway_list = msg.payload.metadata.gateways;\n\n// don't answer on TIME_SYNC_END_FLAG\nif (seqNo == TIME_SYNC_END_FLAG)\n return;\n\n// filter all gateway timestamps that have milliseconds part (which we assume have a \".\")\nvar gateways = gateway_list.filter(function (element) {\n return (element.time.includes(\".\"));\n});\n\nvar gateway_time = gateways.map(gw => {\n return {\n time: new Date(gw.time),\n eui: gw.gtw_id,\n }\n });\nvar server_time = new Date(msg.payload.metadata.time);\n\n// validate all gateway timestamps against lorawan server_time (which is assumed to be recent)\nvar gw_timestamps = gateway_time.filter(function (element) {\n return ((element.time > (server_time - confidence) && element.time <= server_time));\n});\n\n// if no timestamp left, we have no valid one and exit\nif (gw_timestamps.length === 0) {\n var notavailMsg = { payload: \"n/a\" };\n var notimeMsg = { payload: 0xff }; \n var buf2 = Buffer.alloc(1);\n msg.payload = new Buffer(buf2.fill(0xff));\n msg.port = 9; // Paxcounter TIMEPORT\n return [notavailMsg, notavailMsg, deviceMsg, seqNoMsg, msg];}\n\n// sort time array in ascending order to find most recent timestamp for time answer\ngw_timestamps.sort(timecompare);\n\nvar timestamp = gw_timestamps[0].time;\nvar eui = gw_timestamps[0].eui;\nvar offset = server_time - timestamp;\n\nvar seconds = Math.floor(timestamp/1000);\nvar fractions = (timestamp % 1000) / 4;\n\nlet buf = new ArrayBuffer(6);\nnew DataView(buf).setUint8(0, seqNo);\nnew DataView(buf).setUint32(1, seconds);\nnew DataView(buf).setUint8(5, fractions);\n\nmsg.payload = new Buffer(new Uint8Array(buf));\nmsg.port = 9; // Paxcounter TIMEPORT\nvar euiMsg = { payload: eui };\nvar offsetMsg = { payload: offset };\n\nreturn [euiMsg, offsetMsg, deviceMsg, seqNoMsg, msg];", + "outputs": 5, + "noerr": 0, + "x": 330, + "y": 327, + "wires": [ + [ + "c9a83ac9.50fd18", + "6aeb3720.a89618", + "6ac55bbe.12ac54" + ], + [ + "de908e66.b6fd3" + ], + [ + "d5a35bab.44cb18" + ], + [ + "3a661f0a.c61b1" + ], + [ + "9b4f492d.fbfd18" + ] + ], + "outputLabels": [ + "gw_eui", + "offset_ms", + "device", + "seq_no", + "time_sync_ans" + ] + }, { "id": "c9a83ac9.50fd18", "type": "debug", diff --git a/src/Timeserver/timeserver.java b/src/Timeserver/timeserver.java index 5b0db293..ca81cf7a 100644 --- a/src/Timeserver/timeserver.java +++ b/src/Timeserver/timeserver.java @@ -1,6 +1,6 @@ /* LoRaWAN Timeserver -VERSION: 1.3 +VERSION: 1.4 construct 6 byte timesync_answer from gateway timestamp and node's time_sync_req @@ -26,6 +26,7 @@ function timecompare(a, b) { } let confidence = 1000; // max millisecond diff gateway time to server time +let TIME_SYNC_END_FLAG = 255; // guess if we have received a valid time_sync_req command if (msg.payload.payload_raw.length != 1) @@ -36,6 +37,10 @@ var seqNo = msg.payload.payload_raw[0]; var seqNoMsg = { payload: seqNo }; var gateway_list = msg.payload.metadata.gateways; +// don't answer on TIME_SYNC_END_FLAG +if (seqNo == TIME_SYNC_END_FLAG) + return; + // filter all gateway timestamps that have milliseconds part (which we assume have a ".") var gateways = gateway_list.filter(function (element) { return (element.time.includes(".")); diff --git a/src/timesync.cpp b/src/timesync.cpp index b91ae2d7..b79aa110 100644 --- a/src/timesync.cpp +++ b/src/timesync.cpp @@ -148,7 +148,7 @@ void IRAM_ATTR timesync_processReq(void *taskparameter) { // send timesync end char to show timesync was successful payload.reset(); payload.addByte(TIME_SYNC_END_FLAG); - SendPayload(RCMDPORT, prio_high); + SendPayload(TIMEPORT, prio_high); goto Finish; Fail: From 52a56e5cdeed2faf33039a30d40b844cf96ef290 Mon Sep 17 00:00:00 2001 From: Klaus K Wilting Date: Fri, 9 Oct 2020 23:04:34 +0200 Subject: [PATCH 44/44] v2.0.2 --- platformio_orig.ini | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/platformio_orig.ini b/platformio_orig.ini index 4dd2263d..c3e9d878 100644 --- a/platformio_orig.ini +++ b/platformio_orig.ini @@ -46,7 +46,7 @@ description = Paxcounter is a device for metering passenger flows in realtime. I [common] ; for release_version use max. 10 chars total, use any decimal format like "a.b.c" -release_version = 2.0.17 +release_version = 2.0.2 ; DEBUG LEVEL: For production run set to 0, otherwise device will leak RAM while running! ; 0=None, 1=Error, 2=Warn, 3=Info, 4=Debug, 5=Verbose debug_level = 3 @@ -95,10 +95,11 @@ lib_deps_all = build_flags_basic = -include "src/hal/${board.halfile}" -include "src/paxcounter.conf" - -w '-DCORE_DEBUG_LEVEL=${common.debug_level}' '-DLOG_LOCAL_LEVEL=${common.debug_level}' '-DPROGVERSION="${common.release_version}"' + '-Wno-unknown-pragmas' + '-Wno-unused-variable' build_flags_sensors = -Llib/Bosch-BSEC/src/esp32/ -lalgobsec