Using WiFi or Ethernet with ESP8266 (NodeMCU) & W5500

Hello

I have a project where I need to connect with Ethernet as standard, but have the ability to also connect via WiFi if the Ethernet is not available.

I have some code that will connect via Ethernet and, if this fails, then attempt to connect via WiFi, but I cannot get thing.handle() to work with WiFi & Ethernet, depending on which is connected.

I have to use either ThingerEthernet thing(USERNAME, DEVICE_ID, DEVICE_ID); or ThingerESP8266 thing(USERNAME, DEVICE_ID, DEVICE_ID); but not both.

Is there a way of stopping thing.handle from trying to make the WiFi or Ethernet connection so that I can deal with this connection using other libraries?

My code is attached below, I have also included all of my comments because I had a hard time trying to get ESP8266 working with W5500 so my notes may help other people.

/*
Test to get ESP8266 talking to thinger.io via ESP8266 & Wiznet w5500 Ethernet shield
V1 - Original code
  •Problem with Ethernet library from ESP8266 libraries being called by IDE in favour of using the standard Arduino Ethernet library
ESP8266 Ethernet library isnt as good as the standard Arduino one and lacks some of the functions.
Renamed ESP8266 Ethernet.h & cpp files to EthernetESP8266 so that the IDE would ignore them
  •Problem with wiring between ESP8266 & W5500
>Changed pins for reset & CS.
  Set code to manually excercise Reset Pin
  Used  Ethernet.init function to set CS to another pin.
>Compiler complaining with an error about IPAddress and ESP8266
  Found solution in comments on https://esp8266hints.wordpress.com/2018/02/13/adding-an-ethernet-port-to-your-esp-revisited/
        ##Thanks to Tony Onofrio for this##
    >>Changed Ethernet.cpp file to add in.....
      You need to change after line 85 –
        #if ARDUINO > 106 || TEENSYDUINO > 121
          to
        #if defined(ARDUINO_ARCH_ESP8266)
        W5100.setIPAddress(ip.raw_address());
        W5100.setGatewayIp(gateway.raw_address());
        W5100.setSubnetMask(subnet.raw_address());
        #elif ARDUINO > 106 || TEENSYDUINO > 121
      
 V2 - Add in thinger.io stuff
  had to addin ThingerEthernet library because ThingerESP8266 automaticaly tries to connect via WiFi
 V3 - Add in ability to connect via WiFi as well as Ethernet
 */

#define _DEBUG_

#include <SPI.h>
#include <Ethernet.h>
#include <ThingerEthernet.h>
#include <ThingerESP8266.h>
#include <ESP8266WiFi.h>        // Include the Wi-Fi library

#define WIZRST 16 //Specify pin to use for reseting W5500
#define WIZCS 5 //Specify the pin for SPI CS

#define USERNAME "xxxxx"    //Thinger Account User Name
#define DEVICE_ID "xxxxx"     //Thinger Device ID ## NOTE This is the device serial number ##
ThingerEthernet thing(USERNAME, DEVICE_ID, DEVICE_ID);
//ThingerESP8266 thing(USERNAME, DEVICE_ID, DEVICE_ID);
  
const char* ssid     = "xxxxx";         // The SSID (name) of the Wi-Fi network you want to connect to
const char* password = "xxxxx";     // The password of the Wi-Fi network
byte Enet = 1; //1 = Ethernet connection is available

byte mac[] = { 0x00, 0xAA, 0xBB, 0xCC, 0xDE, 0x02 }; //MAC Address
//IPAddress ip = (192,168,1,200); //Fixed IP Address if required

void WizReset() {
Serial.println("Reset Wiz W5500 Ethernet...");
pinMode(WIZRST, OUTPUT);
digitalWrite(WIZRST, HIGH);
delay(500);
digitalWrite(WIZRST, LOW);
delay(50);
digitalWrite(WIZRST, HIGH);
delay(500);
}

void setup() {
  Ethernet.init(WIZCS);  // SPI CS Pin

  // Open serial communications and wait for port to open:
  Serial.begin(9600);
  Serial.println();
  Serial.println("Hello..");
  SPI.begin();
  while (!Serial) {
; // wait for serial port to connect. Needed for native USB port only
  }

  //Reset Wiznet W5500
  WizReset();
   
  // start & check the Ethernet connection:
  Serial.println("Starting Ethernet....");
  Ethernet.begin(mac);
  Enet = 1;
  if (Ethernet.hardwareStatus() == EthernetNoHardware) {
  Serial.println("Ethernet shield was not found.  Sorry, can't run without hardware. :(");
  Enet = 0;
} else if (Ethernet.linkStatus() == LinkOFF) {
  Serial.println("Ethernet cable is not connected.");
  Enet = 0;
}
//Check to see if Ethernet is connected, if not attempt connection with WiFi
  if (Enet == 0){
WiFi.disconnect(); //Remove previous SSID & Password
WiFi.begin(ssid, password);             // Connect to the network
Serial.print("WiFi Connecting to ");
Serial.print(ssid); Serial.println(" ...");

int i = 0;
while (WiFi.status() != WL_CONNECTED) { // Wait for the Wi-Fi to connect
  delay(1000);
  Serial.print(++i); Serial.print(' ');
}

Serial.println('\n');
Serial.println("Connection established!");  
Serial.print("Local WiFi IP address: ");
Serial.println(WiFi.localIP());         // Send the IP address of the ESP8266 to the computer
  } 
// print your local Ethernet IP address if Ethernet is connected
  if (Enet == 1){
  Serial.print("Local Ethernet IP address: ");
  Serial.println(Ethernet.localIP());
  }
  
//Basic thinger.io resource (system timer)
thing["millis"] >> [](pson& out){ out = millis(); };
}

void loop() {
   thing.handle(); 
}

Hi,

What I would do is to define a diferent “thing” by each connection, and call the appropriate according the situation.

something like:

    ThingerEthernet thing(USERNAME, DEVICE_ID, DEVICE_ID);
    ThingerESP8266 thing2(USERNAME, DEVICE_ID, DEVICE_ID);

And of course you need to define the same resources for both "thing"s:

thing["millis"] >> [](pson& out){ out = millis(); };
thing2["millis"] >> [](pson& out){ out = millis(); };

And in the loop, you need to make the call according if you are working by ethernet or wifi

thing.handle(); or thing2.handle(); I would identify it with a boolean variable into the setup when the uC detects which connect is working with.

Hope this helps.

Hello

Works like a dream, thanks.

I have pasted the final code, but I have another couple of questions which I have added below.

/*
Test to get ESP8266 talking to thinger.io via ESP8266 & Wiznet w5500 Ethernet shield
V1 - Original code
  •Problem with Ethernet library from ESP8266 libraries being called by IDE in favour of using the standard Arduino Ethernet library
    ESP8266 Ethernet library isnt as good as the standard Arduino one and lacks some of the functions.
    Renamed ESP8266 Ethernet.h & cpp files to EthernetESP8266 so that the IDE would ignore them
  •Problem with wiring between ESP8266 & W5500
    >Changed pins for reset & CS.
      Set code to manually excercise Reset Pin
      Used  Ethernet.init function to set CS to another pin.
    >Compiler complaining with an error about IPAddress and ESP8266
      Found solution in comments on https://esp8266hints.wordpress.com/2018/02/13/adding-an-ethernet-port-to-your-esp-revisited/
            ##Thanks to Tony Onofrio for this##
        >>Changed Ethernet.cpp file to add in.....
          You need to change after line 85 –
            #if ARDUINO > 106 || TEENSYDUINO > 121
              to
            #if defined(ARDUINO_ARCH_ESP8266)
            W5100.setIPAddress(ip.raw_address());
            W5100.setGatewayIp(gateway.raw_address());
            W5100.setSubnetMask(subnet.raw_address());
            #elif ARDUINO > 106 || TEENSYDUINO > 121
          
 V2 - Add in thinger.io stuff
  had to addin ThingerEthernet library because ThingerESP8266 automaticaly tries to connect via WiFi
 V3 - Add in ability to connect via WiFi as well as Ethernet
 V4 - Created 2nd instance of 'thing' to allow thinger.io to work with either ethernet or wifi whichever was available.
    >This solution was posted on https://community.thinger.io/t/using-wifi-or-ethernet-with-esp8266-nodemcu-w5500/3866/2
 */

#define _DEBUG_

#include <SPI.h>
#include <Ethernet.h>
#include <ThingerEthernet.h>
#include <ThingerESP8266.h>
#include <ESP8266WiFi.h>        // Include the Wi-Fi library

#define WIZRST 16 //Specify pin to use for reseting W5500
#define WIZCS 5 //Specify the pin for SPI CS

#define USERNAME "xxxxxx"    //Thinger Account User Name
#define DEVICE_ID "xxxxxx"     //Thinger Device ID ## NOTE This is the device serial number ##
ThingerEthernet thing1(USERNAME, DEVICE_ID, DEVICE_ID);
ThingerESP8266  thing2(USERNAME, DEVICE_ID, DEVICE_ID);
  
const char* ssid     = "xxxxxx";         // The SSID (name) of the Wi-Fi network you want to connect to
const char* password = "xxxxxx";     // The password of the Wi-Fi network
byte Enet = 0; //1 = Ethernet connection is available
byte wiFi = 0; //1 = Wifi connection

byte mac[] = { 0x00, 0xAA, 0xBB, 0xCC, 0xDE, 0x02 }; //MAC Address
//IPAddress ip = (192,168,0,88); //Fixed IP Address

void WizReset() {
    Serial.println("Reset Wiz W5500 Ethernet...");
    pinMode(WIZRST, OUTPUT);
    digitalWrite(WIZRST, HIGH);
    delay(500);
    digitalWrite(WIZRST, LOW);
    delay(50);
    digitalWrite(WIZRST, HIGH);
    delay(500);
}

void setup() {
  Ethernet.init(WIZCS);  // SPI CS Pin

  // Open serial communications and wait for port to open:
  Serial.begin(9600);
  Serial.println();
  Serial.println("Hello..");
  SPI.begin();
  while (!Serial) {
    ; // wait for serial port to connect. Needed for native USB port only
  }

  //Reset Wiznet W5500
  WizReset();
   
  // start & check the Ethernet connection:
  Serial.println("Starting Ethernet....");
  Ethernet.begin(mac); //Connect using DHCP
  //Ethernet.begin(mac,ip); //Connect using Fixed IP
  Enet = 1;
  if (Ethernet.hardwareStatus() == EthernetNoHardware) {
      Serial.println("Ethernet shield was not found.  Sorry, can't run without hardware. :(");
      Enet = 0;
    } else if (Ethernet.linkStatus() == LinkOFF) {
      Serial.println("Ethernet cable is not connected.");
      Enet = 0;
    }
//Check to see if Ethernet is connected, if not attempt connection with WiFi
  if (Enet == 0){
    WiFi.disconnect(); //Remove previous SSID & Password
    WiFi.begin(ssid, password);             // Connect to the network
    Serial.print("WiFi Connecting to ");
    Serial.print(ssid); Serial.println(" ...");

    int i = 0;
    while (WiFi.status() != WL_CONNECTED) { // Wait for the Wi-Fi to connect
      delay(1000);
      Serial.print(++i); Serial.print(' ');
    }

    Serial.println('\n');
    Serial.println("Connection established!");  
    Serial.print("Local WiFi IP address: ");
    Serial.println(WiFi.localIP());         // Send the IP address of the ESP8266 to the computer
    wiFi = 1; //Set Wifi flag to ON
  } 
// print your local Ethernet IP address if Ethernet is connected
  if (Enet == 1){
  Serial.print("Local Ethernet IP address: ");
  Serial.println(Ethernet.localIP());
  }

  if (Enet ==0 && wiFi ==0){
    Serial.println("Unable to connect to Ethernet or Wifi");
  }
  
//Basic thinger.io resource (system timer & Connection Type)
    thing1["millis"] >> [](pson& out){ out = millis(); };
    thing2["millis"] >> [](pson& out){ out = millis(); };

    thing1["Connection"] >> [](pson& out){ out = "Ethernet"; };
    thing2["Connection"] >> [](pson& out){ out = "WiFi"; };
}

void loop() {
   if (Enet ==1){ //If ethernet is connected then run thing1 instance
    thing1.handle();
    Ethernet.maintain(); //required to renue the DHCP. 
   }
   if (wiFi ==1){ //If wifi is connected then run thing1 instance
    thing2.handle();  
   }
   
}
  1. The DEBUG stream shows that ThingerEthernet is connecting via another different IP address. I have checked the ThingerEthernet library and it appears that a different MAC address is being assigned so I guess the router then sees this as a separate connected device and assigns a new IP. The code in the library doesn’t seem to recognise that the Ethernet connection has already been made, which is why it connects again, (a) why is this 2nd connection being made and (b) can I just comment out the byte mac[] variable definition in the library.

  2. The DEBUG stream states that SSL/TLS is not being used. I am fairly new to IOT stuff so can you please let me know if SSL/TLS should be used for wired ethernet connection. (I’m assuming that it should probably be used regardless of the connection type, but I cannot find anyway of enabling it for the Ethernet connection).

    Hello…
    Reset Wiz W5500 Ethernet…
    Starting Ethernet…
    Local Ethernet IP address: 192.168.0.48
    [NETWORK] Starting connection…
    [NETWORK] Initializing Ethernet…
    [NETWORK] Got IP Address: 192.168.0.60
    [NETWORK] Connected!
    [_SOCKET] Using secure TLS/SSL connection: no
    [_SOCKET] Connected!
    [THINGER] Authenticating. User: Mark_Austin Device: Scratch
    [THINGER] Writing bytes: 38 [OK]
    [THINGER] Authenticated

Thanks

Hi,

Im glad the suggetions worked for you

I guess the 2nd connection is being made because the library does not recognizes that it is already connected, maybe you may comment those actions in the library, if you want to connect by other commands, I dont think it is neccesary needed to use the commands into the library, just have the link to try the upper layer connection, but I’m not an expert in this field.

I think I have read in other post that the SSL support is not available for ethernet connection, maybe we need to wait until they update this into a new library version.

Regards.