jeelabs / esp-link

esp8266 wifi-serial bridge, outbound TCP, and arduino/AVR/LPC/NXP programmer
Other
2.82k stars 720 forks source link

[Solved] How I can get the IP address of the esp-link over SLIP? #418

Closed rtek1000 closed 5 years ago

rtek1000 commented 5 years ago

Hello,

I tried the El-Client software to do a UDP transmission to tell the client their IP, like as the arduino system, but I do not know how I can get the IP address of the esp-link over SLIP.

The broadcast worked, but I can not get the ID hostname or IP of the esp-link.

I found a sample code (maybe not official) that does not work, the routines return 0 at all.

Is it possible for a UDP to post its IP address and ID (to 255.255.255.255) after the uC sends a command through SLIP?

I tried to make mDNS Android APP, but I have no success, apparently older systems with Android does not support mDNS.

rtek1000 commented 5 years ago

Hello, good news!!!

The IP found by the El-client,

The problem seems to be the ESP-01, which has 8Mbits of EEPROM.

This log below was obtained with NodeMCU Lolin V3 with 32Mbtis of EEPROM.

I suspected the behavior of the ESP-01, and I suspected also the program ESPFlashDownloadTool_v3.6.4.exe whenever I try to use it the LED of the NodeMCU flashes, even if it appears "Finish".

With the program ESP8266Flasher.exe, the NodeMCU did not blink anymore, the boot was perfect.

ESP8266Flasher.exe (About):

If you have any questions, please contact me. Vowstar vowstar@gmail.com NodeMcu is a powerful tool for software engineers to program from HardwareIO to Wifi network within several minites. This programmer can flash esp8266 by one click. Our website is http://www.nodemcu.com Our Tencent QQ Group:309957875.

Result of NodeMCU + esp-link v3.2.47 + El-Client (and ESP8266Flasher.exe): (MAC edited)

ELClient test : show IP information 04:03:41.260 -> EL-Client synced! IP Address 192.168.1.42 04:03:43.319 -> Network mask 255.255.255.0 04:03:43.366 -> IP Gateway 192.168.1.1 04:03:43.366 -> MAC Address : A0:B1:C2:D3:E5:F4 04:03:43.413 -> MQTT client id : esp-link

El-Client source: https://github.com/jeelabs/el-client/tree/dd51416303b541e4e3d77d24cf47978824f4921d

#include <Arduino.h>
#include <ELClient.h>
#include <ELClientCmd.h>

// Forward declarations
void wifiCb(void *response);

// Initialize a connection to esp-link using the normal hardware serial port both for
// SLIP and for debug messages.
ELClient esp(&Serial, &Serial);
ELClientCmd cmd(&esp);

boolean wifiConnected = false;

#define IP(x, y) ((int)((x >> (8*y)) & 0xFF))
static char buffer[80];

void setup() {
  Serial.begin(9600);   // Match the esplink config (Arduino serial <-> ESP)
  delay(3000);
  Serial.println("ELClient test : show IP information");

  esp.wifiCb.attach(wifiCb); // wifi status change callback, optional (delete if not desired)
  bool ok;
  do {
    ok = esp.Sync();      // sync up with esp-link, blocks for up to 2 seconds
    if (!ok) Serial.println("EL-Client sync failed!");
  } while(!ok);
  Serial.println("EL-Client synced!");

  uint32_t ip, nm, gw;
  cmd.GetWifiInfo(&ip, &nm, &gw);

  sprintf(buffer, "IP Address %d.%d.%d.%d\n", IP(ip, 0), IP(ip, 1), IP(ip, 2), IP(ip, 3));
  Serial.print(buffer);
  sprintf(buffer, "Network mask %d.%d.%d.%d\n", IP(nm, 0), IP(nm, 1), IP(nm, 2), IP(nm, 3));
  Serial.print(buffer);
  sprintf(buffer, "IP Gateway %d.%d.%d.%d\n", IP(gw, 0), IP(gw, 1), IP(gw, 2), IP(gw, 3));
  Serial.print(buffer);

  char *mac = cmd.getMac();
  Serial.print("MAC Address : ");
  for (int i=0; i<6; i++) {
    char buf[4];
    if (i < 5)
      sprintf(buf, "%02X:", 0xFF & mac[i]);
    else
      sprintf(buf, "%02X", 0xFF & mac[i]);
    Serial.print(buf);
  }
  Serial.println("");

  // Query the MQTT clientid
  Serial.print("MQTT client id : ");
  char *mqtt_clientid = cmd.mqttGetClientId();
  Serial.println(mqtt_clientid);

}

void loop() {
  delay(100);
}

// Callback made from esp-link to notify of wifi status changes
// Here we print something out and set a global flag
void wifiCb(void *response) {
  ELClientResponse *res = (ELClientResponse*)response;
  if (res->argc() == 1) {
    uint8_t status;
    res->popArg(&status, 1);

    if(status == STATION_GOT_IP) {
      Serial.println("WIFI CONNECTED");
      wifiConnected = true;
    } else {
      Serial.print("WIFI NOT READY: ");
      Serial.println(status);
      wifiConnected = false;
    }
  }
}
swilson86 commented 5 years ago

Interesting script. I would LOVE to be able to MQTT publish wifi, IP, and MAC info to a database when a station boots. I too have problems with mDNS. Glad I stumbled upon your code.

When I try to compile it on Arduino for an ESP-01S I get: 'class ELClientCmd' has no member named 'GetWifiInfo'. I am running esp-link 3.0.14 and el-client dated 14-dec-2016 (no version).

rtek1000 commented 5 years ago

Hello, the El-Client is a library, it is available in the link above, it seems to be the same developers of esp-link, to compile, it is necessary to put the library in the Arduino folder, just like any other library, or in the user folder , usually documents, to prevent it from being deleted in an Arduino IDE update.

El-Client source: https://github.com/jeelabs/el-client/tree/dd51416303b541e4e3d77d24cf47978824f4921d

rtek1000 commented 5 years ago

Installing an Arduino Library: https://learn.sparkfun.com/tutorials/installing-an-arduino-library/all

rtek1000 commented 5 years ago

Note: The above code is listed in the examples

el-client lib others

rtek1000 commented 5 years ago

(Note, it may be necessary to restart esp8266 after an Arduino program recompile)

rtek1000 commented 5 years ago

esp-link v3 2 47 get-info

https://github.com/jeelabs/esp-link/releases

I used the "Upgrade Firmware" page of the esp-link to upgrade from "esp-link-v3.0.14" to "esp-link-v3.2.47"

It ran on ESP-01 with modified memory (from 25Q80 to 25Q64, need electronic welding process) and also with NodeMCU Lolin V3 (ESP-12).

With ESP-01 and 25Q80 memory did not work well.

swilson86 commented 5 years ago

Thanks. I have realized that the el-client you are using is a forked version. After installing that in my Arduino library I could compile. Had to modify your code slightly as most of my Arduinos have a watchdog timer, and once you use it you always have to use it. That being said, I get IP Address: 0.0.0.0 and all the others are zeros too.

Not sure what you mean by 25Q80 / 25Q64 or welding process. Are you referring to a setting when flashing the ESP-01S ??

rtek1000 commented 5 years ago

For:

I get IP Address: 0.0.0.0 and all the others are zeros too.

Please see if this helps: (Maybe, in AP mode, it is already assumed that the address is what was previously chosen, it certainly does not need to get it)

ap-0 s

About memory replacement, I did this because my esp-01 were unstable, flashing error, and the esp-link was very unstable too.

Only by flashing directly to the Arduino IDE did things become more stable, but not totally.

So I remembered in another module that I already had to change the memory, the HLK-RM04.

In fact, it was from this HLK-RM04 that I got the 25Q64 (which I bought years ago) and put it on the ESP-01, that's how I discovered that the esp-01 problem must be memory, little memory space, or maybe fake memory.

Errors like this were occurring:

esp-01 25q80

rtek1000 commented 5 years ago

udp send ip

Udp sample code combined with get-info:

/**
   Simple example to demo the El-Client UDP calls + GET-INFO (IP, MAC etc)
*/

#include <Arduino.h>
#include <ELClient.h>
#include <ELClientSocket.h>
#include <ELClientCmd.h>

// Forward declarations
void wifiCb(void *response);

#define IP(x, y) ((int)((x >> (8*y)) & 0xFF))
static char buffer[80];

// IP address for this demo is a local IP.
// Replace it with the IP address where you have a UDP socket server running
//char * const udpServer PROGMEM = "192.168.0.102"; // Send to single ip address
char * const udpServer2 PROGMEM = "255.255.255.255"; // Broadcast to given network ip mask
// Port for this demo is the port used by the UDP socket server.
// Replace it with the port that your UDP socket server is listening to
//uint16_t const udpPort PROGMEM = 5000;
uint16_t const udpPort2 PROGMEM = 22222;

//###########################################################
// For ARDUINO UNO WIFI with I2C to serial chip!
//###########################################################
// Serial port to ESP8266
//#include <SC16IS750.h>
//SC16IS750 i2cuart = SC16IS750(SC16IS750_PROTOCOL_I2C,SC16IS750_ADDRESS_AA);

// Initialize a connection to esp-link using the I2Cuart chip of the Arduino Uno WiFi board for
// SLIP messages.
//ELClient esp(&i2cuart);

//###########################################################
// For boards using the hardware serial port!
//###########################################################
// Initialize a connection to esp-link using the normal hardware serial port both for
// SLIP and for debug messages.
ELClient esp(&Serial, &Serial);

ELClientCmd cmd(&esp);

// Initialize a UDP client on the connection to esp-link
//ELClientSocket udp(&esp);
// Initialize a UDP client on the connection to esp-link
ELClientSocket udp2(&esp);

// Timer value to send out data
uint32_t wait;
// Time to wait between sending out data
uint32_t waitTime;
// Flag for wifi connection
boolean wifiConnected = false;

// Parse error codes and returns error message as char *
// Definitions from error values from espconn.h (Espressif SDK)
// #define ESPCONN_OK           0  /**< No error, everything OK.   */
// #define ESPCONN_MEM         -1  /**< Out of memory.             */
// #define ESPCONN_TIMEOUT     -3  /**< Timeout.                   */
// #define ESPCONN_RTE         -4  /**< Routing problem.           */
// #define ESPCONN_INPROGRESS  -5  /**< Operation in progress.     */
// #define ESPCONN_MAXNUM      -7  /**< Total number exceeds the maximum limitation. */

// #define ESPCONN_ABRT        -8  /**< Connection aborted.    */
// #define ESPCONN_RST         -9  /**< Connection reset.      */
// #define ESPCONN_CLSD       -10  /**< Connection closed.     */
// #define ESPCONN_CONN       -11  /**< Not connected.         */

// #define ESPCONN_ARG        -12  /**< Illegal argument.      */
// #define ESPCONN_IF         -14  /**< UDP send error.        */
// #define ESPCONN_ISCONN     -15  /**< Already connected.     */

char* const errTxt[] PROGMEM = {"No error, everything OK.", "Out of memory.", "Unknown code.", "Timeout.", "Routing problem.", "Operation in progress.",
                                "Unknown code.", "Total number exceeds the maximum limitation.", "Connection aborted.", "Connection reset.", "Connection closed.",
                                "Not connected.", "Illegal argument.", "Unknown code.", "UDP send error.", "Already connected."
                               };
char * getErrTxt(int16_t commError) {
  commError = commError * -1;
  if (commError <= 15) {
    return (char *) pgm_read_word (&errTxt[commError]);
  } else {
    return (char *) pgm_read_word (&errTxt[2]); // Unknown code
  }
}

// Callback for UDP socket, called if data was sent or received
// Receives socket client number, can be reused for all initialized UDP socket connections
// !!! UDP doesn't check if the data was received or if the receiver IP/socket is available !!! You need to implement your own
// error control!
void udpCb(uint8_t resp_type, uint8_t client_num, uint16_t len, char *data) {
  Serial.println("udpCb is called");
  if (len > 0) { // sending complete (no confirmation that it was received!) or we received something
    if (resp_type == USERCB_SENT) {
      Serial.println("\tSent " + String(len) + " bytes over connection #" + String(client_num));
    } else if (resp_type == USERCB_RECV) {
      char recvData[len + 1]; // Prepare buffer for the received data
      memcpy(recvData, data, len); // Copy received data into the buffer
      recvData[len] = '\0'; // Terminate the buffer with 0 for proper printout!

      Serial.println("\tReceived " + String(len) + " bytes over client#" + String(client_num));
      Serial.println("\tReceived: " + String(recvData));
    } else {
      Serial.println("Received invalid response type");
    }
  } else if (len < 0) { // negative result means there was a problem
    Serial.print(F("Send error: "));
    Serial.println(getErrTxt(len));
  }
}

// Callback made from esp-link to notify of wifi status changes
// Here we print something out and set a global flag
void wifiCb(void *response) {
  ELClientResponse *res = (ELClientResponse*)response;
  if (res->argc() == 1) {
    uint8_t status;
    res->popArg(&status, 1);

    if (status == STATION_GOT_IP) {
      Serial.println(F("WIFI CONNECTED"));
      wifiConnected = true;
    } else {
      Serial.print(F("WIFI NOT READY: "));
      Serial.println(status);
      wifiConnected = false;
    }
  }
}

void setup() {
  delay(5000);

  Serial.begin(115200);
  //    i2cuart.begin(9600);
  Serial.println(F("EL-Client starting!"));

  // Sync-up with esp-link, this is required at the start of any sketch and initializes the
  // callbacks to the wifi status change callback. The callback gets called with the initial
  // status right after Sync() below completes.
  esp.wifiCb.attach(wifiCb); // wifi status change callback, optional (delete if not desired)
  bool ok;
  do {
    ok = esp.Sync();            // sync up with esp-link, blocks for up to 2 seconds
    if (!ok) Serial.println(F("EL-Client sync failed!"));
  } while (!ok);
  Serial.println(F("EL-Client synced!"));

  // Get immediate wifi status info for demo purposes. This is not normally used because the
  // wifi status callback registered above gets called immediately.
  esp.GetWifiStatus();
  ELClientPacket *packet;
  if ((packet = esp.WaitReturn()) != NULL) {
    Serial.print(F("Wifi status: "));
    Serial.println(packet->value);
  }

  int err;
  // Set up the UDP socket client to send a short message to <udpServer> on port <>, this doesn't connect to that server,
  // it just sets-up stuff on the esp-link side
  //    int err = udp.begin(udpServer, udpPort, SOCKET_UDP, udpCb);
  //    if (err < 0) {
  //        Serial.print(F("UDP begin failed: "));
  //        Serial.println(err);
  //        delay(10000);
  //        asm volatile ("  jmp 0");
  //    }

  err = udp2.begin(udpServer2, udpPort2, SOCKET_UDP, udpCb);
  if (err < 0) {
    Serial.print(F("UDP2 begin failed: "));
    Serial.println(err);
    delay(10000);
    asm volatile ("  jmp 0");
  }

  Serial.println(F("EL-Client ready!"));
  wait = millis() + 29000; // Start first sending in 1 second
}

void loop() {
  // process any callbacks coming from esp_link
  esp.Process();

  // if we're connected send data over UDP socket
  if (wifiConnected) {
    if (millis() - wait > 5000) { // Send some data every 30 seconds
      wait = millis();
      uint32_t ip, nm, gw;
      cmd.GetWifiInfo(&ip, &nm, &gw);

      sprintf(buffer, "IP Address %d.%d.%d.%d\n", IP(ip, 0), IP(ip, 1), IP(ip, 2), IP(ip, 3));
      Serial.print(buffer);
      sprintf(buffer, "Network mask %d.%d.%d.%d\n", IP(nm, 0), IP(nm, 1), IP(nm, 2), IP(nm, 3));
      Serial.print(buffer);
      sprintf(buffer, "IP Gateway %d.%d.%d.%d\n", IP(gw, 0), IP(gw, 1), IP(gw, 2), IP(gw, 3));
      Serial.print(buffer);

      char *mac = cmd.getMac();
      Serial.print("MAC Address : ");
      for (int i = 0; i < 6; i++) {
        char buf[4];
        if (i < 5)
          sprintf(buf, "%02X:", 0xFF & mac[i]);
        else
          sprintf(buf, "%02X", 0xFF & mac[i]);
        Serial.print(buf);
      }
      Serial.println("");

      // Query the MQTT clientid
      Serial.print("MQTT client id : ");
      char *mqtt_clientid = cmd.mqttGetClientId();
      Serial.println(mqtt_clientid);

      // Send message to the previously set-up server #1
      //            Serial.print(F("Sending message to "));
      //            Serial.println(udpServer);
      //            udp.send("Message from your Arduino Uno WiFi over UDP socket");

      // Send message to the previously set-up server #2
      Serial.print(F("Sending broadcast to "));
      Serial.println(udpServer2);
      udp2.send("Broadcast from your 'Arduino Uno WiFi' over UDP socket:\n");
      sprintf(buffer, "IP Address %d.%d.%d.%d\n", IP(ip, 0), IP(ip, 1), IP(ip, 2), IP(ip, 3));
      udp2.send(buffer);
    }
  } else {
    // This is just for demo, you can as well just try to reconnect
    // and setup the connection to esp-link again
    Serial.println(F("Lost connection, try to reboot"));
    delay(10000);
    asm volatile ("  jmp 0");
  }
}
swilson86 commented 5 years ago

I have everything working! I did not weld (solder) any new memory chip on my ESP-01S, just a standard stock module I bought on eBay a few months ago. One thing different... flash addresses that I used for the ESP-01S which is a 8Mbit module are:

0x00000 boot_v1.7.bin 0x01000 user1.bin 0xFC000 esp_init_data_default.bin 0xFE000 blank.bin

This is recommended on the page https://github.com/jeelabs/esp-link/blob/master/FLASHING.md and I see you are using different addresses. All my other settings are identical to yours.

I used the ESP8266 Download Tool 3.6.5 and flashed the chip with an FTDI232 module. I was unable to firmware upgrade from "esp-link-v3.0.14" to "esp-link-v3.2.47" over the air.

Thanks for your excellent help in solving this. I feel a bit uneasy using esp-link Alpha software, and a forked version of el-client, but the benefits may outweigh that. I'll test this software setup in some non-critical things and see if it can run for a month without error. I hope anyone in the future can refer to our conversations as it will really help them out.

Also, Thorsten von Eicken (jee-labs guru) and Xose Perez (Espurna) are toying with the idea of esp-link version 4 as a joint project. This would be fantastic as Xose's code has far superior networking capability and it also sends out JSON every few minutes containing things like MAC address, ip, date/time and a lot more. This to me is one of the biggest upcoming things for 2018/early 2019.

rtek1000 commented 5 years ago

0x00000 boot_v1.7.bin 0x01000 user1.bin 0xFC000 esp_init_data_default.bin 0xFE000 blank.bin

Very good, I'll try, thank you!

I do not know about the progress of these projects, esp-link and el-client, I think developers are more concerned about other things. Has a chat that has activity yet:

Contact If you find problems with esp-link, please create a github issue. If you have a question, please use the gitter chat link at the top of this page.

https://github.com/jeelabs/esp-link

rtek1000 commented 5 years ago

0x00000 boot_v1.7.bin 0x01000 user1.bin 0xFC000 esp_init_data_default.bin 0xFE000 blank.bin

I tried the addresses that you told me (for esp-01 and 25Q80), it looks like it got more stable, but it still did not work correctly the firmware upgrade part, anyway, I appreciate it.

swilson86 commented 5 years ago

After my testing in the next month I will keep you posted if I learn anything new. Using the ESP8266 tool is sometimes crazy getting communications established. I frequently get comm errors and have to power off/on the FTDI module and try again. Also, I always erase any unknown chip before programming it.

The conversations on esp-link v 4 are at: https://github.com/xoseperez/espurna/pull/1314#issuecomment-438095825

Interesting to see when a release candidate will be ready.

swilson86 commented 5 years ago

I've been running about 25 esp-link/el-client stations (ESP-01s and Arduino) on my network for 5 months using snippets of your code above. Rarely has any station failed or locked up. Once in a while a station will boot with all 0.0.0.0 for the IP address, probably a timing issue.

uzi18 commented 5 years ago

@tve should be added to ELClient, if it is supported by 3.2.x firmware

brandon-feder commented 9 months ago

I have followed this post, and am able to compile and upload the posted code, but am getting the EL-Client sync failed! error. Is it required to use firmware v3.2?

uzi18 commented 9 months ago

First find in issues my build for 3.2 and use latest el-client library.

uzi18 commented 9 months ago

@brandon-feder exactly This copy of EL-Client: https://github.com/dannybackx/el-client