ИнтерфейсГлава 40 / 51

Приложение, которое объясняет

Как показать человеку не только кнопку, но и смысл происходящего?

Приложение показывает неопределённость состояния и помогает восстановить управление. Внешний вид кнопки должен соответствовать известному результату, включая отсутствие подтверждения.

Хороший экран отвечает на несколько коротких вопросов: что система сейчас знает, почему выбрано действие, подтверждено ли оно и как вернуть управление человеку. Если результат неизвестен, это должно быть видно без чтения технического журнала.

KMP объединит часть логики Android и iOS, но не отменит различия разрешений, фоновой работы и системного хранилища ключей. Точные библиотеки будут выбраны по отдельным правилам проекта; здесь задаём поведение и границы интерфейса.

KMP позволяет разделять общую логику между Android и iOS, сохраняя платформенные интеграции там, где они действительно различаются. В Koobique общими могут быть доменные состояния, сценарии подключения, обработка команд и представление данных. BLE, защищённое хранилище, разрешения, аудио и жизненный цикл требуют платформенных адаптеров. [54]

Общий код и Rust#

Общий Rust-код полезен для контрактов и проверок, но стандартный UniFFI генерирует Kotlin/JVM и Swift, а не готовый commonMain KMP. Кандидаты: expect/actual над этими двумя границами или Gobley с KMP-привязками. До выбора нужен небольшой опыт на Android и iPhone: cancellation, callbacks, многопоточность, память и доставка ошибок. Слой FFI не должен открывать внутренние указатели Core. [155][154]

Альтернативный путь — отдельный Kotlin-кодек по той же спецификации и golden vectors. Он уменьшает FFI, но создаёт две реализации. Выбор делается после небольшого proof-of-concept: подключение, одно сообщение, отмена соединения и обновление библиотеки на обеих платформах. Не стоит включать всю Rust-сеть в приложение только ради сокращения ста строк Kotlin.

A33Предлагаемые границы приложения. Макет экрана иллюстрирует состояния интерфейса, а не задаёт окончательную дизайн-систему KMP.

Главный экран и поведение команды#

Плитка света показывает подтверждённое состояние. После нажатия появляется «выполняется». При принятии без результата — «ожидается подтверждение». При обрыве — «результат неизвестен», а не автоматический возврат в OFF. Повтор использует тот же command_id, когда это продолжение прежней попытки.

Карточка температуры показывает возраст данных; карточка присутствия умеет UNKNOWN. Недоступное устройство не исчезает из списка и не выглядит выключенным. История решения доступна через действие «почему»: использованные условия, источник и фактический результат.

Подключение без лабиринта настроек#

Пользователь выбирает «добавить станцию», сканирует QR, подтверждает физическое владение и передаёт сеть. Экран различает ошибочный пароль, отсутствие подходящего диапазона, отказ локальной сети и незавершённую привязку. Подключение устройства — отдельный похожий сценарий, но его результатом является принадлежность конкретной станции.

Разрешения запрашиваются в момент понятной необходимости. Android имеет отдельные требования к Bluetooth-разрешениям, а iOS — к доступу в локальную сеть. Приложение должно объяснять, что оно ищет локальные устройства, а не требовать всё при первом запуске. [56][57]

Хранение ключей#

Android Keystore и Apple Keychain дают платформенные механизмы хранения секретов. Их доступность и ограничения используются через адаптеры, а не заменяются файлом с ключом в обычных preferences. Экспорт резервного ключа владельца — отдельная операция с явным предупреждением, не часть стандартного диагностического пакета. [71][97]

Закреплённая идентичность станции хранится вместе с инсталляцией. Приложение не доверяет новому сертификату только потому, что он пришёл с прежнего IP. Смена ключа требует подписанного перехода или процедуры восстановления с физическим подтверждением.

Фоновый режим#

Нельзя рассчитывать, что приложение постоянно держит BLE, микрофон и сетевой сокет в фоне одинаково на Android и iOS. Android документирует специальные способы фоновой BLE-работы; другие функции имеют собственный жизненный цикл. Поэтому автоматизации живут на станции, а не в мобильном фоне. [83]

Push через внешние службы может быть удобным дополнением, но не основанием безопасности. При отсутствии интернета локальная карточка состояния работает, а внешнее push-уведомление может задержаться. Уведомление об опасном процессе не заменяет локальную защиту оборудования.

Работа с голосом на телефоне#

На первом этапе используется кнопка записи. Аудио передаётся в станцию по защищённой сессии и обрабатывается локально. Это даёт RU/EN-команды без немедленной интеграции микрофонов в куб. Альтернатива — локальное распознавание на телефоне, если выбранный runtime и политика платформы позволяют полностью офлайн-режим.

Приложение показывает распознанный объект и при необходимости уточнение. Различие «свет» / «подсветка» разрешается через модель комнаты. Нельзя молча выполнить случайное ближайшее имя только потому, что STT дал похожую строку.

Сборка и установка личного приложения#

Android-экземпляр должен иметь воспроизводимую подписанную сборку и сохранённый ключ обновления. На iOS заранее проверяются Xcode, provisioning и ограничения выбранного типа аккаунта. Сам факт наличия MacBook не означает бессрочную установку любой development-сборки; текущие условия проверяются по документации Apple. [58]

Приёмка UX#

Дать второму человеку подключить тестовый узел без устной подсказки. Преднамеренно ввести неверный пароль, отказать в разрешении и прервать процесс. Успех — не только подключение, но и понятный способ продолжить без сброса всей инсталляции.

Мобильное приложение связывает состояние переключателя с целью пользователя, неопределённостью и пределами разрешённой автоматизации.

Что видит пользователь#

Экран комнаты содержит актуальные измерения с признаком свежести, оценку присутствия, фактические состояния выходов и выбранный профиль. Системное «неизвестно» отображается отдельно от OFF. При команде показывается продвижение: принята, выход подтвердил, физический результат проверяется.

Для каждой автоматизации доступна краткая причина и возможность отключить её без удаления устройств. Подробный режим раскрывает наблюдения, версии и ограничение, которое изменило решение. Это проектные требования интерфейса; внутренние правила разработки KMP будут согласованы с документами пользователя, а не выдуманы вместо них.

I21Одинаковое действие может прийти из кнопки приложения, речи или автоматизации. Все пути сходятся в едином исполнителе; голос не получает отдельный обход ограничений.

RU/EN и неоднозначность#

«Включи свет», «включи освещение» и “turn on the lights” могут соответствовать одному намерению. «Подсветка» может быть отдельным физическим объектом. Поэтому словарь синонимов связывается с возможностями и пространствами установки, а не глобально заменяет каждое слово «свет» на ID первого реле.

При нескольких подходящих объектах приложение задаёт короткий вопрос: «Основной свет или подсветку стола?» Ответ привязан к текущему запросу и ограничен по времени. Если за это время изменились права или удалилось устройство, старый ответ не запускает прежнее действие.

Локальный тракт речи#

Последовательность сохраняется: захват, определение речевого участка, распознавание, интерпретация, проверка прав, исполнение и ответ. На первом этапе телефон предоставляет микрофон, а станция или существующий ПК выполняет выбранные локальные модели. Встроенный голосовой модуль куба добавляется после испытания акустики и вычислительной нагрузки; аппаратные варианты разобраны в главах 41–42.

Языковая модель нужна для вариативных формулировок и диалога, но не для точного сравнения времени или проверки электрического диапазона. Сложная фраза сначала превращается в атомарные намерения. Непонятный фрагмент не заменяется наиболее удобным действием.

Что считать успехом голоса#

Точность распознавания текста недостаточна. Ошибка в одном слове может перепутать основное освещение и подсветку; грамматическая ошибка может не менять действие. Проверяем точность конечного намерения, долю ненужных уточнений, ошибочные действия и время до физического результата.

Отдельные наборы: русский, английский, смешанная речь, шум вентиляторов, похожие имена, отрицания и составные запросы. Текст из телевизора или воспроизведённой записи не становится командой владельца только потому, что распознаётся уверенно. Риск голосового запуска и методы подтверждения задаются по классу действия.

Обучение пользовательскому смыслу#

Человек может назвать настольную лампу «моя подсветка». Система сохраняет явный локальный псевдоним после подтверждения. Повторяющееся исправление может породить предложение обновить словарь. Не меняем автоматически нагрузку, права и глобальный смысл команд для остальных пользователей.

Приложение связывает человеческую цель с физическим объектом. AI помогает понять речь; авторизация, неоднозначность и проверка результата остаются видимыми и управляемыми.

Обнаружение без подмены доверия#

Сервис объявляется как _koobique._tcp; TXT содержит только ID установки, поддерживаемый профиль и подсказку идентичности. Отпечаток из mDNS не является доверенным pin: любой сосед может объявить похожую запись. Android использует NsdManager, iOS — Bonjour/NWBrowser с необходимыми разрешениями Local Network и списком сервисов. Отказ разрешения показывается отдельно от отсутствия Hub. MulticastLock не назначается всем сборкам автоматически: необходимость зависит от того, используется системное NSD или собственные multicast-сокеты. [159][57]

Один элемент управления показывает текущий snapshot, рядом — выполнение конкретной команды. Поздний APPLIED(A) обновляет историю A, но не заменяет более новый OFF. При UNKNOWN текст объясняет действие: «не удалось подтвердить; проверить состояние», а не «включено». После истечения запроса новая попытка требует текущих условий и нового ID.

В приложении предусмотрены VoiceOver/TalkBack, масштабирование текста и обозначения состояния не только цветом. «Ручной режим» сопровождается ответом, когда вернётся автоматика. Для E0: «до команды “вернуть автоматику”». Технические boot/fence/lease раскрываются только в диагностике, не перегружают основной экран.

Общий микрофон телефона в первом опыте передаёт аудио на локальный speech-worker Hub. Системное распознавание iOS/Android не считается автоматически офлайн; использование Apple Speech требует проверки supportsOnDeviceRecognition и requiresOnDeviceRecognition для конкретного языка. При отсутствии локального режима нет скрытого перехода в облако. [176]

Намерение приложения и команда устройству#

Приложение отправляет пользовательское намерение в Core. Ядро проверяет права, разрешает объект, фиксирует основания и создаёт одну или несколько команд KQIP для узлов. Поэтому пользовательский запрос и попытка исполнения имеют разные идентичности и историю. API приложения должен описывать их связь, чтение snapshot и обновлений, отзыв сессии, ошибки и восстановление подписки. Перенос KQIP в телефон сам по себе этих операций не определяет; до реализации клиента нужен отдельный проверяемый контракт.

Найти в книге

Поиск по всем главам, схемам и техническим разделам.