node-red-contrib-yandex-station-management 0.3.2 → 0.3.5
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/README.md +8 -2
- package/lib/stationHelper.js +52 -0
- package/nodes/get.js +8 -34
- package/nodes/in.js +3 -37
- package/nodes/local-out.html +10 -0
- package/nodes/local-out.js +7 -0
- package/nodes/locales/en-US/local-out.html +2 -1
- package/nodes/locales/en-US/local-out.json +1 -0
- package/nodes/locales/ru-RU/local-out.html +1 -0
- package/nodes/locales/ru-RU/local-out.json +1 -0
- package/nodes/yandex-login.js +164 -123
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
- Яндекс Станция(протестировано)
|
|
4
4
|
- Яндекс Станция мини(протестировано)
|
|
5
5
|
- Яндекс Станция мини 2 с экраном(протестировано)
|
|
6
|
+
- Яндекс Станция лайт(протестировано)
|
|
6
7
|
- Яндекс Станци Макс(протестировано)
|
|
7
8
|
- Яндекс Модуль(не протестировано)
|
|
8
9
|
- Яндекс Модуль - 2 (в процессе тестирования)
|
|
@@ -40,7 +41,7 @@
|
|
|
40
41
|
|
|
41
42
|
После деплоя в настройках ноды в поле Station должны появиться станции доступные для управления.
|
|
42
43
|
|
|
43
|
-
|
|
44
|
+
Если станция не появилась в списке, то можно подождать пару минут или перезапустить Node-Red.
|
|
44
45
|
|
|
45
46
|
## Описание возможностей и сценариев использования.
|
|
46
47
|
### Нода Station
|
|
@@ -125,6 +126,7 @@ Phrase to say - фраза, которую скажет Алиса вместо
|
|
|
125
126
|
-
|
|
126
127
|
Есть ряд опций:
|
|
127
128
|
- Volume. Позволяет произносить фразу заданной громкостью. Если не выбрано, то фраза произносится с текущим уровнем громкости. После произнесения уровень громкости вернется в изначальный. Может быть переопределено через msg.volume
|
|
129
|
+
- Whisper. Позволяет произнести фразу шептом.. Переопределяется через msg.whisper
|
|
128
130
|
- Prevent listening. Если выбрано, то колонка после воспроизведения не "слушает", что ей ответят. Может быть переопределено через msg.prevent_listening
|
|
129
131
|
- Pause while TTS. Ставит воспроизведение плеера на паузу на время речи. Воспроизведение будет продолжено, только если что-то играло на момент поступления команды. Может быть переопределено через msg.pause_music
|
|
130
132
|
Все опции комбинируемы между собой.
|
|
@@ -235,6 +237,7 @@ Phrase to say - фраза, которую скажет Алиса вместо
|
|
|
235
237
|
}
|
|
236
238
|
```
|
|
237
239
|
10. Отправить "Текст" для TTS.
|
|
240
|
+
Больше не работает!
|
|
238
241
|
```json
|
|
239
242
|
{
|
|
240
243
|
"command" : "sendText",
|
|
@@ -303,7 +306,10 @@ Phrase to say - фраза, которую скажет Алиса вместо
|
|
|
303
306
|
```json
|
|
304
307
|
"value": "<speaker audio='alice-sounds-game-win-1.opus'>У вас получилось!"
|
|
305
308
|
```
|
|
306
|
-
|
|
309
|
+
- Говорить шепотом
|
|
310
|
+
```json
|
|
311
|
+
"value": "<speaker is_whisper="true"'>Я говорю тихо-тихо!"
|
|
312
|
+
```
|
|
307
313
|
- Совмещение эффектов
|
|
308
314
|
```json
|
|
309
315
|
"value": "<speaker voice='kostya' audio='alice-sounds-game-win-1.opus' effect='megaphone'>добро пожаловать"
|
|
@@ -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
|
-
|
|
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(
|
|
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) {
|
package/nodes/local-out.html
CHANGED
|
@@ -36,6 +36,9 @@
|
|
|
36
36
|
value: false,
|
|
37
37
|
},
|
|
38
38
|
noTrack: {},
|
|
39
|
+
whisper: {
|
|
40
|
+
value: false,
|
|
41
|
+
},
|
|
39
42
|
ttsVoice: {
|
|
40
43
|
value: null,
|
|
41
44
|
},
|
|
@@ -247,6 +250,13 @@
|
|
|
247
250
|
<input type="range" id="node-input-volume" name="volume" min="0" max="100" step="1" style="display: inline-block; width: 150px; margin-left: 10px; vertical-align: middle;">
|
|
248
251
|
<div id="range-label" class='online'><span id="volume-level" class="online"></span><span class="online">%</span></div>
|
|
249
252
|
</div>
|
|
253
|
+
<div class="form-row command_options command_options-tts">
|
|
254
|
+
<label for="node-input-whisper" class="label label-long">
|
|
255
|
+
<i class="fa fa-deaf"></i> <span data-i18n="label.whisper"></span>
|
|
256
|
+
<div class="red-ui-debug-msg-type-string" style="font-size: 10px;">msg.whisper</div></label>
|
|
257
|
+
</label>
|
|
258
|
+
<input type="checkbox" id="node-input-whisper" style="display: inline-block; width: auto; vertical-align: top;">
|
|
259
|
+
</div>
|
|
250
260
|
<div class="form-row command_options command_options-tts">
|
|
251
261
|
<label for="node-input-stopListening" class="label label-long">
|
|
252
262
|
<i class="fa fa-deaf"></i> <span data-i18n="label.prevent_listening"></span>
|
package/nodes/local-out.js
CHANGED
|
@@ -15,6 +15,7 @@ module.exports = function(RED) {
|
|
|
15
15
|
node.pauseMusic = config.pauseMusic;
|
|
16
16
|
node.ttsVoice = config.ttsVoice;
|
|
17
17
|
node.ttsEffect = config.ttsEffect;
|
|
18
|
+
node.whisper = config.whisper;
|
|
18
19
|
node.status({});
|
|
19
20
|
|
|
20
21
|
function debugMessage(text){
|
|
@@ -32,6 +33,7 @@ module.exports = function(RED) {
|
|
|
32
33
|
|
|
33
34
|
//apply node's config
|
|
34
35
|
if (node.volumeFlag) {data.volume = node.volume/100}
|
|
36
|
+
if (node.whisper) {data.whisper = node.whisper}
|
|
35
37
|
if (node.stopListening) {data.stopListening = node.stopListening}
|
|
36
38
|
if (node.noTrackPhrase) {data.noTrackPhrase = node.noTrackPhrase}
|
|
37
39
|
if (node.pauseMusic) {data.pauseMusic = node.pauseMusic}
|
|
@@ -39,6 +41,7 @@ module.exports = function(RED) {
|
|
|
39
41
|
|
|
40
42
|
//redefine options from input
|
|
41
43
|
if ("volume" in input) {data.volume = input.volume/100}
|
|
44
|
+
if ("whisper" in input) {data.whisper = input.whisper?true:false}
|
|
42
45
|
if ("voice" in input) {node.ttsVoice = input.voice}
|
|
43
46
|
if ("effect" in input) {node.ttsEffect = input.effect}
|
|
44
47
|
if ("prevent_listening" in input) {node.noTrackPhrase = input.prevent_listening}
|
|
@@ -100,6 +103,10 @@ module.exports = function(RED) {
|
|
|
100
103
|
data.payload = "<speaker effect='" + effectsArr[ind] + "'>" + data.payload;
|
|
101
104
|
}
|
|
102
105
|
}
|
|
106
|
+
|
|
107
|
+
if (data.whisper) {
|
|
108
|
+
data.payload = "<speaker is_whisper='"+data.whisper+"'>" + data.payload;
|
|
109
|
+
}
|
|
103
110
|
} else {
|
|
104
111
|
data.payload = ""
|
|
105
112
|
}
|
|
@@ -6,9 +6,10 @@
|
|
|
6
6
|
<p>Воспросизведение голосом отправленных фраз - Text to Speech. Не имеет ограничения по символам.</p>
|
|
7
7
|
<dl class="message-properties">
|
|
8
8
|
<dt>Текст</dt><dd>Откуда брать текст: msg.payload, flow, global или Json - выбрать сообщение случайным образом из массива вида <code>["один", "два", "три"]</code>.</dd>
|
|
9
|
-
<dt class="optional"
|
|
9
|
+
<dt class="optional">Whisper</dt><dd>Ответить шёпотом.</dd>
|
|
10
10
|
<dt class="optional">Эффект</dt><dd>Наложить эффект на голос.</dd>
|
|
11
11
|
<dt class="optional">Громкость</dt><dd>Позволяет произносить фразу заданной громкостью. Если не выбрано, то фраза произносится с текущим уровнем громкости. После произнесения, уровень громкости вернется в изначальный.</dd>
|
|
12
|
+
<dt class="optional">Voice</dt><dd>Say a phrase in a whisper.</dd>
|
|
12
13
|
<dt class="optional">Не ждать ответ</dt><dd>Если выбрано, то колонка, после воспроизведения, не "слушает", что ей ответят.</dd>
|
|
13
14
|
<dt class="optional">Плеер на паузу</dt><dd>Ставит воспроизведение плеера на паузу на время речи. Воспроизведение будет продолжено, только если что-то играло на момент поступления команды.</dd>
|
|
14
15
|
</dl>
|
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
<dt class="optional">Голос</dt><dd>Изменить голос.</dd>
|
|
9
9
|
<dt class="optional">Эффект</dt><dd>Наложить эффект на голос.</dd>
|
|
10
10
|
<dt class="optional">Громкость</dt><dd>Позволяет произносить фразу заданной громкостью. Если не выбрано, то фраза произносится с текущим уровнем громкости. После произнесения, уровень громкости вернется в изначальный.</dd>
|
|
11
|
+
<dt class="optional">Шёпот</dt><dd>Ответить шёпотом.</dd>
|
|
11
12
|
<dt class="optional">Не ждать ответ</dt><dd>Если выбрано, то колонка, после воспроизведения, не "слушает", что ей ответят.</dd>
|
|
12
13
|
<dt class="optional">Плеер на паузу</dt><dd>Ставит воспроизведение плеера на паузу на время речи. Воспроизведение будет продолжено, только если что-то играло на момент поступления команды.</dd>
|
|
13
14
|
</dl>
|
package/nodes/yandex-login.js
CHANGED
|
@@ -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
|
-
|
|
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,21 +96,25 @@ 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
|
});
|
|
98
103
|
//node.emit('refreshHttp', node.activeStationList, node.readyList)
|
|
99
104
|
deviceListProcessing(node.deviceList)
|
|
105
|
+
try {
|
|
106
|
+
discoverDevices(node.deviceList)
|
|
107
|
+
.then(() => {
|
|
108
|
+
//debugMessage(`calling processing for ${node.deviceList.length} devices`);
|
|
109
|
+
deviceListProcessing(node.deviceList)
|
|
110
|
+
|
|
111
|
+
});
|
|
112
|
+
//debugMessage(node.id);
|
|
113
|
+
return node.deviceList;
|
|
114
|
+
} catch (error) {
|
|
115
|
+
debugMessage(`Error while searching: ${error}`);
|
|
116
|
+
}
|
|
100
117
|
|
|
101
|
-
discoverDevices(node.deviceList)
|
|
102
|
-
.then(() => {
|
|
103
|
-
//debugMessage(`calling processing for ${node.deviceList.length} devices`);
|
|
104
|
-
deviceListProcessing(node.deviceList)
|
|
105
|
-
|
|
106
|
-
});
|
|
107
|
-
//debugMessage(node.id);
|
|
108
|
-
return node.deviceList;
|
|
109
118
|
})
|
|
110
119
|
.catch(function (err) {
|
|
111
120
|
//node.emit('refreshHttp', node.readyList);
|
|
@@ -122,7 +131,6 @@ module.exports = function(RED) {
|
|
|
122
131
|
await mDnsSd.discover({
|
|
123
132
|
name: '_yandexio._tcp.local'
|
|
124
133
|
}).then((result) => {
|
|
125
|
-
debugMessage(`MDNS. Found ${result.length} devices`);
|
|
126
134
|
node.emit('refreshHttpDNS', result);
|
|
127
135
|
if (result.length != 0){
|
|
128
136
|
for (const device of deviceList) {
|
|
@@ -143,15 +151,15 @@ module.exports = function(RED) {
|
|
|
143
151
|
} catch(e) {
|
|
144
152
|
debugMessage(`Error searching hostname in mDNS answer`)
|
|
145
153
|
}
|
|
146
|
-
|
|
154
|
+
|
|
147
155
|
}
|
|
148
156
|
}
|
|
149
|
-
}
|
|
157
|
+
}
|
|
150
158
|
})
|
|
151
|
-
|
|
159
|
+
|
|
152
160
|
}
|
|
153
161
|
}
|
|
154
|
-
|
|
162
|
+
|
|
155
163
|
}).catch(function (err) {
|
|
156
164
|
debugMessage(err);
|
|
157
165
|
});
|
|
@@ -168,15 +176,15 @@ module.exports = function(RED) {
|
|
|
168
176
|
|
|
169
177
|
async function getLocalToken(device) {
|
|
170
178
|
let data;
|
|
171
|
-
let options = {
|
|
179
|
+
let options = {
|
|
172
180
|
method: 'GET',
|
|
173
181
|
url: 'https://quasar.yandex.net/glagol/token',
|
|
174
182
|
qs: { device_id: device.id, platform: device.platform },
|
|
175
|
-
headers:
|
|
176
|
-
{
|
|
183
|
+
headers:
|
|
184
|
+
{
|
|
177
185
|
'Authorization': 'Oauth ' + node.token,
|
|
178
|
-
'Content-Type': 'application/json'
|
|
179
|
-
}
|
|
186
|
+
'Content-Type': 'application/json'
|
|
187
|
+
}
|
|
180
188
|
};
|
|
181
189
|
// debugMessage(JSON.stringify(options))
|
|
182
190
|
statusUpdate({"color": "yellow", "text": "connecting..."}, device);
|
|
@@ -184,7 +192,8 @@ module.exports = function(RED) {
|
|
|
184
192
|
.then(function(response)
|
|
185
193
|
{
|
|
186
194
|
data = JSON.parse(response);
|
|
187
|
-
device.token = data.token
|
|
195
|
+
device.token = data.token;
|
|
196
|
+
debugMessage(`${device.id}: Recieved conversation new token`)
|
|
188
197
|
})
|
|
189
198
|
.catch(function (err) {
|
|
190
199
|
removeDevice(node.readyList, device);
|
|
@@ -204,12 +213,12 @@ module.exports = function(RED) {
|
|
|
204
213
|
connect(device)
|
|
205
214
|
};
|
|
206
215
|
|
|
207
|
-
|
|
216
|
+
|
|
208
217
|
function connect(device) {
|
|
209
218
|
//connect only if !device.ws
|
|
210
219
|
//debugMessage(`device.ws = ${JSON.stringify(device.ws)}`);
|
|
211
220
|
if ( (device.connection == true || typeof(device.connection) == "undefined") && node.listenerCount(`statusUpdate_${device.id}`) > 0 ) {
|
|
212
|
-
debugMessage(`Connecting to device ${device.id}. ws is ${
|
|
221
|
+
debugMessage(`Connecting to device ${device.id}. ws is ${device.ws}. Listeners: ` + node.listenerCount(`statusUpdate_${device.id}`));
|
|
213
222
|
if (!device.ws) {
|
|
214
223
|
debugMessage('recieving conversation token...');
|
|
215
224
|
getLocalToken(device)
|
|
@@ -222,7 +231,7 @@ module.exports = function(RED) {
|
|
|
222
231
|
})
|
|
223
232
|
.catch(function (err) {
|
|
224
233
|
debugMessage('Error while getting token: ' + err);
|
|
225
|
-
|
|
234
|
+
|
|
226
235
|
});
|
|
227
236
|
} else {
|
|
228
237
|
if (device.ws.readyState == 3) {
|
|
@@ -254,16 +263,16 @@ module.exports = function(RED) {
|
|
|
254
263
|
//}
|
|
255
264
|
}
|
|
256
265
|
} else {
|
|
257
|
-
debugMessage(`${device.id} connection is disabled by settings in manager node ${device.manager} or you have not use any node for this station`)
|
|
258
|
-
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);
|
|
259
268
|
device.timer = setTimeout(connect, 60000, device);
|
|
260
269
|
|
|
261
270
|
}
|
|
262
271
|
|
|
263
272
|
}
|
|
264
|
-
|
|
273
|
+
|
|
265
274
|
async function makeConn(device) {
|
|
266
|
-
|
|
275
|
+
|
|
267
276
|
let options = {
|
|
268
277
|
key: device.glagol.security.server_private_key,
|
|
269
278
|
cert: device.glagol.security.server_certificate,
|
|
@@ -272,7 +281,9 @@ module.exports = function(RED) {
|
|
|
272
281
|
device.lastState = {};
|
|
273
282
|
debugMessage(`Connecting to wss://${device.address}:${device.port}`);
|
|
274
283
|
device.ws = new WebSocket(`wss://${device.address}:${device.port}`, options);
|
|
275
|
-
device.
|
|
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) {
|
|
276
287
|
debugMessage(`Connected to ${device.address}, data: ${data}`);
|
|
277
288
|
sendMessage(device.id, 'command', {payload: 'ping'});
|
|
278
289
|
statusUpdate({"color": "green", "text": "connected"}, device);
|
|
@@ -282,19 +293,22 @@ module.exports = function(RED) {
|
|
|
282
293
|
device.waitForIdle = false;
|
|
283
294
|
device.watchDog = setTimeout(() => device.ws.close(), 10000);
|
|
284
295
|
device.pingInterval = setInterval(onPing,300,device);
|
|
296
|
+
debugMessage(`${device.id}: Kill connection watchdog`);
|
|
297
|
+
clearTimeout(device.watchDogConn);
|
|
285
298
|
clearTimeout(device.timer);
|
|
286
299
|
debugMessage(`readyState: ${device.ws.readyState}`)
|
|
287
300
|
});
|
|
288
301
|
device.ws.on('message', function incoming(data) {
|
|
289
302
|
//debugMessage(`${device.id}: ${JSON.stringify(data)}`);
|
|
290
303
|
let dataRecieved = JSON.parse(data);
|
|
291
|
-
device.lastState = dataRecieved.state;
|
|
304
|
+
device.lastState = dataRecieved.state;
|
|
292
305
|
device.fullMessage = JSON.stringify(dataRecieved);
|
|
293
306
|
//debugMessage(checkSheduler(device, JSON.parse(data).sentTime));
|
|
294
307
|
node.emit(`message_${device.id}`, device.lastState);
|
|
295
308
|
if (device.lastState.aliceState == 'LISTENING' && device.waitForListening) {node.emit(`stopListening`, device)}
|
|
296
309
|
if (device.lastState.aliceState == 'LISTENING' && device.playAfterTTS) {node.emit('startPlay', device)}
|
|
297
310
|
if (device.lastState.aliceState == 'LISTENING' && device.waitForIdle) {node.emit('setVolume', device)}
|
|
311
|
+
//if (device.lastState.aliceState != 'SPEAKING' && device.ttsBuffer.length > 0) {node.emit('nextTts', device)}
|
|
298
312
|
// if (device.parameters.hasOwnProperty(sheduler)) {
|
|
299
313
|
// let resultSheduler = checkSheduler(device, dataRecieved.sentTime)
|
|
300
314
|
// device.canPlay = resultSheduler[0]
|
|
@@ -307,7 +321,7 @@ module.exports = function(RED) {
|
|
|
307
321
|
if (device.lastState.playing && device.lastState.aliceState != 'LISTENING' && device.parameters.hasOwnProperty("sheduler")) {
|
|
308
322
|
let res = checkSheduler(device, dataRecieved.sentTime)
|
|
309
323
|
//debugMessage(`Result of cheking sheduler is ${res.toString}`);
|
|
310
|
-
if (!res[0]) {
|
|
324
|
+
if (!res[0]) {
|
|
311
325
|
if (device.shedulerFlag || device.shedulerFlag == undefined) {
|
|
312
326
|
node.emit('stopPlay', device, res[1])
|
|
313
327
|
device.shedulerFlag = false
|
|
@@ -319,7 +333,7 @@ module.exports = function(RED) {
|
|
|
319
333
|
clearTimeout(device.watchDog);
|
|
320
334
|
//debugMessage(`cleared timeout for ${device.id}`)
|
|
321
335
|
device.watchDog = setTimeout(() => {device.ws.close()}, 10000);
|
|
322
|
-
});
|
|
336
|
+
});
|
|
323
337
|
//device.ws.on('ping', function);
|
|
324
338
|
device.ws.on('close', function close(code, reason){
|
|
325
339
|
statusUpdate({"color": "red", "text": "disconnected"}, device);
|
|
@@ -331,15 +345,15 @@ module.exports = function(RED) {
|
|
|
331
345
|
debugMessage(`getting new token...`);
|
|
332
346
|
connect(device);
|
|
333
347
|
break;
|
|
334
|
-
case 1000:
|
|
348
|
+
case 1000:
|
|
335
349
|
debugMessage(`Closed connection code ${code} with reason ${reason}. Reconnecting...` );
|
|
336
350
|
connect(device);
|
|
337
|
-
break;
|
|
351
|
+
break;
|
|
338
352
|
case 1006:
|
|
339
353
|
debugMessage(`Lost server, reconnect in 60 seconds...${code} + ${reason}` );
|
|
340
354
|
device.timer = setTimeout(connect, 60000, device);
|
|
341
355
|
break;
|
|
342
|
-
|
|
356
|
+
|
|
343
357
|
case 10000:
|
|
344
358
|
debugMessage(`Reconnect device reason 10000 ${device.id}`);
|
|
345
359
|
connect(device);
|
|
@@ -351,15 +365,13 @@ module.exports = function(RED) {
|
|
|
351
365
|
}
|
|
352
366
|
|
|
353
367
|
|
|
354
|
-
})
|
|
368
|
+
})
|
|
355
369
|
device.ws.on('error', function error(data){
|
|
356
370
|
//statusUpdate({"color": "red", "text": "disconnected"}, device);
|
|
357
371
|
debugMessage(`error: ${data}`);
|
|
358
|
-
device.ws
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
// setTimeout(connect, 60000, device);
|
|
362
|
-
// }
|
|
372
|
+
if (typeof(device) !== 'undefined' && typeof(device.ws) !== 'undefined' ) {
|
|
373
|
+
device.ws.terminate();
|
|
374
|
+
}
|
|
363
375
|
});
|
|
364
376
|
};
|
|
365
377
|
|
|
@@ -412,7 +424,7 @@ module.exports = function(RED) {
|
|
|
412
424
|
return [{
|
|
413
425
|
"command": "rewind",
|
|
414
426
|
"position": 0
|
|
415
|
-
}]
|
|
427
|
+
}]
|
|
416
428
|
}
|
|
417
429
|
} else if (message.payload == 'volumeup') {
|
|
418
430
|
debugMessage(currentVolume);
|
|
@@ -420,7 +432,7 @@ module.exports = function(RED) {
|
|
|
420
432
|
return [{
|
|
421
433
|
"command": "setVolume",
|
|
422
434
|
"volume": currentVolume + 0.1
|
|
423
|
-
}]
|
|
435
|
+
}]
|
|
424
436
|
}
|
|
425
437
|
} else if (message.payload == 'volumedown') {
|
|
426
438
|
debugMessage(currentVolume);
|
|
@@ -428,13 +440,13 @@ module.exports = function(RED) {
|
|
|
428
440
|
return [{
|
|
429
441
|
"command": "setVolume",
|
|
430
442
|
"volume": currentVolume - 0.1
|
|
431
|
-
}]
|
|
443
|
+
}]
|
|
432
444
|
}
|
|
433
445
|
} else if (message.payload == 'volume') {
|
|
434
446
|
return [{
|
|
435
447
|
"command": "setVolume",
|
|
436
448
|
"volume": parseFloat(message.level)
|
|
437
|
-
}]
|
|
449
|
+
}]
|
|
438
450
|
}
|
|
439
451
|
|
|
440
452
|
} else {
|
|
@@ -442,7 +454,7 @@ module.exports = function(RED) {
|
|
|
442
454
|
//node.error(`You can send commands in msg.payload from list as String ${commands + extraCommands}`);
|
|
443
455
|
return [{"command": "ping"}];
|
|
444
456
|
}
|
|
445
|
-
case 'voice':
|
|
457
|
+
case 'voice':
|
|
446
458
|
debugMessage(`Message Voice command: ${message}`);
|
|
447
459
|
return [{
|
|
448
460
|
"command" : "sendText",
|
|
@@ -510,55 +522,84 @@ module.exports = function(RED) {
|
|
|
510
522
|
return result;
|
|
511
523
|
break;
|
|
512
524
|
case 'homekit':
|
|
513
|
-
debugMessage('HAP: ' + JSON.stringify(message) + ' PL: ' + JSON.stringify(message.payload) );
|
|
525
|
+
debugMessage('HAP: ' + JSON.stringify(message) + ' PL: ' + JSON.stringify(message.payload) );
|
|
514
526
|
if ("session" in message.hap) {
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
} else {
|
|
528
|
-
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;
|
|
529
539
|
}
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
return messageConstructor('command', {'payload': '
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
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' })
|
|
542
578
|
} else {
|
|
543
|
-
|
|
579
|
+
if (id) {
|
|
580
|
+
return messageConstructor('command', { 'payload': 'play' })
|
|
581
|
+
} else if (!id && noTrackPhrase) {
|
|
582
|
+
return messageConstructor('voice', { 'payload': noTrackPhrase })
|
|
583
|
+
}
|
|
544
584
|
}
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
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)
|
|
553
592
|
}
|
|
554
|
-
|
|
593
|
+
|
|
594
|
+
debugMessage('unknown command')
|
|
595
|
+
return messageConstructor('command', { 'payload': 'ping' })
|
|
555
596
|
} else {
|
|
556
|
-
return messageConstructor('command', {'payload': 'ping'})
|
|
597
|
+
return messageConstructor('command', { 'payload': 'ping' })
|
|
557
598
|
}
|
|
558
|
-
case 'raw':
|
|
599
|
+
case 'raw':
|
|
559
600
|
if (Array.isArray(message.payload)) { return message.payload }
|
|
560
601
|
return [message.payload];
|
|
561
|
-
case 'stopListening':
|
|
602
|
+
case 'stopListening':
|
|
562
603
|
return [{
|
|
563
604
|
"command": "serverAction",
|
|
564
605
|
"serverActionEventPayload": {
|
|
@@ -570,7 +611,7 @@ module.exports = function(RED) {
|
|
|
570
611
|
|
|
571
612
|
}
|
|
572
613
|
function sendMessage(deviceId, messageType, message) {
|
|
573
|
-
|
|
614
|
+
|
|
574
615
|
try {
|
|
575
616
|
let device = searchDeviceByID(deviceId);
|
|
576
617
|
//debugMessage(`deviceId: ${searchDeviceByID(deviceId)}`);
|
|
@@ -611,19 +652,19 @@ module.exports = function(RED) {
|
|
|
611
652
|
//debugMessage(`timeCur: ${timeCurrent} timeMin: ${timeMin} timeMax: ${timeMax}`);
|
|
612
653
|
return [false, daySheduler.phrase];
|
|
613
654
|
}
|
|
614
|
-
|
|
655
|
+
|
|
615
656
|
|
|
616
657
|
}
|
|
617
|
-
|
|
658
|
+
|
|
618
659
|
function searchDeviceByID(id) {
|
|
619
660
|
if (node.deviceList) {
|
|
620
661
|
return node.deviceList.find(device => device.id == id)
|
|
621
|
-
}
|
|
662
|
+
}
|
|
622
663
|
}
|
|
623
664
|
function onPing(device) {
|
|
624
665
|
if (device) {sendMessage(device.id, 'command', {payload: 'ping'});}
|
|
625
666
|
}
|
|
626
|
-
|
|
667
|
+
|
|
627
668
|
function onPing(device) {
|
|
628
669
|
sendMessage(device.id, 'command', {payload: 'ping'});
|
|
629
670
|
}
|
|
@@ -632,19 +673,19 @@ module.exports = function(RED) {
|
|
|
632
673
|
if (device) {
|
|
633
674
|
if (device.ws) {
|
|
634
675
|
switch(device.ws.readyState){
|
|
635
|
-
case 0:
|
|
676
|
+
case 0:
|
|
636
677
|
return {"color": "yellow", "text": "connecting..."}
|
|
637
|
-
case 1:
|
|
678
|
+
case 1:
|
|
638
679
|
return {"color": "green", "text": "connected"}
|
|
639
|
-
case 2:
|
|
680
|
+
case 2:
|
|
640
681
|
return {"color": "red", "text": "disconnecting"}
|
|
641
|
-
case 3:
|
|
682
|
+
case 3:
|
|
642
683
|
return {"color": "red", "text": "disconnected"}
|
|
643
684
|
default:
|
|
644
685
|
return {"color": "red", "text": "disconnected"}
|
|
645
686
|
}
|
|
646
|
-
|
|
647
|
-
}
|
|
687
|
+
|
|
688
|
+
}
|
|
648
689
|
} else {
|
|
649
690
|
return {"color": "red", "text": "disconnected"}
|
|
650
691
|
}
|
|
@@ -652,7 +693,7 @@ module.exports = function(RED) {
|
|
|
652
693
|
}
|
|
653
694
|
|
|
654
695
|
|
|
655
|
-
|
|
696
|
+
|
|
656
697
|
function registerDevice(deviceId, nodeId, parameters) {
|
|
657
698
|
let device = searchDeviceByID(deviceId);
|
|
658
699
|
debugMessage(`Recieved parameters ${JSON.stringify(parameters)} for station id ${deviceId}`);
|
|
@@ -664,7 +705,7 @@ module.exports = function(RED) {
|
|
|
664
705
|
debugMessage(`Device ${device.id} already registered with manager id ${device.manager}. Updating parameters and restart...`);
|
|
665
706
|
reconnect(device);
|
|
666
707
|
return 1;
|
|
667
|
-
|
|
708
|
+
|
|
668
709
|
}
|
|
669
710
|
//новый и первый запрос на регистрацию для устройства
|
|
670
711
|
if (typeof(device.manager) == 'undefined') {
|
|
@@ -693,7 +734,7 @@ module.exports = function(RED) {
|
|
|
693
734
|
registrationBuffer.splice(registrationBuffer.indexOf(currentBuffer), 1)
|
|
694
735
|
debugMessage(`Element from registration buffer was deleted. Current buffer size is ${registrationBuffer.length}`)
|
|
695
736
|
}
|
|
696
|
-
reconnect(device);
|
|
737
|
+
reconnect(device);
|
|
697
738
|
return 0;
|
|
698
739
|
}
|
|
699
740
|
//новый запрос на регистрацию при наличии уже зарегистрированной ноды
|
|
@@ -711,9 +752,9 @@ module.exports = function(RED) {
|
|
|
711
752
|
registrationBuffer.push({"id": deviceId, "manager": nodeId, "parameters": parameters});
|
|
712
753
|
debugMessage(`New element in registration buffer. Current buffer size is ${registrationBuffer.length}`)
|
|
713
754
|
}
|
|
714
|
-
|
|
755
|
+
|
|
715
756
|
}
|
|
716
|
-
|
|
757
|
+
|
|
717
758
|
|
|
718
759
|
}
|
|
719
760
|
function unregisterDevice(deviceId, nodeId){
|
|
@@ -724,7 +765,7 @@ module.exports = function(RED) {
|
|
|
724
765
|
device.parameters = {};
|
|
725
766
|
debugMessage(`For device ${deviceId} was succesfully unregistred managment node whith id ${device.manager}`);
|
|
726
767
|
debugMessage(`device is: ${device}`);
|
|
727
|
-
return 0;
|
|
768
|
+
return 0;
|
|
728
769
|
} else {
|
|
729
770
|
return 2;
|
|
730
771
|
}
|
|
@@ -745,7 +786,7 @@ module.exports = function(RED) {
|
|
|
745
786
|
if (device.savedVolumeLevel) { sendMessage(device.id, 'raw',{payload: {
|
|
746
787
|
"command": "setVolume",
|
|
747
788
|
"volume": parseFloat(device.savedVolumeLevel)
|
|
748
|
-
}
|
|
789
|
+
}
|
|
749
790
|
});
|
|
750
791
|
}
|
|
751
792
|
device.waitForIdle = false;
|
|
@@ -754,13 +795,13 @@ module.exports = function(RED) {
|
|
|
754
795
|
function onStopPlay(device, phrase) {
|
|
755
796
|
sendMessage(device.id, 'command', {payload: 'stop'});
|
|
756
797
|
if (phrase.length > 0 && device.lastState.aliceState != 'SPEAKING') {sendMessage(device.id, 'tts', {payload: phrase, stopListening: true});}
|
|
757
|
-
}
|
|
798
|
+
}
|
|
758
799
|
function onClose() {
|
|
759
800
|
clearInterval(node.interval);
|
|
760
801
|
node.deviceList = [];
|
|
761
802
|
node.removeListener('deviceReady', onDeviceReady)
|
|
762
803
|
}
|
|
763
|
-
|
|
804
|
+
|
|
764
805
|
node.on('refreshHttp', function(activeList, readyList) {
|
|
765
806
|
RED.httpAdmin.get("/yandexdevices_"+node.id, RED.auth.needsPermission('yandex-login.read'), function(req,res) {
|
|
766
807
|
res.json({"devices": readyList});
|
|
@@ -769,8 +810,8 @@ module.exports = function(RED) {
|
|
|
769
810
|
res.json({"devices": activeList});
|
|
770
811
|
});
|
|
771
812
|
});
|
|
772
|
-
|
|
773
|
-
node.on('refreshHttpDNS', function(dnsList) {
|
|
813
|
+
|
|
814
|
+
node.on('refreshHttpDNS', function(dnsList) {
|
|
774
815
|
RED.httpAdmin.get("/mdns/"+node.id, RED.auth.needsPermission('yandex-login.read'), function(req,res) {
|
|
775
816
|
res.json({"SearchResult": dnsList});
|
|
776
817
|
});
|
|
@@ -794,7 +835,7 @@ module.exports = function(RED) {
|
|
|
794
835
|
res.json({"error": 'no device found'});
|
|
795
836
|
}
|
|
796
837
|
});
|
|
797
|
-
|
|
838
|
+
|
|
798
839
|
// main init
|
|
799
840
|
if (typeof(node.token) !== 'undefined') {
|
|
800
841
|
debugMessage(`Starting server with id ${node.id}`)
|