Как я дал старому планшету глаза и получил панель для Home Assistant
Давно хотелось поставить где-то на видном месте планшет-панель для Home Assistant — сценарии, термостат, камеры, всё в одном месте, без необходимости каждый раз доставать телефон. Готовые панели стоят как отдельный гаджет, а мысль «взять б/у планшет и допилить под себя» выглядела куда веселее.
На Авито нашлось объявление на два старых планшета за копейки — продавец явно расчищал полку. План был простой: вытащить аккумулятор (устройство и так будет висеть на постоянном питании, живой батарее там нечего делать — только распухнет через пару лет) и запитать напрямую от сети.
Вот что в итоге получилось — а дальше расскажу, как до этого дошёл.

Первый блин комом
Первым в разборку пошёл планшет постарше, на Android 4. Разобрал, вытащил батарею, подключил плату к лабораторному блоку питания — сначала же надо на стенде выяснить, какое напряжение и ток планшет реально просит, прежде чем городить постоянную схему. И тут я допустил единственную настоящую ошибку: начал подстраивать напряжение на лабораторнике, не отключая от него планшет. Оказалось, что лабораторный блок при подстройке «на живую» даёт короткие всплески напряжения — и около 5.5В хватило, чтобы убить контроллер питания на плате.
Дело было не в том, что я перепутал напряжение - с расчётами всё было в порядке. Просто не отключил нагрузку перед тем, как крутить ручку. Мелочь, а результат один — труп.

Второй заход — уже без экспериментов на живую
Со вторым планшетом, Lenovo TB-X103F, решил не наступать на те же грабли: сначала на обесточенном стенде выяснил, какие напряжение и ток ему нужны, и только потом собрал постоянную схему на LM2596S — понижающем DC-DC преобразователе, который стоит копейки и с запасом закрывает задачу из 5 В блока питания получить то, что нужно для работы.
Тащить к планшету открытый провод не хотелось, поэтому я впаял в корпус разъём USB-C — не для передачи данных, просто аккуратный вход питания. И чтобы планшет не лежал на столе плашмя, а стоял как задумано, напечатал на 3D-принтере подставку под конкретную модель. Пока планшет так и стоит на столе на этой подставке — до стены руки ещё не дошли, но и на столе свою задачу он выполняет.


Проблема, о которой я не подумал заранее
Планшет ожил, встал на подставке, крутит Home Assistant — и тут всплыли две вещи, которые я не продумал заранее.
Во-первых, у Lenovo TB-X103F физически нет датчика освещённости. Вообще. dumpsys sensorservice показывает один-единственный сенсор — акселерометр. Android в таких случаях даже не рисует переключатель автояркости в настройках: фреймворк просто прячет его, если сенсора нет. Штатного способа «пусть экран сам подстраивается под свет в комнате» тут не существует в принципе.
Во-вторых, экран, включённый круглые сутки — это лишняя нагрузка на понижайку, к которой я хоть и прикрутил радиатор, но всё же греется, да и просто неприятно, когда вечером светит как фонарик в глаза. А постоянно подходить и тыкать в экран, чтобы он проснулся так себе идея для штуки, которая должна работать сама по себе.
Тогда я и решил как обычно "героически" всё это решить.
Главная фишка — не яркость, а движение
Первая мысль была очевидной: раз нормального датчика света нет, а фронтальная камера есть — пусть камера её и заменит. Раз в секунду берём один маленький кадр превью и считаем среднюю яркость по Y-плоскости (luma) — вот и замена отсутствующему android.sensor.light.
Но по факту в приложении получилось две функции на одних и тех же кадрах, и вторая — определение движения — оказалась куда интереснее и полезнее первой. Раз кадр уже есть, почему бы не сравнить его с предыдущим и посчитать, сколько пикселей заметно изменилось? Детектор движения получаем буквально бесплатно.
Первая версия логики «есть движение - буди экран» на практике раздражала до дрожи: сидишь на диване в другом углу комнаты, чуть шевельнулся — и планшет с готовностью загорается. Один порог движения не различает «кто-то есть в комнате» и «кто-то подошёл к планшету».
Решение — считать одну и ту же разницу кадров по двум независимым порогам:
присутствие (по умолчанию 2% кадра) — не даёт погаснуть уже включённому экрану, само по себе ничего не включает;
«рядом» (по умолчанию 12% кадра) — и только это состояние будит экран.
Работает на простой физике: человек в полуметре от камеры занимает заметную часть кадра, человек на диване в другом конце комнаты — единицы процентов. Никакой сложной геометрии — просто доля изменившихся пикселей как грубая оценка расстояния. Эта штука работает настолько хорошо, что стала для меня главной фичей приложения, а автояркость оказалась просто приятным бонусом, который был рядом бесплатно.

Пара слов про яркость и код
Раз уж камера уже даёт кадр для движения, туда же прикрутил и подмену датчика света:
long sum = 0;
for (int i = 0; i < lumaSize; i++) {
sum += data[i] & 0xFF;
}
int avgLuma = (int) (sum / lumaSize); // 0..255
Сверху — экспоненциальное сглаживание и гистерезис, иначе любой человек, прошедший мимо камеры, дёргал бы яркость экрана туда-сюда.
По пути пришлось разобраться с парой вещей, без которых всё это тормозило бы или падало на слабом железе:
Camera1, не Camera2. На MT8163 в Android 6 Camera2 API работает в LEGACY-режиме — по факту это обёртка над тем же старым HAL, только с лишним слоем сложности. Camera1 (
android.hardware.Camera), хоть и deprecated, но именно на этом железе стабильнее и проще.Минимальное разрешение превью — 160×120, этого с запасом хватает и для яркости, и для грубой детекции движения, а нагрузка на слабый CPU почти нулевая.
Буферы кадра переиспользуются (
setPreviewCallbackWithBuffer) — на 1 ГБ RAM лишние аллокации на каждый кадр сборщик мусора бы заметно тормозили.
Живучесть на 24/7
Планшет работает без присмотра, значит сервис обязан переживать всё подряд: зависание камеры (watchdog перезапускает камеру, если кадров нет дольше 15 секунд), смерть HAL-процесса, перезагрузку устройства, попытки системы прибить фоновый сервис. Отдельно неприятный случай — поток камеры может застрять прямо внутри нативного вызова Camera.open(), и тогда даже внутренний watchdog не успевает сработать. На такой случай есть второй, более грубый уровень защиты: если состояние камеры не меняется дольше 90 секунд, весь контроллер камеры вместе со своим потоком пересоздаётся с нуля.
Что приложение умеет
пробуждение экрана при приближении, с раздельными порогами присутствия и «рядом» (можно ограничить зону реакции центром кадра);
поддержка датчика приближения как дополнительного триггера, если он у устройства есть;
автояркость по камере вместо отсутствующего датчика, с настраиваемой кривой «освещённость → яркость»;
«тихие часы» с ограничением яркости и/или запретом пробуждения ночью;
интеграция с Home Assistant через REST API — планшет отдаёт освещённость, яркость, факт движения и состояние экрана как обычные сущности;
диагностика прямо в приложении: график истории, живые показания, журнал событий, экспорт в CSV — без этого пороги под конкретную комнату не подобрать;
управление снаружи через
adb broadcast, экспорт/импорт настроек;пара приятных мелочей для тех, у кого есть root (не обязательно для основной работы).
Камера при этом никогда никуда не «смотрит» в смысле съёмки: кадр обрабатывается в памяти и тут же выбрасывается, сохранения или передачи изображения нет в принципе — наружу уходят только два числа в секунду.
Home Assistant
Включаете интеграцию, вписываете свой адрес и long-lived токен — получаете sensor.screenvigil_luma, sensor.screenvigil_brightness, binary_sensor.screenvigil_motion, binary_sensor.screenvigil_screen и sensor.screenvigil_status. Планшет заодно превращается в датчик освещённости и присутствия для той комнаты, где стоит.
Отдельно наступил на грабли: токен Home Assistant для записи состояний через REST API обязан принадлежать администратору — обычный пользовательский токен читает без проблем, а на запись тихо отвечает 401 Unauthorized, и по коду ошибки это не отличить от банально неверного токена. Если у вас похожая интеграция и всё падает с 401 — проверьте именно права токена, а не только его правильность.
Итого
GitHub — исходники, инструкция по сборке, подробности по каждому порогу, apk билды.
Google Play — если хочется установить в пару тапов.
RuStore — пока без ссылки, добавлю позже, впервые проверяет дольше GP.
Если у вас похожий планшет без датчика освещённости, или свой вариант решения той же задачи — пишите в комментариях, интересно будет сравнить.
KioskNews shows a cleaned-up reading view extracted from the publisher’s page — the original always lives on their site, not ours.