Files
obsidian-vault/family/how-to/magic4pc-webos.md
T

222 lines
12 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Magic4PC — WebOS Client
Управление LG MagicRemote как мышью/клавиатурой на HTPC через Bazzite.
## Архитектура
- **TV (WebOS)** — app `me.wouterdek.magic4pc` + JS-сервис `me.wouterdek.magic4pc.service`
- App: React/Enact UI, слушает кнопки пульта, отправляет в сервис через luna
- Сервис: Node.js, бродкастит UDP, принимает подключение от Go-клиента на HTPC
- **HTPC (Bazzite)** — Go-клиент `~/magic4pc/`, сервис `magic4pc.service`
- Получает UDP-пакеты от TV, инжектирует ввод через `/dev/uinput`
- `inputBackKey()` → Esc в gamescope, x1 в KDE
- Репо: https://github.com/mallexxx/magic4pc_altclient (ветка `main`)
## Исходники
| Компонент | Путь |
|-----------|------|
| WebOS UI | `~/Developer/magic4pc/webos/src/views/MainPanel.js` |
| WebOS сервис | `~/Developer/magic4pc/webos/service/m4p_service.js` |
| Go клиент | `~/Developer/magic4pc_altclient/` |
| HTPC бинарник | `~/magic4pc/magic4pc` |
| HTPC сервис | `~/.config/systemd/user/magic4pc.service` (HTPC) |
| run.sh | `~/magic4pc/run.sh` (HTPC) |
## Кнопки пульта (keyCode)
| Код | Кнопка | Действие |
|-----|--------|----------|
| 406 | 🔵 Синяя | Открыть панель настроек |
| 461 | Back | Esc (gamescope) / x1 (KDE) |
| 458 | Guide | системный (не перехватывается) |
| 403 | 🔴 Красная | передаётся на HTPC |
| 415 | Play | передаётся на HTPC |
| 19 | Pause | передаётся на HTPC |
## Панель настроек (синяя кнопка)
- **Статус** — Connected to IP:port / Waiting / Service disabled
- **v1.1.0 (YYYY-MM-DD HH:MM)** — версия + дата сборки справа от статуса
- **Input source** — выбор HDMI входа
- **Enable / Disable** — старт/стоп сервиса
- **Default app on exit** — приложение которое запускается при выходе из magic4pc (None / Last used / конкретное)
- **Show Log / Hide Log** — лог событий и ошибок поверх видео
## Версия сборки
Версия отображается как `1.1.0 (YYYY-MM-DD HH:MM)` — дата инжектируется webpack автоматически при каждой сборке:
```js
// config/webpack.config.js
'process.env.BUILD_DATE': JSON.stringify(new Date().toISOString().slice(0, 16).replace('T', ' '))
```
## Сборка WebOS app
```bash
cd ~/Developer/magic4pc/webos
NODE_OPTIONS=--openssl-legacy-provider npm run build
```
Требует `--openssl-legacy-provider` — старый webpack несовместим с Node 25.
## Сборка IPK
```bash
cd ~/Developer/magic4pc/webos
NODE_OPTIONS=--openssl-legacy-provider npm run build
/Users/admin/webOS_TV_SDK/CLI/bin/ares-package dist/ service/ --outdir .
# Создаёт me.wouterdek.magic4pc_1.1.0_all.ipk
```
> ⚠️ `ares-package dist/ service/` — оба аргумента обязательны, иначе сервис не попадёт в IPK.
> `npm run package` = `ares-package -n` (без подписи) — **не использовать**, TV отклоняет IPK.
## Деплой на TV (192.168.1.75)
TV рутован, SSH без пароля: `ssh root@192.168.1.75`
> ⚠️ `luna-send` через SSH не выводит ответ в stdout — нужен PTY через `script`:
> `ssh root@192.168.1.75 "script -q -c \"luna-send -n 1 -f luna://...\" /tmp/o.txt; cat /tmp/o.txt"`
```bash
# 1. Скопировать IPK на TV
scp me.wouterdek.magic4pc_1.1.0_all.ipk root@192.168.1.75:/tmp/magic4pc.ipk
# 2. Закрыть приложение
ssh root@192.168.1.75 "script -q -c \"luna-send -n 1 -f luna://com.webos.service.applicationmanager/closeByAppId '{\\\"id\\\":\\\"me.wouterdek.magic4pc\\\"}'\" /tmp/o.txt; cat /tmp/o.txt"
# 3. Удалить старую версию
ssh root@192.168.1.75 "script -q -c \"luna-send -n 1 -f luna://com.webos.appInstallService/dev/remove '{\\\"id\\\":\\\"me.wouterdek.magic4pc\\\"}'\" /tmp/o.txt; cat /tmp/o.txt"
# 4. Установить новую (через PTY — иначе нет вывода)
ssh root@192.168.1.75 "script -q -c \"luna-send -i -f luna://com.webos.appInstallService/dev/install '{\\\"id\\\":\\\"me.wouterdek.magic4pc\\\",\\\"ipkUrl\\\":\\\"/tmp/magic4pc.ipk\\\",\\\"subscribe\\\":true}'\" /tmp/o.txt; cat /tmp/o.txt"
# Ждать "state": "installed" в выводе
# 5. Запустить
ssh root@192.168.1.75 "script -q -c \"luna-send -n 1 -f luna://com.webos.applicationManager/launch '{\\\"id\\\":\\\"me.wouterdek.magic4pc\\\"}'\" /tmp/o.txt; cat /tmp/o.txt"
```
### Проверка логов сервиса
```bash
ssh root@192.168.1.75 "script -q -c \"luna-send -n 1 -f luna://me.wouterdek.magic4pc.service/query '{}'\" /tmp/o.txt; cat /tmp/o.txt"
```
Ожидаемый результат: `serviceActive: true`, `broadcastAdsActive: true` (или `isConnected: true` если HTPC подключён), в логах — `listApps: returned N apps`.
## Деплой Go-клиента на HTPC
```bash
cd ~/Developer/magic4pc_altclient
GOOS=linux GOARCH=amd64 go build -o magic4pc_new .
scp magic4pc_new bazzite@192.168.1.86:~/magic4pc/
ssh bazzite@192.168.1.86 "
systemctl --user stop magic4pc
mv ~/magic4pc/magic4pc_new ~/magic4pc/magic4pc
systemctl --user start magic4pc
"
```
## HTPC сервис
```bash
ssh bazzite@192.168.1.86 "systemctl --user status magic4pc"
ssh bazzite@192.168.1.86 "systemctl --user restart magic4pc"
```
> `enable` не используется — autostart через EIM на стороне TV.
## Auto-launch при boot/wake
Magic4pc автоматически запускает выбранный app (VK Video, Кинопоиск, last used) при включении TV.
### Логика
- **Boot (полный ребут)** — `/tmp` чистится → нет `/tmp/magic4pc-run-state``freshStart=true` → запускает app
- **Wake (standby→on) с последним активным app** — init.d при Suspend удаляет `run-state` → при wake нет файла → `freshStart=true` → запускает app
- **Wake после HDMI/EIM source** — если последний активный был HDMI (`com.webos.app.hdmi*`) — init.d при Suspend тоже удаляет `run-state` (TODO: можно улучшить), magic4pc по wake не запускает чужой app если пользователь вручную переключился на HDMI перед сном
- **Ручной запуск magic4pc** (пользователь сам открыл) — `run-state = running` уже есть → `freshStart=false` → ничего не запускает ✅
### Файлы persistent storage
Сервис (UID 5078, jail) имеет доступ только к `/tmp` и своей директории:
| Файл | Где | Что |
|------|-----|-----|
| `magic4pc-settings` | `PERSISTENT_DIR/` | Выбранный app: appId / `__last_used__` / `none` |
| `magic4pc-last-app` | `PERSISTENT_DIR/` | Последний foreground app (пишет init.d + сервис) |
| `magic4pc-run-state` | `/tmp/` | `running` = уже запускался после boot/wake |
`PERSISTENT_DIR = /media/developer/apps/usr/palm/services/me.wouterdek.magic4pc.service`
Init.d (root) копирует `last-app` в `PERSISTENT_DIR` при каждом обновлении foreground.
### Init.d скрипт
Файл на TV: `/var/lib/webosbrew/init.d/magic4pc`
Исходник в репо: `tv-scripts/init.d-magic4pc.sh`
**Что делает:**
- При старте: удаляет `/tmp/magic4pc-run-state` (fresh boot)
- `track_foreground` — каждые 3 сек пишет foreground app в `/tmp/magic4pc-last-app` и `PERSISTENT_DIR/magic4pc-last-app`
- `monitor_power` — при Suspend удаляет `run-state` чтобы wake выглядел как fresh start
- Каждые 5 мин обновляет `/tmp/magic4pc-apps.json` (список app для Dropdown)
**Деплой init.d:**
```bash
scp tv-scripts/init.d-magic4pc.sh root@192.168.1.75:/var/lib/webosbrew/init.d/magic4pc
ssh root@192.168.1.75 "chmod +x /var/lib/webosbrew/init.d/magic4pc"
# Изменения применяются после ребута TV (init.d запускается Homebrew Channel при старте)
```
> ⚠️ **Правило**: init.d всегда правится локально в репо (`tv-scripts/init.d-magic4pc.sh`), затем деплоится на TV через `scp`. Никогда не редактировать файл на TV напрямую — изменения не попадут в репо.
### Деплой IPK (правильный способ)
`luna-send` через обычный SSH не выводит ответ — нужен PTY через `script`:
```bash
# 1. Собрать и упаковать
cd ~/Developer/magic4pc/webos
NODE_OPTIONS=--openssl-legacy-provider npm run build
/Users/admin/webOS_TV_SDK/CLI/bin/ares-package dist/ service/ --outdir .
# 2. Скопировать на TV
scp me.wouterdek.magic4pc_1.1.0_all.ipk root@192.168.1.75:/tmp/magic4pc.ipk
# 3. Установить (через PTY — иначе нет вывода)
ssh root@192.168.1.75 "script -q -c \"luna-send -i -f luna://com.webos.appInstallService/dev/install '{\\\"id\\\":\\\"me.wouterdek.magic4pc\\\",\\\"ipkUrl\\\":\\\"/tmp/magic4pc.ipk\\\",\\\"subscribe\\\":true}'\" /tmp/o.txt; cat /tmp/o.txt"
# Ждать "state": "installed" в выводе
# 4. Запустить
ssh root@192.168.1.75 "script -q -c \"luna-send -n 1 -f luna://com.webos.applicationManager/launch '{\\\"id\\\":\\\"me.wouterdek.magic4pc\\\"}'\" /dev/null"
```
> ⚠️ `npm run package` = `ares-package -n` (unsigned) — **не использовать**, TV отклоняет.
> ⚠️ `luna-send` без PTY (`script`) молчит — всегда использовать `script -q -c "..." /tmp/o.txt`.
### Отладка
```bash
# Лог сервиса
ssh root@192.168.1.75 "cat /tmp/m4p_debug.log"
# Текущий выбранный app и last-app
ssh root@192.168.1.75 "cat /media/developer/apps/usr/palm/services/me.wouterdek.magic4pc.service/magic4pc-settings"
ssh root@192.168.1.75 "cat /media/developer/apps/usr/palm/services/me.wouterdek.magic4pc.service/magic4pc-last-app"
# Run-state (есть = уже запускался, нет = fresh start)
ssh root@192.168.1.75 "cat /tmp/magic4pc-run-state"
# Лог init.d
ssh root@192.168.1.75 "cat /tmp/m4p_debug.log | grep 'magic4pc init'"
```
## Известные проблемы
- **Guide (458)** — перехватывается WebOS системно, EIM-регистрация не помогает. Нет решения.
- **listApps** — `applicationManager/dev/listApps` недоступен без dev mode. Используется `applicationManager/listApps`.
- **Self-launch** — magic4pc не должен запускать сам себя. Фильтруется в `checkAutoLaunch` по appId.
- **HDMI как last-app** — init.d трекает foreground включая HDMI sources. При `__last_used__` и последнем активном HDMI — не запустит ничего полезного. Решение: выбрать конкретный app вместо `last_used`.