JamesBarwell / rpi-gpio.js

Control Raspberry Pi GPIO pins with node.js
MIT License
657 stars 116 forks source link

Allow Setup to take in an array of channels? #55

Open shayned35 opened 7 years ago

shayned35 commented 7 years ago

If you look at the python gpio library , setting up a pin is the same as node however the only difference is instead of passing a single channel, we can simply pass an array of channels and it will initialize all and provide the call back.

Python code

chan_list = [11,12]  
GPIO.setup(chan_list, GPIO.OUT)

Meanwhile in node there needs to be a recursive function to ensure all the pins are setup in the correct order and only then can the rest of the execution happen. If this can be below the line it would be very helpful.

JamesBarwell commented 7 years ago

Yep, sounds like a good idea. There's some work in progress at the moment to improve the API generally so this might be something that fits in nicely after that work is merged.

thecodershome commented 7 years ago

This could be added with the PR #58 as gpio.promise.setupAll and could look like the example below. However if a promise rejects then setupAll will reject.

    /**
     * @param {number[]}    channels
     * @param direction
     * @param edge
     * @returns {Promise}
     */
    setupAll: function (channels, direction, edge) {
        if (!Array.isArray(channels))
            return Promise.reject(new Error('Channels must be an array'));

        return Promise.all(
            channels.map(function (channel) {
                return GPIO.promise.setup(channel, direction, edge);
            }))
    }

A possible alternative would be to catch errors inside setupAll and return an array of successful channels.

setupAll: function (channels, direction, edge) {
        if (!Array.isArray(channels))
            return Promise.reject(new Error('Channel must be an array'));

        // Iterate over channel
        return Promise.all(
            channels.map(function (channel) {
                return GPIO.promise.setup(channel, direction, edge)
                    .then(function () { // return channel
                        return channel;
                    }, function (e) { // ignore error
                    });
            })) // returns array of results
            .then(function (chanList) {
                return chanList.filter(Number); // filter out 'undefined'
            })
    },
var gpio = require('rpi-gpio.js'),
    gpio_p = gpio.promise;

var list = gpio_p.setup([3, 5, 7, 99])  // ignore reject 99 and resolves successfully 
list.then((res) => {
    console.log(res) // [3, 5, 7]
})

Updated the correct PR

JamesBarwell commented 7 years ago

My thoughts on this:

thecodershome commented 7 years ago

Here is what I've come with for setupAll on the standard API https://github.com/thecodershome/rpi-gpio.js/commit/e56c96bd5373ed7e41d17d213469d932923b9dc8

var gpio = require('rpi-gpio.js');

function done(err, res) {

/*
  err = [{channel: 99, error: Error}]; // Error with stack
  res = [{channel: 3, result: 'result from setup'},
    {channel: 5, result: 'result from setup'},
    {channel: 6, result: 'result from setup'}];
*/
}

var list = gpio.setupAll([3, 5, 7, 99], done)

Currently result is undefined, but if we ever return with something its avaliable.

Then to test for error

function done(err, res) {
  if(err.length > 0)
    // handle errors
}
shayned35 commented 5 years ago

Is this being worked on currently? I'd like to have a go at it if it isn't already done/in progress? PS: Sorry for accidentally closing the issue

shayned35 commented 5 years ago

Is this being worked on currently? I'd like to have a go at it if it isn't already done/in progress? PS: Sorry for accidentally closing the issue

JamesBarwell commented 5 years ago

Hi, there has been some work on this from @thecodershome above which is worth looking at. I haven't picked it up myself.

I'm unsure how useful this is now that the promise API is available, and my current thoughts are that anyone who wants to deal with multiple operations in parallel will be drawn towards using that, and will use setup() and Promise.all(). Have you got a specific problem or example that would help to illustrate where this would be useful?

shayned35 commented 5 years ago

Hey, nothing specific I was just tinkering around when I realised I could only open one channel at a time, I just realised my original issue gets completely solved by using Promise.all().