Самодельный E-ink монитор для сервера за выходные

Прокомментировать Просмотры: 3
Микромонитор для сервера
Микромонитор для сервера

Если совсем кратко: плата Waveshare ESP32-S3-ePaper-1.54, единственный USB-провод и компактный экран с разрешением 200×200 пикселей, размещенный рядом с сервером. Он в режиме реального времени отображает загрузку ЦП, температурные показатели видеокарт, объем задействованной памяти, состояние накопителей, аптайм, актуальный пинг и прочие метрики на усмотрение системного администратора.

Зачем серверу отдельный экран

Серверная станция с двумя ускорителями Tesla P100 функционирует прямо у меня на кухне, о чем подробно рассказывалось в прошлой публикации (https://habr.com/ru/articles/1071442/). Оборудование закономерно выделяет тепло и шумит, поэтому мне важно постоянно контролировать лишь три параметра: не приближается ли температура GPU к критической отметке троттлинга, каков процент заполнения оперативной памяти и не исчерпано ли свободное пространство на твердотельном накопителе.

Я перепробовал множество альтернативных вариантов. Полноценный 15-дюймовый монитор отпал сразу из-за дефицита свободного пространства и избыточного энергопотребления. Идея поднять веб-страницу со сводкой выглядит логично, однако для ее просмотра требуется разблокировать смартфон, отыскать нужную вкладку и дождаться прогрузки интерфейса. Мне же необходимо, чтобы ключевые цифры попадались на глаза мгновенно, стоит лишь пройти мимо. Технология электронных чернил подошла идеально: дисплей не слепит глаза, в статичном положении не расходует энергию и сохраняет картинку даже при полном отключении питания.

Теперь я вижу когда локальная нейросетка заканчивает работу
Теперь я вижу когда локальная нейросетка заканчивает работу

Девайс запитан по USB, ежеминутно обновляет кадр и выводит актуальные показатели производительности и аптайма. Ниже приведены все технические нюансы реализации этого проекта.

Закупка

Типичный лот на маркетплейсах ESP32-S3 плата разработки e-Paper 1.54"
Типичный лот на маркетплейсах ESP32-S3 плата разработки e-Paper 1.54″

Комплект поставки включал пластиковый бокс с безымянной платой ESP32-S3-ePaper-1.54 V2 без кабеля в комплекте. Матрица имеет разрешение 200×200 пикселей и функционирует на базе контроллера SSD1681, а аппаратной основой служит чип ESP32-S3-PICO с 8 МБ флеш-памяти и аналогичным объемом PSRAM. На борту также присутствуют сенсор температуры и влажности SHTC3, модуль реального времени, слот для карт памяти TF, аудиокодек с усилителем, динамик, пара кнопок и современный разъём Type-C. Аккумулятор конструкцией не предусмотрен, что абсолютно не критично при стационарном подключении по USB.

Так присылают
Так присылают

Для реализации задуманного проекта задействована лишь треть потенциала микроконтроллера: динамик безмолвствует, а слот расширения памяти до сих пор пустует.

Написание прошивки

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

На текущий момент проект обзавелся именем inkmetrics и дорос до релиза 0.7.1. Ниже представлен исчерпывающий перечень текущих возможностей системы, а в завершении статьи можно найти ссылки на репозиторий с исходным кодом и готовый установочный комплект.

В первоначальной итерации рендеринг кадра 200×200 выполнял ПК с помощью библиотеки Pillow и шрифта Consolas, передавая по 5000 байт через COM-порт, тогда как плата выступала пассивным приемником буфера. Сейчас от последовательного порта в сборке не осталось и следа. Устройство определяется хостом как комплекс из сетевого адаптера и накопителя, а отрисовкой интерфейса и подбором шрифтов занимается автономно. Персональный компьютер раз в минуту передает исключительно числовые значения в формате легковесного JSON-запроса POST /ingest на адрес 192.168.7.1. Все параметры опциональны: в случае отсутствия данных девайс отображает прочерк.

Подобная архитектурная переделка была необходима. Генерация графики на стороне компьютера не позволяла реализовать второй экран, браузерный конфигуратор и индикацию отсутствия соединения. Кроме того, любое изменение дизайна влекло за собой правку скрипта генератора, а мне хотелось свободно манипулировать отступами и размерами шрифтов независимо от агента. Теперь логика разметки зашита в саму прошивку, а на хосте остался предельно простой сборщик метрик.

Что на экране

Откуда берётся

Загрузка CPU, память, диск, аптайм

штатные счётчики Windows, агент раз в минуту

Состояние диска

SMART, строка OK / WARNING

Аптайм

штатные счётчики Windows

Две видеокарты: загрузка, температура, память

nvidia-smi, а без него счётчики WDDM

Есть ли у компьютера интернет, задержка, сколько из четырёх пингов ответило

агент: четыре ICMP

Температура и влажность в комнате, часы

датчик SHTC3 на плате, время отдаёт браузер при открытии страницы

Актуальность данных

прибор: молчание дольше 90 секунд стирает числа в прочерки

Организация стабильной связи

Стандартное ядро Arduino не поддерживает USB-сети, так как встроенный стек TinyUSB по умолчанию лишен соответствующего сетевого класса. Ради реализации полноценного веб-интерфейса на самом устройстве пришлось мигрировать на официальный фреймворк ESP-IDF.

Первая попытка уперлась в дескрипторы. Windows категорически отвергла протокол NCM, после чего я переключился на RNDIS. Однако библиотека esp_tinyusb генерирует стандартные профили исключительно для CDC, MSC, MTP и NCM, в то время как конфигурацию RNDIS разработчик обязан задавать вручную, получая на выходе лишь лаконичную ошибку ESP_ERR_TIMEOUT. Почти полдня ушло на диагностику физического уровня PHY и тактовых частот, пока отладочные регистры не прояснили ситуацию: до инициализации PHY идентификатор ядра DWC2 возвращает 0x00000000, а после успешного подъема переключается в 0x4f54400a. Аппаратная часть оказалась полностью исправна.

Корректные дескрипторы оживили сеть за минуту, после чего микроконтроллер снова свалился в циклический рестарт. Источником проблемы оказался собственный код: esp_netif транслирует драйверу линейный кадр данных, тогда как я по аналогии с примерами TinyUSB ошибочно приводил его к указателю на pbuf. В результате длина считывалась не из заголовка, а из байтов MAC-адреса, и первый же исходящий DHCP-ответ операционной системе приводил к аварийному падению системы с ошибкой LoadProhibited.

К счастью, к тому моменту дамп сбоев уже успешно расшифровывался: трассировка стека наглядно демонстрировала весь путь выполнения от udp_sendto_if через etharp_output и esp_netif_transmit до моих функций usb_transmit и tud_network_xmit_cb. Исправление свелось к правке одной строчки кода. После этого плата проработала стабильно сто тридцать четыре секунды и останавливаться не собиралась.

Заодно выяснилось, что индикация сетевого конфликта на дисплее была ложной, а хост не получал IP-адрес по другой причине: ежеминутные попытки повторного DHCP-запроса на восемь секунд вырубали встроенный аварийный DHCP-сервер девайса. Дополнительно пришлось жестко зафиксировать IP-адреса хоста и самого прибора и отказаться от шлюза по умолчанию для этого адаптера, иначе Windows перенаправляла туда весь трафик, полностью лишая компьютер доступа в интернет.

Адрес хоста выдается прибором жестко
Адрес хоста выдается прибором жестко

Виртуальный носитель, оказавшийся слишком миниатюрным

Эмулируемая прибором флеш-память доставила немало хлопот с подбором оптимального объема. Изначально разметка содержала 2880 секторов, что в точности соответствует классической дискете объемом 1,44 МБ. Операционная система при обнаружении устройств прямого доступа выбирает между классами Disk и SFloppy именно по размеру носителя. В итоге Windows монтировала его как гибкий диск с буквой A: и характерной подписью.

Я безуспешно пытался скорректировать бит сменного носителя в ответе на команду INQUIRY и даже формировал собственный модифицированный ответ. Не помогло. Структура таблицы разделов внутри образа также не влияла на поведение ОС. Проблема решилась банальным масштабированием: увеличение емкости до 7552 секторов (3,69 МБ) с применением таблицы MBR и файловой системы FAT16 заставило Windows корректно распознать накопитель под буквой E: с меткой INKMETRICS.

Прибор виден как флешка
Прибор виден как флешка

Текущий функционал устройства

Интерфейс и органы управления

Прошивка поддерживает два экрана, переключаемых коротким нажатием клавиши питания (PWR). Главная сводка содержит статус сетевого подключения в верхней строке, пару крупных цифровых метрик в центре, а ниже — показатели загрузки процессора, памяти, диска, аптайма и комнатного датчика. Экран SETUP демонстрирует IP-адрес веб-панели, назначение ключевых метрик, текущую ориентацию дисплея, режим работы накопителя, узел для проверки пинга и версию программного обеспечения.

Строка состояния вынесена отдельно, так как она отражает метрики хост-машины, а не самого гаджета. Возможные варианты статусов сведены в таблицу.

Что видно

Когда

PING — 13MS — 4/4

интернет у компьютера есть, 13 мс это среднее

OFFLINE — 0/4

не ответил ни один, интернета нет

NO DATA

агент молчит дольше 90 секунд, числа стёрты

PING — 13MS

агент старой версии, счёт пингов не сообщает

Пара главных цифровых показателей выбирается через меню настроек посредством выпадающих списков (доступны загрузка CPU, память, накопитель, а также утилизация и температура каждого графического адаптера либо пустые слоты). Конфигурация сохраняется в энергонезависимой памяти NVS и сохраняется при обновлениях прошивки. Алгоритм выбора кегля выведен эмпирическим путем: двузначные значения выводятся крупным шрифтом, но если хотя бы одно число превышает 99, оба элемента автоматически уменьшаются до среднего шрифта. К примеру, крупная надпись «100%» занимает по ширине 124 пикселя, и два таких символа физически не поместятся на 200-пиксельном экране.

Физических кнопок две, каждая обрабатывает одиночные и длинные нажатия. Короткий тап по PWR переключает экраны, а удержание инициирует принудительную перерисовку кадра. На экране SETUP короткое нажатие клавиши BOOT разворачивает изображение на 90 градусов, а удержание блокирует запись на встроенный накопитель девайса.

Веб-интерфейс

Никакого стороннего софта устанавливать не требуется — управляющие страницы хостятся прямо на микроконтроллере по адресу 192.168.7.1.

Адрес

Что делает

/

сводка: то же, что на экране, плюс возраст последнего замера

/setup

настройки: поворот, два крупных числа, узел пинга, блокировка диска

GET /api/state

весь JSON состояния, включая объект ingest с метриками хоста

GET /api/boot

уйти в режим загрузчика: перепрошивка без кнопки BOOT

Первая страница вебсервера
Первая страница вебсервера
Экран настроек
Экран настроек

Развертывание на хост-компьютере

После подключения по USB устройство распознается как флеш-накопитель и сетевой адаптер. На виртуальном диске записаны четыре файла: скрипт установки, деинсталлятор и документация на русском и английском языках. Установщик представляет собой единственный .cmd файл, содержащий код агента. При запуске с правами администратора он размещает утилиту в директории C:\ProgramData\inkmetrics и регистрирует задачу планировщика «inkmetrics agent», которая выполняется от системной учетной записи SYSTEM каждую минуту. Логи пишутся в ту же папку (файл agent.log со строками вида sent ok (cpu=8.4%, ping YA.RU 16ms 4/4)). Никаких зависимостей вроде Python, сторонних драйверов или фоновых служб не требуется. Удаление системы происходит аналогично — в один клик.

Содержимое диска прибора
Содержимое диска прибора

С мониторингом видеокарт связана отдельная история преодоления ограничений Windows. На моей машине установлена утилита nvidia-smi, которую агент опрашивает в первую очередь. Однако устройство должно корректно работать и на системах без дискретной графики NVIDIA, где стандартные счетчики производительности могут быть повреждены (Win32_PerfFormattedData_* возвращает ошибку «Неверный класс», Get-Counter не находит метрики, а поле Win32_Processor.LoadPercentage пустует). Поэтому вычисление загрузки ЦП перенесено на анализ дельты времени простоя, а для сторонних графических чипсетов задействован альтернативный метод через WDDM-счетчики, аналогичные диспетчеру задач. Видеоадаптеры идентифицируются по уникальным LUID, а их сортировка выполняется по объему видеопамяти, чтобы дискретная карта гарантированно получала нулевой индекс. Этот путь позволяет считывать лишь процент утилизации, в то время как температура и объем занятой памяти для сторонних GPU остаются прочерками вместо нулевых значений.

Процесс прошивки отладочной платы

Предусмотрено три сценария обновления, задействующих единственный кабель.

Способ

Что нужно

Команда

Комплект из релиза

Python и esptool

flash-kit\idf\flash.bat COM5

Flash Download Tool от Espressif

ничего, кроме самой утилиты

inkmetrics-fw-0x0.bin с адреса 0x0, setup-disk-big.img с 0x430000

Прошивальщик в браузере

Chrome

страница на GitHub Pages, ниже ссылка

Скрипт flash.bat последовательно прошивает загрузчик, таблицу разделов, основную прошивку и образ диска, после чего самостоятельно сбрасывает загрузочный флаг, позволяя девайсу стартовать без физического переподключения интерфейса. Что касается прошивки через браузер — веб-интерфейс открывается, сверяет контрольные суммы, успешно обнаруживает устройство и открывает порт, однако завершить запись на нашей плате напрямую пока не удается, поэтому я не могу заявить о полноценной работоспособности метода. Причина кроется не в браузере: встроенный USB-Serial/JTAG загрузчик чипа ESP32-S3 после манипуляций с линиями DTR и RTS блокирует последовательный порт вплоть до полного физического переподключения кабеля (это поведение воспроизводится и при использовании классического esptool). Именно поэтому официальный комплект ориентирован на бесшовный режим без аппаратного сброса линий.

В процессе разработки плата практически не покидала USB-порт рабочего компьютера. Переход в режим прошивки инициировался GET-запросом /api/boot, заливка выполнялась автоматизированным скриптом, самостоятельно определяющим порт и снимающим защитные флаги. Физическую кнопку BOOT за последние два дня пришлось нажимать от силы раз пять; счетчик перезагрузок в системном логе перешагнул за тысячу еще в первые сутки, а кабель передергивался лишь в моменты зависания USB-порта после экспериментов с загрузчиком. Большая часть кода создавалась в режиме непрерывного цикла: девайс подключен к ПК, агент самостоятельно заливает новые билды, а я оцениваю результат визуально и корректирую задачу. Способность микроконтроллера отдавать статусную страницу и принимать команды перезагрузки позволила полностью автоматизировать цикл разработки.

Прошивальщик на гитхабе в репозитории
Прошивальщик на гитхабе в репозитории

Планы по доработке

В перспективе планируется внедрить частичное обновление экрана для устранения неприятного мигания при перерисовке кадров. Реализация беспроводного обновления OTA (Over-the-Air) пока не в приоритете, хотя аппаратная разметка уже резервирует под него второй слот: бинарник приложения занимает всего 642 КБ из доступных 3,2 МБ, оставляя целый мегабайт под резервную копию. Также в планах значится поддержка Wi-Fi точек доступа для удаленного мониторинга со смартфона, проектирование полноценного корпуса (пока плата базируется на импровизированной подставке), ведение истории метрик с построением графиков, система алертов и уведомлений в Telegram. Что касается звукового сопровождения — хотя аппаратный кодек с динамиком присутствуют на плате, конкретного применения им пока не нашлось, хотя временами посещает крамольная мысль запрограммировать воспроизведение нецензурной лексики при потере интернет-соединения.

Исходные коды

https://github.com/isemaster/inkmetrics

Проект полностью открыт, любые модификации и форки приветствуются. Теперь нет необходимости настраивать сложные среды разработки — достаточно дать вашему ИИ-агенту ссылку на репозиторий: https://github.com/isemaster/inkmetrics с инструкцией скачать, внести правки и залить на устройство.

Прошивка и образы снабжены версионированием прямо в комплекте, поэтому развертывание на новом компьютере не требует наличия установленного ESP-IDF или сборки из исходников. Потребуется лишь Python со стандартной утилитой esptool, либо можно обойтись вовсе без него, воспользовавшись веб-прошивальщиком прямо из браузера (Прошивальщик в браузере: https://isemaster.github.io/inkmetrics/flash-web/).

Кто автор

Проект реализован в тандеме разработчика и ИИ-агента. Если точнее, код писал агент Hermes, а я ставил задачи, проводил краш-тесты на «железе» и давал обратную связь по результатам. Микроконтроллер при этом был физически подключен к моему рабочему ПК, а агент выполнял сборку и перезагрузку дистанционно. Моя роль заключалась в визуальном контроле экрана и корректировке вектора разработки.

Общие затраты времени на отладку прошивки составили порядка 18 часов. Весь процесс разработки занял 12 сессий, включивших 75 подходов, 4767 отправленных сообщений и 2407 вызовов инструментов.

Подсчет велся следующим образом: сессия стартовала с моего сообщения и продолжалась до завершения диалога. Паузы с моей стороны дольше десяти минут фиксировали окончание текущего подхода на последнем ответе агента (время ночного отдыха и перерывов не учитывалось). Средняя продолжительность подхода составила 14,7 минуты при максимуме в 93 минуты.

Финансовая составляющая выглядит следующим образом. Облачный сервис DeepSeek обработал в рамках проекта 5,3 млн входных токенов, сгенерировал 4,0 млн выходных и потратил 2,2 млн токенов на внутренние рассуждения, а также перезагрузил 782 млн токенов из кэша (последнее представляет собой повторную передачу контекста со скидкой в десять раз). С учетом текущих расценок облачные затраты составили около 8 долларов (внутренняя статистика агента фиксирует 5,9 доллара, но базируется на устадавших тарифах).

Локальная языковая модель Qwen3.8-27B, запущенная на видеокарте, обработала 2,1 млн входных токенов и сгенерировала всего 168 тыс. выходных, выполняя преимущественно аналитическую работу: чтение дампов паники, исходников IDF и логов. Эта часть работы обошлась абсолютно бесплатно, если не считать затрат на электроэнергию.

Планы на будущее

В ближайших планах — реализовать частичное обновление электронной бумаги, чтобы избавиться от раздражающего моргания экрана при каждой смене кадров. Функция беспроводного обновления OTA пока не горит, поскольку девайс постоянно запитан по кабелю, однако под нее уже зарезвировано пространство в таблице разделов. Не исключено, что со временем я добавлю поддержку Wi-Fi для удаленного наблюдения за сервером через локальную сеть.

 

Источник

Поделиться:

Похожие статьи

Поиск по играм, новостям и статьям…

Введите не менее двух символов

Введите не менее двух символов