Система мониторинга сервера с управлением по SMS

Тема в разделе "Глядите, что я сделал", создана пользователем eof, 25 май 2017.

  1. eof

    eof Нерд

    Привет!
    Зацените систему мониторинга сервера/компьютера с управлением по СМС.
    Система позволяет управлять питанием компьютера (on/off, reset), сбрасывать питание маршрутизатора/точки доступа, USB-модема.
    Также возможно мониторить температуру, влажность, уровень шума, присутствие того или иного питания; можно позвонить на устройство и при подключении звуковой аппаратуры "пообщаться" с удаленной точкой, а можно нажав кнопку позвонить с устройства на первый номер в адресной книге.
    Есть функция авторизации входящих звонков и СМС по номерам, хранящихся в EEPROM. Возможно включить пересылку СМС с незнакомых номеров. Адресная книга редактируется через COM-порт. И наконец устройство снабжено автономным питанием от аккумулятора, параметры авторизации, отправки/пересылки СМС хранятся в EEPROM.

    В далеком 2014 году решил я заняться темой проброса физической видеокарты в виртуальную машину.
    Но вот не задача - компьютер дома, а время этим заниматься на работе. Частенько в процессе экспериментов удаленная система зависала от слова совсем, и удаленный доступ в любом виде оказывался бесполезен. Нужна была удаленная кнопка reset...
    Короче, помимо ресета было решено добавить еще немного функционала типа мониторинга питания, температуры, уровня шума, а также возможность сброса питания маршрутизатора и USB-модема.
    Изначально за основу была взята Arduino Ethernet, но, как показала практика, памяти в ней настолько мало, что до применения Ethernet-порта дело вообще не дошло. Так и работала эта система в недоделанном виде живя в коробочке, однако неоднократно меня выручавшая.

    За основу обновленной системы версии взята Iskra Neo, на ней: SeeedStudio Energy Shield, SeeedStudio GPRS Shield V2.0, Amperka Relay Shield.
    Также используются кнопка и светодиод от Амперки, датчик температуры/влажности DHT11 и датчик шума от DFRobot, макетка с 3 делителями напряжения и внутренности USB-хаба. Корпус собран из #структора.
    Один из портов хаба подключен к Neo, еще два выведены на корпус.

    В итоге скоммутировано все таким образом:
    1 реле NO-контакт подключен параллельно кнопке питания компьютера;
    2 реле NO-контакт подключен параллельно кнопке сброса компьютера;
    3 реле NС-контакт подключен в разрыв питания маршрутизатора (можно подключить NO к кнопке сброса, если таковая имеется);
    4 реле NС-контакт подключен в разрыв питания USB порта на корпусе устройства;
    Поскольку в первой версии я использовал Arduino Ethernet - количество свободных портов было ограничено, для экономии управление реле было сделано через GPIO-модема. В этот раз решил оставить как есть.

    Делители напряжения построены на 100 кОм резисторах.
    1 делитель - vin. Сейчас у меня устройство питается от БП компьютера, поэтому по напряжению на vin я сужу включен компьютер или нет. При питании от сети можно судить о наличии напряжения в сети.
    2 делитель - напряжение на USB-хабе (чтобы не получить здесь +5В при фактически отключенном USB-кабеле питание +5В на плату подается через диод, следовательно питание от USB-хаба невозможно, однако в этом случае по наличию питания на хабе можно судить о том включен компьютер или нет).
    3 делитель - напряжение резервной батареи (я использую старый аккумулятор от телефона на 1200 мАч).

    В качестве библиотеки для работы с модемом используется симбиоз библиотек от SeeedStudio и Амперки (которая судя по всему корнями также уходит к Seeed). Библиотеки пришлось существенно доработать - так, например, прием СМС у Seeed реализован через SIM-карту, у Амперки в последовательный порт, но в оригинале работает через раз. Seeed не умеет работать с портом Serial1 на Leonardo, а библиотека от амперки не умеет гарантированно принимать и СМС и звонки, т.к. обработка этих событий от модема реализована в разных функциях и если одна уже считала данные с порта, то второй они не достанутся... В общем, написал новую функцию, которая умеет ловить и СМС и звонки + переписал функции управления питанием под плату от Seeed.

    В первой версии у меня использовались куски от этой тяжеловесной библиотеки. Она реально сжирала 80% доступной памяти, в результате приходилось экономить на всем. Команды максимум по 3 буквы, скудный вывод для отладки... Это было ужасно.

    В этот раз при написании программы, помятуя прошлый опыт, я хорошенько постарался сэкономить память. По максимуму используются глобальные переменные (тру программистов прошу не пинать, сам плачу когда вижу такое), для которых память выделяется заранее, особенно это важно для больших буферов в десятки и сотни символов, которые постоянно используются повторно в разных функциях. Большие строки хранятся не в коде, а в EEPROM и достаются оттуда по необходимости. В результате при полной реализацией "хотелок" имеем:
    Даже есть куда "прикрутить" еще пару-тройку датчиков :)

    Единственный недостаток такой экономии - при первой прошивке в watchdog_3.h надо закомментить MAIN и раскомментить INIT
    Код (C++):

    //#define INIT
    #define MAIN
     
    Залить прошивку, набрать в отладке "fill", чтобы инициализировать EEPROM. Далее вернуть комменты и прошить заново.

    Также для работы потребуется библиотека от Амперки для DHT11, установленная стандартным способом.

    Вот так как-то.
     

    Вложения:

    ИгорьК нравится это.
  2. ИгорьК

    ИгорьК Гуру

    Славный шедевр программирования.
    Вопрос такой - это очередной ПДУ от телевизора, или устройство мониторит параметры и САМО принимает решения о перезагрузка? Из описания не понял.
     
  3. eof

    eof Нерд

    Была такая идея, но как показала практика это не требуется. Если я что-то делаю с удаленным компьютером, то я могу предположить, что произошло и перезагрузить руками.
    Если внезапно пропала связь с компьютером - можно попробовать перезагрузить сетевое оборудование после звонка провайдеру, но решение все равно за мной.
    Опять же, можно запросить состояние датчиков и увидеть, включен компьютер или нет, а при питании устройства от БП воткнутого в розетку - есть ли электричество в помещении.
    Ну и при небольшом допиливании можно сделать автоматическое уведомление по СМС об отключении электричества/компьютера.
    Еще была мысль написать службу, которая бы проверяла соединение с сетью, уровень заряда ИБП его состояние, состояние RAID-массивов и делилась бы данными с устройством, соответственно было бы больше информации для автоматического принятия решения о перезагрузке того или иного устройства.
    Но это потом.
     
  4. AlexU

    AlexU Гуру

    Строки по сути константы -- лучше хранить во flash. А EEPROM использовать для хранения настроек устройства.
    Это недостаток не экономии, а организации хранения данных. Как уже говорил строки желательно поместить во flash, данные с настройками в EEPROM -- смотрите описание макросов PROGMEM и EEPROM EEMEM. При сборке проекта (компиляции и т.п.) будет сформировано два hex файла -- один для заливки во flash, другой для заливки в EEPROM. Эти два файла нужно будет залить в микроконтроллер без всяких не понятных действий вида:
    Вообще если правильно декларировать переменные, то вот это:
    Код (C++):
    /*
    * EEPROM mapping
    * 1024 Kb
    * 10 x 16 = 160 - address book  | first addr 0
    * 16 x  1 =  16 - parameters    | first addr 160
    * 24 x 16 = 384 - commands      | first addr 176
    *  4 x 32 = 128 - short strings | first addr 560
    *  4 x 64 = 256 - long strings  | first addr 688
    * -------------
    *           944 bytes
    *           80 bytes free
    */
    за Вас сделает компилятор. Правильное декларирование переменных (с использованием макросов EEPROM EEMEM и PROGMEM) в свою очередь сильно упростит исходный код программы -- сможете избавится от лишних действий по вычислению адреса данных в памяти (той же EEPROM).
    Зачем делать то, что может сделать компилятор?
     
    Последнее редактирование: 26 май 2017
    eof нравится это.
  5. eof

    eof Нерд

    Действительно получился велосипед с EEPROM, надо будет переделать...
    Про PROGMEM я нашел документацию, но вот про аналогичный макрос EEPROM что-то не вижу, есть только это, чем я собственно и пользовался. Или имеется ввиду какая-то иная среда разработки?
    В любом случае, спасибо!

    PS Это ж вообще все константы можно во флеш закинуть...
     
  6. eof

    eof Нерд

    Нашел. Называется макрос EEMEM. Обсуждение на форуме arduino.cc.
    Как я понял макрос лишь определяет адрес переменной, к которой все равно нужно будет обращаться через read и write.
    Ну а этот комментарий в примере вообще не радует:
    Код (C++):
    // A EEMEM structure or EEMEM variable is not located somewhere.
    // The compiler uses it only to calculate offsets.
    // When more EEMEM variables are used, the order is defined
    // by the compiler.
    // With a new compiler, that [B]order in EEPROM might change[/B].
    Таким образом, имеет смысл объявлять единственную структуру с EEMEM, дабы не нарваться на внезапное изменение адресов по воле компилятора.
     
  7. AlexU

    AlexU Гуру

    Прошу прощения, ввёл в заблуждение. Макрос действительно называется EEMEM.
    Да, но это из-за не доработок компилятора avr-gcc, который так же используется в Arduino IDE. Eсть компиляторы для AVR, которые правильно обработают чтение/запись в такую переменную. Вроде как IAR или CodeVision это умеет делать.
    Объявлять единственную структуру не обязательно. Ну раскидает компилятор по EEPROM как ему захочется, Вы же всё равно будете к ним обращаться через переменные. И компилятор будет знать к какой ячейке EEPROM нужно обращаться.
    Другое дело если захотите изменять содержимое EEPROM минуя прошивку, т.е. прошивать конфигурационные данные внешними средствами. Но в этом случае нужно как-то линковщику сказать каким образом компоновать переменные в памяти. На этот вопрос я пока не готов дать ответ...
    И да, единственную структуру компилятор так же может разместить где угодно (хотя он всегда начинает с нулевого адреса), поэтому закладываться на это не стоит.
     
  8. eof

    eof Нерд

    Тыдыщ!
    Обновленная версия со строками во флеше.
    Стало:
    Почти без изменений, но кода действительно стало меньше и теперь не надо заранее инициализировать EEPROM :)

    Еще раз спасибо за наводку, буду пользовать :)
     

    Вложения: