From a9fa34da1e6aa844e12d1f839abc0d88f3fd6337 Mon Sep 17 00:00:00 2001 From: DL1LMH <126508591+dl1lmh@users.noreply.github.com> Date: Sat, 9 Nov 2024 23:10:08 +0100 Subject: [PATCH 1/3] Add LAN Support for Olimex --- data/igate_conf.json | 3 + data_embed/index.html | 20 ++- data_embed/script.js | 3 + src/LoRa_APRS_iGate.cpp | 10 +- src/aprs_is_utils.cpp | 22 ++-- src/configuration.cpp | 6 + src/configuration.h | 6 + src/eth_utils.cpp | 122 ++++++++++++++++++ src/eth_utils.h | 15 +++ src/lora_utils.cpp | 11 +- src/ntp_utils.cpp | 7 +- src/syslog_utils.cpp | 9 +- src/utils.cpp | 12 +- src/web_utils.cpp | 1 + src/wifi_utils.cpp | 6 +- .../board_pinout.h | 23 ++++ .../platformio.ini | 9 ++ 17 files changed, 258 insertions(+), 27 deletions(-) create mode 100644 src/eth_utils.cpp create mode 100644 src/eth_utils.h create mode 100644 variants/Olimex_ESP32_PoE_diy_LoRa_by_dl1lmh/board_pinout.h create mode 100644 variants/Olimex_ESP32_PoE_diy_LoRa_by_dl1lmh/platformio.ini diff --git a/data/igate_conf.json b/data/igate_conf.json index e8e8fab3..66ebfbef 100644 --- a/data/igate_conf.json +++ b/data/igate_conf.json @@ -7,6 +7,9 @@ }, "AP": [] }, + "ethernet": { + "use_lan": false + }, "beacon": { "latitude": 0.0, "longitude": 0.0, diff --git a/data_embed/index.html b/data_embed/index.html index 4c252a59..4fd373f7 100644 --- a/data_embed/index.html +++ b/data_embed/index.html @@ -290,8 +290,26 @@
Add all Wi-Fi Networks intended to be used. - +
+
+
+
+ + +
+
+
+
receivedPackets; String firstLine, secondLine, thirdLine, fourthLine, fifthLine, sixthLine, seventhLine; @@ -127,6 +130,7 @@ void setup() { #endif DIGI_Utils::checkEcoMode(); WIFI_Utils::setup(); + ETH_Utils::setup(); NTP_Utils::setup(); SYSLOG_Utils::setup(); WX_Utils::setup(); @@ -152,12 +156,14 @@ void loop() { thirdLine = Utils::getLocalIP(); - WIFI_Utils::checkWiFi(); + if (!Config.ethernet.use_lan) WIFI_Utils::checkWiFi(); + if (Config.ethernet.use_lan) ETH_Utils::checkETH(); #ifdef HAS_A7670 if (Config.aprs_is.active && !modemLoggedToAPRSIS) A7670_Utils::APRS_IS_connect(); #else - if (Config.aprs_is.active && (WiFi.status() == WL_CONNECTED) && !espClient.connected()) APRS_IS_Utils::connect(); + if (!Config.ethernet.use_lan && Config.aprs_is.active && (WiFi.status() == WL_CONNECTED) && !espClient.connected()) APRS_IS_Utils::connect(); + if (Config.ethernet.use_lan && Config.aprs_is.active && EthConnected && !espClient.connected()) APRS_IS_Utils::connect(); #endif NTP_Utils::update(); diff --git a/src/aprs_is_utils.cpp b/src/aprs_is_utils.cpp index 43cefc3a..3d361f40 100644 --- a/src/aprs_is_utils.cpp +++ b/src/aprs_is_utils.cpp @@ -21,6 +21,7 @@ extern String sixthLine; extern String seventhLine; extern bool modemLoggedToAPRSIS; extern bool backUpDigiMode; +extern bool EthConnected; uint32_t lastRxTime = millis(); @@ -35,7 +36,7 @@ namespace APRS_IS_Utils { espClient.print(line + "\r\n"); } - void connect() { +void connect() { Serial.print("Connecting to APRS-IS ... "); uint8_t count = 0; while (!espClient.connect(Config.aprs_is.server.c_str(), Config.aprs_is.port) && count < 20) { @@ -67,14 +68,16 @@ namespace APRS_IS_Utils { } void checkStatus() { - String wifiState, aprsisState; - if (WiFi.status() == WL_CONNECTED) { - wifiState = "OK"; + String netState, aprsisState; + if (!Config.ethernet.use_lan && (WiFi.status() == WL_CONNECTED)) { + netState = "WiFi: OK"; + } else if (Config.ethernet.use_lan && EthConnected) { + netState = "LAN: OK"; } else { - if (backUpDigiMode || Config.digi.ecoMode) { - wifiState = "--"; + if (backUpDigiMode || Config.digi.ecoMode || (Config.ethernet.use_lan && !EthConnected) ) { + netState = "Net: -- "; } else { - wifiState = "AP"; + netState = "WiFi: AP"; } if (!Config.display.alwaysOn && Config.display.timeout != 0) { displayToggle(true); @@ -101,10 +104,9 @@ namespace APRS_IS_Utils { if(aprsisState == "--" && !Config.display.alwaysOn && Config.display.timeout != 0) { displayToggle(true); lastScreenOn = millis(); - } + } } - secondLine = "WiFi: "; - secondLine += wifiState; + secondLine = netState; secondLine += " APRS-IS: "; secondLine += aprsisState; } diff --git a/src/configuration.cpp b/src/configuration.cpp index 59170b72..da1ba981 100644 --- a/src/configuration.cpp +++ b/src/configuration.cpp @@ -20,6 +20,8 @@ void Configuration::writeFile() { data["wifi"]["autoAP"]["password"] = wifiAutoAP.password; data["wifi"]["autoAP"]["timeout"] = wifiAutoAP.timeout; + data["ethernet"]["use_lan"] = ethernet.use_lan; + data["callsign"] = callsign; data["aprs_is"]["active"] = aprs_is.active; @@ -137,6 +139,8 @@ bool Configuration::readFile() { wifiAutoAP.password = data["wifi"]["autoAP"]["password"] | "1234567890"; wifiAutoAP.timeout = data["wifi"]["autoAP"]["timeout"] | 10; + ethernet.use_lan = data["ethernet"]["use_lan"] | false; + callsign = data["callsign"] | "NOCALL-10"; rememberStationTime = data["other"]["rememberStationTime"] | 30; @@ -248,6 +252,8 @@ void Configuration::init() { wifiAutoAP.password = "1234567890"; wifiAutoAP.timeout = 10; + ethernet.use_lan = false; + callsign = "N0CALL-10"; beacon.comment = "LoRa APRS"; diff --git a/src/configuration.h b/src/configuration.h index 160c0cee..bc961dc6 100644 --- a/src/configuration.h +++ b/src/configuration.h @@ -18,6 +18,11 @@ class WiFi_Auto_AP { int timeout; }; +class ETHERNET { +public: + bool use_lan; +}; + class BEACON { public: double latitude; @@ -137,6 +142,7 @@ class Configuration { String personalNote; std::vector wifiAPs; WiFi_Auto_AP wifiAutoAP; + ETHERNET ethernet; BEACON beacon; APRS_IS aprs_is; DIGI digi; diff --git a/src/eth_utils.cpp b/src/eth_utils.cpp new file mode 100644 index 00000000..bc31b286 --- /dev/null +++ b/src/eth_utils.cpp @@ -0,0 +1,122 @@ +#include +#include + +#include "configuration.h" +#include "display.h" + +extern Configuration Config; +extern bool backUpDigiMode; +extern uint32_t lastBackupDigiTime; + +uint32_t previousEthMillis = 0; +uint8_t EthCounter = 0; + +bool EthLink = false; +bool EthGotIP = false; +bool EthConnected = false; + + +namespace ETH_Utils { + + void EthEvent(WiFiEvent_t event) { + String hostname = "iGate-" + Config.callsign; + switch (event) { + case ARDUINO_EVENT_ETH_START: + ETH.setHostname(hostname.c_str()); + break; + + case ARDUINO_EVENT_ETH_CONNECTED: + EthLink = true; + break; + + case ARDUINO_EVENT_ETH_GOT_IP: + EthGotIP = true; + EthConnected = true; + break; + + case ARDUINO_EVENT_ETH_DISCONNECTED: + EthConnected = false; + break; + + case ARDUINO_EVENT_ETH_STOP: + EthLink = false; + EthGotIP = false; + EthConnected = false; + break; + + default: + break; + } + + } + + void checkETH() { + if (!Config.digi.ecoMode) { + if (backUpDigiMode) { + uint32_t EthCheck = millis() - lastBackupDigiTime; + if (!EthConnected && EthCheck >= 15 * 60 * 1000) { + Serial.println("*** Stopping BackUp Digi Mode ***"); + backUpDigiMode = false; + } else if (EthConnected) { + Serial.println("*** LAN Reconnect Success (Stopping Backup Digi Mode) ***"); + backUpDigiMode = false; + EthCounter = 0; + } + } + + if (!backUpDigiMode && !EthConnected && ((millis() - previousEthMillis) >= 30 * 1000)) { + Serial.print(millis()); + Serial.println("Waiting for LAN Reconnect..."); + previousEthMillis = millis(); + + if (Config.backupDigiMode) { + EthCounter++; + } + if (EthCounter >= 2) { + Serial.println("*** LAN lost. Starting BackUp Digi Mode ***"); + backUpDigiMode = true; + lastBackupDigiTime = millis(); + } + } + } + } + + void startETH() { + u_int8_t counter = 0; + WiFi.onEvent(ETH_Utils::EthEvent); + displayShow("", "Connecting to LAN:", "", " ...", 0); + Serial.print("Connecting to LAN: "); + ETH.begin(); + while (((EthLink && EthGotIP) == false) || (counter <= 10)) + { + delay(500); + #ifdef INTERNAL_LED_PIN + digitalWrite(INTERNAL_LED_PIN,HIGH); + #endif + Serial.print('.'); + delay(500); + #ifdef INTERNAL_LED_PIN + digitalWrite(INTERNAL_LED_PIN,LOW); + #endif + counter++; + } + if (EthLink && EthGotIP) EthConnected = true; + #ifdef INTERNAL_LED_PIN + digitalWrite(INTERNAL_LED_PIN,LOW); + #endif + if (EthConnected) { + Serial.print("\nConnected as "); + Serial.print(ETH.localIP()); + Serial.print(" / MAC: "); + Serial.println(ETH.macAddress()); + displayShow("", " LAN connected!!", "" , " loading ...", 1000); + } else { + Serial.println("\nNot connected to LAN!"); + displayShow("", " LAN not connected!", "" , " loading ...", 1000); + } + } + + void setup() { + if (Config.ethernet.use_lan && !Config.digi.ecoMode) startETH(); + } +} \ No newline at end of file diff --git a/src/eth_utils.h b/src/eth_utils.h new file mode 100644 index 00000000..cc7606fb --- /dev/null +++ b/src/eth_utils.h @@ -0,0 +1,15 @@ +#ifndef ETH_UTILS_H_ +#define ETH_UTILS_H_ + +#include + +namespace ETH_Utils { + void checkETH(); + void setup(); + void startETH(); + void EthEvent(); +} + + + +#endif \ No newline at end of file diff --git a/src/lora_utils.cpp b/src/lora_utils.cpp index a4d9d05b..30140c54 100644 --- a/src/lora_utils.cpp +++ b/src/lora_utils.cpp @@ -11,6 +11,8 @@ extern Configuration Config; extern uint32_t lastRxTime; +extern bool EthConnected; + extern std::vector receivedPackets; bool operationDone = true; @@ -136,7 +138,8 @@ namespace LoRa_Utils { int state = radio.transmit("\x3c\xff\x01" + newPacket); transmitFlag = true; if (state == RADIOLIB_ERR_NONE) { - if (Config.syslog.active && WiFi.status() == WL_CONNECTED) { + if ((!Config.ethernet.use_lan && Config.syslog.active && WiFi.status() == WL_CONNECTED) || + (Config.ethernet.use_lan && Config.syslog.active && EthConnected)) { SYSLOG_Utils::log(3, newPacket, 0, 0.0, 0); // TX } Utils::print("---> LoRa Packet Tx : "); @@ -200,7 +203,8 @@ namespace LoRa_Utils { receivedPackets.push_back(receivedPacket); } - if (Config.syslog.active && WiFi.status() == WL_CONNECTED) { + if ((!Config.ethernet.use_lan && Config.syslog.active && WiFi.status() == WL_CONNECTED) || + (Config.ethernet.use_lan && Config.syslog.active && EthConnected)) { SYSLOG_Utils::log(1, packet, rssi, snr, freqError); // RX } lastRxTime = millis(); @@ -211,7 +215,8 @@ namespace LoRa_Utils { snr = radio.getSNR(); freqError = radio.getFrequencyError(); Utils::println(F("CRC error!")); - if (Config.syslog.active && WiFi.status() == WL_CONNECTED) { + if ((!Config.ethernet.use_lan && Config.syslog.active && WiFi.status() == WL_CONNECTED) || + (Config.ethernet.use_lan && Config.syslog.active && EthConnected)) { SYSLOG_Utils::log(0, packet, rssi, snr, freqError); // CRC } packet = ""; diff --git a/src/ntp_utils.cpp b/src/ntp_utils.cpp index 3fb1dff5..a57912be 100644 --- a/src/ntp_utils.cpp +++ b/src/ntp_utils.cpp @@ -7,6 +7,7 @@ extern Configuration Config; +extern bool EthConnected; WiFiUDP ntpUDP; NTPClient timeClient(ntpUDP, "pool.ntp.org", 0, 15 * 60 * 1000); // Update interval 15 min @@ -15,7 +16,8 @@ NTPClient timeClient(ntpUDP, "pool.ntp.org", 0, 15 * 60 * 1000); // Update in namespace NTP_Utils { void setup() { - if (WiFi.status() == WL_CONNECTED && !Config.digi.ecoMode && Config.callsign != "NOCALL-10") { + if ((!Config.ethernet.use_lan && WiFi.status() == WL_CONNECTED && !Config.digi.ecoMode && Config.callsign != "NOCALL-10") || + (Config.ethernet.use_lan && EthConnected && !Config.digi.ecoMode && Config.callsign != "NOCALL-10")) { int gmt = Config.ntp.gmtCorrection * 3600; timeClient.setTimeOffset(gmt); timeClient.begin(); @@ -23,7 +25,8 @@ namespace NTP_Utils { } void update() { - if (WiFi.status() == WL_CONNECTED && !Config.digi.ecoMode && Config.callsign != "NOCALL-10") timeClient.update(); + if ((!Config.ethernet.use_lan && WiFi.status() == WL_CONNECTED && !Config.digi.ecoMode && Config.callsign != "NOCALL-10") || + (Config.ethernet.use_lan && EthConnected && !Config.digi.ecoMode && Config.callsign != "NOCALL-10")) timeClient.update(); } String getFormatedTime() { diff --git a/src/syslog_utils.cpp b/src/syslog_utils.cpp index 5d49f3e2..dce5d30d 100644 --- a/src/syslog_utils.cpp +++ b/src/syslog_utils.cpp @@ -1,10 +1,12 @@ #include #include +#include #include "configuration.h" #include "syslog_utils.h" #include "gps_utils.h" extern Configuration Config; +extern bool EthConnected; WiFiUDP udpClient; @@ -12,7 +14,7 @@ WiFiUDP udpClient; namespace SYSLOG_Utils { void log(const uint8_t type, const String& packet, const int rssi, const float snr, const int freqError) { - if (Config.syslog.active && WiFi.status() == WL_CONNECTED) { + if (Config.syslog.active && (( Config.ethernet.use_lan && (WiFi.status() == WL_CONNECTED)) || (Config.ethernet.use_lan && EthConnected))) { String syslogPacket = "<165>1 - "; syslogPacket.concat(Config.callsign); syslogPacket.concat(" CA2RXU_LoRa_iGate_1.3 - - - "); //RFC5424 The Syslog Protocol @@ -111,8 +113,9 @@ namespace SYSLOG_Utils { } void setup() { - if (Config.syslog.active && WiFi.status() == WL_CONNECTED) { - udpClient.begin(WiFi.localIP(), 0); + if (Config.syslog.active && (( !Config.ethernet.use_lan && (WiFi.status() == WL_CONNECTED)) || (Config.ethernet.use_lan && EthConnected))) { + if (Config.ethernet.use_lan && EthConnected) udpClient.begin(ETH.localIP(), 0); + if (!Config.ethernet.use_lan && !EthConnected) udpClient.begin(WiFi.localIP(), 0); Serial.println("init : Syslog Server ... done! (at " + Config.syslog.server + ")"); } } diff --git a/src/utils.cpp b/src/utils.cpp index 665b0439..555c6cf3 100644 --- a/src/utils.cpp +++ b/src/utils.cpp @@ -9,6 +9,7 @@ #include "A7670_utils.h" #include "lora_utils.h" #include "wifi_utils.h" +#include #include "gps_utils.h" #include "wx_utils.h" #include "display.h" @@ -37,6 +38,7 @@ extern int wxModuleType; extern bool backUpDigiMode; extern bool shouldSleepLowVoltage; extern bool transmitFlag; +extern bool EthConnected; extern std::vector lastHeardStations; @@ -58,7 +60,7 @@ namespace Utils { status.concat(","); status.concat(Config.beacon.path); } - if (WiFi.status() == WL_CONNECTED && Config.aprs_is.active && Config.beacon.sendViaAPRSIS) { + if ((WiFi.status() == WL_CONNECTED || EthConnected) && Config.aprs_is.active && Config.beacon.sendViaAPRSIS) { delay(1000); status.concat(",qAC:>https://github.com/richonguzman/LoRa_APRS_iGate "); status.concat(versionDate); @@ -76,14 +78,16 @@ namespace Utils { String getLocalIP() { if (Config.digi.ecoMode) { - return "** WiFi AP Killed **"; - } else if (!WiFiConnected) { + return "** WiFi EcoMode **"; + } else if (!WiFiConnected && !Config.ethernet.use_lan) { return "IP : 192.168.4.1"; } else if (backUpDigiMode) { return "- BACKUP DIGI MODE -"; + } else if (Config.ethernet.use_lan && EthConnected) { + return "IP : " + String(ETH.localIP()[0]) + "." + String(ETH.localIP()[1]) + "." + String(ETH.localIP()[2]) + "." + String(ETH.localIP()[3]); } else { return "IP : " + String(WiFi.localIP()[0]) + "." + String(WiFi.localIP()[1]) + "." + String(WiFi.localIP()[2]) + "." + String(WiFi.localIP()[3]); - } + } } void setupDisplay() { diff --git a/src/web_utils.cpp b/src/web_utils.cpp index d3bae52a..9adf2208 100644 --- a/src/web_utils.cpp +++ b/src/web_utils.cpp @@ -115,6 +115,7 @@ namespace WEB_Utils { Config.wifiAutoAP.password = request->getParam("wifi.autoAP.password", true)->value(); Config.wifiAutoAP.timeout = request->getParam("wifi.autoAP.timeout", true)->value().toInt(); + Config.ethernet.use_lan = request->getParam("ethernet.use_lan", true); Config.aprs_is.active = request->hasParam("aprs_is.active", true); Config.aprs_is.passcode = request->getParam("aprs_is.passcode", true)->value(); diff --git a/src/wifi_utils.cpp b/src/wifi_utils.cpp index f3751ca2..025a3839 100644 --- a/src/wifi_utils.cpp +++ b/src/wifi_utils.cpp @@ -153,8 +153,10 @@ namespace WIFI_Utils { } void setup() { - if (!Config.digi.ecoMode) startWiFi(); - btStop(); + if ((!Config.digi.ecoMode) && !Config.ethernet.use_lan) { + startWiFi(); + btStop(); + } } } \ No newline at end of file diff --git a/variants/Olimex_ESP32_PoE_diy_LoRa_by_dl1lmh/board_pinout.h b/variants/Olimex_ESP32_PoE_diy_LoRa_by_dl1lmh/board_pinout.h new file mode 100644 index 00000000..8358dc99 --- /dev/null +++ b/variants/Olimex_ESP32_PoE_diy_LoRa_by_dl1lmh/board_pinout.h @@ -0,0 +1,23 @@ +#ifndef BOARD_PINOUT_H_ +#define BOARD_PINOUT_H_ + + // LoRa Radio + #define RADIO_SCLK_PIN 14 + #define RADIO_MOSI_PIN 2 + #define RADIO_MISO_PIN 15 + #define RADIO_CS_PIN 5 + #define RADIO_BUSY_PIN 36 + #define RADIO_RST_PIN 4 + + // Display + #define HAS_DISPLAY + + #define OLED_SDA 13 + #define OLED_SCL 16 + #define OLED_RST -1 + + + // Aditional Config + #define BATTERY_PIN 35 + +#endif \ No newline at end of file diff --git a/variants/Olimex_ESP32_PoE_diy_LoRa_by_dl1lmh/platformio.ini b/variants/Olimex_ESP32_PoE_diy_LoRa_by_dl1lmh/platformio.ini new file mode 100644 index 00000000..1941a668 --- /dev/null +++ b/variants/Olimex_ESP32_PoE_diy_LoRa_by_dl1lmh/platformio.ini @@ -0,0 +1,9 @@ +[env:Olimex_ESP32_PoE_diy_LoRa_by_dl1lmh] +; Additional DIY-Board needed! See https://github.com/dl1lmh/LoRa-Board +board = esp32-poe-iso +build_flags = + ${common.build_flags} + -DHAS_SX1278 +lib_deps = + ${common.lib_deps} + ${common.display_libs} \ No newline at end of file From 1bf92f16d41d1bc37295edc3e3cdc72ea8a3477b Mon Sep 17 00:00:00 2001 From: DL1LMH <126508591+dl1lmh@users.noreply.github.com> Date: Sat, 9 Nov 2024 23:17:47 +0100 Subject: [PATCH 2/3] Added Olimex Board --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 101afd83..09c71713 100644 --- a/README.md +++ b/README.md @@ -52,6 +52,7 @@ ____________________________________________________ ## Timeline (Versions): +- 2024.11.09 Added Olimex-PoE-Iso Board with DIY-LoRa (https://github.com/dl1lmh/LoRa-Board-for-Olimex-UEXT) - 2024.11.06 (Silent Update) Working now with Board "VARIANTS". - 2024.10.29 Added LILYGO Lora32 T3S3 support. - 2024.10.25 Added QRP Labs LightGateway 1.0 support. @@ -123,4 +124,4 @@ ____________________________________________________ __________________________________________ -# Hope You Enjoy this, 73! CA2RXU, Valparaiso, Chile \ No newline at end of file +# Hope You Enjoy this, 73! CA2RXU, Valparaiso, Chile From a69a251c69f297ae7f39297c62009906fa6510a5 Mon Sep 17 00:00:00 2001 From: DL1LMH <126508591+dl1lmh@users.noreply.github.com> Date: Sat, 9 Nov 2024 23:19:31 +0100 Subject: [PATCH 3/3] Add Olimex-Board --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 09c71713..366ce47e 100644 --- a/README.md +++ b/README.md @@ -48,6 +48,8 @@ ____________________________________________________ - Wemos Lolin32 Oled + SX1278 DIY Version. +- Olimex ESP32-PoE-ISO Board with DIY-LoRa +
## Timeline (Versions):