Merge pull request #166 from cyberman54/development

v1.5.7
This commit is contained in:
Verkehrsrot 2018-09-27 19:12:13 +02:00 committed by GitHub
commit fb759d3e56
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
23 changed files with 194 additions and 127 deletions

View File

@ -20,9 +20,9 @@ Parts of the source files in this repository are made available under different
listed below. Refer to each individual source file for more details. listed below. Refer to each individual source file for more details.
------------------------------------------------------------------------------------------------ ------------------------------------------------------------------------------------------------
wifisniffer.cpp wifiscan.cpp
Parts of wifisniffer.cpp were derived or taken from Prior art was used for wifiscan.cpp and taken from
* Copyright (c) 2017, Łukasz Marcin Podkalicki <lpodkalicki@gmail.com> * Copyright (c) 2017, Łukasz Marcin Podkalicki <lpodkalicki@gmail.com>
* ESP32/016 WiFi Sniffer * ESP32/016 WiFi Sniffer

View File

@ -90,5 +90,4 @@ def publish_bintray(source, target, env):
# put build file name and upload command to platformio environment # put build file name and upload command to platformio environment
env.Replace( env.Replace(
PROGNAME="firmware_" + package + "_v%s" % version, PROGNAME="firmware_" + package + "_v%s" % version,
UPLOADCMD=publish_bintray UPLOADCMD=publish_bintray)
)

View File

@ -26,7 +26,7 @@ description = Paxcounter is a proof-of-concept ESP32 device for metering passeng
[common] [common]
; for release_version use max. 10 chars total, use any decimal format like "a.b.c" ; for release_version use max. 10 chars total, use any decimal format like "a.b.c"
release_version = 1.5.3 release_version = 1.5.7
; DEBUG LEVEL: For production run set to 0, otherwise device will leak RAM while running! ; 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 ; 0=None, 1=Error, 2=Warn, 3=Info, 4=Debug, 5=Verbose
debug_level = 0 debug_level = 0

View File

@ -6,10 +6,13 @@
// Local logging tag // Local logging tag
static const char TAG[] = "main"; static const char TAG[] = "main";
void IRAM_ATTR ButtonIRQ() { ButtonPressedIRQ++; } void IRAM_ATTR ButtonIRQ() {
portENTER_CRITICAL(&timerMux);
ButtonPressedIRQ++;
portEXIT_CRITICAL(&timerMux);
}
void readButton() { void readButton() {
if (ButtonPressedIRQ) {
portENTER_CRITICAL(&timerMux); portENTER_CRITICAL(&timerMux);
ButtonPressedIRQ = 0; ButtonPressedIRQ = 0;
portEXIT_CRITICAL(&timerMux); portEXIT_CRITICAL(&timerMux);
@ -18,5 +21,4 @@ void readButton() {
payload.addButton(0x01); payload.addButton(0x01);
SendData(BUTTONPORT); SendData(BUTTONPORT);
} }
}
#endif #endif

View File

@ -23,6 +23,19 @@ void doHousekeeping() {
if (cfg.runmode == 1) if (cfg.runmode == 1)
ESP.restart(); ESP.restart();
// task storage debugging //
#ifdef HAS_LORA
ESP_LOGD(TAG, "Loraloop %d bytes left",
uxTaskGetStackHighWaterMark(LoraTask));
#endif
ESP_LOGD(TAG, "Wifiloop %d bytes left",
uxTaskGetStackHighWaterMark(wifiSwitchTask));
ESP_LOGD(TAG, "Statemachine %d bytes left",
uxTaskGetStackHighWaterMark(stateMachineTask));
#ifdef HAS_GPS
ESP_LOGD(TAG, "Gpsloop %d bytes left", uxTaskGetStackHighWaterMark(GpsTask));
#endif
// read battery voltage into global variable // read battery voltage into global variable
#ifdef HAS_BATTERY_PROBE #ifdef HAS_BATTERY_PROBE
batt_voltage = read_voltage(); batt_voltage = read_voltage();
@ -48,7 +61,7 @@ void doHousekeeping() {
esp_get_minimum_free_heap_size(), ESP.getFreeHeap()); esp_get_minimum_free_heap_size(), ESP.getFreeHeap());
SendData(COUNTERPORT); // send data before clearing counters SendData(COUNTERPORT); // send data before clearing counters
reset_counters(); // clear macs container and reset all counters reset_counters(); // clear macs container and reset all counters
reset_salt(); // get new salt for salting hashes get_salt(); // get new salt for salting hashes
if (esp_get_minimum_free_heap_size() <= MEM_LOW) // check again if (esp_get_minimum_free_heap_size() <= MEM_LOW) // check again
esp_restart(); // memory leak, reset device esp_restart(); // memory leak, reset device

View File

@ -13,7 +13,7 @@ const char lora_datarate[] = {"1211100908077BFSNA"};
const char lora_datarate[] = {"100908078CNA121110090807"}; const char lora_datarate[] = {"100908078CNA121110090807"};
#endif #endif
uint8_t DisplayState = 0; uint8_t volatile DisplayState = 0;
// helper function, prints a hex key on display // helper function, prints a hex key on display
void DisplayKey(const uint8_t *key, uint8_t len, bool lsb) { void DisplayKey(const uint8_t *key, uint8_t len, bool lsb) {
@ -91,6 +91,10 @@ void init_display(const char *Productname, const char *Version) {
void refreshtheDisplay() { void refreshtheDisplay() {
portENTER_CRITICAL(&timerMux);
DisplayTimerIRQ = 0;
portEXIT_CRITICAL(&timerMux);
// set display on/off according to current device configuration // set display on/off according to current device configuration
if (DisplayState != cfg.screenon) { if (DisplayState != cfg.screenon) {
DisplayState = cfg.screenon; DisplayState = cfg.screenon;
@ -114,7 +118,8 @@ void refreshtheDisplay() {
// update Battery status (line 2) // update Battery status (line 2)
#ifdef HAS_BATTERY_PROBE #ifdef HAS_BATTERY_PROBE
u8x8.setCursor(0, 2); u8x8.setCursor(0, 2);
u8x8.printf(batt_voltage > 4000 ? "B:USB " : "B:%.1fV", batt_voltage / 1000.0); u8x8.printf(batt_voltage > 4000 ? "B:USB " : "B:%.1fV",
batt_voltage / 1000.0);
#endif #endif
// update GPS status (line 2) // update GPS status (line 2)
@ -191,13 +196,4 @@ void IRAM_ATTR DisplayIRQ() {
portEXIT_CRITICAL_ISR(&timerMux); portEXIT_CRITICAL_ISR(&timerMux);
} }
void updateDisplay() {
if (DisplayTimerIRQ) {
portENTER_CRITICAL(&timerMux);
DisplayTimerIRQ = 0;
portEXIT_CRITICAL(&timerMux);
refreshtheDisplay();
}
}
#endif // HAS_DISPLAY #endif // HAS_DISPLAY

View File

@ -3,13 +3,12 @@
#include <U8x8lib.h> #include <U8x8lib.h>
extern uint8_t DisplayState; extern uint8_t volatile DisplayState;
extern HAS_DISPLAY u8x8; extern HAS_DISPLAY u8x8;
void init_display(const char *Productname, const char *Version); void init_display(const char *Productname, const char *Version);
void refreshtheDisplay(void); void refreshtheDisplay(void);
void DisplayKey(const uint8_t *key, uint8_t len, bool lsb); void DisplayKey(const uint8_t *key, uint8_t len, bool lsb);
void updateDisplay(void);
void DisplayIRQ(void); void DisplayIRQ(void);
#endif #endif

View File

@ -41,17 +41,21 @@ typedef struct {
// global variables // global variables
extern configData_t cfg; // current device configuration extern configData_t cfg; // current device configuration
extern char display_line6[], display_line7[]; // screen buffers extern char display_line6[], display_line7[]; // screen buffers
extern uint8_t channel; // wifi channel rotation counter extern uint8_t volatile channel; // wifi channel rotation counter
extern uint16_t macs_total, macs_wifi, macs_ble, batt_voltage; // display values extern uint16_t volatile macs_total, macs_wifi, macs_ble,
batt_voltage; // display values
extern std::set<uint16_t> macs; // temp storage for MACs extern std::set<uint16_t> macs; // temp storage for MACs
extern hw_timer_t *channelSwitch, *sendCycle; extern hw_timer_t *channelSwitch, *sendCycle;
extern portMUX_TYPE timerMux; extern portMUX_TYPE timerMux;
extern volatile int SendCycleTimerIRQ, HomeCycleIRQ, DisplayTimerIRQ, extern volatile uint8_t SendCycleTimerIRQ, HomeCycleIRQ, DisplayTimerIRQ,
ChannelTimerIRQ, ButtonPressedIRQ; ChannelTimerIRQ, ButtonPressedIRQ;
extern std::array<uint64_t, 0xff>::iterator it; extern std::array<uint64_t, 0xff>::iterator it;
extern std::array<uint64_t, 0xff> beacons; extern std::array<uint64_t, 0xff> beacons;
extern SemaphoreHandle_t xWifiChannelSwitchSemaphore;
extern TaskHandle_t stateMachineTask, wifiSwitchTask;
#ifdef HAS_GPS #ifdef HAS_GPS
extern TaskHandle_t GpsTask; extern TaskHandle_t GpsTask;
#include "gps.h" #include "gps.h"

View File

@ -3,7 +3,9 @@
#define HAS_LORA 1 // comment out if device shall not send data via LoRa #define HAS_LORA 1 // comment out if device shall not send data via LoRa
#define HAS_SPI 1 // comment out if device shall not send data via SPI #define HAS_SPI 1 // comment out if device shall not send data via SPI
#define CFG_sx1272_radio 1 #define CFG_sx1272_radio 1
#define HAS_LED NOT_A_PIN // LoPy has no on board LED, so we use RGB LED on LoPy //#define HAS_LED NOT_A_PIN // LoPy4 has no on board mono LED, we use on board RGB LED
#define HAS_LED GPIO_NUM_12 // use if LoPy is on Expansion Board, this has a user LED
#define LED_ACTIVE_LOW 1 // use if LoPy is on Expansion Board, this has a user LED
#define HAS_RGB_LED GPIO_NUM_0 // WS2812B RGB LED on GPIO0 #define HAS_RGB_LED GPIO_NUM_0 // WS2812B RGB LED on GPIO0
// Hardware pin definitions for Pycom LoPy board // Hardware pin definitions for Pycom LoPy board
@ -28,7 +30,7 @@
// uncomment this only if your LoPy runs on a expansion board 3.0 // uncomment this only if your LoPy runs on a expansion board 3.0
//#define HAS_BATTERY_PROBE ADC1_GPIO39_CHANNEL // battery probe GPIO pin -> ADC1_CHANNEL_7 //#define HAS_BATTERY_PROBE ADC1_GPIO39_CHANNEL // battery probe GPIO pin -> ADC1_CHANNEL_7
//#define BATT_FACTOR 2 // voltage divider 1MOhm/1MOhm on board //#define BATT_FACTOR 2 // voltage divider 1MOhm/1MOhm on board
//#define HAS_BUTTON GPIO_NUM_37 // (P14) //#define HAS_BUTTON GPIO_NUM_13 // (P14)
//#define BUTTON_PULLUP 1 // Button need pullup instead of default pulldown //#define BUTTON_PULLUP 1 // Button need pullup instead of default pulldown
// uncomment this only if your LoPy runs on a expansion board 2.0 // uncomment this only if your LoPy runs on a expansion board 2.0

View File

@ -3,7 +3,9 @@
#define HAS_LORA 1 // comment out if device shall not send data via LoRa #define HAS_LORA 1 // comment out if device shall not send data via LoRa
#define HAS_SPI 1 // comment out if device shall not send data via SPI #define HAS_SPI 1 // comment out if device shall not send data via SPI
#define CFG_sx1276_radio 1 #define CFG_sx1276_radio 1
#define HAS_LED NOT_A_PIN // LoPy4 has no on board LED, so we use RGB LED on LoPy4 //#define HAS_LED NOT_A_PIN // LoPy4 has no on board mono LED, we use on board RGB LED
#define HAS_LED GPIO_NUM_12 // use if LoPy is on Expansion Board, this has a user LED
#define LED_ACTIVE_LOW 1 // use if LoPy is on Expansion Board, this has a user LED
#define HAS_RGB_LED GPIO_NUM_0 // WS2812B RGB LED on GPIO0 #define HAS_RGB_LED GPIO_NUM_0 // WS2812B RGB LED on GPIO0
#define BOARD_HAS_PSRAM // use extra 4MB extern RAM #define BOARD_HAS_PSRAM // use extra 4MB extern RAM
@ -29,7 +31,7 @@
// uncomment this only if your LoPy runs on a expansion board 3.0 // uncomment this only if your LoPy runs on a expansion board 3.0
#define HAS_BATTERY_PROBE ADC1_GPIO39_CHANNEL // battery probe GPIO pin -> ADC1_CHANNEL_7 #define HAS_BATTERY_PROBE ADC1_GPIO39_CHANNEL // battery probe GPIO pin -> ADC1_CHANNEL_7
#define BATT_FACTOR 2 // voltage divider 1MOhm/1MOhm on board #define BATT_FACTOR 2 // voltage divider 1MOhm/1MOhm on board
#define HAS_BUTTON GPIO_NUM_37 // (P14) #define HAS_BUTTON GPIO_NUM_13 // (P14)
#define BUTTON_PULLUP 1 // Button need pullup instead of default pulldown #define BUTTON_PULLUP 1 // Button need pullup instead of default pulldown
// uncomment this only if your LoPy runs on a expansion board 2.0 // uncomment this only if your LoPy runs on a expansion board 2.0

View File

@ -247,7 +247,9 @@ void lorawan_loop(void *pvParameters) {
configASSERT(((uint32_t)pvParameters) == 1); // FreeRTOS check configASSERT(((uint32_t)pvParameters) == 1); // FreeRTOS check
while (1) { while (1) {
//vTaskSuspendAll();
os_runloop_once(); // execute LMIC jobs os_runloop_once(); // execute LMIC jobs
//xTaskResumeAll();
vTaskDelay(2 / portTICK_PERIOD_MS); // yield to CPU vTaskDelay(2 / portTICK_PERIOD_MS); // yield to CPU
} }
} }

View File

@ -11,8 +11,8 @@ static const char TAG[] = "main";
uint16_t salt; uint16_t salt;
uint16_t reset_salt(void) { uint16_t get_salt(void) {
salt = random(65536); // get new 16bit random for salting hashes salt = (uint16_t)random(65536); // get new 16bit random for salting hashes
return salt; return salt;
} }
@ -71,8 +71,8 @@ bool mac_add(uint8_t *paddr, int8_t rssi, bool sniff_type) {
// https://en.wikipedia.org/wiki/MAC_Address_Anonymization // https://en.wikipedia.org/wiki/MAC_Address_Anonymization
snprintf(buff, sizeof(buff), "%08X", snprintf(buff, sizeof(buff), "%08X",
addr2int + (uint32_t)salt); // convert usigned 32-bit salted MAC to addr2int + (uint32_t)salt); // convert usigned 32-bit salted MAC
// 8 digit hex string // to 8 digit hex string
hashedmac = rokkit(&buff[3], 5); // hash MAC last string value, use 5 chars hashedmac = rokkit(&buff[3], 5); // hash MAC last string value, use 5 chars
// to fit hash in uint16_t container // to fit hash in uint16_t container
auto newmac = macs.insert(hashedmac); // add hashed MAC, if new unique auto newmac = macs.insert(hashedmac); // add hashed MAC, if new unique
@ -81,7 +81,6 @@ bool mac_add(uint8_t *paddr, int8_t rssi, bool sniff_type) {
// Count only if MAC was not yet seen // Count only if MAC was not yet seen
if (added) { if (added) {
// increment counter and one blink led // increment counter and one blink led
if (sniff_type == MAC_SNIFF_WIFI) { if (sniff_type == MAC_SNIFF_WIFI) {
macs_wifi++; // increment Wifi MACs counter macs_wifi++; // increment Wifi MACs counter

View File

@ -12,7 +12,7 @@
#define MAC_SNIFF_WIFI 0 #define MAC_SNIFF_WIFI 0
#define MAC_SNIFF_BLE 1 #define MAC_SNIFF_BLE 1
uint16_t reset_salt(void); uint16_t get_salt(void);
uint64_t macConvert(uint8_t *paddr); uint64_t macConvert(uint8_t *paddr);
bool mac_add(uint8_t *paddr, int8_t rssi, bool sniff_type); bool mac_add(uint8_t *paddr, int8_t rssi, bool sniff_type);
void printKey(const char *name, const uint8_t *key, uint8_t len, bool lsb); void printKey(const char *name, const uint8_t *key, uint8_t len, bool lsb);

View File

@ -32,6 +32,7 @@ gpsloop 0 2 read data from GPS over serial or i2c
IDLE 1 0 Arduino loop() -> used for LED switching IDLE 1 0 Arduino loop() -> used for LED switching
loraloop 1 1 runs the LMIC stack loraloop 1 1 runs the LMIC stack
statemachine 1 3 switches application process logic statemachine 1 3 switches application process logic
wifiloop 0 4 rotates wifi channels
ESP32 hardware timers ESP32 hardware timers
========================== ==========================
@ -47,18 +48,20 @@ ESP32 hardware timers
configData_t cfg; // struct holds current device configuration configData_t cfg; // struct holds current device configuration
char display_line6[16], display_line7[16]; // display buffers char display_line6[16], display_line7[16]; // display buffers
uint8_t channel = 0; // channel rotation counter uint8_t volatile channel = 0; // channel rotation counter
uint16_t macs_total = 0, macs_wifi = 0, macs_ble = 0, uint16_t volatile macs_total = 0, macs_wifi = 0, macs_ble = 0,
batt_voltage = 0; // globals for display batt_voltage = 0; // globals for display
// hardware timer for cyclic tasks // hardware timer for cyclic tasks
hw_timer_t *channelSwitch, *displaytimer, *sendCycle, *homeCycle; hw_timer_t *channelSwitch, *displaytimer, *sendCycle, *homeCycle;
// this variables will be changed in the ISR, and read in main loop // this variables will be changed in the ISR, and read in main loop
volatile int ButtonPressedIRQ = 0, ChannelTimerIRQ = 0, SendCycleTimerIRQ = 0, uint8_t volatile ButtonPressedIRQ = 0, ChannelTimerIRQ = 0,
DisplayTimerIRQ = 0, HomeCycleIRQ = 0; SendCycleTimerIRQ = 0, DisplayTimerIRQ = 0, HomeCycleIRQ = 0;
TaskHandle_t StateTask = NULL; TaskHandle_t stateMachineTask, wifiSwitchTask;
SemaphoreHandle_t xWifiChannelSwitchSemaphore;
// RTos send queues for payload transmit // RTos send queues for payload transmit
#ifdef HAS_LORA #ifdef HAS_LORA
@ -96,7 +99,7 @@ void setup() {
// disable brownout detection // disable brownout detection
#ifdef DISABLE_BROWNOUT #ifdef DISABLE_BROWNOUT
// register with brownout is at address DR_REG_RTCCNTL_BASE + 0xd4 // register with brownout is at address DR_REG_RTCCNTL_BASE + 0xd4
(*((volatile uint32_t *)ETS_UNCACHED_ADDR((DR_REG_RTCCNTL_BASE + 0xd4)))) = 0; (*((uint32_t volatile *)ETS_UNCACHED_ADDR((DR_REG_RTCCNTL_BASE + 0xd4)))) = 0;
#endif #endif
// setup debug output or silence device // setup debug output or silence device
@ -143,12 +146,15 @@ void setup() {
batt_voltage = read_voltage(); batt_voltage = read_voltage();
#endif #endif
#ifdef USE_OTA
strcat_P(features, " OTA");
// reboot to firmware update mode if ota trigger switch is set // reboot to firmware update mode if ota trigger switch is set
if (cfg.runmode == 1) { if (cfg.runmode == 1) {
cfg.runmode = 0; cfg.runmode = 0;
saveConfig(); saveConfig();
start_ota_update(); start_ota_update();
} }
#endif
// initialize button // initialize button
#ifdef HAS_BUTTON #ifdef HAS_BUTTON
@ -242,11 +248,6 @@ void setup() {
timerAlarmEnable(displaytimer); timerAlarmEnable(displaytimer);
#endif #endif
// setup channel rotation trigger IRQ using esp32 hardware timer 1
channelSwitch = timerBegin(1, 800, true);
timerAttachInterrupt(channelSwitch, &ChannelSwitchIRQ, true);
timerAlarmWrite(channelSwitch, cfg.wifichancycle * 1000, true);
// setup send cycle trigger IRQ using esp32 hardware timer 2 // setup send cycle trigger IRQ using esp32 hardware timer 2
sendCycle = timerBegin(2, 8000, true); sendCycle = timerBegin(2, 8000, true);
timerAttachInterrupt(sendCycle, &SendCycleIRQ, true); timerAttachInterrupt(sendCycle, &SendCycleIRQ, true);
@ -257,6 +258,12 @@ void setup() {
timerAttachInterrupt(homeCycle, &homeCycleIRQ, true); timerAttachInterrupt(homeCycle, &homeCycleIRQ, true);
timerAlarmWrite(homeCycle, HOMECYCLE * 10000, true); timerAlarmWrite(homeCycle, HOMECYCLE * 10000, true);
// setup channel rotation trigger IRQ using esp32 hardware timer 1
xWifiChannelSwitchSemaphore = xSemaphoreCreateBinary();
channelSwitch = timerBegin(1, 800, true);
timerAttachInterrupt(channelSwitch, &ChannelSwitchIRQ, true);
timerAlarmWrite(channelSwitch, cfg.wifichancycle * 1000, true);
// enable timers // enable timers
// caution, see: https://github.com/espressif/arduino-esp32/issues/1313 // caution, see: https://github.com/espressif/arduino-esp32/issues/1313
yield(); yield();
@ -301,8 +308,13 @@ void setup() {
// https://techtutorialsx.com/2017/05/09/esp32-get-task-execution-core/ // https://techtutorialsx.com/2017/05/09/esp32-get-task-execution-core/
ESP_LOGI(TAG, "Starting Lora..."); ESP_LOGI(TAG, "Starting Lora...");
xTaskCreatePinnedToCore(lorawan_loop, "loraloop", 2048, (void *)1, 1, xTaskCreatePinnedToCore(lorawan_loop, /* task function */
&LoraTask, 1); "loraloop", /* name of task */
2560, /* stack size of task */
(void *)1, /* parameter of the task */
1, /* priority of the task */
&LoraTask, /* task handle*/
1); /* CPU core */
#endif #endif
// if device has GPS and it is enabled, start GPS reader task on core 0 with // if device has GPS and it is enabled, start GPS reader task on core 0 with
@ -310,7 +322,13 @@ void setup() {
// streaming NMEA data // streaming NMEA data
#ifdef HAS_GPS #ifdef HAS_GPS
ESP_LOGI(TAG, "Starting GPS..."); ESP_LOGI(TAG, "Starting GPS...");
xTaskCreatePinnedToCore(gps_loop, "gpsloop", 2048, (void *)1, 2, &GpsTask, 0); xTaskCreatePinnedToCore(gps_loop, /* task function */
"gpsloop", /* name of task */
1024, /* stack size of task */
(void *)1, /* parameter of the task */
2, /* priority of the task */
&GpsTask, /* task handle*/
0); /* CPU core */
#endif #endif
// start BLE scan callback if BLE function is enabled in NVRAM configuration // start BLE scan callback if BLE function is enabled in NVRAM configuration
@ -323,18 +341,30 @@ void setup() {
// start wifi in monitor mode and start channel rotation task on core 0 // start wifi in monitor mode and start channel rotation task on core 0
ESP_LOGI(TAG, "Starting Wifi..."); ESP_LOGI(TAG, "Starting Wifi...");
// esp_event_loop_init(NULL, NULL);
// ESP_ERROR_CHECK(esp_event_loop_init(event_handler, NULL));
wifi_sniffer_init(); wifi_sniffer_init();
// initialize salt value using esp_random() called by random() in // initialize salt value using esp_random() called by random() in
// arduino-esp32 core. Note: do this *after* wifi has started, since // arduino-esp32 core. Note: do this *after* wifi has started, since
// function gets it's seed from RF noise // function gets it's seed from RF noise
reset_salt(); // get new 16bit for salting hashes get_salt(); // get new 16bit for salting hashes
// start wifi channel rotation task
xTaskCreatePinnedToCore(switchWifiChannel, /* task function */
"wifiloop", /* name of task */
1024, /* stack size of task */
NULL, /* parameter of the task */
4, /* priority of the task */
&wifiSwitchTask, /* task handle*/
0); /* CPU core */
// start state machine // start state machine
ESP_LOGI(TAG, "Starting Statemachine..."); ESP_LOGI(TAG, "Starting Statemachine...");
xTaskCreatePinnedToCore(stateMachine, "stateloop", 2048, (void *)1, 3, xTaskCreatePinnedToCore(stateMachine, /* task function */
&StateTask, 1); "stateloop", /* name of task */
2048, /* stack size of task */
(void *)1, /* parameter of the task */
3, /* priority of the task */
&stateMachineTask, /* task handle */
1); /* CPU core */
} // setup() } // setup()

View File

@ -1,3 +1,5 @@
#ifdef USE_OTA
/* /*
Parts of this code: Parts of this code:
Copyright (c) 2014-present PlatformIO <contact@platformio.org> Copyright (c) 2014-present PlatformIO <contact@platformio.org>
@ -17,7 +19,6 @@
#include "ota.h" #include "ota.h"
#include <string>
using namespace std; using namespace std;
const BintrayClient bintray(BINTRAY_USER, BINTRAY_REPO, BINTRAY_PACKAGE); const BintrayClient bintray(BINTRAY_USER, BINTRAY_REPO, BINTRAY_PACKAGE);
@ -29,33 +30,27 @@ const int port = 443;
const uint32_t RESPONSE_TIMEOUT_MS = 5000; const uint32_t RESPONSE_TIMEOUT_MS = 5000;
// Variables to validate firmware content // Variables to validate firmware content
volatile int contentLength = 0; int volatile contentLength = 0;
volatile bool isValidContentType = false; bool volatile isValidContentType = false;
// Local logging tag // Local logging tag
static const char TAG[] = "main"; static const char TAG[] = "main";
void display(const uint8_t row, std::string status, std::string msg) { // helper function to extract header value from header
#ifdef HAS_DISPLAY inline String getHeaderValue(String header, String headerName) {
u8x8.setCursor(14, row); return header.substring(strlen(headerName.c_str()));
u8x8.print((status.substr(0, 2)).c_str());
if (!msg.empty()) {
u8x8.clearLine(7);
u8x8.setCursor(0, 7);
u8x8.print(msg.substr(0, 16).c_str());
}
#endif
}
// callback function to show download progress while streaming data
void show_progress(size_t current, size_t size) {
char buf[17];
snprintf(buf, 17, "%-9lu (%3lu%%)", current, current*100 / size);
display(4, "**", buf);
} }
void start_ota_update() { void start_ota_update() {
// check battery status if we can before doing ota
#ifdef HAS_BATTERY_PROBE
if (batt_voltage < OTA_MIN_BATT) {
ESP_LOGW(TAG, "Battery voltage %dmV too low for OTA", batt_voltage);
return;
}
#endif
// turn on LED // turn on LED
#if (HAS_LED != NOT_A_PIN) #if (HAS_LED != NOT_A_PIN)
#ifdef LED_ACTIVE_LOW #ifdef LED_ACTIVE_LOW
@ -99,7 +94,7 @@ void start_ota_update() {
if (i >= 0) { if (i >= 0) {
ESP_LOGI(TAG, "Connected to %s", WIFI_SSID); ESP_LOGI(TAG, "Connected to %s", WIFI_SSID);
display(1, "OK", "WiFi connected"); display(1, "OK", "WiFi connected");
checkFirmwareUpdates(); // gets and flashes new firmware do_ota_update(); // gets and flashes new firmware
} else { } else {
ESP_LOGI(TAG, "Could not connect to %s, rebooting.", WIFI_SSID); ESP_LOGI(TAG, "Could not connect to %s, rebooting.", WIFI_SSID);
display(1, " E", "no WiFi connect"); display(1, " E", "no WiFi connect");
@ -121,7 +116,9 @@ void start_ota_update() {
} // start_ota_update } // start_ota_update
void checkFirmwareUpdates() { void do_ota_update() {
char buf[17];
// Fetch the latest firmware version // Fetch the latest firmware version
ESP_LOGI(TAG, "Checking latest firmware version on server..."); ESP_LOGI(TAG, "Checking latest firmware version on server...");
display(2, "**", "checking version"); display(2, "**", "checking version");
@ -140,24 +137,10 @@ void checkFirmwareUpdates() {
} }
ESP_LOGI(TAG, "New firmware version v%s available. Downloading...", ESP_LOGI(TAG, "New firmware version v%s available. Downloading...",
latest.c_str()); latest.c_str());
display(2, "OK", ""); display(2, "OK", latest.c_str());
processOTAUpdate(latest); display(3, "**", "");
} String firmwarePath = bintray.getBinaryPath(latest);
// helper function to extract header value from header
inline String getHeaderValue(String header, String headerName) {
return header.substring(strlen(headerName.c_str()));
}
/**
* OTA update processing
*/
void processOTAUpdate(const String &version) {
char buf[17];
display(3, "**", "requesting file");
String firmwarePath = bintray.getBinaryPath(version);
if (!firmwarePath.endsWith(".bin")) { if (!firmwarePath.endsWith(".bin")) {
ESP_LOGI(TAG, "Unsupported binary format, OTA update cancelled."); ESP_LOGI(TAG, "Unsupported binary format, OTA update cancelled.");
display(3, " E", "file type error"); display(3, " E", "file type error");
@ -268,10 +251,10 @@ void processOTAUpdate(const String &version) {
size_t written, current, size; size_t written, current, size;
if (Update.begin(contentLength)) { if (Update.begin(contentLength)) {
#ifdef HAS_DISPLAY
// register callback function for showing progress while streaming data // register callback function for showing progress while streaming data
Update.onProgress(&show_progress); Update.onProgress(&show_progress);
#endif
int i = FLASH_MAX_TRY; int i = FLASH_MAX_TRY;
while ((i--) && (written != contentLength)) { while ((i--) && (written != contentLength)) {
@ -327,6 +310,25 @@ void processOTAUpdate(const String &version) {
ESP_LOGI(TAG, ESP_LOGI(TAG,
"OTA update failed. Rebooting to runmode with current version."); "OTA update failed. Rebooting to runmode with current version.");
client.stop(); client.stop();
} // do_ota_update
void display(const uint8_t row, const std::string status, const std::string msg) {
#ifdef HAS_DISPLAY
u8x8.setCursor(14, row);
u8x8.print((status.substr(0, 2)).c_str());
if (!msg.empty()) {
u8x8.clearLine(7);
u8x8.setCursor(0, 7);
u8x8.print(msg.substr(0, 16).c_str());
}
}
// callback function to show download progress while streaming data
void show_progress(size_t current, size_t size) {
char buf[17];
snprintf(buf, 17, "%-9lu (%3lu%%)", current, current * 100 / size);
display(4, "**", buf);
#endif
} }
// helper function to compare two versions. Returns 1 if v2 is // helper function to compare two versions. Returns 1 if v2 is
@ -363,3 +365,4 @@ int version_compare(const String v1, const String v2) {
} }
return 0; return 0;
} }
#endif // USE_OTA

View File

@ -1,18 +1,21 @@
#ifndef OTA_H #ifndef OTA_H
#define OTA_H #define OTA_H
#ifdef USE_OTA
#include "globals.h" #include "globals.h"
#include "update.h" #include "update.h"
#include <WiFi.h> #include <WiFi.h>
#include <WiFiClientSecure.h> #include <WiFiClientSecure.h>
//#include <Update.h>
#include <BintrayClient.h> #include <BintrayClient.h>
#include <string> #include <string>
void checkFirmwareUpdates(); void do_ota_update();
void processOTAUpdate(const String &version);
void start_ota_update(); void start_ota_update();
int version_compare(const String v1, const String v2); int version_compare(const String v1, const String v2);
void show_progress(size_t current, size_t size); void show_progress(size_t current, size_t size);
void display(const uint8_t row, const std::string status, const std::string msg);
#endif // USE_OTA
#endif // OTA_H #endif // OTA_H

View File

@ -66,8 +66,10 @@
#define HOMECYCLE 30 // house keeping cycle in seconds [default = 30 secs] #define HOMECYCLE 30 // house keeping cycle in seconds [default = 30 secs]
// OTA settings // OTA settings
#define USE_OTA 1 // Comment out to disable OTA update
#define WIFI_MAX_TRY 20 // maximum number of wifi connect attempts for OTA update [default = 20] #define WIFI_MAX_TRY 20 // maximum number of wifi connect attempts for OTA update [default = 20]
#define FLASH_MAX_TRY 3 // maximum number of attempts for writing update binary to flash [default = 3] #define FLASH_MAX_TRY 3 // maximum number of attempts for writing update binary to flash [default = 3]
#define OTA_MIN_BATT 3700 // minimum battery level vor OTA [millivolt]
// LMIC settings // LMIC settings
// define hardware independent LMIC settings here, settings of standard library in /lmic/config.h will be ignored // define hardware independent LMIC settings here, settings of standard library in /lmic/config.h will be ignored

View File

@ -18,7 +18,7 @@ void set_reset(uint8_t val[]) {
case 1: // reset MAC counter case 1: // reset MAC counter
ESP_LOGI(TAG, "Remote command: reset MAC counter"); ESP_LOGI(TAG, "Remote command: reset MAC counter");
reset_counters(); // clear macs reset_counters(); // clear macs
reset_salt(); // get new salt get_salt(); // get new salt
sprintf(display_line6, "Reset counter"); sprintf(display_line6, "Reset counter");
break; break;
case 2: // reset device to factory settings case 2: // reset device to factory settings
@ -33,9 +33,14 @@ void set_reset(uint8_t val[]) {
break; break;
case 9: // reset and ask for software update via Wifi OTA case 9: // reset and ask for software update via Wifi OTA
ESP_LOGI(TAG, "Remote command: software update via Wifi"); ESP_LOGI(TAG, "Remote command: software update via Wifi");
#ifdef USE_OTA
sprintf(display_line6, "Software update"); sprintf(display_line6, "Software update");
cfg.runmode = 1; cfg.runmode = 1;
#else
sprintf(display_line6, "Software update not implemented");
#endif // USE_OTA
break; break;
default: default:
ESP_LOGW(TAG, "Remote command: reset called with invalid parameter(s)"); ESP_LOGW(TAG, "Remote command: reset called with invalid parameter(s)");
} }

View File

@ -29,7 +29,7 @@ void SendData(uint8_t port) {
// clear counter if not in cumulative counter mode // clear counter if not in cumulative counter mode
if ((port == COUNTERPORT) && (cfg.countermode != 1)) { if ((port == COUNTERPORT) && (cfg.countermode != 1)) {
reset_counters(); // clear macs container and reset all counters reset_counters(); // clear macs container and reset all counters
reset_salt(); // get new salt for salting hashes get_salt(); // get new salt for salting hashes
ESP_LOGI(TAG, "Counter cleared"); ESP_LOGI(TAG, "Counter cleared");
} }
} // SendData } // SendData

View File

@ -10,16 +10,15 @@ void stateMachine(void *pvParameters) {
while (1) { while (1) {
#ifdef HAS_BUTTON #ifdef HAS_BUTTON
if (ButtonPressedIRQ)
readButton(); readButton();
#endif #endif
#ifdef HAS_DISPLAY #ifdef HAS_DISPLAY
updateDisplay(); if (DisplayTimerIRQ)
refreshtheDisplay();
#endif #endif
// check wifi scan cycle and if due rotate channel
if (ChannelTimerIRQ)
switchWifiChannel(channel);
// check housekeeping cycle and if due do the work // check housekeeping cycle and if due do the work
if (HomeCycleIRQ) if (HomeCycleIRQ)
doHousekeeping(); doHousekeeping();

View File

@ -8,5 +8,6 @@
#include "cyclic.h" #include "cyclic.h"
void stateMachine(void *pvParameters); void stateMachine(void *pvParameters);
void stateMachineInit();
#endif #endif

View File

@ -30,6 +30,10 @@ void wifi_sniffer_init(void) {
cfg.nvs_enable = 0; // we don't need any wifi settings from NVRAM cfg.nvs_enable = 0; // we don't need any wifi settings from NVRAM
wifi_promiscuous_filter_t filter = { wifi_promiscuous_filter_t filter = {
.filter_mask = WIFI_PROMIS_FILTER_MASK_MGMT}; // we need only MGMT frames .filter_mask = WIFI_PROMIS_FILTER_MASK_MGMT}; // we need only MGMT frames
// esp_event_loop_init(NULL, NULL);
// ESP_ERROR_CHECK(esp_event_loop_init(event_handler, NULL));
ESP_ERROR_CHECK(esp_wifi_init(&cfg)); // configure Wifi with cfg ESP_ERROR_CHECK(esp_wifi_init(&cfg)); // configure Wifi with cfg
ESP_ERROR_CHECK( ESP_ERROR_CHECK(
esp_wifi_set_country(&wifi_country)); // set locales for RF and channels esp_wifi_set_country(&wifi_country)); // set locales for RF and channels
@ -43,20 +47,22 @@ void wifi_sniffer_init(void) {
ESP_ERROR_CHECK(esp_wifi_set_promiscuous(true)); // now switch on monitor mode ESP_ERROR_CHECK(esp_wifi_set_promiscuous(true)); // now switch on monitor mode
} }
// Wifi channel rotation // IRQ Handler
void switchWifiChannel(uint8_t &ch) { void ChannelSwitchIRQ() {
portENTER_CRITICAL(&timerMux); BaseType_t xHigherPriorityTaskWoken = pdFALSE;
ChannelTimerIRQ = 0; // unblock wifi channel rotation task
portEXIT_CRITICAL(&timerMux); xSemaphoreGiveFromISR(xWifiChannelSwitchSemaphore, &xHigherPriorityTaskWoken);
// rotates variable channel 1..WIFI_CHANNEL_MAX
ch = (ch % WIFI_CHANNEL_MAX) + 1;
esp_wifi_set_channel(ch, WIFI_SECOND_CHAN_NONE);
ESP_LOGD(TAG, "Wifi set channel %d", &ch);
} }
// IRQ handler // Wifi channel rotation task
void IRAM_ATTR ChannelSwitchIRQ() { void switchWifiChannel(void * parameter) {
portENTER_CRITICAL(&timerMux); while (1) {
ChannelTimerIRQ++; // task is remaining in block state waiting for channel switch timer interrupt event
portEXIT_CRITICAL(&timerMux); xSemaphoreTake(xWifiChannelSwitchSemaphore, portMAX_DELAY);
// rotates variable channel 1..WIFI_CHANNEL_MAX
channel = (channel % WIFI_CHANNEL_MAX) + 1;
esp_wifi_set_channel(channel, WIFI_SECOND_CHAN_NONE);
ESP_LOGD(TAG, "Wifi set channel %d", channel);
}
vTaskDelete(NULL);
} }

View File

@ -28,6 +28,6 @@ typedef struct {
void wifi_sniffer_init(void); void wifi_sniffer_init(void);
void wifi_sniffer_packet_handler(void *buff, wifi_promiscuous_pkt_type_t type); void wifi_sniffer_packet_handler(void *buff, wifi_promiscuous_pkt_type_t type);
void ChannelSwitchIRQ(void); void ChannelSwitchIRQ(void);
void switchWifiChannel(uint8_t &ch); void switchWifiChannel(void * parameter);
#endif #endif