@evops/lightwaverf 0.0.5 → 0.0.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/index.js DELETED
@@ -1,561 +0,0 @@
1
- var util = require('util');
2
- var events = require('events');
3
- var dgram = require('dgram');
4
- var https = require('https');
5
- var querystring = require('querystring');
6
- var fs = require('fs');
7
- var wait = require('wait.for');
8
- var yaml = require('js-yaml');
9
- var rp = require('request-promise');
10
- const { timeStamp } = require('console');
11
- var debug = require('debug')('lightwaverf');
12
-
13
- /**
14
- * LightwaveRF API
15
- *
16
- * @param object config The config
17
- *
18
- * An instance of the LightwaveRF API
19
- */
20
- function LightwaveRF(config, callback) {
21
- if (!(this instanceof LightwaveRF)) {
22
- return new LightwaveRF(config, callback);
23
- }
24
-
25
- const self = this;
26
- this.timeout = config.timeout || 1000;
27
- this.queue = [];
28
- this.ready = true;
29
-
30
- this.currentTransactionNumber = 0;
31
-
32
- this.devices = [];//[{roomId:0,roomName:'',
33
- //deviceId:0,deviceName:'',
34
- //deviceType:''}];
35
-
36
- events.EventEmitter.call(this);
37
-
38
- this.setMaxListeners(255);
39
-
40
- //Counter
41
- this.messageCounter = 0;
42
-
43
- //Config
44
- this.config = config;
45
-
46
- // Use broadcast to discover the IP
47
- this.config.ip = this.config.ip || '255.255.255.255';
48
-
49
- //Response listeners
50
- this.responseListeners = {};
51
-
52
- //Send Socket
53
- this.sendSocket = dgram.createSocket("udp4");
54
-
55
- //Receive socket
56
- this.receiveSocket = dgram.createSocket("udp4");
57
-
58
- //Receive message
59
- this.receiveSocket.on("message", function (message, rinfo) {
60
- // If we were using broadcast IP, we have now
61
- // discovered Link device IP and can switch off
62
- // broadcast
63
- if (this.config.ip == '255.255.255.255') {
64
- console.log("We have now discovered Link IP address: %s", rinfo.address);
65
- this.config.ip = rinfo.address
66
- this.sendSocket.setBroadcast(false)
67
- }
68
-
69
- //Check this came from the lightwave unit
70
- if (rinfo.address !== this.config.ip) {
71
- //Came from wrong ip]
72
- console.warn("Response came from a different IP than our configured", rinfo.address, this.config.ip)
73
- return false;
74
- }
75
-
76
- const parseResponse = (buffer) => {
77
- const response = {}
78
- const message = buffer.toString('utf-8');
79
- if (message.match(/^\*!/)) {
80
- const jsonResponse = JSON.parse(message.replace(/^\*!/, ''))
81
- self.currentTransactionNumber = jsonResponse.trans + 1;
82
-
83
- Object.assign(response, jsonResponse)
84
- } else {
85
- //Split off the code for the message
86
- var parts = message.split(",");
87
- var trans = parts.splice(0, 1);
88
- var content = parts.join(",").replace(/(\r\n|\n|\r)/gm, "");
89
- response.trans = parseInt(trans);
90
- response.message = content;
91
- }
92
-
93
- return response;
94
- }
95
-
96
- let linkResponse = parseResponse(message)
97
- debug(">>>>>>>> Received response msg: %s, rinfo: %s", message, linkResponse);
98
-
99
- var responseListenerData = this.responseListeners[linkResponse.trans];
100
- if (!responseListenerData) {
101
- debug("We haven't got anyone to respond to, ignoring the message")
102
- return;
103
- }
104
-
105
- responseListenerData.listener(
106
- linkResponse.trans,
107
- linkResponse.fn,
108
- linkResponse.error ? linkResponse.error : null
109
- );
110
-
111
- delete this.responseListeners[linkResponse.trans];
112
-
113
- }.bind(this));
114
-
115
- this.receiveSocket.on("listening", function () {
116
- var address = this.receiveSocket.address();
117
- debug("Receiver socket listening " + address.address + ":" + address.port);
118
-
119
- self.send('@H', (code, err) => {
120
- if (err) {
121
- console.log(code, err)
122
- }
123
-
124
- self.initialiseConfiguration(callback);
125
- })
126
- }.bind(this));
127
-
128
- this.sendSocket.bind();
129
- //Bind to the receive port
130
- this.receiveSocket.bind(9761);
131
-
132
- process.on('SIGINT', () => {
133
- self.stop();
134
- })
135
- }
136
- util.inherits(LightwaveRF, events.EventEmitter);
137
-
138
- LightwaveRF.prototype.stop = function () {
139
- debug("Stopping server sockets")
140
- this.sendSocket.close();
141
- this.receiveSocket.close();
142
- }
143
-
144
- LightwaveRF.prototype.initialiseConfiguration = function (callback) {
145
- if (this.config.file) {
146
- this.getFileConfiguration(this.config.file, callback);
147
- } else {
148
- debug("Not using `config.file`")
149
- //Check config
150
- if (!this.config.host) {
151
- this.config.host = "web.trustsmartcloud.com"
152
- }
153
-
154
- if (!this.config.email || !this.config.pin) {
155
- console.log("No email or pin specified. The server configuration (rooms, devices, etc.) cannot be obtained")
156
- }
157
- else {
158
- this.getConfiguration(this.config.email, this.config.pin, this.config.host, callback)
159
- }
160
- }
161
-
162
- }
163
-
164
- /**
165
- * Register this device with the Wi-Fi Link
166
- *
167
- * @param Function callback The callback function
168
- *
169
- * @return void
170
- */
171
- LightwaveRF.prototype.register = function (callback) {
172
- this.sendUdp("!R1Fa", callback);
173
- }
174
-
175
- /**
176
- * Request energy
177
- *
178
- * @param Function callback The callback function
179
- *
180
- * @return void
181
- */
182
- LightwaveRF.prototype.requestEnergy = function (callback) {
183
- this.sendUdp("@?\0", function (error, content) {
184
- if (error) {
185
- //Send error back
186
- callback(error);
187
- } else {
188
- //Determine if this is the energy monitor
189
- //ID,?W=current,max,today,yesterday (all kwh)
190
- var values = content.substring(3).split(",");
191
- callback(undefined, {
192
- current: parseInt(values[0], 10),
193
- max: parseInt(values[1], 10),
194
- today: parseInt(values[2], 10),
195
- yesterday: parseInt(values[3], 10)
196
- });
197
- }
198
- });
199
- }
200
-
201
- /**
202
- * Turn a device off
203
- *
204
- * @param integer roomId The room ID
205
- * @param integer deviceId The device ID
206
- * @param Function callback The callback for if there are any errors
207
- *
208
- * @return void
209
- */
210
- LightwaveRF.prototype.turnDeviceOff = function (roomId, deviceId, callback) {
211
- var state = "0";
212
- this.exec("!R" + roomId + "D" + deviceId + "F" + state + "|\0", callback);
213
- }
214
-
215
- /**
216
- * Turn a device on
217
- *
218
- * @param integer roomId The room ID
219
- * @param integer deviceId The device ID
220
- * @param Function callback The callback for if there are any errors
221
- *
222
- * @return void
223
- */
224
- LightwaveRF.prototype.turnDeviceOn = function (roomId, deviceId, callback) {
225
- var state = "1";
226
- this.exec("!R" + roomId + "D" + deviceId + "F" + state + "|\0", callback);
227
- }
228
-
229
- /**
230
- * Open a device
231
- *
232
- * @param integer roomId The room ID
233
- * @param integer deviceId The device ID
234
- * @param Function callback The callback for if there are any errors
235
- *
236
- * @return void
237
- */
238
- LightwaveRF.prototype.openDevice = function (roomId, deviceId, callback) {
239
- var state = ">";
240
- this.exec("!R" + roomId + "D" + deviceId + "F" + state + "|\0", callback);
241
- }
242
-
243
- /**
244
- * Close a device
245
- *
246
- * @param integer roomId The room ID
247
- * @param integer deviceId The device ID
248
- * @param Function callback The callback for if there are any errors
249
- *
250
- * @return void
251
- */
252
- LightwaveRF.prototype.closeDevice = function (roomId, deviceId, callback) {
253
- var state = "<";
254
- this.exec("!R" + roomId + "D" + deviceId + "F" + state + "|\0", callback);
255
- }
256
-
257
- /**
258
- * Stop a device
259
- *
260
- * @param integer roomId The room ID
261
- * @param integer deviceId The device ID
262
- * @param Function callback The callback for if there are any errors
263
- *
264
- * @return void
265
- */
266
- LightwaveRF.prototype.stopDevice = function (roomId, deviceId, callback) {
267
- var state = "^";
268
- this.exec("!R" + roomId + "D" + deviceId + "F" + state + "|\0", callback);
269
- }
270
-
271
- /**
272
- * Turn all devices in a room off
273
- *
274
- * @param integer roomId The room ID
275
- * @param Function callback The callback for if there are any errors
276
- *
277
- * @return void
278
- */
279
- LightwaveRF.prototype.turnRoomOff = function (roomId, callback) {
280
- this.exec("!R" + roomId + "Fa\0", callback);
281
- }
282
-
283
- /**
284
- * Set the dim percentage of a device
285
- *
286
- * @param integer roomId The room ID
287
- * @param integer deviceId The device ID
288
- * @param integer dimPercentage The percentage to set the device dim
289
- * @param Function callback The callback for if there are any errors
290
- *
291
- * @return void
292
- */
293
- LightwaveRF.prototype.setDeviceDim = function (roomId, deviceId, dimPercentage, callback) {
294
- var dimAmount = parseInt(dimPercentage * 0.32, 10); //Dim is on a scale from 0 to 32
295
-
296
- if (dimAmount === 0) {
297
- this.turnDeviceOff(roomId, deviceId, callback);
298
- } else {
299
- this.exec("!R" + roomId + "D" + deviceId + "FdP" + dimAmount + "|\0", callback);
300
- }
301
- }
302
-
303
- /**
304
- * Get message code
305
- *
306
- * @return string
307
- */
308
- LightwaveRF.prototype.getTransactionNumber = function () {
309
- return this.currentTransactionNumber;
310
- }
311
-
312
-
313
- LightwaveRF.prototype.exec = function () {
314
- // Check if the queue has a reasonable size
315
- if (this.queue.length > 100) {
316
- this.queue.pop();
317
- }
318
-
319
- this.queue.push(arguments);
320
- this.process();
321
- };
322
-
323
- LightwaveRF.prototype.send = function (cmd, callback) {
324
- this.sendUdp(cmd, callback);
325
- //if (callback) callback();
326
- };
327
- /**
328
- * Send a message over udp
329
- *
330
- * @param string message The message to send
331
- * @param Function callback The callback for if there are any errors
332
- *
333
- * @return void
334
- */
335
- LightwaveRF.prototype.sendUdp = function (message, callback) {
336
- //Add to message
337
- const transactionNumber = this.getTransactionNumber();
338
-
339
- //Prepend code to message
340
- message = transactionNumber + "," + message;
341
-
342
- debug(`[${this.config.ip}] Sending message: ${message}`);
343
-
344
- //Create buffer from message
345
- const messageBuffer = Buffer.from(message, 'utf-8');
346
-
347
- this.sendSocket.setBroadcast(true);
348
-
349
- //Broadcast the message
350
- this.sendSocket.send(messageBuffer, 0, messageBuffer.length, 9760, this.config.ip);
351
-
352
- //Add listener
353
- if (callback) {
354
- this.responseListeners[transactionNumber] = {
355
- time: new Date().getTime(),
356
- listener: callback
357
- };
358
-
359
- // Expire request, trigger retry
360
- setTimeout(() => {
361
- const listener = this.responseListeners[transactionNumber];
362
- if (listener) {
363
- debug("The listener is still there, triggering error");
364
- delete this.responseListeners[transactionNumber];
365
- callback("ERR:EXPIRED", undefined);
366
- }
367
- }, 1000);
368
- }
369
- }
370
-
371
- LightwaveRF.prototype.process = function () {
372
- if (this.queue.length === 0) return;
373
- if (!this.ready) return;
374
- var self = this;
375
- this.ready = false;
376
- this.send.apply(this, this.queue.shift());
377
- setTimeout(function () {
378
- self.ready = true;
379
- self.process();
380
- }, this.timeout);
381
- };
382
-
383
-
384
- /**
385
- * Parser to get de devices from https POST
386
- */
387
- LightwaveRF.prototype.getDevices = function (roomsString, devicesString, typesString, callback) {
388
-
389
- var nrRooms = 8;
390
- var nrDevicesPerRoom = 10;
391
-
392
- var tempRS = roomsString;
393
- var tempDS = devicesString;
394
- var tempTS = typesString;
395
- var deviceCounter = 0;
396
- for (var i = 0; i < nrRooms; i++) {
397
- var rId = i + 1;
398
-
399
- tempRS = tempRS.substring(tempRS.indexOf('\"') + 1);
400
- var rName = tempRS.substring(0, tempRS.indexOf('\"'));
401
- tempRS = tempRS.substring(tempRS.indexOf('\"') + 1);
402
- //console.log("room=" + rName);
403
-
404
- for (var j = 0; j < nrDevicesPerRoom; j++) {
405
- var dId = j + 1;
406
-
407
- tempDS = tempDS.substring(tempDS.indexOf('\"') + 1);
408
- var dName = tempDS.substring(0, tempDS.indexOf('\"'));
409
- tempDS = tempDS.substring(tempDS.indexOf('\"') + 1);
410
- //console.log("devices=" + dName);
411
-
412
- tempTS = tempTS.substring(tempTS.indexOf('\"') + 1);
413
- var dType = tempTS.substring(0, tempTS.indexOf('\"'));
414
- tempTS = tempTS.substring(tempTS.indexOf('\"') + 1);
415
- //console.log("devices=" + deviceName + " type=" + dType);
416
-
417
- // Get device types
418
- // O: On/Off Switch
419
- // D: Dimmer
420
- // R: Radiator(s)
421
- // P: Open/Close
422
- // I: Inactive (i.e. not configured)
423
- // m: Mood (inactive)
424
- // M: Mood (active)
425
- // o: All Off
426
- if (dType == "O" || dType == "D") {
427
- this.devices.push({
428
- roomId: rId, roomName: rName,
429
- deviceId: dId, deviceName: dName,
430
- deviceType: dType
431
- });
432
- //console.log("devices=" + deviceName + " type=" + deviceType);
433
- deviceCounter += 1;
434
- }
435
- }
436
- }
437
-
438
- if (callback) callback(this.devices, this);
439
-
440
- //console.log(this.devices);
441
- }
442
-
443
- /**
444
- * Read configuration from a lightwaverf Gem YAML file
445
- */
446
- LightwaveRF.prototype.getFileConfiguration = function (file, callback) {
447
- try {
448
- var that = this,
449
- yamlConfig = yaml.safeLoad(fs.readFileSync(file, 'utf8'));
450
-
451
- yamlConfig['room'].forEach(function (room, roomIndex) {
452
- room['device'].
453
- filter(function (device) {
454
- return device['type'] == 'O' || device['type'] == 'D';
455
- }).
456
- forEach(function (device, deviceIndex) {
457
- that.devices.push({
458
- roomId: room['id'] ? parseInt(room['id'].substring(1)) : roomIndex + 1,
459
- roomName: room['name'],
460
- deviceId: device['id'] ? parseInt(device['id'].substring(1)) : deviceIndex + 1,
461
- deviceName: device['name'],
462
- deviceType: device['type']
463
- });
464
- });
465
- });
466
-
467
- if (callback) {
468
- callback(that.devices, that);
469
- }
470
-
471
- //console.log(that.devices);
472
-
473
- } catch (e) {
474
- console.log('Unable to read YAML file ' + file);
475
- console.log(e);
476
- }
477
- };
478
-
479
- LightwaveRF.prototype.parseRooms = function (lightwaveResponse, callback) {
480
- debug('Parsing lightwaveResponse: ',
481
- lightwaveResponse.content.estates[0].locations[0].zones[0].rooms[0].devices);
482
-
483
- var home = lightwaveResponse.content.estates[0].locations[0].zones[0];
484
-
485
- for (var i = 0; i < home.rooms.length; i++) {
486
- var r = home.rooms[i];
487
-
488
- debug("Room " + r.name + " with " + r.devices.length + " devices");
489
-
490
- // Get device types
491
- // O: On/Off Switch
492
- // D: Dimmer
493
- // R: Radiator(s)
494
- // P: Open/Close
495
- // I: Inactive (i.e. not configured)
496
- // m: Mood (inactive)
497
- // M: Mood (active)
498
- // o: All Off
499
- var deviceTypeMapping = {
500
- 1: 'L',
501
- 2: 'D',
502
- 3: 'P'
503
- }
504
-
505
- for (var j = 0; j < r.devices.length; j++) {
506
- var d = r.devices[j];
507
-
508
- this.devices.push({
509
- roomId: r.room_number,
510
- roomName: r.name,
511
- deviceId: d.device_number,
512
- deviceName: d.name,
513
- deviceType: deviceTypeMapping[d.device_type_id]
514
- });
515
- }
516
- }
517
-
518
- debug('Devices:', this.devices)
519
-
520
- callback(this.devices, this);
521
- };
522
-
523
- /**
524
- * Connect to the server and obtain the configuration
525
- */
526
- LightwaveRF.prototype.getConfiguration = function (email, pin, manager_host, callback) {
527
- // An object of options to indicate where to post to
528
-
529
- debug('Getting rooms from LightWave');
530
- var self = this;
531
- var host = 'https://control-api.lightwaverf.com';
532
- var json = rp.defaults({
533
- json: true
534
- });
535
- var auth, token;
536
- json.get(host + '/v1/user?password=' + pin + '&username=' + email)
537
- .then(function (res) {
538
- return json.get(host + '/v1/auth?application_key=' + res.application_key)
539
- })
540
- .then(function (res) {
541
- token = res.token;
542
- auth = json.defaults({
543
- headers: {
544
- 'X-LWRF-token': token,
545
- 'X-LWRF-platform': 'ios',
546
- 'X-LWRF-skin': 'lightwaverf'
547
- }
548
- });
549
-
550
- return auth.get(host + '/v1/device_type?nested=1');
551
- })
552
- .then(function (res) {
553
- debug(res);
554
- return auth.get(host + '/v1/user_profile?nested=1')
555
- })
556
- .then(function (res) {
557
- self.parseRooms(res, callback);
558
- });
559
- }
560
-
561
- module.exports = LightwaveRF;
package/test.js DELETED
@@ -1,19 +0,0 @@
1
- console.log("Testing rapid turning on and off");
2
-
3
- const LightwaveRF = require('./');
4
- const lw = new LightwaveRF({
5
- 'email': 'stan@wozniak.com',
6
- 'pin': 2212,
7
- 'timeout': 750
8
- }, devices => {
9
- const ROOM = 1;
10
- const DEVICES = [1];
11
-
12
- DEVICES.forEach(d => {
13
- lw.turnDeviceOn(ROOM, d);
14
- setTimeout(lw.turnDeviceOff.bind(lw, ROOM, d, () => {
15
- console.log("We are done");
16
- lw.stop();
17
- }), 300);
18
- });
19
- })