# SHiNE ESP32 Homeserver UI Spec ## Назначение Этот документ описывает актуальный UI-прототип homeserver `SHiNE` для платы `Waveshare ESP32-S3-Touch-AMOLED-2.16`. Актуальный основной Arduino-скетч лежит в `../main-device/shine_homeserver_main/`. Документ является источником истины для Arduino-скетча: - если меняется этот документ, должен меняться и скетч; - если меняется скетч, должен обновляться и этот документ; - экраны, кнопки, поля, статусы, переходы и тексты не должны расходиться. ## Текущий объём реализации Текущая реализация является интерактивным прототипом экрана устройства, пригодным для ручной проверки на железе. Что уже входит в прототип: - локальный UI на тач-экране; - хранение настроек и секретов во внутренней памяти `ESP32` через `NVS`; - экранный UI устройства работает на английском языке, потому что кириллица на этом шрифтовом пути пока не поддерживается стабильно; - экран пополнения с реальным `solana:` URI и рисованием QR-кода через `LVGL`; - реальное подключение к `Wi-Fi` по сохранённым `SSID/паролю`; - реальная проверка доступности `API`, `RPC` и `WS`-адресов; - реальное чтение баланса кошелька из `Solana RPC`; - проверка обязательных условий перед регистрацией; - живая on-chain регистрация серверного `user_pda` в `shine_users` по нажатию кнопки на главном экране; - живой экран заявок на подключение новых устройств через доверенную homeserver-сессию; - PIN-блокировка (в текущей временной сборке вход по PIN отключён, устройство открывает `HOME` сразу после старта); - базовые настройки, статус и главный экран; - сохранение `PDA` и `tx signature` после успешной регистрации. - создание и возобновление серверной сессии `SHiNE` через WebSocket с `sessionType = 100` и `clientPlatform = "ESP32"`. Что пока считается именно прототипом, а не финальной интеграцией: - пока реализован только сценарий заявок на подключение устройств через доверенную сессию; - другие типы входящих запросов на подпись и произвольные approval-flow на этом устройстве ещё не подключены. ## Основная идея устройства Устройство работает как отдельный homeserver: - хранит секрет на самом устройстве; - позволяет ввести логин, секрет и имя homeserver; - показывает адрес кошелька устройства; - позволяет пополнить баланс перед регистрацией; - после выполнения условий даёт зарегистрировать устройство как homeserver; - после авторизации в SHiNE может подтверждать заявки на подключение новых устройств пользователя. `SD`-карта не нужна для постоянного хранения секрета в этом прототипе. Основное сохранение идёт во внутреннюю flash-память через `NVS`. ## Данные, которые хранятся на устройстве Прототип хранит: - `PIN`; - `Wi-Fi SSID`; - `Wi-Fi password`; - `login`; - `session/homeserver name`; - `master secret`; - `wallet address`; - `user pda address`; - `registration signature`; - `balance`; - `server login` для первичной привязки; - `resolved server api url` / `rpc url` / `ws url` после чтения PDA сервера; - флаги: `wifiReady`, `serversReady`, `secretReady`, `registered`, `online`. Для первой регистрации обычного `user PDA` устройство берёт `createdAtMs` из NTP прямо перед отправкой транзакции в Solana. При последующих обновлениях `user PDA` устройство так же берёт актуальный `updatedAtMs` из NTP перед отправкой update-транзакции. Дальше в `user PDA` сохраняется `accessServers`, где по умолчанию лежит `shineupme`. ## Правило серверной сессии SHiNE При подключении к серверу `SHiNE` устройство должно авторизовываться как homeserver-сеанс: - `sessionType = 100` - `clientPlatform = "ESP32"` - `clientInfo = "ESP32 homeserver:"` Это относится и к `CreateAuthSession`, и к `SessionLogin`. ## Правила готовности к регистрации Кнопка регистрации доступна только если одновременно выполнены условия: 1. настроен и подтверждён `Wi-Fi`; 2. задан и подтверждён `SHiNE server login`; 3. задан логин; 4. сгенерирован или введён секрет; 5. баланс кошелька не меньше `0.20 SOL`; 6. устройство ещё не зарегистрировано. Если хотя бы одно условие не выполнено, главный экран показывает, чего именно не хватает. ## Экранная модель В прототипе используются следующие экраны: 1. `LOCK` 2. `HOME` 3. `STATUS` 4. `CONNECTION` 5. `WIFI_EDIT` 6. `SERVERS` 7. `ACCOUNT` 8. `WALLET` 9. `WALLET_QR` 10. `WALLET_SIGN_REQUEST` 11. `REQUESTS` 12. `REQUEST_DETAIL` 13. `SETTINGS` 14. `PIN_EDIT` 15. `TEXT_INPUT` 16. `CONFIRM` 17. `REGISTER_ACCOUNT_CONFIRM` 18. `REGISTER_ACCOUNT_RESULT` ## Общие правила интерфейса - Верхняя строка всегда показывает краткий статус устройства: `PIN`, `Wi-Fi`, `сервер`, `регистрация`. - В правом верхнем углу рядом с батареей: - сначала процент заряда; - затем, если устройство реально заряжается, маленькая иконка молнии; - затем контур батареи; - затем индикатор `Wi-Fi`. - Основной язык прототипа: английский. - Для вывода текста в текущей временной сборке используется стандартный шрифт `Arduino_GFX`. - Русские строки в UI устройства пока не использовать. - Кнопки крупные, с тач-ориентированным размером. - Опасные действия подтверждаются отдельным диалогом. - После изменения данных конфигурация сразу сохраняется в `NVS`. ## Экран LOCK Назначение: - экран блокировки предусмотрен в UI, но в текущей временной сборке после запуска пропускается; - вход по PIN временно отключён для отладки остальных экранов. Отображается: - заголовок `SHiNE Device`; - статус `Устройство заблокировано`; - поле ввода PIN в виде маски; - кнопки цифровой клавиатуры; - кнопки `Стереть` и `Открыть`. Поведение: - если PIN введён верно, открывается `HOME`; - если PIN неверный, показывается ошибка `Неверный PIN`; - в текущей временной сборке этот экран не показывается автоматически при старте. ## Экран HOME Это основной экран устройства. Показывает: - крупный статус регистрации; - имя логина; - имя homeserver; - строку `Wi-Fi: connected|disconnected`; - строку `SHiNE: connected|unavailable`; - короткий статус баланса. Особенности верхнего блока: - зелёный/контурный статусный кружок аккаунта расположен слева от строки логина; - блок `STATUS` поднят выше относительно предыдущей версии; - если состояние хорошее, слово `connected` в строках `Wi-Fi` и `SHiNE` показывается зелёным. В зоне кошелька: - вместо старых двух кнопок `баланс` и `QR` показывается одна широкая кнопка; - текст кнопки: `Wallet: `; - доступные имена: - `ClientKey` - `RootKey` - либо сохранённое имя `custom`-кошелька; - после старта устройства баланс активного выбранного кошелька пытается загрузиться автоматически, если уже есть секрет и `Wi-Fi`; - нажатие на эту кнопку открывает экран `WALLET`. Нижние кнопки: - `Статус` - `Подключение` - `Аккаунт` - `Wallet` - `Запросы` - `Настройки` Дополнительная большая кнопка: - `REGISTER ACCOUNT` - либо жёлтая `ADD HOMESERVER` - либо жёлтая `FIX HOMESERVER PASSWORD` Если регистрация уже сделана: - если пользователь создан, но в `PDA` ещё нет сессии текущего homeserver, показывается жёлтая кнопка `ADD HOMESERVER`; - если в `PDA` есть homeserver с тем же именем, но с другим ключом, показывается жёлтая кнопка `FIX HOMESERVER PASSWORD`; - если и пользователь, и homeserver-сессия уже корректны, вместо призыва к регистрации показывается статус `Homeserver активен`. - две нижние кнопки внизу экрана не прилегают вплотную друг к другу, между ними есть небольшой зазор. ## Экран REGISTER_ACCOUNT_CONFIRM Показывает предварительную проверку перед отправкой транзакции регистрации. Отображается: - повторный `login`; - сообщение о том, что логин свободен или уже занят; - баланс кошелька с проверкой порога `0.020 SOL`; - имя homeserver; - пометка, если используется стандартное значение `homeserver1`; - отдельное предупреждение, если `Wi-Fi` не подключён. Кнопки: - `ЗАРЕГИСТРИРОВАТЬ В СИЯНИИ` - `BACK` Поведение: - если `Wi-Fi` не подключён, на экране прямо показывается уведомление об этом и кнопка регистрации недоступна; - если `login` уже занят в `shine_users`, регистрация недоступна; - если баланс меньше `0.020 SOL`, на экране показывается соответствующая ошибка; - если все проверки пройдены, кнопка регистрации активна и запускает on-chain регистрацию. ## Экран REGISTER_ACCOUNT_RESULT Показывает результат отправки регистрации. Отображается: - текст успеха или ошибки; - подробное сообщение; - при успехе краткий `user_pda`; - при успехе краткий `tx signature`. Кнопки: - `BACK HOME` - `ACCOUNT` Поведение: - после успешной регистрации данные `user_pda` и `tx signature` сохраняются в `NVS`; - при ошибке на экране показывается причина отказа; - если ошибку вернул `sendTransaction`, экран старается показать не только общий текст, но и детали `RPC`/preflight/simulate-логов. ## Экран HOMESERVER_PDA_CONFIRM Показывает, что именно не так с homeserver-секцией уже существующей пользовательской `PDA`. Отображается: - причина (`homeserver` отсутствует в `PDA` или ключ не совпадает с локальным секретом); - `login`; - имя `homeserver`; - короткое пояснение, что именно будет сделано. Кнопки: - `ADD HOMESERVER` или `FIX HOMESERVER PASSWORD` - `BACK` Поведение: - если `Wi-Fi` не подключён, действие недоступно; - экран не создаёт нового пользователя, а запускает `update_user_pda`; - при `ADD HOMESERVER` в блок `sessions` добавляется запись `session_type=100`; - при `FIX HOMESERVER PASSWORD` обновляется публичный ключ уже существующей записи `homeserver`. ## Экран HOMESERVER_PDA_RESULT Показывает результат обновления `sessions` в пользовательской `PDA`. Отображается: - успех или ошибка; - короткое сообщение; - при успехе краткий `tx signature`. Кнопки: - `BACK HOME` - `ACCOUNT` Поведение: - при ошибке текст ошибки сохраняется в ту же USB/NVS-диагностику, что и регистрация; - после успешного обновления выполняется повторная проверка `PDA`, и основной экран должен перейти в состояние `ok`. ## Экран STATUS Показывает сводку: - логин; - homeserver; - есть ли секрет; - зарегистрировано ли устройство; - подключён ли Wi-Fi; - доступны ли серверы; - хватает ли баланса; - находится ли устройство онлайн; - краткий отпечаток `PDA` или `tx`. Кнопки: - `Назад` - `Обновить статус` `Обновить статус` в прототипе не делает сеть, а просто перерисовывает текущие вычисленные состояния. ## Экран CONNECTION Показывает: - `Wi-Fi`: готов / не готов; - `Серверы`: готовы / не готовы; - `Онлайн`: да / нет. Кнопки: - `Wi-Fi` - `Серверы` - `Подключить` - `Отключить` - `Назад` Поведение: - `Подключить` переводит устройство в `online=true`, если `Wi-Fi` реально подключён и серверы реально проверены; - `Отключить` переводит устройство в `online=false`. ## Экран WIFI_EDIT Поля: - `SSID` - `Пароль` Кнопки: - `Изменить SSID` - `Изменить пароль` - `Проверить` - `Сбросить` - `Назад` Поведение: - `Проверить` делает реальную попытку подключения к `Wi-Fi`; - `Сбросить` очищает обе строки и ставит `wifiReady=false`. ## Экран SERVERS Поля: - `API URL` - `RPC URL` - `WS URL` Кнопки: - `Изменить API` - `Изменить RPC` - `Изменить WS` - `Проверить` - `Тестовые` - `Назад` Поведение: - `Тестовые` подставляет дефолтные тестовые значения; - `Проверить` делает реальные сетевые проверки: - `API URL` должен отвечать по `HTTP/HTTPS`; - `RPC URL` должен отвечать на `Solana JSON-RPC`; - `WS URL` должен принимать `TCP/TLS`-соединение. ## Экран ACCOUNT Показывает: - логин; - имя homeserver; - статус секрета; - короткий отпечаток секрета; - статус регистрации; - короткий отпечаток `PDA` или `tx`. Кнопки: - `Изменить логин` - `Секрет` - `Имя homeserver` - `Сгенерировать` - `Очистить` - `Назад` Поведение: - `Сгенерировать` создаёт новый `master secret` и пересчитывает из него `device`-кошелёк; - `Очистить` удаляет секрет, адрес кошелька, `PDA`, `tx`, регистрацию и онлайн-статус; - логин приводится к нижнему регистру и trim. - после успешной регистрации на экране сохраняются и отображаются краткие отпечатки `PDA` и `TX`. ## Экран WALLET Показывает: - кнопку `Wallet: `; - строку текущего статуса/баланса активного кошелька; - сокращённый публичный ключ активного кошелька. Кнопки: - `Wallet: ` - `SHOW BALANCE` - `SHOW WALLET QR` Поведение: - верхняя кнопка открывает экран выбора кошелька `WALLET_SELECT`; - `Показать баланс кошелька` читает реальный баланс именно активного выбранного кошелька из `Solana RPC`; - `Показать QR-код кошелька` открывает экран `WALLET_QR`; - этот экран не меняет логику Solana-регистрации пользователя: on-chain регистрация и проверки `PDA` по-прежнему завязаны на `client key`. ## Экран WALLET_SELECT Показывает: - строку `Current: `; - три кнопки выбора: - `ClientKey` - `RootKey` - `Custom` или `Custom: <имя>`; - у текущего выбора видна галочка. Поведение: - `ClientKey` активирует кошелёк, выведенный из suffix `client.key`; - `RootKey` активирует кошелёк, выведенный из suffix `root.key`; - `Custom` использует derivation: `sha256(base64(secret32) + "|wallet." + customName)`; - если имя `custom`-кошелька ещё не задано, нажатие `Custom` открывает экран текстового ввода; - если `custom` уже выбран, повторное нажатие на него открывает экран редактирования имени; - после выбора кошелька устройство возвращается на экран `WALLET`. ## Экран WALLET_QR Экран показывает: - крупный реальный `QR` для строки `solana:`; - снизу крупный текст самого адреса кошелька. Поведение: - отдельная текстовая подсказка возврата не показывается; - возврат на главный экран выполняется обычным тапом по экрану. Показывает: - QR-код для строки вида: `solana:`; - мелкую подпись с полным адресом кошелька под QR. Поведение: - QR должен быть сканируемым, а не декоративным; - адрес кошелька берётся из текущего активного выбранного кошелька; - нажатие в любую точку экрана возвращает пользователя на `WALLET`. ## Экран WALLET_SIGN_REQUEST Экран показывается, когда браузерное wallet-расширение присылает на ESP32 запрос `sign_transaction`. Показывает: - заголовок `SIGN REQUEST`; - вопрос о подписи транзакции текущим активным кошельком; - сокращённый публичный ключ кошелька; - комментарий, присланный полем `comment`; - две кнопки: - `REJECT` - `APPROVE` Поведение: - если пользователь нажимает `APPROVE`, ESP32 подписывает транзакцию текущим активным кошельком и отправляет ответ в расширение; - если пользователь нажимает `REJECT`, ESP32 отправляет отказ `rejected_by_user`; - пока запрос активен, свайпом этот экран не закрывается; - после ответа расширению устройство возвращается на предыдущий экран. ## Экран REQUESTS Экран доступен только если homeserver уже авторизован в SHiNE. Показывает: - слева сверху кнопку `REFRESH`; - заголовок `REQUESTS:` немного правее стандартного левого положения; - справа сверху только большую цифру числа активных заявок; - ниже прокручиваемый список активных pairing-заявок; - на экране одновременно видны примерно две плитки. Каждая плитка показывает: - код подключения из `10` цифр в виде `5` пар: `XX XX XX XX XX`; - строку `Session: `; - строку `Kind: Client session` или `Kind: Wallet session`. Поведение: - список берётся из живой операции `ListTrustedDeviceLoginRequests`; - если заявок нет, экран показывает `No active requests`; - отдельная строка вида `Active requests: N` на этом экране не показывается; - вертикальный скролл позволяет просматривать все активные заявки; - нажатие по плитке открывает `REQUEST_DETAIL`; - свайп вправо возвращает в `SETTINGS`. ## Экран REQUEST_DETAIL Показывает детали выбранной pairing-заявки: - вопрос `Connect session ...?`; - код подключения `XX XX XX XX XX`; - строку `Session: `; - строку `Kind: Client session` или `Kind: Wallet session`; - пояснение: - для client session: `Only client key will be transferred. No additional keys will be sent.` - для wallet session: `No keys will be transferred.` Кнопки: - `YES` - `NO` Поведение: - `YES` подтверждает заявку: - для client session устройство передаёт только `client key`; - для wallet session устройство выпускает отдельную `wallet-session` без передачи ключей; - `NO` отклоняет заявку; - после любого решения устройство возвращается в список `REQUESTS` и обновляет его; - свайп вправо возвращает в `REQUESTS`. ## Экран SETTINGS Показывает вертикальное меню крупных пунктов. Если homeserver ещё не авторизован в SHiNE: - `1. Wi-Fi` - `2. Server` - `3. Account` Если homeserver уже авторизован: - `1. Device requests` - `2. Wi-Fi` - `3. Server` - `4. Account` Поведение: - одновременно видны только две карточки; - список листается свайпом вверх/вниз; - свайп вправо возвращает на `HOME`; - пункт `Device requests` должен быть первым и появляется только для авторизованного homeserver. ## Экран PIN_EDIT Используется для ввода нового PIN. Правила: - допустимы только цифры; - длина PIN: 4..8 символов; - после сохранения новый PIN немедленно пишется в `NVS`. ## Экран TEXT_INPUT Это общий экран редактирования текстовых полей. Используется для: - `SSID` - `Пароль Wi-Fi` - `Логин` - `Имя homeserver` - `API URL` - `RPC URL` - `WS URL` Состав экрана: - заголовок поля; - текущее значение; - программная клавиатура; - кнопки `Стереть`, `OK`, `Отмена`. ## Экран CONFIRM Это модальный экран подтверждения. Используется для: - регистрации; - очистки секрета; - полного сброса. Кнопки: - `Подтвердить` - `Отмена` ## Сценарий первой настройки Ожидаемый путь пользователя: 1. открыть устройство сразу после старта; экран PIN временно не требуется; 2. открыть `Подключение -> Wi-Fi`; 3. ввести `SSID` и пароль, нажать `Проверить`; 4. открыть `Подключение -> Серверы`; 5. проверить или задать `SHiNE server login` (по умолчанию `shineupme`); 6. открыть `Аккаунт`; 7. ввести логин; 8. задать имя homeserver; 9. сгенерировать секрет; 10. открыть `Кошелёк`; 11. при необходимости пополнить баланс; 12. вернуться на `HOME`; 13. нажать `REGISTER ACCOUNT`; 14. на экране проверки ещё раз увидеть `login`, статус свободного `PDA`, баланс, `homeserver1`, серверный login и при необходимости сообщение о неподключённом `Wi-Fi`; 15. нажать `ЗАРЕГИСТРИРОВАТЬ В СИЯНИИ`; 16. после завершения увидеть либо экран успеха с `user_pda` и `tx signature`, либо подробную ошибку; 17. после успешной регистрации увидеть статус `Homeserver активен`. Примечание: - устройство реально отправляет `create_user_pda` в `shine_users`, а после подтверждения сохраняет `PDA` и `tx signature`; - при первой регистрации для обычного `user PDA` не заполняется `serverAddress`, а `accessServers` получает `shineupme` или другой выбранный `SHiNE server login`. ## Сценарий входящего запроса 1. открыть `Запросы`; 2. выбрать один из запросов; 3. прочитать детали; 4. нажать `Разрешить` или `Отклонить`; 5. убедиться, что статус запроса изменился. ## Временный режим текста В текущей диагностической версии: - строковые литералы экранного UI должны оставаться английскими ASCII-совместимыми; - возвращение кириллицы допустимо только после отдельной доработки шрифтов и реальной проверки на устройстве; - рендер выполняется стандартным шрифтом `Arduino_GFX`; - это обходной режим, пока `U8g2`-шрифты на устройстве не начнут рисоваться стабильно. ## Критерии ручной проверки Минимально нужно проверить: 1. устройство загружается и сразу открывает `HOME`; экран блокировки временно отключён; 2. весь экранный текст отображается читаемо на английском без замены символов; 3. ввод по экранной клавиатуре работает; 4. после перезагрузки сохранённые поля остаются в памяти; 5. секрет и адрес кошелька сохраняются на устройстве; 6. экран `QR и URI` рисует читаемый QR-код; 7. регистрация блокируется, пока условия не выполнены; 8. после выполнения условий регистрация становится доступной; 9. список запросов и экран подтверждения работают; 10. полный сброс действительно очищает сохранённое состояние.