diff --git a/src/config/settings.h b/src/config/settings.h index fe0053a9..f130434c 100644 --- a/src/config/settings.h +++ b/src/config/settings.h @@ -63,6 +63,19 @@ typedef struct { uint8_t gateway[4]; // standard gateway } cfgIp_t; + +#if defined(ETHERNET) +typedef struct { + bool enabled; + uint8_t pinCs; + uint8_t pinSclk; + uint8_t pinMiso; + uint8_t pinMosi; + uint8_t pinIrq; + uint8_t pinRst; +} cfgEth_t; +#endif + typedef struct { char deviceName[DEVNAME_LEN]; char adminPwd[PWD_LEN]; @@ -72,15 +85,16 @@ typedef struct { uint8_t region; int8_t timezone; + char apPwd[PWD_LEN]; #if !defined(ETHERNET) // wifi char stationSsid[SSID_LEN]; char stationPwd[PWD_LEN]; - char apPwd[PWD_LEN]; bool isHidden; #endif /* !defined(ETHERNET) */ cfgIp_t ip; + cfgEth_t eth; } cfgSys_t; typedef struct { @@ -393,7 +407,17 @@ class settings { snprintf(mCfg.sys.apPwd, PWD_LEN, WIFI_AP_PWD); mCfg.sys.isHidden = false; } - #endif /* !defined(ETHERNET) */ + #endif + + #if defined(ETHERNET) + mCfg.sys.eth.enabled = false; + mCfg.sys.eth.pinCs = DEF_ETH_CS_PIN; + mCfg.sys.eth.pinSclk = DEF_ETH_SCK_PIN; + mCfg.sys.eth.pinMiso = DEF_ETH_MISO_PIN; + mCfg.sys.eth.pinMosi = DEF_ETH_MOSI_PIN; + mCfg.sys.eth.pinIrq = DEF_ETH_IRQ_PIN; + mCfg.sys.eth.pinRst = DEF_ETH_RST_PIN; + #endif snprintf(mCfg.sys.deviceName, DEVNAME_LEN, DEF_DEVICE_NAME); mCfg.sys.region = 0; // Europe @@ -544,6 +568,16 @@ class settings { ah::ip2Char(mCfg.sys.ip.dns1, buf); obj[F("dns1")] = String(buf); ah::ip2Char(mCfg.sys.ip.dns2, buf); obj[F("dns2")] = String(buf); ah::ip2Char(mCfg.sys.ip.gateway, buf); obj[F("gtwy")] = String(buf); + + #if defined(ETHERNET) + obj[F("en")] = mCfg.sys.eth.enabled; + obj[F("cs")] = mCfg.sys.eth.pinCs; + obj[F("sclk")] = mCfg.sys.eth.pinSclk; + obj[F("miso")] = mCfg.sys.eth.pinMiso; + obj[F("mosi")] = mCfg.sys.eth.pinMosi; + obj[F("irq")] = mCfg.sys.eth.pinIrq; + obj[F("rst")] = mCfg.sys.eth.pinRst; + #endif } else { #if !defined(ETHERNET) getChar(obj, F("ssid"), mCfg.sys.stationSsid, SSID_LEN); @@ -567,6 +601,16 @@ class settings { if(mCfg.sys.protectionMask == 0) mCfg.sys.protectionMask = DEF_PROT_INDEX | DEF_PROT_LIVE | DEF_PROT_SERIAL | DEF_PROT_SETUP | DEF_PROT_UPDATE | DEF_PROT_SYSTEM | DEF_PROT_API | DEF_PROT_MQTT | DEF_PROT_HISTORY; + + #if defined(ETHERNET) + getVal(obj, F("en"), &mCfg.sys.eth.enabled); + getVal(obj, F("cs"), &mCfg.sys.eth.pinCs); + getVal(obj, F("sclk"), &mCfg.sys.eth.pinSclk); + getVal(obj, F("miso"), &mCfg.sys.eth.pinMiso); + getVal(obj, F("mosi"), &mCfg.sys.eth.pinMosi); + getVal(obj, F("irq"), &mCfg.sys.eth.pinIrq); + getVal(obj, F("rst"), &mCfg.sys.eth.pinRst); + #endif } } diff --git a/src/eth/ahoyeth.cpp b/src/eth/ahoyeth.cpp index 83f0aef0..497a542f 100644 --- a/src/eth/ahoyeth.cpp +++ b/src/eth/ahoyeth.cpp @@ -31,7 +31,7 @@ void ahoyeth::setup(settings_t *config, uint32_t *utcTimestamp, OnNetworkCB onNe WiFi.onEvent([this](WiFiEvent_t event, arduino_event_info_t info) -> void { this->onEthernetEvent(event, info); }); Serial.flush(); - mEthSpi.begin(DEF_ETH_MISO_PIN, DEF_ETH_MOSI_PIN, DEF_ETH_SCK_PIN, DEF_ETH_CS_PIN, DEF_ETH_IRQ_PIN, DEF_ETH_RST_PIN); + mEthSpi.begin(config->sys.eth.pinMiso, config->sys.eth.pinMosi, config->sys.eth.pinSclk, config->sys.eth.pinCs, config->sys.eth.pinIrq, config->sys.eth.pinRst); if(mConfig->sys.ip.ip[0] != 0) { IPAddress ip(mConfig->sys.ip.ip); diff --git a/src/network/AhoyEthernet.h b/src/network/AhoyEthernet.h new file mode 100644 index 00000000..c56b4338 --- /dev/null +++ b/src/network/AhoyEthernet.h @@ -0,0 +1,82 @@ +//----------------------------------------------------------------------------- +// 2024 Ahoy, https://ahoydtu.de +// Creative Commons - https://creativecommons.org/licenses/by-nc-sa/4.0/deed +//----------------------------------------------------------------------------- + +#ifndef __AHOY_ETHERNET_H__ +#define __AHOY_ETHERNET_H__ + +#include +#include +#include +#include "AhoyEthernetSpi.h" +#include "AhoyEthernet.h" + +class AhoyEthernet : public AhoyNetwork { + public: + void begin() override { + setupIp([this](IPAddress ip, IPAddress gateway, IPAddress mask, IPAddress dns1, IPAddress dns2) -> bool { + return ETH.config(ip, gateway, mask, dns1, dns2); + }); + } + + void tickNetworkLoop() override { + switch(mState) { + case NetworkState::DISCONNECTED: + break; + } + } + + private: + + /*switch (event) { + case ARDUINO_EVENT_ETH_START: + DPRINTLN(DBG_VERBOSE, F("ETH Started")); + + if(String(mConfig->sys.deviceName) != "") + ETH.setHostname(mConfig->sys.deviceName); + else + ETH.setHostname(F("ESP32_W5500")); + break; + + case ARDUINO_EVENT_ETH_CONNECTED: + DPRINTLN(DBG_VERBOSE, F("ETH Connected")); + break; + + case ARDUINO_EVENT_ETH_GOT_IP: + if (!mEthConnected) { + welcome(ETH.localIP().toString(), F(" (Station)")); + + mEthConnected = true; + mOnNetworkCB(true); + } + + if (!MDNS.begin(mConfig->sys.deviceName)) { + DPRINTLN(DBG_ERROR, F("Error setting up MDNS responder!")); + } else { + DBGPRINT(F("mDNS established: ")); + DBGPRINT(mConfig->sys.deviceName); + DBGPRINTLN(F(".local")); + } + break; + + case ARDUINO_EVENT_ETH_DISCONNECTED: + DPRINTLN(DBG_INFO, F("ETH Disconnected")); + mEthConnected = false; + mUdp.close(); + mOnNetworkCB(false); + break; + + case ARDUINO_EVENT_ETH_STOP: + DPRINTLN(DBG_INFO, F("ETH Stopped")); + mEthConnected = false; + mUdp.close(); + mOnNetworkCB(false); + break; + + default: + break; + }*/ +}; + +#endif /*__AHOY_ETHERNET_H__*/ diff --git a/src/eth/ethSpi.h b/src/network/AhoyEthernetSpi.h similarity index 96% rename from src/eth/ethSpi.h rename to src/network/AhoyEthernetSpi.h index 1339c8ec..12e58e4d 100644 --- a/src/eth/ethSpi.h +++ b/src/network/AhoyEthernetSpi.h @@ -1,6 +1,6 @@ //----------------------------------------------------------------------------- -// 2024 Ahoy, https://www.mikrocontroller.net/topic/525778 -// Creative Commons - http://creativecommons.org/licenses/by-nc-sa/3.0/de/ +// 2024 Ahoy, https://ahoydtu.de +// Creative Commons - https://creativecommons.org/licenses/by-nc-sa/4.0/deed //----------------------------------------------------------------------------- #if defined(ETHERNET) @@ -18,10 +18,10 @@ void tcpipInit(); void add_esp_interface_netif(esp_interface_t interface, esp_netif_t* esp_netif); -class EthSpi { +class AhoyEthernetSpi { public: - EthSpi() : + AhoyEthernetSpi() : eth_handle(nullptr), eth_netif(nullptr) {} diff --git a/src/network/AhoyNetwork.h b/src/network/AhoyNetwork.h new file mode 100644 index 00000000..01d7cd8c --- /dev/null +++ b/src/network/AhoyNetwork.h @@ -0,0 +1,194 @@ +//----------------------------------------------------------------------------- +// 2024 Ahoy, https://ahoydtu.de +// Creative Commons - https://creativecommons.org/licenses/by-nc-sa/4.0/deed +//----------------------------------------------------------------------------- + +#ifndef __AHOY_NETWORK_H__ +#define __AHOY_NETWORK_H__ + +#include "AhoyNetworkHelper.h" +#include +#include "../config/settings.h" +#include "../utils/helper.h" + +#if defined(ESP32) +#include +#else +#include +#endif + +#define NTP_PACKET_SIZE 48 + +class AhoyNetwork { + public: + typedef std::function OnNetworkCB; + typedef std::function OnTimeCB; + + public: + void setup(settings_t *config, uint32_t *utcTimestamp, OnNetworkCB onNetworkCB, OnTimeCB onTimeCB) { + mConfig = config; + mUtcTimestamp = utcTimestamp; + mOnNetworkCB = onNetworkCB; + mOnTimeCB = onTimeCB; + + #if defined(ESP32) + WiFi.onEvent([this](WiFiEvent_t event) -> void { + this->OnEvent(event); + }); + #else + wifiConnectHandler = WiFi.onStationModeConnected( + [this](const WiFiEventStationModeConnected& event) -> void { + OnEvent(SYSTEM_EVENT_STA_CONNECTED); + }); + wifiGotIPHandler = WiFi.onStationModeGotIP( + [this](const WiFiEventStationModeGotIP& event) -> void { + OnEvent(SYSTEM_EVENT_STA_GOT_IP); + }); + wifiDisconnectHandler = WiFi.onStationModeDisconnected( + [this](const WiFiEventStationModeDisconnected& event) -> void { + OnEvent(SYSTEM_EVENT_STA_DISCONNECTED); + }); + #endif + } + + bool isConnected() const { + return (mStatus == NetworkState.CONNECTED); + } + + bool updateNtpTime(void) { + if(CONNECTED != mStatus) + return; + + if (!mUdp.connected()) { + IPAddress timeServer; + if (!WiFi.hostByName(mConfig->ntp.addr, timeServer)) + return false; + if (!mUdp.connect(timeServer, mConfig->ntp.port)) + return false; + } + + mUdp.onPacket([this](AsyncUDPPacket packet) { + this->handleNTPPacket(packet); + }); + sendNTPpacket(timeServer); + + return true; + } + + public: + virtual void begin() = 0; + virtual void tickNetworkLoop() = 0; + virtual void connectionEvent(WiFiStatus_t status) = 0; + + protected: + void setupIp(void) { + if(mConfig->sys.ip.ip[0] != 0) { + IPAddress ip(mConfig->sys.ip.ip); + IPAddress mask(mConfig->sys.ip.mask); + IPAddress dns1(mConfig->sys.ip.dns1); + IPAddress dns2(mConfig->sys.ip.dns2); + IPAddress gateway(mConfig->sys.ip.gateway); + if(!ETH.config(ip, gateway, mask, dns1, dns2)) + DPRINTLN(DBG_ERROR, F("failed to set static IP!")); + } + } + + void OnEvent(WiFiEvent_t event) { + switch(event) { + case SYSTEM_EVENT_STA_CONNECTED: + [[fallthrough]]; + case ARDUINO_EVENT_ETH_CONNECTED: + if(NetworkState::CONNECTED != mStatus) { + mStatus = NetworkState::CONNECTED; + DPRINTLN(DBG_INFO, F("Network connected")); + } + break; + + case SYSTEM_EVENT_STA_GOT_IP: + [[fallthrough]]; + case ARDUINO_EVENT_ETH_GOT_IP: + mStatus = NetworkState::GOT_IP; + break; + + case ARDUINO_EVENT_WIFI_STA_LOST_IP: + [[fallthrough]]; + case ARDUINO_EVENT_WIFI_STA_STOP: + [[fallthrough]]; + case SYSTEM_EVENT_STA_DISCONNECTED: + [[fallthrough]]; + case ARDUINO_EVENT_ETH_STOP: + [[fallthrough]]; + case ARDUINO_EVENT_ETH_DISCONNECTED: + mStatus = NetworkState::DISCONNECTED; + break; + + default: + break; + } + } + + private: + void sendNTPpacket(IPAddress& address) { + //DPRINTLN(DBG_VERBOSE, F("wifi::sendNTPpacket")); + uint8_t buf[NTP_PACKET_SIZE]; + memset(buf, 0, NTP_PACKET_SIZE); + + buf[0] = 0b11100011; // LI, Version, Mode + buf[1] = 0; // Stratum + buf[2] = 6; // Max Interval between messages in seconds + buf[3] = 0xEC; // Clock Precision + // bytes 4 - 11 are for Root Delay and Dispersion and were set to 0 by memset + buf[12] = 49; // four-byte reference ID identifying + buf[13] = 0x4E; + buf[14] = 49; + buf[15] = 52; + + //mUdp.beginPacket(address, 123); // NTP request, port 123 + mUdp.write(buf, NTP_PACKET_SIZE); + //mUdp.endPacket(); + } + + void handleNTPPacket(AsyncUDPPacket packet) { + char buf[80]; + + memcpy(buf, packet.data(), sizeof(buf)); + + unsigned long highWord = word(buf[40], buf[41]); + unsigned long lowWord = word(buf[42], buf[43]); + + // combine the four bytes (two words) into a long integer + // this is NTP time (seconds since Jan 1 1900): + unsigned long secsSince1900 = highWord << 16 | lowWord; + + *mUtcTimestamp = secsSince1900 - 2208988800UL; // UTC time + DPRINTLN(DBG_INFO, "[NTP]: " + ah::getDateTimeStr(*mUtcTimestamp) + " UTC"); + mOnTimeCB(true); + mUdp.close(); + } + + protected: + enum class NetworkState : uint8_t { + DISCONNECTED, + CONNECTING, + CONNECTED, + IN_AP_MODE, + GOT_IP, + IN_STA_MODE, + RESET, + SCAN_READY + }; + + protected: + settings_t *mConfig = nullptr; + uint32_t *mUtcTimestamp = nullptr; + + OnNetworkCB mOnNetworkCB; + OnTimeCB mOnTimeCB; + + NetworkState mStatus = NetworkState.DISCONNECTED; + + WiFiUDP mUdp; // for time server + DNSServer mDns; +}; + +#endif /*__AHOY_NETWORK_H__*/ diff --git a/src/network/AhoyNetworkHelper.h b/src/network/AhoyNetworkHelper.h new file mode 100644 index 00000000..ab23f5bc --- /dev/null +++ b/src/network/AhoyNetworkHelper.h @@ -0,0 +1,29 @@ +//----------------------------------------------------------------------------- +// 2024 Ahoy, https://ahoydtu.de +// Creative Commons - https://creativecommons.org/licenses/by-nc-sa/4.0/deed +//----------------------------------------------------------------------------- + +#ifndef __AHOY_NETWORK_HELPER_H__ +#define __AHOY_NETWORK_HELPER_H__ + +#include "../utils/dbg.h" +#include +#include +#include +#include + +namespace ah { + void welcome(String ip, String info) { + DBGPRINTLN(F("\n\n-------------------")); + DBGPRINTLN(F("Welcome to AHOY!")); + DBGPRINT(F("\npoint your browser to http://")); + DBGPRINT(ip); + DBGPRINT(" ("); + DBGPRINT(info); + DBGPRINTLN(")"); + DBGPRINTLN(F("to configure your device")); + DBGPRINTLN(F("-------------------\n")); + } +} + +#endif /*__AHOY_NETWORK_HELPER_H__*/ diff --git a/src/network/AhoyWifiAp.h b/src/network/AhoyWifiAp.h new file mode 100644 index 00000000..f919e030 --- /dev/null +++ b/src/network/AhoyWifiAp.h @@ -0,0 +1,70 @@ +//----------------------------------------------------------------------------- +// 2024 Ahoy, https://ahoydtu.de +// Creative Commons - https://creativecommons.org/licenses/by-nc-sa/4.0/deed +//----------------------------------------------------------------------------- + +#ifndef __AHOY_WIFI_AP_H__ +#define __AHOY_WIFI_AP_H__ + +#include "../utils/dbg.h" +#include +#include "../config/settings.h" +#include "AhoyNetworkHelper.h" + +class AhoyWifiAp { + public: + AhoyWifiAp() : mIp(192, 168, 4, 1) {} + + void setup(cfgSys_t *cfg) { + mCfg = cfg; + } + + void tickLoop() { + if(mEnabled) + mDns.processNextRequest(); + } + + void enable() { + ah::welcome(mIp.toString(), String(F("Password: ") + String(mCfg->apPwd))); + if('\0' == mCfg->deviceName[0]) + snprintf(mCfg->deviceName, DEVNAME_LEN, "%s", DEF_DEVICE_NAME); + WiFi.hostname(mCfg->deviceName); + + #if defined(ETHERNET) + WiFi.mode(WIFI_AP); + #else + WiFi.mode(WIFI_AP_STA); + #endif + WiFi.softAPConfig(mIp, mIp, IPAddress(255, 255, 255, 0)); + WiFi.softAP(WIFI_AP_SSID, mCfg->apPwd); + + mDns.start(53, "*", mIp); + + mEnabled = true; + tickLoop(); + } + + void disable() { + mDns.stop(); + WiFi.softAPdisconnect(); + #if defined(ETHERNET) + WiFi.mode(WIFI_OFF); + #else + WiFi.mode(WIFI_STA); + #endif + + mEnabled = false; + } + + bool getEnable() const { + return mEnabled; + } + + private: + cfgSys_t *mCfg = nullptr; + DNSServer mDns; + IPAddress mIp; + bool mEnabled = false; +}; + +#endif /*__AHOY_WIFI_AP_H__*/ diff --git a/src/web/RestApi.h b/src/web/RestApi.h index 399ea91f..197c6982 100644 --- a/src/web/RestApi.h +++ b/src/web/RestApi.h @@ -381,6 +381,8 @@ class RestApi { obj[F("hidd")] = mConfig->sys.isHidden; obj[F("mac")] = WiFi.macAddress(); obj[F("wifi_channel")] = WiFi.channel(); + #else + getEthernet(obj.createNestedObject(F("eth"))); #endif /* !defined(ETHERNET) */ obj[F("device_name")] = mConfig->sys.deviceName; obj[F("dark_mode")] = (bool)mConfig->sys.darkMode; @@ -762,6 +764,18 @@ class RestApi { } #endif + #if defined(ETHERNET) + void getEthernet(JsonObject obj) { + obj[F("en")] = mConfig->sys.eth.enabled; + obj[F("cs")] = mConfig->sys.eth.pinCs; + obj[F("sclk")] = mConfig->sys.eth.pinSclk; + obj[F("miso")] = mConfig->sys.eth.pinMiso; + obj[F("mosi")] = mConfig->sys.eth.pinMosi; + obj[F("irq")] = mConfig->sys.eth.pinIrq; + obj[F("reset")] = mConfig->sys.eth.pinRst; + } + #endif + void getRadioNrf(JsonObject obj) { obj[F("en")] = (bool) mConfig->nrf.enabled; if(mConfig->nrf.enabled) { diff --git a/src/web/html/setup.html b/src/web/html/setup.html index b6b8929e..8f3fe07c 100644 --- a/src/web/html/setup.html +++ b/src/web/html/setup.html @@ -245,7 +245,7 @@

{#MQTT_NOTE}

{#INTERVAL}
-
+
Discovery Config (homeassistant)
@@ -270,6 +270,10 @@

{#RADIO} (CMT2300A)

+ +

Ethernet

+
+
@@ -986,7 +990,7 @@ ) } - function parseNrfRadio(obj, objPin, type, system) { + function parseNrfRadio(obj, objPin) { var e = document.getElementById("rf24"); var en = inp("nrfEnable", null, null, ["cb"], "nrfEnable", "checkbox"); en.checked = obj["en"]; @@ -1013,11 +1017,11 @@ ]) ); - if ("ESP8266" == type) { - pins = [['cs', 'pinCs'], ['ce', 'pinCe'], ['irq', 'pinIrq']]; - } else { - pins = [['cs', 'pinCs'], ['ce', 'pinCe'], ['irq', 'pinIrq'], ['sclk', 'pinSclk'], ['mosi', 'pinMosi'], ['miso', 'pinMiso']]; - } + /*IF_ESP32*/ + var pins = [['cs', 'pinCs'], ['ce', 'pinCe'], ['irq', 'pinIrq'], ['sclk', 'pinSclk'], ['mosi', 'pinMosi'], ['miso', 'pinMiso']]; + /*ELSE*/ + var pins = [['cs', 'pinCs'], ['ce', 'pinCe'], ['irq', 'pinIrq']]; + /*ENDIF_ESP32*/ for(p of pins) { e.append( ml("div", {class: "row mb-3"}, [ @@ -1031,7 +1035,7 @@ } /*IF_ESP32*/ - function parseCmtRadio(obj, type, system) { + function parseCmtRadio(obj) { var e = document.getElementById("cmt"); var en = inp("cmtEnable", null, null, ["cb"], "cmtEnable", "checkbox"); var pinList = esp32pins; @@ -1046,7 +1050,6 @@ /*ENDIF_ESP32-C3*/ en.checked = obj["en"]; - e.replaceChildren ( ml("div", {class: "row mb-3"}, [ ml("div", {class: "col-8 col-sm-3 my-2"}, "{#CMT_ENABLE}"), @@ -1073,6 +1076,42 @@ } /*ENDIF_ESP32*/ + /*IF_ETHERNET*/ + function parseEth(obj) { + var e = document.getElementById("eth"); + var en = inp("ethEn", null, null, ["cb"], "ethEn", "checkbox"); + var pinList = esp32pins; + /*IF_ESP32-S2*/ + pinList = esp32sXpins; + /*ENDIF_ESP32-S2*/ + /*IF_ESP32-S3*/ + pinList = esp32sXpins; + /*ENDIF_ESP32-S3*/ + /*IF_ESP32-C3*/ + pinList = esp32c3pins; + /*ENDIF_ESP32-C3*/ + + en.checked = obj["en"]; + e.replaceChildren ( + ml("div", {class: "row mb-3"}, [ + ml("div", {class: "col-8 col-sm-3 my-2"}, "{#ETH_ENABLE}"), + ml("div", {class: "col-4 col-sm-9"}, en) + ]) + ); + pins = [['cs', 'ethCs'], ['sclk', 'ethSclk'], ['miso', 'ethMiso'], ['mosi', 'ethMosi'], ['irq', 'ethIrq'], ['reset', 'ethRst']]; + for(p of pins) { + e.append( + ml("div", {class: "row mb-3"}, [ + ml("div", {class: "col-12 col-sm-3 my-2"}, p[0].toUpperCase()), + ml("div", {class: "col-12 col-sm-9"}, + sel(p[1], pinList, obj[p[0]]) + ) + ]) + ); + } + } + /*ENDIF_ETHERNET*/ + function parseSerial(obj) { var e = document.getElementById("serialCb") var l = [["serEn", "show_live_data", "{#LOG_PRINT_INVERTER_DATA}"], ["serDbg", "debug", "{#LOG_SERIAL_DEBUG}"], ["priv", "priv", "{#LOG_PRIVACY_MODE}"], ["wholeTrace", "wholeTrace", "{#LOG_PRINT_TRACES}"], ["log2mqtt", "log2mqtt", "{#LOG_TO_MQTT}"]] @@ -1253,10 +1292,13 @@ parseNtp(root["ntp"]); parseSun(root["sun"]); parsePinout(root["pinout"], root["system"]["esp_type"], root["system"]); - parseNrfRadio(root["radioNrf"], root["pinout"], root["system"]["esp_type"], root["system"]); + parseNrfRadio(root["radioNrf"], root["pinout"]); /*IF_ESP32*/ - parseCmtRadio(root["radioCmt"], root["system"]["esp_type"], root["system"]); + parseCmtRadio(root["radioCmt"]); /*ENDIF_ESP32*/ + /*IF_ETHERNET*/ + parseEth(root.system.eth) + /*ENDIF_ETHERNET*/ parseSerial(root["serial"]); /*IF_PLUGIN_DISPLAY*/ parseDisplay(root["display"], root["system"]["esp_type"], root["system"]); diff --git a/src/web/lang.json b/src/web/lang.json index f1723688..419dd4f4 100644 --- a/src/web/lang.json +++ b/src/web/lang.json @@ -723,6 +723,11 @@ "en": "CMT2300A radio enable", "de": "CMT2300A Funkmodul aktivieren" }, + { + "token": "ETH_ENABLE", + "en": "Ethernet enable", + "de": "Ethernet aktivieren" + }, { "token": "DISP_NONE", "en": "None", diff --git a/src/web/web.h b/src/web/web.h index 3e7d00a8..f4389163 100644 --- a/src/web/web.h +++ b/src/web/web.h @@ -37,14 +37,19 @@ #define WEB_SERIAL_BUF_SIZE 2048 -const char* const pinArgNames[] = {"pinCs", "pinCe", "pinIrq", "pinSclk", "pinMosi", "pinMiso", "pinLed0", "pinLed1", "pinLed2", "pinLedHighActive", "pinLedLum", "pinCmtSclk", "pinSdio", "pinCsb", "pinFcsb", "pinGpio3"}; +const char* const pinArgNames[] = { + "pinCs", "pinCe", "pinIrq", "pinSclk", "pinMosi", "pinMiso", "pinLed0", + "pinLed1", "pinLed2", "pinLedHighActive", "pinLedLum", "pinCmtSclk", + "pinSdio", "pinCsb", "pinFcsb", "pinGpio3" + #if defined (ETHERNET) + , "ethCs", "ethSclk", "ethMiso", "ethMosi", "ethIrq", "ethRst" + #endif +}; template class Web { public: - Web(void) : mWeb(80), mEvts("/events") { - memset(mSerialBuf, 0, WEB_SERIAL_BUF_SIZE); - } + Web(void) : mWeb(80), mEvts("/events") {} void setup(IApp *app, HMSYSTEM *sys, settings_t *config) { mApp = app; @@ -101,11 +106,17 @@ class Web { void tickSecond() { if (mSerialClientConnnected) { + if(nullptr == mSerialBuf) + return; + if (mSerialBufFill > 0) { mEvts.send(mSerialBuf, "serial", millis()); memset(mSerialBuf, 0, WEB_SERIAL_BUF_SIZE); mSerialBufFill = 0; } + } else if(nullptr != mSerialBuf) { + delete[] mSerialBuf; + mSerialBuf = nullptr; } } @@ -177,6 +188,9 @@ class Web { if (!mSerialClientConnnected) return; + if(nullptr == mSerialBuf) + return; + msg.replace("\r\n", ""); if (mSerialAddTime) { if ((13 + mSerialBufFill) < WEB_SERIAL_BUF_SIZE) { @@ -293,6 +307,10 @@ class Web { void onConnect(AsyncEventSourceClient *client) { DPRINTLN(DBG_VERBOSE, "onConnect"); + if(nullptr == mSerialBuf) { + mSerialBuf = new char[WEB_SERIAL_BUF_SIZE]; + memset(mSerialBuf, 0, WEB_SERIAL_BUF_SIZE); + } mSerialClientConnnected = true; if (client->lastId()) @@ -482,7 +500,12 @@ class Web { // pinout - for (uint8_t i = 0; i < 16; i++) { + #if defined(ETHERNET) + for (uint8_t i = 0; i < 22; i++) + #else + for (uint8_t i = 0; i < 16; i++) + #endif + { uint8_t pin = request->arg(String(pinArgNames[i])).toInt(); switch(i) { case 0: mConfig->nrf.pinCs = ((pin != 0xff) ? pin : DEF_NRF_CS_PIN); break; @@ -501,11 +524,23 @@ class Web { case 13: mConfig->cmt.pinCsb = pin; break; case 14: mConfig->cmt.pinFcsb = pin; break; case 15: mConfig->cmt.pinIrq = pin; break; + + #if defined(ETHERNET) + case 16: mConfig->sys.eth.pinCs = pin; break; + case 17: mConfig->sys.eth.pinSclk = pin; break; + case 18: mConfig->sys.eth.pinMiso = pin; break; + case 19: mConfig->sys.eth.pinMosi = pin; break; + case 20: mConfig->sys.eth.pinIrq = pin; break; + case 21: mConfig->sys.eth.pinRst = pin; break; + #endif } } mConfig->nrf.enabled = (request->arg("nrfEnable") == "on"); mConfig->cmt.enabled = (request->arg("cmtEnable") == "on"); + #if defined(ETHERNET) + mConfig->sys.eth.enabled = (request->arg("ethEn") == "on"); + #endif // ntp if (request->arg("ntpAddr") != "") { @@ -906,7 +941,7 @@ class Web { settings_t *mConfig = nullptr; bool mSerialAddTime = true; - char mSerialBuf[WEB_SERIAL_BUF_SIZE]; + char *mSerialBuf = nullptr; uint16_t mSerialBufFill = 0; bool mSerialClientConnnected = false; diff --git a/src/wifi/ahoywifi.h b/src/wifi/ahoywifi.h index 78ec6ab1..acf6d7d4 100644 --- a/src/wifi/ahoywifi.h +++ b/src/wifi/ahoywifi.h @@ -63,7 +63,7 @@ class ahoywifi { void connectionEvent(WiFiStatus_t status); bool isTimeout(uint8_t timeout) { return (mCnt % timeout) == 0; } -#if defined(ESP8266) + #if defined(ESP8266) void onConnect(const WiFiEventStationModeConnected& event); void onGotIP(const WiFiEventStationModeGotIP& event); void onDisconnect(const WiFiEventStationModeDisconnected& event);