forked from anthony-ngu/wemo-client
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathindex.js
127 lines (111 loc) · 3.33 KB
/
index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
var SSDPClient = require('node-ssdp').Client;
var url = require('url');
var http = require('http');
var os = require('os');
var debug = require('debug')('wemo-client');
var WemoClient = require('./client');
var Wemo = module.exports = function(opts) {
opts = opts || {};
this._port = opts.port || 0;
this._clients = {};
this._listen();
this._ssdpClient = new SSDPClient(opts.discover_opts || {});
};
Wemo.DEVICE_TYPE = {
Bridge: 'urn:Belkin:device:bridge:1',
Switch: 'urn:Belkin:device:controllee:1',
Motion: 'urn:Belkin:device:sensor:1',
Maker: 'urn:Belkin:device:Maker:1',
Insight: 'urn:Belkin:device:insight:1',
LightSwitch: 'urn:Belkin:device:lightswitch:1'
};
Wemo.prototype.load = function(setupUrl, cb) {
var self = this;
var location = url.parse(setupUrl);
WemoClient.request({
host: location.hostname,
port: location.port,
path: location.path,
method: 'GET'
}, function(err, json) {
if (!err && json) {
var device = json.root.device;
device.host = location.hostname;
device.port = location.port;
device.callbackURL = self.getCallbackURL();
// Return devices only once!
if (!self._clients[device.UDN] || self._clients[device.UDN].error) {
debug('Found device: %j', json);
if (cb) {
cb.call(self, device);
}
}
}
});
};
Wemo.prototype.discover = function(cb) {
var self = this;
var handleResponse = function(msg, statusCode, rinfo) {
if (msg.ST && msg.ST === 'urn:Belkin:service:basicevent:1') {
self.load(msg.LOCATION, cb);
}
};
this._ssdpClient.removeAllListeners('response');
this._ssdpClient.on('response', handleResponse);
this._ssdpClient.search('urn:Belkin:service:basicevent:1');
};
Wemo.prototype._listen = function() {
this._server = http.createServer(this._handleRequest.bind(this));
this._server.listen(this._port, function(err) {
if (err) {
throw err;
}
});
};
Wemo.prototype._handleRequest = function(req, res) {
var body = '';
var udn = req.url.substring(1);
if ((req.method == 'NOTIFY') && this._clients[udn]) {
req.on('data', function(chunk) {
body += chunk.toString();
});
req.on('end', function() {
debug('Incoming Request for %s: %s', udn, body);
this._clients[udn].handleCallback(body);
res.writeHead(204);
res.end();
}.bind(this));
} else {
debug('Received request for unknown device: %s', udn);
res.writeHead(404);
res.end();
}
};
Wemo.prototype.getCallbackURL = function() {
var getLocalInterfaceAddress = function() {
var interfaces = os.networkInterfaces();
var addresses = [];
for (var k in interfaces) {
for (var k2 in interfaces[k]) {
var address = interfaces[k][k2];
if (address.family === 'IPv4' && !address.internal) {
addresses.push(address.address);
}
}
}
return addresses.shift();
};
if (!this._callbackURL) {
var port = this._server.address().port;
var host = getLocalInterfaceAddress();
this._callbackURL = 'http://' + host + ':' + port;
}
return this._callbackURL;
};
Wemo.prototype.client = function(device) {
if (this._clients[device.UDN] && !this._clients[device.UDN].error) {
return this._clients[device.UDN];
}
var client = this._clients[device.UDN] = new WemoClient(device);
return client;
};