From 34c3d1076795e53941b6b06f0770910c8ab62bf3 Mon Sep 17 00:00:00 2001 From: Bruno Crivelari Sanches Date: Sat, 3 Sep 2022 17:16:33 -0300 Subject: [PATCH 1/2] Keep Ethernet singleton "alive" until connection is established. --- EthernetInterface.cpp | 70 +++++++++++++++++++++---------------------- EthernetInterface.h | 3 ++ 2 files changed, 38 insertions(+), 35 deletions(-) diff --git a/EthernetInterface.cpp b/EthernetInterface.cpp index f691f45..9d04423 100644 --- a/EthernetInterface.cpp +++ b/EthernetInterface.cpp @@ -36,7 +36,15 @@ EthernetInterface * EthernetInterface::singleton=NULL; void EthernetInterface::setup() { singleton=new EthernetInterface(); - if (!singleton->connected) singleton=NULL; + + DIAG(F("Ethernet begin OK.")); + if (Ethernet.hardwareStatus() == EthernetNoHardware) { + DIAG(F("Ethernet shield not found")); + + singleton=NULL; + + return; + } }; @@ -60,38 +68,7 @@ EthernetInterface::EthernetInterface() DIAG(F("Ethernet.begin FAILED")); return; } - #endif - DIAG(F("begin OK.")); - if (Ethernet.hardwareStatus() == EthernetNoHardware) { - DIAG(F("Ethernet shield not found")); - return; - } - - unsigned long startmilli = millis(); - while ((millis() - startmilli) < 5500) // Loop to give time to check for cable connection - { - if (Ethernet.linkStatus() == LinkON) - break; - DIAG(F("Ethernet waiting for link (1sec) ")); - delay(1000); - } - - if (Ethernet.linkStatus() == LinkOFF) { - DIAG(F("Ethernet cable not connected")); - return; - } - - connected=true; - - IPAddress ip = Ethernet.localIP(); // reassign the obtained ip address - - server = new EthernetServer(IP_PORT); // Ethernet Server listening on default port IP_PORT - server->begin(); - - LCD(4,F("IP: %d.%d.%d.%d"), ip[0], ip[1], ip[2], ip[3]); - LCD(5,F("Port:%d"), IP_PORT); - - outboundRing=new RingStream(OUTBOUND_RING_SIZE); + #endif } /** @@ -99,8 +76,9 @@ EthernetInterface::EthernetInterface() * */ void EthernetInterface::loop() -{ - if (!singleton) return; +{ + if(!singleton || ((!singleton->connected) && (!singleton->checkLink()))) + return; switch (Ethernet.maintain()) { @@ -125,6 +103,28 @@ void EthernetInterface::loop() } +bool EthernetInterface::checkLink() +{ + if (Ethernet.linkStatus() != LinkON) + return false; + + DIAG(F("Ethernet cable connected")); + + connected=true; + + IPAddress ip = Ethernet.localIP(); // reassign the obtained ip address + + server = new EthernetServer(IP_PORT); // Ethernet Server listening on default port IP_PORT + server->begin(); + + LCD(4,F("IP: %d.%d.%d.%d"), ip[0], ip[1], ip[2], ip[3]); + LCD(5,F("Port:%d"), IP_PORT); + + outboundRing=new RingStream(OUTBOUND_RING_SIZE); + + return true; +} + void EthernetInterface::loop2() { // get client from the server diff --git a/EthernetInterface.h b/EthernetInterface.h index 2a94ac6..ff673c1 100644 --- a/EthernetInterface.h +++ b/EthernetInterface.h @@ -60,6 +60,9 @@ class EthernetInterface { bool connected; EthernetInterface(); void loop2(); + + bool checkLink(); + EthernetServer * server; EthernetClient clients[MAX_SOCK_NUM]; // accept up to MAX_SOCK_NUM client connections at the same time; This depends on the chipset used on the Shield uint8_t buffer[MAX_ETH_BUFFER+1]; // buffer used by TCP for the recv From 64b1de08be6e1e78d8858c43dddfbed08d0a3097 Mon Sep 17 00:00:00 2001 From: Bruno Crivelari Sanches Date: Mon, 5 Sep 2022 14:23:54 -0300 Subject: [PATCH 2/2] Detects when ethernet cable is connected and is disconnected, also correctly handles EthernetServer tead down on such situations --- EthernetInterface.cpp | 74 ++++++++++++++++++++++++++++++++++--------- EthernetInterface.h | 5 +-- 2 files changed, 62 insertions(+), 17 deletions(-) diff --git a/EthernetInterface.cpp b/EthernetInterface.cpp index 9d04423..ddd762c 100644 --- a/EthernetInterface.cpp +++ b/EthernetInterface.cpp @@ -41,6 +41,7 @@ void EthernetInterface::setup() if (Ethernet.hardwareStatus() == EthernetNoHardware) { DIAG(F("Ethernet shield not found")); + delete singleton; singleton=NULL; return; @@ -71,13 +72,24 @@ EthernetInterface::EthernetInterface() #endif } +/** + * @brief Cleanup any resources + * + * @return none + */ +EthernetInterface::~EthernetInterface() +{ + delete server; + delete outboundRing; +} + /** * @brief Main loop for the EthernetInterface * */ void EthernetInterface::loop() { - if(!singleton || ((!singleton->connected) && (!singleton->checkLink()))) + if(!singleton || (!singleton->checkLink())) return; switch (Ethernet.maintain()) @@ -103,26 +115,58 @@ void EthernetInterface::loop() } +/** + * @brief Checks ethernet link cable status and detects when it connects / disconnects + * + * @return true when cable is connected, false otherwise + */ bool EthernetInterface::checkLink() { - if (Ethernet.linkStatus() != LinkON) - return false; - - DIAG(F("Ethernet cable connected")); + if (Ethernet.linkStatus() == LinkON) + { + //if we are not connected yet, setup a new server + if(!connected) + { + DIAG(F("Ethernet cable connected")); - connected=true; - - IPAddress ip = Ethernet.localIP(); // reassign the obtained ip address + connected=true; + + IPAddress ip = Ethernet.localIP(); // reassign the obtained ip address - server = new EthernetServer(IP_PORT); // Ethernet Server listening on default port IP_PORT - server->begin(); - - LCD(4,F("IP: %d.%d.%d.%d"), ip[0], ip[1], ip[2], ip[3]); - LCD(5,F("Port:%d"), IP_PORT); + server = new EthernetServer(IP_PORT); // Ethernet Server listening on default port IP_PORT + server->begin(); + + LCD(4,F("IP: %d.%d.%d.%d"), ip[0], ip[1], ip[2], ip[3]); + LCD(5,F("Port:%d"), IP_PORT); - outboundRing=new RingStream(OUTBOUND_RING_SIZE); + // + //only create a outboundRing it none exists, this may happen if the cable gets disconnected and connected again + if(!outboundRing) + outboundRing=new RingStream(OUTBOUND_RING_SIZE); + } - return true; + return true; + } + else if(connected) + { + DIAG(F("Ethernet cable disconnected")); + connected=false; + + //clean up any client + for (byte socket = 0; socket < MAX_SOCK_NUM; socket++) + { + if(clients[socket].connected()) + clients[socket].stop(); + } + + /* tear down server */ + delete server; + server = nullptr; + + LCD(4,F("IP: None")); + } + + return false; } void EthernetInterface::loop2() diff --git a/EthernetInterface.h b/EthernetInterface.h index ff673c1..ce5bbd9 100644 --- a/EthernetInterface.h +++ b/EthernetInterface.h @@ -59,14 +59,15 @@ class EthernetInterface { static EthernetInterface * singleton; bool connected; EthernetInterface(); + ~EthernetInterface(); void loop2(); bool checkLink(); - EthernetServer * server; + EthernetServer * server = nullptr; EthernetClient clients[MAX_SOCK_NUM]; // accept up to MAX_SOCK_NUM client connections at the same time; This depends on the chipset used on the Shield uint8_t buffer[MAX_ETH_BUFFER+1]; // buffer used by TCP for the recv - RingStream * outboundRing; + RingStream * outboundRing = nullptr; };