node-red-contrib-yandex-station-management 0.3.3 → 0.3.6

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.
@@ -0,0 +1,52 @@
1
+ 'use strict';
2
+
3
+ class stationHelper {
4
+
5
+ static preparePayload(node, message) {
6
+ let payload = {};
7
+ if (node.output == 'status') {
8
+ payload = { 'payload': message }
9
+ } else if (node.output == 'homekit') {
10
+ let playing = false;
11
+ if (typeof(message.playing) !== 'undefined') {
12
+ playing = message.playing;
13
+ }
14
+ if (node.homekitFormat == 'speaker') {
15
+ let subtitle = 'No Artist';
16
+ let title = 'No Track Name';
17
+
18
+ if (typeof(message.playerState) !== 'undefined') {
19
+ let playerState = message.playerState;
20
+ if (typeof(playerState.subtitle) !== 'undefined') {
21
+ subtitle = playerState.subtitle;
22
+ }
23
+ if (typeof(playerState.title) !== 'undefined') {
24
+ title = playerState.title;
25
+ }
26
+ }
27
+
28
+ let ConfiguredName = `${subtitle} - ${title}`;
29
+ if (ConfiguredName.length > 64) {
30
+ ConfiguredName = title.length <= 64 ? title : title.substr(0, 61) + `...`;
31
+ }
32
+
33
+ payload = {
34
+ 'payload': {
35
+ 'CurrentMediaState': (playing) ? 0 : 1,
36
+ 'ConfiguredName': ConfiguredName
37
+ }
38
+ }
39
+ } else if (node.homekitFormat == 'tv') {
40
+ payload = {
41
+ 'payload': {
42
+ 'Active': (playing) ? 1 : 0
43
+ }
44
+ }
45
+ }
46
+ }
47
+ return payload;
48
+ }
49
+
50
+ }
51
+
52
+ module.exports = stationHelper;
package/nodes/get.js CHANGED
@@ -1,4 +1,6 @@
1
1
  module.exports = function(RED) {
2
+ const stationHelper = require('../lib/stationHelper.js');
3
+
2
4
  function AliceLocalGetNode(config) {
3
5
  RED.nodes.createNode(this,config);
4
6
  let node = this;
@@ -16,43 +18,15 @@ module.exports = function(RED) {
16
18
  node.log(text);
17
19
  }
18
20
  }
19
- function preparePayload(message,inputMsg){
20
- //let payload = {};
21
- if (node.output == 'status') {
22
- inputMsg.payload = message;
23
- } else if (node.output == 'homekit') {
24
- try {
25
- if (node.homekitFormat == 'speaker') {
26
- let ConfiguredName = `${(message.playerState.subtitle) ? message.playerState.subtitle : 'No Artist'} - ${(message.playerState.title) ? message.playerState.title : 'No Track Name'}`;
27
- let title = `${message.playerState.title}`;
28
- if (ConfiguredName.length > 64 && title.length > 0 && title.length <= 64) {
29
- ConfiguredName = title;
30
- } else {
31
- ConfiguredName = title.substr(0, 61) + `...`;
32
- }
33
- (message.playerState)? inputMsg.payload = {
34
- "CurrentMediaState": (message.playing) ? 0 : 1,
35
- "ConfiguredName": ConfiguredName
36
- } :inputMsg.payload = {
37
- "CurrentMediaState": (message.playing) ? 0 : 1,
38
- "ConfiguredName": `No Artist - No Track Name`
39
- }
40
- }else if (node.homekitFormat == 'tv') {
41
- inputMsg.payload = {
42
- "Active": (message.playing) ? 1 : 0
43
- }
44
-
45
- }
46
- } catch (error) {
47
- debugMessage(`Error while preparing payload: `+ e);
48
- }
49
21
 
22
+ function _preparePayload(message, inputMsg) {
23
+ let prepare = stationHelper.preparePayload(node, message);
24
+ if (typeof(prepare.payload) !== 'undefined') {
25
+ inputMsg.payload = prepare.payload;
50
26
  }
51
- return inputMsg;
52
-
27
+ return inputMsg;
53
28
  }
54
29
 
55
-
56
30
  node.onStatus = function(data) {
57
31
  if (data) {
58
32
  node.status({fill: `${data.color}`,shape:"dot",text: `${data.text}`});
@@ -61,7 +35,7 @@ module.exports = function(RED) {
61
35
  }
62
36
  node.onInput = function(msg, send, done){
63
37
  debugMessage('current state: ' + JSON.stringify(node.lastState));
64
- ( 'aliceState' in node.lastState )?node.send(preparePayload(node.lastState,msg)):node.send(msg)
38
+ ( 'aliceState' in node.lastState )?node.send(_preparePayload(node.lastState,msg)):node.send(msg)
65
39
  }
66
40
  node.onMessage = function(message){
67
41
  node.lastState = message;
package/nodes/in.js CHANGED
@@ -1,4 +1,6 @@
1
1
  module.exports = function(RED) {
2
+ const stationHelper = require('../lib/stationHelper.js');
3
+
2
4
  function AliceLocalInNode(config) {
3
5
  RED.nodes.createNode(this,config);
4
6
  let node = this;
@@ -20,42 +22,6 @@ module.exports = function(RED) {
20
22
  }
21
23
  }
22
24
 
23
-
24
- function preparePayload(message){
25
- let payload = {};
26
- if (node.output == 'status') {
27
- payload = {'payload': message}
28
- } else if (node.output == 'homekit') {
29
- try {
30
- if (node.homekitFormat == 'speaker') {
31
- let ConfiguredName = `${(message.playerState.subtitle) ? message.playerState.subtitle : 'No Artist'} - ${(message.playerState.title) ? message.playerState.title : 'No Track Name'}`;
32
- let title = `${message.playerState.title}`;
33
- if (ConfiguredName.length > 64 && title.length > 0 && title.length <= 64) {
34
- ConfiguredName = title;
35
- } else {
36
- ConfiguredName = title.substr(0, 61) + `...`;
37
- }
38
- (message.playerState)? payload = {'payload': {
39
- "CurrentMediaState": (message.playing) ? 0 : 1,
40
- "ConfiguredName": ConfiguredName
41
- } }:payload = {'payload': {
42
- "CurrentMediaState": (message.playing) ? 0 : 1,
43
- "ConfiguredName": `No Artists - No Track Name`
44
- } }
45
- }else if (node.homekitFormat == 'tv') {
46
- payload = {'payload': {
47
- "Active": (message.playing) ? 1 : 0
48
- }
49
- }
50
- }
51
- } catch(e) {
52
- debugMessage(`Error while preparing payload: `+ e)
53
- }
54
-
55
- }
56
- return payload;
57
-
58
- }
59
25
  function sendMessage(message){
60
26
  //debugMessage(JSON.stringify(message));
61
27
  if (node.uniqueFlag && node.output == 'homekit') {
@@ -71,7 +37,7 @@ module.exports = function(RED) {
71
37
  }
72
38
  node.onMessage = function(data){
73
39
  //debugMessage(JSON.stringify(data));
74
- sendMessage(preparePayload(data));
40
+ sendMessage(stationHelper.preparePayload(node, data));
75
41
  }
76
42
  node.onStatus = function(data) {
77
43
  if (data) {
@@ -18,27 +18,32 @@ module.exports = function(RED) {
18
18
  node.readyList = [];
19
19
  node.activeStationList = [];
20
20
  //node.skipCloudDevices = false;
21
-
22
-
21
+
22
+
23
23
  node.on('stopListening', onStopListening);
24
24
  node.on('startPlay', onStartPlay);
25
25
  node.on('stopPlay', onStopPlay);
26
26
  node.on('setVolume', onSetVolume);
27
27
  node.on('deviceReady', onDeviceReady);
28
28
  node.setMaxListeners(0)
29
-
29
+
30
30
  function debugMessage(text){
31
31
  if (node.debugFlag) {
32
- node.log(text);
32
+ try {
33
+ node.log(text);
34
+ } catch (error) {
35
+ node.log(error)
36
+ }
37
+
33
38
  }
34
39
  }
35
-
40
+
36
41
  let registrationBuffer = [];
37
-
42
+
38
43
  function deviceListProcessing(deviceList) {
39
44
  deviceList.forEach(device => {
40
45
  if (device.address && device.port ) {
41
-
46
+
42
47
  if (node.readyList.find(item => item.id == device.id)){
43
48
  //debugMessage('skipping');
44
49
  } else {
@@ -54,23 +59,23 @@ module.exports = function(RED) {
54
59
 
55
60
  async function getDevices(token)
56
61
  {
57
- let options =
58
- {
62
+ let options =
63
+ {
59
64
  method: 'GET',
60
65
  url: 'https://quasar.yandex.net/glagol/device_list',
61
- headers:
62
- {
66
+ headers:
67
+ {
63
68
  'Content-Type': 'application/json',
64
- 'Authorization': 'Oauth ' + token
65
- }
69
+ 'Authorization': 'Oauth ' + token
70
+ }
66
71
  };
67
- // вариант для снижения частоты запросов на серверы ЯНдекса для обновления списка устройств. Требует тестирования.
72
+ // вариант для снижения частоты запросов на серверы ЯНдекса для обновления списка устройств. Требует тестирования.
68
73
  /* if (node.skipCloudDevices) {
69
74
  discoverDevices(node.deviceList)
70
75
  .then(() => {
71
76
  //debugMessage(`calling processing for ${node.deviceList.length} devices`);
72
77
  deviceListProcessing(node.deviceList)
73
-
78
+
74
79
  });
75
80
  return node.deviceList;
76
81
  } */
@@ -91,7 +96,7 @@ module.exports = function(RED) {
91
96
  if (result != 2 && result != undefined) {
92
97
  registrationBuffer.splice(registrationBuffer.indexOf(bufferStation,1));
93
98
  }
94
-
99
+
95
100
  }
96
101
  node.activeStationList.push({ 'name': device.name, 'id': device.id, 'platform': device.platform, 'address': device.address, 'port': device.port});
97
102
  });
@@ -102,13 +107,13 @@ module.exports = function(RED) {
102
107
  .then(() => {
103
108
  //debugMessage(`calling processing for ${node.deviceList.length} devices`);
104
109
  deviceListProcessing(node.deviceList)
105
-
110
+
106
111
  });
107
112
  //debugMessage(node.id);
108
113
  return node.deviceList;
109
114
  } catch (error) {
110
115
  debugMessage(`Error while searching: ${error}`);
111
- }
116
+ }
112
117
 
113
118
  })
114
119
  .catch(function (err) {
@@ -126,7 +131,6 @@ module.exports = function(RED) {
126
131
  await mDnsSd.discover({
127
132
  name: '_yandexio._tcp.local'
128
133
  }).then((result) => {
129
- debugMessage(`MDNS. Found ${result.length} devices`);
130
134
  node.emit('refreshHttpDNS', result);
131
135
  if (result.length != 0){
132
136
  for (const device of deviceList) {
@@ -147,15 +151,15 @@ module.exports = function(RED) {
147
151
  } catch(e) {
148
152
  debugMessage(`Error searching hostname in mDNS answer`)
149
153
  }
150
-
154
+
151
155
  }
152
156
  }
153
- }
157
+ }
154
158
  })
155
-
159
+
156
160
  }
157
161
  }
158
-
162
+
159
163
  }).catch(function (err) {
160
164
  debugMessage(err);
161
165
  });
@@ -172,15 +176,15 @@ module.exports = function(RED) {
172
176
 
173
177
  async function getLocalToken(device) {
174
178
  let data;
175
- let options = {
179
+ let options = {
176
180
  method: 'GET',
177
181
  url: 'https://quasar.yandex.net/glagol/token',
178
182
  qs: { device_id: device.id, platform: device.platform },
179
- headers:
180
- {
183
+ headers:
184
+ {
181
185
  'Authorization': 'Oauth ' + node.token,
182
- 'Content-Type': 'application/json'
183
- }
186
+ 'Content-Type': 'application/json'
187
+ }
184
188
  };
185
189
  // debugMessage(JSON.stringify(options))
186
190
  statusUpdate({"color": "yellow", "text": "connecting..."}, device);
@@ -188,7 +192,8 @@ module.exports = function(RED) {
188
192
  .then(function(response)
189
193
  {
190
194
  data = JSON.parse(response);
191
- device.token = data.token
195
+ device.token = data.token;
196
+ debugMessage(`${device.id}: Recieved conversation new token`)
192
197
  })
193
198
  .catch(function (err) {
194
199
  removeDevice(node.readyList, device);
@@ -208,12 +213,12 @@ module.exports = function(RED) {
208
213
  connect(device)
209
214
  };
210
215
 
211
-
216
+
212
217
  function connect(device) {
213
218
  //connect only if !device.ws
214
219
  //debugMessage(`device.ws = ${JSON.stringify(device.ws)}`);
215
220
  if ( (device.connection == true || typeof(device.connection) == "undefined") && node.listenerCount(`statusUpdate_${device.id}`) > 0 ) {
216
- debugMessage(`Connecting to device ${device.id}. ws is ${JSON.stringify(device.ws)}. Listeners: ` + node.listenerCount(`statusUpdate_${device.id}`));
221
+ debugMessage(`Connecting to device ${device.id}. ws is ${device.ws}. Listeners: ` + node.listenerCount(`statusUpdate_${device.id}`));
217
222
  if (!device.ws) {
218
223
  debugMessage('recieving conversation token...');
219
224
  getLocalToken(device)
@@ -226,7 +231,7 @@ module.exports = function(RED) {
226
231
  })
227
232
  .catch(function (err) {
228
233
  debugMessage('Error while getting token: ' + err);
229
-
234
+
230
235
  });
231
236
  } else {
232
237
  if (device.ws.readyState == 3) {
@@ -258,16 +263,16 @@ module.exports = function(RED) {
258
263
  //}
259
264
  }
260
265
  } else {
261
- debugMessage(`${device.id} connection is disabled by settings in manager node ${device.manager} or you have not use any node for this station`)
262
- statusUpdate({"color": "red", "text": "disconnected"}, device);
266
+ //debugMessage(`${device.id} connection is disabled by settings in manager node ${device.manager} or you have not use any node for this station`)
267
+ //statusUpdate({"color": "red", "text": "disconnected"}, device);
263
268
  device.timer = setTimeout(connect, 60000, device);
264
269
 
265
270
  }
266
271
 
267
272
  }
268
-
273
+
269
274
  async function makeConn(device) {
270
-
275
+
271
276
  let options = {
272
277
  key: device.glagol.security.server_private_key,
273
278
  cert: device.glagol.security.server_certificate,
@@ -276,7 +281,9 @@ module.exports = function(RED) {
276
281
  device.lastState = {};
277
282
  debugMessage(`Connecting to wss://${device.address}:${device.port}`);
278
283
  device.ws = new WebSocket(`wss://${device.address}:${device.port}`, options);
279
- device.ws.on('open', function open(data) {
284
+ debugMessage(`${device.id}: Fire connection watchdog for 60 seconds`);
285
+ device.watchDogConn = setTimeout(() => {reconnect(device)}, 60000);
286
+ device.ws.on('open', function open(data) {
280
287
  debugMessage(`Connected to ${device.address}, data: ${data}`);
281
288
  sendMessage(device.id, 'command', {payload: 'ping'});
282
289
  statusUpdate({"color": "green", "text": "connected"}, device);
@@ -286,13 +293,15 @@ module.exports = function(RED) {
286
293
  device.waitForIdle = false;
287
294
  device.watchDog = setTimeout(() => device.ws.close(), 10000);
288
295
  device.pingInterval = setInterval(onPing,300,device);
296
+ debugMessage(`${device.id}: Kill connection watchdog`);
297
+ clearTimeout(device.watchDogConn);
289
298
  clearTimeout(device.timer);
290
- debugMessage(`readyState: ${device.ws.readyState}`)
299
+ //debugMessage(`readyState: ${device.ws.readyState}`)
291
300
  });
292
301
  device.ws.on('message', function incoming(data) {
293
302
  //debugMessage(`${device.id}: ${JSON.stringify(data)}`);
294
303
  let dataRecieved = JSON.parse(data);
295
- device.lastState = dataRecieved.state;
304
+ device.lastState = dataRecieved.state;
296
305
  device.fullMessage = JSON.stringify(dataRecieved);
297
306
  //debugMessage(checkSheduler(device, JSON.parse(data).sentTime));
298
307
  node.emit(`message_${device.id}`, device.lastState);
@@ -312,7 +321,7 @@ module.exports = function(RED) {
312
321
  if (device.lastState.playing && device.lastState.aliceState != 'LISTENING' && device.parameters.hasOwnProperty("sheduler")) {
313
322
  let res = checkSheduler(device, dataRecieved.sentTime)
314
323
  //debugMessage(`Result of cheking sheduler is ${res.toString}`);
315
- if (!res[0]) {
324
+ if (!res[0]) {
316
325
  if (device.shedulerFlag || device.shedulerFlag == undefined) {
317
326
  node.emit('stopPlay', device, res[1])
318
327
  device.shedulerFlag = false
@@ -324,7 +333,7 @@ module.exports = function(RED) {
324
333
  clearTimeout(device.watchDog);
325
334
  //debugMessage(`cleared timeout for ${device.id}`)
326
335
  device.watchDog = setTimeout(() => {device.ws.close()}, 10000);
327
- });
336
+ });
328
337
  //device.ws.on('ping', function);
329
338
  device.ws.on('close', function close(code, reason){
330
339
  statusUpdate({"color": "red", "text": "disconnected"}, device);
@@ -336,15 +345,15 @@ module.exports = function(RED) {
336
345
  debugMessage(`getting new token...`);
337
346
  connect(device);
338
347
  break;
339
- case 1000:
348
+ case 1000:
340
349
  debugMessage(`Closed connection code ${code} with reason ${reason}. Reconnecting...` );
341
350
  connect(device);
342
- break;
351
+ break;
343
352
  case 1006:
344
353
  debugMessage(`Lost server, reconnect in 60 seconds...${code} + ${reason}` );
345
354
  device.timer = setTimeout(connect, 60000, device);
346
355
  break;
347
-
356
+
348
357
  case 10000:
349
358
  debugMessage(`Reconnect device reason 10000 ${device.id}`);
350
359
  connect(device);
@@ -356,15 +365,13 @@ module.exports = function(RED) {
356
365
  }
357
366
 
358
367
 
359
- })
368
+ })
360
369
  device.ws.on('error', function error(data){
361
370
  //statusUpdate({"color": "red", "text": "disconnected"}, device);
362
371
  debugMessage(`error: ${data}`);
363
- device.ws.terminate();
364
- // if (device.localConnectionFlag) {
365
- // debugMessage(`Reconnecting in 60 seconds...` );
366
- // setTimeout(connect, 60000, device);
367
- // }
372
+ if (typeof(device) !== 'undefined' && typeof(device.ws) !== 'undefined' ) {
373
+ device.ws.terminate();
374
+ }
368
375
  });
369
376
  };
370
377
 
@@ -417,7 +424,7 @@ module.exports = function(RED) {
417
424
  return [{
418
425
  "command": "rewind",
419
426
  "position": 0
420
- }]
427
+ }]
421
428
  }
422
429
  } else if (message.payload == 'volumeup') {
423
430
  debugMessage(currentVolume);
@@ -425,7 +432,7 @@ module.exports = function(RED) {
425
432
  return [{
426
433
  "command": "setVolume",
427
434
  "volume": currentVolume + 0.1
428
- }]
435
+ }]
429
436
  }
430
437
  } else if (message.payload == 'volumedown') {
431
438
  debugMessage(currentVolume);
@@ -433,13 +440,13 @@ module.exports = function(RED) {
433
440
  return [{
434
441
  "command": "setVolume",
435
442
  "volume": currentVolume - 0.1
436
- }]
443
+ }]
437
444
  }
438
445
  } else if (message.payload == 'volume') {
439
446
  return [{
440
447
  "command": "setVolume",
441
448
  "volume": parseFloat(message.level)
442
- }]
449
+ }]
443
450
  }
444
451
 
445
452
  } else {
@@ -447,7 +454,7 @@ module.exports = function(RED) {
447
454
  //node.error(`You can send commands in msg.payload from list as String ${commands + extraCommands}`);
448
455
  return [{"command": "ping"}];
449
456
  }
450
- case 'voice':
457
+ case 'voice':
451
458
  debugMessage(`Message Voice command: ${message}`);
452
459
  return [{
453
460
  "command" : "sendText",
@@ -515,56 +522,84 @@ module.exports = function(RED) {
515
522
  return result;
516
523
  break;
517
524
  case 'homekit':
518
- debugMessage('HAP: ' + JSON.stringify(message) + ' PL: ' + JSON.stringify(message.payload) );
525
+ debugMessage('HAP: ' + JSON.stringify(message) + ' PL: ' + JSON.stringify(message.payload) );
519
526
  if ("session" in message.hap) {
520
- switch(JSON.stringify(message.payload)){
521
- case '{"TargetMediaState":1}':
522
- return messageConstructor('command', {'payload': 'stop'})
523
- case '{"Active":0}':
524
- return messageConstructor('command', {'payload': 'stop'})
525
- case '{"TargetMediaState":0}':
526
- case '{"Active":1}':
527
- if (!device.lastState.playerState && !device.playAfterTTS && message.noTrackPhrase) {
528
- return messageConstructor('voice', {'payload': message.noTrackPhrase})
529
- } else if (device.lastState.playerState.title != "" && !device.playAfterTTS){
530
- return messageConstructor('command', {'payload': 'play'})
531
- } else if (message.noTrackPhrase && !device.playAfterTTS) {
532
- return messageConstructor('voice', {'payload': message.noTrackPhrase})
533
- } else {
534
- return messageConstructor('command', {'payload': 'ping'})
527
+ let playing = false;
528
+ let id = null;
529
+ let noTrackPhrase = message.noTrackPhrase;
530
+
531
+ if (typeof (device.lastState) !== 'undefined') {
532
+ let lastState = device.lastState;
533
+ if (typeof (lastState.playing) !== 'undefined') {
534
+ playing = lastState.playing;
535
+ }
536
+ if (typeof (lastState.playerState) !== 'undefined') {
537
+ if (typeof (lastState.playerState.id) !== 'undefined') {
538
+ id = lastState.playerState.id;
535
539
  }
536
- case '{"RemoteKey":7}':
537
- return messageConstructor('command', {'payload': 'forward'}, device)
538
- case '{"RemoteKey":6}':
539
- return messageConstructor('command', {'payload': 'backward'}, device)
540
- case '{"RemoteKey":4}':
541
- return messageConstructor('command', {'payload': 'next'})
542
- case '{"RemoteKey":5}':
543
- return messageConstructor('command', {'payload': 'prev'})
544
- case '{"RemoteKey":11}':
545
- if (typeof device.lastState.playing !== "undefined") {
546
- if (device.lastState.playing){
547
- return messageConstructor('command', {'payload': 'stop'})
540
+ }
541
+ }
542
+
543
+ // speaker
544
+ if ("TargetMediaState" in message.payload) {
545
+ let TargetMediaState = message.payload.TargetMediaState;
546
+ if (id) {
547
+ return messageConstructor('command', { 'payload': (TargetMediaState ? 'stop' : 'play') })
548
+ } else if (!id && !TargetMediaState && noTrackPhrase) {
549
+ return messageConstructor('voice', { 'payload': noTrackPhrase })
550
+ }
551
+ }
552
+
553
+ // tv
554
+ if ("Active" in message.payload) {
555
+ let Active = message.payload.Active;
556
+ if (id) {
557
+ return messageConstructor('command', { 'payload': (Active ? 'play' : 'stop') })
558
+ } else if (!id && Active && noTrackPhrase) {
559
+ return messageConstructor('voice', { 'payload': noTrackPhrase })
560
+ }
561
+ }
562
+
563
+ // tv + RemoteKey
564
+ if ("RemoteKey" in message.payload) {
565
+ let RemoteKey = message.payload.RemoteKey;
566
+ switch (RemoteKey) {
567
+ case '7':
568
+ return messageConstructor('command', { 'payload': 'forward' }, device)
569
+ case '6':
570
+ return messageConstructor('command', { 'payload': 'backward' }, device)
571
+ case '4':
572
+ return messageConstructor('command', { 'payload': 'next' })
573
+ case '5':
574
+ return messageConstructor('command', { 'payload': 'prev' })
575
+ case '11':
576
+ if (playing) {
577
+ return messageConstructor('command', { 'payload': 'stop' })
548
578
  } else {
549
- return messageConstructor('command', {'payload': 'play'})
579
+ if (id) {
580
+ return messageConstructor('command', { 'payload': 'play' })
581
+ } else if (!id && noTrackPhrase) {
582
+ return messageConstructor('voice', { 'payload': noTrackPhrase })
583
+ }
550
584
  }
551
- }
552
- case '{"VolumeSelector":1}':
553
- return messageConstructor('command', {'payload': 'volumedown'}, device)
554
- case '{"VolumeSelector":0}':
555
- return messageConstructor('command', {'payload': 'volumeup'}, device)
556
- default:
557
- debugMessage('unknown command')
558
- return messageConstructor('command', {'payload': 'ping'})
585
+ }
586
+ }
587
+
588
+ // tv + VolumeSelector
589
+ if ("VolumeSelector" in message.payload) {
590
+ let VolumeSelector = message.payload.VolumeSelector;
591
+ return messageConstructor('command', { 'payload': (VolumeSelector ? 'volumedown' : 'volumeup') }, device)
559
592
  }
560
-
593
+
594
+ debugMessage('unknown command')
595
+ return messageConstructor('command', { 'payload': 'ping' })
561
596
  } else {
562
- return messageConstructor('command', {'payload': 'ping'})
597
+ return messageConstructor('command', { 'payload': 'ping' })
563
598
  }
564
- case 'raw':
599
+ case 'raw':
565
600
  if (Array.isArray(message.payload)) { return message.payload }
566
601
  return [message.payload];
567
- case 'stopListening':
602
+ case 'stopListening':
568
603
  return [{
569
604
  "command": "serverAction",
570
605
  "serverActionEventPayload": {
@@ -576,7 +611,7 @@ module.exports = function(RED) {
576
611
 
577
612
  }
578
613
  function sendMessage(deviceId, messageType, message) {
579
-
614
+
580
615
  try {
581
616
  let device = searchDeviceByID(deviceId);
582
617
  //debugMessage(`deviceId: ${searchDeviceByID(deviceId)}`);
@@ -617,19 +652,19 @@ module.exports = function(RED) {
617
652
  //debugMessage(`timeCur: ${timeCurrent} timeMin: ${timeMin} timeMax: ${timeMax}`);
618
653
  return [false, daySheduler.phrase];
619
654
  }
620
-
655
+
621
656
 
622
657
  }
623
-
658
+
624
659
  function searchDeviceByID(id) {
625
660
  if (node.deviceList) {
626
661
  return node.deviceList.find(device => device.id == id)
627
- }
662
+ }
628
663
  }
629
664
  function onPing(device) {
630
665
  if (device) {sendMessage(device.id, 'command', {payload: 'ping'});}
631
666
  }
632
-
667
+
633
668
  function onPing(device) {
634
669
  sendMessage(device.id, 'command', {payload: 'ping'});
635
670
  }
@@ -638,19 +673,19 @@ module.exports = function(RED) {
638
673
  if (device) {
639
674
  if (device.ws) {
640
675
  switch(device.ws.readyState){
641
- case 0:
676
+ case 0:
642
677
  return {"color": "yellow", "text": "connecting..."}
643
- case 1:
678
+ case 1:
644
679
  return {"color": "green", "text": "connected"}
645
- case 2:
680
+ case 2:
646
681
  return {"color": "red", "text": "disconnecting"}
647
- case 3:
682
+ case 3:
648
683
  return {"color": "red", "text": "disconnected"}
649
684
  default:
650
685
  return {"color": "red", "text": "disconnected"}
651
686
  }
652
-
653
- }
687
+
688
+ }
654
689
  } else {
655
690
  return {"color": "red", "text": "disconnected"}
656
691
  }
@@ -658,7 +693,7 @@ module.exports = function(RED) {
658
693
  }
659
694
 
660
695
 
661
-
696
+
662
697
  function registerDevice(deviceId, nodeId, parameters) {
663
698
  let device = searchDeviceByID(deviceId);
664
699
  debugMessage(`Recieved parameters ${JSON.stringify(parameters)} for station id ${deviceId}`);
@@ -670,7 +705,7 @@ module.exports = function(RED) {
670
705
  debugMessage(`Device ${device.id} already registered with manager id ${device.manager}. Updating parameters and restart...`);
671
706
  reconnect(device);
672
707
  return 1;
673
-
708
+
674
709
  }
675
710
  //новый и первый запрос на регистрацию для устройства
676
711
  if (typeof(device.manager) == 'undefined') {
@@ -699,7 +734,7 @@ module.exports = function(RED) {
699
734
  registrationBuffer.splice(registrationBuffer.indexOf(currentBuffer), 1)
700
735
  debugMessage(`Element from registration buffer was deleted. Current buffer size is ${registrationBuffer.length}`)
701
736
  }
702
- reconnect(device);
737
+ reconnect(device);
703
738
  return 0;
704
739
  }
705
740
  //новый запрос на регистрацию при наличии уже зарегистрированной ноды
@@ -717,9 +752,9 @@ module.exports = function(RED) {
717
752
  registrationBuffer.push({"id": deviceId, "manager": nodeId, "parameters": parameters});
718
753
  debugMessage(`New element in registration buffer. Current buffer size is ${registrationBuffer.length}`)
719
754
  }
720
-
755
+
721
756
  }
722
-
757
+
723
758
 
724
759
  }
725
760
  function unregisterDevice(deviceId, nodeId){
@@ -730,7 +765,7 @@ module.exports = function(RED) {
730
765
  device.parameters = {};
731
766
  debugMessage(`For device ${deviceId} was succesfully unregistred managment node whith id ${device.manager}`);
732
767
  debugMessage(`device is: ${device}`);
733
- return 0;
768
+ return 0;
734
769
  } else {
735
770
  return 2;
736
771
  }
@@ -751,7 +786,7 @@ module.exports = function(RED) {
751
786
  if (device.savedVolumeLevel) { sendMessage(device.id, 'raw',{payload: {
752
787
  "command": "setVolume",
753
788
  "volume": parseFloat(device.savedVolumeLevel)
754
- }
789
+ }
755
790
  });
756
791
  }
757
792
  device.waitForIdle = false;
@@ -760,13 +795,13 @@ module.exports = function(RED) {
760
795
  function onStopPlay(device, phrase) {
761
796
  sendMessage(device.id, 'command', {payload: 'stop'});
762
797
  if (phrase.length > 0 && device.lastState.aliceState != 'SPEAKING') {sendMessage(device.id, 'tts', {payload: phrase, stopListening: true});}
763
- }
798
+ }
764
799
  function onClose() {
765
800
  clearInterval(node.interval);
766
801
  node.deviceList = [];
767
802
  node.removeListener('deviceReady', onDeviceReady)
768
803
  }
769
-
804
+
770
805
  node.on('refreshHttp', function(activeList, readyList) {
771
806
  RED.httpAdmin.get("/yandexdevices_"+node.id, RED.auth.needsPermission('yandex-login.read'), function(req,res) {
772
807
  res.json({"devices": readyList});
@@ -775,8 +810,8 @@ module.exports = function(RED) {
775
810
  res.json({"devices": activeList});
776
811
  });
777
812
  });
778
-
779
- node.on('refreshHttpDNS', function(dnsList) {
813
+
814
+ node.on('refreshHttpDNS', function(dnsList) {
780
815
  RED.httpAdmin.get("/mdns/"+node.id, RED.auth.needsPermission('yandex-login.read'), function(req,res) {
781
816
  res.json({"SearchResult": dnsList});
782
817
  });
@@ -800,7 +835,7 @@ module.exports = function(RED) {
800
835
  res.json({"error": 'no device found'});
801
836
  }
802
837
  });
803
-
838
+
804
839
  // main init
805
840
  if (typeof(node.token) !== 'undefined') {
806
841
  debugMessage(`Starting server with id ${node.id}`)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "node-red-contrib-yandex-station-management",
3
- "version": "0.3.3",
3
+ "version": "0.3.6",
4
4
  "description": "Local management of YandexStation using API on websockets",
5
5
  "main": "index.js",
6
6
  "scripts": {