Source of file ScenarioExpressionManager.php
Size: 55,145 Bytes - Last Modified: 2020-10-24T02:46:31+00:00
/home/travis/build/NextDom/nextdom-core/src/Managers/ScenarioExpressionManager.php
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621 | <?php /* This file is part of Jeedom. * * Jeedom is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * Jeedom is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Jeedom. If not, see <http://www.gnu.org/licenses/>. */ /* This file is part of NextDom Software. * * NextDom is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * NextDom is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with NextDom. If not, see <http://www.gnu.org/licenses/>. */ namespace NextDom\Managers; use NextDom\Enums\CmdType; use NextDom\Enums\DateFormat; use NextDom\Enums\ScenarioState; use NextDom\Helpers\DateHelper; use NextDom\Helpers\DBHelper; use NextDom\Helpers\FileSystemHelper; use NextDom\Helpers\NetworkHelper; use NextDom\Helpers\NextDomHelper; use NextDom\Helpers\TranslateHelper; use NextDom\Helpers\Utils; use NextDom\Managers\Parents\BaseManager; use NextDom\Managers\Parents\CommonManager; use NextDom\Model\Entity\Cmd; use NextDom\Model\Entity\Scenario; use NextDom\Model\Entity\ScenarioExpression; /** * Class ScenarioExpressionManager * @package NextDom\Managers */ class ScenarioExpressionManager extends BaseManager { use CommonManager; const DB_CLASS_NAME = '`scenarioExpression`'; const CLASS_NAME = ScenarioExpression::class; const WAIT_LIMIT = 7200; /** * Get all scenario expressions * * @return ScenarioExpression|null * * @throws \Exception */ public static function all() { return static::getAll(); } /** * Get the sub-element of a scenario from its identifier * * @param int|string $scenarioSubElementId Scenario sub element ID * * @return ScenarioExpression|null * * @throws \Exception */ public static function byScenarioSubElementId($scenarioSubElementId) { return static::getMultipleByClauses(['scenarioSubElement_id' => $scenarioSubElementId], 'order'); } /** * Search an expression by name and/or option * * @param string $expression Expression searched * @param string $options Option searched * @param bool $and True if the expression and the option are a criterion, if not the expression or the option * * @return ScenarioExpression[]|null * * @throws \Exception */ public static function searchExpression($expression, $options = null, $and = true) { $params = ['expression' => '%' . $expression . '%']; $sql = static::getBaseSQL() . ' WHERE `expression` LIKE :expression '; if ($options !== null) { $params['options'] = '%' . $options . '%'; if ($and) { $sql .= 'AND `options` LIKE :options'; } else { $sql .= 'OR `options` LIKE :options'; } } return DBHelper::getAllObjects($sql, $params, self::CLASS_NAME); } /** * Searches for an expression on scenario expression of type "element" * * @param $elementId * @return array|mixed|null * @throws \Exception */ public static function byElement($elementId) { return static::getOneByClauses(['expression' => $elementId, 'type' => 'element']); } /** * @TODO ???? * @TODO Revoir la génération des UID * * @param $expression * @param $options * * @return array * @throws \Exception */ public static function getExpressionOptions($expression, $options) { $replace = [ '#uid#' => 'exp' . mt_rand() ]; $result = ['html' => '']; $cmd = CmdManager::byId(str_replace('#', '', CmdManager::humanReadableToCmd($expression))); if (is_object($cmd)) { $result['html'] = trim($cmd->toHtml('scenario', $options)); return $result; } $result['template'] = FileSystemHelper::getCoreTemplateFileContent('scenario', $expression . '.default'); $options = Utils::isJson($options, $options); if (is_array($options) && count($options) > 0) { foreach ($options as $key => $value) { $replace['#' . $key . '#'] = str_replace('"', '"', $value); } } if (!isset($replace['#id#'])) { $replace['#id#'] = mt_rand(); } $result['html'] = Utils::templateReplace(CmdManager::cmdToHumanReadable($replace), $result['template']); preg_match_all("/#[a-zA-Z_]*#/", $result['template'], $matches); foreach ($matches[0] as $value) { if (!isset($replace[$value])) { $replace[$value] = ''; } } $result['html'] = TranslateHelper::exec(Utils::templateReplace($replace, $result['html']), 'views/templates/scenario/' . $expression . '.default'); return $result; } /** * @TODO ???? * * @param $baseAction * * @return string * * @throws \Exception */ public static function humanAction($baseAction) { $result = ''; if ($baseAction['cmd'] == 'scenario') { $scenario = ScenarioManager::byId($baseAction['options']['scenario_id']); if (!is_object($scenario)) { $name = 'scenario ' . $baseAction['options']['scenario_id']; } else { $name = $scenario->getName(); } $action = $baseAction['options']['action']; $result .= __('Scénario : ') . $name . ' <i class="fa fa-arrow-right"></i> ' . $action; } elseif ($baseAction['cmd'] == 'variable') { $name = $baseAction['options']['name']; $value = $baseAction['options']['value']; $result .= __('Variable : ') . $name . ' <i class="fa fa-arrow-right"></i> ' . $value; } elseif (is_object(CmdManager::byId(str_replace('#', '', $baseAction['cmd'])))) { $cmd = CmdManager::byId(str_replace('#', '', $baseAction['cmd'])); $eqLogic = $cmd->getEqLogicId(); $result .= $eqLogic->getHumanName(true) . ' ' . $cmd->getName(); } return trim($result); } /** * Get a random number * * @param $minValue * @param $maxValue * * @return int */ public static function rand(int $minValue, int $maxValue): int { return mt_rand($minValue, $maxValue); } /** * @TODO ??? * @TODO Result n'est jamais utilisé, le bloc Try peut normalement être supprimé * @param $_sValue * * @return array|mixed * @throws \NextDom\Exceptions\CoreException * @throws \ReflectionException */ public static function randText($_sValue) { $_sValue = self::setTags($_sValue); $_aValue = explode(";", $_sValue); try { $result = Utils::evaluate($_aValue); if (is_string($result)) { $result = $_aValue; } } catch (\Exception $e) { $result = $_aValue; } if (is_array($_aValue)) { $nbr = mt_rand(0, count($_aValue) - 1); return $_aValue[$nbr]; } else { return $_aValue; } } /** * @TODO Faut bien les définir les tags * * @param $_expression * @param Scenario $_scenario * @param bool $_quote * @param int $_nbCall * @return mixed * @throws \NextDom\Exceptions\CoreException * @throws \ReflectionException */ public static function setTags($_expression, &$_scenario = null, $_quote = false, $_nbCall = 0) { if ($_nbCall > 10) { return $_expression; } $replace1 = self::getRequestTags($_expression); if ($_scenario !== null && count($_scenario->getTags()) > 0) { $replace1 = array_merge($replace1, $_scenario->getTags()); } if (is_object($_scenario)) { $cmd = CmdManager::byId(str_replace('#', '', $_scenario->getRealTrigger())); if (is_object($cmd)) { $replace1['#trigger#'] = $cmd->getHumanName(); $replace1['#trigger_value#'] = $cmd->execCmd(); } else { $replace1['#trigger#'] = $_scenario->getRealTrigger(); } } if ($_quote) { foreach ($replace1 as &$value) { if (strpos($value, ' ') !== false || preg_match("/[a-zA-Z]/", $value) || $value === '') { $value = '"' . trim($value, '"') . '"'; } } } $replace2 = []; if (!is_string($_expression)) { return $_expression; } preg_match_all("/([a-zA-Z][a-zA-Z_]*?)\((.*?)\)/", $_expression, $matches, PREG_SET_ORDER); if (is_array($matches)) { foreach ($matches as $match) { $function = $match[1]; $replace_string = $match[0]; if (substr_count($match[2], '(') != substr_count($match[2], ')')) { $pos = strpos($_expression, $match[2]) + strlen($match[2]); while (substr_count($match[2], '(') > substr_count($match[2], ')')) { $match[2] .= $_expression[$pos]; $pos++; if ($pos > strlen($_expression)) { break; } } $arguments = self::setTags($match[2], $_scenario, $_quote, $_nbCall++); while ($arguments[0] == '(' && $arguments[strlen($arguments) - 1] == ')') { $arguments = substr($arguments, 1, -1); } $result = str_replace($match[2], $arguments, $_expression); while (substr_count($result, '(') > substr_count($result, ')')) { $result .= ')'; } $result = self::setTags($result, $_scenario, $_quote, $_nbCall++); return CmdManager::cmdToValue(str_replace(array_keys($replace1), array_values($replace1), $result), $_quote); } else { $arguments = explode(',', $match[2]); } if (method_exists(__CLASS__, $function)) { if ($function == 'trigger') { if (!isset($arguments[0])) { $arguments[0] = ''; } $replace2[$replace_string] = self::trigger($arguments[0], $_scenario); } elseif ($function == 'triggerValue') { $replace2[$replace_string] = self::triggerValue($_scenario); } elseif ($function == 'tag') { if (!isset($arguments[0])) { $arguments[0] = ''; } if (!isset($arguments[1])) { $arguments[1] = ''; } $replace2[$replace_string] = self::tag($_scenario, $arguments[0], $arguments[1]); } else { $replace2[$replace_string] = call_user_func_array(__CLASS__ . "::" . $function, $arguments); } } else { if (function_exists($function)) { foreach ($arguments as &$argument) { $argument = trim(Utils::evaluate(self::setTags($argument, $_scenario, $_quote))); } $replace2[$replace_string] = call_user_func_array($function, $arguments); } } if ($_quote && isset($replace2[$replace_string]) && (strpos($replace2[$replace_string], ' ') !== false || preg_match("/[a-zA-Z#]/", $replace2[$replace_string]) || $replace2[$replace_string] === '')) { $replace2[$replace_string] = '"' . trim($replace2[$replace_string], '"') . '"'; } } } $return = CmdManager::cmdToValue(str_replace(array_keys($replace1), array_values($replace1), str_replace(array_keys($replace2), array_values($replace2), $_expression)), $_quote); return $return; } /** * @TODO: Je demande des tags * * @param $expression * @return array * @throws \Exception */ public static function getRequestTags($expression) { $result = []; preg_match_all("/#([a-zA-Z0-9_]*)#/", $expression, $matches); if (count($matches) == 0) { return $result; } $matches = array_unique($matches[0]); $humanToDate = [ '#seconde#' => 's', '#heure#' => 'G', '#heure12#' => 'g', '#minute#' => 'i', '#jour#' => 'd', '#mois#' => 'm', '#annee#' => 'Y', '#njour#' => 'w', '#time#' => 'Gi', '#date#' => 'md', '#semaine#' => 'W' ]; foreach ($matches as $tag) { switch ($tag) { case '#seconde#': case '#heure#': case '#heure12#': case '#minute#': case '#jour#': case '#mois#': case '#annee#': case '#njour#': $result[$tag] = (int)date($humanToDate[$tag]); break; case '#time#': case '#date#': case '#semaine#': $result[$tag] = date($humanToDate[$tag]); break; case '#timestamp#': $result['#timestamp#'] = time(); break; case '#sjour#': $result['#sjour#'] = '"' . DateHelper::dateToFr(date('l')) . '"'; break; case '#smois#': $result['#smois#'] = '"' . DateHelper::dateToFr(date('F')) . '"'; break; case '#jeedom_name#': case '#nextdom_name#': $result[$tag] = '"NextDom"'; break; case '#hostname#': $result['#hostname#'] = '"' . gethostname() . '"'; break; case '#IP#': $result['#IP#'] = '"' . NetworkHelper::getNetworkAccess('internal', 'ip', '', false) . '"'; break; case '#trigger#': case '#trigger_value#': $result[$tag] = ''; break; } } return $result; } /** * @TODO ???? * @ il semble judicieu de rajouter l'interface SenarioInterface à $senario, elle est prete, faut se servir... * @param string $name * @param Scenario $scenario * @return int */ public static function trigger($name = '', &$scenario = null) { if ($scenario !== null) { if (trim($name) == '') { return $scenario->getRealTrigger(); } if ($name == $scenario->getRealTrigger()) { return 1; } } return 0; } /** * @TODO ???? * * @param Scenario $scenario * @return mixed * @throws \Exception */ public static function triggerValue(&$scenario = null) { if ($scenario !== null) { $cmd = CmdManager::byId(str_replace('#', '', $scenario->getRealTrigger())); if (is_object($cmd)) { return $cmd->execCmd(); } } return false; } /** * @TODO: Un tag * * @param Scenario|null $scenario * @param $name * @param string $default * @return string */ public static function tag(&$scenario = null, $name, $default = '') { if ($scenario === null) { return '"' . $default . '"'; } $tags = $scenario->getTags(); if (isset($tags['#' . $name . '#'])) { return $tags['#' . $name . '#']; } return '"' . $default . '"'; } /** * Get a scenario from its expression * @TODO: Format ??? * * @param $scenarioExpression * @return int @TODO -1, -2, -3 ???? * @throws \Exception */ public static function scenario(string $scenarioExpression) { $id = str_replace(['scenario', '#'], '', trim($scenarioExpression)); $scenario = ScenarioManager::byId($id); if (!is_object($scenario)) { return -2; } $state = $scenario->getState(); if ($scenario->getIsActive() == 0) { return -1; } switch ($state) { case ScenarioState::STOP: return 0; case ScenarioState::IN_PROGRESS: return 1; } return -3; } /** * Enables an eqLogic object * @TODO: -2 en -1 ? * @param mixed $eqLogicId Identifiant du l'objet * * @return int 0 If the object is not activated, 1 if the object is activated, -2 if the object does not exist * @throws \Exception */ public static function eqEnable($eqLogicId) { $id = str_replace(['eqLogic', '#'], '', trim($eqLogicId)); $eqLogic = EqLogicManager::byId($id); if (!is_object($eqLogic)) { return -2; } return $eqLogic->getIsEnable(); } /** * @TODO: Fait une moyenne de quelque chose * @TODO: Mettre en place la gestion du nombre de paramètres variables * * @param mixed $cmdId Identifiant de la commande * @param string $period Période sur laquelle la moyenne doit être calculée * * @return float|int|string * @throws \Exception */ public static function average($cmdId, $period = '1 hour') { $args = func_get_args(); if (count($args) > 2 || strpos($period, '#') !== false || is_numeric($period)) { $values = []; foreach ($args as $arg) { if (is_numeric($arg)) { $values[] = $arg; } else { $value = CmdManager::cmdToValue($arg); if (is_numeric($value)) { $values[] = $value; } else { try { $values[] = Utils::evaluate($value); } catch (\Throwable $ex) { } } } } return array_sum($values) / count($values); } else { $cmd = CmdManager::byId(trim(str_replace('#', '', $cmdId))); if (!is_object($cmd) || $cmd->getIsHistorized() == 0) { return ''; } if (str_word_count($period) == 1 && is_numeric(trim($period)[0])) { $startHist = date(DateFormat::FULL, strtotime(date(DateFormat::FULL) . ' -' . $period)); } else { $startHist = date(DateFormat::FULL, strtotime($period)); if ($startHist == date(DateFormat::FULL, strtotime(0))) { return ''; } } $historyStatistic = $cmd->getStatistique($startHist, date(DateFormat::FULL)); if (!isset($historyStatistic['avg']) || $historyStatistic['avg'] == '') { return $cmd->execCmd(); } return round($historyStatistic['avg'], 1); } } /** * @TODO: Calcule une moyenne de quelque chose entre deux dates * * @param $cmdId * @param $startDate * @param $endDate * * @return float|string * @throws \NextDom\Exceptions\CoreException * @throws \ReflectionException */ public static function averageBetween($cmdId, $startDate, $endDate) { $cmd = CmdManager::byId(trim(str_replace('#', '', $cmdId))); if (!is_object($cmd) || $cmd->getIsHistorized() == 0) { return ''; } $startDate = date(DateFormat::FULL, strtotime(self::setTags($startDate))); $endDate = date(DateFormat::FULL, strtotime(self::setTags($endDate))); $historyStatistic = $cmd->getStatistique($startDate, $endDate); if (!isset($historyStatistic['avg'])) { return ''; } return round($historyStatistic['avg'], 1); } /** * Obtenir un dégradé de couleur * * @param $_from_color Couleur de départ * @param $_to_color Couleur de fin * @param $_min * @param $_max * @param $_value * @return mixed */ public static function color_gradient($_from_color, $_to_color, $_min, $_max, $_value) { if (!is_numeric($_value)) { $value = round(NextDomHelper::evaluateExpression($_value)); } else { $value = round($_value); } $graduations = $_max - $_min - 1; $value -= $_min + 1; $startcol = str_replace('#', '', $_from_color); $endcol = str_replace('#', '', $_to_color); $RedOrigin = hexdec(substr($startcol, 1, 2)); $GrnOrigin = hexdec(substr($startcol, 3, 2)); $BluOrigin = hexdec(substr($startcol, 5, 2)); if ($graduations >= 2) { $GradientSizeRed = (hexdec(substr($endcol, 1, 2)) - $RedOrigin) / $graduations; $GradientSizeGrn = (hexdec(substr($endcol, 3, 2)) - $GrnOrigin) / $graduations; $GradientSizeBlu = (hexdec(substr($endcol, 5, 2)) - $BluOrigin) / $graduations; for ($i = 0; $i <= $graduations; $i++) { $RetVal[$i] = strtoupper("#" . str_pad(dechex($RedOrigin + ($GradientSizeRed * $i)), 2, '0', STR_PAD_LEFT) . str_pad(dechex($GrnOrigin + ($GradientSizeGrn * $i)), 2, '0', STR_PAD_LEFT) . str_pad(dechex($BluOrigin + ($GradientSizeBlu * $i)), 2, '0', STR_PAD_LEFT)); } } elseif ($graduations == 1) { $RetVal[] = $_from_color; $RetVal[] = $_to_color; } else { $RetVal[] = $_from_color; } if (isset($RetVal[$value])) { return $RetVal[$value]; } if ($_value <= $_min) { return $RetVal[0]; } return $RetVal[count($RetVal) - 1]; } /** * Obtenir la valeur maximum sur une période @TODO: de quelque chose * * @param $cmdId * @param string $period * @return float|mixed|string * @throws \Exception */ public static function max($cmdId, $period = '1 hour') { $args = func_get_args(); if (count($args) > 2 || strpos($period, '#') !== false || is_numeric($period)) { $values = []; foreach ($args as $arg) { if (is_numeric($arg)) { $values[] = $arg; } else { $value = CmdManager::cmdToValue($arg); if (is_numeric($value)) { $values[] = $value; } else { try { $values[] = Utils::evaluate($value); } catch (\Throwable $ex) { } } } } return max($values); } else { $cmd = CmdManager::byId(trim(str_replace('#', '', $cmdId))); if (!is_object($cmd) || $cmd->getIsHistorized() == 0) { return ''; } if (str_word_count($period) == 1 && is_numeric(trim($period)[0])) { $startHist = date(DateFormat::FULL, strtotime(date(DateFormat::FULL) . ' -' . $period)); } else { $startHist = date(DateFormat::FULL, strtotime($period)); if ($startHist == date(DateFormat::FULL, strtotime(0))) { return ''; } } $historyStatistique = $cmd->getStatistique($startHist, date(DateFormat::FULL)); if (!isset($historyStatistique['max']) || $historyStatistique['max'] == '') { return $cmd->execCmd(); } return round($historyStatistique['max'], 1); } } /** * Obtenir la valeur maximum entre deux dates @TODO: de quelque chose * * @param $cmdId * @param $startDate * @param $endDate * @return float|string * @throws \NextDom\Exceptions\CoreException * @throws \ReflectionException */ public static function maxBetween($cmdId, $startDate, $endDate) { $cmd = CmdManager::byId(trim(str_replace('#', '', $cmdId))); if (!is_object($cmd) || $cmd->getIsHistorized() == 0) { return ''; } $startDate = date(DateFormat::FULL, strtotime(self::setTags($startDate))); $endDate = date(DateFormat::FULL, strtotime(self::setTags($endDate))); $historyStatistique = $cmd->getStatistique(self::setTags($startDate), self::setTags($endDate)); if (!isset($historyStatistique['max'])) { return ''; } return round($historyStatistique['max'], 1); } /** * Attend que la condition soit vraie. * * @param mixed $condition Condition à tester * @param int $waitTimeout Durée limite de l'attente (7200s par défaut) * * @return int */ public static function wait($condition, $waitTimeout = self::WAIT_LIMIT) { $result = false; $occurence = 0; // Si le timeout est une expression, évalue sa valeur $timeout = NextDomHelper::evaluateExpression($waitTimeout); // Si le timeout $limit = (is_numeric($timeout)) ? $timeout : self::WAIT_LIMIT; while ($result !== true) { $result = NextDomHelper::evaluateExpression($condition); if ($occurence > $limit) { return 0; } $occurence++; sleep(1); } return 1; } /** * Obtenir la valeur minimum sur une période @TODO: ??? Toujours sur quoi ? * @param $cmdId * @param string $period * @return float|mixed|string * @throws \Exception */ public static function min($cmdId, $period = '1 hour') { $args = func_get_args(); if (count($args) > 2 || strpos($period, '#') !== false || is_numeric($period)) { $values = []; foreach ($args as $arg) { if (is_numeric($arg)) { $values[] = $arg; } else { $value = CmdManager::cmdToValue($arg); if (is_numeric($value)) { $values[] = $value; } else { try { $values[] = Utils::evaluate($value); } catch (\Throwable $ex) { } } } } return min($values); } else { $cmd = CmdManager::byId(trim(str_replace('#', '', $cmdId))); if (!is_object($cmd) || $cmd->getIsHistorized() == 0) { return ''; } if (str_word_count($period) == 1 && is_numeric(trim($period)[0])) { $startHist = date(DateFormat::FULL, strtotime(date(DateFormat::FULL) . ' -' . $period)); } else { $startHist = date(DateFormat::FULL, strtotime($period)); if ($startHist == date(DateFormat::FULL, strtotime(0))) { return ''; } } $historyStatistique = $cmd->getStatistique($startHist, date(DateFormat::FULL)); if (!isset($historyStatistique['min']) || $historyStatistique['min'] == '') { return $cmd->execCmd(); } return round($historyStatistique['min'], 1); } } /** * Obtenir la valeur minimum entre deux dates @TODO: De quoi ? * * @param $cmdId * @param $startDate * @param $endDate * @return float|string * @throws \NextDom\Exceptions\CoreException * @throws \ReflectionException */ public static function minBetween($cmdId, $startDate, $endDate) { $cmd = CmdManager::byId(trim(str_replace('#', '', $cmdId))); if (!is_object($cmd) || $cmd->getIsHistorized() == 0) { return ''; } $startDate = date(DateFormat::FULL, strtotime(self::setTags($startDate))); $endDate = date(DateFormat::FULL, strtotime(self::setTags($endDate))); $historyStatistique = $cmd->getStatistique($startDate, $endDate); if (!isset($historyStatistique['min'])) { return ''; } return round($historyStatistique['min'], 1); } /** * Obtenir une valeur médiane @TODO: De quoi ? * * @return int|mixed * @throws \NextDom\Exceptions\CoreException * @throws \ReflectionException */ public static function median() { $args = func_get_args(); $values = []; foreach ($args as $arg) { if (is_numeric($arg)) { $values[] = $arg; } else { $value = CmdManager::cmdToValue($arg); if (is_numeric($value)) { $values[] = $value; } else { try { $values[] = Utils::evaluate($value); } catch (\Throwable $ex) { } } } } if (count($values) < 1) { return 0; } if (count($values) == 1) { return $values[0]; } sort($values); return $values[round(count($values) / 2) - 1]; } public static function avg() { $args = func_get_args(); $values = []; foreach ($args as $arg) { if (is_numeric($arg)) { $values[] = $arg; } else { $value = CmdManager::cmdToValue($arg); if (is_numeric($value)) { $values[] = $value; } else { try { $values[] = evaluate($value); } catch (\Exception $ex) { } } } } if (count($values) < 1) { return 0; } if (count($values) == 1) { return $values[0]; } return array_sum($values) / count($values); } /** * Renvoie une tendance @TODO de ? * * @param $cmdId * @param string $period * @param string $threshold * @return int|string * @throws \Exception */ public static function tendance($cmdId, $period = '1 hour', $threshold = '') { $cmd = CmdManager::byId(trim(str_replace('#', '', $cmdId))); if (!is_object($cmd)) { return ''; } if ($cmd->getIsHistorized() == 0) { return ''; } $endTime = date(DateFormat::FULL); if (str_word_count($period) == 1 && is_numeric(trim($period)[0])) { $startTime = date(DateFormat::FULL, strtotime(date(DateFormat::FULL) . ' -' . $period)); } else { $startTime = date(DateFormat::FULL, strtotime($period)); if ($startTime == date(DateFormat::FULL, strtotime(0))) { return ''; } } $tendance = $cmd->getTendance($startTime, $endTime); if ($threshold != '') { $maxThreshold = $threshold; $minThreshold = -$threshold; } else { $maxThreshold = ConfigManager::byKey('historyCalculTendanceThresholddMax'); $minThreshold = ConfigManager::byKey('historyCalculTendanceThresholddMin'); } if ($tendance > $maxThreshold) { return 1; } if ($tendance < $minThreshold) { return -1; } return 0; } /** * @TODO: j'en sais rien, durée pendant laquelle il a conserver son état sans doute * * @param $cmdId * @param null $value * @return false|int * @throws \Exception */ public static function lastStateDuration($cmdId, $value = null) { return HistoryManager::lastStateDuration(str_replace('#', '', $cmdId), $value); } /** * @TODO Changement d'état, ou de pantalon, ou de slip * * @param $cmdId * @param null $value * @param string $period * @return array|string * @throws \Exception */ public static function stateChanges($cmdId, $value = null, $period = '1 hour') { $cmd = CmdManager::byId(str_replace('#', '', $cmdId)); if (!is_numeric(str_replace('#', '', $cmdId))) { $cmd = CmdManager::byId(str_replace('#', '', CmdManager::humanReadableToCmd($cmdId))); } if (!is_object($cmd) || $cmd->getIsHistorized() == 0) { return ''; } $cmd_id = $cmd->getId(); $args = func_num_args(); if ($args == 2) { if (is_numeric(func_get_arg(1))) { $value = func_get_arg(1); } else { $period = func_get_arg(1); $value = null; } } return HistoryManager::stateChanges($cmd_id, $value, date(DateFormat::FULL, strtotime('-' . $period)), date(DateFormat::FULL)); } /** * Changement entre deux dates //@TODO: Woohoo * * @param $cmdId * @param $value * @param $startDate * @param null $endDate * @return array|string * @throws \NextDom\Exceptions\CoreException * @throws \ReflectionException */ public static function stateChangesBetween($cmdId, $value, $startDate, $endDate = null) { if (!is_numeric(str_replace('#', '', $cmdId))) { $cmd = CmdManager::byId(str_replace('#', '', CmdManager::humanReadableToCmd($cmdId))); } else { $cmd = CmdManager::byId(str_replace('#', '', $cmdId)); } if (!is_object($cmd) || $cmd->getIsHistorized() == 0) { return ''; } $cmd_id = $cmd->getId(); if (func_num_args() == 3) { $endDate = func_get_arg(2); $startDate = func_get_arg(1); $value = null; } $startDate = date(DateFormat::FULL, strtotime(self::setTags($startDate))); $endDate = date(DateFormat::FULL, strtotime(self::setTags($endDate))); return HistoryManager::stateChanges($cmd_id, $value, $startDate, $endDate); } /** * Get the duration since the command has this value * * @param $cmdId * @param $value * @param string $period * @return float|string * @throws \Exception */ public static function duration($cmdId, $value, $period = '1 hour') { $cmd_id = str_replace('#', '', $cmdId); if (!is_numeric($cmd_id)) { $cmd_id = CmdManager::byId(str_replace('#', '', CmdManager::humanReadableToCmd($cmdId))); } $cmd = CmdManager::byId($cmd_id); if (!is_object($cmd) || $cmd->getIsHistorized() == 0) { return ''; } if (str_word_count($period) == 1 && is_numeric(trim($period)[0])) { $startDate = date(DateFormat::FULL, strtotime(date(DateFormat::FULL) . ' -' . $period)); } else { $startDate = date(DateFormat::FULL, strtotime($period)); if ($startDate == date(DateFormat::FULL, strtotime(0))) { return ''; } } $endDate = date(DateFormat::FULL); return self::getCmdValueDuration($cmd, $startDate, $endDate, $value); } /** * @param Cmd $cmd * @param string $startDate * @param string $endDate * @param mixed $value * @return float|string * @throws \Exception */ private static function getCmdValueDuration($cmd, $startDate, $endDate, $value) { $value = str_replace(',', '.', $value); $histories = $cmd->getHistory(); $nbDecimals = strlen(substr(strrchr($value, "."), 1)); if (count($histories) == 0) { return ''; } $duration = 0; $lastDuration = strtotime($histories[0]->getDatetime()); $lastValue = $histories[0]->getValue(); foreach ($histories as $history) { if ($history->getDatetime() >= $startDate) { if ($history->getDatetime() <= $endDate) { if ($lastValue == $value) { $duration = $duration + (strtotime($history->getDatetime()) - $lastDuration); } } else { if ($lastValue == $value) { $duration = $duration + (strtotime($endDate) - $lastDuration); } break; } $lastDuration = strtotime($history->getDatetime()); } else { $lastDuration = strtotime($startDate); } $lastValue = round($history->getValue(), $nbDecimals); } if ($lastValue == $value && $lastDuration <= strtotime($endDate)) { $duration = $duration + (strtotime($endDate) - $lastDuration); } return floor($duration / 60); } /** * Get the duration between the command has this value * * @param $cmdId * @param $value * @param $startDate * @param $endDate * @return float|string * @throws \Exception */ public static function durationBetween($cmdId, $value, $startDate, $endDate) { if (!is_numeric(str_replace('#', '', $cmdId))) { $cmd = CmdManager::byId(str_replace('#', '', CmdManager::humanReadableToCmd($cmdId))); } else { $cmd = CmdManager::byId(str_replace('#', '', $cmdId)); } if (!is_object($cmd) || $cmd->getIsHistorized() == 0) { return ''; } $startDate = date(DateFormat::FULL, strtotime(self::setTags($startDate))); $endDate = date(DateFormat::FULL, strtotime(self::setTags($endDate))); return self::getCmdValueDuration($cmd, $startDate, $endDate, $value); } /** * @TODO: Dernier entre deux dates ??? * * @param $cmdId * @param $startDate * @param $endDate * @return float|string * @throws \NextDom\Exceptions\CoreException * @throws \ReflectionException */ public static function lastBetween($cmdId, $startDate, $endDate) { $cmd = CmdManager::byId(trim(str_replace('#', '', $cmdId))); if (!is_object($cmd) || $cmd->getIsHistorized() == 0) { return ''; } $startDate = date(DateFormat::FULL, strtotime(self::setTags($startDate))); $endDate = date(DateFormat::FULL, strtotime(self::setTags($endDate))); $historyStatistic = $cmd->getStatistique($startDate, $endDate); if (!isset($historyStatistic['last']) || $historyStatistic['last'] === '') { return ''; } return round($historyStatistic['last'], 1); } /** * @TODO: Statistiques de quelque chose * * @param $cmdId * @param $calc * @param string $period * @return string * @throws \Exception */ public static function statistics($cmdId, $calc, $period = '1 hour') { $cmd = CmdManager::byId(trim(str_replace('#', '', $cmdId))); if (!is_object($cmd) || $cmd->getIsHistorized() == 0) { return ''; } if (str_word_count($period) == 1 && is_numeric(trim($period)[0])) { $startHist = date(DateFormat::FULL, strtotime(date(DateFormat::FULL) . ' -' . $period)); } else { $startHist = date(DateFormat::FULL, strtotime($period)); if ($startHist == date(DateFormat::FULL, strtotime(0))) { return ''; } } $calc = str_replace(' ', '', $calc); $historyStatistic = $cmd->getStatistique($startHist, date(DateFormat::FULL)); if (!isset($historyStatistic['min']) || $historyStatistic['min'] == '') { return $cmd->execCmd(); } return $historyStatistic[$calc]; } /** * @TODO: Statistiques de quelque chose entre deux dates * * @param $cmdId * @param $calc * @param $startDate * @param $endDate * @return string * @throws \NextDom\Exceptions\CoreException * @throws \ReflectionException */ public static function statisticsBetween($cmdId, $calc, $startDate, $endDate) { $cmd = CmdManager::byId(trim(str_replace('#', '', $cmdId))); if (!is_object($cmd) || $cmd->getIsHistorized() == 0) { return ''; } $calc = str_replace(' ', '', $calc); $startDate = date(DateFormat::FULL, strtotime(self::setTags($startDate))); $endDate = date(DateFormat::FULL, strtotime(self::setTags($endDate))); $historyStatistique = $cmd->getStatistique(self::setTags($startDate), self::setTags($endDate)); return $historyStatistique[$calc]; } /** * Obtenir la valeur d'une variable * * @param $name * @param string $defaultValue Valeur par défaut * @return string * @throws \Exception */ public static function variable($name, $defaultValue = '') { // @TODO: Yolo sur les trims $name = trim(trim(trim($name), '"')); $dataStore = DataStoreManager::byTypeLinkIdKey('scenario', -1, trim($name)); if (is_object($dataStore)) { $value = $dataStore->getValue($defaultValue); return $value; } return $defaultValue; } /** * Obtenir la durée d'un état * * @param $cmdId * @param null $value * @return false|int * @throws \Exception */ public static function stateDuration($cmdId, $value = null) { return HistoryManager::stateDuration(str_replace('#', '', $cmdId), $value); } /** * @TODO: Dernier changement de la durée de ??? * * @param $cmdId * @param $value * @return false|int * @throws \Exception */ public static function lastChangeStateDuration($cmdId, $value) { return HistoryManager::lastChangeStateDuration(str_replace('#', '', $cmdId), $value); } /** * Tester si une valeur est paire * @TODO: Changer en binaire le résultat * * @param mixed $value * * @return int 1 si $value est pair, sinon 0 * @throws \NextDom\Exceptions\CoreException * @throws \ReflectionException */ public static function odd($value): int { $value = intval(Utils::evaluate(self::setTags($value))); if ($value % 2) { return 1; } else { return 0; } } /** * Obtenir l'interval de temps depuis lequel le scénario s'est exécuté * * @param string $scenarioId Identifiant du scénario * @return false|int * @throws \Exception */ public static function lastScenarioExecution($scenarioId) { $scenario = ScenarioManager::byId(str_replace(['#scenario', '#'], '', $scenarioId)); if (!is_object($scenario)) { return 0; } return strtotime('now') - strtotime($scenario->getLastLaunch()); } /** * @TODO: Collecter une date * * @param $cmdId * @param string $format * @return false|int|string * @throws \Exception */ public static function collectDate($cmdId, $format = DateFormat::FULL) { $cmdObj = CmdManager::byId(trim(str_replace('#', '', $cmdId))); if (!is_object($cmdObj)) { return -1; } if (!$cmdObj->isType(CmdType::INFO)) { return -2; } $cmdObj->execCmd(); return date($format, strtotime($cmdObj->getCollectDate())); } /** * @TODO: Valeur d'une date * * @param $cmdId * @param string $format * @return false|string * @throws \Exception */ public static function valueDate($cmdId, $format = DateFormat::FULL) { $cmd = CmdManager::byId(trim(str_replace('#', '', $cmdId))); if (!is_object($cmd)) { return ''; } $cmd->execCmd(); return date($format, strtotime($cmd->getValueDate())); } /** * @param $_eqLogic_id * @param string $_format * @return false|int|string * @throws \Exception */ public static function lastCommunication($_eqLogic_id, $_format = DateFormat::FULL) { $eqLogic = EqLogicManager::byId(trim(str_replace(['#', '#eqLogic', 'eqLogic'], '', EqLogicManager::fromHumanReadable('#' . str_replace('#', '', $_eqLogic_id) . '#')))); if (!is_object($eqLogic)) { return -1; } return date($_format, strtotime($eqLogic->getStatus('lastCommunication', date(DateFormat::FULL)))); } /** * @param $_cmd_id * @return mixed|string * @throws \NextDom\Exceptions\CoreException * @throws \ReflectionException */ public static function value($_cmd_id) { $cmd = CmdManager::byId(trim(str_replace('#', '', CmdManager::humanReadableToCmd('#' . str_replace('#', '', $_cmd_id) . '#')))); if (!is_object($cmd)) { return ''; } return $cmd->execCmd(); } /** * Obtenir une couleur aléatoire * * @param $rangeLower * @param $rangeHighter * @return string */ public static function randomColor($rangeLower, $rangeHighter) { $value = mt_rand($rangeLower, $rangeHighter); $color_range = 85; $color = new \stdClass(); $color->red = $rangeLower; $color->green = $rangeLower; $color->blue = $rangeLower; if ($value < $color_range * 1) { $color->red += $color_range - $value; $color->green += $value; } elseif ($value < $color_range * 2) { $color->green += $color_range - $value; $color->blue += $value; } elseif ($value < $color_range * 3) { $color->blue += $color_range - $value; $color->red += $value; } $color->red = ($color->red < 0) ? dechex(0) : dechex(round($color->red)); $color->blue = ($color->blue < 0) ? dechex(0) : dechex(round($color->blue)); $color->green = ($color->green < 0) ? dechex(0) : dechex(round($color->green)); $color->red = (strlen($color->red) == 1) ? '0' . $color->red : $color->red; $color->green = (strlen($color->green) == 1) ? '0' . $color->green : $color->green; $color->blue = (strlen($color->blue) == 1) ? '0' . $color->blue : $color->blue; return '#' . $color->red . $color->green . $color->blue; } /** * Arrondir une valeur * * @param mixed $value Valeur à arrondir * @param int $decimal Nombre de décimales * * @return float Valeur arrondie. * @throws \NextDom\Exceptions\CoreException * @throws \ReflectionException */ public static function round($value, $decimal = 0) { $value = self::setTags($value); try { $result = Utils::evaluate($value); if (is_string($result)) { $result = $value; } } catch (\Exception $e) { $result = $value; } if ($decimal == 0) { return ceil(floatval(str_replace(',', '.', $result))); } else { return round(floatval(str_replace(',', '.', $result)), $decimal); } } /** * @TODO:? ??? * * @param $time * @param $value * @return int|string * @throws \Exception */ public static function time_op($time, $value) { $time = self::setTags($time); $value = self::setTags($value); $time = ltrim($time, 0); switch (strlen($time)) { case 1: $date = \DateTime::createFromFormat('Gi', '000' . intval(trim($time))); break; case 2: $date = \DateTime::createFromFormat('Gi', '00' . intval(trim($time))); break; case 3: $date = \DateTime::createFromFormat('Gi', '0' . intval(trim($time))); break; default: $date = \DateTime::createFromFormat('Gi', intval(trim($time))); break; } if ($date === false) { return -1; } if ($value > 0) { $date->add(new \DateInterval('PT' . abs($value) . 'M')); } else { $date->sub(new \DateInterval('PT' . abs($value) . 'M')); } return $date->format('Gi'); } /** * Tester si une date se trouve dans un interval * * @param $time * @param $startInverval * @param $endInterval * * @return int @TODO: 0, 1 * @throws \NextDom\Exceptions\CoreException * @throws \ReflectionException */ public static function time_between($time, $startInverval, $endInterval) { $time = self::setTags($time); $startInverval = self::setTags($startInverval); $endInterval = self::setTags($endInterval); if ($startInverval < $endInterval) { $result = (($time >= $startInverval) && ($time < $endInterval)) ? 1 : 0; } else { $result = (($time >= $startInverval) || ($time < $endInterval)) ? 1 : 0; } return $result; } /** * Obtenir l'interval entre deux dates * * @param string $date1Str Première date au format texte * @param string $date2Str Seconde date au format texte * @param string $intervalFormat Format de l'interval (s : secondes, m : minutes, h : heures, d : jours) * * @return float|int|string * @throws \Exception */ public static function time_diff($date1Str, $date2Str, $intervalFormat = 'd') { $date1 = new \DateTime($date1Str); $date2 = new \DateTime($date2Str); $interval = $date1->diff($date2); if ($intervalFormat == 's') { return intval($interval->format('%s')) + 60 * intval($interval->format('%i')) + 3600 * intval($interval->format('%h')) + 86400 * intval($interval->format('%a')); } if ($intervalFormat == 'm') { return intval($interval->format('%i')) + 60 * intval($interval->format('%h')) + 1440 * intval($interval->format('%a')); } if ($intervalFormat == 'h') { return intval($interval->format('%h')) + 24 * intval($interval->format('%a')); } return $interval->format('%a'); } /** @noinspection PhpOptionalBeforeRequiredParametersInspection */ /** * @TODO: L'heure mais ça à l'air plus compliqué que ça * * @param $value * @return int|mixed|string * @throws \NextDom\Exceptions\CoreException * @throws \ReflectionException */ public static function time($value) { $value = self::setTags($value); try { $result = Utils::evaluate($value); if (is_string($result)) { $result = $value; } } catch (\Exception $e) { $result = $value; } if ($result < 0) { return -1; } if (($result % 100) > 59) { if (strpos($value, '-') !== false) { $result -= 40; } else { $result += 40; } } return $result; } /** * @TODO: Formate l'heure * * @param $time * @return string * @throws \NextDom\Exceptions\CoreException * @throws \ReflectionException */ public static function formatTime($time) { $time = self::setTags($time); if (strlen($time) > 3) { return substr($time, 0, 2) . 'h' . substr($time, 2, 2); } elseif (strlen($time) > 2) { return substr($time, 0, 1) . 'h' . substr($time, 1, 2); } elseif (strlen($time) > 1) { return '00h' . substr($time, 0, 2); } else { return '00h0' . substr($time, 0, 1); } } /** * @TODO: My name is Bond, James Bond * * @param $type * @param $cmdId * @return string * @throws \Exception */ public static function name($type, $cmdId) { $cmd = CmdManager::byId(str_replace('#', '', $cmdId)); if (!is_object($cmd)) { $cmd = CmdManager::byId(trim(str_replace('#', '', CmdManager::humanReadableToCmd('#' . str_replace('#', '', $cmdId) . '#')))); } if (!is_object($cmd)) { return __('Commande non trouvée'); } switch ($type) { case 'cmd': return $cmd->getName(); case 'eqLogic': return $cmd->getEqLogicId()->getName(); case 'object': $linkedObject = $cmd->getEqLogicId()->getObject(); if (!is_object($linkedObject)) { return __('Aucun'); } return $linkedObject->getName(); } return __('Type inconnu'); } /** * @TODO: Créé et exécute un truc * * @param $type * @param $cmd * @param null $options * @return mixed * @throws \Exception */ public static function createAndExec($type, $cmd, $options = null) { $scenarioExpression = new ScenarioExpression(); $scenarioExpression->setType($type); $scenarioExpression->setExpression($cmd); if (is_array($options)) { foreach ($options as $key => $value) { $scenarioExpression->setOptions($key, $value); } } return $scenarioExpression->execute(); } } |