Среда устройства: что есть, чего нет и что сломает залочка
Страница п ро то, во что упрётся код на реальной плате. Все факты сняты с живого устройства 2026-09-01, перед тем как плату отключили.
Экран и ввод
| Панель | одна, 800 × 1280, портрет, 61 Гц |
| Плотность | 160 (320 dpi) |
| Тач | goodix-ts, инвертирован по умолчанию — компенсируется свойством persist.sys.touch.angle=180 |
| Ориентация | активити объявлена портретной |
Свойство сейчас живёт только в памяти, в build.prop образа его нет. Любое стирание
/data вернёт инверсию: человек жмёт «1», нажимается «9». Внести свойство в build.prop —
пункт из NATIVE-GATE.md, и правится он в образе, то есть тем же выездом.
Приложение — это рабочий стол
Категории HOME + DEFAULT навешивает плагин plugins/withHomeLauncher.js, роль закреплена
как preferred. Кнопка «назад» подавлена — из киоска выйти нельзя.
Практический вывод: уронить киоск некуда. Если он упадёт, пользователь увидит пустоту, а через несколько минут плата перезагрузится сторожевым таймером.
Всё, что правит Android-проект, обязано жить в этом плагине: каталог android/ порождается
expo prebuild и при --clean затирается вместе с ручными правками манифеста.
Установка только системная
adb install даст приложение в домене untrusted_app, у которого нет доступа к узлу
сторожевого таймера — почему это важно.
Приложение запекается в образ как /system/priv-app/Postamat/Postamat.apk.
/data затеняет запечённую в образ при равном versionCodeПроверяя новую версию, поднимайте versionCode и делайте adb uninstall. Иначе будете
тестировать старый код, будучи уверены в обратном. Эта грабля один раз уже сделала заливку
холостой.
Чего в системе нет — и не надо туда лезть
- Камер нет. Возможности
android.hardware.camera*в системе отсутствуют: камеры выключены в дереве устройств. Любая библиотека, которой нужна камера, работать не будет. Это цель проекта, а не досадное ограничение. - Микрофона в возможностях системы нет, пути захвата вырезаны из политики аудио. 🔒 Но микрофонный тракт на плате физически есть (кодек, контрол в положении «выключено») и включается одной командой из софта. Для проекта, затеянного ради выпиливания камер, включить его из приложения — такая же дыра. Не включать.
- Телефонии и Bluetooth нет — вырезаны из образа.
- Есть: Wi-Fi, USB-host, Vulkan / GLES 3.2.
🔴 Сканера QR на плате нет — и не было
Это факт со съёма, а не предположение: на USB нет ни одного устройства, кроме хаба платы;
среди устройств ввода только тач, кнопки и детектор гарнитуры — ИК-приёмник из этого
списка с тех пор убран; узлы /dev/ttyUSB*
и /dev/ttyACM* не создавались.
Что это значит для кода. Интеграцию сканера не на чем было проверить. Всё, что про сканер записано в документах проекта — модель, работа как USB-HID «клавиатура», права на устройства ввода — это сведения из документации и рассуждение, а не измерение.
Первое подключение сканера будет первой проверкой сразу трёх вещей: что он опознаётся, что киоск читает его посылки и что порту хватает питания. Заложите на это время и живую плату.
Если киоск будет ловить сканер как клавиатуру, он по построению ловит и всё остальное, что притворяется клавиатурой. Раньше главным таким источником был ИК-пульт; теперь приёмник выключен, но само свойство никуда не делось — любое подключённое HID-устройство пойдёт тем же путём.
ИК-приёмник выключен в образе
На плате был живой инфракрасный приёмник пульта, зарегистрированный как устройство ввода с полной картой клавиш, включая power. Это был единственный беспроводной вход, который не был заглушен: подросток с универсальным пультом за пять евро гасил экран постамата.
Теперь его нет. В дереве устройств узел pwm@fe6e0030 (pwm7, к которому подключён
фотоприёмник) переведён в status = "fail".
Проверено на живом, а не выведено рассуждением:
- драйвер ИК-приёмника не загрузился;
- устройств ввода стало пять вместо шести — приёмник исчез из списка целиком;
- подсветки на соседних узлах (
pwm4,pwm5) не задеты, экран работает как работал.
Раньше в списке нативных задач стоял фильтр, отсекающий нажатия с пульта, — и его нельзя было ни написать заранее, ни проверить. Теперь фильтровать нечего: события не приходят вовсе, потому что устройства ввода больше не существует.
Это как раз тот случай, когда задача решена не кодом, а тем, что источник убран.
⚠️ В COMMISSIONING.md остаётся отдельный шаг «заклеить фотоприёмник непрозрачной лентой».
Он писался до этой правки образа и теперь дублирует программное выключение. ❓ Оставлять его
или убрать — решение владельца; аргумент за то, чтобы оставить: лен та продолжает работать
и на плате, залитой старым образом, а стоит она тридцать секунд.
Чего в приложении сейчас нет — и чинится это только выездом
Пункты из NATIVE-GATE.md, которые легко принять за мелочь. Каждый стоит поездки,
если про него забыть при единственной нативной заливке.
Экран может погаснуть. Разрешения WAKE_LOCK в манифесте нет, удержания экрана тоже.
Погасший экран на уличном постамате неотличим от сломанного: человек уходит.
Приложению нечем издать звук. Динамик подключён и оставлен намеренно, но системные звуки в образе выключены — своих звуковых файлов у приложения нет. Последствия конкретные: нажатие цифры в перчатке на морозе ничем не подтверждается (человек жмёт дважды и попадает в антибрут); щелчок замка через дверцу не слышен; и главное — некому крикнуть «закройте дверцу». Это единственный исполнительный механизм, которым можно вернуть уже уходящего человека, и он не задействован.
Яркость не управляется. Днём на солнце экран нечитаем, ночью светит жильцам в окна.
✅ Пункт про ИК-пульт закрыт и из списка ушёл. Он был четвёртым: незаглушённый беспроводной вход, для которого пришлось бы писать фильтр клавиш вслепую и отлаживать его в тот же выезд. Вместо фильтра приёмник выключен в образе — проверено на живом.
Порты и разъёмы, которые важны коду
| Разъём | Куда идёт | Зачем нам |
|---|---|---|
RS485 (клеммник) | /dev/ttyS0 | 🔴 плата замков, главный рабочий интерфейс |
UART (клеммник) | консоль отладки, 1 500 000 бод | единственный путь из кирпича, снаружи корпуса |
| Type-C | USB-OTG | adb и заливка образа; ⚠️ только USB 2.0 |
| RJ45 | eth0, PHY 10/100 | проводной путь обслуживания |
| USB ×5 | хаб платы | на съёме не подключено ничего |
⚠️ Пин «5V» на задних клеммниках — это выход питания платы, а не вход. Питание переходника к нему не подключать.
Сеть
В проде связь по Wi-Fi, на роутере фильтр — только до нашего backend. Фильтр работает
по именам, и в него заносятся ровно два: api (эндпоинты устройства) и ota (обновления).
Панель оператора и документация живут на других именах и постамату недоступны вовсе —
зачем так сделано. Ethernet остаётся проводным путём обслуживания: если через 45 секунд после загрузки DHCP ничего не дал, на
eth0 встаёт запасной адрес 169.254.1.1/16 — воткнутый напрямую ноутбук достучится без
единой настройки со своей стороны.
Пока на ней отладочная сборка, SELinux в permissive и adb по TCP:5555 — любой, кто дотянется по сети, получает root одной командой. Это осознанное временное состояние на время разработки, решение владельца.
Что сломает залочка
Залочка — это перевод SELinux в enforcing, отключение отладочной сборки и выключение
сетевого adb. Список того, что перестанет работать, снят с живого: в permissive система
пишет в лог всё, что запретила бы. Собрано 274 отказа.
| Что случится | |
|---|---|
| 🔴 кормление сторожевого тай мера | будет отклонено молча, плата уйдёт в цикл «пять минут — сброс». Нужна своя политика |
| 🟡 оверлей температуры / CPU / GPU в киоске | покажет «—». Приложение не упадёт: каждое чтение в try/catch, любое поле может быть null. Не добавлять сюда «упасть, если не прочиталось» |
| ✅ работа с платой замков | не пострадает: среди 274 отказов нет ни одного на устройство порта |
Он снят с одной загрузки, работавшей около двадцати минут, и покрывает только те пути кода, которые за это время выполнились. Приложение тогда было пустым. Когда в нём появится бизнес-логика — сеть, файлы, сканер, кормление таймера — появятся и новые обращения. Сбор отказов надо повторить на готовом приложении, перед самой залочкой.
Обратим а ли залочка — да, пока цел загрузчик и есть физический доступ к клеммнику UART:
путь восстановления идёт мимо Android. Разбор — docs/ROOT-AND-LOCKDOWN.md в репозитории
прошивки.