Merge pull request #499 from cyberman54/master

sync dev to master
This commit is contained in:
Verkehrsrot 2019-11-27 22:51:41 +01:00 committed by GitHub
commit 0c584f0f1b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 427 additions and 395 deletions

View File

@ -171,7 +171,7 @@ Output of sensor and peripheral data is internally switched by a bitmask registe
| Bit | Sensordata | Default
| --- | ------------- | -------
| 0 | GPS | off*
| 0 | GPS* | on
| 1 | Beacon alarm | on
| 2 | BME280/680 | on
| 3 | Paxcounter | on
@ -190,6 +190,12 @@ Paxcounter can keep it's time-of-day synced with an external time source. Set *#
Paxcounter can be used to sync a wall clock which has a DCF77 or IF482 time telegram input. Set *#define HAS_IF482* or *#define HAS_DCF77* in board's hal file to setup clock controller. Use case of this function is to integrate paxcounter and clock. Accurary of the synthetic DCF77 signal depends on accuracy of on board's time base, see above.
# mobile PaxCounter via https://opensensemap.org/
This describes how to set up a mobile PaxCounter:
Follow all steps so far for preparing the device, use the packed payload format. In paxcounter.conf set PAYLOAD_OPENSENSEBOX to 1. Register a new sensbox on https://opensensemap.org/.
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"}]
# Payload format
You can select different payload formats in [paxcounter.conf](src/paxcounter.conf#L12):
@ -213,7 +219,6 @@ Hereafter described is the default *plain* format, which uses MSB bit numbering.
[**packed_decoder.js**](src/TTN/packed_decoder.js) |
[**packed_converter.js**](src/TTN/packed_converter.js)
**Port #1:** Paxcount data
byte 1-2: Number of unique devices, seen on Wifi
@ -308,7 +313,7 @@ Note: all settings are stored in NVRAM and will be reloaded when device starts.
0x03 set GPS data on/off
0 = GPS data off
1 = GPS data on, sends GPS data on port 4, if GPS is present and has a fix [default]
1 = GPS data on, sends GPS data on port 4 (default, use port 1 for mobile pax counter), if GPS is present and has a fix
0x04 set display on/off
@ -501,3 +506,4 @@ Thanks to
- [robbi5](https://github.com/robbi5) for the payload converter
- [terrillmoore](https://github.com/mcci-catena) for maintaining the LMIC for arduino LoRaWAN stack
- [sbamueller](https://github.com/sbamueller) for writing the tutorial in Make Magazine
- [Stefan](https://github.com/nerdyscout) for paxcounter opensensebox integration

View File

@ -7,7 +7,7 @@
; ---> SELECT THE TARGET PLATFORM HERE! <---
[board]
;halfile = generic.h
halfile = generic.h
;halfile = ebox.h
;halfile = eboxtube.h
;halfile = ecopower.h
@ -18,7 +18,7 @@
;halfile = ttgov21old.h
;halfile = ttgov21new.h
;halfile = ttgofox.h
halfile = ttgobeam.h
;halfile = ttgobeam.h
;halfile = ttgobeam10.h
;halfile = fipy.h
;halfile = lopy.h
@ -43,10 +43,10 @@ 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 = 1.9.81
release_version = 1.9.82
; 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 = 4
debug_level = 3
extra_scripts = pre:build.py
otakeyfile = ota.conf
lorakeyfile = loraconf.h

View File

@ -18,6 +18,14 @@ function Decoder(bytes, port) {
if (bytes.length === 4) {
return decode(bytes, [uint16, uint16], ['wifi', 'ble']);
}
// combined wifi counter and gps data, used by https://opensensemap.org
if (bytes.length === 10) {
return decode(bytes, [latLng, latLng, uint16], ['latitude', 'longitude', 'wifi']);
}
// combined wifi + ble counter and gps data, used by https://opensensemap.org
if (bytes.length === 12) {
return decode(bytes, [latLng, latLng, uint16, uint16], ['latitude', 'longitude', 'wifi', 'ble']);
}
// combined wifi counter and gps data
if (bytes.length === 15) {
return decode(bytes, [uint16, latLng, latLng, uint8, hdop, altitude], ['wifi', 'latitude', 'longitude', 'sats', 'hdop', 'altitude']);
@ -42,7 +50,11 @@ function Decoder(bytes, port) {
if (port === 4) {
// gps data
return decode(bytes, [latLng, latLng, uint8, hdop, altitude], ['latitude', 'longitude', 'sats', 'hdop', 'altitude']);
if (bytes.length === 8) {
return decode(bytes, [latLng, latLng], ['latitude', 'longitude']);
} else {
return decode(bytes, [latLng, latLng, uint8, hdop, altitude], ['latitude', 'longitude', 'sats', 'hdop', 'altitude']);
}
}
if (port === 5) {

View File

@ -1,364 +1,364 @@
/* configmanager persists runtime configuration using NVRAM of ESP32*/
#include "globals.h"
// Local logging tag
static const char TAG[] = "flash";
nvs_handle my_handle;
esp_err_t err;
#define PAYLOADMASK \
((ALARM_DATA | MEMS_DATA | COUNT_DATA | SENSOR1_DATA | SENSOR2_DATA | \
SENSOR3_DATA) & \
(~BATT_DATA) & (~GPS_DATA))
// 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 =
WIFI_CHANNEL_SWITCH_INTERVAL; // wifi channel switch cycle [seconds/100]
cfg.blescantime =
BLESCANINTERVAL /
10; // BT channel scan cycle [seconds/100], default 1 (= 10ms)
cfg.blescan = BLECOUNTER; // 0=disabled, 1=enabled
cfg.wifiscan = WIFICOUNTER; // 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");
}
}
// save current configuration from RAM to NVRAM
void saveConfig() {
ESP_LOGI(TAG, "Storing settings in NVS");
open_storage();
if (err == ESP_OK) {
int8_t flash8 = 0;
int16_t flash16 = 0;
size_t required_size;
uint8_t bsecstate_buffer[BSEC_MAX_STATE_BLOB_SIZE + 1];
char storedversion[10];
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);
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_i8(my_handle, "loradr", &flash8) != ESP_OK ||
flash8 != cfg.loradr)
nvs_set_i8(my_handle, "loradr", cfg.loradr);
if (nvs_get_i8(my_handle, "txpower", &flash8) != ESP_OK ||
flash8 != cfg.txpower)
nvs_set_i8(my_handle, "txpower", cfg.txpower);
if (nvs_get_i8(my_handle, "adrmode", &flash8) != ESP_OK ||
flash8 != cfg.adrmode)
nvs_set_i8(my_handle, "adrmode", cfg.adrmode);
if (nvs_get_i8(my_handle, "screensaver", &flash8) != ESP_OK ||
flash8 != cfg.screensaver)
nvs_set_i8(my_handle, "screensaver", cfg.screensaver);
if (nvs_get_i8(my_handle, "screenon", &flash8) != ESP_OK ||
flash8 != cfg.screenon)
nvs_set_i8(my_handle, "screenon", cfg.screenon);
if (nvs_get_i8(my_handle, "countermode", &flash8) != ESP_OK ||
flash8 != cfg.countermode)
nvs_set_i8(my_handle, "countermode", cfg.countermode);
if (nvs_get_i8(my_handle, "sendcycle", &flash8) != ESP_OK ||
flash8 != cfg.sendcycle)
nvs_set_i8(my_handle, "sendcycle", cfg.sendcycle);
if (nvs_get_i8(my_handle, "wifichancycle", &flash8) != ESP_OK ||
flash8 != cfg.wifichancycle)
nvs_set_i8(my_handle, "wifichancycle", cfg.wifichancycle);
if (nvs_get_i8(my_handle, "blescantime", &flash8) != ESP_OK ||
flash8 != cfg.blescantime)
nvs_set_i8(my_handle, "blescantime", cfg.blescantime);
if (nvs_get_i8(my_handle, "blescanmode", &flash8) != ESP_OK ||
flash8 != cfg.blescan)
nvs_set_i8(my_handle, "blescanmode", cfg.blescan);
if (nvs_get_i8(my_handle, "wifiscanmode", &flash8) != ESP_OK ||
flash8 != cfg.wifiscan)
nvs_set_i8(my_handle, "wifiscanmode", cfg.wifiscan);
if (nvs_get_i8(my_handle, "wifiant", &flash8) != ESP_OK ||
flash8 != cfg.wifiant)
nvs_set_i8(my_handle, "wifiant", cfg.wifiant);
if (nvs_get_i8(my_handle, "vendorfilter", &flash8) != ESP_OK ||
flash8 != cfg.vendorfilter)
nvs_set_i8(my_handle, "vendorfilter", cfg.vendorfilter);
if (nvs_get_i8(my_handle, "rgblum", &flash8) != ESP_OK ||
flash8 != cfg.rgblum)
nvs_set_i8(my_handle, "rgblum", cfg.rgblum);
if (nvs_get_i8(my_handle, "payloadmask", &flash8) != ESP_OK ||
flash8 != cfg.payloadmask)
nvs_set_i8(my_handle, "payloadmask", cfg.payloadmask);
if (nvs_get_i8(my_handle, "monitormode", &flash8) != ESP_OK ||
flash8 != cfg.monitormode)
nvs_set_i8(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);
}
}
// set and save cfg.version
void migrateVersion() {
snprintf(cfg.version, 10, "%s", PROGVERSION);
ESP_LOGI(TAG, "version set to %s", cfg.version);
saveConfig();
}
// 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 {
int8_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);
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_i8(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_i8(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();
}
if (nvs_get_i8(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();
}
if (nvs_get_i8(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_i8(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_i8(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_i8(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_i8(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_i8(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_i8(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_i8(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_i8(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_i8(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_i8(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_i8(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_i8(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()
/* configmanager persists runtime configuration using NVRAM of ESP32*/
#include "globals.h"
// Local logging tag
static const char TAG[] = "flash";
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) )
// 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 =
WIFI_CHANNEL_SWITCH_INTERVAL; // wifi channel switch cycle [seconds/100]
cfg.blescantime =
BLESCANINTERVAL /
10; // BT channel scan cycle [seconds/100], default 1 (= 10ms)
cfg.blescan = BLECOUNTER; // 0=disabled, 1=enabled
cfg.wifiscan = WIFICOUNTER; // 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");
}
}
// save current configuration from RAM to NVRAM
void saveConfig() {
ESP_LOGI(TAG, "Storing settings in NVS");
open_storage();
if (err == ESP_OK) {
int8_t flash8 = 0;
int16_t flash16 = 0;
size_t required_size;
uint8_t bsecstate_buffer[BSEC_MAX_STATE_BLOB_SIZE + 1];
char storedversion[10];
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);
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_i8(my_handle, "loradr", &flash8) != ESP_OK ||
flash8 != cfg.loradr)
nvs_set_i8(my_handle, "loradr", cfg.loradr);
if (nvs_get_i8(my_handle, "txpower", &flash8) != ESP_OK ||
flash8 != cfg.txpower)
nvs_set_i8(my_handle, "txpower", cfg.txpower);
if (nvs_get_i8(my_handle, "adrmode", &flash8) != ESP_OK ||
flash8 != cfg.adrmode)
nvs_set_i8(my_handle, "adrmode", cfg.adrmode);
if (nvs_get_i8(my_handle, "screensaver", &flash8) != ESP_OK ||
flash8 != cfg.screensaver)
nvs_set_i8(my_handle, "screensaver", cfg.screensaver);
if (nvs_get_i8(my_handle, "screenon", &flash8) != ESP_OK ||
flash8 != cfg.screenon)
nvs_set_i8(my_handle, "screenon", cfg.screenon);
if (nvs_get_i8(my_handle, "countermode", &flash8) != ESP_OK ||
flash8 != cfg.countermode)
nvs_set_i8(my_handle, "countermode", cfg.countermode);
if (nvs_get_i8(my_handle, "sendcycle", &flash8) != ESP_OK ||
flash8 != cfg.sendcycle)
nvs_set_i8(my_handle, "sendcycle", cfg.sendcycle);
if (nvs_get_i8(my_handle, "wifichancycle", &flash8) != ESP_OK ||
flash8 != cfg.wifichancycle)
nvs_set_i8(my_handle, "wifichancycle", cfg.wifichancycle);
if (nvs_get_i8(my_handle, "blescantime", &flash8) != ESP_OK ||
flash8 != cfg.blescantime)
nvs_set_i8(my_handle, "blescantime", cfg.blescantime);
if (nvs_get_i8(my_handle, "blescanmode", &flash8) != ESP_OK ||
flash8 != cfg.blescan)
nvs_set_i8(my_handle, "blescanmode", cfg.blescan);
if (nvs_get_i8(my_handle, "wifiscanmode", &flash8) != ESP_OK ||
flash8 != cfg.wifiscan)
nvs_set_i8(my_handle, "wifiscanmode", cfg.wifiscan);
if (nvs_get_i8(my_handle, "wifiant", &flash8) != ESP_OK ||
flash8 != cfg.wifiant)
nvs_set_i8(my_handle, "wifiant", cfg.wifiant);
if (nvs_get_i8(my_handle, "vendorfilter", &flash8) != ESP_OK ||
flash8 != cfg.vendorfilter)
nvs_set_i8(my_handle, "vendorfilter", cfg.vendorfilter);
if (nvs_get_i8(my_handle, "rgblum", &flash8) != ESP_OK ||
flash8 != cfg.rgblum)
nvs_set_i8(my_handle, "rgblum", cfg.rgblum);
if (nvs_get_i8(my_handle, "payloadmask", &flash8) != ESP_OK ||
flash8 != cfg.payloadmask)
nvs_set_i8(my_handle, "payloadmask", cfg.payloadmask);
if (nvs_get_i8(my_handle, "monitormode", &flash8) != ESP_OK ||
flash8 != cfg.monitormode)
nvs_set_i8(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);
}
}
// set and save cfg.version
void migrateVersion() {
snprintf(cfg.version, 10, "%s", PROGVERSION);
ESP_LOGI(TAG, "version set to %s", cfg.version);
saveConfig();
}
// 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 {
int8_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);
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_i8(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_i8(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();
}
if (nvs_get_i8(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();
}
if (nvs_get_i8(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_i8(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_i8(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_i8(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_i8(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_i8(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_i8(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_i8(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_i8(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_i8(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_i8(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_i8(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_i8(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()

View File

@ -34,9 +34,9 @@ IDLE 0 0 ESP32 arduino scheduler -> runs wifi sniffer
lmictask 1 2 MCCI LMiC LORAWAN stack
clockloop 1 4 generates realtime telegrams for external clock
timesync_req 1 3 processes realtime time sync requests
irqhandler 1 1 display, timesync, gps, etc. triggered by timers
irqhandler 1 1 cyclic tasks (i.e. displayrefresh) triggered by timers
gpsloop 1 1 reads data from GPS via serial or i2c
lorasendtask 1 1 feed data from lora sendqueue to lmcic
lorasendtask 1 1 feeds data from lora sendqueue to lmcic
IDLE 1 0 ESP32 arduino scheduler -> runs wifi channel rotator
Low priority numbers denote low priority tasks.

View File

@ -47,6 +47,7 @@
#define MEM_LOW 2048 // [Bytes] low memory threshold triggering a send cycle
#define RETRANSMIT_RCMD 5 // [seconds] wait time before retransmitting rcommand results
#define PAYLOAD_BUFFER_SIZE 51 // maximum size of payload block per transmit
#define PAYLOAD_OPENSENSEBOX 0 // send payload compatible to sensebox.de (swap geo position and pax data)
#define LORADRDEFAULT 5 // 0 .. 15, LoRaWAN datarate, according to regional LoRaWAN specs [default = 5]
#define LORATXPOWDEFAULT 14 // 0 .. 255, LoRaWAN TX power in dBm [default = 14]
#define MAXLORARETRY 500 // maximum count of TX retries if LoRa busy
@ -92,7 +93,7 @@
#define RCMDPORT 2 // remote commands
#define STATUSPORT 2 // remote command results
#define CONFIGPORT 3 // config query results
#define GPSPORT 4 // gps - set to 1 to send combined GPS+COUNT payload
#define GPSPORT 4 // gps - set to 1 to send combined GPS+COUNTERPORT payload
#define BUTTONPORT 5 // button pressed signal
#define BEACONPORT 6 // beacon alarms
#define BMEPORT 7 // BME680 sensor

View File

@ -89,12 +89,14 @@ void PayloadConvert::addGPS(gpsStatus_t value) {
buffer[cursor++] = (byte)((value.longitude & 0x00FF0000) >> 16);
buffer[cursor++] = (byte)((value.longitude & 0x0000FF00) >> 8);
buffer[cursor++] = (byte)((value.longitude & 0x000000FF));
#if (!PAYLOAD_OPENSENSEBOX)
buffer[cursor++] = value.satellites;
buffer[cursor++] = highByte(value.hdop);
buffer[cursor++] = lowByte(value.hdop);
buffer[cursor++] = highByte(value.altitude);
buffer[cursor++] = lowByte(value.altitude);
#endif
#endif
}
void PayloadConvert::addSensor(uint8_t buf[]) {
@ -193,10 +195,12 @@ void PayloadConvert::addStatus(uint16_t voltage, uint64_t uptime, float cputemp,
void PayloadConvert::addGPS(gpsStatus_t value) {
#if(HAS_GPS)
writeLatLng(value.latitude, value.longitude);
#if (!PAYLOAD_OPENSENSEBOX)
writeUint8(value.satellites);
writeUint16(value.hdop);
writeUint16(value.altitude);
#endif
#endif
}
void PayloadConvert::addSensor(uint8_t buf[]) {

View File

@ -58,6 +58,7 @@ void sendData() {
uint8_t bitmask = cfg.payloadmask;
uint8_t mask = 1;
gpsStatus_t gps_status;
while (bitmask) {
switch (bitmask & mask) {
@ -65,21 +66,28 @@ void sendData() {
#if ((WIFICOUNTER) || (BLECOUNTER))
case COUNT_DATA:
payload.reset();
#if !(PAYLOAD_OPENSENSEBOX)
if (cfg.wifiscan)
payload.addCount(macs_wifi, MAC_SNIFF_WIFI);
if (cfg.blescan)
payload.addCount(macs_ble, MAC_SNIFF_BLE);
#endif
#if (HAS_GPS)
if (GPSPORT == COUNTERPORT) {
// send GPS position only if we have a fix
if (gps.location.isValid()) {
gps_storelocation(&gps_status);
payload.addGPS(gps_status);
} else
ESP_LOGD(TAG, "No valid GPS position");
}
#endif
#if (PAYLOAD_OPENSENSEBOX)
if (cfg.wifiscan)
payload.addCount(macs_wifi, MAC_SNIFF_WIFI);
if (cfg.blescan)
payload.addCount(macs_ble, MAC_SNIFF_BLE);
#if (HAS_GPS) && (GPSPORT == 1)
// send GPS position only if we have a fix
if (gps.location.isValid()) {
gpsStatus_t gps_status;
gps_storelocation(&gps_status);
payload.addGPS(gps_status);
} else
ESP_LOGD(TAG, "No valid GPS position");
#endif
SendPayload(COUNTERPORT, prio_normal);
// clear counter if not in cumulative counter mode
if (cfg.countermode != 1) {
@ -102,17 +110,18 @@ void sendData() {
break;
#endif
#if (HAS_GPS) && (GPSPORT != 1)
#if (HAS_GPS)
case GPS_DATA:
// send GPS position only if we have a fix
if (gps.location.isValid()) {
gpsStatus_t gps_status;
gps_storelocation(&gps_status);
payload.reset();
payload.addGPS(gps_status);
SendPayload(GPSPORT, prio_high);
} else
ESP_LOGD(TAG, "No valid GPS position");
if (GPSPORT != COUNTERPORT) {
// send GPS position only if we have a fix
if (gps.location.isValid()) {
gps_storelocation(&gps_status);
payload.reset();
payload.addGPS(gps_status);
SendPayload(GPSPORT, prio_high);
} else
ESP_LOGD(TAG, "No valid GPS position");
}
break;
#endif