Stabilise using AsyncTCP to scrape FOTA JSON file.

Need to establish WTF "closed_slots" in AsyncTCP are all about, especially the bad indexes that fly about leading to LWIP crashes.
This commit is contained in:
Ray Jones 2019-12-15 17:58:11 +11:00
parent c76490481d
commit 69155f8e45
16 changed files with 361 additions and 86 deletions

View File

@ -156,6 +156,7 @@ static void _handle_async_event(lwip_event_packet_t * e){
// do nothing when arg is NULL
//ets_printf("event arg == NULL: 0x%08x\n", e->recv.pcb);
} else if(e->event == LWIP_TCP_CLEAR){
// ets_printf("-X: 0x%08x\n", e->recv.pcb);
_remove_events_with_arg(e->arg);
} else if(e->event == LWIP_TCP_RECV){
//ets_printf("-R: 0x%08x\n", e->recv.pcb);
@ -374,6 +375,10 @@ typedef struct {
static err_t _tcp_output_api(struct tcpip_api_call_data *api_call_msg){
tcp_api_call_t * msg = (tcp_api_call_t *)api_call_msg;
msg->err = ERR_CONN;
if(msg->closed_slot >= 16 || msg->closed_slot < -1) {
Serial.printf("CLOSED SLOTS BOUNDS!! _tcp_output_api (%d)\r\n", msg->closed_slot);
return msg->err;
}
if(msg->closed_slot == -1 || !_closed_slots[msg->closed_slot]) {
msg->err = tcp_output(msg->pcb);
}
@ -394,6 +399,10 @@ static esp_err_t _tcp_output(tcp_pcb * pcb, int8_t closed_slot) {
static err_t _tcp_write_api(struct tcpip_api_call_data *api_call_msg){
tcp_api_call_t * msg = (tcp_api_call_t *)api_call_msg;
msg->err = ERR_CONN;
if(msg->closed_slot >= 16 || msg->closed_slot < -1) {
Serial.printf("CLOSED SLOTS BOUNDS!! _tcp_write_api (%d)\r\n", msg->closed_slot);
return msg->err;
}
if(msg->closed_slot == -1 || !_closed_slots[msg->closed_slot]) {
msg->err = tcp_write(msg->pcb, msg->write.data, msg->write.size, msg->write.apiflags);
}
@ -417,6 +426,10 @@ static esp_err_t _tcp_write(tcp_pcb * pcb, int8_t closed_slot, const char* data,
static err_t _tcp_recved_api(struct tcpip_api_call_data *api_call_msg){
tcp_api_call_t * msg = (tcp_api_call_t *)api_call_msg;
msg->err = ERR_CONN;
if(msg->closed_slot >= 16 || msg->closed_slot < -1) {
Serial.printf("CLOSED SLOTS BOUNDS!! _tcp_recv_api (%d)\r\n", msg->closed_slot);
return msg->err;
}
if(msg->closed_slot == -1 || !_closed_slots[msg->closed_slot]) {
msg->err = 0;
tcp_recved(msg->pcb, msg->received);
@ -439,6 +452,10 @@ static esp_err_t _tcp_recved(tcp_pcb * pcb, int8_t closed_slot, size_t len) {
static err_t _tcp_close_api(struct tcpip_api_call_data *api_call_msg){
tcp_api_call_t * msg = (tcp_api_call_t *)api_call_msg;
msg->err = ERR_CONN;
if(msg->closed_slot >= 16 || msg->closed_slot < -1) {
Serial.printf("CLOSED SLOTS BOUNDS!! _tcp_close_api (%d)\r\n", msg->closed_slot);
return msg->err;
}
if(msg->closed_slot == -1 || !_closed_slots[msg->closed_slot]) {
msg->err = tcp_close(msg->pcb);
}
@ -459,6 +476,10 @@ static esp_err_t _tcp_close(tcp_pcb * pcb, int8_t closed_slot) {
static err_t _tcp_abort_api(struct tcpip_api_call_data *api_call_msg){
tcp_api_call_t * msg = (tcp_api_call_t *)api_call_msg;
msg->err = ERR_CONN;
if(msg->closed_slot >= 16 || msg->closed_slot < -1) {
Serial.printf("CLOSED SLOTS BOUNDS!! _tcp_abort_api (%d)\r\n", msg->closed_slot);
return msg->err;
}
if(msg->closed_slot == -1 || !_closed_slots[msg->closed_slot]) {
tcp_abort(msg->pcb);
}
@ -834,6 +855,10 @@ void AsyncClient::_allocate_closed_slot(){
}
void AsyncClient::_free_closed_slot(){
if(_closed_slot >= 16 || _closed_slot < -1) {
Serial.printf("CLOSED SLOTS BOUNDS!! free_closed_slot (%d)\r\n", _closed_slot);
return;
}
if (_closed_slot != -1) {
_closed_slots[_closed_slot] = _closed_index;
_closed_slot = -1;

View File

@ -11,6 +11,7 @@
#include <HTTPClient.h>
#include <Update.h>
#include "../../ArduinoJson/ArduinoJson.h"
#include "../../asyncHTTPrequest/src/asyncHTTPrequest.h"
extern void forceBootInit();
@ -328,3 +329,237 @@ void esp32FOTA::onFail( std::function<void()> func ) {
_onFail = func;
}
void FOTAconnectCallback(void* arg, AsyncClient * c)
{
esp32FOTA* pInstance = (esp32FOTA*)arg;
if(pInstance) {
Serial.printf("ESPFOTA Connected. Sending Data\r\n");
String resp;
resp = "GET ";
resp += pInstance->getURI();
resp += " HTTP/1.1\r\n"
"Host: ";
resp += pInstance->getHost();
resp += "\r\n"
// "www.mrjones.id.au" "\r\n"
"Connection: close\r\n\r\n";
/* c->write(("GET " + pInstance->getURI() + " HTTP/1.1\r\n"
"Host: " + pInstance->getHost() + "\r\n"
// "www.mrjones.id.au" "\r\n"
"Connection: close\r\n\r\n")
.c_str());*/
c->write(resp.c_str());
}
}
void FOTAdataCallback(void* arg, AsyncClient* c, void* data, size_t len)
{
esp32FOTA* pInstance = (esp32FOTA*)arg;
if(pInstance == NULL) {
c->close();
return;
}
Serial.printf("FOTA received with length: %d\r\n", len);
char JSONMessage[1500];
memset(JSONMessage, 0, 1500);
char* pData = (char*)data;
for (int i = 0; i < len && i < 1499; i++) {
JSONMessage[i] = pData[i];
}
Serial.printf("%s\r\n", JSONMessage);
pInstance->decodeResponse(JSONMessage);
c->close();
}
bool esp32FOTA::decodeResponse(String payload)
{
int str_len = payload.length() + 1;
char* JSONMessage = new char[str_len];
payload.toCharArray(JSONMessage, str_len);
bool retval = decodeResponse(JSONMessage);
delete[] JSONMessage;
return retval;
}
bool esp32FOTA::decodeResponse(char* resp)
{
StaticJsonBuffer<300> JSONBuffer; //Memory pool
JsonObject &parsed = JSONBuffer.parseObject(resp); //Parse message
if (!parsed.success())
{ //Check for errors in parsing
// delete[] JSONMessage;
Serial.println("FOTA Parsing failed\r\n");
// delay(5000);
// return false;
}
const char *pltype = parsed["type"];
int plversion = parsed["version"];
const char *plhost = parsed["host"];
_port = parsed["port"];
const char *plbin = parsed["bin"];
String jshost(plhost);
String jsbin(plbin);
_host = jshost;
_bin = jsbin;
String fwtype(pltype);
if (plversion > _firwmareVersion && fwtype == _firwmareType)
{
_newVersion = plversion;
return true;
}
else
{
_newVersion = 0;
return false;
}
}
bool esp32FOTA::setURL(const char* URL, const char* expectedProtocol)
{
String url(URL);
// check for : (http: or https:
int index = url.indexOf(':');
if(index < 0) {
log_e("failed to parse protocol");
return false;
}
_webprotocol = url.substring(0, index);
if (_webprotocol != expectedProtocol) {
log_w("unexpected protocol: %s, expected %s", _protocol.c_str(), expectedProtocol);
return false;
}
url.remove(0, (index + 3)); // remove http:// or https://
index = url.indexOf('/');
String host = url.substring(0, index);
url.remove(0, index); // remove host part
/* // get Authorization
index = host.indexOf('@');
if(index >= 0) {
// auth info
String auth = host.substring(0, index);
host.remove(0, index + 1); // remove auth part including @
_base64Authorization = base64::encode(auth);
}*/
// get port
_webport = 80;
index = host.indexOf(':');
if(index >= 0) {
_webhost = host.substring(0, index); // hostname
host.remove(0, (index + 1)); // remove hostname + :
_webport = host.toInt(); // get port
} else {
_webhost = host;
}
_webURI = url;
log_d("host: %s port: %d url: %s", _webhost.c_str(), _webport, _webURI.c_str());
Serial.printf("host: %s port: %d url: %s", _webhost.c_str(), _webport, _webURI.c_str());
return true;
}
/*void esp32FOTA::setupAsync(const char* host)
{
setURL(host, "http");
static const char* shost = host;
_webclient.onError([](void* arg, AsyncClient * c, int8_t error) {
Serial.printf("ESPFOTA Error %s\r\n", c->errorToString(error));
c->close();
});
_webclient.onTimeout([](void* arg, AsyncClient * c, uint32_t tm) {
Serial.printf("ESPFOTA Timeout\r\n");
});
// _webclient.onConnect([](void* arg, AsyncClient * c) {
// Serial.printf("ESPFOTA Connected. Sending Data\r\n");
// c->write(("GET /?format=json HTTP/1.1\r\n"
// "Host: " +
// String(shost) + "\r\n"
// "Connection: close\r\n\r\n")
// .c_str());
// });
// _webclient.onData([](void* arg, AsyncClient* c, void* data, size_t len) {
// Serial.printf("FOTA received with length: %d\r\n", len);
// Serial.printf("%s\r\n", (char*)data);
// c->close();
// });
_webclient.onConnect(FOTAconnectCallback, this);
_webclient.onData(FOTAdataCallback, this);
}*/
// void esp32FOTA::poll(const char* host)
// {
// _webclient.connect(host, 80);
// }
asyncHTTPrequest request;
void FOTArequestCB(void* optParm, asyncHTTPrequest* pRequest, int readyState){
if(readyState == 4){ // resposnse
String JSONinfo(pRequest->responseText());
Serial.println(JSONinfo);
Serial.println();
// pRequest->close();
esp32FOTA* pFOTA = (esp32FOTA*) optParm;
if(pFOTA) pFOTA->decodeResponse(JSONinfo);
// delete pRequest;
}
if(readyState == 1) { // connected
pRequest->send();
}
}
void esp32FOTA::setupAsync(const char* host)
{
request.setDebug(true);
request.onReadyStateChange(FOTArequestCB, this);
}
void esp32FOTA::poll(const char* host)
{
asyncHTTPrequest* pRequest = &request/*new asyncHTTPrequest*/;
// pRequest->setDebug(true);
// pRequest->onReadyStateChange(FOTArequestCB, this);
if(pRequest->readyState() == 0 || pRequest->readyState() == 4) {
bool bOK = pRequest->open("GET", host);
}
}

View File

@ -10,6 +10,8 @@
//#include <Arduino.h>
#include <functional>
#include "../../AsyncTCP/src/AsyncTCP.h"
#include "../../asyncHTTPrequest/src/asyncHTTPrequest.h"
class esp32FOTA
{
@ -24,6 +26,16 @@ public:
void onSuccess( std::function<void()> func );
void onFail( std::function<void()> func );
int getNewVersion() { return _newVersion; };
bool setURL(const char* URL, const char* expectedProtocol);
void setupAsync(const char* host);
void poll(const char* host);
bool decodeResponse(String payload);
bool decodeResponse(char* resp);
const char* getURI() { return _webURI.c_str(); };
const char* getHost() { return _webhost.c_str(); };
private:
String getHeaderValue(String header, String headerName);
String getDeviceID();
@ -36,6 +48,11 @@ private:
std::function<bool(int)> _onComplete;
std::function<void()> _onSuccess;
std::function<void()> _onFail;
AsyncClient _webclient;
String _webhost;
String _webURI;
String _webprotocol;
int _webport;
};
#endif

View File

@ -20,12 +20,12 @@ upload_speed = 921600
;upload_flags =
; --port=3232
upload_port = COM5
upload_protocol = esptool
;upload_protocol = esptool
;monitor_speed = 115200
extra_scripts = post:add_CRC.py
; replace shitty Arduino millis with a linear time version
build_flags =
-Wl,--wrap,millis
debug_tool = esp-prog
;upload_protocol = esp-prog
upload_protocol = esp-prog
debug_init_break =

View File

@ -436,13 +436,15 @@ void setup() {
sCredentials creds = NVstore.getCredentials(); // local AP credentials
if(NVstore.getUserSettings().enableWifi) {
initWifi(WiFi_TriggerPin, creds.SSID, creds.APpassword);
// if(NVstore.getUserSettings().enableWifi) {
if(NVstore.getUserSettings().wifiMode) {
initWifi(creds.SSID, creds.APpassword); // SSID and passowrd the the ESP32's inbuilt AP
#if USE_OTA == 1
if(NVstore.getUserSettings().enableOTA) {
initOTA();
}
#endif // USE_OTA
initFOTA();
#if USE_WEBSERVER == 1
initWebServer();
#endif // USE_WEBSERVER
@ -1798,7 +1800,8 @@ void doStreaming()
{
#if USE_WIFI == 1
if(NVstore.getUserSettings().enableWifi) {
// if(NVstore.getUserSettings().enableWifi) {
if(NVstore.getUserSettings().wifiMode) {
doWiFiManager();
#if USE_OTA == 1
DoOTA();

View File

@ -122,13 +122,13 @@ CBluetoothHC05::begin()
else {
DebugPort.println("OK");
}
DebugPort.print(" Lowering power consumption...");
/* DebugPort.print(" Lowering power consumption...");
if(!ATCommand("AT+IPSCAN=1024,1,1024,1\r\n")) {
DebugPort.println("FAILED");
}
else {
DebugPort.println("OK");
}
}*/
DebugPort.print(" Getting MAC address...");
int len = 32;
char response[32];

View File

@ -61,7 +61,7 @@ CWiFiScreen::_initUI()
_OTAsel = NVstore.getUserSettings().enableOTA;
_bShowMAC = false;
if(NVstore.getUserSettings().enableWifi) {
if(NVstore.getUserSettings().wifiMode) {
if(isWifiAP()) {
if(isWifiConfigPortal()) {
_colSel = 1; // " WiFi: CFG AP only "

View File

@ -381,7 +381,8 @@ sUserSettings::load()
DebugPort.printf("2) Window = %f\r\n", ThermostatWindow);
validatedLoad("frostOn", FrostOn, 0, u8inBounds, 0, 10);
validatedLoad("frostRise", FrostRise, 5, u8inBounds, 0, 20);
validatedLoad("enableWifi", enableWifi, 1, u8inBounds, 0, 1);
// validatedLoad("enableWifi", enableWifi, 1, u8inBounds, 0, 1);
validatedLoad("enableWifi", wifiMode, 1, u8inBounds, 0, 3);
validatedLoad("enableOTA", enableOTA, 0, u8inBounds, 0, 1);
validatedLoad("cyclicStop", cyclic.Stop, 0, s8inBounds, 0, 10);
validatedLoad("cyclicStart", cyclic.Start, -1, s8inBounds, -20, 0);
@ -448,7 +449,8 @@ sUserSettings::save()
preferences.putFloat("thermoWindow", ThermostatWindow);
preferences.putUChar("frostOn", FrostOn);
preferences.putUChar("frostRise", FrostRise);
preferences.putUChar("enableWifi", enableWifi);
// preferences.putUChar("enableWifi", enableWifi);
preferences.putUChar("enableWifi", wifiMode);
preferences.putUChar("enableOTA", enableOTA);
preferences.putChar("cyclicStop", cyclic.Stop);
preferences.putChar("cyclicStart",cyclic.Start);

View File

@ -287,8 +287,9 @@ struct sUserSettings : public CESP32_NVStorage {
uint8_t FrostOn;
uint8_t FrostRise;
uint8_t useThermostat;
uint8_t enableWifi;
// uint8_t enableWifi;
uint8_t enableOTA;
uint8_t wifiMode;
uint16_t FrameRate;
sCyclicThermostat cyclic;
sHomeMenuActions HomeMenu;
@ -307,7 +308,8 @@ struct sUserSettings : public CESP32_NVStorage {
retval &= ThermostatMethod <= 3; // only modes 0, 1 or 2, 3
retval &= INBOUNDS(ThermostatWindow, 0.2f, 10.f);
retval &= useThermostat < 2;
retval &= (enableWifi == 0) || (enableWifi == 1);
// retval &= (enableWifi == 0) || (enableWifi == 1);
retval &= INBOUNDS(wifiMode, 0, 3);
retval &= (enableOTA == 0) || (enableOTA == 1);
retval &= GPIO.in1Mode < 4;
retval &= GPIO.in2Mode < 3;
@ -329,7 +331,8 @@ struct sUserSettings : public CESP32_NVStorage {
FrostOn = 0;
FrostRise = 5;
useThermostat = 1;
enableWifi = 1;
// enableWifi = 1;
wifiMode = 1;
enableOTA = 0;
GPIO.in1Mode = CGPIOin1::Disabled;
GPIO.in2Mode = CGPIOin2::Disabled;
@ -358,7 +361,8 @@ struct sUserSettings : public CESP32_NVStorage {
FrostOn = rhs.FrostOn;
FrostRise = rhs.FrostRise;
useThermostat = rhs.useThermostat;
enableWifi = rhs.enableWifi;
// enableWifi = rhs.enableWifi;
wifiMode = rhs.wifiMode;
enableOTA = rhs.enableOTA;
GPIO.in1Mode = rhs.GPIO.in1Mode;
GPIO.in2Mode = rhs.GPIO.in2Mode;

View File

@ -24,6 +24,9 @@
#if USE_MQTT == 1
//#define BLOCK_MQTT_RECON
#include <Arduino.h>
#include "ABMqtt.h"
#include "../../lib/async-mqtt-client/src/AsyncMqttClient.h"
@ -189,8 +192,10 @@ void onMqttSubscribe(uint16_t packetId, uint8_t qos) {
bool mqttInit()
{
#ifdef USE_RTOS_MQTTTIMER
#ifndef BLOCK_MQTT_RECON
if(mqttReconnectTimer==NULL)
mqttReconnectTimer = xTimerCreate("mqttTimer", pdMS_TO_TICKS(20000), pdFALSE, (void*)0, reinterpret_cast<TimerCallbackFunction_t>(connectToMqtt));
mqttReconnectTimer = xTimerCreate("mqttTimer", pdMS_TO_TICKS(6000), pdFALSE, (void*)0, reinterpret_cast<TimerCallbackFunction_t>(connectToMqtt));
#endif
#else
mqttReconnect = 0;
#endif
@ -282,9 +287,11 @@ void doMQTT()
#endif
#ifdef USE_RTOS_MQTTTIMER
#ifndef BLOCK_MQTT_RECON
if (!MQTTclient.connected() && WiFi.isConnected() && !xTimerIsTimerActive(mqttReconnectTimer)) {
xTimerStart(mqttReconnectTimer, 0);
xTimerStart(mqttReconnectTimer, 0);
}
#endif
#else
if (!MQTTclient.connected() && WiFi.isConnected() && mqttReconnect==0) {
mqttReconnect = millis() + 5000;

View File

@ -30,8 +30,6 @@
#include "../Utility/NVStorage.h"
#include "../../lib/WiFiManager-dev/WiFiManager.h"
//#define USE_AP
// function to control the behaviour upon reboot if no wifi manager credentials exist
// or connection fails
void prepBootIntoConfigPortal(bool state);
@ -43,7 +41,6 @@ WiFiManager wm;
bool isPortalAP = false; // true if config portal is running
bool isSTA = false; // true if connected to an access point
int TRIG_PIN; // pin that triggers the configuration portal when set to LOW
unsigned restartServer = 0; // set to time of portal reconfig - will cause reboot a while later
char MACstr[2][20]; // MACstr[0] STA, MACstr[1] = AP
int wifiButtonState = 0;
@ -52,12 +49,9 @@ unsigned long WifiReconnectHoldoff = 0;
extern CScreenManager ScreenManager;
bool initWifi(int initpin,const char *failedssid, const char *failedpassword)
bool initWifi(const char *failedssid, const char *failedpassword)
{
TRIG_PIN = initpin;
pinMode(TRIG_PIN, INPUT_PULLUP);
// report the MAC addresses - note individual values for STA and AP modes
uint8_t MAC[6];
esp_read_mac(MAC, ESP_MAC_WIFI_STA);
@ -121,8 +115,10 @@ bool initWifi(int initpin,const char *failedssid, const char *failedpassword)
DebugPort.println("Now promoting to STA+AP mode...");
retval = true;
}
#ifdef USE_AP
startAP = true;
#if USE_AP_ALWAYS == 1
if(NVstore.getUserSettings().wifiMode & 0x01) { // Own AP enabled
startAP = true;
}
#endif
if(startAP) {
// for STA+AP mode we *must* use the same RF channel as STA
@ -149,7 +145,7 @@ bool initWifi(int initpin,const char *failedssid, const char *failedpassword)
// call from main sketch loop()
void doWiFiManager()
{
if(NVstore.getUserSettings().enableWifi) {
if(NVstore.getUserSettings().wifiMode) {
wm.process();
if(WiFi.status() != WL_CONNECTED) {
@ -177,60 +173,14 @@ void doWiFiManager()
WifiReconnectHoldoff = 0;
}
#if USE_PORTAL_TRIGGER_PIN == 1
// manage handling of pin to enter WiFManager config portal
// we typically use the BOOT pin for this (pins.h)
//
// Quick Press (< 1 sec) - enable config portal
// > 1 second (< 5 sec) press - disable config portal
// > 5 second press - erase credentials, enable config portal
static bool pinDown = false;
static long pinTime = 0;
unsigned long tDelta;
if(digitalRead(TRIG_PIN) == LOW) {
if(!pinDown) {
pinTime = millis();
ScreenManager.reqUpdate();
}
pinDown = true;
// track hold duration - change OLED Wifi annotation according to length of press
tDelta = millis() - pinTime;
if(tDelta > 5000)
wifiButtonState = 3; // we will show 'ERS' on OLED!
else if(tDelta > 1000)
wifiButtonState = 2; // we will show 'HTR' on OLED!
else
wifiButtonState = 1; // we will show 'CFG' on OLED!
}
else {
if(pinDown) {
pinDown = false;
tDelta = millis() - pinTime;
DebugPort.printf("Wifi config button tDelta = %ld\r\n", tDelta);
// > 5 second press?
if(tDelta > 5000) {
wifiEnterConfigPortal(true, true); // very long press - clear credentials, reboot into portal
}
// > 1 second press?
else if(tDelta > 1000) {
wifiEnterConfigPortal(false); // long press - reboot into web server
}
// > 50ms press?
else if(tDelta > 50) {
wifiEnterConfigPortal(true); // quick press - reboot into portal
}
// consider as contact bounce if < 50ms!
}
}
#endif
}
}
void wifiDisable(long rebootDelay)
{
sUserSettings settings = NVstore.getUserSettings();
settings.enableWifi = 0;
// settings.enableWifi = 0;
settings.wifiMode = 0;
NVstore.setUserSettings(settings);
NVstore.save();
@ -249,7 +199,7 @@ void wifiEnterConfigPortal(bool state, bool erase, long rebootDelay)
wm.disconnect();
sUserSettings settings = NVstore.getUserSettings();
settings.enableWifi = 1;
settings.wifiMode = 1;
NVstore.setUserSettings(settings);
NVstore.save();
@ -286,7 +236,8 @@ void wifiFactoryDefault()
wm.resetSettings();
prepBootIntoConfigPortal(false);
sUserSettings settings = NVstore.getUserSettings();
settings.enableWifi = 1;
// settings.enableWifi = 1;
settings.wifiMode = 1;
NVstore.setUserSettings(settings);
NVstore.save();
}
@ -305,7 +256,7 @@ void APstartedCallback(WiFiManager*)
const char* getWifiAPAddrStr()
{
if(NVstore.getUserSettings().enableWifi) {
if(NVstore.getUserSettings().wifiMode) {
IPAddress IPaddr = WiFi.softAPIP(); // use stepping stone - function returns an automatic stack var - LAME!
static char APIPaddr[16];
sprintf(APIPaddr, "%d.%d.%d.%d", IPaddr[0], IPaddr[1], IPaddr[2], IPaddr[3]);
@ -317,7 +268,7 @@ const char* getWifiAPAddrStr()
const char* getWifiSTAAddrStr()
{
if(NVstore.getUserSettings().enableWifi) {
if(NVstore.getUserSettings().wifiMode) {
IPAddress IPaddr = WiFi.localIP(); // use stepping stone - function returns an automatic stack var - LAME!
static char STAIPaddr[16];
sprintf(STAIPaddr, "%d.%d.%d.%d", IPaddr[0], IPaddr[1], IPaddr[2], IPaddr[3]);
@ -339,7 +290,7 @@ const char* getWifiSTAMACStr()
String getSSID()
{
if(NVstore.getUserSettings().enableWifi) {
if(NVstore.getUserSettings().wifiMode) {
wifi_config_t conf;
esp_wifi_get_config(WIFI_IF_STA, &conf);
return String(reinterpret_cast<const char*>(conf.sta.ssid));
@ -350,7 +301,7 @@ String getSSID()
bool isWifiConnected()
{
if(NVstore.getUserSettings().enableWifi)
if(NVstore.getUserSettings().wifiMode)
return WiFi.status() == WL_CONNECTED;
else
return false;
@ -358,7 +309,7 @@ bool isWifiConnected()
bool isWifiAP()
{
if(NVstore.getUserSettings().enableWifi) {
if(NVstore.getUserSettings().wifiMode) {
int mode = WiFi.getMode();
return !isSTA && ((mode & WIFI_MODE_AP) != 0);
}

View File

@ -25,7 +25,7 @@
#include <WiFi.h>
void doWiFiManager();
bool initWifi(int initpin,const char *failedssid, const char *failedpassword);
bool initWifi(const char *failedssid, const char *failedpassword);
const char* getWifiAPAddrStr();
const char* getWifiSTAAddrStr();
const char* getWifiAPMACStr();

View File

@ -51,6 +51,10 @@ void hard_restart() {
while(true);
}
void initFOTA(){
FOTA.setupAsync("");
}
void initOTA(){
ArduinoOTA.setHostname("AfterburnerOTA");
@ -98,21 +102,25 @@ void initOTA(){
});
ArduinoOTA.begin();
}
//#define OLD_FOTA
void DoOTA()
{
ArduinoOTA.handle();
#ifdef OLD_FOTA
// manage Firmware OTA
// this is where the controller contacts a web server to discover if new firmware is available
// if so, it can download and implant using OTA and become effective next reboot!
long tDelta = millis() - FOTAtime;
if(tDelta > 0) {
// FOTAtime = millis() + 6000; // 6 seconds
FOTAtime = millis() + 6000; // 6 seconds
// FOTAtime = millis() + 60000; // 60 seconds
// FOTAtime = millis() + 600000; // 10 minutes
FOTAtime = millis() + 3600000; // 1 hour
// FOTAtime = millis() + 3600000; // 1 hour
if ((WiFi.status() == WL_CONNECTED)) { // bug workaround in FOTA where execHTTPcheck does not return false in this condition
FOTA.onProgress(onWebProgress); // important - keeps watchdog fed
FOTA.onComplete(CheckFirmwareCRC); // upload complete, but not yet verified
@ -137,6 +145,28 @@ void DoOTA()
}
}
}
#else
// manage Firmware OTA
// this is where the controller contacts a web server to discover if new firmware is available
// if so, it can download and implant using OTA and become effective next reboot!
long tDelta = millis() - FOTAtime;
if(tDelta > 0) {
// FOTA.setURL("http://www.mrjones.id.au/afterburner/fota/fota.json", "http");
// FOTA.setupAsync("http://www.mrjones.id.au/afterburner/fota/fota.json");
FOTAtime = millis() + 6000; // 6 seconds
// FOTAtime = millis() + 60000; // 60 seconds
// FOTAtime = millis() + 600000; // 10 minutes
// FOTAtime = millis() + 3600000; // 1 hour
// if ((WiFi.status() == WL_CONNECTED)) { // bug workaround in FOTA where execHTTPcheck does not return false in this condition
static bool flipflop = false;
flipflop = !flipflop;
if(flipflop)
FOTA.poll("http://www.mrjones.id.au/afterburner/fota/fotatest.json");
else
FOTA.poll("http://210.8.241.226/afterburner/fota/fotatest.json");
// }
}
#endif
};
int isUpdateAvailable(bool test)

View File

@ -23,6 +23,7 @@
#define __BTC_OTA_H
void initOTA();
void initFOTA();
void DoOTA();
bool CheckFirmwareCRC(int size);

View File

@ -23,7 +23,7 @@
// Place Holder Config File - User config vars and defines to be moved here
#define USE_JTAG 0
#define USE_JTAG 1
//////////////////////////////////////////////////////////////////////////////
// Configure bluetooth options
@ -42,6 +42,7 @@
// HC-05 works OK with WiFi
//
#define USE_WIFI 1
#define USE_AP_ALWAYS 1
#define USE_OTA 1
#define USE_WEBSERVER 1
#define USE_MQTT 1

View File

@ -57,5 +57,4 @@ const uint8_t keyCentre_pin = 35; // input only, no chip pullup
const uint8_t keyRight_pin = 36; // input only, no chip pullup
const uint8_t keyLeft_pin = 39; // input only, no chip pullup
const uint8_t WiFi_TriggerPin = 0; // BOOT switch!