Update README token guide and refine WB rule behavior

This commit is contained in:
2026-04-02 12:12:00 +03:00
parent 2c8f9f32b9
commit 5f61142941
3 changed files with 79 additions and 15 deletions

View File

@@ -11,6 +11,7 @@
- [Быстрый старт](#быстрый-старт)
- [Полная установка](#полная-установка)
- [Токен](#токен)
- [Как получить токен](#как-получить-токен)
- [CLI](#cli)
- [Примеры wb-rules](#примеры-wb-rules)
- [Прямые Python-команды](#прямые-python-команды)
@@ -89,9 +90,15 @@ alice/
## Быстрый старт
```bash
cd /путь/к/распакованному/репозиторию
apt update
apt install -y git python3 python3-venv python3-pip
mkdir -p /opt/shd/plugins
cd /opt/shd/plugins
git clone https://git.xyz.su/shd/local_yandex_station.git alice
cd alice
chmod +x *.sh
./install.sh
./install.sh --in-place
printf %s 'YANDEX_OAUTH_TOKEN' > /opt/shd/plugins/alice/token.txt
chmod 600 /opt/shd/plugins/alice/token.txt
@@ -100,7 +107,10 @@ cd /opt/shd/plugins/alice
./cli.sh columns
./cli.sh loxone
./cli.sh wb-rules
./cli.sh web
systemctl enable --now shd-alice.service shd-alice-plugin.service
curl -sS http://127.0.0.1:9124/health
curl -sS http://127.0.0.1:9140/api/status
```
После этого web UI обычно доступен по адресу:
@@ -120,17 +130,20 @@ sudo apt install -y python3 python3-venv python3-pip
Для более удобной синхронизации в `/opt` желателен `rsync`, но без него установка тоже работает.
### 2. Распаковать проект и запустить установку
### 2. Клонировать проект в рабочий путь и запустить установку
```bash
cd /путь/к/распакованному/репозиторию
mkdir -p /opt/shd/plugins
cd /opt/shd/plugins
git clone https://git.xyz.su/shd/local_yandex_station.git alice
cd alice
chmod +x *.sh
./install.sh
./install.sh --in-place
```
Что делает `install.sh`:
- копирует проект в `/opt/shd/plugins/alice`;
- при запуске с `--in-place` работает прямо из `/opt/shd/plugins/alice`;
- создаёт `.venv`, если его нет;
- ставит зависимости из `requirements.txt`;
- создаёт каталоги `data/`, `configs/loxone/`, `configs/wb-rules/`;
@@ -146,11 +159,12 @@ printf %s 'YANDEX_OAUTH_TOKEN' > /opt/shd/plugins/alice/token.txt
chmod 600 /opt/shd/plugins/alice/token.txt
```
Или через CLI/web-команду:
Разовый запуск через переменную окружения (не для постоянного хранения):
```bash
cd /opt/shd/plugins/alice
./cli.sh web --token 'YANDEX_OAUTH_TOKEN'
export YANDEX_TOKEN='YANDEX_OAUTH_TOKEN'
./cli.sh columns
unset YANDEX_TOKEN
```
### 4. Обновить список станций
@@ -188,12 +202,32 @@ sudo systemctl enable --now shd-alice.service shd-alice-plugin.service
/opt/shd/plugins/alice/token.txt
```
Рекомендация по безопасности:
- для постоянной работы храни токен только в `token.txt` с правами `600`;
- `YANDEX_TOKEN` используй только временно для разовых команд, затем делай `unset YANDEX_TOKEN`.
Если токен неверный, при обновлении списка станций будет ошибка:
```text
YANDEX_OAUTH_TOKEN invalid: update token and retry
```
## Как получить токен
Создать собственное OAuth-приложение для этого сценария нельзя. Обычно используют токен,
полученный через официальные клиенты Яндекс.Музыки.
Рабочие варианты:
- Веб-сервис (может работать не для всех аккаунтов): [music-yandex-bot.ru](https://music-yandex-bot.ru/)
- Android-приложение (APK): [MarshalX/yandex-music-token releases](https://github.com/MarshalX/yandex-music-token/releases)
- Расширение для Google Chrome: [Yandex Music Token (Chrome Web Store)](https://chrome.google.com/webstore/detail/yandex-music-token/lcbjeookjibfhjjopieifgjnhlegmkib)
- Расширение для Mozilla Firefox: [Yandex Music Token (Firefox Add-ons)](https://addons.mozilla.org/en-US/firefox/addon/yandex-music-token/)
Во всех вариантах выше итог один: получить и скопировать OAuth-токен.
Исходный код инструментов открыт: [github.com/MarshalX/yandex-music-token](https://github.com/MarshalX/yandex-music-token).
## CLI
Основной интерфейс из терминала — `cli.sh`.
@@ -322,11 +356,11 @@ configs/wb-rules/wb-rules-examples.js
Как привязать к конкретной колонке:
1. возьми `id` нужной станции из `data/stations.json`;
1. возьми IP нужной станции (или `id` из `data/stations.json`);
2. подставь его в строку:
```js
var STATION = "PUT_EXACT_STATION_ID_HERE";
var STATION = "PUT_STATION_IP_HERE";
```
3. скопируй файл в `/etc/wb-rules/` и перезапусти `wb-rules`.

View File

@@ -479,6 +479,25 @@ function _enc(v) {{
return encodeURIComponent(String(v === undefined || v === null ? "" : v));
}}
function _clampVolume(v, defVal) {{
var n = parseInt(v, 10);
if (isNaN(n)) n = defVal;
if (isNaN(n)) n = 35;
if (n < 0) n = 0;
if (n > 100) n = 100;
return n;
}}
function _ttsRestoreDelayMs(text) {{
var clean = String(text || "").trim();
if (!clean) return 3500;
var chars = clean.length;
var words = clean.split(/\\s+/).filter(Boolean).length;
var speechSec = Math.max(words / 2.4, chars / 14.0);
var delaySec = Math.max(3.5, Math.min(20.0, speechSec + 1.5));
return Math.round(delaySec * 1000);
}}
defineVirtualDevice(DEVICE_ID, {{
title: DEVICE_TITLE,
cells: {{
@@ -507,7 +526,18 @@ defineRule(DEVICE_ID + "_tts_send", {{
if (!newValue) return;
var txt = String(dev[DEVICE_ID + "/tts_text"] || "").trim();
if (!txt) return;
_apiGet("/api/exec?action=tts&station=" + _enc(STATION_SELECTOR) + "&text=" + _enc(txt) + "&volume=35", function(){{}});
var targetVolume = _clampVolume(dev[DEVICE_ID + "/volume"], 35);
var prevVolumeRaw = dev[DEVICE_ID + "/current_volume"];
var prevVolume = _clampVolume(prevVolumeRaw, targetVolume);
_apiGet(
"/api/exec?action=tts&station=" + _enc(STATION_SELECTOR) + "&text=" + _enc(txt) + "&volume=" + _enc(targetVolume),
function(){{}}
);
if (prevVolume !== targetVolume) {{
setTimeout(function() {{
_apiGet("/api/exec?action=volume&station=" + _enc(STATION_SELECTOR) + "&level=" + _enc(prevVolume), function(){{}});
}}, _ttsRestoreDelayMs(txt));
}}
}}
}});

View File

@@ -1,12 +1,12 @@
// Примеры wb-rules для ОДНОЙ выбранной станции.
//
// Как использовать:
// 1) подставь id станции из data/stations.json в переменную STATION;
// 1) подставь IP станции (или station_id) в переменную STATION;
// 2) скопируй файл в /etc/wb-rules/;
// 3) перезапусти сервис wb-rules.
var API_BASE = "http://127.0.0.1:9124";
var STATION = "PUT_EXACT_STATION_ID_HERE";
var STATION = "PUT_STATION_IP_HERE";
function enc(v) {
return encodeURIComponent(String(v === undefined || v === null ? "" : v));