diff --git a/lib/config/GWConfig.cpp b/lib/config/GWConfig.cpp index 53b93fb..1758c77 100644 --- a/lib/config/GWConfig.cpp +++ b/lib/config/GWConfig.cpp @@ -7,9 +7,9 @@ bool isTrue(const char * value){ return (strcasecmp(value,"true") == 0); } -class DummyConfig : public ConfigItem{ +class DummyConfig : public GwConfigItem{ public: - DummyConfig():ConfigItem("dummy",""){} + DummyConfig():GwConfigItem("dummy",""){} virtual void fromString(const String v){ }; virtual void reset(){ @@ -17,7 +17,7 @@ class DummyConfig : public ConfigItem{ }; DummyConfig dummyConfig; -String ConfigHandler::toString() const{ +String GwConfigHandler::toString() const{ String rt; rt+="Config: "; for (int i=0;igetName() == name) return configs[i]; } if (!dummy) return NULL; return &dummyConfig; } - -#define PREF_NAME "gwprefs" -ConfigHandler::ConfigHandler(){ - +GwConfigInterface * GwConfigHandler::getConfigItem(const String name, bool dummy) const{ + for (int i=0;igetName() == name) return configs[i]; + } + if (!dummy) return NULL; + return &dummyConfig; } -bool ConfigHandler::loadConfig(){ +#define PREF_NAME "gwprefs" +GwConfigHandler::GwConfigHandler(GwLog *logger){ + this->logger=logger; +} +bool GwConfigHandler::loadConfig(){ + logger->logString("config load"); prefs.begin(PREF_NAME,true); for (int i=0;igetName().c_str(),configs[i]->getDefault()); @@ -58,31 +65,36 @@ bool ConfigHandler::loadConfig(){ prefs.end(); return true; } -bool ConfigHandler::saveConfig(){ +bool GwConfigHandler::saveConfig(){ prefs.begin(PREF_NAME,false); for (int i=0;igetName().c_str(),configs[i]->asString()); } prefs.end(); + logger->logString("saved config"); return true; } -bool ConfigHandler::updateValue(const char *name, const char * value){ - return false; +bool GwConfigHandler::updateValue(const char *name, const char * value){ + GwConfigItem *i=findConfig(name); + if (i == NULL) return false; + logger->logString("update config %s=>%s",name,value); + i->fromString(value); } -bool ConfigHandler::reset(bool save){ +bool GwConfigHandler::reset(bool save){ + logger->logString("reset config"); for (int i=0;ireset(); } if (!save) return true; return saveConfig(); } -String ConfigHandler::getString(const String name){ - ConfigItem *i=findConfig(name); +String GwConfigHandler::getString(const String name){ + GwConfigItem *i=findConfig(name); if (!i) return String(); return i->asString(); } -bool ConfigHandler::getBool(const String name){ - ConfigItem *i=findConfig(name); +bool GwConfigHandler::getBool(const String name){ + GwConfigItem *i=findConfig(name); if (!i) return false; return i->asBoolean(); } \ No newline at end of file diff --git a/lib/config/GWConfig.h b/lib/config/GWConfig.h index 94b346f..3817a7d 100644 --- a/lib/config/GWConfig.h +++ b/lib/config/GWConfig.h @@ -2,27 +2,37 @@ #define _GWCONFIG_H #include #include +#include "GwLog.h" -class ConfigItem{ +class GwConfigInterface{ + public: + virtual String asString() const=0; + virtual const char * asCString() const =0; + virtual bool asBoolean() const = 0; +}; +class GwConfigItem: public GwConfigInterface{ private: String name; String initialValue; String value; public: - ConfigItem(const String &name, const String initialValue){ + GwConfigItem(const String &name, const String initialValue){ this->name=name; this->initialValue=initialValue; this->value=initialValue; } - ConfigItem(const String &name, bool initalValue): - ConfigItem(name,initalValue?String("true"):String("false")){}; - String asString() const{ + GwConfigItem(const String &name, bool initalValue): + GwConfigItem(name,initalValue?String("true"):String("false")){}; + virtual String asString() const{ return value; } + virtual const char * asCString() const{ + return value.c_str(); + }; virtual void fromString(const String v){ value=v; }; - bool asBoolean() const{ + virtual bool asBoolean() const{ return strcasecmp(value.c_str(),"true") == 0; } String getName() const{ @@ -40,9 +50,10 @@ class ConfigItem{ }; -class ConfigHandler{ +class GwConfigHandler{ private: Preferences prefs; + GwLog *logger; public: public: const String sendUsb="sendUsb"; @@ -50,7 +61,7 @@ class ConfigHandler{ const String wifiClient="wifiClient"; const String wifiPass="wifiPass"; const String wifiSSID="wifiSSID"; - ConfigHandler(); + GwConfigHandler(GwLog *logger); bool loadConfig(); bool saveConfig(); bool updateValue(const char *name, const char * value); @@ -59,17 +70,18 @@ class ConfigHandler{ String toJson() const; String getString(const String name); bool getBool(const String name); - ConfigItem * findConfig(const String name, bool dummy=false); + GwConfigItem * findConfig(const String name, bool dummy=false); + GwConfigInterface * getConfigItem(const String name, bool dummy=false) const; private: - ConfigItem* configs[5]={ - new ConfigItem(sendUsb,true), - new ConfigItem (receiveUsb,false), - new ConfigItem (wifiClient,false), - new ConfigItem (wifiSSID,""), - new ConfigItem (wifiPass,"") + GwConfigItem* configs[5]={ + new GwConfigItem(sendUsb,true), + new GwConfigItem (receiveUsb,false), + new GwConfigItem (wifiClient,false), + new GwConfigItem (wifiSSID,""), + new GwConfigItem (wifiPass,"") }; int getNumConfig() const{ - return sizeof(configs)/sizeof(ConfigItem*); + return sizeof(configs)/sizeof(GwConfigItem*); } }; #endif \ No newline at end of file diff --git a/lib/log/GWLog.cpp b/lib/log/GWLog.cpp new file mode 100644 index 0000000..dcc71b6 --- /dev/null +++ b/lib/log/GWLog.cpp @@ -0,0 +1,14 @@ +#include "GwLog.h" + +GwLog::GwLog(bool logSerial){ + this->logSerial=logSerial; +} +void GwLog::logString(const char *fmt,...){ + va_list args; + va_start(args,fmt); + vsnprintf(buffer,99,fmt,args); + if (logSerial){ + Serial.print("LOG: "); + Serial.println(buffer); + } +} \ No newline at end of file diff --git a/lib/log/GwLog.h b/lib/log/GwLog.h new file mode 100644 index 0000000..e9ad797 --- /dev/null +++ b/lib/log/GwLog.h @@ -0,0 +1,12 @@ +#ifndef _GWLOG_H +#define _GWLOG_H +#include +class GwLog{ + private: + char buffer[100]; + bool logSerial=false; + public: + GwLog(bool logSerial); + void logString(const char *fmt,...); +}; +#endif \ No newline at end of file diff --git a/lib/wifi/GWWifi.h b/lib/wifi/GWWifi.h new file mode 100644 index 0000000..b823907 --- /dev/null +++ b/lib/wifi/GWWifi.h @@ -0,0 +1,21 @@ +#ifndef _GWWIFI_H +#define _GWWIFI_H +#include +#include +class GwWifi{ + private: + const GwConfigHandler *config; + GwLog *logger; + const GwConfigInterface *wifiClient; + const GwConfigInterface *wifiSSID; + const GwConfigInterface *wifiPass; + bool connectInternal(); + long lastConnectStart=0; + public: + GwWifi(const GwConfigHandler *config,GwLog *log); + void setup(); + void loop(); + bool clientConnected(); + bool connectClient(); +}; +#endif \ No newline at end of file diff --git a/lib/wifi/GwWifi.cpp b/lib/wifi/GwWifi.cpp new file mode 100644 index 0000000..f2371f3 --- /dev/null +++ b/lib/wifi/GwWifi.cpp @@ -0,0 +1,56 @@ +#include "GWWifi.h" + + +const char *AP_ssid = "ESP32NMEA2K"; // ESP32 as AP +const char *AP_password = "esp32nmea2k"; //too short - so no pass + +GwWifi::GwWifi(const GwConfigHandler *config,GwLog *log){ + this->config=config; + this->logger=log; + wifiClient=config->getConfigItem(config->wifiClient,true); + wifiSSID=config->getConfigItem(config->wifiSSID,true); + wifiPass=config->getConfigItem(config->wifiPass,true); +} +void GwWifi::setup(){ + logger->logString("Wifi setup"); + + IPAddress AP_local_ip(192, 168, 15, 1); // Static address for AP + IPAddress AP_gateway(192, 168, 15, 1); + IPAddress AP_subnet(255, 255, 255, 0); + WiFi.mode(WIFI_AP_STA); //enable both AP and client + WiFi.softAP(AP_ssid,AP_password); + delay(100); + WiFi.softAPConfig(AP_local_ip, AP_gateway, AP_subnet); + logger->logString("WifiAP created: ssid=%s,adress=%s", + AP_ssid, + WiFi.softAPIP().toString().c_str() + ); + connectInternal(); +} +bool GwWifi::connectInternal(){ + if (wifiClient->asBoolean()){ + logger->logString("creating wifiClient ssid=%s",wifiSSID->asString().c_str()); + WiFi.begin(wifiSSID->asCString(),wifiPass->asCString()); + lastConnectStart=millis(); + return true; + } + return false; +} +#define RETRY_MILLIS 5000 +void GwWifi::loop(){ + if (wifiClient->asBoolean() && ! clientConnected()){ + long now=millis(); + if (lastConnectStart > now || (lastConnectStart+RETRY_MILLIS) < now){ + logger->logString("wifiClient: retry connect to %s",wifiSSID->asCString()); + WiFi.disconnect(); + connectInternal(); + } + } +} +bool GwWifi::clientConnected(){ + return WiFi.status() == WL_CONNECTED; +}; +bool GwWifi::connectClient(){ + WiFi.disconnect(); + return connectInternal(); +} \ No newline at end of file diff --git a/src/main.cpp b/src/main.cpp index 0191443..9c0a1f3 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -23,6 +23,7 @@ #define ESP32_CAN_RX_PIN GPIO_NUM_4 // Set CAN RX port to 4 #endif +#define LOG_SERIAL true #include #include // This will automatically choose right CAN library and create suitable NMEA2000 object @@ -37,7 +38,10 @@ #include "List.h" #include "BoatData.h" +#include "GwLog.h" #include "GWConfig.h" +#include "GWWifi.h" + @@ -47,29 +51,11 @@ #define HighTempAlarm 12 // Alarm level for fridge temperature (higher) #define LowVoltageAlarm 11 // Alarm level for battery voltage (lower) -#define ADC_Calibration_Value 34.3 // The real value depends on the true resistor values for the ADC input (100K / 27 K) -#define WLAN_CLIENT 0 // Set to 1 to enable client network. 0 to act as AP only +GwLog logger(LOG_SERIAL); +GwConfigHandler config(&logger); +GwWifi gwWifi(&config,&logger); -ConfigHandler config; - -// Wifi cofiguration Client and Access Point -const char *AP_ssid = "MyESP32"; // ESP32 as AP -const char *CL_ssid = "MyWLAN"; // ESP32 as client in network - -const char *AP_password = "appassw"; // AP password -const char *CL_password = "clientpw"; // Client password - -// Put IP address details here -IPAddress AP_local_ip(192, 168, 15, 1); // Static address for AP -IPAddress AP_gateway(192, 168, 15, 1); -IPAddress AP_subnet(255, 255, 255, 0); - -IPAddress CL_local_ip(192, 168, 1, 10); // Static address for Client Network. Please adjust to your AP IP and DHCP range! -IPAddress CL_gateway(192, 168, 1, 1); -IPAddress CL_subnet(255, 255, 255, 0); - -int wifiType = 0; // 0= Client 1= AP //counter int numCan=0; @@ -175,6 +161,8 @@ void js_status(){ DynamicJsonDocument status(50); status["numcan"]=numCan; status["version"]=VERSION; + status["wifiConnected"]=gwWifi.clientConnected(); + status["clientIP"]=WiFi.localIP().toString(); String buf; serializeJson(status,buf); webserver.send(200,F("application/json"),buf); @@ -184,7 +172,7 @@ void js_config(){ webserver.send(200,F("application/json"),config.toJson()); } -void web_config(){ +void web_setConfig(){ } void handleNotFound() @@ -193,14 +181,14 @@ void handleNotFound() } -ConfigItem *sendUsb=NULL; +GwConfigInterface *sendUsb=NULL; void setup() { uint8_t chipid[6]; uint32_t id = 0; int i = 0; - int wifi_retry = 0; + // Init USB serial port @@ -208,47 +196,10 @@ void setup() { Serial.println("Starting..."); config.loadConfig(); Serial.println(config.toString()); - sendUsb=config.findConfig(config.sendUsb,true); - // Init AIS serial port 2 - //Serial2.begin(baudrate, rs_config); - //NMEA0183.Begin(&Serial2, 3, baudrate); + sendUsb=config.getConfigItem(config.sendUsb,true); + + gwWifi.setup(); - if (WLAN_CLIENT == 1) { - Serial.println("Start WLAN Client"); // WiFi Mode Client - - WiFi.config(CL_local_ip, CL_gateway, CL_subnet, CL_gateway); - delay(100); - WiFi.begin(CL_ssid, CL_password); - - while (WiFi.status() != WL_CONNECTED && wifi_retry < 20) { // Check connection, try 10 seconds - wifi_retry++; - delay(5000); - Serial.print("."); - } - } - - if (WiFi.status() != WL_CONNECTED) { // No client connection start AP - // Init wifi connection - Serial.println("Start WLAN AP"); // WiFi Mode AP - WiFi.mode(WIFI_AP); - WiFi.softAP(AP_ssid, AP_password); - delay(100); - WiFi.softAPConfig(AP_local_ip, AP_gateway, AP_subnet); - IPAddress IP = WiFi.softAPIP(); - Serial.println(""); - Serial.print("AP IP address: "); - Serial.println(IP); - wifiType = 1; - - } else { // Wifi Client connection was sucessfull - - Serial.println(""); - Serial.println("WiFi client connected"); - Serial.println("IP client address: "); - Serial.println(WiFi.localIP()); - } - - // Start TCP server server.begin(); @@ -477,6 +428,7 @@ void loop() { int wifi_retry; webserver.handleClient(); + gwWifi.loop(); handle_json(); if (NMEA0183.GetMessage(NMEA0183Msg)) { // Get AIS NMEA sentences from serial2 @@ -517,22 +469,4 @@ void loop() { Serial.read(); } - - - if (wifiType == 0) { // Check connection if working as client - wifi_retry = 0; - while (WiFi.status() != WL_CONNECTED && wifi_retry < 5 ) { // Connection lost, 5 tries to reconnect - wifi_retry++; - Serial.println("WiFi not connected. Try to reconnect"); - WiFi.disconnect(); - WiFi.mode(WIFI_OFF); - WiFi.mode(WIFI_STA); - WiFi.begin(CL_ssid, CL_password); - delay(1000); - } - if (wifi_retry >= 5) { - Serial.println("\nReboot"); // Did not work -> restart ESP32 - ESP.restart(); - } - } } diff --git a/web/index.html b/web/index.html index 991ea60..52322cc 100644 --- a/web/index.html +++ b/web/index.html @@ -57,6 +57,14 @@ span.label { # CAN messages --- +
+ wifi client connected + --- +
+
+ wifi client IP + --- +