Does node.js not include packages in opkg yet?



  • @Boken-Lin I am erroring out on the line:
    cd openwrtevernote:///view/1434696247/s567/edc62026-49b6-4a74-a2aa-a5b6d4b2d90b/edc62026-49b6-4a74-a2aa-a5b6d4b2d90b/

    what is that? I have never seen this format. Are you sure that this is an artifact that resolves for you all on a windows system with evernote installed? I think it'd be best to host fork of openwrt + whatever changes you have in whatever that link resolves to. If I can get that point resolved, I have found a way to eliminate all other hand configurable items by usings 'scripts/diffconfig' to create a .config file that will just roll into the docker build env source tree once I check it in.



  • @Theodore-Borromeo OOPS... We copy and pasted it from Evernote, and they must have their proprietary protocol to keep track of hyperlinks within notes. Fixed now šŸ™‚



  • @Boken-Lin How is this: https://github.com/borromeotlhs/docker-onion-omega/commit/b4c98eab76e6f3d02704da39da890991e8fba1f4

    I can't get 'make' to work due to my firewall issues, and I do still need to:

    1. parameterize the number of cores to make
    2. Set the ENV variables to point to the OpenWRT toolchain ahead of the make succeeding (for node.js, at least)

    Though I would love for someone to instantiate this and run 'make' to test that the image builds through.





  • @Theodore-Borromeo, @Boken-Lin - When you guys get this sorted out, do you mind pinging me with install details?



  • Assuming you have serial console access or have terminal access from the wifi console, and that your onion omega is connected to the same wifi network. PLEASE NOTE: working node.js is NOT built from openwrt toolchain provided by onion corp., and I am still working on getting that 'container-ized', so that is still TBD.

    1.) Download the two files from google drive I linked to, get them over to a mounted usb drive on the onion (i format to ext4). Run:
    ln -s /path/to/usb/libv8.so /usr/lib/libv8.so

    2.) and then go to:
    cd /path/to/usb/

    3.) and run:
    ./node --version

    That's about it

    OR
    pull borromeotlh/docker-onion-omega-nodejs from dockerhub, then:
    docker cp over 'node' and 'libv8.so' from /node/nodejs_deploy to your host machine
    scp over those two libs onto a usb drive (ext4 formatted is what I used, but ymmv) mounted to on the omega
    make a symlink for /usr/lib/libv8.so that points to libv8.so you just scp-ed over
    go to usb drive and run './node --version'



  • šŸ»šŸ»šŸ»



  • Have quickly re-implemented my Python GPIO helper in JavaScript, if anyone wants to give it a go? Wont be able to test for another 12 hours (supposed to be working!).

    EDIT: Code now here https://community.onion.io/topic/46/simple-node-js-wrapper-and-demo



  • @Dan-L. I would, but I got the micro dock and haven't had time to:
    1.) wire up the omega to a breadboard
    2.) breadboard -> micro dock so that I can get serial access
    3.) and wire up omega pin outs from breadboard to leds/buttons šŸ˜ž

    It's is probably why I've been tinkering around with just getting software to work šŸ˜‰

    I think I should probably guy the other docks, though I am awaiting the camera kit as I've been wanting to see if I can't create a forward facing camera for my car (rear facing cams are great, but I still can't tell where my hood is in relation to the other guy's bumper!) I test drove the new Tesla Model S, and their 360 sonar ranging was SWEET! Not to mention auto-pilot <digressing>



  • @Dan-L. Also, your use of 'this' is mangled for javascript. I'm trying to fix it now. You also meant to write:
    GPIOHelper.prototype.setPinDirection = function(pin, dir, callback) {
    if(dir !== 'out' && dir !== 'in') {
    throw new Error("Invalid pin direction, use 'in' or 'out'.");
    }
    fs.writeFile(this.pinDirectionPath.replace('$', pin), dir, callback);
    };

    GPIOHelper.prototype.setPinDirectionSync = function(pin, dir) {
    if(dir !== 'out' && dir !== 'in') {
    throw new Error("Invalid pin direction, use 'in' or 'out'.");
    }
    fs.writeFileSync(this.pinDirectionPath.replace('$', pin), dir);
    };

    I'll have to ensure that:
    fs.writeFileSync(this.pinValuePath.replace('$', pin), String(value));

    resolves to the this.pinValuePath you've defined in the GPIOHelper function. ES7, with proper class support, will hopefully make this moot šŸ˜› As of right now I get the error:

    /mnt/sda1/scripts/js/gpiotest/GPIOHelper.js:53
    fs.writeFileSync(this.pinDirectionPath.replace('$', pin), dir);
    ^
    TypeError: Cannot call method 'replace' of undefined



  • @Theodore-Borromeo Correction to last post:
    'this' usage is fine, but we can't 'see' :
    this.pinDirectionPath
    this.pinValuePath

    from outside the function definition. I've tried returning them at the end of the GPIOHelper() function, though that is still returning undefined. I think this wrapper may need a little bit of work, and I'm tinkering away with it now. However, I am only moderately skilled at javascript. . .



  • Uggh. Here's where I'm stuck.

    -- GPIOHelper.js --

    var fs = require('fs');
    
    function GPIOHelper() {
    
    this.exportPath = "/sys/class/gpio/gpiochip0/subsystem/export";
    this.pinDirectionPath = "/sys/class/gpio/gpio$/direction";
    this.pinValuePath = "/sys/class/gpio/gpio$/value";
    this.pins = [0, 1, 6, 7, 8, 12, 13, 14, 23, 26, 21, 20, 19, 18];
    
    for(var x = 0; x < this.pins.length; x++) {
        fs.writeFileSync(this.exportPath, String(this.pins[x]));
    }
    
    }
    
    GPIOHelper.prototype.setPinDirection = function(pin, dir, callback) {
        if(dir !== 'out' && dir !== 'in') {
            throw new Error("Invalid pin direction, use 'in' or 'out'.");
        }
        fs.writeFile(this.pinDirectionPath.replace('$', pin), dir, callback);
    };
    
    GPIOHelper.prototype.setPin = function(pin, value, callback) {
        var newPinValuePath = this.pinValuePath.replace('$',pin);
        this.setPinDirection(pin, 'out', function(err) {
            if(err) {
                callback(err);
            } else {
                fs.writeFile(newPinValuePath, String(value), callback);
            }
        });
    };
    
    GPIOHelper.prototype.getPin = function(pin, callback) {
        var newPinValuePath = this.pinValuePath.replace('$',pin);
        this.setPinDirection(pin, 'in', function(err) {
            if(err) {
                callback(err);
            } else {
                fs.readFile(newPinValuePath, function(err, buf) {
                    if(err) {
                        callback(err);
                    } else {
                        callback(null, parseInt(buf.toString()));
                    }
                });
            }
        });
    };
    
    GPIOHelper.prototype.setPinDirectionSync = function(pin, dir) {
        var newPinDirectionPath = this.pinDirectionPath.replace('$',pin);
        if(dir !== 'out' && dir !== 'in') {
            throw new Error("Invalid pin direction, use 'in' or 'out'.");
        }
        fs.writeFileSync(newPinDirectionPath, dir);
    };
    GPIOHelper.prototype.setPinSync = function(pin, value) {
        var newPinValuePath = this.pinValuePath.replace('$',pin);
        this.setPinDirectionSync(pin, 'out');
        fs.writeFileSync(newPinValuePath, String(value));
    };
    
    GPIOHelper.prototype.getPinSync = function(pin) {
        var newPinValuePath = this.pinValuePath.replace('$',pin);
        this.setPinDirectionSync(pin, 'in');
        var val = fs.readFileSync(this.pinValuePath.replace('$', pin));
        return parseInt(buf.toString());
    };
    
    module.exports = GPIOHelper;
    

    -- gpiotest.js --

    var gpiohelper = require('./GPIOHelper'),
        ledPins = [0],
        buttonPin = 26;
    
    var Controller = gpiohelper();
    
    function turnOn(){
        for (pin in ledPins){
                Controller.setPinSync(pin,1);
                print("Turning on pin {0}".format(pin));
        }
    }
    
    function turnOff(){
        for (pin in ledPins){
                Controller.setPinSync(pin,0);
                print("Turning off pin {0}".format(pin));
        }
    }
    
    do {
        setTimeout(turnOn,250);
        setTimeout(turnOff,250);
    } while (1)
    

    -- log output --

    /mnt/sda1/scripts/js/gpiotest# /mnt/sda1/out/Release/node gpiotest.js
    
    fs.js:528
      return binding.write(fd, buffer, offset, length, position);
                 ^
    Error: EBUSY, resource busy or locked
    at Object.fs.writeSync (fs.js:528:18)
    at Object.fs.writeFileSync (fs.js:975:21)
    at GPIOHelper (/mnt/sda1/scripts/js/gpiotest/GPIOHelper.js:11:12)
    at Object.<anonymous> (/mnt/sda1/scripts/js/gpiotest/gpiotest.js:5:18)
    at Module._compile (module.js:456:26)
    at Object.Module._extensions..js (module.js:474:10)
    at Module.load (module.js:356:32)
    at Function.Module._load (module.js:312:12)
    at Function.Module.runMain (module.js:497:10)
    at startup (node.js:119:16)
    

    šŸ˜ž



  • Hmm, looking into this now, I just woke up. I'm getting the same error, but also note you need to call var Controller = new gpiohelper(); ā€” the new keyword creates an object with the methods. Otherwise, the constructor function runs but you wont get an object out of it.



  • @Dan-L. updated code:

    var gpiohelper = require('./GPIOHelper'),
        ledPins = [0],
        buttonPin = 26;
    
    var Controller = new gpiohelper();
    
    function turnOn(){
        for (pin in ledPins){
                Controller.setPinSync(pin,1);
                print("Turning on pin {0}".format(pin));
        }
    }
    
    function turnOff(){
        for (pin in ledPins){
                Controller.setPinSync(pin,0);
                print("Turning off pin {0}".format(pin));
        }
    }
    
    do {
         var p1 = new Promise(
             function(resolve,reject){
                 setTimeout(turnOn,1000);
             });
        p1.then(
            setTimeout(turnOff,1000)
        )
        .catch(
            function(reason) {
                console.log(reason + ' rejected');
            });
    } while(1);
    

    Still no dice, and same error.



  • Turns out the export errors are kinda OK? Still works without em (if you try/catch). It's not working from the command line either.

    There were also a bunch of other bugs, like the wrong variable name as you found above, and if you called .setPin(5, true) it would send "true" rather than "1".

    Try the new code, then check the "/sys/class/gpio/" folder ā€” do you see a bunch of gpioX folders?

    EDIT: Code now here https://community.onion.io/topic/46/simple-node-js-wrapper-and-demo



  • @Dan-L. SO with this code in test.js:

    // test.js
    var GPIOHelper = require('./gpiohelper');
    
    var helper = new GPIOHelper();
    
    // Get pin value synchronously
    console.log("Sync value was "+helper.getPinSync(1));
    
    // Set some pins synchronously
    helper.setPinSync(0, true);
    
    // Get pin async
    helper.getPin(0, function(err, val) {
        if(err) {
            console.log("Couldn't set pin?", err);
        } else {
            console.log("Value is", val);
        }
    });
    
    // Set pin async
    helper.setPin(0, true, function(err) {
        if(err) {
            console.log("Couldn't set pin?", err);
        }
    });
    
    helper.setPinSync(0,false);
    console.log("Sync value was "+helper.getPinSync(0));
    

    I get:

    /mnt/sda1/out/Release/node test.js
    Ignoring pin 0 export error Error: EBUSY, resource busy or locked
    Ignoring pin 1 export error Error: EBUSY, resource busy or locked
    Ignoring pin 6 export error Error: EBUSY, resource busy or locked
    Ignoring pin 7 export error Error: EBUSY, resource busy or locked
    Ignoring pin 8 export error Error: EBUSY, resource busy or locked
    Ignoring pin 12 export error Error: EBUSY, resource busy or locked
    Ignoring pin 13 export error Error: EBUSY, resource busy or locked
    Ignoring pin 14 export error Error: EBUSY, resource busy or locked
    Ignoring pin 23 export error Error: EBUSY, resource busy or locked
    Ignoring pin 26 export error Error: EBUSY, resource busy or locked
    Ignoring pin 21 export error Error: EBUSY, resource busy or locked
    Ignoring pin 20 export error Error: EBUSY, resource busy or locked
    Ignoring pin 19 export error Error: EBUSY, resource busy or locked
    Ignoring pin 18 export error Error: EBUSY, resource busy or locked
    Sync value was 1
    Sync value was 0
    Value is 1
    

    So with some static typing, I perhaps could have realized I should have been using 'true' and 'false' instead of int values šŸ˜ž Though I don't even think that it would have mattered. I'm modifying code now to get a simple blink example off of pin 0.



  • @Theodore-Borromeo Ahh, well 1 or 0 would have worked with the previous code ā€” but I updated it so any "truthy" value will be sent as "1".

    Next step is adding some event listening, which should really get things moving. It'll be hacky though and have to use polling! Will try and implement tonight though šŸ™‚



  • It seems that depending on javascript to take care of file handle closing, especially with asynchronous calls, is a bit too much with the current state of this sample šŸ™‚

    I get, when I just try to run a blink example in an infinite loop, this error:

    Error: EMFILE, too many open files '/sys/class/gpio/gpio0/direction'
        at Object.fs.openSync (fs.js:427:18)
        at Object.fs.writeFileSync (fs.js:966:15)
        at GPIOHelper.setPinDirectionSync (/mnt/sda1/scripts/js/gpiotest/gpiohelper.js:61:8)
        at GPIOHelper.setPinSync (/mnt/sda1/scripts/js/gpiotest/gpiohelper.js:65:10)
        at Object.<anonymous> (/mnt/sda1/scripts/js/gpiotest/test.js:15:23)
        at Module._compile (module.js:456:26)
        at Object.Module._extensions..js (module.js:474:10)
        at Module.load (module.js:356:32)
        at Function.Module._load (module.js:312:12)
        at Function.Module.runMain (module.js:497:10)
    

    I think that, perhaps it wouldn't be a bad idea to utilize a command line to fast-gpio, so that this stuff is taken care of for simple access. Until, that is, lower level and better syncing primitives are explored. This driver, I think, would best be implemented in C and wrapped up into a js lib, right? Heck, I'm not exactly well versed in getting the js side hooked up to the C low end drivers, so I wouldn't be the best person to ask.

    In any case, this is a good start and proves that your system works. Of course, for pins, EBUSY doesn't make any sense for those coming from the arduino/avr world. But, having linux on your device is going to expose all the ugly embedded nonsense that makes it not that fun šŸ˜ž



  • @Dan-L. Cool! I'm honestly not really that great with Javascript yet, just knowledgeable enough to get myself into and out of trouble. However, the reason I bought the omega was the idea that we as the community could define node packages, have node.js on device, and just extend the capabilities for the device with npm.

    The solution I stumbled upon did seem to have npm, and can be built with the script:
    https://github.com/nneves/openwrt_mips_ar9331_nodejs/blob/master/npm_mips_ar9331.sh

    So, when I get time on Monday, I'll probably have to update the Dockerfile for nneve's scripts to build npm too. That should allow us to quickly iterate on stuff, push to npm, and then disseminate that way until official support for a slimmer node.js server comes from Onion, Inc. šŸ™‚

    Great stuff and great progress!



  • Hey @Theodore-Borromeo, can I see your blink code? I'm managing to write a bunch of things and not getting the EMFILE, too many open files message at any point. If you were using setPinSync you shouldn't get that, but maybe with just setPin you might? šŸ˜•


Log in to reply
 

Looks like your connection to Community was lost, please wait while we try to reconnect.