node-red-contrib-yandex-station-management 0.3.12 → 0.5.0
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/.github/workflows/publish.yml +41 -0
- package/.github/workflows/release.yml +41 -0
- package/README.md +3 -0
- package/nodes/get.html +17 -11
- package/nodes/in.html +33 -23
- package/nodes/in.js +11 -3
- package/nodes/local-out.html +29 -28
- package/nodes/local-out.js +16 -0
- package/nodes/locales/en-US/local-out.json +2 -1
- package/nodes/locales/ru-RU/local-out.json +2 -1
- package/nodes/station.html +37 -27
- package/nodes/yandex-login.html +13 -7
- package/nodes/yandex-login.js +114 -19
- package/package.json +1 -1
- package/test/cloud-requests.test.js +203 -0
- package/test/discovery.test.js +51 -5
- package/test/msg-source.test.js +84 -0
- package/test/unique-messages.test.js +87 -0
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
name: Publish to npm
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
workflow_dispatch:
|
|
5
|
+
|
|
6
|
+
permissions:
|
|
7
|
+
contents: read
|
|
8
|
+
id-token: write
|
|
9
|
+
|
|
10
|
+
concurrency:
|
|
11
|
+
group: npm-publish
|
|
12
|
+
cancel-in-progress: false
|
|
13
|
+
|
|
14
|
+
jobs:
|
|
15
|
+
publish:
|
|
16
|
+
if: startsWith(github.ref, 'refs/tags/v')
|
|
17
|
+
runs-on: ubuntu-latest
|
|
18
|
+
steps:
|
|
19
|
+
- uses: actions/checkout@v4
|
|
20
|
+
with:
|
|
21
|
+
fetch-depth: 0
|
|
22
|
+
persist-credentials: false
|
|
23
|
+
- uses: actions/setup-node@v4
|
|
24
|
+
with:
|
|
25
|
+
node-version: '24'
|
|
26
|
+
registry-url: https://registry.npmjs.org
|
|
27
|
+
cache: npm
|
|
28
|
+
- name: Verify release tag and branch
|
|
29
|
+
env:
|
|
30
|
+
RELEASE_TAG: ${{ github.ref_name }}
|
|
31
|
+
run: |
|
|
32
|
+
set -euo pipefail
|
|
33
|
+
version=$(node -p "require('./package.json').version")
|
|
34
|
+
test "$RELEASE_TAG" = "v$version"
|
|
35
|
+
git merge-base --is-ancestor HEAD origin/master
|
|
36
|
+
- run: npm ci --ignore-scripts
|
|
37
|
+
- run: npm test
|
|
38
|
+
- name: Preview package contents
|
|
39
|
+
run: npm pack --dry-run
|
|
40
|
+
- name: Publish package
|
|
41
|
+
run: npm publish --access public
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
name: Prepare minor release
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
workflow_dispatch:
|
|
5
|
+
|
|
6
|
+
permissions:
|
|
7
|
+
contents: write
|
|
8
|
+
actions: write
|
|
9
|
+
|
|
10
|
+
concurrency:
|
|
11
|
+
group: npm-release
|
|
12
|
+
cancel-in-progress: false
|
|
13
|
+
|
|
14
|
+
jobs:
|
|
15
|
+
prepare:
|
|
16
|
+
if: github.ref == 'refs/heads/master'
|
|
17
|
+
runs-on: ubuntu-latest
|
|
18
|
+
steps:
|
|
19
|
+
- uses: actions/checkout@v4
|
|
20
|
+
with:
|
|
21
|
+
fetch-depth: 0
|
|
22
|
+
- uses: actions/setup-node@v4
|
|
23
|
+
with:
|
|
24
|
+
node-version: '24'
|
|
25
|
+
cache: npm
|
|
26
|
+
- run: npm ci --ignore-scripts
|
|
27
|
+
- run: npm test
|
|
28
|
+
- name: Create version commit and tag
|
|
29
|
+
id: version
|
|
30
|
+
run: |
|
|
31
|
+
set -euo pipefail
|
|
32
|
+
git config user.name "github-actions[bot]"
|
|
33
|
+
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
|
|
34
|
+
version=$(npm version minor -m 'Release %s')
|
|
35
|
+
git push --atomic origin HEAD:refs/heads/master "refs/tags/$version"
|
|
36
|
+
echo "tag=$version" >> "$GITHUB_OUTPUT"
|
|
37
|
+
- name: Start npm publication
|
|
38
|
+
env:
|
|
39
|
+
GH_TOKEN: ${{ github.token }}
|
|
40
|
+
RELEASE_TAG: ${{ steps.version.outputs.tag }}
|
|
41
|
+
run: gh workflow run publish.yml --ref "$RELEASE_TAG"
|
package/README.md
CHANGED
|
@@ -112,6 +112,9 @@ Phrase to say - фраза, которую скажет Алиса вместо
|
|
|
112
112
|
#### Player command.
|
|
113
113
|
Управление воспроизведением колонки. Нода ждет, что в payload строкой придет одна из следующих команд: play, stop, next, prev, forward(вперед на 10 секунд), backward(назад на 10 секунд), volumeup, volumedown
|
|
114
114
|
|
|
115
|
+
#### Reinit connection.
|
|
116
|
+
Полный сброс websocket-соединения с колонкой без деплоя Node-RED. Нода рвёт текущее соединение, сбрасывает накопленное состояние (последний статус, флаги, таймеры) и заново запрашивает conversation token и подключение. Полезно, когда после долгой работы соединение "зарастает" накопленным состоянием. Запускается двумя способами: выбрать команду "Reinit connection" в настройках ноды (тогда любое сообщение на вход срабатывает, msg.payload не используется) или просто прислать в любом режиме сообщение с `msg.reinit = true` — обычный payload в этом случае не отправляется, т.к. соединение на время сброса недоступно.
|
|
117
|
+
|
|
115
118
|
#### Voice command.
|
|
116
119
|
Отправка команды, вместо того, чтобы говорить ее колонке голосом: "Включи свет", "Включи музыку", "Включи мой плейлист", "Отключись через 15 минут" и так далее.
|
|
117
120
|
|
package/nodes/get.html
CHANGED
|
@@ -39,7 +39,7 @@
|
|
|
39
39
|
$.getJSON('yandexdevices_'+config.id,function(data) {
|
|
40
40
|
data.devices.forEach(device => {
|
|
41
41
|
selector.append(`<option value="${device.id}">
|
|
42
|
-
${device.name}(${device.id})
|
|
42
|
+
${device.name} (${device.id})
|
|
43
43
|
</option>`)
|
|
44
44
|
$(`#node-input-station_id :contains(${currentId})`).attr("selected", "selected");
|
|
45
45
|
|
|
@@ -61,20 +61,26 @@
|
|
|
61
61
|
<style>
|
|
62
62
|
.label-long {min-width: 150px;width: 20%;}
|
|
63
63
|
.online {display: inline-block; width: auto; vertical-align: middle;}
|
|
64
|
+
/* msg.*-под-подпись — под основной надписью, не растягивает label (основная
|
|
65
|
+
надпись центрируется по строке штатно) */
|
|
66
|
+
.form-horizontal label{position: relative;}
|
|
67
|
+
.form-horizontal label > div.red-ui-debug-msg-type-string{
|
|
68
|
+
position: absolute; left: 0; top: 100%; margin: 0;
|
|
69
|
+
}
|
|
64
70
|
</style>
|
|
65
71
|
|
|
66
72
|
|
|
67
73
|
<div class="form-row">
|
|
68
|
-
<label for="node-input-name"><i class="fa fa-bookmark"></i>Name</label>
|
|
74
|
+
<label for="node-input-name"><i class="fa fa-bookmark"></i> <span>Name</span></label>
|
|
69
75
|
<input type="text" id="node-input-name" placeholder="">
|
|
70
76
|
</div>
|
|
71
77
|
<div class="form-row">
|
|
72
|
-
<label for="node-input-token"><i class="fa fa-globe"></i>Login</label>
|
|
78
|
+
<label for="node-input-token"><i class="fa fa-globe"></i> <span>Login</span></label>
|
|
73
79
|
<input type="text" id="node-input-token" placeholder="Token">
|
|
74
80
|
</div>
|
|
75
81
|
<div class="form-row">
|
|
76
|
-
<label for="node-input-station_id"><i class="fa fa-database">Station</
|
|
77
|
-
<div style="display: inline-block;position: relative;width: 70%;height:
|
|
82
|
+
<label for="node-input-station_id" style="padding-top: 7px;"><i class="fa fa-database"></i> <span>Station</span></label>
|
|
83
|
+
<div style="display: inline-block;position: relative;width: 70%;height: 34px;vertical-align: top;">
|
|
78
84
|
<div style="position: absolute;left: 0px; right: 40px;">
|
|
79
85
|
<select id="node-input-station_id" data-single="true" style="width: 100%"></select>
|
|
80
86
|
</div>
|
|
@@ -84,8 +90,8 @@
|
|
|
84
90
|
</div>
|
|
85
91
|
</div>
|
|
86
92
|
<div class="form-row">
|
|
87
|
-
<label for="node-input-output"><i class="fa fa-arrow-circle-o-left">Output</
|
|
88
|
-
<div style="display: inline-block;position: relative;width: 70%;height:
|
|
93
|
+
<label for="node-input-output" style="padding-top: 7px;"><i class="fa fa-arrow-circle-o-left"></i> <span>Output</span></label>
|
|
94
|
+
<div style="display: inline-block;position: relative;width: 70%;height: 34px;vertical-align: top;">
|
|
89
95
|
<div style="position: absolute;left: 0px; right: 0px;">
|
|
90
96
|
<select id="node-input-output" data-single="true" style="width: 100%">
|
|
91
97
|
<option value="status">Full status Message</option>
|
|
@@ -95,8 +101,8 @@
|
|
|
95
101
|
</div>
|
|
96
102
|
</div>
|
|
97
103
|
<div class="form-row" id="node-homekitFormat">
|
|
98
|
-
<label for="node-input-homekitFormat"><i class="fa fa-arrow-circle-o-left">Homekit
|
|
99
|
-
<div style="display: inline-block;position: relative;width: 70%;height:
|
|
104
|
+
<label for="node-input-homekitFormat" style="padding-top: 7px;"><i class="fa fa-arrow-circle-o-left"></i> <span>Homekit</span></label>
|
|
105
|
+
<div style="display: inline-block;position: relative;width: 70%;height: 34px;vertical-align: top;">
|
|
100
106
|
<div style="position: absolute;left: 0px; right: 0px;">
|
|
101
107
|
<select id="node-input-homekitFormat" data-single="true" style="width: 100%">
|
|
102
108
|
<option value="speaker">Smart Speaker</option>
|
|
@@ -106,8 +112,8 @@
|
|
|
106
112
|
</div>
|
|
107
113
|
</div>
|
|
108
114
|
<div class="form-row">
|
|
109
|
-
<label for='node-input-debugFlag'><i class='fa fa-share-square'>Debug</
|
|
110
|
-
<input type="checkbox" id="node-input-debugFlag" checked="checked" style="display: inline-block; width: auto; vertical-align:
|
|
115
|
+
<label for='node-input-debugFlag'><i class='fa fa-share-square'></i> <span>Debug</span></label>
|
|
116
|
+
<input type="checkbox" id="node-input-debugFlag" checked="checked" style="display: inline-block; width: auto; vertical-align: middle;">
|
|
111
117
|
</div>
|
|
112
118
|
</script>
|
|
113
119
|
|
package/nodes/in.html
CHANGED
|
@@ -43,20 +43,24 @@
|
|
|
43
43
|
$.getJSON('yandexdevices_'+config.id,function(data) {
|
|
44
44
|
data.devices.forEach(device => {
|
|
45
45
|
selector.append(`<option value="${device.id}">
|
|
46
|
-
${device.name}(${device.id})
|
|
46
|
+
${device.name} (${device.id})
|
|
47
47
|
</option>`)
|
|
48
48
|
$(`#node-input-station_id :contains(${currentId})`).attr("selected", "selected");
|
|
49
49
|
});
|
|
50
50
|
});
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
51
|
+
// Строка "Homekit" показывается только в режиме HomeKit. Применяем её
|
|
52
|
+
// сразу при открытии (значения уже восстановлены из сохранённой ноды)
|
|
53
|
+
// и на каждое изменение Output. Только обработчик change не гарантирует
|
|
54
|
+
// стабильное состояние при повторном открытии: Node-RED сам триггерит
|
|
55
|
+
// 'change' при восстановлении значений, и до него строка мигает
|
|
56
|
+
// (видна по шаблону), а затем прячется не от сохранённого значения.
|
|
57
|
+
// Чекбокс "Unique messages" всегда видим: его состояние сохраняется
|
|
58
|
+
// независимо от режима Output.
|
|
59
|
+
function applyOutputMode() {
|
|
60
|
+
$('#node-homekitFormat').toggle($('#node-input-output').val() == 'homekit');
|
|
61
|
+
}
|
|
62
|
+
$('#node-input-output').on('change', applyOutputMode);
|
|
63
|
+
applyOutputMode();
|
|
60
64
|
}
|
|
61
65
|
</script>
|
|
62
66
|
|
|
@@ -64,20 +68,26 @@
|
|
|
64
68
|
<style>
|
|
65
69
|
.label-long {min-width: 150px;width: 20%;}
|
|
66
70
|
.online {display: inline-block; width: auto; vertical-align: middle;}
|
|
71
|
+
/* msg.*-под-подпись — под основной надписью, не растягивает label (основная
|
|
72
|
+
надпись центрируется по строке штатно) */
|
|
73
|
+
.form-horizontal label{position: relative;}
|
|
74
|
+
.form-horizontal label > div.red-ui-debug-msg-type-string{
|
|
75
|
+
position: absolute; left: 0; top: 100%; margin: 0;
|
|
76
|
+
}
|
|
67
77
|
</style>
|
|
68
78
|
|
|
69
79
|
|
|
70
80
|
<div class="form-row">
|
|
71
|
-
<label for="node-input-name"><i class="fa fa-bookmark"></i>Name</label>
|
|
81
|
+
<label for="node-input-name"><i class="fa fa-bookmark"></i> <span>Name</span></label>
|
|
72
82
|
<input type="text" id="node-input-name" placeholder="">
|
|
73
83
|
</div>
|
|
74
84
|
<div class="form-row">
|
|
75
|
-
<label for="node-input-token"><i class="fa fa-globe"></i>Login</label>
|
|
85
|
+
<label for="node-input-token"><i class="fa fa-globe"></i> <span>Login</span></label>
|
|
76
86
|
<input type="text" id="node-input-token" placeholder="Token">
|
|
77
87
|
</div>
|
|
78
88
|
<div class="form-row">
|
|
79
|
-
<label for="node-input-station_id"><i class="fa fa-database">Station</
|
|
80
|
-
<div style="display: inline-block;position: relative;width: 70%;height:
|
|
89
|
+
<label for="node-input-station_id" style="padding-top: 7px;"><i class="fa fa-database"></i> <span>Station</span></label>
|
|
90
|
+
<div style="display: inline-block;position: relative;width: 70%;height: 34px;vertical-align: top;">
|
|
81
91
|
<div style="position: absolute;left: 0px; right: 40px;">
|
|
82
92
|
<select id="node-input-station_id" data-single="true" style="width: 100%"></select>
|
|
83
93
|
</div>
|
|
@@ -87,8 +97,8 @@
|
|
|
87
97
|
</div>
|
|
88
98
|
</div>
|
|
89
99
|
<div class="form-row">
|
|
90
|
-
<label for="node-input-output"><i class="fa fa-arrow-circle-o-left">Output</
|
|
91
|
-
<div style="display: inline-block;position: relative;width: 70%;height:
|
|
100
|
+
<label for="node-input-output" style="padding-top: 7px;"><i class="fa fa-arrow-circle-o-left"></i> <span>Output</span></label>
|
|
101
|
+
<div style="display: inline-block;position: relative;width: 70%;height: 34px;vertical-align: top;">
|
|
92
102
|
<div style="position: absolute;left: 0px; right: 0px;">
|
|
93
103
|
<select id="node-input-output" data-single="true" style="width: 100%">
|
|
94
104
|
<option value="status">Full status Message</option>
|
|
@@ -97,9 +107,9 @@
|
|
|
97
107
|
</div>
|
|
98
108
|
</div>
|
|
99
109
|
</div>
|
|
100
|
-
<div class="form-row" id="node-homekitFormat">
|
|
101
|
-
<label for="node-input-homekitFormat"><i class="fa fa-arrow-circle-o-left">Homekit
|
|
102
|
-
<div style="display: inline-block;position: relative;width: 70%;height:
|
|
110
|
+
<div class="form-row" id="node-homekitFormat" style="display: none;">
|
|
111
|
+
<label for="node-input-homekitFormat" style="padding-top: 7px;"><i class="fa fa-arrow-circle-o-left"></i> <span>Homekit</span></label>
|
|
112
|
+
<div style="display: inline-block;position: relative;width: 70%;height: 34px;vertical-align: top;">
|
|
103
113
|
<div style="position: absolute;left: 0px; right: 0px;">
|
|
104
114
|
<select id="node-input-homekitFormat" data-single="true" style="width: 100%">
|
|
105
115
|
<option value="speaker">Smart Speaker</option>
|
|
@@ -109,12 +119,12 @@
|
|
|
109
119
|
</div>
|
|
110
120
|
</div>
|
|
111
121
|
<div class="form-row" id="node-unique">
|
|
112
|
-
<label for='node-input-uniqueFlag' class="label-long"><i class='fa fa-first-order'>Unique messages</
|
|
113
|
-
<input type="checkbox" id="node-input-uniqueFlag" checked="checked" style="display: inline-block; width: auto; vertical-align:
|
|
122
|
+
<label for='node-input-uniqueFlag' class="label-long"><i class='fa fa-first-order'></i> <span>Unique messages</span></label>
|
|
123
|
+
<input type="checkbox" id="node-input-uniqueFlag" checked="checked" style="display: inline-block; width: auto; vertical-align: middle;">
|
|
114
124
|
</div>
|
|
115
125
|
<div class="form-row">
|
|
116
|
-
<label for='node-input-debugFlag'
|
|
117
|
-
<input type="checkbox" id="node-input-debugFlag" checked="checked" style="display: inline-block; width: auto; vertical-align:
|
|
126
|
+
<label for='node-input-debugFlag' class="label-long"><i class='fa fa-share-square'></i> <span>Debug</span></label>
|
|
127
|
+
<input type="checkbox" id="node-input-debugFlag" checked="checked" style="display: inline-block; width: auto; vertical-align: middle;">
|
|
118
128
|
</div>
|
|
119
129
|
</script>
|
|
120
130
|
|
package/nodes/in.js
CHANGED
|
@@ -24,11 +24,13 @@ module.exports = function(RED) {
|
|
|
24
24
|
|
|
25
25
|
function sendMessage(message){
|
|
26
26
|
//debugMessage(JSON.stringify(message));
|
|
27
|
-
|
|
27
|
+
// «Unique messages»: не дублируем сообщение, если оно совпало с предыдущим.
|
|
28
|
+
// Работает в обоих режимах Output (status/homekit) — чекбокс всегда видим в форме
|
|
29
|
+
if (node.uniqueFlag) {
|
|
28
30
|
if ((JSON.stringify(node.lastMessage.payload) != JSON.stringify(message.payload))) {
|
|
29
31
|
node.send(message)
|
|
30
32
|
node.lastMessage = message
|
|
31
|
-
debugMessage(`Sended message
|
|
33
|
+
debugMessage(`Sended message: ${JSON.stringify(message)}`);
|
|
32
34
|
|
|
33
35
|
}
|
|
34
36
|
} else {
|
|
@@ -37,7 +39,13 @@ module.exports = function(RED) {
|
|
|
37
39
|
}
|
|
38
40
|
node.onMessage = function(data){
|
|
39
41
|
//debugMessage(JSON.stringify(data));
|
|
40
|
-
|
|
42
|
+
const message = stationHelper.preparePayload(node, data);
|
|
43
|
+
//Кто источник события: имя станции (из deviceList login-ноды) и имя этой IN-ноды
|
|
44
|
+
const device = (node.controller && node.controller.deviceList)
|
|
45
|
+
? node.controller.deviceList.find(d => d.id === node.station) : undefined;
|
|
46
|
+
message.station = device ? device.name : node.station;
|
|
47
|
+
message._node = node.name || node.id;
|
|
48
|
+
sendMessage(message);
|
|
41
49
|
}
|
|
42
50
|
node.onStatus = function(data) {
|
|
43
51
|
if (data) {
|
package/nodes/local-out.html
CHANGED
|
@@ -99,7 +99,7 @@
|
|
|
99
99
|
$.getJSON('yandexdevices_' + config.id, function(data) {
|
|
100
100
|
data.devices.forEach(device => {
|
|
101
101
|
selector.append(`<option value="${device.id}">
|
|
102
|
-
${device.name}(${device.id})
|
|
102
|
+
${device.name} (${device.id})
|
|
103
103
|
</option>`);
|
|
104
104
|
$(`#node-input-station_id :contains(${currentId})`).attr('selected', 'selected');
|
|
105
105
|
});
|
|
@@ -151,6 +151,12 @@
|
|
|
151
151
|
display: inline-block;
|
|
152
152
|
width: auto;
|
|
153
153
|
vertical-align: middle;
|
|
154
|
+
}
|
|
155
|
+
/* msg.*-под-подпись — под основной надписью, не растягивает label (основная
|
|
156
|
+
надпись центрируется по строке штатно) */
|
|
157
|
+
.form-horizontal label{position: relative;}
|
|
158
|
+
.form-horizontal label > div.red-ui-debug-msg-type-string{
|
|
159
|
+
position: absolute; left: 0; top: 100%; margin: 0;
|
|
154
160
|
}
|
|
155
161
|
</style>
|
|
156
162
|
|
|
@@ -163,8 +169,8 @@
|
|
|
163
169
|
<input type="text" id="node-input-token" placeholder="">
|
|
164
170
|
</div>
|
|
165
171
|
<div class="form-row">
|
|
166
|
-
<label for="node-input-station_id"><i class="fa fa-database"></i> <span data-i18n="label.station"></span></label>
|
|
167
|
-
<div style="display: inline-block;position: relative;width: 70%;height:
|
|
172
|
+
<label for="node-input-station_id" style="padding-top: 7px;"><i class="fa fa-database"></i> <span data-i18n="label.station"></span></label>
|
|
173
|
+
<div style="display: inline-block;position: relative;width: 70%;height: 34px;vertical-align: top;">
|
|
168
174
|
<div style="position: absolute;left: 0; right: 40px;">
|
|
169
175
|
<select id="node-input-station_id" data-single="true" style="width: 100%"></select>
|
|
170
176
|
</div>
|
|
@@ -175,8 +181,8 @@
|
|
|
175
181
|
</div>
|
|
176
182
|
</div>
|
|
177
183
|
<div class="form-row">
|
|
178
|
-
<label for="node-input-input"><i class="fa fa-arrow-circle-o-right"></i> <span data-i18n="label.command"></span></label>
|
|
179
|
-
<div style="display: inline-block;position: relative;width: 70%;height:
|
|
184
|
+
<label for="node-input-input" style="padding-top: 7px;"><i class="fa fa-arrow-circle-o-right"></i> <span data-i18n="label.command"></span></label>
|
|
185
|
+
<div style="display: inline-block;position: relative;width: 70%;height: 34px;vertical-align: top;">
|
|
180
186
|
<div style="position: absolute;left: 0px; right: 0px;">
|
|
181
187
|
<select id="node-input-input" data-single="true" style="width: 100%">
|
|
182
188
|
<option value="command" data-i18n="command.player"></option>
|
|
@@ -185,6 +191,7 @@
|
|
|
185
191
|
<option value="homekit" data-i18n="command.homekit"></option>
|
|
186
192
|
<option value="stopListening" data-i18n="command.stop_listening"></option>
|
|
187
193
|
<option value="raw" data-i18n="command.raw"></option>
|
|
194
|
+
<option value="reinit" data-i18n="command.reinit"></option>
|
|
188
195
|
</select>
|
|
189
196
|
</div>
|
|
190
197
|
</div>
|
|
@@ -193,7 +200,7 @@
|
|
|
193
200
|
<!--for homekit-->
|
|
194
201
|
<div class="form-row command_options command_options-homekit">
|
|
195
202
|
<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>
|
|
196
|
-
<input type="text" id="node-input-noTrack" data-i18n="[placeholder]placeholder.play_music" style="display: inline-block;left: 0px; right: 0px; width:
|
|
203
|
+
<input type="text" id="node-input-noTrack" data-i18n="[placeholder]placeholder.play_music" style="display: inline-block;left: 0px; right: 0px; width: calc(70% - 50px); vertical-align: middle;">
|
|
197
204
|
</div>
|
|
198
205
|
|
|
199
206
|
<!--for tts-->
|
|
@@ -203,13 +210,12 @@
|
|
|
203
210
|
<input type="hidden" id="node-input-payloadType">
|
|
204
211
|
</div>
|
|
205
212
|
<div class="form-row command_options command_options-tts">
|
|
206
|
-
<label class="label" for='node-input-ttsVoice'>
|
|
213
|
+
<label class="label" for='node-input-ttsVoice' style="padding-top: 7px;">
|
|
207
214
|
<i class='fa fa-user'></i> <span data-i18n="label.voice"></span>
|
|
208
|
-
<div class="red-ui-debug-msg-type-string" style="font-size: 10px;">msg.voice</div></label>
|
|
209
|
-
|
|
210
|
-
<div style="display: inline-block;position: relative;width: 70%;height: 30px;">
|
|
215
|
+
<div class="red-ui-debug-msg-type-string" style="font-size: 10px; line-height: 1em;">msg.voice</div></label>
|
|
216
|
+
<div style="display: inline-block;position: relative;width: 70%;height: 34px;vertical-align: top;">
|
|
211
217
|
<div style="position: absolute;left: 0px; right: 0px;">
|
|
212
|
-
<select id="node-input-ttsVoice" style="width: 100%;vertical-align:
|
|
218
|
+
<select id="node-input-ttsVoice" style="width: 100%;vertical-align: middle;">
|
|
213
219
|
<option value="" data-i18n="voice.default"></option>
|
|
214
220
|
<!-- <option value="alena" data-i18n="voice.alena"></option>-->
|
|
215
221
|
<option value="alyss" data-i18n="voice.alyss"></option>
|
|
@@ -243,47 +249,42 @@
|
|
|
243
249
|
</div>
|
|
244
250
|
</div>
|
|
245
251
|
<div class="form-row command_options command_options-tts">
|
|
246
|
-
<label for="node-input-ttsEffect" class="label l-width" style="
|
|
252
|
+
<label for="node-input-ttsEffect" class="label l-width" style="padding-top: 7px;">
|
|
247
253
|
<i class="fa fa-magic"></i> <span data-i18n="label.effect"></span>
|
|
248
|
-
<div class="red-ui-debug-msg-type-string" style="font-size: 10px;">msg.effect</div></label>
|
|
249
|
-
|
|
250
|
-
<input type="text" id="node-input-ttsEffect">
|
|
254
|
+
<div class="red-ui-debug-msg-type-string" style="font-size: 10px; line-height: 1em;">msg.effect</div></label>
|
|
255
|
+
<input type="text" id="node-input-ttsEffect" style="width: 70%;">
|
|
251
256
|
</div>
|
|
252
257
|
<div class="form-row command_options command_options-tts">
|
|
253
258
|
<label for="node-input-volume" class="label label-long">
|
|
254
259
|
<i class="fa fa-volume-up"></i> <span data-i18n="label.volume"></span>
|
|
255
|
-
<div class="red-ui-debug-msg-type-string" style="font-size: 10px;">msg.volume</div></label>
|
|
256
|
-
|
|
257
|
-
<input type="checkbox" id="node-input-volumeFlag" style="display: inline-block; width: auto; vertical-align: top;">
|
|
260
|
+
<div class="red-ui-debug-msg-type-string" style="font-size: 10px; line-height: 1em;">msg.volume</div></label>
|
|
261
|
+
<input type="checkbox" id="node-input-volumeFlag" style="display: inline-block; width: auto; vertical-align: middle;">
|
|
258
262
|
<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;">
|
|
259
263
|
<div id="range-label" class='online'><span id="volume-level" class="online"></span><span class="online">%</span></div>
|
|
260
264
|
</div>
|
|
261
265
|
<div class="form-row command_options command_options-tts">
|
|
262
266
|
<label for="node-input-whisper" class="label label-long">
|
|
263
267
|
<i class="fa fa-deaf"></i> <span data-i18n="label.whisper"></span>
|
|
264
|
-
<div class="red-ui-debug-msg-type-string" style="font-size: 10px;">msg.whisper</div></label>
|
|
265
|
-
|
|
266
|
-
<input type="checkbox" id="node-input-whisper" style="display: inline-block; width: auto; vertical-align: top;">
|
|
268
|
+
<div class="red-ui-debug-msg-type-string" style="font-size: 10px; line-height: 1em;">msg.whisper</div></label>
|
|
269
|
+
<input type="checkbox" id="node-input-whisper" style="display: inline-block; width: auto; vertical-align: middle;">
|
|
267
270
|
</div>
|
|
268
271
|
<div class="form-row command_options command_options-tts">
|
|
269
272
|
<label for="node-input-stopListening" class="label label-long">
|
|
270
273
|
<i class="fa fa-deaf"></i> <span data-i18n="label.prevent_listening"></span>
|
|
271
|
-
<div class="red-ui-debug-msg-type-string" style="font-size: 10px;">msg.prevent_listening</div></label>
|
|
272
|
-
|
|
273
|
-
<input type="checkbox" id="node-input-stopListening" style="display: inline-block; width: auto; vertical-align: top;">
|
|
274
|
+
<div class="red-ui-debug-msg-type-string" style="font-size: 10px; line-height: 1em;">msg.prevent_listening</div></label>
|
|
275
|
+
<input type="checkbox" id="node-input-stopListening" style="display: inline-block; width: auto; vertical-align: middle;">
|
|
274
276
|
</div>
|
|
275
277
|
<div class="form-row command_options command_options-tts">
|
|
276
278
|
<label for="node-input-pauseMusic" class="label label-long">
|
|
277
279
|
<i class="fa fa-pause"></i> <span data-i18n="label.pause_while_tts"></span>
|
|
278
|
-
<div class="red-ui-debug-msg-type-string" style="font-size: 10px;">msg.pause_music</div></label>
|
|
279
|
-
|
|
280
|
-
<input type="checkbox" id="node-input-pauseMusic" style="display: inline-block; width: auto; vertical-align: top;">
|
|
280
|
+
<div class="red-ui-debug-msg-type-string" style="font-size: 10px; line-height: 1em;">msg.pause_music</div></label>
|
|
281
|
+
<input type="checkbox" id="node-input-pauseMusic" style="display: inline-block; width: auto; vertical-align: middle;">
|
|
281
282
|
</div>
|
|
282
283
|
|
|
283
284
|
|
|
284
285
|
<div class="form-row" style="vertical-align:bottom;">
|
|
285
286
|
<label for='node-input-debugFlag' class="label-long"><i class='fa fa-share-square'></i> <span data-i18n="label.debug"></span></label>
|
|
286
|
-
<input type="checkbox" id="node-input-debugFlag" checked="checked" style="display: inline-block; width: auto; vertical-align:
|
|
287
|
+
<input type="checkbox" id="node-input-debugFlag" checked="checked" style="display: inline-block; width: auto; vertical-align: middle;">
|
|
287
288
|
</div>
|
|
288
289
|
</script>
|
|
289
290
|
|
package/nodes/local-out.js
CHANGED
|
@@ -27,6 +27,22 @@ module.exports = function(RED) {
|
|
|
27
27
|
node.on('input', (input) => {
|
|
28
28
|
debugMessage(`input: ${JSON.stringify(input)}`)
|
|
29
29
|
|
|
30
|
+
//reinit: полный сброс соединения с колонкой без деплоя Node-RED.
|
|
31
|
+
//Срабатывает в двух случаях:
|
|
32
|
+
// 1) во вход ноды выбрана команда "reinit" (msg.payload не используется);
|
|
33
|
+
// 2) в любом режиме, если в сообщении msg.reinit === true.
|
|
34
|
+
//В обоих случаях обычная обработка сообщения пропускается,
|
|
35
|
+
//т.к. соединение в этот момент ещё не поднято.
|
|
36
|
+
if ('reinit' === node.input || input.reinit === true) {
|
|
37
|
+
if (node.station && node.controller && node.controller.reinitDevice) {
|
|
38
|
+
let result = node.controller.reinitDevice(node.station, node.id);
|
|
39
|
+
debugMessage(`Reinit ${node.station}: ${result}`);
|
|
40
|
+
} else {
|
|
41
|
+
debugMessage('Reinit: no station or controller node');
|
|
42
|
+
}
|
|
43
|
+
return;
|
|
44
|
+
}
|
|
45
|
+
|
|
30
46
|
if (node.station) {
|
|
31
47
|
var data = {};
|
|
32
48
|
//data.payload = input.payload;
|