Differences in getIP() syntax

Posted on
  • On an ESP8266 running v1.85

    var wifi = require("Wifi");
    wifi.connect(Netname, {password:Key}, function(err){
      console.log("connected? err=", err, "info=", wifi.getIP());
    });
    
    

    On an Espruino v1.85 board connected to an AT command ESP8266

    var wifi = require("ESP8266WiFi_0v25").connect(seri­al, function(err) {
      if (err) throw err;
    
      wifi.reset(function(err) {
        if (err) throw err;
        console.log("Connecting to WiFi");
        wifi.connect(SSID,key, function(err) {
          if (err) throw err;
          wifi.getIP(function(l,ip){console.log("I­P= ",ip,"\n\r"+l);});
    
    
  • The way I understand this is: on ESP8266, Espruino has direct, synchronous and blocking access to the ip information, and therefore does not need to handle asynchronousity. An Espruino connecting to a ESP8266 has to go through the non-blocking, asynchronous serial send and receive interfaces and therefore has to use the callback to provide the information 'where to resume' with the response.

    I do not like to see different code for logically the same thing... unfortunately with MCs, hardware is so close to the application that differences in it must be (heart) felt... Just noticed that for wifi.connect() the syntax is also different - this time for no obvious hardware reasons... probably just for historical (soft/firm-ware) reasons... :( - @Gordon / @tve ?

    Having to cater for two different interfaces for getIP() leads me again to use sort of a 'pico container'/sequence controller that manages serialization of asynchronous and regular calls. With such a construct, it is possible to have the very same application code after connecting.

    Without such a controller, the code could look like below where both wifi options share one and the same code for getting and printing the IP address (see lines 2..6 in third, shared code block):

    ESPRUINO on ESP8266:

    // Espruino on ESP8266
    var creds = require("creds"), ip;
    console.log("Connectin wifi...");
    wifi.connect(creds.ssid, {password: creds.pwd}, function(err){
      app(err);
    });
    

    ESPRUINO with ESP8266:

    // Espruino with ESP8266
    var creds = require("creds"), ip;
    Serial2.setup(115200, { rx: A3, tx : A2 });
    var wifi = require("ESP8266WiFi_0v25").connect(Seri­al2, function(err) {
      if (err) throw err;
      wifi.reset(function(err) {
        if (err) throw err;
        console.log("Connectin wifi...");
        wifi.connect(creds.ssid,creds.pwd, function(err) {
          app(err);
        });
      });
    });
    

    Shared application code that also handles getting the IP address:

    // shared app code
    function app(err,ip) {
      // Some pretext... getting IP addr when 'with' or 'on' ESP8266
      if (err) { throw err; } else if (!ip) { console.log("Connected."); }
      if (!ip) { if (!(ip = wifi.getIP(app))) return; }
      console.log("IP: " + ip);
      // Now you can do something, like an HTTP request
      require("http").get("http://www.pur3.co.­uk/hello.txt", function(res) {
        console.log("Response: ",res);
        res.on('data', function(d) {
          console.log("--->"+d);
        });
      });
    }
    

    Console output:

     1v85 Copyright 2016 G.Williams
    >echo(0);
    =undefined
    Connectin wifi...
    Connected.
    IP: 192.168.0.106
    Response:  {
      "headers": {
        "Date": "Mon, 02 May 2016 09:55:12 GMT",
        "Server": "Apache/2.2.14 (Ubuntu)",
        "Last-Modified": "Fri, 15 Nov 2013 15:42:26 GMT",
        "ETag": "\"c01036-d-4eb390b8a8d18\"",
        "Accept-Ranges": "bytes",
        "Content-Length": "13",
        "Vary": "Accept-Encoding",
        "Connection": "close",
        "Content-Type": "text/plain"
       },
      "httpVersion": "1.1",
      "statusCode": "200",
      "statusMessage": "OK"
     }
    --->Hello World!
    > 
    

    Notes:

    1. This setup maximizes the reuse and minimizes the code different to the wifi options.
    2. module "creds" is my credential module in my project sandbox modules folder (a single line with exports = { ssid: "MySSID", pwd: "myPassword" };. It enables to pull the credentials from a single point and hide them from the code
    3. the app() function or functions can be put into a module "app" as well to maximize reuse without having duplicates - copy-pastes - hanging around... (module content: exports = function(err, ip) {...}; and usage: var app = require("app");).
    4. Solution for same code for both options assumes that method .getIP() of "Wifi" module (for 'Espruino on ESP8266') does not care about arguments passed and always returns something that evaluates to true, and .getIP(...) of "ESP8266WiFi_... (for 'Espruino with ESP8266') always returns something that evaluates to false...
    5. If you do not like running functions unnecessarily nested, you can split app() into two pieces: a preText(err, ip) {...} function and an app() {...} function. preText() calls first itself as callback and then it calls app() in a timeout. That way the execution stack is completely pop-ed (as max as possible). - Don't forget to change invocation in wifi.connect(...) callback from app(err, ip); to preText(err, ip);:

      // shared preText and app code
      function preText(err,ip) {
      // Some pretext... getting IP addr when 'with' or 'on' ESP8266
      if (err) { throw err; } else if (!ip) { console.log("Connected."); }
      if (!ip) { if (!(ip = wifi.getIP(preText))) return; }
      console.log("IP: " + ip);
      setTimeout(app,0);
      }
      function app() {
      // Now you can do something, like an HTTP request
      require("http").get("http://www.pur3.co.­uk/hello.txt", function(res) {
      console.log("Response: ",res);
      res.on('data', function(d) {
        console.log("--->"+d);
      });
      });
      }
      
  • Yes, @allObjects has it right. You can't have a sync getIP when running with a separate ESP8266.

    Collectively we spent days discussing Wifi for ESP8266, and made a huge wiki page where we agreed on an API that would work for both.

    Ultimately it got totally ignored when ESP8266 was implemented though, and sadly it's stuck since I have no time to fix it :)

  • It was an interesting point @ClearMemory041063 brought up and a riddle to 'solve' with the least amount of different code... I enjoyed it.

  • Thanks for all the discussion and tricks to make things work.

  • FYI, getIP on the esp8266 also accepts a callback function, so if you want to write portable code you can stick to the async callback:

    wifi.getIP(function(x){console.log("got"­, x);})
    ={
      "ip": "192.168.0.197",
      "netmask": "255.255.255.0",
      "gw": "192.168.0.1",
      "mac": "5c:cf:7f:10:a2:42"
     }
    got {
      "ip": "192.168.0.197",
      "netmask": "255.255.255.0",
      "gw": "192.168.0.1",
      "mac": "5c:cf:7f:10:a2:42"
     }
    

    Collectively we spent days discussing Wifi for ESP8266, and made a
    huge wiki page where we agreed on an API that would work for both.

    Ultimately it got totally ignored when ESP8266 was implemented though,
    and sadly it's stuck since I have no time to fix it :)

    I'm not sure why you feel this way. Some of the stuff specified on that page didn't work or didn't mesh with reality. I tried to stick to it, but some of it neither made sense nor was it consistent.

  • Great to hear that .getIP(...) on ESP8266 accepts callback... So no need for the trickery I used if code. It still works, it just behaves flow-wise like async callback with 'no sick time', but with quite different callback argument: a rich object vs. just an IP as strin (can still be fixed/determined). Having a callbak with a different argument makes it actually worse than being just incompatible..

  • @tve sorry - it wasn't aimed at you... you didn't start the wiki and do the initial implementation. That was the slightly frustrating part :) Since then you've sanitised it quite a lot.

    It's great that it takes an optional callback - that makes things a lot easier. It's a shame about the different argument types - but to be honest I should really update the other libraries to be more like the ESP8266 one in that respect.

    With the first err argument - it's dumb, but it seemed to be what node.js did in most cases so I was trying to keep with that to keep things consistent, even if on some platforms err would never be used.

  • Post a reply
    • Bold
    • Italics
    • Link
    • Image
    • List
    • Quote
    • code
    • Preview
About

Differences in getIP() syntax

Posted by Avatar for ClearMemory041063 @ClearMemory041063

Actions