# Virtual Device Emulator

Эмуляторы устройств умного дома на Python + Flask. Полностью повторяют REST-контракт реальных ESP8266/ESP32 устройств.

## Типы устройств

- **relay** — 4 канала реле. Управление `set_state` (`on`/`off`).
- **button** — 4 канала кнопок. При клике шлёт событие `POST /events/new` на сервер.

## Установка

```bash
cd tools/virtual_devices
python3 -m venv .venv
source .venv/bin/activate  # или .venv\Scripts\activate на Windows
pip install -r requirements.txt
```

## CLI

```bash
# Создать виртуальное реле
python cli.py create --type relay --alias virt_relay --name "Virtual Relay" --port 9001

# Создать виртуальные кнопки
python cli.py create --type button --alias virt_btn --name "Virtual Buttons" --port 9002

# Запустить эмулятор
python cli.py start --alias virt_relay
python cli.py start --alias virt_btn

# Список устройств
python cli.py list

# Остановить
python cli.py stop --alias virt_relay

# Статус (JSON)
python cli.py status --alias virt_relay

# Нажать кнопку (для button-типа)
python cli.py click --alias virt_btn --channel 0

# Удалить устройство
python cli.py remove --alias virt_relay
```

## Регистрация в PHP-сервере

```bash
# Убедитесь, что сервер доступен по нужному URL
python cli.py register --alias virt_relay --server-url http://smart-home-serv.local
```

Команда `register`:
1. Проверяет `/about` эмулятора (должен быть `setup`)
2. Отправляет `POST /api/v1/devices/setup/new-device` на сервер
3. Сервер сам устанавливает токен и переводит устройство в `normal`

## Web UI

Каждый эмулятор предоставляет UI на корневом URL:
```
http://127.0.0.1:9001/
```

- Для реле — тумблеры on/off
- Для кнопок — кнопки Click и лог событий
- Обновление каждые 2 секунды

## Эндпоинты эмулятора

| Method | Path | Auth | Описание |
|--------|------|------|----------|
| GET | `/about` | — | Информация об устройстве |
| GET | `/status` | Bearer | Состояние каналов |
| POST | `/action` | Bearer | Управление (`set_state`, `simulate_click`) |
| POST | `/set_token` | — (setup) / Bearer (normal) | Установка токена |
| POST | `/reset` | Bearer | Сброс в setup |
| GET | `/channels_schema` | Bearer (или — в setup) | Схема каналов |
| POST | `/simulate-event` | — | Debug: ручной триггер события |

## Структура

```
virtual_devices/
├── cli.py              # Управление устройствами
├── emulator.py         # Flask-приложение эмулятора
├── state.py            # Хранение состояния (JSON)
├── device/
│   ├── base.py         # Базовый класс устройства
│   ├── relay.py        # Реле
│   └── button.py       # Кнопки
├── templates/
│   └── control.html    # UI (inline в emulator.py)
├── devices/            # Состояния (*.json, .gitignore)
└── pids/               # PID-файлы запущенных процессов
```

## Изменения в сервере

Для поддержки `IP:port` в `device_ip` при регистрации:
- `server/SHServ/Controllers/DevicesRESTAPIController.php` — валидация `setup_new_device` теперь разбирает `host:port` и валидирует только host.
