node-red-contrib-yandex-station-management 0.2.5 → 0.3.1
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 +54 -7
- package/nodes/get.js +25 -18
- package/nodes/in.js +30 -18
- package/nodes/local-out.html +236 -134
- package/nodes/local-out.js +100 -11
- package/nodes/locales/en-US/local-out.html +45 -0
- package/nodes/locales/en-US/local-out.json +71 -0
- package/nodes/locales/ru-RU/local-out.html +42 -0
- package/nodes/locales/ru-RU/local-out.json +68 -0
- package/nodes/yandex-login.html +102 -9
- package/nodes/yandex-login.js +41 -14
- package/package.json +1 -1
package/nodes/local-out.html
CHANGED
|
@@ -1,169 +1,271 @@
|
|
|
1
1
|
<script type="text/javascript">
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
2
|
+
|
|
3
|
+
RED.nodes.registerType('alice-local-out', {
|
|
4
|
+
category: 'Yandex Station',
|
|
5
|
+
color: '#b89fcc',
|
|
6
|
+
defaults: {
|
|
7
|
+
name: {value: ''},
|
|
8
|
+
token: {
|
|
9
|
+
type: 'yandex-login',
|
|
10
|
+
required: true,
|
|
11
|
+
},
|
|
12
|
+
station_id: {
|
|
13
|
+
required: true,
|
|
14
|
+
},
|
|
15
|
+
debugFlag: {
|
|
16
|
+
value: false,
|
|
17
|
+
},
|
|
18
|
+
input: {
|
|
19
|
+
value: 'command',
|
|
20
|
+
required: true,
|
|
21
|
+
},
|
|
22
|
+
payload: {
|
|
23
|
+
value: 'payload',
|
|
24
|
+
},
|
|
25
|
+
payloadType: {
|
|
26
|
+
value: 'msg',
|
|
27
|
+
},
|
|
28
|
+
volume: {},
|
|
29
|
+
volumeFlag: {
|
|
30
|
+
value: false,
|
|
31
|
+
},
|
|
32
|
+
stopListening: {
|
|
33
|
+
value: true,
|
|
34
|
+
},
|
|
35
|
+
pauseMusic: {
|
|
36
|
+
value: false,
|
|
37
|
+
},
|
|
38
|
+
noTrack: {},
|
|
39
|
+
ttsVoice: {
|
|
40
|
+
value: null,
|
|
41
|
+
},
|
|
42
|
+
ttsEffect: {
|
|
43
|
+
value: null,
|
|
44
|
+
required: false,
|
|
45
|
+
},
|
|
46
|
+
},
|
|
47
|
+
inputs: 1,
|
|
48
|
+
outputs: 0,
|
|
49
|
+
icon: 'station.png',
|
|
50
|
+
label: function() {
|
|
51
|
+
return this.name || this.station_id;
|
|
52
|
+
},
|
|
53
|
+
paletteLabel: 'Yandex OUT',
|
|
54
|
+
oneditprepare: onOpen,
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
function onOpen() {
|
|
58
|
+
var command = $('#node-input-input').val();
|
|
59
|
+
|
|
60
|
+
$('#node-input-payload').typedInput({
|
|
61
|
+
types: ['msg', 'str', 'flow', 'global', 'json'],
|
|
62
|
+
default: 'msg',
|
|
63
|
+
value: 'payload',
|
|
64
|
+
typeField: $('#node-input-payloadType'),
|
|
43
65
|
});
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
$("#node-input-ttsEffect").typedInput({type:"ttsEffect", types:[{
|
|
70
|
+
value: 'ttsEffect',
|
|
71
|
+
multiple: false,
|
|
72
|
+
options: [
|
|
73
|
+
{ value: "", label: RED._("node-red-contrib-yandex-station-management/alice-local-out:effect.none")},
|
|
74
|
+
{ value: "behind_the_wall", label: RED._("node-red-contrib-yandex-station-management/alice-local-out:effect.behind_the_wall")},
|
|
75
|
+
{ value: "hamster", label: RED._("node-red-contrib-yandex-station-management/alice-local-out:effect.hamster")},
|
|
76
|
+
{ value: "megaphone", label: RED._("node-red-contrib-yandex-station-management/alice-local-out:effect.megaphone")},
|
|
77
|
+
{ value: "pitch_down", label: RED._("node-red-contrib-yandex-station-management/alice-local-out:effect.pitch_down")},
|
|
78
|
+
{ value: "psychodelic", label: RED._("node-red-contrib-yandex-station-management/alice-local-out:effect.psychodelic")},
|
|
79
|
+
{ value: "pulse", label: RED._("node-red-contrib-yandex-station-management/alice-local-out:effect.pulse")},
|
|
80
|
+
{ value: "train_announce", label: RED._("node-red-contrib-yandex-station-management/alice-local-out:effect.train_announce")}
|
|
81
|
+
]
|
|
82
|
+
}]})
|
|
83
|
+
|
|
84
|
+
let config = RED.nodes.node($('#node-input-token').val());
|
|
85
|
+
let selector = $('#node-input-station_id');
|
|
86
|
+
selector.empty();
|
|
87
|
+
let currentId = this.station_id;
|
|
88
|
+
$.getJSON('yandexdevices_' + config.id, function(data) {
|
|
89
|
+
data.devices.forEach(device => {
|
|
90
|
+
selector.append(`<option value="${device.id}">
|
|
52
91
|
${device.name}(${device.id})
|
|
53
|
-
</option>`)
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
}
|
|
91
|
-
})
|
|
92
|
-
$('#node-input-volume').on('change', function() {
|
|
93
|
-
$('#volume-level').text(`${parseFloat($('#node-input-volume').val())*100}`)
|
|
94
|
-
})
|
|
95
|
-
}
|
|
96
|
-
function updateDevices() {
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
}
|
|
92
|
+
</option>`);
|
|
93
|
+
$(`#node-input-station_id :contains(${currentId})`).attr('selected', 'selected');
|
|
94
|
+
});
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
$('.command_options').hide();
|
|
98
|
+
$('.command_options-' + command).show();
|
|
99
|
+
|
|
100
|
+
$('#node-input-input').on('change', function(type, value) {
|
|
101
|
+
$('.command_options').hide();
|
|
102
|
+
$('.command_options-' + $(this).val()).show();
|
|
103
|
+
|
|
104
|
+
if ($(this).val() == 'tts') {
|
|
105
|
+
if ($('#node-input-volumeFlag').prop('checked')) {
|
|
106
|
+
$('#node-input-volume').show();
|
|
107
|
+
$('#range-label').show();
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
$('#node-input-volumeFlag').on('change', function(type, value) {
|
|
113
|
+
let val = $(this).val();
|
|
114
|
+
if ($('#node-input-input').val() == 'tts' && $(this).prop('checked')) {
|
|
115
|
+
$('#node-input-volume').show();
|
|
116
|
+
$('#range-label').show();
|
|
117
|
+
|
|
118
|
+
} else if ($('#node-input-input').val() == 'tts' && !$(this).prop('checked')) {
|
|
119
|
+
$('#node-input-volume').hide();
|
|
120
|
+
$('#range-label').hide();
|
|
121
|
+
|
|
122
|
+
}
|
|
123
|
+
});
|
|
124
|
+
$('#node-input-volume').on('change', function() {
|
|
125
|
+
$('#volume-level').text(`${parseFloat($('#node-input-volume').val())}`);
|
|
126
|
+
});
|
|
127
|
+
}
|
|
100
128
|
</script>
|
|
101
129
|
|
|
102
130
|
<script type="text/html" data-template-name="alice-local-out">
|
|
103
131
|
<style>
|
|
104
|
-
.label
|
|
105
|
-
|
|
106
|
-
|
|
132
|
+
label.label {
|
|
133
|
+
line-height: 1em;
|
|
134
|
+
}
|
|
135
|
+
label.label-long {
|
|
136
|
+
min-width: 150px;
|
|
137
|
+
width: 20%;
|
|
138
|
+
}
|
|
139
|
+
.online {
|
|
140
|
+
display: inline-block;
|
|
141
|
+
width: auto;
|
|
142
|
+
vertical-align: middle;
|
|
143
|
+
}
|
|
144
|
+
</style>
|
|
107
145
|
|
|
108
146
|
<div class="form-row">
|
|
109
|
-
<label for="node-input-name"><i class="fa fa-bookmark"></i
|
|
110
|
-
<input type="text" id="node-input-name"
|
|
147
|
+
<label for="node-input-name"><i class="fa fa-bookmark"></i> <span data-i18n="label.name"></span></label>
|
|
148
|
+
<input type="text" id="node-input-name">
|
|
111
149
|
</div>
|
|
112
150
|
<div class="form-row">
|
|
113
|
-
<label for="node-input-token"><i class="fa fa-globe"></i
|
|
114
|
-
<input type="text" id="node-input-token" placeholder="
|
|
151
|
+
<label for="node-input-token"><i class="fa fa-globe"></i> <span data-i18n="label.login"></span></label>
|
|
152
|
+
<input type="text" id="node-input-token" placeholder="">
|
|
115
153
|
</div>
|
|
116
154
|
<div class="form-row">
|
|
117
|
-
<label for="node-input-station_id"><i class="fa fa-database"
|
|
155
|
+
<label for="node-input-station_id"><i class="fa fa-database"></i> <span data-i18n="label.station"></span></label>
|
|
118
156
|
<div style="display: inline-block;position: relative;width: 70%;height: 20px;">
|
|
119
|
-
<div style="position: absolute;left:
|
|
157
|
+
<div style="position: absolute;left: 0; right: 40px;">
|
|
120
158
|
<select id="node-input-station_id" data-single="true" style="width: 100%"></select>
|
|
121
|
-
</div>
|
|
159
|
+
</div>
|
|
122
160
|
<div style="text-align: end; display: inline; float: right">
|
|
123
|
-
<button onclick="onOpen()" class="red-ui-button" style="position: absolute;right: 0px;top: 0px;"
|
|
161
|
+
<button onclick="onOpen()" class="red-ui-button" style="position: absolute;right: 0px;top: 0px;">
|
|
162
|
+
<i class="fa fa-refresh"></i></button>
|
|
124
163
|
</div>
|
|
125
164
|
</div>
|
|
126
165
|
</div>
|
|
127
166
|
<div class="form-row">
|
|
128
|
-
<label for="node-input-input"><i class="fa fa-arrow-circle-o-right"
|
|
167
|
+
<label for="node-input-input"><i class="fa fa-arrow-circle-o-right"></i> <span data-i18n="label.command"></span></label>
|
|
129
168
|
<div style="display: inline-block;position: relative;width: 70%;height: 20px;">
|
|
130
169
|
<div style="position: absolute;left: 0px; right: 0px;">
|
|
131
170
|
<select id="node-input-input" data-single="true" style="width: 100%">
|
|
132
|
-
<option value="command"
|
|
133
|
-
<option value="voice"
|
|
134
|
-
<option value="tts"
|
|
135
|
-
<option value="homekit"
|
|
136
|
-
<option value="
|
|
137
|
-
<option value="
|
|
171
|
+
<option value="command" data-i18n="command.player"></option>
|
|
172
|
+
<option value="voice" data-i18n="command.voice"></option>
|
|
173
|
+
<option value="tts" data-i18n="command.tts"></option>
|
|
174
|
+
<option value="homekit" data-i18n="command.homekit"></option>
|
|
175
|
+
<option value="stopListening" data-i18n="command.stop_listening"></option>
|
|
176
|
+
<option value="raw" data-i18n="command.raw"></option>
|
|
138
177
|
</select>
|
|
139
|
-
|
|
178
|
+
</div>
|
|
140
179
|
</div>
|
|
141
180
|
</div>
|
|
142
181
|
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
<
|
|
146
|
-
<input type="
|
|
147
|
-
<div id="range-label" class='online'><span id="volume-level" class="online"></span><span class="online">%</span></div>
|
|
182
|
+
<!--for homekit-->
|
|
183
|
+
<div class="form-row command_options command_options-homekit">
|
|
184
|
+
<label for="node-input-noTrack" class="label-long" style="display: inline-block"><i class="fa fa-podcast"></i> <span data-i18n="label.default_command"></span></label>
|
|
185
|
+
<input type="text" id="node-input-noTrack" data-i18n="[placeholder]placeholder.play_music" style="display: inline-block;left: 0px; right: 0px; width: 60%; vertical-align: middle;">
|
|
148
186
|
</div>
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
187
|
+
|
|
188
|
+
<!--for tts-->
|
|
189
|
+
<div class="form-row command_options command_options-tts">
|
|
190
|
+
<label for="node-input-payload" class="l-width"><i class="fa fa-envelope"></i> <span data-i18n="label.text"></span></label>
|
|
191
|
+
<input type="text" id="node-input-payload" style="width:70%">
|
|
192
|
+
<input type="hidden" id="node-input-payloadType">
|
|
152
193
|
</div>
|
|
153
|
-
<div class="form-row
|
|
154
|
-
<label
|
|
155
|
-
|
|
194
|
+
<div class="form-row command_options command_options-tts">
|
|
195
|
+
<label class="label" for='node-input-ttsVoice'>
|
|
196
|
+
<i class='fa fa-user'></i> <span data-i18n="label.voice"></span>
|
|
197
|
+
<div class="red-ui-debug-msg-type-string" style="font-size: 10px;">msg.voice</div></label>
|
|
198
|
+
</label>
|
|
199
|
+
<div style="display: inline-block;position: relative;width: 70%;height: 30px;">
|
|
200
|
+
<div style="position: absolute;left: 0px; right: 0px;">
|
|
201
|
+
<select id="node-input-ttsVoice" style="width: 100%;vertical-align: top;">
|
|
202
|
+
<option value="" data-i18n="voice.default"></option>
|
|
203
|
+
<!-- <option value="alena" data-i18n="voice.alena"></option>-->
|
|
204
|
+
<option value="alyss" data-i18n="voice.alyss"></option>
|
|
205
|
+
<option value="anton_samokhvalov" data-i18n="voice.anton_samokhvalov"></option>
|
|
206
|
+
<option value="dude" data-i18n="voice.dude"></option>
|
|
207
|
+
<option value="ermil" data-i18n="voice.ermil"></option>
|
|
208
|
+
<option value="ermilov" data-i18n="voice.ermilov"></option>
|
|
209
|
+
<option value="ermil_with_tuning" data-i18n="voice.ermil_with_tuning"></option>
|
|
210
|
+
<option value="erkanyavas" data-i18n="voice.erkanyavas"></option>
|
|
211
|
+
<!-- <option value="filipp" data-i18n="voice.filipp"></option>-->
|
|
212
|
+
<option value="jane" data-i18n="voice.jane"></option>
|
|
213
|
+
<option value="kolya" data-i18n="voice.kolya"></option>
|
|
214
|
+
<option value="kostya" data-i18n="voice.kostya"></option>
|
|
215
|
+
<option value="levitan" data-i18n="voice.levitan"></option>
|
|
216
|
+
<option value="nastya" data-i18n="voice.nastya"></option>
|
|
217
|
+
<option value="nick" data-i18n="voice.nick"></option>
|
|
218
|
+
<option value="oksana" data-i18n="voice.oksana"></option>
|
|
219
|
+
<option value="omazh" data-i18n="voice.omazh"></option>
|
|
220
|
+
<option value="robot" data-i18n="voice.robot"></option>
|
|
221
|
+
<option value="sasha" data-i18n="voice.sasha"></option>
|
|
222
|
+
<option value="silaerkan" data-i18n="voice.silaerkan"></option>
|
|
223
|
+
<option value="smoky" data-i18n="voice.smoky"></option>
|
|
224
|
+
<option value="tanya" data-i18n="voice.tanya"></option>
|
|
225
|
+
<option value="tatyana_abramova" data-i18n="voice.tatyana_abramova"></option>
|
|
226
|
+
<option value="zahar" data-i18n="voice.zahar"></option>
|
|
227
|
+
<option value="zhenya" data-i18n="voice.zhenya"></option>
|
|
228
|
+
<option value="zombie" data-i18n="voice.zombie"></option>
|
|
229
|
+
<option value="voicesearch" data-i18n="voice.voicesearch"></option>
|
|
230
|
+
</select>
|
|
231
|
+
</div>
|
|
232
|
+
</div>
|
|
233
|
+
</div>
|
|
234
|
+
<div class="form-row command_options command_options-tts">
|
|
235
|
+
<label for="node-input-ttsEffect" class="label l-width" style="vertical-align: bottom;">
|
|
236
|
+
<i class="fa fa-magic"></i> <span data-i18n="label.effect"></span>
|
|
237
|
+
<div class="red-ui-debug-msg-type-string" style="font-size: 10px;">msg.effect</div></label>
|
|
238
|
+
</label>
|
|
239
|
+
<input type="text" id="node-input-ttsEffect">
|
|
240
|
+
</div>
|
|
241
|
+
<div class="form-row command_options command_options-tts">
|
|
242
|
+
<label for="node-input-volume" class="label label-long">
|
|
243
|
+
<i class="fa fa-volume-up"></i> <span data-i18n="label.volume"></span>
|
|
244
|
+
<div class="red-ui-debug-msg-type-string" style="font-size: 10px;">msg.volume</div></label>
|
|
245
|
+
</label>
|
|
246
|
+
<input type="checkbox" id="node-input-volumeFlag" style="display: inline-block; width: auto; vertical-align: top;">
|
|
247
|
+
<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
|
+
<div id="range-label" class='online'><span id="volume-level" class="online"></span><span class="online">%</span></div>
|
|
156
249
|
</div>
|
|
157
|
-
<div class="form-row
|
|
158
|
-
<label for="node-input-
|
|
159
|
-
|
|
250
|
+
<div class="form-row command_options command_options-tts">
|
|
251
|
+
<label for="node-input-stopListening" class="label label-long">
|
|
252
|
+
<i class="fa fa-deaf"></i> <span data-i18n="label.prevent_listening"></span>
|
|
253
|
+
<div class="red-ui-debug-msg-type-string" style="font-size: 10px;">msg.prevent_listening</div></label>
|
|
254
|
+
</label>
|
|
255
|
+
<input type="checkbox" id="node-input-stopListening" style="display: inline-block; width: auto; vertical-align: top;">
|
|
160
256
|
</div>
|
|
257
|
+
<div class="form-row command_options command_options-tts">
|
|
258
|
+
<label for="node-input-pauseMusic" class="label label-long">
|
|
259
|
+
<i class="fa fa-pause"></i> <span data-i18n="label.pause_while_tts"></span>
|
|
260
|
+
<div class="red-ui-debug-msg-type-string" style="font-size: 10px;">msg.pause_music</div></label>
|
|
261
|
+
</label>
|
|
262
|
+
<input type="checkbox" id="node-input-pauseMusic" style="display: inline-block; width: auto; vertical-align: top;">
|
|
263
|
+
</div>
|
|
264
|
+
|
|
265
|
+
|
|
161
266
|
<div class="form-row" style="vertical-align:bottom;">
|
|
162
|
-
<label for='node-input-debugFlag'><i class='fa fa-share-square'
|
|
163
|
-
<input type="checkbox" id="node-input-debugFlag" checked="checked" style="display: inline-block; width: auto; vertical-align: top;">
|
|
267
|
+
<label for='node-input-debugFlag' class="label-long"><i class='fa fa-share-square'></i> <span data-i18n="label.debug"></span></label>
|
|
268
|
+
<input type="checkbox" id="node-input-debugFlag" checked="checked" style="display: inline-block; width: auto; vertical-align: top;">
|
|
164
269
|
</div>
|
|
165
270
|
</script>
|
|
166
271
|
|
|
167
|
-
<script type="text/html" data-help-name="alice-local-out">
|
|
168
|
-
<p> Output node for Yandex Station local management</p>
|
|
169
|
-
</script>
|
package/nodes/local-out.js
CHANGED
|
@@ -2,7 +2,9 @@ module.exports = function(RED) {
|
|
|
2
2
|
function AliceLocalOutNode(config) {
|
|
3
3
|
RED.nodes.createNode(this,config);
|
|
4
4
|
let node = this;
|
|
5
|
+
node.config = config;
|
|
5
6
|
node.controller = RED.nodes.getNode(config.token);
|
|
7
|
+
|
|
6
8
|
node.input = config.input;
|
|
7
9
|
node.station = config.station_id;
|
|
8
10
|
node.debugFlag = config.debugFlag;
|
|
@@ -11,6 +13,8 @@ module.exports = function(RED) {
|
|
|
11
13
|
node.stopListening = config.stopListening;
|
|
12
14
|
node.noTrackPhrase = config.noTrack;
|
|
13
15
|
node.pauseMusic = config.pauseMusic;
|
|
16
|
+
node.ttsVoice = config.ttsVoice;
|
|
17
|
+
node.ttsEffect = config.ttsEffect;
|
|
14
18
|
node.status({});
|
|
15
19
|
|
|
16
20
|
function debugMessage(text){
|
|
@@ -19,15 +23,100 @@ module.exports = function(RED) {
|
|
|
19
23
|
}
|
|
20
24
|
}
|
|
21
25
|
debugMessage(node.station);
|
|
22
|
-
node.on('input', (
|
|
23
|
-
debugMessage(`input: ${JSON.stringify(
|
|
24
|
-
|
|
25
|
-
if (node.stopListening) {data.stopListening = node.stopListening}
|
|
26
|
-
if (node.noTrackPhrase) {data.noTrackPhrase = node.noTrackPhrase}
|
|
27
|
-
if (node.pauseMusic) {data.pauseMusic = node.pauseMusic}
|
|
26
|
+
node.on('input', (input) => {
|
|
27
|
+
debugMessage(`input: ${JSON.stringify(input)}`)
|
|
28
|
+
|
|
28
29
|
if (node.station) {
|
|
29
|
-
|
|
30
|
-
|
|
30
|
+
var data = {};
|
|
31
|
+
//data.payload = input.payload;
|
|
32
|
+
|
|
33
|
+
//apply node's config
|
|
34
|
+
if (node.volumeFlag) {data.volume = node.volume/100}
|
|
35
|
+
if (node.stopListening) {data.stopListening = node.stopListening}
|
|
36
|
+
if (node.noTrackPhrase) {data.noTrackPhrase = node.noTrackPhrase}
|
|
37
|
+
if (node.pauseMusic) {data.pauseMusic = node.pauseMusic}
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
//redefine options from input
|
|
41
|
+
if ("volume" in input) {data.volume = input.volume/100}
|
|
42
|
+
if ("voice" in input) {node.ttsVoice = input.voice}
|
|
43
|
+
if ("effect" in input) {node.ttsEffect = input.effect}
|
|
44
|
+
if ("prevent_listening" in input) {node.noTrackPhrase = input.prevent_listening}
|
|
45
|
+
if ("pause_music" in input) {data.pauseMusic = input.pause_music}
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
if ('tts' === node.input) {
|
|
49
|
+
let payload;
|
|
50
|
+
switch (node.config.payloadType) {
|
|
51
|
+
case 'flow': {
|
|
52
|
+
if (typeof(node.context().flow.get(node.config.payload)) != "undefined") {
|
|
53
|
+
payload = node.context().flow.get(node.config.payload)
|
|
54
|
+
} else {
|
|
55
|
+
debugMessage('Empty flow context with key '+ node.config.payload)
|
|
56
|
+
}
|
|
57
|
+
break;
|
|
58
|
+
}
|
|
59
|
+
case 'global': {
|
|
60
|
+
if (typeof(node.context().global.get(node.config.payload)) != "undefined") {
|
|
61
|
+
payload = node.context().global.get(node.config.payload)
|
|
62
|
+
} else {
|
|
63
|
+
debugMessage('Empty global context with key '+ node.config.payload)
|
|
64
|
+
}
|
|
65
|
+
break;
|
|
66
|
+
|
|
67
|
+
}
|
|
68
|
+
case 'str': {
|
|
69
|
+
payload = node.config.payload;
|
|
70
|
+
break;
|
|
71
|
+
}
|
|
72
|
+
case 'json': {
|
|
73
|
+
let arr = [];
|
|
74
|
+
|
|
75
|
+
try {
|
|
76
|
+
arr = JSON.parse(node.config.payload)
|
|
77
|
+
payload = arr[(Math.random() * arr.length) | 0];
|
|
78
|
+
} catch (e) {
|
|
79
|
+
debugMessage("Error on parsing input JSON: "+ e);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
break;
|
|
83
|
+
}
|
|
84
|
+
case 'msg': {
|
|
85
|
+
payload = node.input[node.config.payload]
|
|
86
|
+
}
|
|
87
|
+
default: {
|
|
88
|
+
payload = input[node.config.payload];
|
|
89
|
+
break;
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
if (typeof(payload) != "undefined" ) {
|
|
93
|
+
data.payload = payload;
|
|
94
|
+
if (node.ttsVoice) {
|
|
95
|
+
data.payload = "<speaker voice='" + node.ttsVoice + "'>" + data.payload;
|
|
96
|
+
}
|
|
97
|
+
if (node.ttsEffect) {
|
|
98
|
+
let effectsArr = node.ttsEffect.split(',');
|
|
99
|
+
for (let ind in effectsArr) {
|
|
100
|
+
data.payload = "<speaker effect='" + effectsArr[ind] + "'>" + data.payload;
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
} else {
|
|
104
|
+
data.payload = ""
|
|
105
|
+
}
|
|
106
|
+
if (data.payload.length > 0) {node.controller.sendMessage(node.station, node.input, data)
|
|
107
|
+
debugMessage(`Sending data: station: ${node.station}, input type: ${node.input}, data: ${JSON.stringify(data)}`);
|
|
108
|
+
} else {
|
|
109
|
+
debugMessage("Nothing to send. Check input and parameters")
|
|
110
|
+
}
|
|
111
|
+
} else {
|
|
112
|
+
data.payload = input.payload;
|
|
113
|
+
data.hap = input.hap;
|
|
114
|
+
node.controller.sendMessage(node.station, node.input, data);
|
|
115
|
+
debugMessage(`Sending data: station: ${node.station}, input type: ${node.input}, data: ${JSON.stringify(data)}`);
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
} else {
|
|
119
|
+
debugMessage('node.station is empty');
|
|
31
120
|
}
|
|
32
121
|
});
|
|
33
122
|
|
|
@@ -37,10 +126,10 @@ module.exports = function(RED) {
|
|
|
37
126
|
node.status({fill: data.color,shape:"dot",text: data.text});
|
|
38
127
|
}
|
|
39
128
|
}
|
|
40
|
-
|
|
129
|
+
|
|
41
130
|
|
|
42
131
|
node.on('close', () => {
|
|
43
|
-
node.controller.removeListener(`statusUpdate_${node.station}`, node.onStatus)
|
|
132
|
+
node.controller.removeListener(`statusUpdate_${node.station}`, node.onStatus)
|
|
44
133
|
});
|
|
45
134
|
|
|
46
135
|
if (node.controller) {
|
|
@@ -49,4 +138,4 @@ module.exports = function(RED) {
|
|
|
49
138
|
}
|
|
50
139
|
}
|
|
51
140
|
RED.nodes.registerType("alice-local-out",AliceLocalOutNode);
|
|
52
|
-
}
|
|
141
|
+
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
<script type="text/html" data-help-name="alice-local-out">
|
|
2
|
+
<p>Output node for Yandex Station local management</p>
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
<h3>TTS</h3>
|
|
6
|
+
<p>Воспросизведение голосом отправленных фраз - Text to Speech. Не имеет ограничения по символам.</p>
|
|
7
|
+
<dl class="message-properties">
|
|
8
|
+
<dt>Текст</dt><dd>Откуда брать текст: msg.payload, flow, global или Json - выбрать сообщение случайным образом из массива вида <code>["один", "два", "три"]</code>.</dd>
|
|
9
|
+
<dt class="optional">Голос</dt><dd>Изменить голос.</dd>
|
|
10
|
+
<dt class="optional">Эффект</dt><dd>Наложить эффект на голос.</dd>
|
|
11
|
+
<dt class="optional">Громкость</dt><dd>Позволяет произносить фразу заданной громкостью. Если не выбрано, то фраза произносится с текущим уровнем громкости. После произнесения, уровень громкости вернется в изначальный.</dd>
|
|
12
|
+
<dt class="optional">Не ждать ответ</dt><dd>Если выбрано, то колонка, после воспроизведения, не "слушает", что ей ответят.</dd>
|
|
13
|
+
<dt class="optional">Плеер на паузу</dt><dd>Ставит воспроизведение плеера на паузу на время речи. Воспроизведение будет продолжено, только если что-то играло на момент поступления команды.</dd>
|
|
14
|
+
</dl>
|
|
15
|
+
|
|
16
|
+
<h4>Отмечайте ударения</h4>
|
|
17
|
+
<p>При необходимости ударные гласные в словах следует отмечать знаком «+», например:</p>
|
|
18
|
+
<ul>
|
|
19
|
+
<li><code>остр+ота</code></li>
|
|
20
|
+
<li><code>м+ука</code></li>
|
|
21
|
+
</ul>
|
|
22
|
+
|
|
23
|
+
<h4>Разделяйте слова</h4>
|
|
24
|
+
<p>Длинные слова можно разбить на слова покороче и проставить ударения для каждого из этих коротких слов, например:</p>
|
|
25
|
+
<ul>
|
|
26
|
+
<li><code>мн+ого пр+офильный</code></li>
|
|
27
|
+
<li><code>с+еми пал+атинск</code></li>
|
|
28
|
+
</ul>
|
|
29
|
+
|
|
30
|
+
<h4>Меняйте написание слов</h4>
|
|
31
|
+
<p>Некоторые слова можно попробовать писать так, как они слышатся:</p>
|
|
32
|
+
<ul>
|
|
33
|
+
<li><code>«ненастный» — нен+асный</code></li>
|
|
34
|
+
<li><code>«пожалуйста» — пож+алуста</code></li>
|
|
35
|
+
</ul>
|
|
36
|
+
|
|
37
|
+
<h4>Добавляйте паузы</h4>
|
|
38
|
+
<p>Чтобы задать паузу между словами, используйте синтаксис sil <[ количество_миллисекунд ]>. Например:</p>
|
|
39
|
+
<ul>
|
|
40
|
+
<li><code>смелость sil <[500]> город+а берёт</code></li>
|
|
41
|
+
</ul>
|
|
42
|
+
<p>Каждый отделенный пробелами пунктуационный знак обозначается паузой в 50-100 мс.</p>
|
|
43
|
+
</script>
|
|
44
|
+
|
|
45
|
+
|