• Not sure if anyone else has tried this or had any luck, but the ESP8266 in the Espruino Wifi has built in functionality to simultaneously be an AP as well as a station/client.

    The functionality isn't exposed in the Espruino libraries, so a little work is required to get it into the right mode, and I feel like I'm almost there, but something isn't quite right and I get the feeling the Espruino http library is to blame.

    Try out the following code, and what should be able to happen is that if you connect to the AP that the Espruino makes, and visit http://192.168.4.1 (assuming it gets this IP, which in my testing it usually does), the Espruino should fetch a http resource. However, I seem to get stuck in some sort of loop

    got http request
    fetching page
    got http request
    fetching page
    got http request
    fetching page
    got http request
    fetching page
    got http request
    fetching page
    Uncaught Error: No free sockets
    at line 1 col 278
    ...row Error("No free sockets");

    which to me indicates something odd is going on in the http lib.

    Does anyone have any ideas?

    const wifi = require("EspruinoWiFi");
    
    const startDual = (callback) => {
      const at = wifi.at;
    
      at.cmd('AT+CWMODE=3\r\n', 1000, (cwm) => {
        if (cwm!="no change" && cwm!="OK" && cwm!="WIFI DISCONNECT")
          callback("CWMODE failed: "+(cwm?cwm:"Timeout"));
        else
          callback(null);
      });
    };
    
    const connect = (_apName, _apKey, callback) => {
      const apName = JSON.stringify(_apName);
      const apKey = JSON.stringify(_apKey);
      const at = wifi.at;
      
      at.cmd("AT+CWJAP="+apName+","+apKey+"\r\­n", 20000, function cb(d) {
        if (["WIFI DISCONNECT","WIFI CONNECTED","WIFI GOT IP","+CWJAP:1"].indexOf(d)>=0) {
          return cb;
        }
        if (d!="OK") {
          setTimeout(callback,0,"WiFi connect failed: "+(d?d:"Timeout"));
        } else {
          setTimeout(callback,0,null);
        }
      });
    };
    
    const becomeAP = (ssid, options, callback) => {
      const at = wifi.at;
      options = options||{};
      
      if (!options.password || options.password.length<8) throw new Error("Password must be at least 8 characters");
      var enc = options.password?"3":"0"; // wpa2 or open
      if (options.authMode) {
        enc={
          "open":0,
          "wpa":2,
          "wpa2":3,
          "wpa_wpa2":4
        }[options.authMode];
        if (enc===undefined) throw new Error("Unknown authMode "+options.authMode);
      }
      if (options.channel===undefined) options.channel=5;
    
      at.cmd("AT+CWSAP="+JSON.stringify(ssid)+­","+JSON.stringify(options.password)+","­+options.channel+","+enc+"\r\n", 5000, function(cwm) {
          if (cwm!="OK") callback("CWSAP failed: "+(cwm?cwm:"Timeout"));
          else callback(null);        
        });
    };
    
    const startServer = () => {
      var http = require("http");
      
      //start a server
      http.createServer(function (req, res) {
        console.log('got http request');
        
        // break context in case something is weird.
        setTimeout(() => {
          console.log('fetching page');
          
          // fetch a resource
          http.get("http://www.pur3.co.uk/hello.tx­t", function(clientRes) {
            console.log("Response: ",clientRes);
            clientRes.on('data', function(d) {
              console.log("--->"+d);
            });
          });
        }, 1000);
      }).listen(80);
    };
    
    // Force a scan so that 'at' gets assigned
    wifi.scan((err, result) => {
      if (err) { throw err; }
      
      startDual((err) => {
        if (err) { throw err; }
        
        // Connect to a real AP
        connect('apSSID', 'apPass', (err) => {
          if (err) { throw err; }
          
          console.log('wifi connected');
          
          // Become an AP
          becomeAP('newSSID', {
            password: 'newPass',
            authMode: 'wpa2',
          }, (err) => {
            if (err) { throw err; }
            
            console.log('ap started');
            
            // Fetch some resource to prove we can
            require("http").get("http://www.pur3.co.­uk/hello.txt", function(res) {
              console.log("Response: ",res);
              res.on('data', function(d) {
                console.log("--->"+d);
              });
              res.on('end', () => {
                // start a http server
                startServer();
              });
            });
          });
        });
      });
    });
    
About

Avatar for dave_irvine @dave_irvine started