maintenance mode (experimental)
This commit is contained in:
parent
cb07ad4414
commit
f5d5e7c6fc
@ -437,6 +437,7 @@ Send for example `8386` as Downlink on Port 2 to get battery status and time/dat
|
|||||||
2 = reset device to factory settings
|
2 = reset device to factory settings
|
||||||
3 = flush send queues
|
3 = flush send queues
|
||||||
4 = restart device (warmstart)
|
4 = restart device (warmstart)
|
||||||
|
8 = reboot device to maintenance mode (local web server)
|
||||||
9 = reboot device to OTA update via Wifi mode
|
9 = reboot device to OTA update via Wifi mode
|
||||||
|
|
||||||
0x0A set LoRaWAN payload send cycle
|
0x0A set LoRaWAN payload send cycle
|
||||||
|
@ -58,7 +58,8 @@ enum runmode_t {
|
|||||||
RUNMODE_NORMAL,
|
RUNMODE_NORMAL,
|
||||||
RUNMODE_WAKEUP,
|
RUNMODE_WAKEUP,
|
||||||
RUNMODE_UPDATE,
|
RUNMODE_UPDATE,
|
||||||
RUNMODE_SLEEP
|
RUNMODE_SLEEP,
|
||||||
|
RUNMODE_MAINTENANCE
|
||||||
};
|
};
|
||||||
|
|
||||||
// Struct holding devices's runtime configuration
|
// Struct holding devices's runtime configuration
|
||||||
@ -83,7 +84,6 @@ typedef struct __attribute__((packed)) {
|
|||||||
uint8_t macfilter; // 0=disabled, 1=enabled
|
uint8_t macfilter; // 0=disabled, 1=enabled
|
||||||
uint8_t rgblum; // RGB Led luminosity (0..100%)
|
uint8_t rgblum; // RGB Led luminosity (0..100%)
|
||||||
uint8_t monitormode; // 0=disabled, 1=enabled
|
uint8_t monitormode; // 0=disabled, 1=enabled
|
||||||
uint8_t runmode; // 0=normal, 1=update
|
|
||||||
uint8_t payloadmask; // bitswitches for payload data
|
uint8_t payloadmask; // bitswitches for payload data
|
||||||
uint8_t enscount; // 0=disabled 1= enabled
|
uint8_t enscount; // 0=disabled 1= enabled
|
||||||
|
|
||||||
@ -149,5 +149,6 @@ extern TaskHandle_t irqHandlerTask, ClockTask, macProcessTask;
|
|||||||
extern TimerHandle_t WifiChanTimer;
|
extern TimerHandle_t WifiChanTimer;
|
||||||
extern Timezone myTZ;
|
extern Timezone myTZ;
|
||||||
extern RTC_DATA_ATTR runmode_t RTC_runmode;
|
extern RTC_DATA_ATTR runmode_t RTC_runmode;
|
||||||
|
extern char clientId[20]; // generated device name
|
||||||
|
|
||||||
#endif
|
#endif
|
@ -13,8 +13,13 @@
|
|||||||
#include <WiFiClientSecure.h>
|
#include <WiFiClientSecure.h>
|
||||||
#include <BintrayClient.h>
|
#include <BintrayClient.h>
|
||||||
|
|
||||||
|
#include <WiFiClient.h>
|
||||||
|
#include <WebServer.h>
|
||||||
|
#include <ESPmDNS.h>
|
||||||
|
|
||||||
int do_ota_update();
|
int do_ota_update();
|
||||||
void start_ota_update();
|
void start_ota_update();
|
||||||
|
void start_maintenance();
|
||||||
void ota_display(const uint8_t row, const std::string status,
|
void ota_display(const uint8_t row, const std::string status,
|
||||||
const std::string msg);
|
const std::string msg);
|
||||||
void show_progress(unsigned long current, unsigned long size);
|
void show_progress(unsigned long current, unsigned long size);
|
||||||
|
@ -13,15 +13,13 @@ Ticker cyclicTimer;
|
|||||||
extern boolean isSDS011Active;
|
extern boolean isSDS011Active;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void setCyclicIRQ() {
|
void setCyclicIRQ() { xTaskNotify(irqHandlerTask, CYCLIC_IRQ, eSetBits); }
|
||||||
xTaskNotify(irqHandlerTask, CYCLIC_IRQ, eSetBits);
|
|
||||||
}
|
|
||||||
|
|
||||||
// do all housekeeping
|
// do all housekeeping
|
||||||
void doHousekeeping() {
|
void doHousekeeping() {
|
||||||
|
|
||||||
// check if update mode trigger switch was set by rcommand
|
// check if update or maintenance mode trigger switch was set by rcommand
|
||||||
if (RTC_runmode == RUNMODE_UPDATE)
|
if ((RTC_runmode == RUNMODE_UPDATE) || (RTC_runmode == RUNMODE_MAINTENANCE))
|
||||||
do_reset(true);
|
do_reset(true);
|
||||||
|
|
||||||
// heap and task storage debugging
|
// heap and task storage debugging
|
||||||
|
11
src/main.cpp
11
src/main.cpp
@ -93,6 +93,7 @@ uint8_t batt_level = 0; // display value
|
|||||||
uint8_t volatile channel = WIFI_CHANNEL_MIN; // channel rotation counter
|
uint8_t volatile channel = WIFI_CHANNEL_MIN; // channel rotation counter
|
||||||
uint8_t volatile rf_load = 0; // RF traffic indicator
|
uint8_t volatile rf_load = 0; // RF traffic indicator
|
||||||
uint16_t volatile macs_wifi = 0, macs_ble = 0; // globals for display
|
uint16_t volatile macs_wifi = 0, macs_ble = 0; // globals for display
|
||||||
|
char clientId[20]; // generated device name
|
||||||
|
|
||||||
hw_timer_t *ppsIRQ = NULL, *displayIRQ = NULL, *matrixDisplayIRQ = NULL;
|
hw_timer_t *ppsIRQ = NULL, *displayIRQ = NULL, *matrixDisplayIRQ = NULL;
|
||||||
|
|
||||||
@ -142,6 +143,12 @@ void setup() {
|
|||||||
|
|
||||||
do_after_reset();
|
do_after_reset();
|
||||||
|
|
||||||
|
// generate unique clientId from device's MAC
|
||||||
|
uint8_t mac[6];
|
||||||
|
esp_eth_get_mac(mac);
|
||||||
|
const uint32_t hashedmac = hash((const char *)mac, 6);
|
||||||
|
snprintf(clientId, 20, "paxcounter_%08x", hashedmac);
|
||||||
|
|
||||||
// print chip information on startup if in verbose mode after coldstart
|
// print chip information on startup if in verbose mode after coldstart
|
||||||
#if (VERBOSE)
|
#if (VERBOSE)
|
||||||
|
|
||||||
@ -290,6 +297,10 @@ void setup() {
|
|||||||
start_ota_update();
|
start_ota_update();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// start local webserver if maintenance trigger switch is set
|
||||||
|
if (RTC_runmode == RUNMODE_MAINTENANCE)
|
||||||
|
start_maintenance();
|
||||||
|
|
||||||
// start mac processing task
|
// start mac processing task
|
||||||
ESP_LOGI(TAG, "Starting MAC processor...");
|
ESP_LOGI(TAG, "Starting MAC processor...");
|
||||||
macQueueInit();
|
macQueueInit();
|
||||||
|
@ -43,13 +43,6 @@ esp_err_t mqtt_init(void) {
|
|||||||
|
|
||||||
int mqtt_connect(const char *my_host, const uint16_t my_port) {
|
int mqtt_connect(const char *my_host, const uint16_t my_port) {
|
||||||
IPAddress mqtt_server_ip;
|
IPAddress mqtt_server_ip;
|
||||||
uint8_t mac[6];
|
|
||||||
char clientId[20];
|
|
||||||
|
|
||||||
// hash 6 byte MAC to 4 byte hash
|
|
||||||
esp_eth_get_mac(mac);
|
|
||||||
const uint32_t hashedmac = hash((const char *)mac, 6);
|
|
||||||
snprintf(clientId, 20, "paxcounter_%08x", hashedmac);
|
|
||||||
|
|
||||||
ESP_LOGI(TAG, "MQTT name is %s", MQTT_CLIENTNAME);
|
ESP_LOGI(TAG, "MQTT name is %s", MQTT_CLIENTNAME);
|
||||||
|
|
||||||
|
113
src/ota.cpp
113
src/ota.cpp
@ -330,4 +330,117 @@ void show_progress(unsigned long current, unsigned long size) {
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// start local web user with user interface for maintenance mode
|
||||||
|
// currently used only for manually uploading a firmware file via wifi
|
||||||
|
|
||||||
|
void start_maintenance(void) {
|
||||||
|
|
||||||
|
// code snippets taken from
|
||||||
|
// https://github.com/espressif/arduino-esp32/blob/master/libraries/ArduinoOTA/examples/OTAWebUpdater/OTAWebUpdater.ino
|
||||||
|
|
||||||
|
const char *host = MQTT_CLIENTNAME;
|
||||||
|
const char *ssid = WIFI_SSID;
|
||||||
|
const char *password = WIFI_PASS;
|
||||||
|
|
||||||
|
WebServer server(80);
|
||||||
|
|
||||||
|
const char *serverIndex =
|
||||||
|
"<script "
|
||||||
|
"src='https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/"
|
||||||
|
"jquery.min.js'></script>"
|
||||||
|
"<form method='POST' action='#' enctype='multipart/form-data' "
|
||||||
|
"id='upload_form'>"
|
||||||
|
"<input type='file' name='update'>"
|
||||||
|
"<input type='submit' value='Update'>"
|
||||||
|
"</form>"
|
||||||
|
"<div id='prg'>progress: 0%</div>"
|
||||||
|
"<script>"
|
||||||
|
"$('form').submit(function(e){"
|
||||||
|
"e.preventDefault();"
|
||||||
|
"var form = $('#upload_form')[0];"
|
||||||
|
"var data = new FormData(form);"
|
||||||
|
" $.ajax({"
|
||||||
|
"url: '/update',"
|
||||||
|
"type: 'POST',"
|
||||||
|
"data: data,"
|
||||||
|
"contentType: false,"
|
||||||
|
"processData:false,"
|
||||||
|
"xhr: function() {"
|
||||||
|
"var xhr = new window.XMLHttpRequest();"
|
||||||
|
"xhr.upload.addEventListener('progress', function(evt) {"
|
||||||
|
"if (evt.lengthComputable) {"
|
||||||
|
"var per = evt.loaded / evt.total;"
|
||||||
|
"$('#prg').html('progress: ' + Math.round(per*100) + '%');"
|
||||||
|
"}"
|
||||||
|
"}, false);"
|
||||||
|
"return xhr;"
|
||||||
|
"},"
|
||||||
|
"success:function(d, s) {"
|
||||||
|
"console.log('success!')"
|
||||||
|
"},"
|
||||||
|
"error: function (a, b, c) {"
|
||||||
|
"}"
|
||||||
|
"});"
|
||||||
|
"});"
|
||||||
|
"</script>";
|
||||||
|
|
||||||
|
// Connect to WiFi network
|
||||||
|
WiFi.begin(ssid, password);
|
||||||
|
|
||||||
|
// Wait for connection
|
||||||
|
while (WiFi.status() != WL_CONNECTED) {
|
||||||
|
delay(500);
|
||||||
|
}
|
||||||
|
ESP_LOGI(TAG, "Connected to %s", ssid);
|
||||||
|
|
||||||
|
// use mdns for host name resolution
|
||||||
|
if (!MDNS.begin(host)) {
|
||||||
|
ESP_LOGI(TAG, "Error setting up mDNS responder!");
|
||||||
|
delay(3000);
|
||||||
|
do_reset(false);
|
||||||
|
}
|
||||||
|
server.on("/", HTTP_GET, [&server, &serverIndex]() {
|
||||||
|
server.sendHeader("Connection", "close");
|
||||||
|
server.send(200, "text/html", serverIndex);
|
||||||
|
});
|
||||||
|
// handling uploading firmware file
|
||||||
|
server.on(
|
||||||
|
"/update", HTTP_POST,
|
||||||
|
[&server]() {
|
||||||
|
server.sendHeader("Connection", "close");
|
||||||
|
server.send(200, "text/plain", (Update.hasError()) ? "FAIL" : "OK");
|
||||||
|
do_reset(false);
|
||||||
|
},
|
||||||
|
[&server]() {
|
||||||
|
HTTPUpload &upload = server.upload();
|
||||||
|
if (upload.status == UPLOAD_FILE_START) {
|
||||||
|
ESP_LOGI(TAG, "Update: %s\n", upload.filename.c_str());
|
||||||
|
if (!Update.begin(
|
||||||
|
UPDATE_SIZE_UNKNOWN)) { // start with max available size
|
||||||
|
ESP_LOGE(TAG, "Error: %s", Update.errorString());
|
||||||
|
}
|
||||||
|
} else if (upload.status == UPLOAD_FILE_WRITE) {
|
||||||
|
// flashing firmware to ESP
|
||||||
|
if (Update.write(upload.buf, upload.currentSize) !=
|
||||||
|
upload.currentSize) {
|
||||||
|
ESP_LOGE(TAG, "Error: %s", Update.errorString());
|
||||||
|
}
|
||||||
|
} else if (upload.status == UPLOAD_FILE_END) {
|
||||||
|
if (Update.end(
|
||||||
|
true)) { // true to set the size to the current progress
|
||||||
|
ESP_LOGI(TAG, "Update Success: %u\nRebooting...\n",
|
||||||
|
upload.totalSize);
|
||||||
|
} else {
|
||||||
|
ESP_LOGE(TAG, "Update failed");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
server.begin();
|
||||||
|
|
||||||
|
while (1) {
|
||||||
|
server.handleClient();
|
||||||
|
delay(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#endif // USE_OTA
|
#endif // USE_OTA
|
@ -31,7 +31,11 @@ void set_reset(uint8_t val[]) {
|
|||||||
ESP_LOGI(TAG, "Remote command: restart device warm");
|
ESP_LOGI(TAG, "Remote command: restart device warm");
|
||||||
do_reset(true);
|
do_reset(true);
|
||||||
break;
|
break;
|
||||||
case 9: // reset and ask for software update via Wifi OTA
|
case 8: // reset and start local web server for manual software update
|
||||||
|
ESP_LOGI(TAG, "Remote command: software update via user interface");
|
||||||
|
RTC_runmode = RUNMODE_MAINTENANCE;
|
||||||
|
break;
|
||||||
|
case 9: // reset and ask OTA server via Wifi for automated software update
|
||||||
ESP_LOGI(TAG, "Remote command: software update via Wifi");
|
ESP_LOGI(TAG, "Remote command: software update via Wifi");
|
||||||
#if (USE_OTA)
|
#if (USE_OTA)
|
||||||
// check power status before scheduling ota update
|
// check power status before scheduling ota update
|
||||||
|
@ -14,7 +14,7 @@ RTC_DATA_ATTR struct timeval RTC_sleep_start_time;
|
|||||||
RTC_DATA_ATTR unsigned long long RTC_millis = 0;
|
RTC_DATA_ATTR unsigned long long RTC_millis = 0;
|
||||||
timeval sleep_stop_time;
|
timeval sleep_stop_time;
|
||||||
|
|
||||||
const char *runmode[5] = {"powercycle", "normal", "wakeup", "update", "sleep"};
|
const char *runmode[6] = {"powercycle", "normal", "wakeup", "update", "sleep", "maintenance"};
|
||||||
|
|
||||||
void do_reset(bool warmstart) {
|
void do_reset(bool warmstart) {
|
||||||
if (warmstart) {
|
if (warmstart) {
|
||||||
|
Loading…
Reference in New Issue
Block a user