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):
ESPRUINOonESP8266:
// Espruino on ESP8266
var creds = require("creds"), ip;
console.log("Connectin wifi...");
wifi.connect(creds.ssid, {password: creds.pwd}, function(err){
app(err);
});
ESPRUINOwithESP8266:
// Espruino with ESP8266
var creds = require("creds"), ip;
Serial2.setup(115200, { rx: A3, tx : A2 });
var wifi = require("ESP8266WiFi_0v25").connect(Serial2, 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);
});
});
}
This setup maximizes the reuse and minimizes the code different to the wifi options.
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
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");).
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...
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);
});
});
}
Espruino is a JavaScript interpreter for low-power Microcontrollers. This site is both a support community for Espruino and a place to share what you are working on.
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 with ESP8266:
Shared application code that also handles getting the IP address:
Console output:
Notes:
"creds"
is my credential module in my project sandbox modules folder (a single line withexports = { ssid: "MySSID", pwd: "myPassword" };
. It enables to pull the credentials from a single point and hide them from the codeapp()
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");
)..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...If you do not like running functions unnecessarily nested, you can split
app()
into two pieces: apreText(err, ip) {...}
function and anapp() {...}
function.preText()
calls first itself as callback and then it callsapp()
in a timeout. That way the execution stack is completely pop-ed (as max as possible). - Don't forget to change invocation inwifi.connect(...)
callback fromapp(err, ip);
topreText(err, ip);
: