Важным аспектом функционирования системы управления Умным Домом является контроль состояния компонентов, её составляющих. В этой статье я покажу, каким образом можно организовать наглядный и эффективный контроль работы системы.
(Ремарка: ниже описывается процесс создания необходимых классов и методов, но, начиная с некоторой версии системы, эти данные уже созданы и готовы к использованию/модификации.)
Для вышеописанной задачи нам потребуется создать класс объектов systemStates. В этом классе мы будем создавать объекты "уровней состояния" (название условное, дальше будет понятней). Объектов будет несколько, т.к. они будут служить разным целям.
Уровень состояния это простая оценка качества состояния системы с той или иной точки зрения. Я выделил три основные показателя и добавил их как объекты созданного выше класса:
Comminication -- состояние систем связи
Security -- состояние систем безопасности
System -- состояние целостности функционирования системы
Для созданного выше класса systemStates добавляем следующие свойства:
stateColor -- условный цвет уровня
stateTitle -- название уровня
stateDetails -- детали текущего уровня состояния
Кроме того, добавляем следующие методы класса:
checkState -- метод проверки состояния системы по выбранному параметру
stateChanged -- метод, который будет вызываться в случае изменения состояния
Таким образом, мы создали три объекта и у каждого есть выше перечисленные свойства и методы. Для того, чтобы система могла за собой следить необходимо наполнить необходимым кодом методы checkState каждого из объектов, а так же организовать постоянный запуск этих методов. Последнее, кстати, уже встроено в систему в виде цикла/scripts/cycle_states.php, который автоматически запускается со стартом системы и ежесекундно запускает метод checkState для всех объектов класса systemStates, так что нам остаётся написать код метода checkState для каждого из созданных объектов.
Назначение кода checkState -- проверить какие-то показатели, принять решение о том, в каком состоянии находится система и установить соответствующий уровень.
Для начала реализуем проверку состояния коммуникаций. Считаем, что с ними всё в порядке, если есть соединение с интернетом и "пингуется" шлюз -- зелёный уровень. Если интернета нет, но шлюз доступен, то ставим жёлтый уровень. Если недоступен шлюз, то красный.
Для метода Communication.checkState установим следующий код:
Нажмите для отображения кода
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 |
$details=array(); $red_state=0; $yellow_state=0; if (!isOnline('Интернет')) { // в модуле "Устройства Online" должна быть запись с названием "Интернет" $yellow_state=1; $details[]="Нет доступа в интернет"; } if (!isOnline('192.168.0.1')) { // в модуле "Устройства Online" должна быть запись с IP-адресом либо названием "192.168.0.1" $red_state=1; $details[]="Не доступен шлюз и беспроводная сеть"; } if ($red_state) { $state='red'; $state_title='Красный'; } elseif ($yellow_state) { $state='yellow'; $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'); } |
Дальше сделаем код для проверки уровня безопасности (Security.checkState)
Нажмите для отображения кода
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 |
$details=array(); $red_state=0; $yellow_state=0; if ((gg('sensorEntry.status')==0) && (gg('sensorGarage.status')==0)) { $yellow_state=1; $details[]="Ворота и гараж открыты"; } elseif (gg('sensorEntry.status')==0) { $yellow_state=1; $details[]="Ворота открыты."; } if (!isOnline("192.168.0.115")) { $yellow_state=1; $details[]="Камера на втором этаже недоступна"; } if ((gg('ThisComputer.somebodyHome')==0) && (gg('sensorEntry.status')==0) && (gg('sensorGarage.status')==0)) { $red_state=1; $details[]="Дома никого нет, а ворота и гараж открыты"; } if ($red_state) { $state='red'; $state_title='Красный'; } elseif ($yellow_state) { $state='yellow'; $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'); } |
И, наконец, код для контроля целостности системы (System.checkState)
Нажмите для отображения кода
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 |
$details=array(); $red_state=0; $yellow_state=0; $cycles=array('states'=>'цикл проверки состояния','main'=>'главный цикл','execs'=>'цикл запуска команд','scheduler'=>'цикл планировщика'); foreach($cycles as $k=>$v) { $tm=getGlobal('ThisComputer.cycle_'.$k.'Run'); if (time()-$tm>5*60) { $red_state=1; $details[]="Остановлен ".$v; } } $cycles=array('ping'=>'цикл пинг','webvars'=>'цикл веб переменных','watchfolders'=>'цикл слежения за папками','rss'=>'цикл эр-эс-эс'); foreach($cycles as $k=>$v) { $tm=getGlobal('ThisComputer.cycle_'.$k.'Run'); if (time()-$tm>10*60) { $yellow_state=1; $details[]="Остановлен ".$v; } } if (isOnline('Контроллер Arduino 2')!==1) { $red_state=1; $details[]="Недоступен исполнительный контроллер"; } if (isOnline('Контроллер Arduino_RF_RCV')!==1) { $yellow_state=1; $details[]="Недоступен RF-приёмник"; } $sensors=array(); $sensors['sensorHumidityRemote3']="датчик влажности в спальне"; $sensors['sensorKotel']="датчик температуры на котле"; $sensors['sensorZal']="датчик температуры в зале"; $sensors['sensorTempRemote1']="датчик температуры в гараже"; $sensors['sensorTempRemote2']="датчик температуры в спальне"; $sensors['ws']="модуль погодной станции"; foreach($sensors as $k=>$v) { if (!gg($k.'.alive')) { $yellow_state=1; $details[]="Не обновляется ".$v; } } if ($red_state) { $state='red'; $state_title='Красный'; } elseif ($yellow_state) { $state='yellow'; $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'); } |
Следующим шагом нам нужно сделать вывод состояния системы. Можем для этого использовать "Меню управления". Добавим новый элемент типа HTML-блок:
В поле Data необходимо поместить следующий код
1 2 3 |
Безопасность: <span style="color:%Security.stateColor%">%Security.stateTitle%</span> %Security.stateDetails%<br> Система: <span style="color:%System.stateColor%">%System.stateTitle%</span> %System.stateDetails%<br> Связь: <span style="color:%Communication.stateColor%">%Communication.stateTitle%</span> %Communication.stateDetails% |
В итоге в меню мы будем видеть подобную картину:
Таким образом, получаем наглядную и оперативную сводку по состоянию системы.
Важное замечание: в виду того, что методы checkState вызываются каждую секунду, необходимо исключить использование "медленных" операций при опросе состояния систем, т.е. статусы подсистем (датчиков, модулей и т.п.) должны обновляться отдельно, а checkState их только проверяет и делает вывод об общем статусе.
Обсуждение статьи на форуме.