# 11 · Устройства (BAS-IP, реле, эмулятор) [← Home](Home.md) Приложение управляет одним или несколькими устройствами открытия через драйверы. Настройка — `config.device` или **Админка → Шлагбаум → Устройства**. ## Драйверы ### `basip` — панель BAS-IP Camdroid (`/api/v0`) Официальный HTTP API панелей BAS-IP ([developers.bas-ip.com](https://developers.bas-ip.com/Camdroid-panels/)): * **логин** → токен устройства (TTL ~1600 с, автоматическое обновление заранее, хранение в БД/файле/кэше на выбор — `device.token.store`); * **открытие замка**: `access/general/lock/open/remote/accepted/{channel}` (endpoint и канал настраиваются, импульс `pulse_ms`); * **статус**: SIP-регистрация, версия прошивки, время панели; * **камера**: `security/ipcam` — snapshot (JPEG), proxy через приложение (скрывает панель от жителей) или прямой MJPEG-поток; * **SIP вкл/выкл**, **перезагрузка** панели; * таймауты/ретраи: `timeout 10 с`, `connect_timeout 4 с`, `retries 2`. ```php 'device' => [ 'driver' => 'basip', 'base_url' => 'http://192.168.1.20/api/v0/', 'login' => 'admin', 'password' => '${secret:DEVICE_PASSWORD}', 'lock' => ['channel' => 1, 'channels' => [1 => 'Main gate']], ], ``` Пароль панели храните шифрованным: `bin/bas-ip secret:set DEVICE_PASSWORD`. Для самоподписанных сертификатов — `verify_tls: false` или свой `ca_bundle`. ### `http-relay` — произвольный HTTP-контроллер Для DIY-реле (ESP32/реле-борды), сторонних шлюзов и «умных» розеток: настраиваются URL/метод/заголовки/тело для open/close/status, ожидаемый ответ, таймауты. Подходит всему, что умеет принимать HTTP. ### `dryrun` — эмулятор Все команды «выполняются», события пишутся, камера — заглушка. Режим для разработки, демо и тестов; `doctor` предупреждает, если эмулятор включён в production. ## Несколько устройств `device.gates` — именованные устройства, наследующие общие настройки: ```php 'gates' => [ 'north' => ['base_url' => 'http://192.168.1.21/api/v0/', 'login' => 'admin', 'password' => '${secret:DEVICE_NORTH_PASSWORD}'], 'parking' => ['driver' => 'http-relay', 'open_url' => 'http://10.0.0.5/relay/2/pulse'], ], ``` В UI и API устройство выбирается параметром `device` (по умолчанию `main`); журнал событий хранит, какое устройство сработало. ## Возможности (capabilities) Драйвер объявляет, что умеет: `open`, `close`, `status`, `snapshot`, `sip`, `reboot`. UI скрывает недоступные кнопки; API `/meta` публикует список. ## Камера и видеопоток Камера **привязана к устройству (шлагбауму)** и настраивается в его карточке (Админка → Шлагбаум → Устройства → «Камера шлагбаума и видеопоток») или в `device.camera.*` / `device.gates..camera.*`: | Режим (`camera.mode`) | Как работает | Когда выбирать | |---|---|---| | `snapshot` (default) | приложение забирает JPEG-кадр у панели (`camera.endpoint`, у BAS-IP — `security/ipcam`) и отдаёт браузеру; JS обновляет кадр каждые `cache_ttl` сек | надёжный базовый вариант; учётные данные панели не видны браузеру | | `proxy` | непрерывный MJPEG-поток транслируется **через сервер** (`/panel/camera/stream?device=…`): если задан `camera.stream_url` — прозрачный pass-through, иначе поток синтезируется из snapshot-кадров панели | панель/камера видны только серверу; плавное движение; занимает по одному PHP-процессу на зрителя (ограничение `?seconds=`, клиент переподключается сам) | | `mjpeg` | браузер открывает `camera.stream_url` **напрямую** (`` с multipart/x-mixed-replace) | камера доступна клиентам по сети; нулевая нагрузка на сервер; хост потока автоматически добавляется в CSP (`img-src`/`media-src`) | | `off` | видео выключено | — | Потребители: **пульт жителя** `/remote` (камера выбранного шлагбаума, 30% экрана, переключатель между воротами) и **панель оператора** `/panel`. Список доступных камер — `GET /panel/cameras` (JSON, привязка device→камера). Любой сбой видео деградирует мягко: кнопка открытия продолжает работать, вместо видео — заглушка «Камера недоступна». Снимок сохраняется в файл вручную: `bin/bas-ip gate:snapshot out.jpg`. События журнала хранят текст (кто/когда/результат), а не фото — база остаётся лёгкой, принцип минимизации данных соблюдается. ## Расписания и тихие часы **Админка → Шлагбаум → Расписания**: окна (день недели, время), действие (свободный проход / запрет гостевых / только свои), устройство. «Тихие часы» (например 23:00–06:00) блокируют гостевые открытия; аварийное открытие админом — всегда с явным подтверждением и отметкой `emergency` в журнале. ## Cooldown и защита от спама `device.lock.cooldown_seconds` (3 с) — физический анти-даблтап; поверх — rate-limit `gate_open` (12/мин на пользователя/IP). Повторное открытие в cooldown возвращает `422 error_code=cooldown` с секундами до повтора. ## Диагностика устройства * **UI**: карточка устройства → «Проверить» (login/status/snapshot), «Тест открытия». * **CLI**: `gate:test`, `gate:status`, `gate:snapshot`, `health --deep`. * **Журнал `device`**: каждый вызов с таймингом и результатом; ошибки сети — с телом ответа (секреты маскируются). ## Если панель недоступна 1. `gate:test` — что именно падает (сеть/логин/команда)? 2. Пинг/Telnet к `base_url`; панель и сервер в одной сети/VLAN? 3. Учётка панели жива? Пароль не меняли? (`secret:list`) 4. Журнал `device` — коды ответов (401 — логин, 404 — неверный endpoint для прошивки, timeouts — сеть). 5. Временно переключите устройство на `dryrun`, чтобы жители не остались без журнала, и чините сеть. Шлагбаум при этом **не должен** зависеть от доступности приложения: держите аппаратную кнопку/пульт у охраны — приложение добавляет учёт и удобство, а не заменяет аварийное открытие. --- Дальше: [12 · Безопасность](12-Security.md)