Skip to content

Commit

Permalink
lwIP on ethernet: examples (#8395)
Browse files Browse the repository at this point in the history
* ethernet: examples

* remove duplicate

* styling

* fix comment restyle + comment eth.setdefault()

* comment and add comments about eth.setDefault()

* update comments when using interface::setDefault()

* repair bad merge

* fix default interface case

* factorize

* change comment
  • Loading branch information
d-a-v authored Jun 2, 2022
1 parent f5ef02d commit 5f2af19
Show file tree
Hide file tree
Showing 13 changed files with 945 additions and 110 deletions.
54 changes: 41 additions & 13 deletions cores/esp8266/LwipIntfDev.h
Original file line number Diff line number Diff line change
Expand Up @@ -59,20 +59,36 @@ class LwipIntfDev: public LwipIntf, public RawDev
return IPAddress(ip4_addr_get_u32(ip_2_ip4(&_netif.gw)));
}

void setDefault();
// 1. Currently when no default is set, esp8266-Arduino uses the first
// DHCP client interface receiving a valid address and gateway to
// become the new lwIP default interface.
// 2. Otherwise - when using static addresses - lwIP for every packets by
// defaults selects automatically the best suited output interface
// matching the destination address. If several interfaces match,
// the first one is picked. On esp8266/Arduno: WiFi interfaces are
// checked first.
// 3. Or, use `::setDefault(true)` to force using this interface's gateway
// as default router.
void setDefault(bool deflt = true);

// true if interface has a valid IPv4 address
bool connected()
{
return !!ip4_addr_get_u32(ip_2_ip4(&_netif.ip_addr));
}

bool routable()
{
return !ip_addr_isany(&_netif.gw);
}

// ESP8266WiFi API compatibility

wl_status_t status();

protected:
err_t netif_init();
void check_route();
void netif_status_callback();

static err_t netif_init_s(netif* netif);
Expand Down Expand Up @@ -184,10 +200,10 @@ boolean LwipIntfDev<RawDev>::begin(const uint8_t* macAddress, const uint16_t mtu
return false;
}

_netif.flags |= NETIF_FLAG_UP;

if (localIP().v4() == 0)
{
// IP not set, starting DHCP
_netif.flags |= NETIF_FLAG_UP;
switch (dhcp_start(&_netif))
{
case ERR_OK:
Expand All @@ -201,6 +217,12 @@ boolean LwipIntfDev<RawDev>::begin(const uint8_t* macAddress, const uint16_t mtu
return false;
}
}
else
{
// IP is set, static config
netif_set_link_up(&_netif);
netif_set_up(&_netif);
}

_started = true;

Expand Down Expand Up @@ -301,16 +323,25 @@ err_t LwipIntfDev<RawDev>::netif_init()
template<class RawDev>
void LwipIntfDev<RawDev>::netif_status_callback()
{
check_route();
if (connected())
{
if (_default || (netif_default == nullptr && !ip_addr_isany(&_netif.gw)))
sntp_stop();
sntp_init();
}
}

template<class RawDev>
void LwipIntfDev<RawDev>::check_route()
{
if (connected())
{
if (_default || (netif_default == nullptr && routable()))
{
// on user request,
// or if there is no current default interface, but a gateway is valid
// or if there is no current default interface, but our gateway is valid
netif_set_default(&_netif);
}
sntp_stop();
sntp_init();
}
else if (netif_default == &_netif)
{
Expand Down Expand Up @@ -386,13 +417,10 @@ err_t LwipIntfDev<RawDev>::handlePackets()
}

template<class RawDev>
void LwipIntfDev<RawDev>::setDefault()
void LwipIntfDev<RawDev>::setDefault(bool deflt)
{
_default = true;
if (connected())
{
netif_set_default(&_netif);
}
_default = deflt;
check_route();
}

#endif // _LWIPINTFDEV_H
14 changes: 8 additions & 6 deletions libraries/ESP8266mDNS/src/LEAmDNS_Transfer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1766,11 +1766,13 @@ namespace MDNSImplementation
stcMDNS_RRAttributes attributes(DNS_RRTYPE_AAAA,
((p_rSendParameter.m_bCacheFlush ? 0x8000 : 0)
| DNS_RRCLASS_IN)); // Cache flush? & INternet
bool bResult = ((_writeMDNSHostDomain(m_pcHostname, false, p_rSendParameter)) && // esp8266.local
(_writeMDNSRRAttributes(attributes, p_rSendParameter)) && // TYPE & CLASS
(_write32((p_rSendParameter.m_bUnannounce ? 0 : MDNS_HOST_TTL), p_rSendParameter)) && // TTL
(_write16(MDNS_IP6_SIZE, p_rSendParameter)) && // RDLength
(false /*TODO: IP6 version of: _udpAppendBuffer((uint32_t)p_IPAddress, MDNS_IP4_SIZE)*/)); // RData
bool bResult
= ((_writeMDNSHostDomain(m_pcHostname, false, p_rSendParameter)) && // esp8266.local
(_writeMDNSRRAttributes(attributes, p_rSendParameter)) && // TYPE & CLASS
(_write32((p_rSendParameter.m_bUnannounce ? 0 : MDNS_HOST_TTL), p_rSendParameter))
&& // TTL
(_write16(MDNS_IP6_SIZE, p_rSendParameter)) && // RDLength
(false /*TODO: IP6 version of: _udpAppendBuffer((uint32_t)p_IPAddress, MDNS_IP4_SIZE)*/)); // RData

DEBUG_EX_ERR(if (!bResult) {
DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _writeMDNSAnswer_AAAA: FAILED!\n"));
Expand Down Expand Up @@ -1855,7 +1857,7 @@ namespace MDNSImplementation
p_rSendParameter.m_u16Offset))
&& (_writeMDNSRRDomain(hostDomain,
p_rSendParameter))) // Host, eg. esp8266.local
// Cache available for domain
// Cache available for domain
: ((MDNS_DOMAIN_COMPRESS_MARK
> ((u16CachedDomainOffset >> 8) & ~MDNS_DOMAIN_COMPRESS_MARK))
&& // Valid offset
Expand Down
89 changes: 89 additions & 0 deletions libraries/lwIP_Ethernet/examples/EthClient/EthClient.ino
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
/*
This sketch establishes a TCP connection to a "quote of the day" service.
It sends a "hello" message, and then prints received data.
This is Ethernet version of:
https://github.com/esp8266/Arduino/blob/master/libraries/ESP8266WiFi/examples/WiFiClient/WiFiClient.ino
*/

#include <LwipEthernet.h>

Wiznet5500lwIP eth(/*SS*/ 16); // <== adapt to your hardware

const char* host = "djxmmx.net";
const uint16_t port = 17;

void setup() {
Serial.begin(115200);

Serial.println("\nEthernet\n");

// 1. Currently when no default is set, esp8266-Arduino uses the first
// DHCP client interface receiving a valid address and gateway to
// become the new lwIP default interface.
// 2. Otherwise - when using static addresses - lwIP for every packets by
// defaults selects automatically the best suited output interface
// matching the destination address. If several interfaces match,
// the first one is picked. On esp8266/Arduno: WiFi interfaces are
// checked first.
// 3. Or, use `::setDefault()` to force routing through this interface.
// eth.setDefault(); // default route set through this interface

if (!ethInitDHCP(eth)) {
Serial.printf("no hardware found\n");
while (1) {
delay(1000);
}
}

while (!eth.connected()) {
Serial.printf(".");
delay(1000);
}

Serial.printf("Ethernet: IP Address: %s\n",
eth.localIP().toString().c_str());
}

void loop() {

Serial.print("connecting to ");
Serial.print(host);
Serial.print(':');
Serial.println(port);

// Use WiFiClient class to create TCP connections
// (this class could have been named TCPClient)
WiFiClient client;
if (!client.connect(host, port)) {
Serial.println("connection failed");
delay(5000);
return;
}

// This will send a string to the server
Serial.println("sending data to server");
if (client.connected()) { client.println("hello from ESP8266"); }

// wait for data to be available
unsigned long timeout = millis();
while (client.available() == 0) {
if (millis() - timeout > 5000) {
Serial.println(">>> Client Timeout !");
client.stop();
delay(60000);
return;
}
}

// Read all the lines of the reply from server and print them to Serial
Serial.println("receiving from remote server");
client.sendAll(Serial); // this peer closes once all data are sent

// Close the connection
Serial.println();
Serial.println("closing connection");
client.stop();

delay(300000); // execute once every 5 minutes, don't flood remote service
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
/*
This sketch establishes a TCP connection to a "quote of the day" service.
It sends a "hello" message, and then prints received data.
This is Ethernet version of:
https://github.com/esp8266/Arduino/blob/master/libraries/ESP8266WiFi/examples/WiFiClient/WiFiClient.ino
*/

#include <LwipEthernet.h>

#define LOCAL_IP IPAddress(192, 168, 0, 233)
#define LOCAL_GW IPAddress(192, 168, 0, 254) // <== adapt to your network
#define LOCAL_MASK IPAddress(255, 255, 255, 0)
#define DNS IPAddress(8, 8, 8, 8)

Wiznet5500lwIP eth(/*SS*/ 16); // <== adapt to your hardware

const char* host = "djxmmx.net";
const uint16_t port = 17;

void setup() {
Serial.begin(115200);

Serial.println("\nEthernet\n");

// 1. Currently when no default is set, esp8266-Arduino uses the first
// DHCP client interface receiving a valid address and gateway to
// become the new lwIP default interface.
// 2. Otherwise - when using static addresses - lwIP for every packets by
// defaults selects automatically the best suited output interface
// matching the destination address. If several interfaces match,
// the first one is picked. On esp8266/Arduno: WiFi interfaces are
// checked first.
// 3. Or, use `::setDefault()` to force routing through this interface.
// eth.setDefault(true); // default route set through this interface

if (!ethInitStatic(eth, LOCAL_IP, LOCAL_GW, LOCAL_MASK, DNS)) {
// enabling debug message will show the real cause
Serial.printf("no hardware found or bad network configuration\n");
while (1) {
delay(1000);
}
}

Serial.printf("Ethernet: IP Address: %s\n",
eth.localIP().toString().c_str());
}

void loop() {

Serial.print("connecting to ");
Serial.print(host);
Serial.print(':');
Serial.println(port);

// Use WiFiClient class to create TCP connections
// (this class could have been named TCPClient)
WiFiClient client;
if (!client.connect(host, port)) {
Serial.println("connection failed");
delay(5000);
return;
}

// This will send a string to the server
Serial.println("sending data to server");
if (client.connected()) {
client.println("hello from ESP8266");
}

// wait for data to be available
unsigned long timeout = millis();
while (client.available() == 0) {
if (millis() - timeout > 5000) {
Serial.println(">>> Client Timeout !");
client.stop();
delay(60000);
return;
}
}

// Read all the lines of the reply from server and print them to Serial
Serial.println("receiving from remote server");
client.sendAll(Serial); // this peer closes once all data are sent

// Close the connection
Serial.println();
Serial.println("closing connection");
client.stop();

delay(600000); // execute once every 10 minutes, don't flood remote service
}
Loading

0 comments on commit 5f2af19

Please sign in to comment.