Решил поделиться своей небольшой заготовкой для будущего умного дома.
Я считаю что любая система автоматического управления, тем более умная, должна иметь надежное питание, поэтому каждый инженер решает задачу, каким образом осуществить гарантированное питание своего детища. Есть многие способы решения, но в любом случае в системе присутствует аккумуляторная батарея. Ввиду того, что я оказался счастливым обладателем ИБП типа Ippon Back Power Pro 600VA, еще в старом (белом) корпусе, решил его применить. Забегая немного вперед, отмечу, что изначально хотел использовать Powercom IMP-425AP, но его не получилось привязать...
Итак, в качестве сервера у меня трудится/пыжится Raspberry Pi на Debian Wheezy (Raspbian) с установленными пакетами PHP5, Apache, MySQL и пр. Более подробно установка хорошо описана на сайте и форуме. Пока из периферии работают различные ардуины с Ethernet-шилдами. Планы конечно грандиозные, но сейчас более конкретно.
Сам ИБП у меня подключен не напрямую, через вводной автомат с доп. контактами и реле на два перекидных контакта (см. схему) в качестве сервисного байпаса, чтобы можно было безболезненно ИБП вывести в ремонт.
Мой бесперебойник имеет на борту порт RS-232 и USB для интеграции. ИМХО, схема интеграции в систему MDM должна быть примерно такая:
--------
Моя идея мониторинга ИБП такова: в MDM можно в классе systemStates создать объект UPS с сопутствующим классу свойством - условный цвет системы питания.
Зеленый - питание в норме, связь с ИБП есть.
Желтый - отсутствует внешнее питание, система работает от АКБ
Красный - отсутствует внешнее питание, система работает от разряженной АКБ
Серый - нет связи с ИБП.
Соответственно рядом с иконками системы, коммуникаций и защиты расположить меняющую цвет иконку ИБП.
Дополнение 1. Можно извлекать дополнительные данные, например, напряжение на входе в ИБП, на выходе, емкость АКБ, температуру и пр.
Дополнение 2. В будущем попробую реализовать управление ИБП через shell-скрипт, например, отключать пищалку ночью, запускать тестирование АКБ и пр.
Дополнение 3. С корректным shutdown пока не разобрался, мой ИБПшник что то мудрит, работает как ему вздумается))
--------
Условно реализацию можно разделить на этапы.
1. Установка ПО на сервер для обмена данными с ИБП по цифровому интерфейсу USB. Передача информации о состоянии ИБП и управляющих команд.
Неглубокий поиск на просторах всемирной паутины привел меня к универсальному решению для интеграции практически любого ИБП в Linux-систему - программный продукт Network UPS Tools или коротко - NUT. Его используют даже в коммерческих системах - т.е. это ПО довольно надежное. Теперь смотрим как обстоят дела с поддержкой моего ИБП Ippon Back Power Pro 600VA, для этого переходим по ссылке compatible UPS, выбираем нашу модель ИБП и видим, что подключение по USB необходимо осуществлять с помощью универсальных драйверов blazer_usb.
Используя опыт других пользователей в инете и ознакомившись с документацией, получилась следующая схемка:
Не буду подробно описывать установку, подобных манов полно в интернете, приведу лишь тексты файлов конфигураций:
nut.conf
Код: Выделить всё
MODE=standalone
Код: Выделить всё
[ippon-600]
driver = blazer_usb
port = auto
desc = "Ippon Back Power Pro 600"
default.battery.voltage.high = 13.60
default.battery.voltage.low = 10.60
Код: Выделить всё
LISTEN 127.0.0.1 3493
Код: Выделить всё
[admin]
password = admin123
actions = SET
instcmds = ALL
[monmaster]
password = master123
upsmon master
[monslave]
password = slave123
upsmon slave
Код: Выделить всё
#ippon-600 - название ИБПшника из файла ups.conf
#monmaster master123 - имя пользователя и пароль из файла upsd.users
MONITOR ippon-600@localhost 1 monmaster master123 master
MINSUPPLIES 1
SHUTDOWNCMD "sudo halt -t now" #комадна выключения сервера
NOTIFYCMD "/var/lib/nut/nutalert" #при изменении состояния ИБП выполнить этот скрипт
POLLFREQ 5
POLLFREQALERT 5
HOSTSYNC 15
DEADTIME 100
POWERDOWNFLAG /var/lib/nut/killpower
#эти сообщения будут записываться в лог-файл и передаваться в скрипт NOTIFYCMD
NOTIFYMSG ONLINE "UPS on line power" #"UPS %s on line power"
NOTIFYMSG ONBATT "UPS on battery power" #"UPS %s on battery"
NOTIFYMSG LOWBATT "UPS battery low" #"UPS %s battery is low"
NOTIFYMSG FSD "UPS %s: forced shutdown in progress"
NOTIFYMSG COMMOK "UPS commok" #"Communications with UPS %s established"
NOTIFYMSG COMMBAD "UPS commbad" #"Communications with UPS %s lost"
NOTIFYMSG SHUTDOWN "Auto logout and shutdown proceeding"
NOTIFYMSG REPLBATT "UPS %s battery needs to be replaced"
NOTIFYMSG NOCOMM "UPS nocomm" #"UPS %s is unavailable"
NOTIFYMSG NOPARENT "upsmon parent process died - shutdown impossible"
#какие предпринять действия при изменении состояния ИБП.
#syslog - запись в системный лог, exec - выполнение скрипта из секции NOTIFYCMD
NOTIFYFLAG ONLINE SYSLOG+EXEC
NOTIFYFLAG ONBATT SYSLOG+EXEC
NOTIFYFLAG LOWBATT SYSLOG+EXEC
NOTIFYFLAG FSD SYSLOG+WALL
NOTIFYFLAG COMMOK SYSLOG+EXEC
NOTIFYFLAG COMMBAD SYSLOG+EXEC
NOTIFYFLAG SHUTDOWN SYSLOG+WALL
NOTIFYFLAG REPLBATT SYSLOG+WALL
NOTIFYFLAG NOCOMM SYSLOG+EXEC
NOTIFYFLAG NOPARENT SYSLOG+WALL
RBWARNTIME 43200
NOCOMMWARNTIME 300
FINALDELAY 5
Для оперативной передачи состояния ИБПшника в МДМ, я написал shell-скрипт, который вызывается демоном UPSMON с передачей ему сообщения (непосредственно сообщение и несет смысловую нагрузку состояния ИБП). Текст скрипта:
Код: Выделить всё
#!/bin/bash
case "$1" in
"UPS on line power") curl "http://127.0.0.1/objects/?object=UPS&op=m&m=checkInputState&stateColor=green" ;;
"UPS on battery power") curl "http://127.0.0.1/objects/?object=UPS&op=m&m=checkInputState&stateColor=yellow" ;;
"UPS battery low") curl "http://127.0.0.1/objects/?object=UPS&op=m&m=checkInputState&stateColor=red" ;;
"UPS commbad") curl "http://127.0.0.1/objects/?object=UPS&op=m&m=checkInputState&stateColor=grey" ;;
"UPS nocomm") curl "http://127.0.0.1/objects/?object=UPS&op=m&m=checkInputState&stateColor=grey" ;;
"UPS commok")
STATEUPS=`upsc ippon-600@localhost ups.status`
case "$STATEUPS" in
"OL") curl "http://127.0.0.1/objects/?object=UPS&op=m&m=checkInputState&stateColor=green" ;;
"OB") curl "http://127.0.0.1/objects/?object=UPS&op=m&m=checkInputState&stateColor=yellow" ;;
"LB") curl "http://127.0.0.1/objects/?object=UPS&op=m&m=checkInputState&stateColor=red" ;;
*) curl "http://127.0.0.1/objects/?object=UPS&op=m&m=checkInputState&stateColor=green" ;;
esac
;;
*) curl "http://127.0.0.1/objects/?object=UPS&op=m&m=checkInputState&stateColor=green" ;;
esac
exit 0
Но возникает вопрос, если связь с ИБП восстановилась - как узнать, в каком он состоянии сейчас? В программном пакете есть набор команд "upsc". Если в консоли набрать команду "upsc [вашИБП]@localhost", в окне появится информация о бесперебойнике. Можно уточнить запрос дописав интересующее свойство, например "ups.status" или "ups.input.voltage" и пр., в ответ будет состояние именно этого свойства. Соответственно после восстановления связи я отсылаю запрос на текущее состояние ИБП. Ну строка "http://127.0.0.1/objects/?object=UPS&op ... olor=green" думаю многим знакома, тут расписывать нечего. Вызываем метод "checkInputState" объекта "UPS" с передачей ему параметра "stateColor" в состоянии "green".
3. Прием и обработка данных в Majordomo.
Как писал выше, я создал новый объект "UPS" в классе "systemStates". Вместо стандартного метода "checkState", который вызывается автоматически, создал новый "checkInputState" чтобы его можно было вызывать вручную. Метод типа php-скрипт:
Код: Выделить всё
$details=array();
$t=$params['stateColor'];
$red_state=0;
$yellow_state=0;
$grey_state=0;
if ($t == "red") {
$red_state=1;
$details[]="Батарея ИБП разряжена";
}
if ($t == "yellow") {
$yellow_state=1;
$details[]="Работа от аккумуляторов ИБП";
}
if ($t == "grey") {
$grey_state=1;
$details[]="Нет связи с ИБП";
}
if ($red_state) {
$state='red';
$state_title='Красный';
} elseif ($yellow_state) {
$state='yellow';
$state_title='Жёлтый';
} elseif ($grey_state) {
$state='grey';
$state_title='Серый';
} else {
$state='green';
$state_title='Зелёный';
}
$this->setProperty('stateDetails',implode(". ",$details));
if ($this->getProperty('stateColor')!=$state) {
$this->setProperty('stateColor',$state);
$this->setProperty('stateTitle',$state_title);
if ($state!='green') {
say("Уровень системы питания изменился на ".$state_title.".");
say(implode(". ",$details));
} else {
say("Уровень системы питания восстановлен на ".$state_title);
}
$this->callMethod('stateChanged');
}
Саму иконку скачал в инете, подрисовал в фотошопе, если кому надо, могу выложить...
И вот тут всплыл еще один косяк. После полной перезагрузки малинки или при первом включении система почему то не отрабатывала переход от цвета серого (драйвер видимо не успевал стартовать) к цвету зеленому (все ОК). Поэтому пришлось запускать раз в минуту еще один скрипт. Данный сценарий "SystemInfo_UPS" прописал в методе "onNewMinute" и вызываю раз в минуту. Смысл - так сказать еще раз удостовериться, в каком состоянии ИБП на данный момент.
Код: Выделить всё
//Скрипт проверки состояния ИБП.
//Если вдруг upsmon не смог передать изменение состояния в MDM.
$UPS_state=exec("upsc ippon-600@localhost ups.status");
//$UPS_state="LB";
switch ($UPS_state) {
case "OL":callMethod("UPS.checkInputState",array("stateColor"=>"green"));break;
case "OL TRIM":callMethod("UPS.checkInputState",array("stateColor"=>"green"));break;
case "OB":callMethod("UPS.checkInputState",array("stateColor"=>"yellow"));break;
case "LB":callMethod("UPS.checkInputState",array("stateColor"=>"red"));break;
//default:
// callMethod("UPS.checkInputState",array("stateColor"=>"green"));
};
P.S. Согласен, что получилось слишком мудрено и сложно, можно было просто в методе "checkState" объекта "UPS", который вызывает автоматически, получить строку командой типа "$UPS=exec("upsc ippon-600@localhost");" и потом парсить её как душе угодно. Но мне хочется разобраться как работает демон UPSMON, ведь с его помощью можно корректно завершать работу не только малинки, но и других потребителей питания от этого ИБПшника - благо клиентов для NUT достаточно, даже для винды есть.