Xor

<<< Назад

Группа как объект - экономим на коде

Создаем группы объектов с помощью стандартных механизмов Мажордомо

just for fun

Добрый день, коллеги.

( Когда я занялся этой темой, честно говоря, не знал, что Сергей уже реализовал группы в ПУ. Но чтобы до них добраться, нужно войти в приложение Простые устройства и там уже создавать и настраивать группы.)

Как возникла идея о группах? Очень просто - объектов стало много и управлять ими трудно. Давно уже в коде стали появляться функции для массовой обработки объектов. Стали появляться спецсвойства - Отключать с рассветом, Включать с закатом, Выключать при экономрежиме, Включать при выходе из эконом режима и т.д.

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

Для этого создал класс Groups со свойствами Items - тут список имен объектов в группе.

Думал, как хранить список имён в текстовом поле?
Просто названиями через разделитель? Плюсы - легко править вручную, минусы - так же легко напортачить.
serialize/json? Плюсы - порядок, минусы - редактирование.

Подумал, что состав группы не так часто меняется и остановился на стандарте php - serialize.
Написал две функции для добавления/удаления объектов из группы:

/**
 * Добавим объект в группу
 * appObj2Grp("ObjectName","groupName");
 */
function appObj2Grp($objName, $grp) {
    if(!isset($grp)||!isset($objName))  return "no params"; 
     if(null == getObject($grp))  return "no group";  
     $grpObj = getObject($grp);
     if(null == getObject($objName) )  return "no object"; 

     $items = unserialize($grpObj->getProperty('Items')); //переведем в массив
     $items[] = $objName; //добавим наш объект
     $newItems = array_unique($items); //от греха избавимся от дублей

     $grpObj->setProperty('Items',serialize($newItems));//сохраним строку   
   return "ok";
}
function delObjFromGrp($objName, $grp) {
    if(!isset($grp)||!isset($objName))  return "no params"; 
     if(null == getObject($grp))  return "no group";
     $grpObj = getObject($grp);
     $list = $grpObj->getProperty('Items');//получим строку
        if(trim($list) == "") { //если пусто, нечего удалять
          $grpObj->setProperty('Items','a:0:{}');//сохраним строку
          return "ok";
        }
     $items = unserialize($list); //переведем в массив
     foreach($items as $key => $item){ //удалим по значению
        if ($item == $objName){
          unset($items[$key]);
        }
     }

    $newItems = array_unique($items); //от греха избавимся от дублей

    $grpObj->setProperty('Items',serialize($newItems));//сохраним строку
    return "ok";
}

Набиваю объектами и редактирую группы с помощью этих двух функций в консоли Панели управления предварительно создав новые группы в классе.

Методы класса:
setGroupProperty Установить всем объектам группы значение свойства(если есть - установится, если нет - новое не появится)

//setGroupProperty
if(!isset($params['property']))  return 0; //no param
$prop = $params['property'];
if(!isset($params['value'])){
 $value = 0; //по умолчанию
}else{
 $value = $params['value'];
}
$items = unserialize($this->getProperty('Items')); //переведем в массив
 foreach($items as $obj){ //переберем объекты
   $obj_prop = $obj.".".$prop; //object.property
   $rec = SQLSelectOne("SELECT * FROM `pvalues` WHERE `PROPERTY_NAME`='".$obj_prop."'");   
   if($rec) {
    sg($obj_prop,$value);
    echo('setGroupProperty '.$obj_prop.' set to '.$value.'<br>');
   }else{
    echo('setGroupProperty '.$obj_prop.' not find!<br>');
   }
 }

callGrpMethod Для всех объектов группы выполнить метод(если есть)

//callGrpMethod
if(!isset($params['mg']))  return 0; //no param
$mg = $params['mg'];
$obj_title = $params['ORIGINAL_OBJECT_TITLE'];
$items = unserialize($this->getProperty('Items')); //переведем в массив
foreach($items as $obj){ //переберем имена объектов группы
   eval('callMethodSafe("'.$obj.'.'.$mg.'",array("source" =>"'.$obj_title.'"));');
   usleep(50000);
   //echo('callGroupMethod ->'.$obj.'.'.$mg.' run <br>');
}
return 'grp method done';

Что это дает?
Допустим, у нас есть аналог группы Отключать_с_рассветом - grpSunriseOff, поместим туда нужные объекты и начнём ими управлять - при рассвете просто выполняем групповой метод callGrpMethod

 cm('grpSunriseOff.callGrpMethod',array("mg"=>"turnOff")); //в качестве параметра передается имя метода

Создадим группу Освещение - grpLights и включим туда все наши осветительные приборы - реле, диммеры, rgb-подсветку.
и теперь можем управлять освещением одним махом.

//Выключить весь свет везде
cm('grpLights.callGrpMethod',array("mg"=>"turnOff"));
//приведем всё освещение к запомненному состоянию после перезагрузки/аварии
cm('grpLights.callGrpMethod',array("mg"=>"refresh"));

Ещё несколько примеров:

//Перейдем в экономичный режим: Установим целевую температуру 18 для всех термостатов и включим у них режим Авто, если есть
cm('grpThermo.setGroupProperty',array('property'=>'temperature','value'=>18));
cm('grpThermo.setGroupProperty',array('property'=>'regime','value'=>'auto'));

//В комнате несколько окон с автошторами - объединим их группу
cm('grpKitchenBlinds.callGrpMethod',array("mg"=>"open")); 

В планах - создать методы групп:
расчет среднего, мин/макс, суммы заданного свойства объектов - на текущий момент, без истории.
Типа

$avglr = cm('grpLivingRooms.AvgGrpProperty',array('property'=>'temperature')); //узнаем среднюю температуру в жилых помещениях
$minlr = cm('grpLivingRooms.MinGrpProperty',array('property'=>'humidity')); //минимальная влажность в жилых помещениях
$sumpw = cm('grpThermo.SumGrpProperty',array('property'=>'power')); //суммарная мощность, отдаваемая сейчас конвекторами группы

Действующие ограничения - объектам в одной группе хорошо иметь (но не обязательно) одноименные свойства/методы(

Так уж нужно это в Мажордомо или нет, не знаю. Мне это помогло избавиться от спецсвойств в объектах и я не пишу циклы перебора foreach() в коде, убрав их в групповые методы.

upd. благодаря Логрусу, найдена и исправлена ошибка в методе вызова метода групп( кавычки, мать их)

Upd.add code for class method AvgGrpProperty/MinGrpProperty/MaxGrpProperty/SumGrpProperty/CountGrpProperty
Для соотв. метода раскоментировать нужную строку.

//пример вызова $avg = cm('myGroup.AvgGrpProperty',array('property'=>'propName');//среднее

//code for class method AvgGrpProperty/MinGrpProperty/MaxGrpProperty/SumGrpProperty/CountGrpProperty 
if(!isset($params['property']))  return "no property"; //no param
$prop = $params['property'];
$items = unserialize($this->getProperty('Items')); //переведем в массив
if(count($items) == 0) return "no objects";

$obj_prop = "'".implode("','",$items) . "'";  // 'obj1','obj2',...
$sql = "SELECT avg(`VALUE`+0.0) res FROM `pvalues` p join objects o on o.id=p.`OBJECT_ID` where `PROPERTY_NAME` like '%.".$prop."' and o.title in ($obj_prop) and not p.value is null";
//$sql = "SELECT min(`VALUE`+0.0) res FROM `pvalues` p join objects o on o.id=p.`OBJECT_ID` where `PROPERTY_NAME` like '%.".$prop."' and o.title in ($obj_prop) and not p.value is null";
//$sql = "SELECT max(`VALUE`+0.0) res FROM `pvalues` p join objects o on o.id=p.`OBJECT_ID` where `PROPERTY_NAME` like '%.".$prop."' and o.title in ($obj_prop) and not p.value is null";
//$sql = "SELECT sum(`VALUE`+0.0) res FROM `pvalues` p join objects o on o.id=p.`OBJECT_ID` where `PROPERTY_NAME` like '%.".$prop."' and o.title in ($obj_prop) and not p.value is null";
//$sql = "SELECT count(`VALUE`+0.0) res FROM `pvalues` p join objects o on o.id=p.`OBJECT_ID` where `PROPERTY_NAME` like '%.".$prop."' and o.title in ($obj_prop) and not p.value is null";
//echo $sql;
$rec = SQLSelectOne($sql);
return $rec['res'];

Методы очень похожи и, в принципе, их можно объединить в один, передавая функцию как параметр

Обсуждение (1) (6)

Смотрите так же:
20.11.2019 По следам наших выступлений - сколько мы наэкономили?
04.11.2019 Группа как объект - экономим на коде - 2
26.10.2019 Прикручиваем Grafana к Мажордому
25.09.2019 Если у вас нет телеги...
11.09.2019 Датчик присутствия из ип камеры
30.07.2019 Win-платформа-замена ffmpeg для получения скриншотов из rstp - потока
24.06.2019 Форматированный отчет в телеграм - имитация таблицы
30.04.2019 Используем зомбо-ящик в Мажордомо
24.03.2019 О среднем в Мажордомо
31.10.2018 Об "обделённых" пользователях Win-систем -- с точки зрения кэширования winTTS сообщений
16.09.2018 Перезагрузка Мажордомо в Win-системах

Домодедово, Россия

На форуме: xor