@evops/lightwaverf 0.0.4 → 0.0.8

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,551 +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
- util.inherits(LightwaveRF, events.EventEmitter);
133
-
134
- LightwaveRF.prototype.initialiseConfiguration = function (callback) {
135
- if (this.config.file) {
136
- this.getFileConfiguration(this.config.file, callback);
137
- } else {
138
- debug("Not using `config.file`")
139
- //Check config
140
- if (!this.config.host) {
141
- this.config.host = "web.trustsmartcloud.com"
142
- }
143
-
144
- if (!this.config.email || !this.config.pin) {
145
- console.log("No email or pin specified. The server configuration (rooms, devices, etc.) cannot be obtained")
146
- }
147
- else {
148
- this.getConfiguration(this.config.email, this.config.pin, this.config.host, callback)
149
- }
150
- }
151
-
152
- }
153
-
154
- /**
155
- * Register this device with the Wi-Fi Link
156
- *
157
- * @param Function callback The callback function
158
- *
159
- * @return void
160
- */
161
- LightwaveRF.prototype.register = function (callback) {
162
- this.sendUdp("!R1Fa", callback);
163
- }
164
-
165
- /**
166
- * Request energy
167
- *
168
- * @param Function callback The callback function
169
- *
170
- * @return void
171
- */
172
- LightwaveRF.prototype.requestEnergy = function (callback) {
173
- this.sendUdp("@?\0", function (error, content) {
174
- if (error) {
175
- //Send error back
176
- callback(error);
177
- } else {
178
- //Determine if this is the energy monitor
179
- //ID,?W=current,max,today,yesterday (all kwh)
180
- var values = content.substring(3).split(",");
181
- callback(undefined, {
182
- current: parseInt(values[0], 10),
183
- max: parseInt(values[1], 10),
184
- today: parseInt(values[2], 10),
185
- yesterday: parseInt(values[3], 10)
186
- });
187
- }
188
- });
189
- }
190
-
191
- /**
192
- * Turn a device off
193
- *
194
- * @param integer roomId The room ID
195
- * @param integer deviceId The device ID
196
- * @param Function callback The callback for if there are any errors
197
- *
198
- * @return void
199
- */
200
- LightwaveRF.prototype.turnDeviceOff = function (roomId, deviceId, callback) {
201
- var state = "0";
202
- this.exec("!R" + roomId + "D" + deviceId + "F" + state + "|\0", callback);
203
- }
204
-
205
- /**
206
- * Turn a device on
207
- *
208
- * @param integer roomId The room ID
209
- * @param integer deviceId The device ID
210
- * @param Function callback The callback for if there are any errors
211
- *
212
- * @return void
213
- */
214
- LightwaveRF.prototype.turnDeviceOn = function (roomId, deviceId, callback) {
215
- var state = "1";
216
- this.exec("!R" + roomId + "D" + deviceId + "F" + state + "|\0", callback);
217
- }
218
-
219
- /**
220
- * Open a device
221
- *
222
- * @param integer roomId The room ID
223
- * @param integer deviceId The device ID
224
- * @param Function callback The callback for if there are any errors
225
- *
226
- * @return void
227
- */
228
- LightwaveRF.prototype.openDevice = function (roomId, deviceId, callback) {
229
- var state = ">";
230
- this.exec("!R" + roomId + "D" + deviceId + "F" + state + "|\0", callback);
231
- }
232
-
233
- /**
234
- * Close a device
235
- *
236
- * @param integer roomId The room ID
237
- * @param integer deviceId The device ID
238
- * @param Function callback The callback for if there are any errors
239
- *
240
- * @return void
241
- */
242
- LightwaveRF.prototype.closeDevice = function (roomId, deviceId, callback) {
243
- var state = "<";
244
- this.exec("!R" + roomId + "D" + deviceId + "F" + state + "|\0", callback);
245
- }
246
-
247
- /**
248
- * Stop a device
249
- *
250
- * @param integer roomId The room ID
251
- * @param integer deviceId The device ID
252
- * @param Function callback The callback for if there are any errors
253
- *
254
- * @return void
255
- */
256
- LightwaveRF.prototype.stopDevice = function (roomId, deviceId, callback) {
257
- var state = "^";
258
- this.exec("!R" + roomId + "D" + deviceId + "F" + state + "|\0", callback);
259
- }
260
-
261
- /**
262
- * Turn all devices in a room off
263
- *
264
- * @param integer roomId The room ID
265
- * @param Function callback The callback for if there are any errors
266
- *
267
- * @return void
268
- */
269
- LightwaveRF.prototype.turnRoomOff = function (roomId, callback) {
270
- this.exec("!R" + roomId + "Fa\0", callback);
271
- }
272
-
273
- /**
274
- * Set the dim percentage of a device
275
- *
276
- * @param integer roomId The room ID
277
- * @param integer deviceId The device ID
278
- * @param integer dimPercentage The percentage to set the device dim
279
- * @param Function callback The callback for if there are any errors
280
- *
281
- * @return void
282
- */
283
- LightwaveRF.prototype.setDeviceDim = function (roomId, deviceId, dimPercentage, callback) {
284
- var dimAmount = parseInt(dimPercentage * 0.32, 10); //Dim is on a scale from 0 to 32
285
-
286
- if (dimAmount === 0) {
287
- this.turnDeviceOff(roomId, deviceId, callback);
288
- } else {
289
- this.exec("!R" + roomId + "D" + deviceId + "FdP" + dimAmount + "|\0", callback);
290
- }
291
- }
292
-
293
- /**
294
- * Get message code
295
- *
296
- * @return string
297
- */
298
- LightwaveRF.prototype.getTransactionNumber = function () {
299
- return this.currentTransactionNumber;
300
- }
301
-
302
-
303
- LightwaveRF.prototype.exec = function () {
304
- // Check if the queue has a reasonable size
305
- if (this.queue.length > 100) {
306
- this.queue.pop();
307
- }
308
-
309
- this.queue.push(arguments);
310
- this.process();
311
- };
312
-
313
- LightwaveRF.prototype.send = function (cmd, callback) {
314
- this.sendUdp(cmd, callback);
315
- //if (callback) callback();
316
- };
317
- /**
318
- * Send a message over udp
319
- *
320
- * @param string message The message to send
321
- * @param Function callback The callback for if there are any errors
322
- *
323
- * @return void
324
- */
325
- LightwaveRF.prototype.sendUdp = function (message, callback) {
326
- //Add to message
327
- const transactionNumber = this.getTransactionNumber();
328
-
329
- //Prepend code to message
330
- message = transactionNumber + "," + message;
331
-
332
- debug(`[${this.config.ip}] Sending message: ${message}`);
333
-
334
- //Create buffer from message
335
- const messageBuffer = Buffer.from(message, 'utf-8');
336
-
337
- this.sendSocket.setBroadcast(true);
338
-
339
- //Broadcast the message
340
- this.sendSocket.send(messageBuffer, 0, messageBuffer.length, 9760, this.config.ip);
341
-
342
- //Add listener
343
- if (callback) {
344
- this.responseListeners[transactionNumber] = {
345
- time: new Date().getTime(),
346
- listener: callback
347
- };
348
-
349
- // Expire request, trigger retry
350
- setTimeout(() => {
351
- const listener = this.responseListeners[transactionNumber];
352
- if (listener) {
353
- debug("The listener is still there, triggering error");
354
- delete this.responseListeners[transactionNumber];
355
- callback(listenerKey, undefined, "ERR:EXPIRED");
356
- }
357
- }, 1000);
358
- }
359
- }
360
-
361
- LightwaveRF.prototype.process = function () {
362
- if (this.queue.length === 0) return;
363
- if (!this.ready) return;
364
- var self = this;
365
- this.ready = false;
366
- this.send.apply(this, this.queue.shift());
367
- setTimeout(function () {
368
- self.ready = true;
369
- self.process();
370
- }, this.timeout);
371
- };
372
-
373
-
374
- /**
375
- * Parser to get de devices from https POST
376
- */
377
- LightwaveRF.prototype.getDevices = function (roomsString, devicesString, typesString, callback) {
378
-
379
- var nrRooms = 8;
380
- var nrDevicesPerRoom = 10;
381
-
382
- var tempRS = roomsString;
383
- var tempDS = devicesString;
384
- var tempTS = typesString;
385
- var deviceCounter = 0;
386
- for (var i = 0; i < nrRooms; i++) {
387
- var rId = i + 1;
388
-
389
- tempRS = tempRS.substring(tempRS.indexOf('\"') + 1);
390
- var rName = tempRS.substring(0, tempRS.indexOf('\"'));
391
- tempRS = tempRS.substring(tempRS.indexOf('\"') + 1);
392
- //console.log("room=" + rName);
393
-
394
- for (var j = 0; j < nrDevicesPerRoom; j++) {
395
- var dId = j + 1;
396
-
397
- tempDS = tempDS.substring(tempDS.indexOf('\"') + 1);
398
- var dName = tempDS.substring(0, tempDS.indexOf('\"'));
399
- tempDS = tempDS.substring(tempDS.indexOf('\"') + 1);
400
- //console.log("devices=" + dName);
401
-
402
- tempTS = tempTS.substring(tempTS.indexOf('\"') + 1);
403
- var dType = tempTS.substring(0, tempTS.indexOf('\"'));
404
- tempTS = tempTS.substring(tempTS.indexOf('\"') + 1);
405
- //console.log("devices=" + deviceName + " type=" + dType);
406
-
407
- // Get device types
408
- // O: On/Off Switch
409
- // D: Dimmer
410
- // R: Radiator(s)
411
- // P: Open/Close
412
- // I: Inactive (i.e. not configured)
413
- // m: Mood (inactive)
414
- // M: Mood (active)
415
- // o: All Off
416
- if (dType == "O" || dType == "D") {
417
- this.devices.push({
418
- roomId: rId, roomName: rName,
419
- deviceId: dId, deviceName: dName,
420
- deviceType: dType
421
- });
422
- //console.log("devices=" + deviceName + " type=" + deviceType);
423
- deviceCounter += 1;
424
- }
425
- }
426
- }
427
-
428
- if (callback) callback(this.devices, this);
429
-
430
- //console.log(this.devices);
431
- }
432
-
433
- /**
434
- * Read configuration from a lightwaverf Gem YAML file
435
- */
436
- LightwaveRF.prototype.getFileConfiguration = function (file, callback) {
437
- try {
438
- var that = this,
439
- yamlConfig = yaml.safeLoad(fs.readFileSync(file, 'utf8'));
440
-
441
- yamlConfig['room'].forEach(function (room, roomIndex) {
442
- room['device'].
443
- filter(function (device) {
444
- return device['type'] == 'O' || device['type'] == 'D';
445
- }).
446
- forEach(function (device, deviceIndex) {
447
- that.devices.push({
448
- roomId: room['id'] ? parseInt(room['id'].substring(1)) : roomIndex + 1,
449
- roomName: room['name'],
450
- deviceId: device['id'] ? parseInt(device['id'].substring(1)) : deviceIndex + 1,
451
- deviceName: device['name'],
452
- deviceType: device['type']
453
- });
454
- });
455
- });
456
-
457
- if (callback) {
458
- callback(that.devices, that);
459
- }
460
-
461
- //console.log(that.devices);
462
-
463
- } catch (e) {
464
- console.log('Unable to read YAML file ' + file);
465
- console.log(e);
466
- }
467
- };
468
-
469
- LightwaveRF.prototype.parseRooms = function (lightwaveResponse, callback) {
470
- debug('Parsing lightwaveResponse: ',
471
- lightwaveResponse.content.estates[0].locations[0].zones[0].rooms[0].devices);
472
-
473
- var home = lightwaveResponse.content.estates[0].locations[0].zones[0];
474
-
475
- for (var i = 0; i < home.rooms.length; i++) {
476
- var r = home.rooms[i];
477
-
478
- debug("Room " + r.name + " with " + r.devices.length + " devices");
479
-
480
- // Get device types
481
- // O: On/Off Switch
482
- // D: Dimmer
483
- // R: Radiator(s)
484
- // P: Open/Close
485
- // I: Inactive (i.e. not configured)
486
- // m: Mood (inactive)
487
- // M: Mood (active)
488
- // o: All Off
489
- var deviceTypeMapping = {
490
- 1: 'L',
491
- 2: 'D',
492
- 3: 'P'
493
- }
494
-
495
- for (var j = 0; j < r.devices.length; j++) {
496
- var d = r.devices[j];
497
-
498
- this.devices.push({
499
- roomId: r.room_number,
500
- roomName: r.name,
501
- deviceId: d.device_number,
502
- deviceName: d.name,
503
- deviceType: deviceTypeMapping[d.device_type_id]
504
- });
505
- }
506
- }
507
-
508
- debug('Devices:', this.devices)
509
-
510
- callback(this.devices, this);
511
- };
512
-
513
- /**
514
- * Connect to the server and obtain the configuration
515
- */
516
- LightwaveRF.prototype.getConfiguration = function (email, pin, manager_host, callback) {
517
- // An object of options to indicate where to post to
518
-
519
- debug('Getting rooms from LightWave');
520
- var self = this;
521
- var host = 'https://control-api.lightwaverf.com';
522
- var json = rp.defaults({
523
- json: true
524
- });
525
- var auth, token;
526
- json.get(host + '/v1/user?password=' + pin + '&username=' + email)
527
- .then(function (res) {
528
- return json.get(host + '/v1/auth?application_key=' + res.application_key)
529
- })
530
- .then(function (res) {
531
- token = res.token;
532
- auth = json.defaults({
533
- headers: {
534
- 'X-LWRF-token': token,
535
- 'X-LWRF-platform': 'ios',
536
- 'X-LWRF-skin': 'lightwaverf'
537
- }
538
- });
539
-
540
- return auth.get(host + '/v1/device_type?nested=1');
541
- })
542
- .then(function (res) {
543
- debug(res);
544
- return auth.get(host + '/v1/user_profile?nested=1')
545
- })
546
- .then(function (res) {
547
- self.parseRooms(res, callback);
548
- });
549
- }
550
-
551
- module.exports = LightwaveRF;
package/test.js DELETED
@@ -1,17 +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
- 'ip': '10.0.1.177',
8
- 'timeout': 750
9
- }, devices => {
10
- const ROOM = 3;
11
- const DEVICES = [1,2,3];
12
-
13
- DEVICES.forEach(d => {
14
- lw.turnDeviceOn(ROOM, d);
15
- setTimeout(lw.turnDeviceOff.bind(lw, ROOM, d), 300);
16
- });
17
- })