Main

Мониторинг состояния системы

Важным аспектом функционирования системы управления Умным Домом является контроль состояния компонентов, её составляющих. В этой статье я покажу, каким образом можно организовать наглядный и эффективный контроль работы системы.

(Ремарка: ниже описывается процесс создания необходимых классов и методов, но, начиная с некоторой версии системы, эти данные уже созданы и готовы к использованию/модификации.)

Для вышеописанной задачи нам потребуется создать класс объектов systemStates. В этом классе мы будем создавать объекты "уровней состояния" (название условное, дальше будет понятней). Объектов будет несколько, т.к. они будут служить разным целям.

Уровень состояния это простая оценка качества состояния системы с той или иной точки зрения. Я выделил три основные показателя и добавил их как объекты созданного выше класса:

Comminication -- состояние систем связи

Security -- состояние систем безопасности

System -- состояние целостности функционирования системы

Для созданного выше класса systemStates добавляем следующие свойства:

stateColor -- условный цвет уровня

stateTitle -- название уровня

stateDetails -- детали текущего уровня состояния

Кроме того, добавляем следующие методы класса:

checkState -- метод проверки состояния системы по выбранному параметру

stateChanged -- метод, который будет вызываться в случае изменения состояния

Таким образом, мы создали три объекта и у каждого есть выше перечисленные свойства и методы. Для того, чтобы система могла за собой следить необходимо наполнить необходимым кодом методы checkState каждого из объектов, а так же организовать постоянный запуск этих методов. Последнее, кстати, уже встроено в систему в виде цикла /scripts/cycle_states.php, который автоматически запускается со стартом системы и ежесекундно запускает метод checkState для всех объектов класса systemStates, так что нам остаётся написать код метода checkState для каждого из созданных объектов.

Назначение кода checkState -- проверить какие-то показатели, принять решение о том, в каком состоянии находится система и установить соответствующий уровень.

Для начала реализуем проверку состояния коммуникаций. Считаем, что с ними всё в порядке, если есть соединение с интернетом и "пингуется" шлюз -- зелёный уровень. Если интернета нет, но шлюз доступен, то ставим жёлтый уровень. Если недоступен шлюз, то красный.

Для метода Communication.checkState установим следующий код:

Нажмите для отображения кода

$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)

Нажмите для отображения кода

$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)

Нажмите для отображения кода

$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 необходимо поместить следующий код

Безопасность: <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 их только проверяет и делает вывод об общем статусе.

 
 

Обсуждение

 

sergejey: Обсуждение страницы Мониторинг состояния системы

pdmitry2: Сергей, а как сделать аналогично этому $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'); } но, для датчика температуры? Например, есть датчик со свойством temp_1.temp, как сделать, что бы если температура ниже 20 градусов, в меню управления висел красный статус, а как только температура поднимается выше 20 градусов, статус менялся бы на зелёный, ну и всё это с соответствующими уведомлениями. Поможете? ;)

sergejey: там в коде есть блок условий. например такое: if (!isOnline("192.168.0.115")) { $yellow_state=1; $details[]="Камера на втором этаже недоступна"; } можно заменить его на такое (или добавить под ним): if (getGlobal('temp_1.temp')<20) { $red_state=1; $details[]="Температура на датчике 1 ниже 20 градусов"; }

Satgate_M: Сергей, добрый день. Более менее разобрался, что за что отвечает, но никак не могу осилить обновление датчиков. внизу в коде есть параметр(где массив сенсоров задаем): .alive вот где надо создать это .alive и как его вызывать и что должно в нем быть чтобы сенсоры работали. По факту у меня сенсоры работают, но система пишет, что датчик не обновляется! Спасибо.

sergejey: Сергей, добрый день. Более менее разобрался, что за что отвечает, но никак не могу осилить обновление датчиков. внизу в коде есть параметр(где массив сенсоров задаем): .alive вот где надо создать это .alive и как его вызывать и что должно в нем быть чтобы сенсоры работали. По факту у меня сенсоры работают, но система пишет, что датчик не обновляется! Спасибо. Смотрите на моём профайле в коннекте как сделано. Если в кратце, то при обновления значения датчиков у меня устанавливается значение alive в 1 и задаётся таймер, который сбрасывает это значение в 0. Таким образом, если датчик регулярно присылает обновления, то alive будет всегда 1.

Satgate_M: Сергей, добрый день. Более менее разобрался, что за что отвечает, но никак не могу осилить обновление датчиков. внизу в коде есть параметр(где массив сенсоров задаем): .alive вот где надо создать это .alive и как его вызывать и что должно в нем быть чтобы сенсоры работали. По факту у меня сенсоры работают, но система пишет, что датчик не обновляется! Спасибо. Смотрите на моём профайле в коннекте как сделано. Если в кратце, то при обновления значения датчиков у меня устанавливается значение alive в 1 и задаётся таймер, который сбрасывает это значение в 0. Таким образом, если датчик регулярно присылает обновления, то alive будет всегда 1. В профайле нашел вроде эти alive, а вот какой код в них записан где можно посмотреть?

sergejey: вот, к примеру: http://c2n.me/6TBpaN.jpg

Satgate_M: Добавил в метод tempChanged и при изменении температуры почему-то ничего не происходит ни в alive ни в других полях ничего нет, только температура (снимок в приложении) И ни как не могу ни у кого получить как поменять статус системы со слов на разцоцветные иконки (антенна, шестерня и тп). Скриншоты ниже.

Satgate_M: и что это за параметр в таймере 30*60 например как перевести его в реальное время чтобы понимать период обновления?

sergejey: и что это за параметр в таймере 30*60 например как перевести его в реальное время чтобы понимать период обновления? 30*60 это 30 раз по 60 секунд, т.е. 30 минут

vladragor: уже разобрался...

Kiruxa: Добавил в метод tempChanged и при изменении температуры почему-то ничего не происходит ни в alive ни в других полях ничего нет, только температура (снимок в приложении) Добрый день! Как решил проблему? Данные идут от MQTT брокера. Метод TempChanged не срабатывает. Если зайти в настройки этого метода и выполнить вручную через консоль - Ошибка Parse error

[ Обсудить на форуме ]

 

MajorDomo

Информация

Проекты

Партнёры

edit SideBar

 
 
 

 

Blix theme adapted by David Gilbert, powered by PmWiki