Терминал для домашнего Linux сервера на базе ESP8266

c7855f85896b49fca445ce4347fa9d73.png

Введение


Данное устройство служит для удалённого доступа к Linux серверу посредством последовательного порта и позволяет отказаться от локальных монитора и клавиатуры. Зачем оно нужно если есть SSH и VNC? Нужно в виду ряда проблем, связанных с управлением на этапе загрузки системы и управлением питанием:

  • Выбор загружаемой ОС, вход в recovery mode, memtest. Нажатие S во время загрузки при невозможности смонтировать одну из файловых систем, управление fsck во время загрузки.
  • Ввод пароля от зашифрованного корневого раздела во время загрузки. Приходилось в initramfs устанавливать dropbear действующий на этапе загрузки. Пароль вводился по SSH. Хочу отметить, что данный способ непросто мне давался в плане конфигурации, на популярных дистрибутивах приходилось править скрипты загрузки и использовать некоторые костыли, которые переставали работать с выходом новых релизов.
  • Удаленное выключение и включение. С первым затруднений никогда не было, а вот для включения приходилось применять технологию Wake-on-LAN (WOL), магический пакет посылался с маршрутизатора и сервер включался, правда не всегда, а только тогда когда в конфигурационных регистрах сетевой карты были «правильные» значения перед выключением, которые должна была внести туда ОС.
  • Отказы после отключения электричества и некорректной работы UPS, вкупе с автоматическим включением настроенном на материнской плате.
  • К сожалению, оборудование моего домашнего сервера не промышленное и не обладает высокой степенью надежности. То же касается и программного обеспечения, зачастую работают «сырые» модули ядра. В следствие чего не раз сервер «зависал» не отвечая ни по сети, ни на нажатие клавиш клавиатуры. Приходилось использовать аппаратный сброс зажимая кнопку питания более чем на 3 секунды.

На промышленном оборудование таких проблем нет, в пример можно привести решение HP iLO позволяющее удаленно хоть систему устанавливать, не говоря о таких вещах как управление питанием и диагностика системы. Кстати говоря у них есть продукты и для дома/малого бизнеса с этим решением. Но так сложилось, что система строилась на базе обычной miniITX материнской платы без таких возможностей.
Появилась необходимость в устройстве которое бы позволяло:

  • Быть доступно по сети
  • Взаимодействовать с загрузчиком и ОС сервера, хотя бы в текстовом режиме
  • «Железно» взаимодействовать с кнопкой питания и иметь возможность замкнуть контакты этой кнопки дольше чем на 3 секунды для принудительного выключения
  • Менять настройки BIOS (EFI) (пока не решено, доступно только для некоторых материнских плат)


Известный факт, что раньше применялись текстовые терминалы, подключаемые к последовательному порту машины. Исторически сложилась поддержка терминала в Linux и загрузчике grub. На современных материнских платах данный порт отсутствует в привычном виде внешнего разъема DB-9, но практически всегда разведен на внутренней 10-контактный разъем.

С появлением копеечного ESP8266, по сути своей моста между Wi-Fi и UART, появилась идея реализации сетевого терминала на его базе, с функционалом управления питанием.

Помимо ESP8266 есть разные варианты
Применение маршрутизатора с OpenWRT или подобной прошивкой. Соединение UART’a маршрутизатора с последовательным портом через MAX232 (или подключение USB — RS232 адаптера), а свободного GPIO, в случае наличия, с кнопкой питания. Этот вариант, кстати говоря, был реализован и некоторое время проходил опытную эксплуатацию.

Еще рассматривалось микроконтроллерное устройство работающее в связке с мобильным телефоном в тональном режиме или по СМС, замыкающее контакты кнопки вкл./выкл., эмулирующее клавиатуру. Отклонено из за дополнительных расходов и сомнительной обратной связи. Навеяно этим.

Принципиальная схема


cc5d51e735d34dba97b6e58db1485885.png
Основной элемент — ESP8266 (ESP-03), имеет Wi-Fi для связи с внешнем миром, UART для связи с сервером, и пару GPIO, на которые были повешены светодиод индикатор состояния и реле для замыкания кнопки питания. Осталось пару свободных GPIO, которые впрочем можно применить и для подключения I2C, 1-Wire и прочих датчиков и устройств.
Применена распространенная микросхема MAX232 для преобразования UART с ESP8266 в RS-232. MAX232 питается от 5В, тогда как ESP8266 через преобразователь LM1117 5–3.3В, на всякий случай на RX линию ESP8266 применен делитель напряжения приводящие 5В с вывода MAX232 в 3.3В. Выход MAX232 разведен на два разъема, один для подключения к DB-9 второй IDC-10 для подключения прямым шлейфом прямо к контактам на материнской плате. Реле используется для замыкания контактов кнопки питания ПК и подключается параллельно с кнопкой на корпусе. Кстати, для для подключения кнопки питания с корпуса системного блока можно предусмотреть разъем на плате, у меня это реализовано через двойник для 2.54 выводов на разъёме материнской платы. Вообще решение с применением реле спорное. Хватило бы транзистора. В макете я заложил оптопару 817, она не сработала, были приняты радикальные меры и включено реле… подействовало. Пусть будет, может потом пригодится замыкать/размыкать цепи 220В, кроме того слышно щелчки — полезно для диагностики. P6 — разъем для удобства программирования через китайские адаптеры для arduino на FTDI. В режим программирования включается джампером JP1. Питается устройство через разъем P4 напрямую от дежурного напряжения блока питания или от USB порта. Разъем P1 служит для подключения внешней антенны.

Возможные пути развития
  • Управление контактами сброса CMOS
  • Подключение датчика температуры, например для контроля температуры блока питания
  • Подключение концевика вскрытия корпуса

Печатная плата


Однослойная, но вышло целых 5 перемычек.
ee5c2c5e68de483ba7f53a535b744ed1.png

Топорно изготовлена на дому
806937b100874fd1994fd4f5b3804bce.jpg
Старая версия без разъема P6.

Прошивка


Простейшая, состоит из одного сервера TELNET — собственно для обмена. Все, что появляется в UART выбрасывается всем клиентам TELNET, все, что приходит от клиентов выбрасывается в UART. Так же прикручены AT команды для управления кнопкой питания и настройки параметров порта и Wi-Fi. Хотя если говорить честно, это далеко не сервер RFC 854, команды не поддерживаются, TELNET называю потому, что порт 23, обмен прямым текстом, и клиенты TELNET отлично подходят для взаимодействия (опробовано на Android клиенте ConnectBot и Linux утилите telnet, у меня корректно заработало с переменной окружения export TERM=VT100, параметром -8 и последующем переходом в посимвольный режим ^]mode character).
Примечательная особенность, ESP8266 может работать и как точка доступа и как клиент беспроводной сети одновременно. Это очень важно для отказоустойчивости — позволяет подключится к терминалу в случае отказа сетевого оборудования.
Изначально была написана прошивка на Sming. Главный плюс Sming в том, что не надо разбираться в китайском SDK ESP8266, для всех нужд уже есть удобоваримая обертка, будь то WEB сервер, обновление прошивки по воздуху или работа с GPIO. Но при использование обертки TCP сервера для реализации TELNET при передаче больших объемов соединение рвалось, а ESP8266 висла. Были попытки оперировать напрямую АПИшкой lwip…
Но на этом этапе я наткнулся на проект ESP8266-transparent-bridge. Было решено просто напросто его форкнуть для реализации команд управления кнопкой питания, все остальное уже было сделано его автором. Бала добавлена команда AT

+++AT PWBTN  # замыкание кнопки питания на пол секунды | четыре секунды | четыре, пауза в одну и снова на пол секунды

В прошивке есть изъян. Если на терминал вывести единовременно большой объем информации то часть данных может потеряться. Все же ESP8266 это не Moxa NPort и возможности ограничены. Например, если сделать dmesg то мы увидим только часть данных, так что приходится чаще использовать grep more и less и избегать длинных выводов на экран. Вообще говоря стоит в прошивке попробовать увеличить буфер передачи, сейчас он всего 1024 байта, пока руки не доходили, сделать его 32768 и может быть станет комфортно работать с утилитами вроде htop.

Конфигурация Linux машины


В /etc/default/grub должно быть что то вроде:

GRUB_CMDLINE_LINUX="console=ttyS0,115200n8"
GRUB_TERMINAL=serial
GRUB_SERIAL_COMMAND="serial --speed=115200 --unit=0 --word=8 --parity=no --stop=1"


Для вывода меню загрузчика и сообщений загрузки в последовательный порт. В данном случае первый с битрейтом 115200. После редактирования следует выполнить команду update-grub. В принципе этим можно ограничиться, но на всякий случай еще можно открыть терминал на последовательном порту, для этого создать /etc/init/ttyS0.conf следующего содержания:

# ttyS0 - getty
#
# This service maintains a getty on ttyS0 from the point the system is
# started until it is shut down again.

start on stopped rc or RUNLEVEL=[2345]
stop on runlevel [!2345]
#
respawn
exec /sbin/getty -L 115200 ttyS0 vt102


Подключение к серверу
Как уже было сказано питание берется напрямую от дежурного напряжения блока питания или от USB порта, выводы реле подключаются параллельно кнопки питания, Контактная площадка RS-232 соединяется прямым шлейфом с разъемом типа IDC-10. Есть нюанс размещения устройства внутри корпуса сервера, требуется вывести за корпус Wi-Fi антенну подключаемую к u.fl разъему устройства. Это конечно можно не делать если корпус относительно радиопрозрачный, например изготовлен из дерева.

cc167647b315495eafaf671f7b37b084.jpg

Подсчет стоимости


$3 за ESP8266, $1 за 10 штук MAX232, остальное обычно есть в хозяйстве.

Видео демонстрация

Исходники железа и софта тут.

© Geektimes