self-propagating code

Posted on
  • So this is it.
    Thanks to a few hints from @Gordon my first self-propagating Puck.js code
    (Kind of worm if you like)

    Feedback and improvements welcome.

    setSleepIndicator( LED3 );
    
    function transfer(device, text, callback) {
      var char;
      var result = "";
      console.log( "connecting " + device.name );
      return device.gatt.connect().then(function(d) {
        device = d;
        console.log( "connected" );
        return d.getPrimaryService("6e400001-b5a3-f393-­e0a9-e50e24dcca9e");
      }).then(function(s) {
        console.log( "service found" );
        return s.getCharacteristic("6e400002-b5a3-f393-­e0a9-e50e24dcca9e");
      }).then(function(c) {
        char = c;
        console.log( "characteristic found, sending..." );
        function sender(resolve, reject) {
          if (text.length) {
            char.writeValue(text.substr(0,20)).then(­function() {
              sender(resolve, reject);
            }).catch(reject);
            text = text.substr(20);
          } else  {
            console.log("finished");
            resolve();
          }
        }
        return new Promise( sender );
      }).then(function() {
        device.disconnect();
        if(callback) callback(true);
      }).catch(function() {
        console.log( "error" );
        if(callback) callback(false);
      });
    }
    
    function scan( callback ) {
      var result = [];
      NRF.findDevices(function(list) {
        for( var i = 0; i < list.length; i++ ) {
          var d = list[ i ];
          if( typeof d.name !== "undefined" && d.name.indexOf( "Puck.js" ) === 0 ) {
            console.log( "found " + d.name );
            result.push( d );
          }
        }
        callback( result );
      });
    }
    
    function spread() {
      var code = E.dumpStr();
    
      scan( function( queue ) {
        // recurse through queue
        function process() {
          if( queue.length ) {
              transfer( queue.pop(), code, function( result ) {
                console.log( "done" );
                setTimeout( process, 200 );
              });
          }
        }
        process();
      });
    }
    
    spread();
    

    Output for 4 Pucks:

    found Puck.js c9fc
    found Puck.js f002
    found Puck.js 38a4
    connecting Puck.js 38a4
    connected
    service found
    characteristic found, sending...
    finished
    done
    connecting Puck.js f002
    connected
    service found
    characteristic found, sending...
    finished
    done
    connecting Puck.js c9fc
    connected
    service found
    characteristic found, sending...
    finished
    done
    
  • Still can't figure out why my own example doesn't work when I change some bits, but just a note that line 43 should read

          if( typeof d.name !== "undefined" && d.name.indexOf( "Puck.js" ) === 0 ) {
    

    as typeof returns a string and you're not coercing type.

  • Thanks @trezm for pointing out. Just changed that bit.

    One think I'd like to improve is checking some version number before updating a remote.
    Then omit the update if the version is already there or higher.

    But without reading the response (not possible to receive notifications yet) this is tricky.
    Some thoughts:

    • just execute some verification code and let the peripheral hang up itself. Like if same or newer then disconnect(). Problem here: how can the central see the disconnect and move on? Tried it and catch() was not called. Maybe a watchdog with timeout?
    • implement another service just for reading the version first. More complex and less elegant.
    • waiting for a newer release so the UART response can be used.
      Other ideas?
  • Hi @ChristianW, one idea would be to advertise the installed version number. So when scanning, the sender would skip the pucks which have the same or a higher version number. That's not completely fool proof, when two pucks are sending at the same time with different versions, the older version could in theory win. But it's better than nothing...

  • BTW: This is a seriously cool method to program many Pucks automatically! Very useful

  • Cool. I like it. Will recruit all nearby pucks:-)
    Suggest that as well as being aware of versions it might benefit from 2 things:

    1. A simple white list and/or blacklist to limit pucks of interest( perhaps with wildcard *)
    2. Ability to password protect each puck at the same time to prevent others from capturing your pucks in this way.
  • Hi Gordon,

    How can I get the optimized js code which is deployed on the Puck ?
    This is required when doing mass deployment from Android device for example. Do you think that it is a good idea to have in the Espruino WebIDE "Get deployed code" button ?

    Thank you.

  • You might be able to get it as a string by looking in the 'console' under settings...

    However if you install the command-line tools npmjs.com/package/espruino you can use -o out.js to output the code directly to a file.

  • Thank you Gordon.

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

self-propagating code

Posted by Avatar for ChristianW @ChristianW

Actions