node-red-contrib-yandex-station-management 0.3.0 → 0.3.4
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 +7 -1
- package/lib/stationHelper.js +52 -0
- package/nodes/get.js +8 -29
- package/nodes/in.js +3 -32
- package/nodes/local-out.html +10 -0
- package/nodes/local-out.js +8 -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 +166 -120
- 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 (в процессе тестирования)
|
|
@@ -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,38 +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
|
-
if (node.homekitFormat == 'speaker') {
|
|
25
|
-
let ConfiguredName = `${(message.playerState.subtitle) ? message.playerState.subtitle : 'No Artist'} - ${(message.playerState.title) ? message.playerState.title : 'No Track Name'}`;
|
|
26
|
-
let title = `${message.playerState.title}`;
|
|
27
|
-
if (ConfiguredName.length > 64 && title.length > 0 && title.length <= 64) {
|
|
28
|
-
ConfiguredName = title;
|
|
29
|
-
} else {
|
|
30
|
-
ConfiguredName = title.substr(0, 61) + `...`;
|
|
31
|
-
}
|
|
32
|
-
(message.playerState)? inputMsg.payload = {
|
|
33
|
-
"CurrentMediaState": (message.playing) ? 0 : 1,
|
|
34
|
-
"ConfiguredName": ConfiguredName
|
|
35
|
-
} :inputMsg.payload = {
|
|
36
|
-
"CurrentMediaState": (message.playing) ? 0 : 1,
|
|
37
|
-
"ConfiguredName": `No Artist - No Track Name`
|
|
38
|
-
}
|
|
39
|
-
}else if (node.homekitFormat == 'tv') {
|
|
40
|
-
inputMsg.payload = {
|
|
41
|
-
"Active": (message.playing) ? 1 : 0
|
|
42
|
-
}
|
|
43
21
|
|
|
44
|
-
|
|
22
|
+
function _preparePayload(message, inputMsg) {
|
|
23
|
+
let prepare = stationHelper.preparePayload(node, message);
|
|
24
|
+
if (typeof(prepare.payload) !== 'undefined') {
|
|
25
|
+
inputMsg.payload = prepare.payload;
|
|
45
26
|
}
|
|
46
|
-
|
|
47
|
-
|
|
27
|
+
return inputMsg;
|
|
48
28
|
}
|
|
49
29
|
|
|
50
|
-
|
|
51
30
|
node.onStatus = function(data) {
|
|
52
31
|
if (data) {
|
|
53
32
|
node.status({fill: `${data.color}`,shape:"dot",text: `${data.text}`});
|
|
@@ -56,7 +35,7 @@ module.exports = function(RED) {
|
|
|
56
35
|
}
|
|
57
36
|
node.onInput = function(msg, send, done){
|
|
58
37
|
debugMessage('current state: ' + JSON.stringify(node.lastState));
|
|
59
|
-
( 'aliceState' in node.lastState )?node.send(
|
|
38
|
+
( 'aliceState' in node.lastState )?node.send(_preparePayload(node.lastState,msg)):node.send(msg)
|
|
60
39
|
}
|
|
61
40
|
node.onMessage = function(message){
|
|
62
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,37 +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
|
-
if (node.homekitFormat == 'speaker') {
|
|
30
|
-
let ConfiguredName = `${(message.playerState.subtitle) ? message.playerState.subtitle : 'No Artist'} - ${(message.playerState.title) ? message.playerState.title : 'No Track Name'}`;
|
|
31
|
-
let title = `${message.playerState.title}`;
|
|
32
|
-
if (ConfiguredName.length > 64 && title.length > 0 && title.length <= 64) {
|
|
33
|
-
ConfiguredName = title;
|
|
34
|
-
} else {
|
|
35
|
-
ConfiguredName = title.substr(0, 61) + `...`;
|
|
36
|
-
}
|
|
37
|
-
(message.playerState)? payload = {'payload': {
|
|
38
|
-
"CurrentMediaState": (message.playing) ? 0 : 1,
|
|
39
|
-
"ConfiguredName": ConfiguredName
|
|
40
|
-
} }:payload = {'payload': {
|
|
41
|
-
"CurrentMediaState": (message.playing) ? 0 : 1,
|
|
42
|
-
"ConfiguredName": `No Artists - No Track Name`
|
|
43
|
-
} }
|
|
44
|
-
}else if (node.homekitFormat == 'tv') {
|
|
45
|
-
payload = {'payload': {
|
|
46
|
-
"Active": (message.playing) ? 1 : 0
|
|
47
|
-
}
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
}
|
|
51
|
-
return payload;
|
|
52
|
-
|
|
53
|
-
}
|
|
54
25
|
function sendMessage(message){
|
|
55
26
|
//debugMessage(JSON.stringify(message));
|
|
56
27
|
if (node.uniqueFlag && node.output == 'homekit') {
|
|
@@ -66,7 +37,7 @@ module.exports = function(RED) {
|
|
|
66
37
|
}
|
|
67
38
|
node.onMessage = function(data){
|
|
68
39
|
//debugMessage(JSON.stringify(data));
|
|
69
|
-
sendMessage(preparePayload(data));
|
|
40
|
+
sendMessage(stationHelper.preparePayload(node, data));
|
|
70
41
|
}
|
|
71
42
|
node.onStatus = function(data) {
|
|
72
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
|
}
|
|
@@ -110,6 +117,7 @@ module.exports = function(RED) {
|
|
|
110
117
|
}
|
|
111
118
|
} else {
|
|
112
119
|
data.payload = input.payload;
|
|
120
|
+
data.hap = input.hap;
|
|
113
121
|
node.controller.sendMessage(node.station, node.input, data);
|
|
114
122
|
debugMessage(`Sending data: station: ${node.station}, input type: ${node.input}, data: ${JSON.stringify(data)}`);
|
|
115
123
|
}
|
|
@@ -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,17 +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);
|
|
299
|
+
debugMessage(`readyState: ${device.ws.readyState}`)
|
|
286
300
|
});
|
|
287
301
|
device.ws.on('message', function incoming(data) {
|
|
288
302
|
//debugMessage(`${device.id}: ${JSON.stringify(data)}`);
|
|
289
303
|
let dataRecieved = JSON.parse(data);
|
|
290
|
-
device.lastState = dataRecieved.state;
|
|
304
|
+
device.lastState = dataRecieved.state;
|
|
305
|
+
device.fullMessage = JSON.stringify(dataRecieved);
|
|
291
306
|
//debugMessage(checkSheduler(device, JSON.parse(data).sentTime));
|
|
292
307
|
node.emit(`message_${device.id}`, device.lastState);
|
|
293
308
|
if (device.lastState.aliceState == 'LISTENING' && device.waitForListening) {node.emit(`stopListening`, device)}
|
|
294
309
|
if (device.lastState.aliceState == 'LISTENING' && device.playAfterTTS) {node.emit('startPlay', device)}
|
|
295
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)}
|
|
296
312
|
// if (device.parameters.hasOwnProperty(sheduler)) {
|
|
297
313
|
// let resultSheduler = checkSheduler(device, dataRecieved.sentTime)
|
|
298
314
|
// device.canPlay = resultSheduler[0]
|
|
@@ -305,7 +321,7 @@ module.exports = function(RED) {
|
|
|
305
321
|
if (device.lastState.playing && device.lastState.aliceState != 'LISTENING' && device.parameters.hasOwnProperty("sheduler")) {
|
|
306
322
|
let res = checkSheduler(device, dataRecieved.sentTime)
|
|
307
323
|
//debugMessage(`Result of cheking sheduler is ${res.toString}`);
|
|
308
|
-
if (!res[0]) {
|
|
324
|
+
if (!res[0]) {
|
|
309
325
|
if (device.shedulerFlag || device.shedulerFlag == undefined) {
|
|
310
326
|
node.emit('stopPlay', device, res[1])
|
|
311
327
|
device.shedulerFlag = false
|
|
@@ -317,10 +333,11 @@ module.exports = function(RED) {
|
|
|
317
333
|
clearTimeout(device.watchDog);
|
|
318
334
|
//debugMessage(`cleared timeout for ${device.id}`)
|
|
319
335
|
device.watchDog = setTimeout(() => {device.ws.close()}, 10000);
|
|
320
|
-
});
|
|
336
|
+
});
|
|
321
337
|
//device.ws.on('ping', function);
|
|
322
338
|
device.ws.on('close', function close(code, reason){
|
|
323
339
|
statusUpdate({"color": "red", "text": "disconnected"}, device);
|
|
340
|
+
//debugMessage(`readyState: ${device.ws.readyState}`)
|
|
324
341
|
device.lastState = {};
|
|
325
342
|
clearTimeout(device.watchDog);
|
|
326
343
|
switch(code) {
|
|
@@ -328,15 +345,15 @@ module.exports = function(RED) {
|
|
|
328
345
|
debugMessage(`getting new token...`);
|
|
329
346
|
connect(device);
|
|
330
347
|
break;
|
|
331
|
-
case 1000:
|
|
348
|
+
case 1000:
|
|
332
349
|
debugMessage(`Closed connection code ${code} with reason ${reason}. Reconnecting...` );
|
|
333
350
|
connect(device);
|
|
334
|
-
break;
|
|
351
|
+
break;
|
|
335
352
|
case 1006:
|
|
336
353
|
debugMessage(`Lost server, reconnect in 60 seconds...${code} + ${reason}` );
|
|
337
354
|
device.timer = setTimeout(connect, 60000, device);
|
|
338
355
|
break;
|
|
339
|
-
|
|
356
|
+
|
|
340
357
|
case 10000:
|
|
341
358
|
debugMessage(`Reconnect device reason 10000 ${device.id}`);
|
|
342
359
|
connect(device);
|
|
@@ -348,7 +365,7 @@ module.exports = function(RED) {
|
|
|
348
365
|
}
|
|
349
366
|
|
|
350
367
|
|
|
351
|
-
})
|
|
368
|
+
})
|
|
352
369
|
device.ws.on('error', function error(data){
|
|
353
370
|
//statusUpdate({"color": "red", "text": "disconnected"}, device);
|
|
354
371
|
debugMessage(`error: ${data}`);
|
|
@@ -409,7 +426,7 @@ module.exports = function(RED) {
|
|
|
409
426
|
return [{
|
|
410
427
|
"command": "rewind",
|
|
411
428
|
"position": 0
|
|
412
|
-
}]
|
|
429
|
+
}]
|
|
413
430
|
}
|
|
414
431
|
} else if (message.payload == 'volumeup') {
|
|
415
432
|
debugMessage(currentVolume);
|
|
@@ -417,7 +434,7 @@ module.exports = function(RED) {
|
|
|
417
434
|
return [{
|
|
418
435
|
"command": "setVolume",
|
|
419
436
|
"volume": currentVolume + 0.1
|
|
420
|
-
}]
|
|
437
|
+
}]
|
|
421
438
|
}
|
|
422
439
|
} else if (message.payload == 'volumedown') {
|
|
423
440
|
debugMessage(currentVolume);
|
|
@@ -425,13 +442,13 @@ module.exports = function(RED) {
|
|
|
425
442
|
return [{
|
|
426
443
|
"command": "setVolume",
|
|
427
444
|
"volume": currentVolume - 0.1
|
|
428
|
-
}]
|
|
445
|
+
}]
|
|
429
446
|
}
|
|
430
447
|
} else if (message.payload == 'volume') {
|
|
431
448
|
return [{
|
|
432
449
|
"command": "setVolume",
|
|
433
450
|
"volume": parseFloat(message.level)
|
|
434
|
-
}]
|
|
451
|
+
}]
|
|
435
452
|
}
|
|
436
453
|
|
|
437
454
|
} else {
|
|
@@ -439,7 +456,7 @@ module.exports = function(RED) {
|
|
|
439
456
|
//node.error(`You can send commands in msg.payload from list as String ${commands + extraCommands}`);
|
|
440
457
|
return [{"command": "ping"}];
|
|
441
458
|
}
|
|
442
|
-
case 'voice':
|
|
459
|
+
case 'voice':
|
|
443
460
|
debugMessage(`Message Voice command: ${message}`);
|
|
444
461
|
return [{
|
|
445
462
|
"command" : "sendText",
|
|
@@ -507,55 +524,84 @@ module.exports = function(RED) {
|
|
|
507
524
|
return result;
|
|
508
525
|
break;
|
|
509
526
|
case 'homekit':
|
|
510
|
-
debugMessage('HAP: ' + JSON.stringify(message
|
|
511
|
-
if (message.hap
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
} else {
|
|
525
|
-
return messageConstructor('command', {'payload': 'ping'})
|
|
527
|
+
debugMessage('HAP: ' + JSON.stringify(message) + ' PL: ' + JSON.stringify(message.payload) );
|
|
528
|
+
if ("session" in message.hap) {
|
|
529
|
+
let playing = false;
|
|
530
|
+
let id = null;
|
|
531
|
+
let noTrackPhrase = message.noTrackPhrase;
|
|
532
|
+
|
|
533
|
+
if (typeof (device.lastState) !== 'undefined') {
|
|
534
|
+
let lastState = device.lastState;
|
|
535
|
+
if (typeof (lastState.playing) !== 'undefined') {
|
|
536
|
+
playing = lastState.playing;
|
|
537
|
+
}
|
|
538
|
+
if (typeof (lastState.playerState) !== 'undefined') {
|
|
539
|
+
if (typeof (lastState.playerState.id) !== 'undefined') {
|
|
540
|
+
id = lastState.playerState.id;
|
|
526
541
|
}
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
return messageConstructor('command', {'payload': '
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
542
|
+
}
|
|
543
|
+
}
|
|
544
|
+
|
|
545
|
+
// speaker
|
|
546
|
+
if ("TargetMediaState" in message.payload) {
|
|
547
|
+
let TargetMediaState = message.payload.TargetMediaState;
|
|
548
|
+
if (id) {
|
|
549
|
+
return messageConstructor('command', { 'payload': (TargetMediaState ? 'stop' : 'play') })
|
|
550
|
+
} else if (!id && !TargetMediaState && noTrackPhrase) {
|
|
551
|
+
return messageConstructor('voice', { 'payload': noTrackPhrase })
|
|
552
|
+
}
|
|
553
|
+
}
|
|
554
|
+
|
|
555
|
+
// tv
|
|
556
|
+
if ("Active" in message.payload) {
|
|
557
|
+
let Active = message.payload.Active;
|
|
558
|
+
if (id) {
|
|
559
|
+
return messageConstructor('command', { 'payload': (Active ? 'play' : 'stop') })
|
|
560
|
+
} else if (!id && Active && noTrackPhrase) {
|
|
561
|
+
return messageConstructor('voice', { 'payload': noTrackPhrase })
|
|
562
|
+
}
|
|
563
|
+
}
|
|
564
|
+
|
|
565
|
+
// tv + RemoteKey
|
|
566
|
+
if ("RemoteKey" in message.payload) {
|
|
567
|
+
let RemoteKey = message.payload.RemoteKey;
|
|
568
|
+
switch (RemoteKey) {
|
|
569
|
+
case '7':
|
|
570
|
+
return messageConstructor('command', { 'payload': 'forward' }, device)
|
|
571
|
+
case '6':
|
|
572
|
+
return messageConstructor('command', { 'payload': 'backward' }, device)
|
|
573
|
+
case '4':
|
|
574
|
+
return messageConstructor('command', { 'payload': 'next' })
|
|
575
|
+
case '5':
|
|
576
|
+
return messageConstructor('command', { 'payload': 'prev' })
|
|
577
|
+
case '11':
|
|
578
|
+
if (playing) {
|
|
579
|
+
return messageConstructor('command', { 'payload': 'stop' })
|
|
539
580
|
} else {
|
|
540
|
-
|
|
581
|
+
if (id) {
|
|
582
|
+
return messageConstructor('command', { 'payload': 'play' })
|
|
583
|
+
} else if (!id && noTrackPhrase) {
|
|
584
|
+
return messageConstructor('voice', { 'payload': noTrackPhrase })
|
|
585
|
+
}
|
|
541
586
|
}
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
return messageConstructor('command', {'payload': 'ping'})
|
|
587
|
+
}
|
|
588
|
+
}
|
|
589
|
+
|
|
590
|
+
// tv + VolumeSelector
|
|
591
|
+
if ("VolumeSelector" in message.payload) {
|
|
592
|
+
let VolumeSelector = message.payload.VolumeSelector;
|
|
593
|
+
return messageConstructor('command', { 'payload': (VolumeSelector ? 'volumedown' : 'volumeup') }, device)
|
|
550
594
|
}
|
|
551
|
-
|
|
595
|
+
|
|
596
|
+
debugMessage('unknown command')
|
|
597
|
+
return messageConstructor('command', { 'payload': 'ping' })
|
|
552
598
|
} else {
|
|
553
|
-
return messageConstructor('command', {'payload': 'ping'})
|
|
599
|
+
return messageConstructor('command', { 'payload': 'ping' })
|
|
554
600
|
}
|
|
555
|
-
case 'raw':
|
|
601
|
+
case 'raw':
|
|
556
602
|
if (Array.isArray(message.payload)) { return message.payload }
|
|
557
603
|
return [message.payload];
|
|
558
|
-
case 'stopListening':
|
|
604
|
+
case 'stopListening':
|
|
559
605
|
return [{
|
|
560
606
|
"command": "serverAction",
|
|
561
607
|
"serverActionEventPayload": {
|
|
@@ -567,7 +613,7 @@ module.exports = function(RED) {
|
|
|
567
613
|
|
|
568
614
|
}
|
|
569
615
|
function sendMessage(deviceId, messageType, message) {
|
|
570
|
-
|
|
616
|
+
|
|
571
617
|
try {
|
|
572
618
|
let device = searchDeviceByID(deviceId);
|
|
573
619
|
//debugMessage(`deviceId: ${searchDeviceByID(deviceId)}`);
|
|
@@ -608,19 +654,19 @@ module.exports = function(RED) {
|
|
|
608
654
|
//debugMessage(`timeCur: ${timeCurrent} timeMin: ${timeMin} timeMax: ${timeMax}`);
|
|
609
655
|
return [false, daySheduler.phrase];
|
|
610
656
|
}
|
|
611
|
-
|
|
657
|
+
|
|
612
658
|
|
|
613
659
|
}
|
|
614
|
-
|
|
660
|
+
|
|
615
661
|
function searchDeviceByID(id) {
|
|
616
662
|
if (node.deviceList) {
|
|
617
663
|
return node.deviceList.find(device => device.id == id)
|
|
618
|
-
}
|
|
664
|
+
}
|
|
619
665
|
}
|
|
620
666
|
function onPing(device) {
|
|
621
667
|
if (device) {sendMessage(device.id, 'command', {payload: 'ping'});}
|
|
622
668
|
}
|
|
623
|
-
|
|
669
|
+
|
|
624
670
|
function onPing(device) {
|
|
625
671
|
sendMessage(device.id, 'command', {payload: 'ping'});
|
|
626
672
|
}
|
|
@@ -629,19 +675,19 @@ module.exports = function(RED) {
|
|
|
629
675
|
if (device) {
|
|
630
676
|
if (device.ws) {
|
|
631
677
|
switch(device.ws.readyState){
|
|
632
|
-
case 0:
|
|
678
|
+
case 0:
|
|
633
679
|
return {"color": "yellow", "text": "connecting..."}
|
|
634
|
-
case 1:
|
|
680
|
+
case 1:
|
|
635
681
|
return {"color": "green", "text": "connected"}
|
|
636
|
-
case 2:
|
|
682
|
+
case 2:
|
|
637
683
|
return {"color": "red", "text": "disconnecting"}
|
|
638
|
-
case 3:
|
|
684
|
+
case 3:
|
|
639
685
|
return {"color": "red", "text": "disconnected"}
|
|
640
686
|
default:
|
|
641
687
|
return {"color": "red", "text": "disconnected"}
|
|
642
688
|
}
|
|
643
|
-
|
|
644
|
-
}
|
|
689
|
+
|
|
690
|
+
}
|
|
645
691
|
} else {
|
|
646
692
|
return {"color": "red", "text": "disconnected"}
|
|
647
693
|
}
|
|
@@ -649,7 +695,7 @@ module.exports = function(RED) {
|
|
|
649
695
|
}
|
|
650
696
|
|
|
651
697
|
|
|
652
|
-
|
|
698
|
+
|
|
653
699
|
function registerDevice(deviceId, nodeId, parameters) {
|
|
654
700
|
let device = searchDeviceByID(deviceId);
|
|
655
701
|
debugMessage(`Recieved parameters ${JSON.stringify(parameters)} for station id ${deviceId}`);
|
|
@@ -661,7 +707,7 @@ module.exports = function(RED) {
|
|
|
661
707
|
debugMessage(`Device ${device.id} already registered with manager id ${device.manager}. Updating parameters and restart...`);
|
|
662
708
|
reconnect(device);
|
|
663
709
|
return 1;
|
|
664
|
-
|
|
710
|
+
|
|
665
711
|
}
|
|
666
712
|
//новый и первый запрос на регистрацию для устройства
|
|
667
713
|
if (typeof(device.manager) == 'undefined') {
|
|
@@ -690,7 +736,7 @@ module.exports = function(RED) {
|
|
|
690
736
|
registrationBuffer.splice(registrationBuffer.indexOf(currentBuffer), 1)
|
|
691
737
|
debugMessage(`Element from registration buffer was deleted. Current buffer size is ${registrationBuffer.length}`)
|
|
692
738
|
}
|
|
693
|
-
reconnect(device);
|
|
739
|
+
reconnect(device);
|
|
694
740
|
return 0;
|
|
695
741
|
}
|
|
696
742
|
//новый запрос на регистрацию при наличии уже зарегистрированной ноды
|
|
@@ -708,9 +754,9 @@ module.exports = function(RED) {
|
|
|
708
754
|
registrationBuffer.push({"id": deviceId, "manager": nodeId, "parameters": parameters});
|
|
709
755
|
debugMessage(`New element in registration buffer. Current buffer size is ${registrationBuffer.length}`)
|
|
710
756
|
}
|
|
711
|
-
|
|
757
|
+
|
|
712
758
|
}
|
|
713
|
-
|
|
759
|
+
|
|
714
760
|
|
|
715
761
|
}
|
|
716
762
|
function unregisterDevice(deviceId, nodeId){
|
|
@@ -721,7 +767,7 @@ module.exports = function(RED) {
|
|
|
721
767
|
device.parameters = {};
|
|
722
768
|
debugMessage(`For device ${deviceId} was succesfully unregistred managment node whith id ${device.manager}`);
|
|
723
769
|
debugMessage(`device is: ${device}`);
|
|
724
|
-
return 0;
|
|
770
|
+
return 0;
|
|
725
771
|
} else {
|
|
726
772
|
return 2;
|
|
727
773
|
}
|
|
@@ -742,7 +788,7 @@ module.exports = function(RED) {
|
|
|
742
788
|
if (device.savedVolumeLevel) { sendMessage(device.id, 'raw',{payload: {
|
|
743
789
|
"command": "setVolume",
|
|
744
790
|
"volume": parseFloat(device.savedVolumeLevel)
|
|
745
|
-
}
|
|
791
|
+
}
|
|
746
792
|
});
|
|
747
793
|
}
|
|
748
794
|
device.waitForIdle = false;
|
|
@@ -751,13 +797,13 @@ module.exports = function(RED) {
|
|
|
751
797
|
function onStopPlay(device, phrase) {
|
|
752
798
|
sendMessage(device.id, 'command', {payload: 'stop'});
|
|
753
799
|
if (phrase.length > 0 && device.lastState.aliceState != 'SPEAKING') {sendMessage(device.id, 'tts', {payload: phrase, stopListening: true});}
|
|
754
|
-
}
|
|
800
|
+
}
|
|
755
801
|
function onClose() {
|
|
756
802
|
clearInterval(node.interval);
|
|
757
803
|
node.deviceList = [];
|
|
758
804
|
node.removeListener('deviceReady', onDeviceReady)
|
|
759
805
|
}
|
|
760
|
-
|
|
806
|
+
|
|
761
807
|
node.on('refreshHttp', function(activeList, readyList) {
|
|
762
808
|
RED.httpAdmin.get("/yandexdevices_"+node.id, RED.auth.needsPermission('yandex-login.read'), function(req,res) {
|
|
763
809
|
res.json({"devices": readyList});
|
|
@@ -766,8 +812,8 @@ module.exports = function(RED) {
|
|
|
766
812
|
res.json({"devices": activeList});
|
|
767
813
|
});
|
|
768
814
|
});
|
|
769
|
-
|
|
770
|
-
node.on('refreshHttpDNS', function(dnsList) {
|
|
815
|
+
|
|
816
|
+
node.on('refreshHttpDNS', function(dnsList) {
|
|
771
817
|
RED.httpAdmin.get("/mdns/"+node.id, RED.auth.needsPermission('yandex-login.read'), function(req,res) {
|
|
772
818
|
res.json({"SearchResult": dnsList});
|
|
773
819
|
});
|
|
@@ -786,12 +832,12 @@ module.exports = function(RED) {
|
|
|
786
832
|
let device = searchDeviceByID(id);
|
|
787
833
|
if (device) {
|
|
788
834
|
|
|
789
|
-
res.json({"id": device.id,"name": device.name, "platform": device.platform, "address": device.address, "port": device.port, "manager": device.manager, "ws": device.ws, "parameters": device.parameters});
|
|
835
|
+
res.json({"id": device.id,"name": device.name, "platform": device.platform, "address": device.address, "port": device.port, "manager": device.manager, "ws": device.ws, "parameters": device.parameters, "fullMessage": device.fullMessage });
|
|
790
836
|
} else {
|
|
791
837
|
res.json({"error": 'no device found'});
|
|
792
838
|
}
|
|
793
839
|
});
|
|
794
|
-
|
|
840
|
+
|
|
795
841
|
// main init
|
|
796
842
|
if (typeof(node.token) !== 'undefined') {
|
|
797
843
|
debugMessage(`Starting server with id ${node.id}`)
|