diff --git a/src/httpserver/http_fns.c b/src/httpserver/http_fns.c index db35eb2da..78b6ae7bc 100644 --- a/src/httpserver/http_fns.c +++ b/src/httpserver/http_fns.c @@ -382,6 +382,82 @@ int http_fn_cfg_webapp_set(http_request_t *request) { + +int http_fn_cfg_ping(http_request_t *request) { + char tmpA[128]; + const char *tmp; + int i; + int bChanged; + + http_setup(request, httpMimeTypeHTML); + poststr(request,htmlHeader); + poststr(request,g_header); + bChanged = 0; + poststr(request,"

Ping watchdog (backup reconnect mechanism)

"); + poststr(request,"

By default, all OpenBeken devices automatically tries to reconnect to WiFi when a connection is lost."); + poststr(request," I have tested the reconnect mechanism many times by restarting my router and it always worked reliably."); + poststr(request," However, according to some reports, there are still some edge cases when a device fails to reconnect to WIFi."); + poststr(request," This is why this mechanism has been added.

"); + poststr(request,"

This mechanism keeps pinging certain host and reconnects to WiFi if it doesn't respond at all for a certain amount of seconds.

"); + poststr(request,"

USAGE: For a host, choose the main address of your router and make sure it responds to a pings. Interval can be 2 seconds or so, timeout 60 sec

"); + if(http_getArg(request->url,"host",tmpA,sizeof(tmpA))) { + CFG_SetPingHost(tmpA); + poststr(request,"

New ping host set!

"); + bChanged = 1; + } + if(http_getArg(request->url,"interval",tmpA,sizeof(tmpA))) { + CFG_SetPingIntervalSeconds(atoi(tmpA)); + poststr(request,"

New ping interval set!

"); + bChanged = 1; + } + if(http_getArg(request->url,"disconnectTime",tmpA,sizeof(tmpA))) { + CFG_SetPingDisconnectedSecondsToRestart(atoi(tmpA)); + poststr(request,"

New ping disconnectTime set!

"); + bChanged = 1; + } + if(http_getArg(request->url,"clear",tmpA,sizeof(tmpA))) { + CFG_SetPingDisconnectedSecondsToRestart(0); + CFG_SetPingIntervalSeconds(0); + CFG_SetPingHost(""); + poststr(request,"

Ping watchdog disabled!

"); + bChanged = 1; + } + if(bChanged) { + poststr(request,"

Changes will be applied after restarting

"); + } + poststr(request,"
\ + \ + \ +
"); + poststr(request,"

Use this to enable pinger

"); + poststr(request,"
\ +
\ +
\ +
\ +
\ +
\ +

\ + \ +
"); + poststr(request,htmlReturnToCfg); + HTTP_AddBuildFooter(request); + poststr(request,htmlEnd); + + poststr(request, NULL); + return 0; +} int http_fn_cfg_wifi(http_request_t *request) { // for a test, show password as well... const char *cur_ssid, *cur_pass; @@ -1020,6 +1096,7 @@ int http_fn_cfg(http_request_t *request) { poststr(request,"
"); poststr(request,"
"); poststr(request,"
"); + poststr(request,"
"); poststr(request,"
"); poststr(request,"
"); poststr(request,"
"); diff --git a/src/httpserver/http_fns.h b/src/httpserver/http_fns.h index ba11026d6..78056b54e 100644 --- a/src/httpserver/http_fns.h +++ b/src/httpserver/http_fns.h @@ -21,6 +21,7 @@ int http_fn_cfg_quick(http_request_t *request); int http_fn_cfg_ha(http_request_t *request); int http_fn_cfg(http_request_t *request); int http_fn_cfg_pins(http_request_t *request); +int http_fn_cfg_ping(http_request_t *request); int http_fn_index(http_request_t *request); int http_fn_ota_exec(http_request_t *request); int http_fn_ota(http_request_t *request); diff --git a/src/httpserver/new_http.c b/src/httpserver/new_http.c index 973d118f9..ae68e76d1 100644 --- a/src/httpserver/new_http.c +++ b/src/httpserver/new_http.c @@ -531,6 +531,7 @@ int HTTP_ProcessPacket(http_request_t *request) { if(http_checkUrlBase(urlStr,"cfg")) return http_fn_cfg(request); if(http_checkUrlBase(urlStr,"cfg_pins")) return http_fn_cfg_pins(request); + if(http_checkUrlBase(urlStr,"cfg_ping")) return http_fn_cfg_ping(request); if(http_checkUrlBase(urlStr,"ota")) return http_fn_ota(request); if(http_checkUrlBase(urlStr,"ota_exec")) return http_fn_ota_exec(request); diff --git a/src/new_cfg.c b/src/new_cfg.c index 8455e1cc3..ede9eeebb 100644 --- a/src/new_cfg.c +++ b/src/new_cfg.c @@ -17,9 +17,47 @@ int g_cfg_pendingChanges = 0; #define CFG_IDENT_1 'F' #define CFG_IDENT_2 'G' -#define MAIN_CFG_VERSION 1 +#define MAIN_CFG_VERSION 2 -static byte CFG_CalcChecksum(mainConfig_t *inf) { +// version v1 +// Version v2 is now flexible and doesnt have to be duplicated +// in order to support previous versions any more +typedef struct mainConfig_v1_s { + byte ident0; + byte ident1; + byte ident2; + byte crc; + int version; + // unused + int genericFlags; + // unused + int genericFlags2; + unsigned short changeCounter; + unsigned short otaCounter; + // target wifi credentials + char wifi_ssid[64]; + char wifi_pass[64]; + // MQTT information for Home Assistant + char mqtt_host[256]; + char mqtt_brokerName[64]; + char mqtt_userName[64]; + char mqtt_pass[128]; + int mqtt_port; + // addon JavaScript panel is hosted on external server + char webappRoot[64]; + // TODO? + byte mac[6]; + // TODO? + char shortDeviceName[32]; + char longDeviceName[64]; + pinsState_t pins; + byte unusedSectorA[256]; + byte unusedSectorB[128]; + byte unusedSectorC[128]; + char initCommandLine[512]; +} mainConfig_v1_t; + +static byte CFG_CalcChecksum_V1(mainConfig_v1_t *inf) { byte crc = 0; crc ^= Tiny_CRC8((const char*)&inf->version,sizeof(inf->version)); crc ^= Tiny_CRC8((const char*)&inf->changeCounter,sizeof(inf->changeCounter)); @@ -45,6 +83,25 @@ static byte CFG_CalcChecksum(mainConfig_t *inf) { return crc; } +static byte CFG_CalcChecksum(mainConfig_t *inf) { + int header_size; + int remaining_size; + byte crc; + + if(inf->version <= 1) { + return CFG_CalcChecksum_V1((mainConfig_v1_t *)inf); + } + header_size = ((byte*)&inf->version)-((byte*)inf); + remaining_size = sizeof(mainConfig_t) - header_size; + + ADDLOG_DEBUG(LOG_FEATURE_CFG, "CFG_CalcChecksum: header size %i, total size %i, rem size %i\n", + header_size, sizeof(mainConfig_t), remaining_size); + + // This is more flexible method and won't be affected by field offsets + crc = Tiny_CRC8((const char*)&inf->version,remaining_size); + + return crc; +} static void CFG_SetDefaultConfig() { // must be unsigned, else print below prints negatives as e.g. FFFFFFFe unsigned char mac[6] = { 0 }; @@ -58,10 +115,12 @@ static void CFG_SetDefaultConfig() { g_configInitialized = 1; memset(&g_cfg,0,sizeof(mainConfig_t)); + g_cfg.version = MAIN_CFG_VERSION; g_cfg.mqtt_port = 1883; g_cfg.ident0 = CFG_IDENT_0; g_cfg.ident1 = CFG_IDENT_1; g_cfg.ident2 = CFG_IDENT_2; + strcpy(g_cfg.ping_host,"192.168.0.1"); strcpy(g_cfg.mqtt_host, "192.168.0.113"); strcpy(g_cfg.mqtt_brokerName, "test"); strcpy(g_cfg.mqtt_userName, "homeassistant"); @@ -84,8 +143,37 @@ const char *CFG_GetWebappRoot(){ const char *CFG_GetShortStartupCommand() { return g_cfg.initCommandLine; } - +const char *CFG_GetPingHost() { + return g_cfg.ping_host; +} +int CFG_GetPingDisconnectedSecondsToRestart() { + return g_cfg.ping_seconds; +} +int CFG_GetPingIntervalSeconds() { + return g_cfg.ping_interval; +} +void CFG_SetPingHost(const char *s) { + // this will return non-zero if there were any changes + if(strcpy_safe_checkForChanges(g_cfg.ping_host, s,sizeof(g_cfg.ping_host))) { + // mark as dirty (value has changed) + g_cfg_pendingChanges++; + } +} +void CFG_SetPingDisconnectedSecondsToRestart(int i) { + if(g_cfg.ping_seconds != i) { + g_cfg.ping_seconds = i; + // mark as dirty (value has changed) + g_cfg_pendingChanges++; + } +} +void CFG_SetPingIntervalSeconds(int i) { + if(g_cfg.ping_interval != i) { + g_cfg.ping_interval = i; + // mark as dirty (value has changed) + g_cfg_pendingChanges++; + } +} void CFG_SetShortStartupCommand_AndExecuteNow(const char *s) { CFG_SetShortStartupCommand(s); CMD_ExecuteCommand(s); @@ -222,6 +310,7 @@ void CFG_IncrementOTACount() { } void CFG_Save_IfThereArePendingChanges() { if(g_cfg_pendingChanges > 0) { + g_cfg.version = MAIN_CFG_VERSION; g_cfg.changeCounter++; g_cfg.crc = CFG_CalcChecksum(&g_cfg); HAL_Configuration_SaveConfigMemory(&g_cfg,sizeof(g_cfg)); diff --git a/src/new_cfg.h b/src/new_cfg.h index c8b1e6bb0..6456d393e 100644 --- a/src/new_cfg.h +++ b/src/new_cfg.h @@ -36,6 +36,12 @@ void CFG_IncrementOTACount(); void CFG_SetShortStartupCommand(const char *s); void CFG_SetShortStartupCommand_AndExecuteNow(const char *s); const char *CFG_GetShortStartupCommand(); +const char *CFG_GetPingHost(); +int CFG_GetPingDisconnectedSecondsToRestart(); +int CFG_GetPingIntervalSeconds(); +void CFG_SetPingHost(const char *s); +void CFG_SetPingDisconnectedSecondsToRestart(int i); +void CFG_SetPingIntervalSeconds(int i); diff --git a/src/new_common.h b/src/new_common.h index df377a01d..afa90c4cd 100644 --- a/src/new_common.h +++ b/src/new_common.h @@ -197,6 +197,8 @@ int strcat_safe(char *tg, const char *src, int tgMaxLen); int strcpy_safe(char *tg, const char *src, int tgMaxLen); int strcpy_safe_checkForChanges(char *tg, const char *src, int tgMaxLen); void urldecode2_safe(char *dst, const char *srcin, int maxDstLen); + +// user_main.c int Time_getUpTimeSeconds(); char Tiny_CRC8(const char *data,int length); void RESET_ScheduleModuleReset(int delSeconds); @@ -207,6 +209,11 @@ void Main_OnEverySecond(); int Main_GetLastRebootBootFailures(); void Main_OnPingCheckerReply(int ms); +// new_ping.c +void Main_SetupPingWatchDog(const char *target, int delayBetweenPings); + + + diff --git a/src/new_ping.c b/src/new_ping.c index 68f0195c5..0df94dd26 100644 --- a/src/new_ping.c +++ b/src/new_ping.c @@ -6,7 +6,8 @@ */ // // TODO: convert it to structure-based code instead of using global variables -// so we can have multiple ping instances running +// so we can have multiple ping instances running. +// One ping for "ping watchdog", second ran from console by user, etc etc // #include "lwip/mem.h" @@ -156,10 +157,12 @@ static u8_t ping_recv(void *arg, struct raw_pcb *pcb, struct pbuf *p, const ip_a return 0; /* don't eat the packet */ } -void ping_raw_init(void){ + +void Main_SetupPingWatchDog(const char *target, int delayBetweenPings) { ///ipaddr_aton("192.168.0.1",&ping_target) - ipaddr_aton("8.8.8.8",&ping_target); + //ipaddr_aton("8.8.8.8",&ping_target); + ipaddr_aton(target,&ping_target); ping_pcb = raw_new(IP_PROTO_ICMP); LWIP_ASSERT("ping_pcb != NULL", ping_pcb != NULL); diff --git a/src/new_pins.h b/src/new_pins.h index 574c52e62..97e2b9127 100644 --- a/src/new_pins.h +++ b/src/new_pins.h @@ -104,7 +104,10 @@ typedef struct mainConfig_s { pinsState_t pins; byte unusedSectorA[256]; byte unusedSectorB[128]; - byte unusedSectorC[128]; + byte unusedSectorC[56]; + int ping_interval; + int ping_seconds; + char ping_host[64]; char initCommandLine[512]; } mainConfig_t; diff --git a/src/user_main.c b/src/user_main.c index f832421dc..f65ab8952 100644 --- a/src/user_main.c +++ b/src/user_main.c @@ -350,6 +350,16 @@ void Main_Init() CMD_Init(); if (g_bootFailures < 2){ + const char *pingTargetServer; + int pingInterval; + + pingTargetServer = CFG_GetPingHost(); + pingInterval = CFG_GetPingIntervalSeconds(); + + if(*pingTargetServer && pingInterval > 0) { + Main_SetupPingWatchDog(pingTargetServer,pingInterval); + } + CMD_ExecuteCommand(CFG_GetShortStartupCommand()); CMD_ExecuteCommand("exec autoexec.bat"); }