njh / node-owfs

A node.js client library for the owserver protocol in owfs
https://www.npmjs.com/package/owfs
MIT License
10 stars 4 forks source link

Listing all devices and properties #6

Closed njh closed 10 years ago

njh commented 10 years ago

Hello,

I am trying to create a complete list of devices and the properties for each device. However I am having problems with second call to dirall throwing EADDRNOTAVAIL.

Here is my code:

var owfs = require("owfs");
var async = require("async");

var client = new owfs.Client('localhost');
client.dirall("/",function(error, directories){
    if (!error) {
        console.log("Top no error");
        async.mapSeries(directories, client.dirall,
            function(error, results) {
                console.log("Inner Error: "+error);
                console.log("Inner Results: "+results);
            }
        );
    } else {
        console.log("Top error: "+error);
    }
});

This is the output:

Top no error
error:  code=EADDRNOTAVAIL, errno=EADDRNOTAVAIL, syscall=connect
Inner Error: Error: connect EADDRNOTAVAIL
Inner Results: 

I am using async.mapSeries in an attempt to make a sequence of calls to owserver and avoid making a large number of calls in parallel.

My theory is the while each call to dirall should be creating its own socket and connection to owserver. By the time the second socket is created, the first socket is only half-closed and node.js tries to re-use the same local port and then fails.

Can you suggest a solution to this problem?

Thanks,

nick.

benediktarnold commented 10 years ago

Ok the error message is very missleading...

I debugged the code and found out that async is calling apply on the iterator function with null as first argument. According to https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/apply this means, that this inside the iterator function (in your case client.dirall) will be the global object.

Inside dirall I am calling an internal function on the this object. This fails in your case because this is not the client instance.

Wrapping the second dirall inside a function, like this, works as expected:

client.dirall("/",function(error, directories){
    if (!error) {
        console.log("Top no error");
        async.mapSeries(directories, function(directory,cb){
                client.dirall(directory,cb);
            },
            function(error, results) {
                console.log("Inner Error: "+error);
                console.log("Inner Results: "+results);
            }
        );
    } else {
        console.log("Top error: "+error);
    }
});

I will try to detect the error and provide a better error message.

njh commented 10 years ago

Thank you so much for looking into this. Working for me too.