Add adaptive FPS and honest device reachability during streaming

DDP uses fire-and-forget UDP, so when a WiFi device becomes overwhelmed
by sustained traffic, sends appear successful while the device is
actually unreachable. This adds:

- HTTP liveness probe (GET /json/info, 2s timeout) every 10s during
  streaming, exposed as device_streaming_reachable in target state
- Adaptive FPS (opt-in): exponential backoff when device is unreachable,
  gradual recovery when it stabilizes — finds sustainable send rate
- Honest health checks: removed the lie that forced device_online=true
  during streaming; now runs actual health checks regardless
- Target editor toggle, FPS display shows effective rate when throttled,
  health dot reflects streaming reachability, red highlight when
  unreachable
- Auto-backup scheduling support in settings modal

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-02-26 20:22:58 +03:00
parent f8656b72a6
commit cadef971e7
23 changed files with 873 additions and 21 deletions

View File

@@ -169,6 +169,7 @@
"device.metrics.device_fps": "Частота обновления устройства",
"device.health.online": "Онлайн",
"device.health.offline": "Недоступен",
"device.health.streaming_unreachable": "Недоступен во время стриминга",
"device.health.checking": "Проверка...",
"device.tutorial.start": "Начать обучение",
"device.tip.metadata": "Информация об устройстве (кол-во LED, тип, цветовые каналы) определяется автоматически",
@@ -912,6 +913,8 @@
"targets.brightness_vs.none": "Нет (яркость устройства)",
"targets.min_brightness_threshold": "Мин. порог яркости:",
"targets.min_brightness_threshold.hint": "Если итоговая яркость (яркость пикселей × яркость устройства/источника) ниже этого значения, светодиоды полностью выключаются (0 = отключено)",
"targets.adaptive_fps": "Адаптивный FPS:",
"targets.adaptive_fps.hint": "Автоматически снижает частоту отправки, когда устройство перестаёт отвечать, и постепенно восстанавливает её при стабилизации. Рекомендуется для WiFi-устройств со слабым сигналом.",
"search.open": "Поиск (Ctrl+K)",
"search.placeholder": "Поиск... (Ctrl+K)",
@@ -943,5 +946,25 @@
"settings.restore.error": "Ошибка восстановления",
"settings.restore.restarting": "Сервер перезапускается...",
"settings.restore.restart_timeout": "Сервер не отвечает. Обновите страницу вручную.",
"settings.button.close": "Закрыть"
"settings.button.close": "Закрыть",
"settings.auto_backup.label": "Авто-бэкап",
"settings.auto_backup.hint": "Автоматическое создание периодических резервных копий конфигурации. Старые копии удаляются при превышении максимального количества.",
"settings.auto_backup.enable": "Включить авто-бэкап",
"settings.auto_backup.interval_label": "Интервал",
"settings.auto_backup.max_label": "Макс. копий",
"settings.auto_backup.save": "Сохранить настройки",
"settings.auto_backup.saved": "Настройки авто-бэкапа сохранены",
"settings.auto_backup.save_error": "Не удалось сохранить настройки авто-бэкапа",
"settings.auto_backup.last_backup": "Последний бэкап",
"settings.auto_backup.never": "Никогда",
"settings.saved_backups.label": "Сохранённые копии",
"settings.saved_backups.hint": "Файлы авто-бэкапа на сервере. Скачайте для локального хранения или удалите для освобождения места.",
"settings.saved_backups.empty": "Нет сохранённых копий",
"settings.saved_backups.restore": "Восстановить",
"settings.saved_backups.download": "Скачать",
"settings.saved_backups.delete": "Удалить",
"settings.saved_backups.delete_confirm": "Удалить эту резервную копию?",
"settings.saved_backups.delete_error": "Не удалось удалить копию"
}