commit
						215149d479
					
				@ -26,7 +26,7 @@ description = Paxcounter is a proof-of-concept ESP32 device for metering passeng
 | 
			
		||||
 | 
			
		||||
[common]
 | 
			
		||||
; 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!
 | 
			
		||||
; 0=None, 1=Error, 2=Warn, 3=Info, 4=Debug, 5=Verbose
 | 
			
		||||
debug_level = 0
 | 
			
		||||
 | 
			
		||||
@ -4,7 +4,7 @@
 | 
			
		||||
// Basic config
 | 
			
		||||
#include "globals.h"
 | 
			
		||||
#include "senddata.h"
 | 
			
		||||
#include "OTA.h"
 | 
			
		||||
#include "ota.h"
 | 
			
		||||
 | 
			
		||||
// Local logging tag
 | 
			
		||||
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
 | 
			
		||||
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
 | 
			
		||||
@ -90,39 +109,66 @@ void setup() {
 | 
			
		||||
  esp_log_set_vprintf(redirect_log);
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
  ESP_LOGI(TAG, "Starting %s v%s", PRODUCTNAME, PROGVERSION);
 | 
			
		||||
 | 
			
		||||
  // 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
 | 
			
		||||
  // read (and initialize on first run) runtime settings from NVRAM
 | 
			
		||||
  loadConfig(); // includes initialize if necessary
 | 
			
		||||
 | 
			
		||||
#ifdef VENDORFILTER
 | 
			
		||||
  strcat_P(features, " OUIFLT");
 | 
			
		||||
  // initialize leds
 | 
			
		||||
#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
 | 
			
		||||
 | 
			
		||||
// initialize LoRa
 | 
			
		||||
@ -149,58 +195,32 @@ void setup() {
 | 
			
		||||
             SEND_QUEUE_SIZE * PAYLOAD_BUFFER_SIZE);
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
    // initialize led
 | 
			
		||||
#if (HAS_LED != NOT_A_PIN)
 | 
			
		||||
  pinMode(HAS_LED, OUTPUT);
 | 
			
		||||
  strcat_P(features, " LED");
 | 
			
		||||
#ifdef VENDORFILTER
 | 
			
		||||
  strcat_P(features, " OUIFLT");
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifdef HAS_RGB_LED
 | 
			
		||||
  rgb_set_color(COLOR_PINK);
 | 
			
		||||
  strcat_P(features, " RGB");
 | 
			
		||||
#endif
 | 
			
		||||
  ESP_LOGI(TAG, "Starting %s v%s", PRODUCTNAME, PROGVERSION);
 | 
			
		||||
 | 
			
		||||
  // 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
 | 
			
		||||
  // 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());
 | 
			
		||||
 | 
			
		||||
  // 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
 | 
			
		||||
  strcat_P(features, " GPS");
 | 
			
		||||
  ESP_LOGI(TAG, "TinyGPS+ v%s", TinyGPSPlus::libraryVersion());
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
// initialize battery status
 | 
			
		||||
#ifdef HAS_BATTERY_PROBE
 | 
			
		||||
  strcat_P(features, " BATT");
 | 
			
		||||
  calibrate_voltage();
 | 
			
		||||
  batt_voltage = read_voltage();
 | 
			
		||||
#endif
 | 
			
		||||
#endif // verbose
 | 
			
		||||
 | 
			
		||||
// initialize display
 | 
			
		||||
#ifdef HAS_DISPLAY
 | 
			
		||||
@ -208,16 +228,6 @@ void setup() {
 | 
			
		||||
  DisplayState = cfg.screenon;
 | 
			
		||||
  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
 | 
			
		||||
  // https://techtutorialsx.com/2017/10/07/esp32-arduino-timer-interrupts/
 | 
			
		||||
 | 
			
		||||
@ -232,13 +242,6 @@ void setup() {
 | 
			
		||||
  timerAlarmEnable(displaytimer);
 | 
			
		||||
#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
 | 
			
		||||
  channelSwitch = timerBegin(1, 800, true);
 | 
			
		||||
  timerAttachInterrupt(channelSwitch, &ChannelSwitchIRQ, true);
 | 
			
		||||
@ -293,18 +296,6 @@ void setup() {
 | 
			
		||||
  // join network
 | 
			
		||||
  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
 | 
			
		||||
  // (note: arduino main loop runs on core 1, too)
 | 
			
		||||
  // 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
 | 
			
		||||
  ESP_LOGI(TAG, "Starting Wifi...");
 | 
			
		||||
  // esp_event_loop_init(NULL, NULL);
 | 
			
		||||
  // ESP_ERROR_CHECK(esp_event_loop_init(event_handler, NULL));
 | 
			
		||||
  wifi_sniffer_init();
 | 
			
		||||
  // initialize salt value using esp_random() called by random() in
 | 
			
		||||
  // arduino-esp32 core. Note: do this *after* wifi has started, since
 | 
			
		||||
@ -345,40 +338,9 @@ void 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() {
 | 
			
		||||
 | 
			
		||||
// 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)
 | 
			
		||||
  led_loop();
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										19
									
								
								src/main.h
									
									
									
									
									
								
							
							
						
						
									
										19
									
								
								src/main.h
									
									
									
									
									
								
							@ -1,20 +1,17 @@
 | 
			
		||||
#ifndef _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_event_loop.h> // needed for Wifi event handler
 | 
			
		||||
#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
 | 
			
		||||
							
								
								
									
										121
									
								
								src/ota.cpp
									
									
									
									
									
								
							
							
						
						
									
										121
									
								
								src/ota.cpp
									
									
									
									
									
								
							@ -35,15 +35,36 @@ volatile bool isValidContentType = false;
 | 
			
		||||
// Local logging tag
 | 
			
		||||
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
 | 
			
		||||
  u8x8.setCursor(x, y);
 | 
			
		||||
  u8x8.print(text);
 | 
			
		||||
  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());
 | 
			
		||||
  }
 | 
			
		||||
#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() {
 | 
			
		||||
 | 
			
		||||
// 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
 | 
			
		||||
  u8x8.begin();
 | 
			
		||||
  u8x8.setFont(u8x8_font_chroma48medium8_r);
 | 
			
		||||
@ -51,67 +72,80 @@ void start_ota_update() {
 | 
			
		||||
#ifdef DISPLAY_FLIP
 | 
			
		||||
  u8x8.setFlipMode(1);
 | 
			
		||||
#endif
 | 
			
		||||
  u8x8.draw2x2String(0, 0, "UPDATING");
 | 
			
		||||
  u8x8.setCursor(0, 3);
 | 
			
		||||
  u8x8.print("Wifi connect  ..\n");
 | 
			
		||||
  u8x8.print("Get Update?   ..\n");
 | 
			
		||||
  u8x8.setInverseFont(1);
 | 
			
		||||
  u8x8.print("SOFTWARE UPDATE \n");
 | 
			
		||||
  u8x8.setInverseFont(0);
 | 
			
		||||
  u8x8.print("WiFi connect  ..\n");
 | 
			
		||||
  u8x8.print("Has Update?   ..\n");
 | 
			
		||||
  u8x8.print("Downloading   ..\n");
 | 
			
		||||
  u8x8.print("Flashing      ..\n");
 | 
			
		||||
  u8x8.print("Rebooting     ..");
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
  ESP_LOGI(TAG, "Starting Wifi OTA update");
 | 
			
		||||
  display(14, 3, "**");
 | 
			
		||||
  display(1, "**", WIFI_SSID);
 | 
			
		||||
 | 
			
		||||
  WiFi.begin(WIFI_SSID, WIFI_PASS);
 | 
			
		||||
 | 
			
		||||
  int i = WIFI_MAX_TRY;
 | 
			
		||||
 | 
			
		||||
  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)
 | 
			
		||||
      break;
 | 
			
		||||
    vTaskDelay(5000 / portTICK_PERIOD_MS);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  if (i >= 0) {
 | 
			
		||||
    ESP_LOGI(TAG, "connected to %s", WIFI_SSID);
 | 
			
		||||
    display(14, 3, "OK");
 | 
			
		||||
    checkFirmwareUpdates(); // gets and flashes new firmware and restarts
 | 
			
		||||
    ESP_LOGI(TAG, "Connected to %s", WIFI_SSID);
 | 
			
		||||
    display(1, "OK", "WiFi connected");
 | 
			
		||||
    checkFirmwareUpdates(); // gets and flashes new firmware
 | 
			
		||||
  } else {
 | 
			
		||||
    ESP_LOGI(TAG, "could not connect to %s, rebooting.", WIFI_SSID);
 | 
			
		||||
    display(14, 3, " E");
 | 
			
		||||
    ESP_LOGI(TAG, "Could not connect to %s, rebooting.", WIFI_SSID);
 | 
			
		||||
    display(1, " E", "no WiFi connect");
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  display(14, 7, "**");
 | 
			
		||||
  delay(5000);
 | 
			
		||||
  ESP.restart(); // reached only if update was not successful or no wifi connect
 | 
			
		||||
  display(5, "**", ""); // mark line rebooting
 | 
			
		||||
 | 
			
		||||
// 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
 | 
			
		||||
 | 
			
		||||
void checkFirmwareUpdates() {
 | 
			
		||||
  // Fetch the latest firmware version
 | 
			
		||||
  ESP_LOGI(TAG, "OTA mode, checking latest firmware version on server...");
 | 
			
		||||
  display(14, 4, "**");
 | 
			
		||||
  ESP_LOGI(TAG, "Checking latest firmware version on server...");
 | 
			
		||||
  display(2, "**", "checking version");
 | 
			
		||||
  const String latest = bintray.getLatestVersion();
 | 
			
		||||
 | 
			
		||||
  if (latest.length() == 0) {
 | 
			
		||||
    ESP_LOGI(
 | 
			
		||||
        TAG,
 | 
			
		||||
        "Could not load info about the latest firmware. Rebooting to runmode.");
 | 
			
		||||
    display(14, 4, " E");
 | 
			
		||||
    display(2, " E", "file not found");
 | 
			
		||||
    return;
 | 
			
		||||
  } else if (version_compare(latest, cfg.version) <= 0) {
 | 
			
		||||
    ESP_LOGI(TAG, "Current firmware is up to date. Rebooting to runmode.");
 | 
			
		||||
    display(14, 4, "NO");
 | 
			
		||||
    display(2, "NO", "no update found");
 | 
			
		||||
    return;
 | 
			
		||||
  }
 | 
			
		||||
  ESP_LOGI(TAG, "New firmware version v%s available. Downloading...",
 | 
			
		||||
           latest.c_str());
 | 
			
		||||
  display(14, 4, "OK");
 | 
			
		||||
  display(2, "OK", "");
 | 
			
		||||
 | 
			
		||||
  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) {
 | 
			
		||||
  return header.substring(strlen(headerName.c_str()));
 | 
			
		||||
}
 | 
			
		||||
@ -120,11 +154,13 @@ inline String getHeaderValue(String header, String headerName) {
 | 
			
		||||
 * OTA update processing
 | 
			
		||||
 */
 | 
			
		||||
void processOTAUpdate(const String &version) {
 | 
			
		||||
  display(14, 5, "**");
 | 
			
		||||
 | 
			
		||||
  char buf[17];
 | 
			
		||||
  display(3, "**", "requesting file");
 | 
			
		||||
  String firmwarePath = bintray.getBinaryPath(version);
 | 
			
		||||
  if (!firmwarePath.endsWith(".bin")) {
 | 
			
		||||
    ESP_LOGI(TAG, "Unsupported binary format, OTA update cancelled.");
 | 
			
		||||
    display(14, 5, " E");
 | 
			
		||||
    display(3, " E", "file type error");
 | 
			
		||||
    return;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
@ -136,7 +172,7 @@ void processOTAUpdate(const String &version) {
 | 
			
		||||
 | 
			
		||||
  if (!client.connect(currentHost.c_str(), port)) {
 | 
			
		||||
    ESP_LOGI(TAG, "Cannot connect to %s", currentHost.c_str());
 | 
			
		||||
    display(14, 5, " E");
 | 
			
		||||
    display(3, " E", "connection lost");
 | 
			
		||||
    return;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
@ -148,7 +184,7 @@ void processOTAUpdate(const String &version) {
 | 
			
		||||
      if (!client.connect(currentHost.c_str(), port)) {
 | 
			
		||||
        ESP_LOGI(TAG, "Redirect detected, but cannot connect to %s",
 | 
			
		||||
                 currentHost.c_str());
 | 
			
		||||
        display(14, 5, " E");
 | 
			
		||||
        display(3, " E", "server error");
 | 
			
		||||
        return;
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
@ -164,7 +200,7 @@ void processOTAUpdate(const String &version) {
 | 
			
		||||
    while (client.available() == 0) {
 | 
			
		||||
      if (millis() - timeout > RESPONSE_TIMEOUT_MS) {
 | 
			
		||||
        ESP_LOGI(TAG, "Client Timeout.");
 | 
			
		||||
        display(14, 5, " E");
 | 
			
		||||
        display(3, " E", "client timeout");
 | 
			
		||||
        client.stop();
 | 
			
		||||
        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
 | 
			
		||||
  if (contentLength && isValidContentType) {
 | 
			
		||||
 | 
			
		||||
    size_t written;
 | 
			
		||||
    size_t written, current, size;
 | 
			
		||||
 | 
			
		||||
    if (Update.begin(contentLength)) {
 | 
			
		||||
 | 
			
		||||
      // register callback function for showing progress while streaming data
 | 
			
		||||
      Update.onProgress(&show_progress);
 | 
			
		||||
 | 
			
		||||
      int i = FLASH_MAX_TRY;
 | 
			
		||||
      while ((i--) && (written != contentLength)) {
 | 
			
		||||
 | 
			
		||||
        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...",
 | 
			
		||||
                 FLASH_MAX_TRY - i, FLASH_MAX_TRY);
 | 
			
		||||
        display(14, 6, "**");
 | 
			
		||||
        display(4, "**", "writing...");
 | 
			
		||||
 | 
			
		||||
        written = Update.writeStream(client);
 | 
			
		||||
 | 
			
		||||
        if (written == contentLength) {
 | 
			
		||||
          ESP_LOGI(TAG, "Written %d bytes successfully", written);
 | 
			
		||||
          display(14, 6, "**");
 | 
			
		||||
          ESP_LOGI(TAG, "Written %u bytes successfully", written);
 | 
			
		||||
          snprintf(buf, 17, "%u kB Done!", (uint16_t)(written / 1024));
 | 
			
		||||
          display(4, "OK", buf);
 | 
			
		||||
          break;
 | 
			
		||||
        } else {
 | 
			
		||||
          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);
 | 
			
		||||
          display(14, 6, " E");
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
@ -262,33 +301,31 @@ void processOTAUpdate(const String &version) {
 | 
			
		||||
          ESP_LOGI(
 | 
			
		||||
              TAG,
 | 
			
		||||
              "OTA update completed. Rebooting to runmode with new version.");
 | 
			
		||||
          display(14, 7, "OK");
 | 
			
		||||
          client.stop();
 | 
			
		||||
          return;
 | 
			
		||||
        } else {
 | 
			
		||||
          ESP_LOGI(TAG, "Something went wrong! OTA update hasn't been finished "
 | 
			
		||||
                        "properly.");
 | 
			
		||||
          display(14, 7, " E");
 | 
			
		||||
        }
 | 
			
		||||
      } else {
 | 
			
		||||
        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 {
 | 
			
		||||
      ESP_LOGI(TAG, "There isn't enough space to start OTA update");
 | 
			
		||||
      display(14, 7, " E");
 | 
			
		||||
      display(4, " E", "disk full");
 | 
			
		||||
      client.flush();
 | 
			
		||||
    }
 | 
			
		||||
  } else {
 | 
			
		||||
    ESP_LOGI(TAG,
 | 
			
		||||
             "There was no valid content in the response from the OTA server!");
 | 
			
		||||
    display(14, 7, " E");
 | 
			
		||||
    display(4, " E", "response error");
 | 
			
		||||
    client.flush();
 | 
			
		||||
  }
 | 
			
		||||
  ESP_LOGI(TAG,
 | 
			
		||||
           "OTA update failed. Rebooting to runmode with current version.");
 | 
			
		||||
  display(14, 7, " E");
 | 
			
		||||
  client.stop();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -13,5 +13,6 @@ void checkFirmwareUpdates();
 | 
			
		||||
void processOTAUpdate(const String &version);
 | 
			
		||||
void start_ota_update();
 | 
			
		||||
int version_compare(const String v1, const String v2);
 | 
			
		||||
void show_progress(size_t current, size_t size);
 | 
			
		||||
 | 
			
		||||
#endif // OTA_H
 | 
			
		||||
 | 
			
		||||
@ -73,8 +73,8 @@ void IRAM_ATTR SendCycleIRQ() {
 | 
			
		||||
  portEXIT_CRITICAL(&timerMux);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// interrupt triggered function to eat data from RTos send queues and transmit it
 | 
			
		||||
void enqueuePayload() {
 | 
			
		||||
// interrupt triggered function to eat data from send queues and transmit it
 | 
			
		||||
void checkSendQueues() {
 | 
			
		||||
  MessageBuffer_t SendBuffer;
 | 
			
		||||
 | 
			
		||||
#ifdef HAS_LORA
 | 
			
		||||
@ -98,7 +98,7 @@ void enqueuePayload() {
 | 
			
		||||
  }
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
} // enqueuePayload
 | 
			
		||||
} // checkSendQueues
 | 
			
		||||
 | 
			
		||||
void flushQueues() {
 | 
			
		||||
#ifdef HAS_LORA
 | 
			
		||||
 | 
			
		||||
@ -4,7 +4,7 @@
 | 
			
		||||
void SendData(uint8_t port);
 | 
			
		||||
void sendPayload(void);
 | 
			
		||||
void SendCycleIRQ(void);
 | 
			
		||||
void enqueuePayload(void);
 | 
			
		||||
void checkSendQueues(void);
 | 
			
		||||
void flushQueues();
 | 
			
		||||
 | 
			
		||||
#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) {
 | 
			
		||||
    data.setTimeout(10000);
 | 
			
		||||
    data.setTimeout(20000);
 | 
			
		||||
    size_t written = 0;
 | 
			
		||||
    size_t toRead = 0;
 | 
			
		||||
    if(hasError() || !isRunning())
 | 
			
		||||
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user