Architecture: WiFi support for WiFi enabled boards ...

Posted on
Page
of 3
Prev
/ 3
Next
  • WRT IPv6, no, the esp8266 doesn't, but I believe WICED does. In any case, IPv6 should become really important with IoT stuff so I'd plan for it. But I was really referring to JS-land, so strings it is.

    Since the Socket library has a capital S I'll change to Wifi. WiFi is just too awkward IMHO and I've never seen it used anywhere other than trademarks.

    I'm not a python wiz (never written any real python code) so if you could spare half an hour to tinker I would very much appreciate!

    (I updated the doc file)

  • I'm having second thoughts about Wifi.getStatus (file:///H:/src/esp8266/Espruino/functio­ns.html#l_Wifi_getStatus). It's missing a number of fields, specifically, the AP's ssid, password, and authentication mode. I suspect there will be more down the road. That makes for a very long list of things to gather and return. I wonder how long it would take with the esp8266 AT firmware at 9600 baud... I propose to split the call into getStatus (station status) and getAPStatus. Other names are OK with me, but so far we have a similar scheme for getIP and getAPIP.

  • It's a good point... Yes, I think that makes a lot of sense. After all, you're going to know what information you're interested in - and on other devices that don't do AP, those functions just get left out.

  • Moar stuff as I continue to go through code...

    Errors and callbacks: in some cases there are "expected" errors, such as a bad password in a connect call. In those cases I think the best is to pass an err param to the callback which is null on success and an error string on failure. (This is what the current spec more or less has.) But there are also other errors, such as disabling the AP mode failing (not sure what would cause that, maybe if it wasn't enabled or the new default can't be saved to flash). In those cases I think it's best to raise an exception, just like we do if the user passes a callback argument that is not a function. Otherwise everything everywhere will have err returns and err arguments, and that just clutters stuff to be ignored in 99% of cases.

    Currently connect/disconnect/startAP/stopAP take an option that specifies whether the change is to be saved as boot-up default. I'm finding that this leads to lots of if statements, is not cleanly implementable on the esp8266, and I'm not sure it's all that great to use. In particular, this option kind'a suck on the connect() call because you have to commit to saving the setting before knowing whether the connection actually works. So if the user specifies a bad password and the new config is saved no-one is happy.

    I'm wondering whether a separate save call that saves "everything" to flash for the next boot-up would not be better. (I'd implement the saving in Espruino as opposed to relying on the SDK, I think.)

  • Q: how do I implement the "on" event callbacks? The difficulty I have is that Wifi is a library. In order to queue a callback, I believe I need to use:

    jsiQueueObjectCallbacks(wifi, eventName, params, 1);
    

    where wifi is the wifi library object. But I believe there is no such thing? Suggestions for implementing the events on a global singleton?

  • Assuming what you want to do is invoke a JavaScript function next time around the idle loop AND there is no "this" JavaScript context needed, then I think the solution would be to call:

    jsiQueueEvents(NULL, jsCallbackFunction, params, count)

    Where jsCallbackFunction is a reference to a JsVar that is a function reference.

  • Ugh, all this is turning into a ton of work... I split getStatus and revamped the auto-at-boot stuff into a simple save() function. Overall, things are a lot simpler both from an interface and an implementation point of view. However, I did add a lot more functionality to the whole library. I updated the html docs: http://s3.voneicken.com/espruino/functio­ns.html#t_Wifi

  • Phew, a few more changes later I have it almost all implemented. Main features missing are the "on" event handlers (I need Gordon's help for how to do that) and the save() function. Everything now has a functional test, which isn't 100% but exercises all the functions.
    I updated the docs.

  • Thanks - yes, I'll have a think about this and will try and come up with an example...

  • Lemme, know, 'cause the "on" event handlers are the only piece missing at this point.

  • Yeah, I'll look today. Ended up quite bust yesterday trying to catch up after the weekend.

  • Ok, so you'll need to do:

    include "jswrap_modules.h" // for jswrap_require
    
    /*JSON{
        "type": "library",
        "class" : "foo"
    }*/
    
    static JsVar *getFooModule() {
      JsVar *moduleName = jsvNewFromString("foo");
      JsVar *m = jswrap_require(moduleName);
      jsvUnLock(moduleName);
      return m;
    }
    
    /*JSON{
        "type" : "staticmethod",
        "class" : "foo",
        "name" : "bar",
        "generate" : "jswrap_foo_bar"
    }*/
    void jswrap_foo_bar() {
      JsVar *module = getFooModule();
      if (!module) return; // out of memory?
      jsiQueueObjectCallbacks(module, "#onbob", NULL, 0);
      jsvUnLock(module);
    }
    

    and then this works:

    >require("foo").on("bob",function() { print('Hello'); });
    =undefined
    >require("foo").bar()  
    =undefined
    Hello
    

    It's a bit nasty. With the prototype chain branch I'm hoping to tidy it up so you'll be able to do:

    /*JSON{
        "type" : "method", // <----- changed
        "class" : "foo",
        "name" : "bar",
        "generate" : "jswrap_foo_bar"
    }*/
    void jswrap_foo_bar(JsVar *module) {
      jsiQueueObjectCallbacks(module, "#onbob", NULL, 0);
    }
    

    But right now I think the safest method is above, and should be easy enough to tweak later on.

  • cool, thanks!

  • That worked well! Next issue... do you have a pattern somewhere for using timers in native code? When a wifi connection attempt fails I'd like to schedule a reconnection attempt a few seconds out. How do I do that?
    (Background is that the SDK auto reconnects, but every second, and on battery that's a total killer. So I'd like to implement my own reconnection logic with exponential back-off.)

  • I haven't personally done it, but something like this should work fine:

    include "jswrap_interactive.h"
    
    void doStuff() {
    }
    
    JsVar *func = jsvNewNativeFunction(doStuff, JSWAT_VOID);
    jsvUnLock(jswrap_interface_setTimeout(fu­nc, 1000/*ms*/, 0));
    jsvUnLock(func);
    
  • I just created a PR with the new Wifi library. Docs can be found at https://s3.voneicken.com/espruino/functi­ons.html and a build at http://www.espruino.com/binaries/travis/­7390e23a1e475a882edc9bbc20f0893947c7b925­/espruino_1v83.tve_wifi_7390e23_esp8266.­tgz

    Dunno whether anyone is up for giving it a test spin. This does not change any of the socket code and I broke neopixelWrite due to too little static RAM. I'll figure out how to get it back in...

    I have two open items in the Wifi library: doing retries in the library instead of SDK when no association can be established and adding static IP support.

  • @tve are there particular bits to test? I think I've been using the wifi object rather than the ESP8266WiFi object for a bit now. I can flash this build tonight and test my basic apps, but if there are new/specific bits of of the module to test, happy to try help.

  • @tve I can run some tests as well, any specific things or the whole wifi ?

  • The whole wifi library/class. Connect/disconnect/AP/callbacks all the getters, save()/reboot.

    I tried to document everything, but I write terse docs, kind'a "minimal but complete info" strategy, so typically there is stuff that needs to be expanded on. So don't hesitate to flag that.

  • Gordon, currently when loading the new Wifi library the IDE prints out a warning "Wifi module not found". How do I teach the IDE that Wifi is a built-in module? Does that happen automatically once everything gets released?

  • Limited time to test so far. Only thing that jumped out tonight is that the "got_IP" event does not seem to fire - despite fact i can connect and use the "getIP" method.

    Also of interest (to me) the "probe_recv" event seems to fire (repeatedly) despite not being connected as AP or as Station - maybe this is expected behaviour? Interesting to think that other devices, simply by being, in range can trigger this event (just thinking out loud).

    Re the docs, it may be worth pointing out that all the callbacks receive an object literal as a single argument. People will try to access the vars direct otherwise and then wonder why they get an object and then undefined - I did :)

    Tests done so far:

    var wifi = require("Wifi");
    
    wifi.scan(function(params){
      console.log("params:" + JSON.stringify(params)); // Tested OK
    });
    
    // Connect 
    wifi.connect(SSID, {password: pwd}, function(){
      // Log IP address
      wifi.getIP(function(params){
        console.log("params:" + JSON.stringify(params)); // Tested OK
      });
      
      // Get Status
      wifi.getStatus(function(params){
        console.log("params:" + JSON.stringify(params)); // Tested OK
      });
      
      // Get Details
      wifi.getDetails(function(params){
        console.log("params:" + JSON.stringify(params)); // Tested OK
      });
    
      // Get IP address of host
      wifi.getHostByName("bbc.co.uk", function(params){
        console.log("params:" + JSON.stringify(params)); // Tested OK
      });
      
      // Wait 60 seconds
      setTimeout(function(){
        // Disconnnect
        wifi.disconnect(); // Tested OK
      }, 60000);
    
    });
    
    // Event tests
    wifi.on("connected", function(){
      console.log("Event fired: connected"); // Tested OK
    });
    
    wifi.on("disconnected", function(){
      console.log("Event fired: disconnected"); // Tested OK
    });
    
    wifi.on("got_ip", function(params) {
      console.log("Event fired: got_ip");
      console.log("params:" + JSON.stringify(params)); // Does not fire
    });
    
    wifi.on('probe_recv', function(params) {
      console.log("Event fired: probe_recv");
      console.log("params:" + JSON.stringify(params)); // Tested OK
    });
    
    
  • I may have incorrect docs, will look later. I replaced the "connected" event by, what i think is a more accurate "associated" event, and the "got_ip" by "connected". Part of the reason was that once someone adds static IP support the got_ip doesn't make much sense anymore, but getting "associated" and "connected" still does. So you can trigger off "connected" whether you have a static IP or a dynamic one.

    WRT probe_recv, you probably have the AP on. When you flash blank.bin the default is to have the AP on, which makes sense going forward because it will allow for serial-less operation.

    I'll fix the docs WRT callbacks.

  • Retested and "associated" and "connected" events work fine for me - I get the expected IP address on the latter.

  • You're right that the callbacks were described in the docs as having multiple parameters. I think I'm going to keep the single object param implementation and change the docs because that is more generic. It makes it easier to have a single event handler function for different events and it make is easier to add/remove info in other implementations without upsetting the entire function signature.

  • I updated the docs and hope that they now match implementation: s3.voneicken.com/espruino/functions.html­
    Thanks for pointing out the issues!!

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

Architecture: WiFi support for WiFi enabled boards ...

Posted by Avatar for Kolban @Kolban

Actions