commit
215149d479
@ -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.2
|
release_version = 1.5.3
|
||||||
; 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
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
// Basic config
|
// Basic config
|
||||||
#include "globals.h"
|
#include "globals.h"
|
||||||
#include "senddata.h"
|
#include "senddata.h"
|
||||||
#include "OTA.h"
|
#include "ota.h"
|
||||||
|
|
||||||
// Local logging tag
|
// Local logging tag
|
||||||
static const char TAG[] = "main";
|
static const char TAG[] = "main";
|
||||||
|
236
src/main.cpp
236
src/main.cpp
@ -21,6 +21,25 @@ NOTICE:
|
|||||||
Parts of the source files in this repository are made available under different
|
Parts of the source files in this repository are made available under different
|
||||||
licenses. Refer to LICENSE.txt file in repository for more details.
|
licenses. Refer to LICENSE.txt file in repository for more details.
|
||||||
|
|
||||||
|
//////////////////////// ESP32-Paxcounter \\\\\\\\\\\\\\\\\\\\\\\\\\
|
||||||
|
|
||||||
|
Uused tasks and timers:
|
||||||
|
|
||||||
|
Task Core Prio Purpose
|
||||||
|
====================================================================
|
||||||
|
IDLE 0 0 ESP32 arduino scheduler
|
||||||
|
gpsloop 0 2 read data from GPS over serial or i2c
|
||||||
|
IDLE 1 0 Arduino loop() -> used for LED switching
|
||||||
|
loraloop 1 1 runs the LMIC stack
|
||||||
|
statemachine 1 3 switches application process logic
|
||||||
|
|
||||||
|
ESP32 hardware timers
|
||||||
|
==========================
|
||||||
|
0 Display-Refresh
|
||||||
|
1 Wifi Channel Switch
|
||||||
|
2 Send Cycle
|
||||||
|
3 Housekeeping
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// Basic Config
|
// Basic Config
|
||||||
@ -90,39 +109,66 @@ void setup() {
|
|||||||
esp_log_set_vprintf(redirect_log);
|
esp_log_set_vprintf(redirect_log);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
ESP_LOGI(TAG, "Starting %s v%s", PRODUCTNAME, PROGVERSION);
|
// read (and initialize on first run) runtime settings from NVRAM
|
||||||
|
|
||||||
// initialize system event handler for wifi task, needed for
|
|
||||||
// wifi_sniffer_init()
|
|
||||||
// esp_event_loop_init(NULL, NULL);
|
|
||||||
// ESP_ERROR_CHECK(esp_event_loop_init(event_handler, NULL));
|
|
||||||
|
|
||||||
// print chip information on startup if in verbose mode
|
|
||||||
#ifdef VERBOSE
|
|
||||||
esp_chip_info_t chip_info;
|
|
||||||
esp_chip_info(&chip_info);
|
|
||||||
ESP_LOGI(TAG,
|
|
||||||
"This is ESP32 chip with %d CPU cores, WiFi%s%s, silicon revision "
|
|
||||||
"%d, %dMB %s Flash",
|
|
||||||
chip_info.cores, (chip_info.features & CHIP_FEATURE_BT) ? "/BT" : "",
|
|
||||||
(chip_info.features & CHIP_FEATURE_BLE) ? "/BLE" : "",
|
|
||||||
chip_info.revision, spi_flash_get_chip_size() / (1024 * 1024),
|
|
||||||
(chip_info.features & CHIP_FEATURE_EMB_FLASH) ? "embedded"
|
|
||||||
: "external");
|
|
||||||
ESP_LOGI(TAG, "ESP32 SDK: %s", ESP.getSdkVersion());
|
|
||||||
ESP_LOGI(TAG, "Free RAM: %d bytes", ESP.getFreeHeap());
|
|
||||||
|
|
||||||
#ifdef HAS_GPS
|
|
||||||
ESP_LOGI(TAG, "TinyGPS+ v%s", TinyGPSPlus::libraryVersion());
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif // verbose
|
|
||||||
|
|
||||||
// read settings from NVRAM
|
|
||||||
loadConfig(); // includes initialize if necessary
|
loadConfig(); // includes initialize if necessary
|
||||||
|
|
||||||
#ifdef VENDORFILTER
|
// initialize leds
|
||||||
strcat_P(features, " OUIFLT");
|
#if (HAS_LED != NOT_A_PIN)
|
||||||
|
pinMode(HAS_LED, OUTPUT);
|
||||||
|
strcat_P(features, " LED");
|
||||||
|
#endif
|
||||||
|
#ifdef HAS_RGB_LED
|
||||||
|
rgb_set_color(COLOR_PINK);
|
||||||
|
strcat_P(features, " RGB");
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// initialize wifi antenna
|
||||||
|
#ifdef HAS_ANTENNA_SWITCH
|
||||||
|
strcat_P(features, " ANT");
|
||||||
|
antenna_init();
|
||||||
|
antenna_select(cfg.wifiant);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// switch off bluetooth, if not compiled
|
||||||
|
#ifdef BLECOUNTER
|
||||||
|
strcat_P(features, " BLE");
|
||||||
|
#else
|
||||||
|
bool btstop = btStop();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// initialize battery status
|
||||||
|
#ifdef HAS_BATTERY_PROBE
|
||||||
|
strcat_P(features, " BATT");
|
||||||
|
calibrate_voltage();
|
||||||
|
batt_voltage = read_voltage();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// reboot to firmware update mode if ota trigger switch is set
|
||||||
|
if (cfg.runmode == 1) {
|
||||||
|
cfg.runmode = 0;
|
||||||
|
saveConfig();
|
||||||
|
start_ota_update();
|
||||||
|
}
|
||||||
|
|
||||||
|
// initialize button
|
||||||
|
#ifdef HAS_BUTTON
|
||||||
|
strcat_P(features, " BTN_");
|
||||||
|
#ifdef BUTTON_PULLUP
|
||||||
|
strcat_P(features, "PU");
|
||||||
|
// install button interrupt (pullup mode)
|
||||||
|
pinMode(HAS_BUTTON, INPUT_PULLUP);
|
||||||
|
attachInterrupt(digitalPinToInterrupt(HAS_BUTTON), ButtonIRQ, RISING);
|
||||||
|
#else
|
||||||
|
strcat_P(features, "PD");
|
||||||
|
// install button interrupt (pulldown mode)
|
||||||
|
pinMode(HAS_BUTTON, INPUT_PULLDOWN);
|
||||||
|
attachInterrupt(digitalPinToInterrupt(HAS_BUTTON), ButtonIRQ, FALLING);
|
||||||
|
#endif // BUTTON_PULLUP
|
||||||
|
#endif // HAS_BUTTON
|
||||||
|
|
||||||
|
// initialize gps
|
||||||
|
#ifdef HAS_GPS
|
||||||
|
strcat_P(features, " GPS");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// initialize LoRa
|
// initialize LoRa
|
||||||
@ -149,58 +195,32 @@ void setup() {
|
|||||||
SEND_QUEUE_SIZE * PAYLOAD_BUFFER_SIZE);
|
SEND_QUEUE_SIZE * PAYLOAD_BUFFER_SIZE);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// initialize led
|
#ifdef VENDORFILTER
|
||||||
#if (HAS_LED != NOT_A_PIN)
|
strcat_P(features, " OUIFLT");
|
||||||
pinMode(HAS_LED, OUTPUT);
|
|
||||||
strcat_P(features, " LED");
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef HAS_RGB_LED
|
ESP_LOGI(TAG, "Starting %s v%s", PRODUCTNAME, PROGVERSION);
|
||||||
rgb_set_color(COLOR_PINK);
|
|
||||||
strcat_P(features, " RGB");
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// initialize button
|
// print chip information on startup if in verbose mode
|
||||||
#ifdef HAS_BUTTON
|
#ifdef VERBOSE
|
||||||
strcat_P(features, " BTN_");
|
esp_chip_info_t chip_info;
|
||||||
#ifdef BUTTON_PULLUP
|
esp_chip_info(&chip_info);
|
||||||
strcat_P(features, "PU");
|
ESP_LOGI(TAG,
|
||||||
// install button interrupt (pullup mode)
|
"This is ESP32 chip with %d CPU cores, WiFi%s%s, silicon revision "
|
||||||
pinMode(HAS_BUTTON, INPUT_PULLUP);
|
"%d, %dMB %s Flash",
|
||||||
attachInterrupt(digitalPinToInterrupt(HAS_BUTTON), ButtonIRQ, RISING);
|
chip_info.cores, (chip_info.features & CHIP_FEATURE_BT) ? "/BT" : "",
|
||||||
#else
|
(chip_info.features & CHIP_FEATURE_BLE) ? "/BLE" : "",
|
||||||
strcat_P(features, "PD");
|
chip_info.revision, spi_flash_get_chip_size() / (1024 * 1024),
|
||||||
// install button interrupt (pulldown mode)
|
(chip_info.features & CHIP_FEATURE_EMB_FLASH) ? "embedded"
|
||||||
pinMode(HAS_BUTTON, INPUT_PULLDOWN);
|
: "external");
|
||||||
attachInterrupt(digitalPinToInterrupt(HAS_BUTTON), ButtonIRQ, FALLING);
|
ESP_LOGI(TAG, "ESP32 SDK: %s", ESP.getSdkVersion());
|
||||||
#endif // BUTTON_PULLUP
|
ESP_LOGI(TAG, "Free RAM: %d bytes", ESP.getFreeHeap());
|
||||||
#endif // HAS_BUTTON
|
|
||||||
|
|
||||||
// initialize wifi antenna
|
|
||||||
#ifdef HAS_ANTENNA_SWITCH
|
|
||||||
strcat_P(features, " ANT");
|
|
||||||
antenna_init();
|
|
||||||
antenna_select(cfg.wifiant);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// switch off bluetooth on esp32 module, if not compiled
|
|
||||||
#ifdef BLECOUNTER
|
|
||||||
strcat_P(features, " BLE");
|
|
||||||
#else
|
|
||||||
bool btstop = btStop();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// initialize gps
|
|
||||||
#ifdef HAS_GPS
|
#ifdef HAS_GPS
|
||||||
strcat_P(features, " GPS");
|
ESP_LOGI(TAG, "TinyGPS+ v%s", TinyGPSPlus::libraryVersion());
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// initialize battery status
|
#endif // verbose
|
||||||
#ifdef HAS_BATTERY_PROBE
|
|
||||||
strcat_P(features, " BATT");
|
|
||||||
calibrate_voltage();
|
|
||||||
batt_voltage = read_voltage();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// initialize display
|
// initialize display
|
||||||
#ifdef HAS_DISPLAY
|
#ifdef HAS_DISPLAY
|
||||||
@ -208,16 +228,6 @@ void setup() {
|
|||||||
DisplayState = cfg.screenon;
|
DisplayState = cfg.screenon;
|
||||||
init_display(PRODUCTNAME, PROGVERSION);
|
init_display(PRODUCTNAME, PROGVERSION);
|
||||||
|
|
||||||
/*
|
|
||||||
Usage of ESP32 hardware timers
|
|
||||||
==============================
|
|
||||||
|
|
||||||
0 Display-Refresh
|
|
||||||
1 Wifi Channel Switch
|
|
||||||
2 Send Cycle
|
|
||||||
3 Housekeeping
|
|
||||||
*/
|
|
||||||
|
|
||||||
// setup display refresh trigger IRQ using esp32 hardware timer
|
// setup display refresh trigger IRQ using esp32 hardware timer
|
||||||
// https://techtutorialsx.com/2017/10/07/esp32-arduino-timer-interrupts/
|
// https://techtutorialsx.com/2017/10/07/esp32-arduino-timer-interrupts/
|
||||||
|
|
||||||
@ -232,13 +242,6 @@ void setup() {
|
|||||||
timerAlarmEnable(displaytimer);
|
timerAlarmEnable(displaytimer);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// reboot to firmware update mode if ota trigger switch is set
|
|
||||||
if (cfg.runmode == 1) {
|
|
||||||
cfg.runmode = 0;
|
|
||||||
saveConfig();
|
|
||||||
start_ota_update();
|
|
||||||
}
|
|
||||||
|
|
||||||
// setup channel rotation trigger IRQ using esp32 hardware timer 1
|
// setup channel rotation trigger IRQ using esp32 hardware timer 1
|
||||||
channelSwitch = timerBegin(1, 800, true);
|
channelSwitch = timerBegin(1, 800, true);
|
||||||
timerAttachInterrupt(channelSwitch, &ChannelSwitchIRQ, true);
|
timerAttachInterrupt(channelSwitch, &ChannelSwitchIRQ, true);
|
||||||
@ -293,18 +296,6 @@ void setup() {
|
|||||||
// join network
|
// join network
|
||||||
LMIC_startJoining();
|
LMIC_startJoining();
|
||||||
|
|
||||||
/*
|
|
||||||
|
|
||||||
Task Core Prio Purpose
|
|
||||||
====================================================================
|
|
||||||
IDLE 0 0 ESP32 arduino scheduler
|
|
||||||
gpsloop 0 2 read data from GPS over serial or i2c
|
|
||||||
IDLE 1 0 Arduino loop() -> used for LED switching
|
|
||||||
loraloop 1 1 runs the LMIC stack
|
|
||||||
statemachine 1 3 switches application process logic
|
|
||||||
|
|
||||||
*/
|
|
||||||
|
|
||||||
// start lmic runloop in rtos task on core 1
|
// start lmic runloop in rtos task on core 1
|
||||||
// (note: arduino main loop runs on core 1, too)
|
// (note: arduino main loop runs on core 1, too)
|
||||||
// https://techtutorialsx.com/2017/05/09/esp32-get-task-execution-core/
|
// https://techtutorialsx.com/2017/05/09/esp32-get-task-execution-core/
|
||||||
@ -332,6 +323,8 @@ 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
|
||||||
@ -345,40 +338,9 @@ void setup() {
|
|||||||
|
|
||||||
} // setup()
|
} // setup()
|
||||||
|
|
||||||
void stateMachine(void *pvParameters) {
|
|
||||||
|
|
||||||
configASSERT(((uint32_t)pvParameters) == 1); // FreeRTOS check
|
|
||||||
|
|
||||||
while (1) {
|
|
||||||
|
|
||||||
#ifdef HAS_BUTTON
|
|
||||||
readButton();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef HAS_DISPLAY
|
|
||||||
updateDisplay();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// check wifi scan cycle and if due rotate channel
|
|
||||||
if (ChannelTimerIRQ)
|
|
||||||
switchWifiChannel(channel);
|
|
||||||
// check housekeeping cycle and if due do the work
|
|
||||||
if (HomeCycleIRQ)
|
|
||||||
doHousekeeping();
|
|
||||||
// check send queue and process it
|
|
||||||
enqueuePayload();
|
|
||||||
// check send cycle and if due enqueue payload to send
|
|
||||||
if (SendCycleTimerIRQ)
|
|
||||||
sendPayload();
|
|
||||||
|
|
||||||
// give yield to CPU
|
|
||||||
vTaskDelay(2 / portTICK_PERIOD_MS);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void loop() {
|
void loop() {
|
||||||
|
|
||||||
// switch LED states if device has a LED
|
// switch LED state if device has LED(s)
|
||||||
#if (HAS_LED != NOT_A_PIN) || defined(HAS_RGB_LED)
|
#if (HAS_LED != NOT_A_PIN) || defined(HAS_RGB_LED)
|
||||||
led_loop();
|
led_loop();
|
||||||
#endif
|
#endif
|
||||||
|
19
src/main.h
19
src/main.h
@ -1,20 +1,17 @@
|
|||||||
#ifndef _MAIN_H
|
#ifndef _MAIN_H
|
||||||
#define _MAIN_H
|
#define _MAIN_H
|
||||||
|
|
||||||
#include "globals.h"
|
|
||||||
#include "led.h"
|
|
||||||
#include "macsniff.h"
|
|
||||||
#include "wifiscan.h"
|
|
||||||
#include "configmanager.h"
|
|
||||||
#include "senddata.h"
|
|
||||||
#include "cyclic.h"
|
|
||||||
#include "beacon_array.h"
|
|
||||||
#include "OTA.h"
|
|
||||||
|
|
||||||
#include <esp_spi_flash.h> // needed for reading ESP32 chip attributes
|
#include <esp_spi_flash.h> // needed for reading ESP32 chip attributes
|
||||||
#include <esp_event_loop.h> // needed for Wifi event handler
|
#include <esp_event_loop.h> // needed for Wifi event handler
|
||||||
#include <esp32-hal-timer.h> // needed for timers
|
#include <esp32-hal-timer.h> // needed for timers
|
||||||
|
|
||||||
void stateMachine(void *pvParameters);
|
#include "globals.h"
|
||||||
|
#include "led.h"
|
||||||
|
#include "wifiscan.h"
|
||||||
|
#include "configmanager.h"
|
||||||
|
#include "cyclic.h"
|
||||||
|
#include "beacon_array.h"
|
||||||
|
#include "ota.h"
|
||||||
|
#include "statemachine.h"
|
||||||
|
|
||||||
#endif
|
#endif
|
121
src/ota.cpp
121
src/ota.cpp
@ -35,15 +35,36 @@ volatile bool isValidContentType = false;
|
|||||||
// Local logging tag
|
// Local logging tag
|
||||||
static const char TAG[] = "main";
|
static const char TAG[] = "main";
|
||||||
|
|
||||||
void display(const uint8_t x, const uint8_t y, char* text) {
|
void display(const uint8_t row, std::string status, std::string msg) {
|
||||||
#ifdef HAS_DISPLAY
|
#ifdef HAS_DISPLAY
|
||||||
u8x8.setCursor(x, y);
|
u8x8.setCursor(14, row);
|
||||||
u8x8.print(text);
|
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
|
#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() {
|
||||||
|
|
||||||
|
// turn on LED
|
||||||
|
#if (HAS_LED != NOT_A_PIN)
|
||||||
|
#ifdef LED_ACTIVE_LOW
|
||||||
|
digitalWrite(HAS_LED, LOW);
|
||||||
|
#else
|
||||||
|
digitalWrite(HAS_LED, HIGH);
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef HAS_DISPLAY
|
#ifdef HAS_DISPLAY
|
||||||
u8x8.begin();
|
u8x8.begin();
|
||||||
u8x8.setFont(u8x8_font_chroma48medium8_r);
|
u8x8.setFont(u8x8_font_chroma48medium8_r);
|
||||||
@ -51,67 +72,80 @@ void start_ota_update() {
|
|||||||
#ifdef DISPLAY_FLIP
|
#ifdef DISPLAY_FLIP
|
||||||
u8x8.setFlipMode(1);
|
u8x8.setFlipMode(1);
|
||||||
#endif
|
#endif
|
||||||
u8x8.draw2x2String(0, 0, "UPDATING");
|
u8x8.setInverseFont(1);
|
||||||
u8x8.setCursor(0, 3);
|
u8x8.print("SOFTWARE UPDATE \n");
|
||||||
u8x8.print("Wifi connect ..\n");
|
u8x8.setInverseFont(0);
|
||||||
u8x8.print("Get Update? ..\n");
|
u8x8.print("WiFi connect ..\n");
|
||||||
|
u8x8.print("Has Update? ..\n");
|
||||||
u8x8.print("Downloading ..\n");
|
u8x8.print("Downloading ..\n");
|
||||||
u8x8.print("Flashing ..\n");
|
u8x8.print("Flashing ..\n");
|
||||||
u8x8.print("Rebooting ..");
|
u8x8.print("Rebooting ..");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
ESP_LOGI(TAG, "Starting Wifi OTA update");
|
ESP_LOGI(TAG, "Starting Wifi OTA update");
|
||||||
display(14, 3, "**");
|
display(1, "**", WIFI_SSID);
|
||||||
|
|
||||||
WiFi.begin(WIFI_SSID, WIFI_PASS);
|
WiFi.begin(WIFI_SSID, WIFI_PASS);
|
||||||
|
|
||||||
int i = WIFI_MAX_TRY;
|
int i = WIFI_MAX_TRY;
|
||||||
|
|
||||||
while (i--) {
|
while (i--) {
|
||||||
ESP_LOGI(TAG, "trying to connect to %s", WIFI_SSID);
|
ESP_LOGI(TAG, "Trying to connect to %s", WIFI_SSID);
|
||||||
if (WiFi.status() == WL_CONNECTED)
|
if (WiFi.status() == WL_CONNECTED)
|
||||||
break;
|
break;
|
||||||
vTaskDelay(5000 / portTICK_PERIOD_MS);
|
vTaskDelay(5000 / portTICK_PERIOD_MS);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (i >= 0) {
|
if (i >= 0) {
|
||||||
ESP_LOGI(TAG, "connected to %s", WIFI_SSID);
|
ESP_LOGI(TAG, "Connected to %s", WIFI_SSID);
|
||||||
display(14, 3, "OK");
|
display(1, "OK", "WiFi connected");
|
||||||
checkFirmwareUpdates(); // gets and flashes new firmware and restarts
|
checkFirmwareUpdates(); // 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(14, 3, " E");
|
display(1, " E", "no WiFi connect");
|
||||||
}
|
}
|
||||||
|
|
||||||
display(14, 7, "**");
|
display(5, "**", ""); // mark line rebooting
|
||||||
delay(5000);
|
|
||||||
ESP.restart(); // reached only if update was not successful or no wifi connect
|
// turn off LED
|
||||||
|
#if (HAS_LED != NOT_A_PIN)
|
||||||
|
#ifdef LED_ACTIVE_LOW
|
||||||
|
digitalWrite(HAS_LED, HIGH);
|
||||||
|
#else
|
||||||
|
digitalWrite(HAS_LED, LOW);
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
vTaskDelay(5000 / portTICK_PERIOD_MS);
|
||||||
|
ESP.restart();
|
||||||
|
|
||||||
} // start_ota_update
|
} // start_ota_update
|
||||||
|
|
||||||
void checkFirmwareUpdates() {
|
void checkFirmwareUpdates() {
|
||||||
// Fetch the latest firmware version
|
// Fetch the latest firmware version
|
||||||
ESP_LOGI(TAG, "OTA mode, checking latest firmware version on server...");
|
ESP_LOGI(TAG, "Checking latest firmware version on server...");
|
||||||
display(14, 4, "**");
|
display(2, "**", "checking version");
|
||||||
const String latest = bintray.getLatestVersion();
|
const String latest = bintray.getLatestVersion();
|
||||||
|
|
||||||
if (latest.length() == 0) {
|
if (latest.length() == 0) {
|
||||||
ESP_LOGI(
|
ESP_LOGI(
|
||||||
TAG,
|
TAG,
|
||||||
"Could not load info about the latest firmware. Rebooting to runmode.");
|
"Could not load info about the latest firmware. Rebooting to runmode.");
|
||||||
display(14, 4, " E");
|
display(2, " E", "file not found");
|
||||||
return;
|
return;
|
||||||
} else if (version_compare(latest, cfg.version) <= 0) {
|
} else if (version_compare(latest, cfg.version) <= 0) {
|
||||||
ESP_LOGI(TAG, "Current firmware is up to date. Rebooting to runmode.");
|
ESP_LOGI(TAG, "Current firmware is up to date. Rebooting to runmode.");
|
||||||
display(14, 4, "NO");
|
display(2, "NO", "no update found");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
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(14, 4, "OK");
|
display(2, "OK", "");
|
||||||
|
|
||||||
processOTAUpdate(latest);
|
processOTAUpdate(latest);
|
||||||
}
|
}
|
||||||
|
|
||||||
// A helper function to extract header value from header
|
// helper function to extract header value from header
|
||||||
inline String getHeaderValue(String header, String headerName) {
|
inline String getHeaderValue(String header, String headerName) {
|
||||||
return header.substring(strlen(headerName.c_str()));
|
return header.substring(strlen(headerName.c_str()));
|
||||||
}
|
}
|
||||||
@ -120,11 +154,13 @@ inline String getHeaderValue(String header, String headerName) {
|
|||||||
* OTA update processing
|
* OTA update processing
|
||||||
*/
|
*/
|
||||||
void processOTAUpdate(const String &version) {
|
void processOTAUpdate(const String &version) {
|
||||||
display(14, 5, "**");
|
|
||||||
|
char buf[17];
|
||||||
|
display(3, "**", "requesting file");
|
||||||
String firmwarePath = bintray.getBinaryPath(version);
|
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(14, 5, " E");
|
display(3, " E", "file type error");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -136,7 +172,7 @@ void processOTAUpdate(const String &version) {
|
|||||||
|
|
||||||
if (!client.connect(currentHost.c_str(), port)) {
|
if (!client.connect(currentHost.c_str(), port)) {
|
||||||
ESP_LOGI(TAG, "Cannot connect to %s", currentHost.c_str());
|
ESP_LOGI(TAG, "Cannot connect to %s", currentHost.c_str());
|
||||||
display(14, 5, " E");
|
display(3, " E", "connection lost");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -148,7 +184,7 @@ void processOTAUpdate(const String &version) {
|
|||||||
if (!client.connect(currentHost.c_str(), port)) {
|
if (!client.connect(currentHost.c_str(), port)) {
|
||||||
ESP_LOGI(TAG, "Redirect detected, but cannot connect to %s",
|
ESP_LOGI(TAG, "Redirect detected, but cannot connect to %s",
|
||||||
currentHost.c_str());
|
currentHost.c_str());
|
||||||
display(14, 5, " E");
|
display(3, " E", "server error");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -164,7 +200,7 @@ void processOTAUpdate(const String &version) {
|
|||||||
while (client.available() == 0) {
|
while (client.available() == 0) {
|
||||||
if (millis() - timeout > RESPONSE_TIMEOUT_MS) {
|
if (millis() - timeout > RESPONSE_TIMEOUT_MS) {
|
||||||
ESP_LOGI(TAG, "Client Timeout.");
|
ESP_LOGI(TAG, "Client Timeout.");
|
||||||
display(14, 5, " E");
|
display(3, " E", "client timeout");
|
||||||
client.stop();
|
client.stop();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -224,35 +260,38 @@ void processOTAUpdate(const String &version) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
display(14, 5, "OK");
|
display(3, "OK", ""); // line download
|
||||||
|
|
||||||
// check whether we have everything for OTA update
|
// check whether we have everything for OTA update
|
||||||
if (contentLength && isValidContentType) {
|
if (contentLength && isValidContentType) {
|
||||||
|
|
||||||
size_t written;
|
size_t written, current, size;
|
||||||
|
|
||||||
if (Update.begin(contentLength)) {
|
if (Update.begin(contentLength)) {
|
||||||
|
|
||||||
|
// register callback function for showing progress while streaming data
|
||||||
|
Update.onProgress(&show_progress);
|
||||||
|
|
||||||
int i = FLASH_MAX_TRY;
|
int i = FLASH_MAX_TRY;
|
||||||
while ((i--) && (written != contentLength)) {
|
while ((i--) && (written != contentLength)) {
|
||||||
|
|
||||||
ESP_LOGI(TAG,
|
ESP_LOGI(TAG,
|
||||||
"Starting OTA update, attempt %d of %d. This will take some "
|
"Starting OTA update, attempt %u of %u. This will take some "
|
||||||
"time to complete...",
|
"time to complete...",
|
||||||
FLASH_MAX_TRY - i, FLASH_MAX_TRY);
|
FLASH_MAX_TRY - i, FLASH_MAX_TRY);
|
||||||
display(14, 6, "**");
|
display(4, "**", "writing...");
|
||||||
|
|
||||||
written = Update.writeStream(client);
|
written = Update.writeStream(client);
|
||||||
|
|
||||||
if (written == contentLength) {
|
if (written == contentLength) {
|
||||||
ESP_LOGI(TAG, "Written %d bytes successfully", written);
|
ESP_LOGI(TAG, "Written %u bytes successfully", written);
|
||||||
display(14, 6, "**");
|
snprintf(buf, 17, "%u kB Done!", (uint16_t)(written / 1024));
|
||||||
|
display(4, "OK", buf);
|
||||||
break;
|
break;
|
||||||
} else {
|
} else {
|
||||||
ESP_LOGI(TAG,
|
ESP_LOGI(TAG,
|
||||||
"Written only %d of %d bytes, OTA update attempt cancelled.",
|
"Written only %u of %u bytes, OTA update attempt cancelled.",
|
||||||
written, contentLength);
|
written, contentLength);
|
||||||
display(14, 6, " E");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -262,33 +301,31 @@ void processOTAUpdate(const String &version) {
|
|||||||
ESP_LOGI(
|
ESP_LOGI(
|
||||||
TAG,
|
TAG,
|
||||||
"OTA update completed. Rebooting to runmode with new version.");
|
"OTA update completed. Rebooting to runmode with new version.");
|
||||||
display(14, 7, "OK");
|
|
||||||
client.stop();
|
client.stop();
|
||||||
return;
|
return;
|
||||||
} else {
|
} else {
|
||||||
ESP_LOGI(TAG, "Something went wrong! OTA update hasn't been finished "
|
ESP_LOGI(TAG, "Something went wrong! OTA update hasn't been finished "
|
||||||
"properly.");
|
"properly.");
|
||||||
display(14, 7, " E");
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
ESP_LOGI(TAG, "An error occurred. Error #: %d", Update.getError());
|
ESP_LOGI(TAG, "An error occurred. Error #: %d", Update.getError());
|
||||||
display(14, 7, " E");
|
snprintf(buf, 17, "Error #: %d", Update.getError());
|
||||||
|
display(4, " E", buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
ESP_LOGI(TAG, "There isn't enough space to start OTA update");
|
ESP_LOGI(TAG, "There isn't enough space to start OTA update");
|
||||||
display(14, 7, " E");
|
display(4, " E", "disk full");
|
||||||
client.flush();
|
client.flush();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
ESP_LOGI(TAG,
|
ESP_LOGI(TAG,
|
||||||
"There was no valid content in the response from the OTA server!");
|
"There was no valid content in the response from the OTA server!");
|
||||||
display(14, 7, " E");
|
display(4, " E", "response error");
|
||||||
client.flush();
|
client.flush();
|
||||||
}
|
}
|
||||||
ESP_LOGI(TAG,
|
ESP_LOGI(TAG,
|
||||||
"OTA update failed. Rebooting to runmode with current version.");
|
"OTA update failed. Rebooting to runmode with current version.");
|
||||||
display(14, 7, " E");
|
|
||||||
client.stop();
|
client.stop();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -13,5 +13,6 @@ void checkFirmwareUpdates();
|
|||||||
void processOTAUpdate(const String &version);
|
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);
|
||||||
|
|
||||||
#endif // OTA_H
|
#endif // OTA_H
|
||||||
|
@ -73,8 +73,8 @@ void IRAM_ATTR SendCycleIRQ() {
|
|||||||
portEXIT_CRITICAL(&timerMux);
|
portEXIT_CRITICAL(&timerMux);
|
||||||
}
|
}
|
||||||
|
|
||||||
// interrupt triggered function to eat data from RTos send queues and transmit it
|
// interrupt triggered function to eat data from send queues and transmit it
|
||||||
void enqueuePayload() {
|
void checkSendQueues() {
|
||||||
MessageBuffer_t SendBuffer;
|
MessageBuffer_t SendBuffer;
|
||||||
|
|
||||||
#ifdef HAS_LORA
|
#ifdef HAS_LORA
|
||||||
@ -98,7 +98,7 @@ void enqueuePayload() {
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
} // enqueuePayload
|
} // checkSendQueues
|
||||||
|
|
||||||
void flushQueues() {
|
void flushQueues() {
|
||||||
#ifdef HAS_LORA
|
#ifdef HAS_LORA
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
void SendData(uint8_t port);
|
void SendData(uint8_t port);
|
||||||
void sendPayload(void);
|
void sendPayload(void);
|
||||||
void SendCycleIRQ(void);
|
void SendCycleIRQ(void);
|
||||||
void enqueuePayload(void);
|
void checkSendQueues(void);
|
||||||
void flushQueues();
|
void flushQueues();
|
||||||
|
|
||||||
#endif // _SENDDATA_H_
|
#endif // _SENDDATA_H_
|
35
src/statemachine.cpp
Normal file
35
src/statemachine.cpp
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
#include "statemachine.h"
|
||||||
|
|
||||||
|
// Local logging tag
|
||||||
|
static const char TAG[] = "main";
|
||||||
|
|
||||||
|
void stateMachine(void *pvParameters) {
|
||||||
|
|
||||||
|
configASSERT(((uint32_t)pvParameters) == 1); // FreeRTOS check
|
||||||
|
|
||||||
|
while (1) {
|
||||||
|
|
||||||
|
#ifdef HAS_BUTTON
|
||||||
|
readButton();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef HAS_DISPLAY
|
||||||
|
updateDisplay();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// check wifi scan cycle and if due rotate channel
|
||||||
|
if (ChannelTimerIRQ)
|
||||||
|
switchWifiChannel(channel);
|
||||||
|
// check housekeeping cycle and if due do the work
|
||||||
|
if (HomeCycleIRQ)
|
||||||
|
doHousekeeping();
|
||||||
|
// check send cycle and if due enqueue payload to send
|
||||||
|
if (SendCycleTimerIRQ)
|
||||||
|
sendPayload();
|
||||||
|
// check send queues and process due payload to send
|
||||||
|
checkSendQueues();
|
||||||
|
|
||||||
|
// give yield to CPU
|
||||||
|
vTaskDelay(2 / portTICK_PERIOD_MS);
|
||||||
|
}
|
||||||
|
}
|
12
src/statemachine.h
Normal file
12
src/statemachine.h
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
#ifndef _STATEMACHINE_H
|
||||||
|
#define _STATEMACHINE_H
|
||||||
|
|
||||||
|
#include "globals.h"
|
||||||
|
#include "led.h"
|
||||||
|
#include "wifiscan.h"
|
||||||
|
#include "senddata.h"
|
||||||
|
#include "cyclic.h"
|
||||||
|
|
||||||
|
void stateMachine(void *pvParameters);
|
||||||
|
|
||||||
|
#endif
|
@ -310,7 +310,7 @@ size_t UpdateClass::write(uint8_t *data, size_t len) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
size_t UpdateClass::writeStream(Stream &data) {
|
size_t UpdateClass::writeStream(Stream &data) {
|
||||||
data.setTimeout(10000);
|
data.setTimeout(20000);
|
||||||
size_t written = 0;
|
size_t written = 0;
|
||||||
size_t toRead = 0;
|
size_t toRead = 0;
|
||||||
if(hasError() || !isRunning())
|
if(hasError() || !isRunning())
|
||||||
|
Loading…
Reference in New Issue
Block a user