Skip to content

Commit 45b7c44

Browse files
author
greguz
committed
removed socket.js lib
rewrote module with node events emitter refactor dumper.js refactor test.js update README.md
1 parent 5da5475 commit 45b7c44

6 files changed

Lines changed: 211 additions & 149 deletions

File tree

README.md

Lines changed: 74 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,32 +1,90 @@
1-
# node-raidar
1+
# node-raidar: a node.js NetGear RADIar library
22

3+
`node-raidar` is a simple to use NetGear RAIDar implementation for node.js.
34

5+
# Example
46

5-
Define error callback:
7+
``` js
8+
var raidar = require('raidar');
69

7-
```
8-
raidar.on('error', function(err) {
9-
console.log('ERROR', err);
10+
// send request, wait 10000 ms, and return founded devices
11+
raidar.request(10000, function(err, devices) {
12+
if (err)
13+
console.log('ERROR', err);
14+
else
15+
console.log('Founded devices: ' + devices.length);
1016
});
1117
```
1218

19+
# Methods
1320

21+
``` js
22+
var raidar = require('raidar')
23+
```
1424

15-
Define device info callback:
25+
## raidar.open(opt:Object, cb:Function)
1626

17-
```
18-
raidar.on('device', function(device) {
19-
console.log(device.ip, device.hostname, device.mac, device.info.disk[0].status);
20-
});
21-
```
27+
Open new UDP socket with given `opt` options and fire `cb` callback when socket is open.
28+
All arguments are optional.
29+
Default options:
30+
- `socketType` : socket type to use ('udp4' or 'udp6'), default `udp4`
31+
- `portToListen` : port to listen, default `57877`
32+
- `targetHost` : target host to send "request info" packet, default `255.255.255.255`
33+
- `targetPort` : target port to send "request info" packet, default `22081`
2234

35+
## raidar.close()
2336

37+
Close UDP socket.
2438

25-
To request information from ReadyNAS devices:
39+
## raidar.request(timeout:Number, callback:Function)
2640

27-
```
28-
raidar.sendMagic();
29-
```
41+
Send "request info" broadcast packet.
42+
If at least `callback` function is passed, it will execute after `timeout` ms, default 5000 ms.
43+
The event fires with `callback(err, devices)`.
44+
`err` is set in case of errors and `devices` is an array of all devices found.
45+
46+
## raidar.on(event:String, callback:Function)
47+
48+
Set an event callback.
49+
50+
## raidar.once(event:String, callback:Function)
51+
52+
Set an event callback that execute only one time.
53+
54+
## Events
55+
56+
List of possible events.
57+
58+
### raidar.on('device', callback:Function)
59+
60+
Generic ReadyNAS device response.
61+
This event fires with `callback(device)` where `device` is an instance of `ReadyNAS` class.
62+
63+
### raidar.on(id:String, callback:Function)
64+
65+
Specific device response callback where `id` is IP or Hostname or MAC address.
66+
This event fires with `callback(device)` where `device` is an instance of `ReadyNAS` class.
67+
68+
### raidar.on('error', callback:Function)
69+
70+
Generic Error.
71+
This event fires with `callback(err)` where `err` is an instance of `Error` class.
72+
73+
### raidar.on('fail', callback:Function)
74+
75+
Fail to parse response data.
76+
This event fires with `callback(msg, err)` where `msg` is the response buffer and `err` is an instance of `Error` class.
77+
78+
# ReadyNAS class
79+
80+
...
81+
82+
## Property
83+
84+
...
85+
86+
## Methods
3087

88+
...
3189

32-
License: MIT
90+
# License: MIT

dumper.js

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
1-
var socket = require('./libs/socket')
1+
var raidar = require('./index')
22
, path = require('path')
33
, fs = require('fs');
44

55
var folder = path.join(process.argv[2] || __dirname, 'dump');
66

7-
socket.on('error', function(err) {
7+
raidar.on('error', function(err) {
88
console.log('ERROR', err);
99
});
1010

11-
socket.on('message', function(msg) {
11+
raidar.on('message', function(msg) {
1212
var id = new Date().getTime()
1313
, file = path.join(folder, id + '.readynas');
1414

@@ -23,10 +23,10 @@ socket.on('message', function(msg) {
2323
console.log('Creating folder ' + folder + '...');
2424

2525
fs.mkdir(folder, function(err) {
26-
if (err)
27-
console.log('ERROR', err);
28-
else
29-
socket.sendMagic();
26+
if (!err) return raidar.request();
27+
28+
console.log('ERROR', err);
29+
process.exit();
3030
});
3131

3232
setTimeout(function() {

index.js

Lines changed: 106 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -2,74 +2,149 @@
22
// dependencies
33
// #########################################################################
44

5-
var socket = require('./libs/socket')
6-
, ReadyNAS = require('./libs/readynas')
7-
, _ = require('lodash');
5+
var dgram = require('dgram')
6+
, EventEmitter = require('events').EventEmitter
7+
, _ = require('lodash')
8+
, ReadyNAS = require('./readynas');
89

910

1011

1112
// #########################################################################
1213
// module vars
1314
// #########################################################################
1415

15-
var _events = {};
16+
var _defaultOptions = {
17+
socketType : 'udp4',
18+
portToListen : 57877,
19+
targetHost : '255.255.255.255',
20+
targetPort : 22081,
21+
magicPacket : new Buffer('0000073e0000000100000000f8d496c3ffffffff0000001c00000000', 'hex')
22+
};
23+
24+
var _socket = null
25+
, _options = null
26+
, _events = new EventEmitter();
1627

1728

1829

1930
// #########################################################################
2031
// utility functions
2132
// #########################################################################
2233

23-
var notifyEvent = function() {
24-
var args = _.values(arguments)
25-
, event = args.shift()
26-
, callback = _events[event];
34+
var firstValueByType = function(obj, type) {
35+
for (var i in obj) {
36+
if (typeof obj[i] === type)
37+
return obj[i];
38+
}
39+
};
40+
41+
var firstNumber = function(obj) {
42+
return firstValueByType(obj, 'number');
43+
};
2744

28-
if (typeof callback !== 'function') return;
45+
var firstFunction = function(obj) {
46+
return firstValueByType(obj, 'function');
47+
};
2948

30-
callback.apply(this, args);
49+
var firstObject = function(obj) {
50+
return firstValueByType(obj, 'object');
3151
};
3252

3353

3454

3555
// #########################################################################
36-
// socket settings
56+
// socket functions
3757
// #########################################################################
3858

39-
socket.on('error', function(err) {
40-
notifyEvent('error', err);
41-
});
4259

43-
socket.on('message', function(msg) {
60+
var socketError = function(err) {
61+
_events.emit('error', err);
62+
};
63+
64+
var socketMessage = function(msg) {
65+
_events.emit('message', msg);
66+
4467
try {
4568
var device = new ReadyNAS(msg);
46-
47-
notifyEvent('device', device);
48-
notifyEvent(device.ip, device);
49-
notifyEvent(device.hostname, device);
50-
notifyEvent(device.mac, device);
69+
[ 'device', device.ip, device.hostname, device.mac ].forEach(function(e) {
70+
_events.emit(e, device);
71+
});
5172
} catch(e) {
52-
notifyEvent('error', e);
73+
_events.emit('fail', msg, e);
5374
}
54-
});
75+
};
76+
77+
var openNewSocket = function() {
78+
var options = firstObject(arguments)
79+
, callback = firstFunction(arguments);
80+
81+
_options = _.extend(_.clone(_defaultOptions), options);
82+
83+
_socket = dgram.createSocket(_options.socketType);
84+
85+
_socket.on('error', socketError);
86+
_socket.on('message', socketMessage);
5587

56-
socket.open();
88+
_socket.bind(_options.portToListen, function() {
89+
_socket.setBroadcast(true);
90+
if (callback) callback();
91+
});
92+
};
93+
94+
var closeSocket = function() {
95+
if (_socket) _socket.close();
96+
_socket = null;
97+
};
98+
99+
var sendMagic = function() {
100+
var callback = firstFunction(arguments);
101+
102+
var send = function() {
103+
_socket.send(_options.magicPacket, 0, _options.magicPacket.length, _options.targetPort, _options.targetHost, function(err) {
104+
if (callback) callback(err);
105+
});
106+
};
107+
108+
if (!_socket) openNewSocket(send); else send();
109+
};
57110

58111

59112

60113
// #########################################################################
61-
// functions
114+
// exports
62115
// #########################################################################
63116

64-
module.exports.options = function(options) {
65-
socket.close();
66-
socket.open(options);
117+
module.exports.on = function(event, callback) {
118+
return _events.on(event, callback.bind(_events));
67119
};
68120

69-
module.exports.sendMagic = function(options, callback) {
70-
socket.sendMagic();
121+
module.exports.once = function(event, callback) {
122+
return _events.once(event, callback.bind(_events));
71123
};
72124

73-
module.exports.on = function(event, callback) {
74-
_events[event] = callback;
125+
module.exports.open = openNewSocket;
126+
127+
module.exports.close = closeSocket;
128+
129+
module.exports.request = function() {
130+
var timeout = firstNumber(arguments)
131+
, callback = firstFunction(arguments)
132+
, founded = [];
133+
134+
if (!callback) return sendMagic();
135+
136+
var cbDevice = function(device) {
137+
founded.push(device);
138+
};
139+
140+
sendMagic(function(err) {
141+
if (err) return callback(err);
142+
143+
_events.on('device', cbDevice);
144+
145+
setTimeout(function() {
146+
_events.removeListener('device', cbDevice);
147+
callback(null, founded);
148+
}, timeout || 5000);
149+
});
75150
};

0 commit comments

Comments
 (0)