Class properties:
Class methods:
$s=$params['status']; if (isset($s)) { // Если некорректные данные if (($s > 6) || ($s < 0)) { return; } // Записать в свойство объекта $this->setProperty('status',$s); } else { // Для слинкованных свойств и запуска этого метода без передачи данных $s = $this->getProperty('status'); } switch ($s) { case 0: $t='Процесс завершен'; say('Завершение процесса дистилляции'); $this->setProperty('tmaxColumn', 0); $this->setProperty('tempCube', 0); $this->setProperty('tempColumn', 0); $this->setProperty('tempStartColumn', 0); $this->setProperty('startPercentCube',0); $this->setProperty('currentPercentCube',0); //sg('cycle_alcoControl','stop'); break; case 1: $t='Разогрев куба'; $this->setProperty('tmaxColumn', 0); $this->setProperty('tempCube', 0); $this->setProperty('tempColumn', 0); sg('cycle_alcoControl','start'); setTimeOut($ot.'_status_Timer',"say('Напоминаю о продлении таймера работы печи', 2);", 25*60); break; case 2: $t='Готовность к началу'; break; case 3: $t='Работа на себя'; break; case 4: $t='Отбор головных фракций'; say('Дальнейшее переключение стадий вручную', 2); break; case 5: $t='Отбор тела'; break; case 6: $t='Отбор хвостов'; break; } // Убрать задержду для следующего сообщения $this->setProperty('notifyTime',0); // для титула переключателя в меню $this->setProperty('titleStage',$t); $this->setProperty('log',date('h:m').' '.$t); if ($s) { say("Стадия $s. $t"); }
/* $p - имя датчика $s - температура $status - стадия работы $tmax - максимальная температура колонны в разных режимов + rnd для движения живого графика */ // должно быть передано имя свойства датчика // $params['tempCube'] или $params['tempColumn'] $p = key($params); $s = current($params); $status=$this->getProperty('status'); if (isset($s)) { // Если некорректные данные if (($s > 150) || ($s < 5)) { return; } // Записать в свойство объекта $s=round($s, 3); $this->setProperty($p, $s); } else { say('не передано имя свойства'); return; } /* максимальная температура колонны расчитывается при изменении температуры куба если пришли данные колонны, то читаем её из свойства */ if ($p=='tempColumn') { $tmax=($this->getProperty('tmaxColumn')); } $ot=$this->object_title; // playsound($p.'.wav'); switch ($status.$p) { /* --------- разогрев --------- */ case '1tempCube': //$tmax=40; $tmax=34; // переключить на стадию 2 при разогреве куба до 85 градусов. ToDo расчитать по указанной спиртуозности if ($s>85) { say('Скоро начнется процесс дисциляции', 2); $this->setProperty('log',date('h:m').' Скоро начнется процесс'); $this->callMethod('statusChanged', array('status'=>2)); } break; case '1tempColumn': // переключить на стадию 2 при неожиданном росте t колонны if ($s>$tmax) { // это притормозит переход при неостывшей колонне if ($this->getProperty('tempCube') > 60) { say('Неожиданный рост температуры колонны', 2); $this->setProperty('log',date('h:m').' Неожиданный рост t колонны'); $this->callMethod('statusChanged', array('status'=>2)); } } break; /* --------- готовность к началу --------- */ case '2tempCube': $tmax=37; if ($s>90) { $n='Температура близка к началу процесса дисциляции'; } // ToDo расчитать по указанной спиртуозности раствора break; case '2tempColumn': //zzzzzzz if ($s>$tmax) { // записать температуру куба при прогреве колонны $this->setProperty('tempStartColumn', $this->getProperty('tempCube')); say('Прогрев спиртовой колонны', 2); $this->setProperty('log',date('h:m').' Прогрев колонны'); // переключить на стадию 4 через 5 минут setTimeOut($ot.'_status_Timer',"cm('$ot.statusChanged', array('status'=>4));", 5*60); // переключить на стадию 3 $this->callMethod('statusChanged', array('status'=>3)); } break; /* --------- работа на себя --------- */ case '3tempCube': //$tmax=70; $tmax=74; break; case '3tempColumn': if ($s>$tmax) { $n='Высокая температура колонны'; } break; /* --------- головы --------- */ case '4tempCube': //$tmax=73; $tmax=75; break; case '4tempColumn': if ($s>$tmax) { $n='Высокая температура колонны'; } break; /* --------- тело --------- */ case '5tempCube': // блок расчета максимальной температуры колонны $const_tColStart = 75.4; // начальная t колонны. Определена опытным путем. ToDo уточнить $const_tColEnd = 77.3; // конечная t колонны. Определена опытным путем. t кип этил спирта 78.39 //$const_tColLimitUp = 0.5; // дозволенный предел превышения температуры колонны $const_tColLimitUp = 0.2; // дозволенный предел превышения температуры колонны $const_tCubStart = $this->getProperty('tempStartColumn'); // записанная температура куба при подъеме колонны $const_tCubEnd = 97.8; //завершением процесса отбора тела можно считать температуру куба 97,8 градусов $kCol = ($const_tColEnd - $const_tColStart) / ($const_tCubEnd - $const_tCubStart); // коэффициент наклона для линии колонны $tmax = $const_tColStart + $kCol*($s - $const_tCubStart) + $const_tColLimitUp; // начало /\ подъем /\ лимит /\ if ($s>$const_tCubEnd) { $n='Температура куба на стадии завершения отбора тела'; } break; case '5tempColumn': if ($s>$tmax) { $n='Высокая температура колонны'; } if ($s<$tmax-2) { $n='Низкая температура колонны'; } break; /* --------- хвосты --------- */ case '6tempCube': //$tmax=max($s-15, 78.4); // максивальная температура колонны принимается на 15 градусов ниже куба, либо 78 градусов $tmax=min($s-14, 78.4); // максивальная температура колонны принимается на 14 градусов ниже куба, либо 78 градусов. Изопропиловый 82,1 if ($s>99) { $n='Максимальная температура куба. Завершите процесс'; } break; case '6tempColumn': if ($s>$tmax) { $n='Высокая температура колонны'; } break; /* --------- завершить --------- */ default: return; } // рандомные данные для графика $this->setProperty('tmaxColumn', $tmax+rand(0,100)/100000); // Уведомления с пуш не чаще 1 минуты (либо нет времени последнего уведомления) if ($n) { $lastn=$this->getProperty('notifyTime'); if (time() - $lastn > 60) { // сказать say($n, 2); // лог $this->setProperty('log',date('h:m').' '.$n); // записать время уведомления $this->setProperty('notifyTime',time()); } } // на стадии >=3 и при данных t куба вычисляем процент спирта // пишем в currentPercentCube // если не startPercentCube то пишем и туда // очень примерно, но можно подогнать под свой аппарат с великолепной точностью if ($status>=3 && $p=='tempCube' && $s>60) { //$Ti = ( $s - 89.03 ) / 6.54; //$ob = 16.75 - 19.05 * $Ti + 12.64 * pow($Ti,2) - 3.69 * pow($Ti,3) - 0.38 * pow($Ti,4); $Ti = ( $s - 89 ) / 6.49; $ob = 17.26 - 18.32 * $Ti + 7.81 * pow($Ti,2) - 1.77 * pow($Ti,3) + 4.81 * pow($Ti,4) - 2.95 * pow($Ti,5) - 1.43 * pow($Ti,6) + 0.8 * pow($Ti,7) + 0.05 * pow($Ti,8); $ob = round($ob,1); $this->setProperty('currentPercentCube', $ob); if ($status==3 && !($this->getProperty('startPercentCube'))) { say("В кубе $ob% спирта"); $this->setProperty('startPercentCube',$s); $this->setProperty('log',date('h:m')." В кубе $ob% спирта"); } }
Class properties:
Class methods:
if ($params['NEW_VALUE']) { // направление вращения мотора переключает контрол $this->setProperty('controlSwitch', $params['NEW_VALUE']); $this->setProperty('bottonColor','#FF0000'); } else { // остановка мотора /* возможна по конечнику, а так же кнопками стоп на щите или меню. При вклбючении сообщения Меги о стопе мотора можно через секунду смотреть статусы конечников. Если не в крайнем положении, значит $ot=$this->object_title; setTimeOut($ot.'_controlreset_delayexec'," sg($ot.'.controlSwitch', 0); sg($ot.'.bottonColor', NULL); ", 1); */ }
global $do_not_execute_object_method_AutoDoors; $ot=$this->getProperty('title'); // проверка разрешения на управление if (!$this->getProperty('generalAdmin')) { say("$ot запрещено администрировать"); $do_not_execute_object_method_AutoDoors=true; return; } // проверка движения if (!$this->getProperty('moveStatus')) { say("$ot сейчас не движутся"); $do_not_execute_object_method_AutoDoors=true; return; } // проверка крайнего положения if ($this->getProperty('positionStatus')) { $do_not_execute_object_method_AutoDoors=true; say("$ot сейчас в крайнем положении"); return; } // если добралить, значит будет выполнен метод объекта stop. // но сразу после перывания питания будут отправлены статусы конечников ворот. // убираем кнопку и цвет $ot=$this->object_title; setTimeOut($ot.'_controlreset_delayexec'," sg($ot.'.controlSwitch', 0); sg($ot.'.bottonColor', NULL); ", 1);
global $do_not_execute_object_method_AutoDoors; $ot=$this->getProperty('title'); // проверка разрешения на управление if (!$this->getProperty('generalAdmin')) { say("$ot запрещено администрировать"); $do_not_execute_object_method_AutoDoors=true; return; } // проверка разрешения на открытие if (!$this->getProperty('closingEnable')) { say("$ot запрещено закрывать"); $do_not_execute_object_method_AutoDoors=true; return; } // проверка движения if ($this->getProperty('moveStatus')) { say("$ot сейчас в движении"); $do_not_execute_object_method_AutoDoors=true; return; } // проверка крайнего положения if ($this->getProperty('positionStatus')==-1) { $do_not_execute_object_method_AutoDoors=true; say("$ot уже закрыты"); return; }
global $do_not_execute_object_method_AutoDoors; $ot=$this->getProperty('title'); // проверка разрешения на управление if (!$this->getProperty('generalAdmin')) { say("$ot запрещено администрировать"); $do_not_execute_object_method_AutoDoors=true; return; } // проверка разрешения на открытие if (!$this->getProperty('openingEnable')) { say("$ot запрещено открывать"); $do_not_execute_object_method_AutoDoors=true; return; } // проверка движения if ($this->getProperty('moveStatus')) { say("$ot сейчас в движении"); $do_not_execute_object_method_AutoDoors=true; return; } // проверка крайнего положения if ($this->getProperty('positionStatus')==1) { $do_not_execute_object_method_AutoDoors=true; say("$ot уже открыты"); return; }
if ($params['NEW_VALUE']) { $this->setProperty('moveStatus', '0'); // если ворота в крайнем положении, значит мотор отключен. Заплата на мегу!!! $this->setProperty('bottonColor','#00FF00'); // попробую включить опять, по идее ничему помешать не должно. $this->setProperty('controlSwitch', $params['NEW_VALUE']); //направление контрола уже задано методом мотора }
Class properties:
Class methods:
// Может получить параметр VALUE, а если его нет, возьмет громкость из свойства volumeLevel if (isset($params['VALUE'])) { $vl=$params['VALUE']; $this->setProperty('volumeLevel',$vl); } else { $vl=$this->getProperty('volumeLevel'); } // Громкость, как и любой другой параметр, может быть передан прямо в тексте сообщения say('-volumemaster:'.$vl." Громкость ".$vl." процентов");
Class properties:
Class methods:
//debmes(json_encode($params, JSON_UNESCAPED_UNICODE), 'test'); $ot=$this->object_title; // при линке с эоементом слайдер будут переданы VALUE и OLD_VALUE. Иначе взять данные из текущих свойств объекта if (isset($params['VALUE'])) { $slider = (int)$params['VALUE']; } else { $slider = (int)$this->getProperty('slider'); } if (isset($params['OLD_VALUE'])) { $position = (int)$params['OLD_VALUE']; } else { $position = (int)$this->getProperty('position'); } // Высчитать текущее положение с учетом возможного перемещения $position = $position - timeoutresidue($ot.'_open') + timeoutresidue($ot.'_close'); // ОТКРЫТЬ if ($slider > $position) { $this->callMethod('closeStop'); say('Открываю заслонку '. ($slider - $position) . ' секунд'); $this->callMethod('openStart'); cleartimeout($ot.'_close'); setTimeOut($ot.'_open', "callMethod('$ot.incomingMessage', array('command'=>'openStop'));", ($slider - $position)); // ЗАКРЫТЬ } elseif ($slider < $position) { // остановить открытие $this->callMethod('openStop'); say('Закрываю заслонку '. ($position - $slider) . ' секунд'); // начать закрытие $this->callMethod('closeStart'); // запланировать стоп cleartimeout($ot.'_open'); setTimeOut($ot.'_close', "callMethod('$ot.incomingMessage', array('command'=>'closeStop'));", ($position - $slider)); } else { say('Заслонка уже на позиции'); }
if (!isset($params['command'])) { debmes('Класс Dampers. Вызов метода incomingMessage без параметра command'); } $ot=$this->object_title; $slider = (int)$this->getProperty('slider'); $min = $this->getProperty('min'); $max = $this->getProperty('max'); // определить время максимальной работы //if (!is_numeric($max)) { $t_сalib = $max; } $t_сalib = 5; // доводить придод до конечника ещё 5 секунд switch ($params['command']) { case 'openCalibrat': $this->callMethod('openStop'); say('Калибровка положения открытия заслонки не удалась'); break; case 'closeCalibrat': $this->callMethod('closeStop'); say('Калибровка положения закрытия заслонки не удалась'); break; case 'openStop': // если слайдер на максимуме и задан максимум if (is_numeric($max) && $slider>=$max ) { say('Начинаю калибровку положения открытия заслонки'); // $this->callMethod('openStart'); //в данный момент мотор уже работает setTimeOut($ot.'_open', "callMethod('$ot.incomingMessage', array('command'=>'openCalibrat'));", $t_сalib); } else { $this->callMethod('openStop'); say('Заслонка достигла позиции'); } break; case 'closeStop': if (is_numeric($min) && $slider<=$min ) { say('Начинаю калибровку положения закрытия заслонки'); // $this->callMethod('closeStart'); //в данный момент мотор уже работает setTimeOut($ot.'_close', "callMethod('$ot.incomingMessage', array('command'=>'closeCalibrat'));", $t_сalib); } else { $this->callMethod('closeStop'); say('Заслонка достигла позиции'); } break; case 'openKey': // удалить таймер конца открытия cleartimeout($ot.'_open'); // остановить открытие $this->callMethod('openStop'); // сообщить о полном открытии say('Заслонка полностью открыта'); break; case 'closeKey': cleartimeout($ot.'_close'); $this->callMethod('closeStop'); say('Заслонка полностью закрыта'); break; default: debmes('Класс Dampers. Не корректный параметр command='.$params['command'].' при вызове метода incomingMessage'); } $this->setProperty('position', $slider); // команда с конечника при его срабатывании //callMethod('$ot.incomingMessage', array('command'=>'openKey'));
Class properties:
Class methods:
// say('OLD_VALUE='.$params['OLD_VALUE']); // say('NEW_VALUE='.$params['NEW_VALUE']); $t=''; $p=$this->getProperty('name'); if ($params['NEW_VALUE']==0) {$t="С провайдером $p потеряно соединение";} elseif ($params['NEW_VALUE']==1 && $params['OLD_VALUE']==0) {$t="Установлено соединения c провайдером $p";} elseif ($params['NEW_VALUE']==1 && $params['OLD_VALUE']>=2) {$t="Провайдер $p не предоставляет Интернет";} elseif ($params['NEW_VALUE']==2 && $params['OLD_VALUE']<=1) {$t="Провайдер $p, Интернет предоставлен";} elseif ($params['NEW_VALUE']==3) {$t="Провайдер $p выбран главным";} if ($t) { say($t, gg(NightMode.status)?-1:0); }
Class properties:
Class methods:
Class properties:
Class properties:
Class methods:
//u $this->setProperty("updated",time()); //u $this->setProperty("updatedTime",date("Y-m-d H:i:s",time())); // Свойство alive для класса тревожных датчиков не актуально $s=$params['status']; if (isset($s)) { $this->setProperty('status',$s); } else { $s = $this->getProperty('status'); } // у датчика есть слинкованная комната и его маркер тревоги $mark = $this->getProperty('marker'); //маркер fire smoke heat toxic gas flood freeze $linked_room = $this->getProperty('LinkedRoom'); if ($mark) { if ($linked_room) { /* получить тревожную строку у слинкованной комнаты и декодировать её в массив */ $alarms = getGlobal("$linked_room.Alarms"); $alarms_old = $alarms; /* сценарий - функция для внесения изменений с строку тревог */ $alarms = runscript('editJson', array('key'=>$mark, 'val'=>$this->id, 'js'=>$alarms, 'add'=>$s)); /* записать в свойство комнаты и вызвать метод */ if ($alarms_old != $alarms) { callMethod("$linked_room.onAlarms", array('Alarms'=>$alarms)); } } else { sg('alerts_message', 'Объект датчика '. $this->object_title.' не имеет слинкованной комнаты'); } // if_linked_room } else { sg('alerts_message', 'В объекте датчика '. $this->object_title.' не указано свойство маркер'); } // if_mark
Class methods:
//u $this->setProperty("updated",time()); //u $this->setProperty("updatedTime",date("Y-m-d H:i:s",time())); $this->setProperty("alive",1); $ot=$this->object_title; $alive_timeout=(int)$this->getProperty("aliveTimeOut"); if (!$alive_timeout) { $alive_timeout=12*60*60; } setTimeOut($ot."_alive","sg('".$ot.".alive',0);",$alive_timeout); $s=$params['status']; if (isset($s)) { // Записать в свойство объекта $this->setProperty('status',$s); } else { // Для слинкованных свойств и запуска этого метода без передачи данных, $s = $this->getProperty('status'); } /* if ($s) { } */
Class properties:
Class methods:
$this->setProperty("alive",1); $ot=$this->object_title; $alive_timeout=(int)$this->getProperty("aliveTimeOut"); if (!$alive_timeout) { $alive_timeout=12*60*60; } setTimeOut($ot."_alive","sg('".$ot.".alive',0);",$alive_timeout); // Записать в свойство, если его имя содержит history foreach ($params as $key => $value) { $pos = stripos($key, 'history'); if ($pos !== false) { $this->setProperty($key, $value); } }
Class properties:
Class methods:
//u $this->setProperty("updated",time()); //u $this->setProperty("updatedTime",date("Y-m-d H:i:s",time())); $this->setProperty("alive",1); $ot=$this->object_title; $alive_timeout=(int)$this->getProperty("aliveTimeOut"); if (!$alive_timeout) { $alive_timeout=12*60*60; } setTimeOut($ot."_alive","sg('".$ot.".alive',0);",$alive_timeout); $s=$params['status']; if (isset($s)) { // Если некорректные данные if (($s > 100) || ($s <= 0)) { return; } // Записать в свойство объекта $this->setProperty('status',$s); } else { // Для слинкованных свойств и запуска этого метода без передачи данных, взять их из свойства. $s = $this->getProperty('status'); } // Получение среднего значения из истории ToDo заменить на штатную функцию //Получить id свойства $prop_id=$this->getPropertyByName('status', $this->class_id, $this->id); //Получаем VALUE_ID для следующей таблицы $pvalue=SQLSelectOne("SELECT * FROM pvalues WHERE PROPERTY_ID='".$prop_id."' AND OBJECT_ID='".$this->id."'"); //Получаем средние значения за последние 30 минут $start_time=time()-30*60; // 30 минут $arr_s = SQLSelectOne("SELECT avg(VALUE) as AVG_V FROM phistory WHERE VALUE_ID='".$pvalue['ID']."' AND ADDED>='".date('Y-m-d H:i:s', $start_time)."'"); $avg_s=round($arr_s['AVG_V'], 1); $s=round($s, 1); // Сравнение if ($s-$avg_s > 10) { $d=1; } elseif ($s-$avg_s < -10) { $d=-1; } else { $d=0; } $this->setProperty('direction',$d); $this->setProperty('status',$s); // Передать данные слинкованной комнате $linked_room=$this->getProperty("LinkedRoom"); if ($linked_room) { // Получение последней записи истории комнаты ToDo РАЗОБРАТЬСЯ $obj=getObject($linked_room); $prop_id=$obj->getPropertyByName('Humidity', $obj->class_id, $obj->id); $pvalue=SQLSelectOne("SELECT * FROM pvalues WHERE PROPERTY_ID='".$prop_id."' AND OBJECT_ID='".$obj->id."'"); $arr_s = SQLSelectOne("SELECT UNIX_TIMESTAMP(ADDED)as ADDED, VALUE FROM phistory WHERE VALUE_ID='".$pvalue['ID']."' ORDER BY ADDED DESC LIMIT 1"); // Обновить если прошло больше часа. При этом на графике будет горизонтальная и вертикальная линии вместо одной наклонной. if (time()-$arr_s['ADDED'] > 60*60) { setGlobal($linked_room.'.Humidity', $arr_s['VALUE']); } // Записать новое значение setGlobal($linked_room.'.Humidity', $s); }
Class properties:
Class methods:
//u $this->setProperty("updated",time()); //u $this->setProperty("updatedTime",date("Y-m-d H:i:s",time())); $this->setProperty("alive",1); $ot=$this->object_title; $alive_timeout=(int)$this->getProperty("aliveTimeOut"); if (!$alive_timeout) { $alive_timeout=6*60*60; } setTimeOut($ot."_alive","sg('".$ot.".alive',0);",$alive_timeout); $s=$params['status']; if (isset($s)) { // Если некорректные данные if (($s > 65535) || ($s < 0)) { return; } // Записать в свойство объекта $this->setProperty('status',$s); } else { // Для слинкованных свойств и запуска этого метода без передачи данных, взять их из свойства. $s = $this->getProperty('status'); } // Передать данные слинкованной комнате $linked_room=$this->getProperty('LinkedRoom'); if ($linked_room) { // Для этого датчика слинкованой комнате передавать усредненное значение // эффективно при большом разбросе показаний датчика if ($ot=='ls_driveway') { // Определить период усреднения // чем ниже показания датчика, тем больше период усреднения, чтобы исключить большие скачки у нуля switch ($s) { case 0: $avgtime=26; break; case $s<10: $avgtime=21; break; case $s<20: $avgtime=16; break; case $s<50: $avgtime=11; break; case $s<100: $avgtime=6; break; default: $avgtime=0; } //$avgtime=1; // Получение среднего значения из истории ToDo заменитьна штатную функцию if ($avgtime) { //Получить id свойства $pvalueid = getHistoryValueId("$ot.status"); //Получаем средние значение за требуемый период $start_time=time()-$avgtime*60; //$arr_s = SQLSelectOne("SELECT avg(VALUE) as AVG_V FROM phistory WHERE VALUE_ID=$pvalueid AND ADDED>='".date('Y-m-d H:i:s', $start_time)."'"); $arr_s = SQLSelect("SELECT VALUE FROM phistory WHERE VALUE_ID=$pvalueid AND ADDED>='".date('Y-m-d H:i:s', $start_time)."'"); //Среднее значение округлить до целых если в ответе есть данные if ($arr_s!==[]) { //echo 'SQL массив <br/>'; //print_r($arr_s); // в ответе масив массивов. нам нужено получить простой массив значений //$arr_s=array_column($arr_s, 'VALUE'); // работает с php версии 5.5.0 У меня сейчас 5.4 // альтернативный вариант функции array_column function array_column_alt($arr_u) { return $arr_u['VALUE']; } $arr_s = array_map('array_column_alt', $arr_s); // добавить в массив текущее значение // $arr_s[]=array("VALUE"=>$s); // массив уже приведен к простому $arr_s[]=$s; //echo 'МОЙ массив <br/>'; //print_r($arr_s); //debmes('Свет '.$this->object_title.' array_sum($arr_s)='.array_sum($arr_s).'count($arr_s)='.count($arr_s)); // avg $s=array_sum($arr_s)/count($arr_s); $s=round($s, 0); } //else { debmes('Свет '.$this->object_title.' Пустой массив'); } } } //debmes('Свет '.$this->object_title.' отправлено '.$s); // Передать комнате setGlobal($linked_room.'.Luminiscence', $s); }
Class properties:
Class methods:
$this->setProperty("alive",1); $ot=$this->object_title; $alive_timeout=(int)$this->getProperty("aliveTimeOut"); if (!$alive_timeout) { $alive_timeout=7*24*60*60; } setTimeOut($ot."_alive","sg('".$ot.".alive',0);",$alive_timeout); // Установить статус датчика на 30 секунд. ТЕПЕРЬ у импульсных датчиков не должен быть status //$this->setProperty('status', 1); //setTimeOut($ot.'_status', "sg('".$ot.".status', 0);", 30); // Вызывать метод onActivity $linked_room=$this->getProperty("LinkedRoom"); if ($linked_room) { cm($linked_room.'.onActivity', ['source'=>$ot]); }
$this->setProperty("alive",1); $ot=$this->object_title; $alive_timeout=(int)$this->getProperty("aliveTimeOut"); if (!$alive_timeout) { $alive_timeout=24*60*60; } setTimeOut($ot."_alive","sg('".$ot.".alive',0);",$alive_timeout); $s=$params['status']; if (isset($s)) { // Записать в свойство объекта $this->setProperty('status',$s); } else { // Для слинкованных свойств и запуска этого метода без передачи данных, взять их из свойства. $s = $this->getProperty('status'); } $linked_room=$this->getProperty("LinkedRoom"); if ($linked_room) { if ($s) { // Вызывать метод onActivity при активности cm($linked_room.'.onActivity', ['source'=>$ot]); //ToDo Передача дескрипшена датчика } else { /* ПЕРЕИГРАЛ на вызов метода onActivity с половиной таймера // Вызывать метод onIdle если статусный датчик потерял движение и прислал 0. // onIdle прервет выполнение, если существуют другие активные статусные датчики или таймер cm($linked_room.'.onIdle'); */ // Вызывать метод onActivity с половиной таймера при получении 0 от датчика cm($linked_room.'.onActivity', ['source'=>$ot, 'activity_timeout_factor'=>0.5]); } }
Class properties:
Class methods:
//u $this->setProperty("updated",time()); //u $this->setProperty("updatedTime",date("Y-m-d H:i:s",time())); $this->setProperty("alive",1); $ot=$this->object_title; $alive_timeout=(int)$this->getProperty("aliveTimeOut"); if (!$alive_timeout) { $alive_timeout=12*60*60; } setTimeOut($ot."_alive","sg('".$ot.".alive',0);",$alive_timeout); $s=$params['status']; if (isset($s)) { // Записать в свойство объекта $this->setProperty('status',$s); } else { // Для слинкованных свойств и запуска этого метода без передачи данных, //u $s = $this->getProperty('status'); } /* if ($s) { } */
Class properties:
Class methods:
$this->setProperty('alive', 1); $ot = $this->object_title; $alive_timeout = (int)$this->getProperty('aliveTimeOut'); if (!$alive_timeout) { $alive_timeout = 6*60*60; } setTimeOut($ot.'_alive', "sg('$ot.alive', 0);", $alive_timeout); // *** Получение среднего значения из истории $start_time = time() - 30*60; // секунд // средние значения температуры за последее время $s_avg = getHistoryAvg("$ot.status", $start_time); // *** принять или прочитать данные if (isset($params['status'])) { $s = $params['status']; // Если некорректные данные if (($s > 150) || ($s < -50)) { return; } // Записать в свойство объекта $this->setProperty('status', $s); } else { // Для слинкованных свойств и запуска этого метода без передачи данных, взять их из свойства. $s = $this->getProperty('status'); } $s = round($s, 1); // *** Сравнение if ($s_avg === false) { $d = 0; // в истории нет записей } else { $s_avg = round($s_avg, 1); if ($s-$s_avg > 0.3) { $d = 1; // вверх } elseif ($s-$s_avg < -0.3) { $d = -1; // вниз } else { $d = 0; // нет существенных изменений } } $this->setProperty('direction', $d); // *** Передать данные слинкованной комнате $linked_room = $this->getProperty("LinkedRoom"); if ($linked_room) { // Если НЕ задано (пустота, 0) свойство distance, то датчик считается главным, и его данные обязательно будут // переданы объекту комнаты. Иначе будет проведен поиск других живых датчиков с более короткой дистанцией. if (!$this->getProperty('distance')) { setGlobal($linked_room.'.Temperature', $s); } else { // Получить id свойств для работы с базой данных. Свои id свойств этого класса я уже знаю. $alive_pid = 49; //$this->getPropertyByName('alive', $this->class_id, $this->id); $distance_pid = 647; //$this->getPropertyByName('distance', $this->class_id, $this->id); $LinkedRoom_pid = 253; //$this->getPropertyByName('LinkedRoom', $this->class_id, $this->id); /* Выбрать все записи свойств дистанции у объектов которых: свойство $linked_room такое же как и у текущего объекта И свойство $alive > 0 И это не этот объект */ $sql = " SELECT VALUE FROM pvalues WHERE PROPERTY_ID = $distance_pid AND OBJECT_ID IN ( SELECT OBJECT_ID FROM pvalues WHERE PROPERTY_ID = $LinkedRoom_pid AND VALUE = '$linked_room') AND OBJECT_ID IN ( SELECT OBJECT_ID FROM pvalues WHERE PROPERTY_ID = $alive_pid AND CAST(VALUE AS INT) > 0 ) AND OBJECT_ID <> $this->id ORDER BY VALUE LIMIT 1 "; $rec = SQLSelectOne($sql); // Если не найдено других живых датчиков с более короткой дистанцией if (is_null($rec) || $this->getProperty('distance') <= $rec['VALUE']) { setGlobal($linked_room.'.Temperature', $s); sg('alerts_message', "Объекту $linked_room переданы данные с резервного датчика температуры $ot"); } } }
Class properties:
Class methods:
$ot = $this->object_title; say("Мега $ot включилась");
/* Варианты что можно спросить callMethod('MegaD3.sendCommand', array('params'=>'pt=0&cmd=get&cnt=0')); // Сбросить счетчик импульсов. */ $reclog = 1; // Писать логи отладки ( 0-нет, 1-только крит, 2-все ) $ot = $this->object_title; // Проверка что есть ip адрес if (!filter_var($this->getProperty('IpAddress'), FILTER_VALIDATE_IP, FILTER_FLAG_IPV4)) { if ($reclog) { debmes('Megad class error => ip address is not set for object '.$ot); } return; } // Проверка что есть пароль if (!$this->getProperty('Password')) { if ($reclog) { debmes('Megad class error => Password is not set for object '.$ot); } return; } // Сборка строки начала запроса для Меги $cmdUrl = sprintf("http://%s/%s/?%s", $this->getProperty('IpAddress'), $this->getProperty('Password'), strval($params['params'])); // запрос данных у Меги $ta = 2; //секунд $ctx = stream_context_create(array( 'http' => array('timeout'=>$ta) ) ); $dt = trim(file_get_contents($cmdUrl, 0, $ctx)); // Живой или При отсутствии ответа установить флаг "НеЖивой" // Запись данных в лог if (isset($dt)) { $this->setProperty('alive',1); if ($reclog > 1) { debmes(sprintf('Megad class log => sendCommand method: %s returned %s', $cmdUrl, $dt)); } } else { $this->setProperty('alive',0); if ($reclog) { debmes("Megad class log => sendCommand method: No response from $cmdUrl"); } }
/* Варианты что можно спросить callMethod('MegaD99.getData', array('port'=>'all')); // спросить сразу все. callMethod('MegaD99.getData', array('port'=>0)); // состояние первого порта callMethod('MegaD99.getData', array('port'=>'tget')); // показания встроенного температурного датчика (только для версии прошивки 3.25 и до 3.52 не вкл) callMethod('MegaD99.getData', array('port'=>2, 'cmd'=>'list')); // получить массив 1WireBUS датчиков с порта 2 */ $reclog = 1; // Писать логи отладки ( 0-нет, 1-только крит, 2-все ) $ot = $this->object_title; // Проверка что есть ip адрес if (!filter_var($this->getProperty('IpAddress'), FILTER_VALIDATE_IP, FILTER_FLAG_IPV4)) { if ($reclog) { debmes('Megad class error => ip address is not set for object '.$ot); } return; } // Проверка что есть пароль if (!$this->getProperty('Password')) { if ($reclog) { debmes('Megad class error => Password is not set for object '.$ot); } return; } // Сборка строки начала запроса для Меги $cmdUrl = sprintf("http://%s/%s/", $this->getProperty('IpAddress'), $this->getProperty('Password')); // Добавление дополнительных параметров запроса в зависимости от его типа switch (strval($params['port'])) { case 'tget': // Температура встроенного датчика $cmdUrl .= '?tget=1'; $ta = 2; break; case 'all': // Спросить сразу все $cmdUrl .= '?cmd=all'; $ta = 4; //Таймаут ожидания меги break; default: // Состояние указанного порта //$cmdUrl .= sprintf("?pt=%d&cmd=get", intval($params['port'])); $cmdUrl .= '?pt='.intval($params['port']); if (!isset($params['cmd'])) { $params['cmd']='get'; } $cmdUrl .= '&cmd='.$params['cmd']; $ta = 4; } // формирование массива параметров для запроса $ctx = stream_context_create(array( 'http' => array('timeout'=>$ta) ) ); // запрос данных у Меги $dt = file_get_contents($cmdUrl, 0, $ctx); // Повторный запрос при отсутствии ответа если была жива if ($dt===false) { if ($this->getProperty('alive')) { //say("Повторный запрос у Меги $ot",gg(NightMode.status)?-1:0); sg('alerts_message', "Повторный запрос у Меги $ot"); $dt = file_get_contents($cmdUrl, 0, $ctx); }} // При отсутствии ответа установить флаг "НеЖивой" и завершить работу if ($dt===false) { // ToThink установка неживой с задержкой. Убрать таймер если получили ответ $this->setProperty('alive',0); if ($reclog) { debmes("Megad class log => getData method: No response from $cmdUrl"); } say("Мега $ot не отвечает",2); sg('alerts_message', "Мега $ot не отвечает"); return; } // возможно были лишние пробелы. до проверки условия $dt===false удалять нельзя. $dt = trim($dt); // Запись данных в лог if ($reclog > 1) { debmes(sprintf('Megad class log => getData method: %s returned %s', $cmdUrl, $dt)); } // Обработка ответа в зависимости от его типа, и передача его в метод incomingMessage // В методе incomingMessage безусловно будет установлен флаг "Живой" т.к. метод может быть вызван и самой мегой switch (strval($params['port'])) { // Температура внутреннего датчика case 'tget': if (strlen($dt)) { // Проверить $dt на число и Записать в свойство объекта // в 2561 мегах больше нет датчика температуры. Новые прошивки 328-х тоже больше не отвечают на tget // поэтому периодическим опросом мег мы можем только убедиться, что она отвечает (живая) if (is_numeric($dt)) { //записать в свойство температуру мени если в ответе число $this->setProperty('temperature', $dt); } elseif (stripos($dt, 'MegaD-328') !== false) { if ($reclog > 2) { debmes('Megad class log => getData method: Does not report temperature for object '.$ot); } } elseif (stripos($dt, 'MegaD-2561') !== false) { if ($reclog > 2) { debmes('Megad class log => getData method: Does not report temperature for object '.$ot); } } else { if ($reclog) { debmes('Megad class error => getData method: Failed to get data internal temperature sensor for object '.$ot); } } } // Нужно вызнать родительский метод для установки флага живой // в методах класса реакция на $params['port'] = 'tget' пропускается // Запретить выполнение кода методов объектов никак $this->callMethod('incomingMessage', array('pt'=>$params['port'], 'iasked'=>'ping')); break; /* Теперь ответ на запрос all отправляется как ответ на обычный порт // Запустить метод incomingMessage с передачей всего ответа в параметре all case 'all': $this->callMethod('incomingMessage', array('all'=>$dt)); break; */ // Запустить метод incomingMessage с передачей параметров как есть в параметре 'iasked' с номером указанного порта в параметре 'pt' default: $this->callMethod('incomingMessage', array('pt'=>$params['port'], 'iasked'=>$dt)); }
// Expects 'output' and 'value' in $params $reclog = 1; // Писать логи отладки ( 0-нет, 1-только крит, 2-все ) // Открывает лог если нужно if ($reclog) { $log = getLogger($this); } if (isset($params['command'])) { $cmd = $params['command']; } else { $cmd = intval($params['port']).':'.intval($params['value']); } /* $cmdUrl = sprintf('http://%s/%s/?cmd=%d:%d', $this->getProperty('IpAddress'), $this->getProperty('Password'), intval($params['port']), intval($params['value'])); */ $cmdUrl = sprintf('http://%s/%s/?cmd=%s', $this->getProperty('IpAddress'), $this->getProperty('Password'), $cmd); // Запись данных в лог if ($reclog == 2) { $log->trace('setOutput method: '.$cmdUrl); } getURL($cmdUrl, 0);
/* Общий код метода: Установка статуса alive "Живой" Запуск метода activate при первом отклике */ $reclog = 1; // Писать логи отладки ( 0-нет, 1-только крит, 2-все ) $ot = $this->object_title; if ($reclog > 1) { debmes('Megad class log => incomingMessage method: received params '.serialize($params)); } // Безусловная установка флага "Живой" т.к. метод был вызван самой мегой, или методом getData при успешном ответе if ($this->getProperty('alive') <> 1) { if ($reclog) { debmes('Megad class log => incomingMessage method: previous alive value 0. Received params '.serialize($params)); } say("Мега $ot ответила",2); $this->callMethod('activate'); } $this->setProperty('alive', 1);
Class properties:
Class methods:
/* Объекты могут быть двух типов. 1 Переключатель - имеет только один настраиваемый метод modeChanged. Свойство Status указывает на режим. 2 Выключатель - имеет настраиваемые методы activate и deactivate. Свойство Status может быть = 0 или 1. Оба типа существуют одновременно. Для изменения вызов метода modeChanged с указанием параметра status; либо линком (установкой) status и вызовом modeChanged без папаметров. Для типа Выключатель можно сразу просто вызывать методы activate и deactivate. */ $s=$params['status']; if (isset($s)) { // Записать в свойство объекта при его передаче в параметре $this->setProperty('status',$s); } else { // Для слинкованных свойств наоборот взять значение из объекта $s = $this->getProperty('status'); } // Вызов метода if ($s) { $this->callMethod('activate'); } else { $this->callMethod('deactivate'); }
//u $this->setProperty("updated",time()); //u $this->setProperty("updatedTime",date('H:i')); //Единственное возможное новое значение свойства status при вызове этого метода $this->setProperty('status',0);
//u $this->setProperty("updated",time()); //u $this->setProperty("updatedTime",date('H:i')); // Для типа Выключатель записать в свойство status единицу, если там был ноль // Для типа Переключатель в этом методе нет смысла, но он всё равно будет вызван из общего кода метода, // при этом в статусе полюбому будет что то отличное от нуля, и изменений не будет. if (!$this->getProperty('status')) { $this->setProperty('status',1); }
Class properties:
Class methods:
$this->setProperty('status', 0); if ($this->getProperty('modeSwitch') == 1) { $this->setProperty('modeSwitch', 0); }
/* вкл/выкл реле если modeSwitch число и = 0, 1, >=2 и существует таймер При этом передать указания для отмены кода личного метода. Родительский код вернет в ответе 3, если решение принято им на основании modeSwitch, таймеров и предложения статуса; или вернет 2. Код метода объекта перезапишет на 1, если он существует. т.е. ответ логики: 3 - если modeSwitch = 0; 1; >=2 и есть таймер или (предлодение и нет личной логки) 2 - если нет логики объекта и родительский код не принял решение 1 - есть логика в объекте Возможность отправить методу логики предложение вкл/выкл если modeSwitch >= 2 В большинстве случаев при этом нет надобности в создании логики метода у объекта. Имя глобальной переменной доступно из всех методов, вызванных по цепочке Важно если в коде метода объекта вызываются другие методы, например рекомандация вкл/выкл реле */ global $do_not_execute_object_method_Relays; $ms=$this->getProperty('modeSwitch'); if (is_numeric($ms)) { if ($ms==0) { $f=0; } elseif ($ms==1) { $f=1; } elseif ($ms>=2) { // вкл/выкл при существовании таймера if (timeOutExists($this->object_title.'_nowork')) { $f=0; } elseif (timeOutExists($this->object_title.'_work')) { $f=1; } // вкл/выкл при существовании рекомендации и отсутствии личной логики объекта elseif (isset($params['status'])) { $om = SQLSelectOne("SELECT ID FROM methods WHERE TITLE='logic' AND OBJECT_ID=".$this->id); if (!$om) { if ($params['status']) { $f=1; } else { $f=0; } //debmes('у объекта ' . $this->object_title . ' нет метода логики', 'test'); } } } } if (isset($f)) { // переключить реле $s=$this->getProperty('status'); if ($f>$s) { $this->callMethod('turnOn'); } if ($f<$s) { $this->callMethod('turnOff'); } // запретить выполнение кода метода объекта $do_not_execute_object_method_Relays=true; return 3; } else { // решение на усмотрение метода объекта при его наличии $do_not_execute_object_method_Relays=false; return 2; // если метод объекта есть, он перезапишет на 1 // стоит обратить внимание, что echo в коде метода добавляет текст в начало ответа }
//$ot=$this->object_title; $this->callMethod("turnOn"); //setTimeOut($ot."_click","cm('".$ot.".turnOff');",2); $this->callMethod("turnOff");
/* Параметр onTime в секундах для включения на время. Если у объекта задано свойство modeSwitch 0,1,3 то оно будет установлено на 3, и по истечении времени установлено 0 и реле выключено методом turnOff. Если 2 то по по истечении вызван метод logic. Если modeSwitch не определеноЮ, то оно не будет изменено. По истечении метод turnOff. Пример: callMethod('RelayFrontDoorOpen.turnOn', array('onTime'=>1)); */ $this->setProperty('status', 1); $m = $this->getProperty('modeSwitch'); // Передан параметр для включения на время onTime if (array_key_exists('onTime', $params)) { $ot = $this->object_title; // Время по умолчанию if (!$params['onTime']) { $params['onTime'] = 5; } //$m=$this->getProperty('modeSwitch'); if (is_numeric($m)) { // После выбора Time возврат на Off если было Off, On или Time if (in_array($m, [0, 1, 3])) { $code="sg('$ot.modeSwitch', 0); cm('$ot.turnOff');"; } // Возврат на Auto если было выбрано ранее if ($m == 2) { $code="sg('$ot.modeSwitch', 2); cm('$ot.logic', array('status'=>0));"; } $this->setProperty('modeSwitch', 3); } else { // Просто выключить если modeSwitch не был числом $code="cm('$ot.turnOff');"; } clearTimeOut($ot.'_nowork'); setTimeOut($ot.'_work', $code, $params['onTime']); // Обычный вызов метода } else { if (is_numeric($m) && $m==0) { $this->setProperty('modeSwitch', 1); } }
$status=$this->getProperty("status"); if ($status) { $this->callMethod('turnOff'); } else { $this->callMethod('turnOn'); }
$status=$this->getProperty('status'); if ($status) { $this->callMethod('turnOn'); } else { $this->callMethod('turnOff'); }
Class properties:
Class methods:
$al = $params['Alarms']; if (isset($al)) { // Записать в свойство объекта $this->setProperty('Alarms',$al); } else { // Для слинкованных свойств и запуска этого метода без передачи данных, $al = $this->getProperty('Alarms'); } //$al - тревоги комнаты $alarms - общие $alarms = getGlobal('globalAlarms'); $alarms_old = $alarms; $alarmsKeys = (array)array_keys(json_decode($alarms, true)); $alKeys = (array)array_keys(json_decode($al, true)); /* callMethod('as_drivewayArea_freeze1.statusChanged', array('status'=>1)); 1.1 вычесть из ключей глобала ключи комнаты 1.2 попытаться удалить из ключей глобала эту разничу т.е. всё что нет у нас, но с нашим id 2 просто добавить в глобал все что у нас есть c нашим id */ /* сценарий - функция для внесения изменений с строку тревог */ $alarms = runscript('editJson', array('key'=>array_values(array_diff($alarmsKeys, $alKeys)), 'val'=>$this->id, 'js'=>$alarms, 'add'=>0)); $alarms = runscript('editJson', array('key'=>$alKeys, 'val'=>$this->id, 'js'=>$alarms, 'add'=>1)); //debMes("тревоги комнаты $al общие было $alarms_old общие стало $alarms"); /* записать в общее свойство тревоги и вызвать сценарий */ if ($alarms_old != $alarms) { // setGlobal('globalAlarms', $alarms); runScript('generalAlarms', array('alarms'=>$alarms)); }
$ot=$this->object_title; global $do_not_execute_object_method_onIdle; /* БЛОКИРОВКА выполнения личного кода метода, если существует таймер или есть активный статусный датчик */ $rec = null; if (timeoutexists($ot."_activity_timeout")) { /* Существует таймер активности в комнате. Ситуация происходит когда статусный датчик присылает 0 и пробует снять активность в комнате, но существует таймер активности, запущенный импульсным датчиком */ $rec = true; } else { /* У импульсных датчиков не должно быть параметра status. При срабатывании они, например, вызывают метод motionDetected подкласса MovementSensors. Что приведет к вызову метода onActivity в комнате и запуску таймера для onIdle Статусные датчики при срабатывании устанавливают параметр status 1 и при потере движения 0, вызывая метод statusChanged, либо вызов метода сразу с параметром status. При 1 вызывается onActivity. Таймер при этом можно не запускать, чтобы не выполнять лишние действия, он просто не нужен. При 0 вызывается onIdle, но... В методе onIdle идет запрос всех слинкованных с комнатой датчиков, у которых status = 1, (да ещё и живых). Если список не пустой, то прервать выполнение метода. */ // 49-alive 51-status 246-LinkedRoom $sql = " SELECT ID FROM pvalues WHERE OBJECT_ID IN ( SELECT OBJECT_ID FROM pvalues WHERE PROPERTY_ID = 49 AND CAST(VALUE AS INT) > 0) AND OBJECT_ID IN ( SELECT OBJECT_ID FROM pvalues WHERE PROPERTY_ID = 51 AND CAST(VALUE AS INT) > 0) AND OBJECT_ID IN ( SELECT OBJECT_ID FROM pvalues WHERE PROPERTY_ID = 246 AND VALUE = '$ot') "; $rec = SQLSelectOne($sql); } // Прервать выполнение если существуют слинкованные живые датчики со status=1. У импульсных не должно быть свойства status. // Это означает что в дальнейшем этот метод будет вызван снова, когда с датчика придет 0 if (!is_null($rec)) { //say("В $ot Есть статусные датчики",1); $do_not_execute_object_method_onIdle=true; return; } else { $do_not_execute_object_method_onIdle=false; } /* ДАЛЬНЕЙШЕЕ выполнение кода */ $this->setProperty('SomebodyHere',0); // Определяем метод по лакации // 2-баня 1-дом $location_id = $this->location_id; switch ($location_id) { case 1: $m = 'NobodyHomeMode'; break; case 2: $m = 'NobodyBathMode'; break; default: $m = 0; } if ($m) { // *** Получить всех гостей *** /* WHERE PROPERTY_ID = 124 id свойстви TITLE например для получения названия. В данном случае нам всё равно, и нужен только факт есть хоть какаянибудь комната или нет. Поэтому в ответе будут все свойства выбранных объектов. Ограничим вывод только ID, т.к. нам и тут всё равно. Используем SQLSelectOne, список нам не нужен. */ // 61-SomebodyHere 25-ROOMS $sql = " SELECT ID FROM pvalues WHERE OBJECT_ID IN ( SELECT OBJECT_ID FROM pvalues WHERE PROPERTY_ID = 61 AND value is not null and value <> '0' and value <> '' ) AND OBJECT_ID IN ( SELECT ID FROM objects WHERE CLASS_ID = 25 AND LOCATION_ID = $location_id ) "; $rec = SQLSelectOne($sql); /* Условие активации режима никого нет в локации. проверка статуса режима не должна быть нужна, т.к. до этого комната была активной, и сделовательно была общая активность в локации */ if (is_null($rec)) { cm("$m.activate"); } }
/* Активность будет регистрироваться каждый раз при срабатывании датчика Для уменьшения числа срабатываний можно сравнивать $latestActivity с time() На сценах можно использовать условие time() - LatestActivity <= 10 секунд например */ $latestActivity=$this->getProperty('LatestActivity'); $this->setProperty('LatestActivity',time()); $this->setProperty('LatestActivityTime',date('H:i')); $ot=$this->object_title; global $do_not_execute_object_method_onActivity; /* Установить активность в комнате */ // Передать источник события вместо 1 ToDo НА ДИКИЙ ТЕСТ!!! $source = 1; if (isset($params['source'])) { $source = $params['source']; } $prev_SomebodyHere = $this->getProperty('SomebodyHere'); $this->setProperty('SomebodyHere', $source); /*** КАЖДЫЙ раз при подтверждении активности ***/ /* Установить (отодвинуть) таймер активности в комнате. Свойство объекта комнаты класса Rooms может быть не задано вовсе, тогда таймаут активности будет принят как 10 минут. Задано простым числом, или задано последовательностью из 5 чисел, разделенных ; для разных режимов работы энергопотребления */ $idl = $this->getProperty("IdleDelay"); if (strpos($idl, ';')) { $activity_timeout=explode(";", $idl); $activity_timeout= $activity_timeout[(int)gg('EconomMode.status')+2]; } elseif ($idl) { $activity_timeout=(int)$idl; } else { $activity_timeout=10*60; } // умножить таймер на множитель, если был передан в параметре // используеься для запуска половины времени таймера, нарпимер. if (isset($params['activity_timeout_factor'])) { $activity_timeout = round($activity_timeout * $params['activity_timeout_factor']); //debmes($ot . '.onActivity вызов со множителем ' . $params['activity_timeout_factor'] . ' activity_timeout=' . $activity_timeout, 'test'); // Запустить таймер, если он не существует (меньше) if (timeoutresidue($ot.'_activity_timeout') < $activity_timeout) { setTimeOut($ot.'_activity_timeout', "callMethod('$ot.onIdle');", $activity_timeout); } } else { // Запустить таймер setTimeOut($ot.'_activity_timeout', "callMethod('$ot.onIdle');", $activity_timeout); } // блокировка повторных вызовов после выполнения первой активности if ($prev_SomebodyHere) { $do_not_execute_object_method_onActivity=true; return; } else { $do_not_execute_object_method_onActivity=false; } /*** ДАЛЕЕ только при первой активности ***/ /* В свойстве msAlarmLeven нужно указать цифры соответствующих режимов на которые будет реагировать объект комнаты Группа условий сработает на первой максимальной цифре, указанной в свойстве msAlarmLeven. К примеру при GuardMode.status=3 и msAlarmLeven = 12, стаботает группа 2, и выполнение кода закончится. GuardMode.status=2 и msAlarmLeven = 12, стаботает группа 2, и выполнение кода закончится. GuardMode.status=1 и msAlarmLeven = 12, стаботает группа 1. GuardMode.status=3 и msAlarmLeven = 3, стаботает группа 3. Других вариантов срабатывания нет. msAlarmLeven: 0- Пищалка 1- Сообщение о движении только в чате 2- Чат и голос 3- Тревога GuardMode.status: 0- Отключить все уведомления и сообщения (в данный момент к выбору не предложено, но технически возвожно) 1- Снят с охраны 2- Наблюдение за перриметром 3- Охрана объекта */ $al = $this->getProperty('msAlarmLeven'); // Обратите внимание на break; Он сработает только если выполенно условие if. Иначе выполнение кода групп case продолжится. switch (gg('GuardMode.status')) { case 3: /*** добавить тревогу security в свойство общих тревог и вызвать сценарий ***/ if (strpos($al, '3') !== false) { // получить строку общих тревог $gal = getGlobal('globalAlarms'); $gal_old = $gal; // сценарий - функция для внесения изменений в строку тревог $gal = runscript('editJson', array('key'=>'security', 'val'=>$this->id, 'js'=>$gal)); // вызвать сценарий с передачей параметра if ($gal_old != $gal) { runScript('generalAlarms', array('alarms'=>$gal)); } break; } case 2: /*** кричалка при движении в режиме охраны периметра ***/ if (strpos($al, '2') !== false) { say ('Внимание, активность '.$this->getProperty('inRoomText'), (gg('GuestsMode.status'))?2:3); break; } case 1: if (strpos($al, '1') !== false) { // Написать в чат say('Активность '.$this->getProperty("inRoomText"), -1); } if (strpos($al, '0') !== false) { // Пищалка при активности. В папке sounds должен быть wav файл с именем объекта класса ROOMS // если у объекта присутствует 0 в свойстве msAlarmLeven playSound($ot.'.wav'); } } /* Декативировать режим "Никого нет" В этом методе возможна только деактивация режима Решение об активации режима будет принято в методе onIdle после перебора всех комнат */ switch ($this->location_id) { case 1: if (gg('NobodyHomeMode.status')) { debmes('RVC => ROOMS-onActivity => Активность '.$this->getProperty("inRoomText"). '. Деактивация режима'); cm('NobodyHomeMode.deactivate'); } break; case 2: if (gg('NobodyBathMode.status')) { debmes('RVC => ROOMS-onActivity => Активность '.$this->getProperty("inRoomText"). '. Деактивация режима'); cm('NobodyBathMode.deactivate'); } break; }
Class properties:
Class methods:
Class properties:
Class methods:
/* begin injection of {SDevices} */ require(DIR_MODULES.'devices/SDevices_keepAlive.php'); /* end injection of {SDevices} */
require(DIR_MODULES.'devices/SDevices_logicAction.php');
require(DIR_MODULES.'devices/SDevices_statusUpdated.php');
/* begin injection of {SDevices} */ require(DIR_MODULES.'devices/SDevices_setUpdatedText.php'); /* end injection of {SDevices} */
Class properties:
Class methods:
require(DIR_MODULES.'devices/SButtons_pressed.php');
Class properties:
Class methods:
/* begin injection of {SDevices} */ require(DIR_MODULES.'devices/SCameras_motionDetected.php'); /* end injection of {SDevices} */
/* begin injection of {SDevices} */ require(DIR_MODULES.'devices/SCameras_updatePreview.php'); /* end injection of {SDevices} */
/* begin injection of {SDevices} */ require(DIR_MODULES.'devices/SCameras_takeSnapshot.php'); /* end injection of {SDevices} */
/* begin injection of {SDevices} */ require(DIR_MODULES.'devices/SCameras_takeSeries.php'); /* end injection of {SDevices} */
Class properties:
Class methods:
require(DIR_MODULES.'devices/SControllers_turnOn.php');
require(DIR_MODULES.'devices/SControllers_turnOff.php');
require(DIR_MODULES.'devices/SControllers_switch.php');
Class properties:
Class methods:
/* begin injection of {SDevices} */ require(DIR_MODULES.'devices/SDimmers_levelWorkUpdated.php'); /* end injection of {SDevices} */
/* begin injection of {SDevices} */ require(DIR_MODULES.'devices/SDimmers_statusUpdated.php'); /* end injection of {SDevices} */
/* begin injection of {SDevices} */ require(DIR_MODULES.'devices/SDimmers_setLevel.php'); /* end injection of {SDevices} */
require(DIR_MODULES.'devices/SDimmers_turnOn.php');
require(DIR_MODULES.'devices/SDimmers_turnOff.php');
require(DIR_MODULES.'devices/SDimmers_levelUpdated.php');
Class properties:
Class methods:
/* begin injection of {SDevices} */ require(DIR_MODULES.'devices/SGroups_turnOff.php'); /* end injection of {SDevices} */
/* begin injection of {SDevices} */ require(DIR_MODULES.'devices/SGroups_statusUpdated.php'); /* end injection of {SDevices} */
/* begin injection of {SDevices} */ require(DIR_MODULES.'devices/SGroups_switch.php'); /* end injection of {SDevices} */
/* begin injection of {SDevices} */ require(DIR_MODULES.'devices/SGroups_turnOn.php'); /* end injection of {SDevices} */
Class properties:
Class methods:
/* begin injection of {SDevices} */ require(DIR_MODULES.'devices/SRGB_colorUpdated.php'); /* end injection of {SDevices} */
/* begin injection of {SDevices} */ require(DIR_MODULES.'devices/SRGB_setColor.php'); /* end injection of {SDevices} */
/* begin injection of {SDevices} */ require(DIR_MODULES.'devices/SRGB_turnOn.php'); /* end injection of {SDevices} */
/* begin injection of {SDevices} */ require(DIR_MODULES.'devices/SRGB_turnOff.php'); /* end injection of {SDevices} */
Class properties:
Class methods:
/* begin injection of {SDevices} */ require(DIR_MODULES.'devices/SThermostats_setTargetTemperature.php'); /* end injection of {SDevices} */
/* begin injection of {SDevices} */ require(DIR_MODULES.'devices/SThermostats_enable.php'); /* end injection of {SDevices} */
/* begin injection of {SDevices} */ require(DIR_MODULES.'devices/SThermostats_turnOff.php'); /* end injection of {SDevices} */
/* begin injection of {SDevices} */ require(DIR_MODULES.'devices/SThermostats_turnOn.php'); /* end injection of {SDevices} */
/* begin injection of {SDevices} */ //require(DIR_MODULES.'devices/SThermostats_disable.php'); /* end injection of {SDevices} */
/* begin injection of {SDevices} */ require(DIR_MODULES.'devices/SThermostats_switchEnable.php'); /* end injection of {SDevices} */
/* begin injection of {SDevices} */ require(DIR_MODULES.'devices/SThermostats_tempUp.php'); /* end injection of {SDevices} */
/* begin injection of {SDevices} */ require(DIR_MODULES.'devices/SThermostats_tempDown.php'); /* end injection of {SDevices} */
/* begin injection of {SDevices} */ require(DIR_MODULES.'devices/SThermostats_valueUpdated.php'); /* end injection of {SDevices} */
/* begin injection of {SDevices} */ require(DIR_MODULES.'devices/SThermostats_statusUpdated.php'); /* end injection of {SDevices} */
Class properties:
Class methods:
/* begin injection of {SDevices} */ require(DIR_MODULES.'devices/SCounters_valueUpdated.php'); /* end injection of {SDevices} */
/* begin injection of {SDevices} */ require(DIR_MODULES.'devices/SCounters_valueWorkUpdated.php'); /* end injection of {SDevices} */
/* begin injection of {SDevices} */ require(DIR_MODULES.'devices/SCounters_refreshStats.php'); /* end injection of {SDevices} */
Class properties:
Class properties:
Class methods:
/* begin injection of {SDevices} */ require(DIR_MODULES.'devices/SLeak_statusUpdated.php'); /* end injection of {SDevices} */
/* begin injection of {SDevices} */ require(DIR_MODULES.'devices/SLeak_alert.php'); /* end injection of {SDevices} */
/* begin injection of {SDevices} */ require(DIR_MODULES.'devices/SLeak_blockSensor.php'); /* end injection of {SDevices} */
/* begin injection of {SDevices} */ require(DIR_MODULES.'devices/SLeak_unblockSensor.php'); /* end injection of {SDevices} */
Class properties:
Class methods:
/* begin injection of {SDevices} */ require(DIR_MODULES.'devices/SMotions_blockSensor.php'); /* end injection of {SDevices} */
/* begin injection of {SDevices} */ require(DIR_MODULES.'devices/SMotions_unblockSensor.php'); /* end injection of {SDevices} */
require(DIR_MODULES.'devices/SMotions_motionDetected.php');
Class properties:
Class methods:
/* begin injection of {SDevices} */ require(DIR_MODULES.'devices/SOpenable_statusUpdated.php'); /* end injection of {SDevices} */
/* begin injection of {SDevices} */ require(DIR_MODULES.'devices/SOpenable_switch.php'); /* end injection of {SDevices} */
/* begin injection of {SDevices} */ require(DIR_MODULES.'devices/SOpenable_open.php'); /* end injection of {SDevices} */
/* begin injection of {SDevices} */ require(DIR_MODULES.'devices/SOpenable_close.php'); /* end injection of {SDevices} */
Class properties:
Class methods:
/* begin injection of {SDevices} */ require(DIR_MODULES.'devices/SOpenClose_blockSensor.php'); /* end injection of {SDevices} */
/* begin injection of {SDevices} */ require(DIR_MODULES.'devices/SOpenClose_unblockSensor.php'); /* end injection of {SDevices} */
require(DIR_MODULES.'devices/SOpenClose_statusUpdated.php');
Class properties:
Class methods:
/* begin injection of {SDevices} */ require(DIR_MODULES.'devices/SSensors_alert.php'); /* end injection of {SDevices} */
/* begin injection of {SDevices} */ require(DIR_MODULES.'devices/SSensors_blockSensor.php'); /* end injection of {SDevices} */
/* begin injection of {SDevices} */ require(DIR_MODULES.'devices/SSensors_unblockSensor.php'); /* end injection of {SDevices} */
require(DIR_MODULES.'devices/SSensors_valueUpdated.php');
Class properties:
Class properties:
Class properties:
Class methods:
/* begin injection of {SDevices} */ require(DIR_MODULES.'devices/SPowerSensors_valueUpdated.php'); /* end injection of {SDevices} */
/* begin injection of {SDevices} */ require(DIR_MODULES.'devices/SPowerSensors_loadStatusChanged.php'); /* end injection of {SDevices} */
Class properties:
Class methods:
/* begin injection of {SDevices} */ require(DIR_MODULES.'devices/SSmoke_statusUpdated.php'); /* end injection of {SDevices} */
/* begin injection of {SDevices} */ require(DIR_MODULES.'devices/SSmoke_alert.php'); /* end injection of {SDevices} */
/* begin injection of {SDevices} */ require(DIR_MODULES.'devices/SSmoke_blockSensor.php'); /* end injection of {SDevices} */
/* begin injection of {SDevices} */ require(DIR_MODULES.'devices/SSmoke_unblockSensor.php'); /* end injection of {SDevices} */
Class properties:
Class methods:
Class properties:
Class methods:
$ot=$this->object_title; if (defined('THRM_LOG_LEVEL') && THRM_LOG_LEVEL != '') { $log_level = THRM_LOG_LEVEL; } else { $log_level = 0; } if ($log_level>1) { DebMes("$ot.$name Start Called " . mb_substr($source, 0, 50) . '...','thrm'); } if (isset($params['status'])) { $status = $params['status']; } else { $status=(int)$this->getProperty('status'); } // Время таймеров $mintimeoff = $this->getProperty('mintimeoff'); if (is_numeric($mintimeoff)) { $mintimeoff = (int)$mintimeoff; } else { $mintimeoff = 15*60; } $mintimeon = $this->getProperty('mintimeon'); if (is_numeric($mintimeon)) { $mintimeon = (int)$mintimeon; } else { $mintimeon = 10*60; } // Cтатус уже устанавливается в методе workDecision // Создание таймеров if ($status) { $this->setProperty('log', "Включаю $status ступень"); setTimeOut($ot.'_work', "debmes('Tаймер '.$ot.'_work закончен'); cm('$ot.workDecision');", $mintimeon); clearTimeOut($ot.'_nowork'); } else { $this->setProperty('log', 'Выключаю устройство'); setTimeOut($ot.'_nowork', "debmes('Tаймер '.$ot.'_nowork закончен'); cm('$ot.workDecision');", $mintimeoff); clearTimeOut($ot.'_work'); }
/* Принимает решение о работе котла или насоса, на основе текущей и требуемой температуры воздуха Запускается из метода airCalculate, а так же может быть вызван при необходимости проверки решения о работе котла из других элементов системы */ $ot=$this->object_title; if (defined('THRM_LOG_LEVEL') && THRM_LOG_LEVEL != '') { $log_level = THRM_LOG_LEVEL; } else { $log_level = 0; } if ($log_level>1) { DebMes("$ot.$name Start Called " . mb_substr($source, 0, 50) . '...','thrm'); } // Не выполнять логику если установлен ручной режим if (!$this->getProperty('auto')) { if ($log_level>0) { DebMes("$ot.workDecision режим auto не выбран",'thrm'); } return; } /* *** Сбор данных *** */ // При вызове метода после изменения свойства, его значение будет передано в массиве if (isset($params['PROPERTY'])) { // Прекратить выполнение если данные не изменились if ($params['NEW_VALUE'] == $params['OLD_VALUE']) { if ($log_level>1) {DebMes("$ot.workDecision значение " . $params['PROPERTY'] . " не изменилось",'thrm');} return; } // Составить список всех переменных (одну) list($params['PROPERTY']) = array($params['NEW_VALUE']); } // создать переменные из массива // Если переменная с таким именем существует, её текущее значение не будет перезаписано. extract($params, EXTR_SKIP); // *** Воздух if (!isset($airCurrentTemp)) { $airCurrentTemp=$this->getProperty('airCurrentTemp'); } if (!isset($airRequiredTemp)) { $airRequiredTemp=$this->getProperty('airRequiredTemp'); } if (!isset($airShiftTemp)) { $airShiftTemp=$this->getProperty('airShiftTemp'); } if (!isset($hysteresis)) { $hysteresis=$this->getProperty('hysteresis'); } // *** Вода if (!isset($waterCurrentTemp)) { $waterCurrentTemp=$this->getProperty('waterCurrentTemp'); } if (!isset($waterRequiredTemp)) { $waterRequiredTemp=$this->getProperty('waterRequiredTemp'); } if (!isset($waterReturnTemp)) { $waterReturnTemp=$this->getProperty('waterReturnTemp'); } if (!isset($waterMaxTemp)) { $waterMaxTemp=$this->getProperty('waterMaxTemp'); } if (!isset($waterMinTemp)) { $waterMinTemp=$this->getProperty('waterMinTemp'); } /* *** Разрешения Получить значение метода, запрещающего работу. В некоторых ситуациях необходимо запретить работу. Например, в данный момент у нас работает бойлер нагрева горячей воды, и предел допустимой мощности не позвоняет включить электрический. Либо будут открыты ворота, и нужно заранее повысить температуру. Методы в МД возвращают 1. В ответе метода число с цифрами ступеней будет прибавлено к этой единице. Например: ответ 1: 1-1=0 ничего; ответ 2: 2-1=1 первая ступень; ответ 24: 24-1=23 вторая и третья */ $mayBanOn = intval($this->callmethod('mayBanOn'))-1; $mayResolve = intval($this->callmethod('mayResolve'))-1; // запрет по таймерам на вкл/выкл в т.ч. быстрое изменение мощности ступеней. $timeWork = false; $timeNoWork = false; if (timeOutExists($ot.'_work')) { $timeWork = true; } if (timeOutExists($ot.'_nowork')) { $timeNoWork = true; } // *** текущий статус работы. Количество работающих ступеней. $status = (int)$this->getProperty('status'); //$arr_status = mygetGlobalWithUpd("$ot.status"); //$status = (int)$arr_status['VALUE']; // *** формат данных и значения по умолчанию if (is_numeric($airCurrentTemp)) { $airCurrentTemp = (float)$airCurrentTemp; } else { $airCurrentTemp = null; } if (is_numeric($airRequiredTemp)) { $airRequiredTemp = (float)$airRequiredTemp; } else { $airRequiredTemp = null; } if (is_numeric($airShiftTemp)) { $airShiftTemp = (float)$airShiftTemp; } else { $airShiftTemp = $airRequiredTemp; } if (is_numeric($hysteresis)) { $hysteresis = (float)$hysteresis; } else { $hysteresis = 0.2; } if (is_numeric($waterCurrentTemp)) { $waterCurrentTemp = (float)$waterCurrentTemp; } else { $waterCurrentTemp = null; } if (is_numeric($waterRequiredTemp)) { $waterRequiredTemp = (float)$waterRequiredTemp; } else { $waterRequiredTemp = null; } if (is_numeric($waterReturnTemp)) { $waterReturnTemp = (float)$waterReturnTemp; } else { $waterReturnTemp = null; } if (is_numeric($waterMaxTemp)) { $waterMaxTemp = (int)$waterMaxTemp; } else { $waterMaxTemp = 80; } if (is_numeric($waterMinTemp)) { $waterMinTemp = (int)$waterMinTemp; } else { $waterMinTemp = 10; } $f_on = true; // Разрешающие факоры: if (!is_null($airCurrentTemp) && !is_null($airShiftTemp) && $airCurrentTemp < $airShiftTemp - $hysteresis) { DebMes("$ot.workDecision текущая t воздуха $airCurrentTemp < заблаговременной требуемой $airShiftTemp - гистерезис $hysteresis",'thrm'); } elseif (!is_null($waterCurrentTemp) && !is_null($waterRequiredTemp) && $waterCurrentTemp < $waterRequiredTemp - 3) { DebMes("$ot.workDecision t подачи $waterCurrentTemp < целевой $waterRequiredTemp - гист",'thrm'); } elseif (!is_null($waterCurrentTemp) && $waterCurrentTemp < $waterMinTemp) { DebMes("$ot.workDecision t подачи $waterCurrentTemp < минимальной $waterMinTemp",'thrm'); //} elseif (timeOutExists($n.'_work')) { // DebMes("$ot.workDecision существует таймер работы",'thrm'); } elseif ($mayResolve) { DebMes("$ot.workDecision существует рекомендация на включение",'thrm'); } else { $f_on = false; } $f_off = true; // Запрещаюшие факторы: if (!is_null($airCurrentTemp) && !is_null($airShiftTemp) && $airCurrentTemp > $airShiftTemp + $hysteresis) { DebMes("$ot.workDecision текущая t воздуха $airCurrentTemp > заблаговременной требуемой $airShiftTemp + гистерезис $hysteresis",'thrm'); } elseif (!is_null($waterCurrentTemp) && !is_null($waterRequiredTemp) && $waterCurrentTemp > $waterRequiredTemp + 3) { DebMes("$ot.workDecision t подачи $waterCurrentTemp > целевой $waterRequiredTemp + гист",'thrm'); } elseif (!is_null($waterCurrentTemp) && $waterCurrentTemp > $waterMaxTemp) { DebMes("$ot.workDecision t подачи $waterCurrentTemp > максимальной $waterMaxTemp",'thrm'); //} elseif (timeOutExists($n.'_nowork')) { // DebMes("$ot.workDecision существует таймер запрета",'thrm'); } elseif ($mayBanOn) { DebMes("$ot.workDecision существует бан на включение",'thrm'); } else { $f_off = false; } /* запрет по таймеру на вкл/выкл в т.ч. быстрое изменение мощности ступеней. Включение запрещает таймер отдыха и таймер работы (для быстрого набора ступеней) ВЫключение запрещает только таймер работы */ if ($f_on && ($timeWork || $timeNoWork)) { DebMes("$ot.workDecision запрет за включение по таймеру",'thrm'); $f_on=false; } if ($f_off && $timeWork) { DebMes("$ot.workDecision запрет за выключение по таймеру",'thrm'); $f_off=false; } // В итоге есть решения о необходимости работы или отключеня. DebMes("$ot.workDecision status=$status f_on=$f_on f_off=$f_off",'thrm'); /* Для подсчета общей мощности должно быть задано свойство powerLevels (массивом для нескольких ступеней) В случае массива это свойство ДАЕТ разрещение на управление дополнительными ступенями. */ // Управление. Включить (добавить) if ($f_on && !$f_off) { /* Первое включение после бездействия. При первом пуске сначала включем только первую ступень. Она по факту есть у любого котла. */ if (!$status) { $new_status = 1; } /* Рассчитать количество требуемых ступеней. Формулу расчета требуемой мощности можно использовать только когда котёл, работая на любых ступенях, выйдет на заявленную мощность. Старый вариант: cмотреть на время записи свойства статус, Дадим ему поработать пять минут. Новый вариант: смотреть на существование таймера минимальной работы. Условие таймера _work уже отменяет включение. P.S. По формуле расчета мощности проточного нагревателя W = Q×(t2–t1)×0,073 возможно сразу рассчитать количество нужных ступеней. Но скорость потока через котел будет неизвестной для большинства моделей. Поэтому сделаем расчет исходя из заявленной мощности котла. */ // котел включен и работает какое то время И существуют все температуры воды //if ($status && time()-$arr_status['UPDATED'] > 60*5 && is_numeric($waterRequiredTemp) && is_numeric($waterCurrentTemp) && is_numeric($waterReturnTemp)) { if ($status && is_numeric($waterRequiredTemp) && is_numeric($waterCurrentTemp) && is_numeric($waterReturnTemp)) { // Разбить powerLevels на массив мощностей $powerLevels=$this->getProperty('powerLevels'); preg_match_all('/(\d+\.?\d?)/', $powerLevels, $matches, PREG_PATTERN_ORDER); // ЗНАЧИТ котел со ступенями if (count($matches[0]) > 1) { // Получить текущую мощность работающих ступеней $W = 0; for ($i = 0; $i < $status; $i++) { $W += $matches[0][$i]; } DebMes("$ot.workDecision мощность работы $status ступеней $W кВт",'thrm'); // Вычислить требуемую мощность $W = $W * ($waterRequiredTemp - $waterReturnTemp) / ($waterCurrentTemp - $waterReturnTemp); $W = round($W); DebMes("$ot.workDecision требуемая мощность для выхода на целевую t подачи $W кВт",'thrm'); // Найти нужное количество ступеней $P=0; for ($i = 0; $i < count($matches[0]); $i++) { // Требуемая мощность <= 40% мощности ступени + сумма всех предыдущих ступеней if ($W <= $matches[0][$i]*40/100 + $P) { break; } $P += $matches[0][$i]; } DebMes("$ot.workDecision Нужно $i ступеней",'thrm'); $new_status=$i; } } } // Управление. Выключить (убавить) elseif ($status && $f_off) { /* Ступени будут отключаться по одной. Таймер мин работы должен удержать быстрое отключение сразу всех. Расчета мощности тут не провожу. */ $new_status = max($status - 1, 0); // уже не пойму что это такое было. Просто уменьшаем количество работающих ступеней //if (count($matches[0]) > 1 && $status > 1) { DebMes("$ot.workDecision Условие отключает ступень не по мощности!",'thrm'); } } // Выполнение if (isset($new_status) && $status <> $new_status) { $status = $new_status; DebMes("$ot.workDecision вызов меода managePower с параметром status = $status",'thrm'); $this->setProperty('status', $status); $this->callMethod('managePower', array('status'=>$status)); } return array('status'=>$status); // ответ уходим в ватеркальк
// Вызывается когда меняется текущая или расчетная температура подачи, // передает другому объекту или агрегату расчетную температуру подачи. $ot=$this->object_title; if (defined('THRM_LOG_LEVEL') && THRM_LOG_LEVEL != '') { $log_level = THRM_LOG_LEVEL; } else { $log_level = 0; } if ($log_level>1) { DebMes("$ot.$name Start Called $source",'thrm'); } $this->setProperty('log', 'установка t');
/* Расчет температуры подачи если фактическая температура воздуха +3 <= заблаговременной расчетной т.е. запаздываем на 3 градуса, то берем максимальную температуру подачи из ПЗА. иначе если температура воздуха +1 <= заблаговременной расчетной т.е. меньше заданной на 1 градус, то берем температуру по ПЗА иначе при приближении к заблаговременной температуре воздуха, начинаем уменьшать t подачи */ $ot=$this->object_title; if (defined('THRM_LOG_LEVEL') && THRM_LOG_LEVEL != '') { $log_level = THRM_LOG_LEVEL; } else { $log_level = 0; } if ($log_level>1) { DebMes("$ot.$name Start Called " . mb_substr($source, 0, 50) . '...','thrm'); } /* *** Сбор данных *** */ // При вызове метода после изменения свойства, его значение будет передано в массиве if (isset($params['PROPERTY'])) { // Прекратить выполнение если данные не изменились if ($params['NEW_VALUE'] == $params['OLD_VALUE']) { if ($log_level>1) {DebMes("$ot.waterCalculate значение ".$params['PROPERTY']. " не изменилось",'thrm');} return; } // Составить список всех переменных (одну) list($params['PROPERTY']) = array($params['NEW_VALUE']); } // создать переменные из массива // Если переменная с таким именем существует, её текущее значение не будет перезаписано. extract($params, EXTR_SKIP); // Воздух if (!isset($airCurrentTemp)) { $airCurrentTemp = $this->getProperty('airCurrentTemp'); } if (!isset($airRequiredTemp)) { $airRequiredTemp = $this->getProperty('airRequiredTemp'); } if (!isset($airShiftTemp)) { $airShiftTemp = $this->getProperty('airShiftTemp'); } if (!isset($hysteresis)) { $hysteresis = $this->getProperty('hysteresis'); } if (!isset($pzaTemp)) { $pzaTemp = $this->getProperty('pzaTemp'); } // Вода if (!isset($waterRequiredTemp)) { $waterRequiredTemp = $this->getProperty('waterRequiredTemp'); } if (!isset($waterMaxTemp)) { $waterMaxTemp = $this->getProperty('waterMaxTemp'); } if (!isset($waterMinTemp)) { $waterMinTemp = $this->getProperty('waterMinTemp'); } // *** формат данных и значения по умолчанию if (is_numeric($airCurrentTemp)) { $airCurrentTemp = (float)$airCurrentTemp; } else { $airCurrentTemp = null; } if (is_numeric($airRequiredTemp)) { $airRequiredTemp = (float)$airRequiredTemp; } else { $airRequiredTemp = null; } if (is_numeric($airShiftTemp)) { $airShiftTemp = (float)$airShiftTemp; } else { $airShiftTemp = $airRequiredTemp; } // ! if (is_numeric($hysteresis)) { $hysteresis = (float)$hysteresis; } else { $hysteresis = 0.2; } if (is_numeric($pzaTemp)) { $pzaTemp = (int)$pzaTemp; } else { $pzaTemp = null; } if (is_numeric($waterRequiredTemp)) { $waterRequiredTemp = (int)$waterRequiredTemp; } else { $waterRequiredTemp = null; } if (is_numeric($waterMaxTemp)) { $waterMaxTemp = (int)$waterMaxTemp; } else { $waterMaxTemp = 85; } if (is_numeric($waterMinTemp)) { $waterMinTemp = (int)$waterMinTemp; } else { $waterMinTemp = 10; } if (is_null($airCurrentTemp) || is_null($airShiftTemp)) { $t = 'Нет air данных. t подачи по ПЗА'; $wrt = $pzaTemp; } elseif ($airCurrentTemp + 3 <= $airShiftTemp) { $t = 'Сильно отстаём. максимальная t подачи из ПЗА'; $wrt = (int)$this->callMethod('pzaCalculate', array('t_outside'=>-30, 'option'=>'tm')); } elseif ($airCurrentTemp + 0.6 <= $airShiftTemp) { $t = 'В пределах нормы. t подачи по ПЗА'; $wrt = $pzaTemp; } else { $t = 'Коррекция t при приближении к целевой'; // 10% от температуры ПЗА * коэффициент приближения // коррекция идет по логарифмической шкале (третья степень) $wrt = $pzaTemp; $wrt -= $pzaTemp*10/100 * min(max((1-$airShiftTemp+$airCurrentTemp)**3,0),2); $wrt = round($wrt); } // предельные температуры подачи $wrt = max($wrt, $waterMinTemp); $wrt = min($wrt, $waterMaxTemp); if ($log_level>0) { DebMes("$ot.waterCalculate $t $wrt",'thrm'); } if ($waterRequiredTemp <> $wrt || 1) { $waterRequiredTemp = $wrt; $this->setProperty('waterRequiredTemp', $waterRequiredTemp); $this->setProperty('log', 'расчет t подачи'); /* $arr=[]; $arr['airCurrentTemp'] = $airCurrentTemp; $arr['airRequiredTemp'] = $airRequiredTemp; $arr['airShiftTemp'] = $airShiftTemp; $arr['hysteresis'] = $hysteresis; $arr['pzaTemp'] = $pzaTemp; $arr['waterRequiredTemp'] = $waterRequiredTemp; $arr['waterMaxTemp'] = $waterMaxTemp; $arr['waterMinTemp'] = $waterMinTemp; */ $arr = compact('airCurrentTemp','airRequiredTemp','airShiftTemp', 'hysteresis','pzaTemp', 'waterRequiredTemp','waterMaxTemp','waterMinTemp'); // Запуск исполняющих методов $answers = $this->callMethod('workDecision', $arr); //DebMes("$ot.waterCalculate метод workDecision ОТВЕТИЛ ".serialize($answers),'thrm'); // Передача целевой. Сервопривод? ToDo if (isset($answers['status']) && $answers['status'] > 0 ) { $this->callMethod('setTemperature', array('waterRequiredTemp'=>$waterRequiredTemp)); //$this->callMethod('positionServo', $arr); // ToDo определиться после монтажа } }
/* Расчет целевой температуры воздуха в зависимости от времени суток В результате записывается свойство с историей airRequiredTemp для построения графика и контроля достижения заданной температуры; и свойство без истории airShiftTemp со сдвигом по свойству timeShift для расчета температуры подачи с учетом инерции системы. При изменении будет вызван метод waterCalculate Свойство airFunc должно быть задано массивом, иначе выполнение будет прервано. */ $ot=$this->object_title; if (defined('THRM_LOG_LEVEL') && THRM_LOG_LEVEL != '') { $log_level = THRM_LOG_LEVEL; } else { $log_level = 0; } if ($log_level>1) { DebMes("$ot.$name Start Called " . mb_substr($source, 0, 50) . '...','thrm'); } // Аборт $airFunc=$this->getProperty('airFunc'); if (empty($airFunc)) { if ($log_level>1) { DebMes("$ot.airCalculate Не задана airFunc",'thrm'); } return; } // Преобразовать строку в массив. ToDo использовать регулярку $arrTemp=explode(' ', $airFunc); // Проверить корректность массива температур. ToDo использовать регулярку if (count($arrTemp)<>24) { if ($log_level>0) { DebMes("$ot.airCalculate ИСКЛЮЧЕНИЕ в методе! Не корректный массив в свойстве airFunc",'thrm'); } return; } $h=(int)date('G',time()); $m=date('i',time()); $airRequiredTemp=(float)$this->getProperty('airRequiredTemp'); $airShiftTemp=(float)$this->getProperty('airShiftTemp'); // Получить значение температуры текущего часа $t_desire=$arrTemp[$h]; // следующий элемент массива $hn=$h+1; if ($hn>23) {$hn-=24;} // пропорционально изменить на разницу значения следующего часа $t_desire+=($arrTemp[$hn]-$arrTemp[$h])*$m/60; $t_desire=round($t_desire, 1); // airRequiredTemp используется в основном для построения графиков // и показа желаемого значения температуры на элементах термостатов if ($airRequiredTemp <> $t_desire) { if ($log_level>1) { DebMes("$ot.airCalculate уст. t текущего часа $arrTemp[$h], следующего часа $arrTemp[$hn]",'thrm'); } if ($log_level>0) { DebMes("$ot.airCalculate целевая температура воздуха $t_desire",'thrm'); } $airRequiredTemp = $t_desire; $this->setProperty('airRequiredTemp', $airRequiredTemp); } else { if ($log_level>1) { DebMes("$ot.airCalculate Целевая этого часа не извенилась",'thrm'); } } // Смотреть в будущее чтобы успеть по причине инерционности системы $h += (int)$this->getProperty('timeShift'); if ($h>23) {$h-=24;} // Получить значение температуры будущего часа $t_desire=$arrTemp[$h]; // следующий элемент массива $hn=$h+1; if ($hn>23) {$hn-=24;} // пропорционально изменить на разницу значения следующего часа $t_desire+=($arrTemp[$hn]-$arrTemp[$h])*$m/60; $t_desire=round($t_desire, 1); if ($airShiftTemp <> $t_desire) { if ($log_level>1) { DebMes("$ot.airCalculate уст. t будущего часа $arrTemp[$h], следующего часа $arrTemp[$hn]",'thrm'); } if ($log_level>0) { DebMes("$ot.airCalculate Требуемая будущая температура $t_desire",'thrm'); } $airShiftTemp = $t_desire; $this->setProperty('airShiftTemp', $airShiftTemp); $this->setProperty('log', 'расчет t воздуха'); $this->callMethod('waterCalculate', array('airRequiredTemp'=>$airRequiredTemp, 'airShiftTemp'=>$airShiftTemp)); } else { if ($log_level>1) { DebMes("$ot.airCalculate Целевая будущего часа не извенилась",'thrm'); } }
/* Расчет требуемой температуры подачи по ПЗА Учитывается уличная температура, скорость ветра, яркость солнца Многие коэффициенты влияния этих факторов указаны в коде */ $ot=$this->object_title; if (defined('THRM_LOG_LEVEL') && THRM_LOG_LEVEL != '') { $log_level = THRM_LOG_LEVEL; } else { $log_level = 0; } if ($log_level>1) { DebMes("$ot.$name Start Called $source",'thrm'); } /* *** Сбор данных *** */ // При вызове метода после изменения свойства, его значение будет передано в массиве. В данном методе это не должно случиться. Код оставлен как шаблон. if (isset($params['PROPERTY'])) { // Прекратить выполнение если данные не изменились if ($params['NEW_VALUE'] == $params['OLD_VALUE']) { if ($log_level>1) {DebMes("$ot.waterCalculate вызван свойством ".$params['PROPERTY']. " и получил одинаковые значения ".$params['NEW_VALUE']." Выполнение прервано",'thrm');} return; } // Составить список всех переменных (одну) list($params['PROPERTY']) = array($params['NEW_VALUE']); } // создать переменные из массива // Если переменная с таким именем существует, её текущее значение не будет перезаписано. extract($params, EXTR_SKIP); if (!isset($airRequiredTemp)) { $airRequiredTemp=$this->getProperty('airRequiredTemp'); } if (!isset($k1)) { $k1 = $this->getProperty('k1'); } if (!isset($k2)) { $k2 = $this->getProperty('k2'); } // ВНИМАНИЕ данные берутся с других объектов if (!isset($t_outside)) { $t_outside = gg('weather_now.temperature'); } if (!isset($windSpeed)) { $windSpeed = gg('weather_now.windSpeed'); } if (!isset($Luminiscence)) { $Luminiscence = gg('DrivewayArea.Luminiscence'); } // *** формат данных и значения по умолчанию if (is_numeric($airRequiredTemp)) { $airRequiredTemp = (float)$airRequiredTemp; } else { $airRequiredTemp = null; } if (is_numeric($k1)) { $k1 = (float)$k1; } else { $k1 = 0.6; } if (is_numeric($k2)) { $k2 = (float)$k2; } else { $k2 = 0.6; } if (is_numeric($t_outside)) { $t_outside = (int)$t_outside; } else { $t_outside = null; } if (is_numeric($windSpeed)) { $windSpeed = (float)$windSpeed; } else { $windSpeed = null; } if (is_numeric($Luminiscence)) { $Luminiscence = (int)$Luminiscence; } else { $Luminiscence = null; } // Вертикальное поднятие кривой вверх. При отсутствии берется для 20 градусов по классике if ($airRequiredTemp) { $t_air = $airRequiredTemp; } else { $t_air = 20; } // В начале примет подачу как значение воздуха. $Tp = $t_air; /* Старый вариант расчета с типовыми коэффициентами k1=1.2 k2=20 // Рассчитать изгиб кривой $Tp = sqrt((20-$t)*$k1)*10; if (!isset($params['t_outside']) && $log_level>1) { DebMes("$ot.pzaCalculate Изгиб кривой $Tp",'thrm'); } // При увеличении желаемой комнатной температуры на 1°C кривая традиционно смещается на 5°C: $Tp = $Tp + ($k2-20)*5; if (!isset($params['t_outside']) && $log_level>1) { DebMes("$ot.pzaCalculate Смещение кривой $Tp",'thrm'); } */ /* Рассчитать изгиб кривой по формуле 0.3*sqrt((20-x))*7 + 0.7*(20-x) + 20 коэффициенты k1 + k2 дают классическую кривую. k1 влияет на резкий подъем, k2 дает линейную зависимость вертикальный побъем кривой обеспечивает $airRequiredTemp. Если не задано то считается как 20 */ if (!is_null($t_outside)) { // можно использовать кубический корень и добавить режим охлаждения. Пока мне это не нужно. if ($t_air > $t_outside ) { $Tp = round( $k1*sqrt($t_air-$t_outside)*7 + $k2*($t_air-$t_outside) + $t_air, 2 ); } if ($log_level>0) { DebMes("$ot.pzaCalculate t по холодной кривой $Tp",'thrm'); } if (isset($params['log'])) { echo "Расчет по холодной кривой $Tp <br>"; } } /* Правка на коррекцию В данный момент корректировка включена для всех термостатов */ //if ($ot == 'thrm_beta') { $pazSrt = gg('pzaStr'); if ($pazSrt) { $pzaArr=explode(' ', $pazSrt); } else { $pzaArr=[]; } // проверка массива if (count($pzaArr) == 50) { $corrective = $pzaArr[20-$t_outside]; $Tp += $corrective; if ($log_level>1) { DebMes("$ot.pzaCalculate Коррекция $corrective",'thrm'); } if (isset($params['log'])) { echo "Коррекция $corrective <br>"; } } //} /* Правка на ветер <3 Слабый <6 Сильный <9 Очень сильный Иначе Шквальный поправку вносим из расчета 0- ничего, 10 м*с - 20% */ if (!is_null($windSpeed) && !isset($params['justcount'])) { $corrective = round( $Tp*$windSpeed*2/100, 2 ); //2 - коэффициент соответствия скорости к процентам $Tp += $corrective; if ($log_level>1) { DebMes("$ot.pzaCalculate Поправка на ветер $corrective",'thrm'); } if (isset($params['log'])) { echo "Поправка на ветер $corrective <br>"; } } /* Правка на солнце Освещенность у меня наблюдается от 0 до 600 пунктов поправку вносим из расчета 1 процент с каждой сотни света */ if (!is_null($Luminiscence) && !isset($params['justcount'])) { $corrective = -round( $Tp*$Luminiscence/100/100, 2 ); $Tp += $corrective; if ($log_level>1) { DebMes("$ot.pzaCalculate Поправка на солнце $corrective",'thrm'); } if (isset($params['log'])) { echo "Поправка на солнце $corrective <br>"; } } /* Правка по истории уличной t Долговременное воздействии уличной t на стены здания вызывает необходимость коррекции t подачи. Для упрощения будем только увеличивать подачу, учитывая этот момент при первоначальном задании кривой. т.к. 0 градусов это просто условность шкалы, то из t улицы вычтем 20 и поменяем знак на + получится коэффициент от 0 до 50. Чем он выше, тем больше будет корректировка. Возьмем среднюю t улицы на последние два дня (48 часов) */ // средние значения температуры за последние 2 дня (максимальная глубина истории weather_now) if (!isset($params['justcount'])) { $t_avg = getHistoryAvg('weather_now.temperature', time() - 1*24*60*60); if (is_numeric($t_avg)) { $percent = max(0, -($t_avg - 20)) ** 1.6 / 35; $corrective = round($Tp * $percent / 100, 2); $Tp += $corrective; if ($log_level>1) { DebMes("$ot.pzaCalculate Поправка на холодные стены $corrective",'thrm'); } if (isset($params['log'])) { echo "История t улицы " . round($t_avg). " Правка на " . round($percent) . "% <br>"; } if (isset($params['log'])) { echo "Поправка на холодные стены $corrective <br>"; } } } // *** Округлить до целого числа $Tp = round($Tp); if ($log_level>0) { DebMes("$ot.pzaCalculate Итоговая t по ПЗА $Tp",'thrm'); } if (isset($params['log'])) { echo "На запрос уличной $t_outside ответ $Tp <br>"; } // *** Итоговые действия if (isset($params['justcount'])) { // Возврат для графиков℃ return($Tp); } else { // установка свойства и запуск метода $pzaTemp = $this->getProperty('pzaTemp'); if ($pzaTemp <> $Tp) { $pzaTemp = $Tp; $this->setProperty('pzaTemp', $pzaTemp); $this->setProperty('log', 'расчет t ПЗА'); $this->callMethod('waterCalculate', array('pzaTemp'=>$pzaTemp, 'airRequiredTemp'=>$airRequiredTemp)); } }
Class properties:
Class methods:
//u $this->setProperty("updated",time()); //u $this->setProperty("updatedTime",date("H:i",time())); $ot=$this->object_title; $alive_timeout=(int)$this->getProperty("aliveTimeOut"); if (!$alive_timeout) { $alive_timeout=1*60*60; } setTimeOut($ot."_alive","sg('".$ot.".alive',0);",$alive_timeout); $cmdUrl = $this->getProperty("ipAddress"); if (!$cmdUrl) { return; } $cmdUrl = 'http://'.$cmdUrl; $ctx = stream_context_create(array( 'http' => array('timeout'=>1) ) ); $state = file_get_contents($cmdUrl, 0, $ctx); if (!$state) { $this->setProperty("alive",0); return; } $this->setProperty("alive",1); $value = explode('</br>',$state); // Report - 04.01.2015 14:02:18 $value[0] = substr($value[0],17,18); // I/P Voltage = 217.5 V $value[2] = substr($value[2],16,5); // I/P Fault Voltage = 217.5 V $value[3] = substr($value[3],22,5); // O/P Voltage = 217.5 V $value[4] = substr($value[4],16,5); // O/P Current = 015 % $value[5] = substr($value[5],16,3); // I/P Frequency = 50.0 Hz $value[6] = substr($value[6],18,4); // Battery Voltage = 0108 V $value[7] = substr($value[7],20,4); // Temperature = 53.2 °C $value[8] = trim(substr($value[8],16,5)); // UPS Status = 00001001 $value[9] = substr($value[9],15,8); /* battery.voltage - battery.voltage.low battery.charge = ------------------------------------------ x 100 % battery.voltage.high - battery.voltage.low */ $bh = gg('UPS.batVoltHigh'); $bl = gg('UPS.batVoltLow'); $bc = round( ($value[7] - $bl) / ($bh - $bl) *100 ); $this->setProperty('measurTime',$value[0]); $this->setProperty('inVoltage',$value[2]); $this->setProperty('faultVoltage',$value[3]); $this->setProperty('outVoltage',$value[4]); $this->setProperty('load',$value[5]); $this->setProperty('Frequency',$value[6]); $this->setProperty('batVoltage',$value[7]); $this->setProperty('inTemp',$value[8]); $this->setProperty('status',$value[9]); $this->setProperty('batCharge',$bc);
Class methods:
//$params["LOCATION_OBJECT"], $params["LOCATION"]
//$params["LOCATION_OBJECT"], $params["LOCATION"]
Class properties:
Class methods:
$msg = $this->description.' '.$this->getProperty('weatherType').'.'; $s=round($this->getProperty('temperature')); /* $i=abs($s); if ($i >= 11 and $i <= 14){ $t='ов'; } else { while ($i > 9){ $i=$i-10; } if ($i == 0 or $i >= 5 and $i <= 9) { $t='ов'; } elseif ($i == 1) { $s=''; } elseif ($i >= 2 and $i <= 4) { $t='а'; } } $msg.=' Температура '.$s.' градус'.$t.'. '; */ $msg.=' Температура '.$s.'°.'; $msg.=' Относительная влажность '.$this->getProperty('humidity').'%.'; $s=$this->getProperty('pressure'); if ($s<728) { $msg.=' Атмосферное давление пониженное.'; } elseif ($s>768) { $msg.=' Атмосферное давление повышенное.'; } else { $msg.=' Атмосферное давление нормальное.'; } $s=$this->getProperty('windSpeed'); if ($s==0) { $msg.=' Ветра не ожидается.'; } elseif ($s<3) { $msg.=' Слабый'; } elseif ($s<6) { $msg.=' Сильный'; } elseif ($s<9) { $msg.=' Очень сильный'; } else { $msg.=' Шквальный'; } if ($s) { switch (strtolower($this->getProperty('windDirection'))){ case 's': $msg.=" южный"; break; case 'n': $msg.=" северный"; break; case 'w': $msg.=" западный"; break; case 'e': $msg.=" восточный"; break; case 'sw': $msg.=" юго-западный"; break; case 'nw': $msg.=" северо-западный"; break; case 'se': $msg.=" юго-восточный"; break; case 'ne': $msg.=" северо-восточный"; break; } $msg.= ' ветер.'; } say($msg);
Class properties:
Class methods:
$s=$this->object_title; // переопределить имя точки. [0] имя [1] где $s=runscript('CAPsFriendlyName',array('name'=>$s))[1]; say("Точка $s активна", 1);
$s=$this->object_title; // переопределить имя точки. [0] имя [1] где $s=runscript('CAPsFriendlyName',array('name'=>$s))[1]; say("Внимание. Точка $s не активна", 1);
Class properties:
Class methods:
// ToDo передать в параметре всё что можно, особенно CAPname и marker $ot=$this->object_title; if (preg_match("/[fd]/i", $this->getProperty('marker'), $match)) { switch ($this->getProperty('CAPname')) { case 'CAP--Bagir-1': // только друзья продлевают активность у подъезда if (!in_array('f', $match)) { break; } // моя функция получения времени изменения свойства. Ссылка на форум есть в блоге $rec = mygetGlobalWithUpd('KitchenArea.SomebodyHere'); if ($rec['VALUE']<>$ot || time()-$rec['UPDATED'] > 60*5) { cm('DrivewayArea.onActivity', ['source'=>$ot]); } break; case 'CAP--SXT-1': // свои и друзья продлевают активность беседки $rec = mygetGlobalWithUpd('KitchenArea.SomebodyHere'); if ($rec['VALUE']<>$ot || time()-$rec['UPDATED'] > 60*5) { cm('Gazebo.onActivity', ['source'=>$ot]); } break; case 'CAP--hAPmini-1': // свои и друзья продлевают активность кухни $rec = mygetGlobalWithUpd('KitchenArea.SomebodyHere'); if ($rec['VALUE']<>$ot || time()-$rec['UPDATED'] > 60*5) { cm('KitchenArea.onActivity', ['source'=>$ot]); } break; } }
// *** Уведомление о смене точки *** $n=$this->getProperty('notify'); switch ($n[2]) { case '0': $i=-1; break; case '1': $i=0; break; case '2': $i=1; break; } if (isset($i)) { // переопределить имя точки. [0] имя [1] где $t=$this->getProperty('CAPname'); $t=runscript('CAPsFriendlyName',array('name'=>$t))[1]; // Получить имя девайса $s=$this->getProperty('deviceName'); if (!$s) {$s='Неизвестный девайс';} say("$s передан точке $t", $i); } // *** Маркер *** if (stripos($this->getProperty('marker'), 'd') !== false) { switch ($this->getProperty('CAPname')) { // Открыть дверь ToDo использовать функцию склонения имени case 'CAP--Door': if ($params['oldCAPName']<>'CAP--hAPmini-1') { //запретить открытие при переходе из кухни в гараж say('Открываю входную дверь'); callMethod('RelayFrontDoorOpen.click'); } break; } }
// Получить id свойств для работы с базой данных. Свои id свойств этого класса я уже знаю. $online_pid = 573; //$this->getPropertyByName('online', $this->class_id, $this->id); $marker_pid = 707; //$this->getPropertyByName('marker', $this->class_id, $this->id); $owner_pid = 575; //$this->getPropertyByName('owner', $this->class_id, $this->id); //debmes($online_pid.' '.$marker_pid.' '.$owner_pid, 'test'); $notify = $this->getProperty('notify'); $marker = $this->getProperty('marker'); // *** Уведомление *** switch ($notify[1]) { case '0': $i=-1; break; case '1': $i=0; break; case '2': $i=1; break; } if (isset($i)) { $s=$this->getProperty('deviceName'); if (!$s) {$s='Неизвестный девайс';} say("$s покинул сеть", $i); } /* Выбрать все свойства имен владельцев, свойства объектов которых живые и содержат букву */ // *** Маркер f *** if (stripos($marker, 'f') !== false) { $sql = " SELECT VALUE FROM pvalues WHERE PROPERTY_ID = $owner_pid AND OBJECT_ID IN ( SELECT OBJECT_ID FROM pvalues WHERE PROPERTY_ID = $online_pid AND CAST(VALUE AS INT) > 0) AND OBJECT_ID IN ( SELECT OBJECT_ID FROM pvalues WHERE PROPERTY_ID = $marker_pid AND VALUE LIKE '%f%') "; $rec = SQLSelectOne($sql); // отключить гостевой режим если больше гостей нет и режим был включен if (is_null($rec) && gg('GuestsMode.status')) { cm('GuestsMode.deactivate'); } } // *** Маркер d *** if (stripos($marker, 'd') !== false) { $sql = " SELECT VALUE FROM pvalues WHERE PROPERTY_ID = $owner_pid AND OBJECT_ID IN ( SELECT OBJECT_ID FROM pvalues WHERE PROPERTY_ID = $online_pid AND CAST(VALUE AS INT) > 0) AND OBJECT_ID IN ( SELECT OBJECT_ID FROM pvalues WHERE PROPERTY_ID = $marker_pid AND VALUE LIKE '%d%') "; $rec = SQLSelectOne($sql); if (is_null($rec) && gg('OwnerMode.status')) { cm('OwnerMode.deactivate'); } }
$ot=$this->object_title; // *** Уведомления о статусе устройства в сети *** $n=$this->getProperty('notify'); switch ($n[0]) { case '0': $i=-1; break; case '1': $i=0; break; case '2': $i=1; break; } if (isset($i)) { // переопределить имя точки. [0] имя [1] где $t=$this->getProperty('CAPname'); $t=runscript('CAPsFriendlyName',array('name'=>$t))[1]; // получить имя девайса $s=$this->getProperty('deviceName'); if (!$s) {$s='Неизвестный девайс';} say("$s сейчас в сети. Точка доступа - $t", $i); if ($s == 'Неизвестный девайс') { say($this->getProperty('MAC'), -1); say('Последний раз в сети '.$this->getProperty('lastActive'), -1); } } // *** Буквы маркера *** $m=$this->getProperty('marker'); if (preg_match("/[fd]/i", $m, $match)) { // активность у подъезда, если телефон первый раз обнаружен на этой точке switch ($this->getProperty('CAPname')) { case 'CAP--Bagir-1': cm('DrivewayArea.onActivity', ['source'=>$ot]); break; } // Пустить своих домой if (in_array('d', $match)) { // режим хозяин дома if (!gg('OwnerMode.status')) { cm('OwnerMode.activate'); } switch ($this->getProperty('CAPname')) { case 'CAP--Door': // Открыть дверь ToDo использовать функцию склонения имени say('Открываю входную дверь'); callMethod('RelayFrontDoorOpen.click'); break; } } // Активация гостевого режима if (in_array('f', $match)) { if (!gg('GuestsMode.status')) { cm('GuestsMode.activate'); } } }
Class properties:
Class methods:
//u $this->setProperty("updated",time()); //u $this->setProperty("updatedTime",date("m.d.Y H:i",time())); $this->setProperty("alive",1); $ot=$this->object_title; $alive_timeout=(int)$this->getProperty("aliveTimeOut"); if (!$alive_timeout) { $alive_timeout=24*60*60; } setTimeOut($ot."_alive","sg('".$ot.".alive',0);",$alive_timeout);
//u $this->setProperty("updated",time()); //u $this->setProperty("updatedTime",date("Y-m-d H:i:s",time())); $this->setProperty("alive",1); $ot=$this->object_title; $alive_timeout=(int)$this->getProperty("aliveTimeOut"); if (!$alive_timeout) { $alive_timeout=24*60*60; } setTimeOut($ot."_alive","sg('".$ot.".alive',0);",$alive_timeout);
, Россия
На форуме: Bagir
© 2025 - Site Built By SergeJey | Реквизиты: Курицын С. С. ИНН 762001394609 | Контакты | Public agreement
SmartLiving