From 555abb7c88be67244298833e459aede83219acdd Mon Sep 17 00:00:00 2001 From: Daniel Tartavel Date: Sun, 10 Jul 2022 19:33:19 +0200 Subject: [PATCH] adding command test in apiserver\nsome debugging\nfree sms now running fine --- apiserver/apiserver.php | 4 + apiserver/cmd_functions.php | 9 +++ class/main.php | 7 +- config/{events.php => eventsConfig.php} | 0 events.php | 88 +++++++++++++++------- hooks/notifiers/notificationfreemobile.php | 44 +++++++---- hooks/scripts/rdc_portes_ouvertes.php | 14 +++- hooks/scripts/rdc_store.php | 2 +- hooks/scripts/rdc_wc_eclairage.php | 8 +- moha.php | 37 +++++---- topics_callbacks/linky2mqtt.php | 3 + topics_callbacks/pws2mqtt.php | 5 +- topics_callbacks/zigbee2mqtt.php | 6 +- utils.php | 21 ++++++ 14 files changed, 182 insertions(+), 66 deletions(-) rename config/{events.php => eventsConfig.php} (100%) diff --git a/apiserver/apiserver.php b/apiserver/apiserver.php index 65025bb..1baf94c 100644 --- a/apiserver/apiserver.php +++ b/apiserver/apiserver.php @@ -143,6 +143,10 @@ function apiServer($read) logger(DEBUG, $command . _(" reached"), __FILE__ . ":" . __LINE__); htmlSend($spawn, deleteDevice($argList)); break; + case "test": + logger(DEBUG, $command . _(" reached"), __FILE__ . ":" . __LINE__); + htmlSend($spawn, test($argList)); + break; default: if (is_numeric(array_key_first($argList))) { diff --git a/apiserver/cmd_functions.php b/apiserver/cmd_functions.php index ad51782..bb1ed46 100644 --- a/apiserver/cmd_functions.php +++ b/apiserver/cmd_functions.php @@ -559,4 +559,13 @@ function apiDisplayByType($argList) } } */ + +function test() +{ + global $hooks; + logger(DEBUG, _("Testing doors") , __FILE__ . ":" . __LINE__); + echo "testing doors"; + return $hooks["alerte_intrusion"]->testPortes(); +} + ?> diff --git a/class/main.php b/class/main.php index 4b2ed4e..750d5e5 100644 --- a/class/main.php +++ b/class/main.php @@ -18,6 +18,9 @@ class topic { public $config; public $callback; public $getOnStart = false; + public $lastSeen; + public $timeOut = 5; + public $notificationSent = false; } class device @@ -33,6 +36,7 @@ class device public $toConfirm; public $triggerDevice; public $properties = array(); + public $lastSeen; public function __construct() { @@ -69,9 +73,10 @@ class event public $dateTimeEvent; // datetime : next occurence for recurrent event public $startDatetime; public $stopDatetime; - public $recurrenceInterval; // interval : for recurrent event + public $recurrenceInterval; // interval : for recurrent event public $exceptionInterval; // array of object ranges public $method; // cf: constants.php (IDLE, AUTO, MANUAL) + public $isInterval; // 0 => recurence by date 1 => by interval } class watch diff --git a/config/events.php b/config/eventsConfig.php similarity index 100% rename from config/events.php rename to config/eventsConfig.php diff --git a/events.php b/events.php index 29f92a6..45c9e17 100644 --- a/events.php +++ b/events.php @@ -7,13 +7,15 @@ logger(DEBUG, _("Including events.php"), __FILE__ . ":" . __LINE__); function checkEvents() { global $logLevel, $events; + logger(DEBUG, _("Checking events"), __FILE__ . ":" . __LINE__); + $oldLevel = $logLevel; //$logLevel = DEBUG; $exception = false; - if ($events === null) + /*if ($events === null) { $events = array(); - } + }*/ foreach ($events as $key => &$event) { $now = now(); @@ -23,7 +25,8 @@ function checkEvents() if($event->dateTimeEvent < $now) { logger(DEBUG, _("Event must be executed"), __FILE__ . ":" . __LINE__); - if (!empty($event->exceptionInterval)) + + if (!empty($event->exceptionInterval) and $event->isInterval == true) { logger(DEBUG, _("Testing exceptions"), __FILE__ . ":" . __LINE__); foreach($event->exceptionInterval as $key => $value) @@ -37,20 +40,24 @@ function checkEvents() } } } + if ($exception === false) { - if (is_callable($this->function)) + if (is_callable($event->function)) { - $this->function($event); + logger(DEBUG, _("executing function") . $event->function[1], __FILE__ . ":" . __LINE__); + $event->function(); + $event->published = $now; }else { logger(DEBUG, sprintf(_("sending command set %s => %s for %s"), $event->param ,bool2string($event->value), $event->device->friendlyName), __FILE__ . ":" . __LINE__); publish(mktopic($event->device), array($event->param => $event->value), "set"); - if ($event->method !== null) $event->device->properties[$event->param]["method"] = $event->method; - if (($event->dateTimeEvent->add($event->recurrenceInterval)) === false) - { - logger(ERROR, _("Error in adding interval to event recurrence. event: ") . $key, __FILE__ . ":" . __LINE__); - } + $event->published = $now; + } + if ($event->method !== null) $event->device->properties[$event->param]["method"] = $event->method; + if (($event->dateTimeEvent->add($event->recurrenceInterval)) === false) + { + logger(ERROR, _("Error in adding interval to event recurrence. event: ") . $key, __FILE__ . ":" . __LINE__); } } } @@ -89,9 +96,11 @@ function setOneshotEvent(device &$deviceObject, string $datetime, $property, $va // startDatetime and stopDatetime format : "yyyy-mm-dd hh:mm:ss" -function setRecurrentEvent(device &$deviceObject, string $property, $value, string $startDatetime, string $stopDatetime, int $hours, int $minutes, int $seconds, int $days, int $weeks, int $months, int $years, int $method = null) +function setRecurrentEvent($function, $ieeeAddress, string $property, $value, bool $isInterval, string $startDatetime, string $stopDatetime, int $hours, int $minutes, int $seconds, int $days, int $weeks, int $months, int $years, int $method = null) { - global $events; + global $events, $indexDevices; + logger(INFO, _("Setting recurrent event"), __FILE__ . ":" . __LINE__); + $string = "P"; if (!empty($years)) $string .= $years . "Y"; if (!empty($months)) $string .= $months . "M"; @@ -101,24 +110,51 @@ function setRecurrentEvent(device &$deviceObject, string $property, $value, stri if (!empty($hours)) $string .= $hours . "H"; if (!empty($months)) $string .= $months . "M"; if (!empty($seconds)) $string .= $seconds . "S"; - + logger(DEBUG, _("reccurrent event string : ") . $string, __FILE__ . ":" . __LINE__); + + $event = new event; - - $event->recurrenceInterval = new DateInterval($string); - $event->startDatetime = new datetime($startDatetime); - $event->stopDatetime = new datetime($stopDatetime); - $event->ieee_address = $deviceObject->ieeeAddress; - $event->topic = $deviceObject->topic; - $event->device = & $deviceObject; - $event->param = $property; - $event->value = $value; - $event->dateTimeEvent = $event->startDatetime; - if (($event->dateTimeEvent->add($event->recurrenceInterval)) === false) + // pb in recurrent event in case of date and not interval + if ($isInterval === true) { - logger(ERROR, _("Error in event recurrence. event: ") . $key, __FILE__ . ":" . __LINE__); - + $event->recurrenceInterval = new DateInterval($string); + }else + { + $event->recurrenceInterval = 0; + } + + if (!empty($startDatetime)) + { + $event->startDatetime = new datetime($startDatetime); + }else + { + $event->startDatetime = now(); + } + $event->dateTimeEvent = $event->startDatetime; + + if (!empty($stopDatetime)) + { + $event->stopDatetime = new datetime($stopDatetime); + } + if (!empty($ieeeAddress)) + { + $event->ieee_address = $ieeeAddress; + $event->topic = $indexDevices[$deviceObject]->topic; + $event->device = &$indexDevices[$deviceObject]; + $event->param = $property; + $event->value = $value; + } + + if ($event->recurrenceInterval != 0) + { + if (($event->dateTimeEvent->add($event->recurrenceInterval)) === false) + { + logger(ERROR, _("Error in event recurrence. event: ") . $key, __FILE__ . ":" . __LINE__); + return 1; + } } if ($method !== null) $event->method = $method; + return 0; } function setDelay(device &$deviceObject, float $delay, string $unit, string $property, $value, bool $replace=false, int $method = null) diff --git a/hooks/notifiers/notificationfreemobile.php b/hooks/notifiers/notificationfreemobile.php index 58e6fb8..bbae5e6 100644 --- a/hooks/notifiers/notificationfreemobile.php +++ b/hooks/notifiers/notificationfreemobile.php @@ -5,8 +5,11 @@ class notificationFreemobile private $name = "freemobile"; public $active = true; public $level; - private $dest = array( - "daniel" => "32886706&pass=JTGUY6l5OG73zX", + public $curlErr; + public $lastTry; + public $lastTryTimeout = 5; + protected $dest = array( + "daniel" => "15480189&pass=yVpPmCWmUl2HGp", ); function __construct() @@ -16,37 +19,50 @@ class notificationFreemobile function send($message, $destinataire=NOTIF_DEFAULT_DEST) { - global $curlErr; - $result = false; + $error = false; if ($this->active === true) { $ch = curl_init(); // set url curl_setopt($ch, CURLOPT_URL, $this->url . $this->dest[$destinataire] . "&msg=" . urlencode(trim($message))); - echo $this->url . urlencode(trim($message)) . EOL; + //return the transfer as a string //curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); // $result contains the output string - if ($curlErr <= 10) + if ($this->curlErr <= 5) { - $result = curl_exec($ch); - if ($result === false) + logger(DEBUG, _("Curl sending message"), false, __FILE__ . ":" . __LINE__); + echo $this->url . urlencode(trim($message)) . EOL; + curl_exec($ch); + if (curl_errno($ch) != 0) { - $curlErr += 1; + $this->curlErr += 1; + $this->lastTry = time(); logger(ERROR, sprintf( _("Curl return error %d: %s when sending notification"), curl_errno($ch), curl_error($ch)), false, __FILE__ . ":" . __LINE__); + $error = true; }else { - logger(DEBUG, sprintf(_("Curl return: %s when sending notification"), $result), false); + logger(DEBUG, sprintf(_("Curl return: %s when sending notification"), $result), false, __FILE__ . ":" . __LINE__); + $this->curlErr = 0; } - } //TODO managing curl errors + }else + { + if ((time() - $this->lastTry) > ($this->lastTryTimeout*60)) + { + $this->curlErr -= 1; + } + $error = true; + } + + + //TODO managing curl errors // close curl resource to free up system resources curl_close($ch); - return true; + } - return false; + return $error; } } $notificationMethods["freemobile"] = new notificationFreemobile(); - ?> diff --git a/hooks/scripts/rdc_portes_ouvertes.php b/hooks/scripts/rdc_portes_ouvertes.php index 480fad3..71b1fb5 100644 --- a/hooks/scripts/rdc_portes_ouvertes.php +++ b/hooks/scripts/rdc_portes_ouvertes.php @@ -1,4 +1,6 @@ testPorte"), __FILE__ . ":" . __LINE__); + $msg = ""; foreach ($this->devicelist as $device => $property) { if($indexDevices[$device]->properties[$property] != false) { - $msg .= $indexDevices->friendlyName . " is open" . EOL; + $msg .= $indexDevices[$device]->friendlyName . " is open" . EOL; } } - if ($msg != "") + if (!empty($msg)) { logger(ALERT, $msg, __FILE__ . ":" . __LINE__); } + return nl2br($msg); } } $hooks["alerte_intrusion"] = new alerte_intrusion(); +logger(DEBUG, _("Initializing event"), __FILE__ . ":" . __LINE__); +$function = array($hooks["alerte_intrusion"], "testPortes"); +setRecurrentEvent($function, 0, 0, 0, 0, 0, 0, 21, 0, 0, 1, 0, 0, 0); ?> diff --git a/hooks/scripts/rdc_store.php b/hooks/scripts/rdc_store.php index d3d6347..a173ba1 100644 --- a/hooks/scripts/rdc_store.php +++ b/hooks/scripts/rdc_store.php @@ -237,7 +237,7 @@ class rdc_store extends hook } } - private function send($level) + private function send($level, $method) { global $indexDevices; $deviceObject = $indexDevices[RDC_STORE]; diff --git a/hooks/scripts/rdc_wc_eclairage.php b/hooks/scripts/rdc_wc_eclairage.php index 1125ede..dbd0d1b 100644 --- a/hooks/scripts/rdc_wc_eclairage.php +++ b/hooks/scripts/rdc_wc_eclairage.php @@ -31,16 +31,16 @@ class rdc_wc_eclairage extends hook if ($targetDevice->properties["state_l2"]["method"] == IDLE) { $targetDevice->properties["state_l2"]["method"] = MANUAL; - setDelay($device, $this->delayManual, $this->timeUnit, "state_l2", "OFF", true); + setDelay($targetDevice, $this->delayManual, $this->timeUnit, "state_l2", "OFF", true); } }elseif ($value == "OFF") { $targetDevice->properties["state_l2"]["method"] = IDLE; - removeEvent($device, "state_l2", "OFF"); + removeEvent($targetDevice, "state_l2", "OFF"); } break; case "occupancy": - logger(DEBUG, "CASE: occupancy", __FILE__ . ":" . __LINE__); + logger(DEBUG, "CASE: WC occupancy", __FILE__ . ":" . __LINE__); logger(DEBUG, "method =" . $targetDevice->properties["state_l2"]["method"], __FILE__ . ":" . __LINE__); if ($value === true and $targetDevice->properties["state_l2"]["method"] == IDLE) { @@ -50,7 +50,7 @@ class rdc_wc_eclairage extends hook { //$targetDevice->properties["state_l2"]["method"] = IDLE; //$this->send($targetDevice, "OFF"); - setDelay($device, $this->delay, $this->timeUnit, "state_l2", "OFF", true, IDLE); + setDelay($targetDevice, $this->delay, $this->timeUnit, "state_l2", "OFF", true, IDLE); } } logger (INFO, sprintf(_("%s: notification received from MQTT from %s => parameter: %s value: %s"), $this->hookName, $device->friendlyName, $property, bool2string($value)), __FILE__ . ":" . __LINE__); diff --git a/moha.php b/moha.php index 20b3b59..c782551 100644 --- a/moha.php +++ b/moha.php @@ -50,7 +50,7 @@ if ($testMode) $httpServerIp = "192.168.1.253"; }else { - $logLevel = INFO | NOTICE | WARNING | ERROR | ALERT; + $logLevel = DEBUG | INFO | NOTICE | WARNING | ERROR | ALERT; $mqttServerIp = "127.0.0.1"; // IP address of mqttserver in production mode $dataPath = "/usr/share/moha/"; $logFile = "/var/log/moha.log"; // Path of log file @@ -64,13 +64,13 @@ if (!init()) exit(1); bindtextdomain("moha", "./locale"); textdomain("moha"); -function notify($message) +function notify($message, $destinataire=NOTIF_DEFAULT_DEST) { global $notificationMethods; $result = false; foreach($notificationMethods as $value) { - $result = $result | $value->send($message); + $result = $result | $value->send($message, $destinataire); } return $result; } @@ -95,8 +95,10 @@ function logger($level, $log, $pos = "", $notif = true) if(notify("Moha\n" . $logString) === false) { logger(INFO, _("Notification not sent"), __FILE__ . ":" . __LINE__, false); + return true; } } + return false; } function init() @@ -200,6 +202,18 @@ require "events.php"; require "db_functions.php"; require "apiserver/apiserver.php"; +logger(DEBUG, _("Loading stored events datas from ") . $dataPath . "events.db", __FILE__ . ":" . __LINE__); +if (file_exists($dataPath . "events.db")) +{ + if (($db = loadDB($dataPath . "events.db")) === false) + { + logger(ERROR, _("Can not load events db"), __FILE__ . ":" . __LINE__); + }else + { + $events = $db; + } + +} // topics definition listHooks("./topics_callbacks", $topicsCallbacks); if (!empty($topicsCallbacks)) @@ -236,6 +250,11 @@ if (file_exists($dataPath . "topics.db")) }else { $topics = $db; + foreach($topics as $topicName => $topic ) + { + $topic->notificationSent = false; + logger(DEBUG, "topic: " . $topicName . " is " . bool2string($topic->notificationSent)); + } } } @@ -253,18 +272,7 @@ if (file_exists($dataPath . "devices.db")) } } -logger(DEBUG, _("Loading stored events datas from ") . $dataPath . "events.db", __FILE__ . ":" . __LINE__); -if (file_exists($dataPath . "events.db")) -{ - if (($db = loadDB($dataPath . "events.db")) === false) - { - logger(ERROR, _("Can not load events db"), __FILE__ . ":" . __LINE__); - }else - { - $events = $db; - } -} // Program start logger(DEBUG, _("Program start"), __FILE__ . ":" . __LINE__, false); @@ -338,6 +346,7 @@ while (true) //logger(DEBUG, _("looping"), __FILE__ . ":" . __LINE__); } checkEvents(); + checkTopicsAvailability(); if ($apiServerIsActive) apiServer($read); } diff --git a/topics_callbacks/linky2mqtt.php b/topics_callbacks/linky2mqtt.php index 6926001..614a9d6 100644 --- a/topics_callbacks/linky2mqtt.php +++ b/topics_callbacks/linky2mqtt.php @@ -8,6 +8,7 @@ function linky2mqttCallback($topic, $message) { global $topics, $logFh, $devices, $included; $topicName = $topic[0]; + $topics[$topicName]->lastSeen = time(); $friendlyName = $topic[1]; // get friendlyName logger(INFO, sprintf(_("Incoming notification of device %s"), $topicName, $fn), __FILE__ . ":" . __LINE__); $payloadArray = json_decode($message->payload, true); @@ -36,4 +37,6 @@ function linky2mqttCallback($topic, $message) //print_r($device["device"]); } $topics["linky2mqtt"]->callback = "linky2mqttCallback"; +$topics["linky2mqtt"]->timeOut = 3; // timeOut in minutes +$topics["linky2mqtt"]->lastSeen = time(); ?> diff --git a/topics_callbacks/pws2mqtt.php b/topics_callbacks/pws2mqtt.php index 216c97e..ab5ba94 100644 --- a/topics_callbacks/pws2mqtt.php +++ b/topics_callbacks/pws2mqtt.php @@ -4,7 +4,7 @@ if (!array_key_exists("pws2mqtt", $devices)) $devices["pws2mqtt"] = array(); function pws2mqttCallback($topic, $message) { - global $logFh, $devices, $included; + global $logFh, $devices, $included, $topics; $topicName = $topic[0]; $fn = $topic[1]; logger(INFO, sprintf(_("Incoming notification of device %s => friendly name : %s"), $topicName, $fn), __FILE__ . ":" . __LINE__); @@ -30,6 +30,7 @@ function pws2mqttCallback($topic, $message) { $device = &$device[$fn]; } + $topics[$topicName]->lastSeen = time(); unset($payloadArray["friendly_name"]); unset($payloadArray["ieeeAddress"]); unset($payloadArray["type"]); @@ -60,6 +61,8 @@ function pws2mqttCallback($topic, $message) } }; $topics["pws2mqtt"]->callback = "pws2mqttCallback"; +$topics["pws2mqtt"]->timeOut = 3; //timeOut in minutes +$topics["pws2mqtt"]->lastSeen = time(); if (!is_callable("pws2mqttGetList")) { diff --git a/topics_callbacks/zigbee2mqtt.php b/topics_callbacks/zigbee2mqtt.php index 64bd0be..3bccb2e 100644 --- a/topics_callbacks/zigbee2mqtt.php +++ b/topics_callbacks/zigbee2mqtt.php @@ -6,7 +6,8 @@ if (!array_key_exists("zigbee2mqtt", $devices)) $devices["zigbee2mqtt"] = array function zigbee2mqttCallback($topic, $message) { global $topics, $devices, $included, $logFh, $indexFriendlyNames, $devicesRequest; - + + $topics[$topic[0]]->lastSeen = time(); if ($topic[1] == "bridge") { switch ($topic[2]) @@ -117,5 +118,6 @@ function zigbee2mqttCallback($topic, $message) }; $topics["zigbee2mqtt"]->callback = "zigbee2mqttCallback"; - +$topics["zigbee2mqtt"]->timeOut = 3; +$topics["zigbee2mqtt"]->lastSeen = time(); ?> diff --git a/utils.php b/utils.php index 4177a0b..e6305a4 100644 --- a/utils.php +++ b/utils.php @@ -16,6 +16,27 @@ print ("MOHA-" . $logString . EOL); } }*/ + +function checkTopicsAvailability() +{ + global$topics; + foreach($topics as $topicName => $topic) + { + if ($topic->status == 1) + { + logger(DEBUG, "time is " . time() . " lastSeen is " . $topic->lastSeen, __FILE__ . ":" . __LINE__ ); + + if ((time() - $topic->lastSeen > $topic->timeOut*60) and ($topic->notificationSent == false)) + { + if (logger(ALERT, $topicName . _(" is not available"), __FILE__ . ":" . __LINE__) == false); + { + $topic->notificationSent = true; + } + } + } + } +} + function testActionneurs(array $actionneurs) { global $indexDevices;