diff --git a/class/db.php b/class/db.php index 34f7392..28472a9 100644 --- a/class/db.php +++ b/class/db.php @@ -50,7 +50,7 @@ class db extends mysqli { if (!array_key_exists("lastValueLogged", $device->properties[$property])) { - $oldvalue = -1; + $oldValue = -1; }else { $oldValue = $device->properties[$property]["lastValueLogged"]; diff --git a/class/main.php b/class/main.php index 80a6f98..b046e14 100644 --- a/class/main.php +++ b/class/main.php @@ -63,6 +63,8 @@ class ranges class event { + public $id; + public $key; public $ieeeAddress; public $topic; public $param; diff --git a/events.php b/events.php index 0600c9d..c6a63db 100644 --- a/events.php +++ b/events.php @@ -12,38 +12,44 @@ function checkEvents() $oldLevel = $logLevel; //$logLevel = DEBUG; $exception = false; - /*if ($events === null) + if ($events === null) { $events = array(); - }*/ + } + //var_dump($events); $now = now(); - foreach ($events as $key => &$event) + if (!empty($events)) { - - if($event->dateTimeEvent < $now) + foreach ($events as $key => &$event) { - if (is_callable($event->function)) + + if($event->dateTimeEvent < $now) { - logger(DEBUG, _("executing function") . $event->function[1], __FILE__ . ":" . __LINE__); - $event->function($event); - }elseif (is_object($event->device)) - { - 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; - }else - { - logger(ERROR, _("Event is malformed") . $key, __FILE__ . ":" . __LINE__); + logger(DEBUG, _("Executing event") . $key, __FILE__ . ":" . __LINE__); + if (is_callable($event->function)) + { + logger(DEBUG, _("executing function") . $event->function[1], __FILE__ . ":" . __LINE__); + $event->function($event); + }elseif (is_object($event->device)) + { + 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; + }else + { + logger(ERROR, _("Event is malformed") . $key, __FILE__ . ":" . __LINE__); + } + + $event->published = $now; + if (!empty($event->recurrence)) + { + nextOccurence($event, $key); + }else + { + logger(DEBUG, _("Unsetting event") . $key, __FILE__ . ":" . __LINE__); + unset($events[$key]); + } } - - $event->published = $now; - } - if (!empty($event->recurrence)) - { - nextOccurence($event, $key, $now); - }else - { - unset($events[$key]); } } } @@ -125,7 +131,7 @@ function nextDate(&$event) $event->dateTimeEvent->setTime(intval($hour), intval($minutes), intval($seconds)); } -function exceptionsTest(&$event, $now) +function exceptionsTest(&$event, $date) { $exception = false; @@ -146,10 +152,10 @@ function exceptionsTest(&$event, $now) return $exception; } -function nextOccurence(&$event, $eventKey, $now) +function nextOccurence(&$event, $eventKey) { $n = 0; - logger(DEBUG, _("Calculating next occurence"), __FILE__ . ":" . __LINE__); + logger(DEBUG, _("Calculating next occurence of event #") . $event->key, __FILE__ . ":" . __LINE__); do { if ($event->isInterval === true) @@ -164,7 +170,7 @@ function nextOccurence(&$event, $eventKey, $now) logger(ERROR, _("infinite loop"), __FILE__ . ":" . __LINE__); return 1; } - }while (exceptionsTest($event, $now) === true); // loop until the date is not comprise in exceptions dates + }while (exceptionsTest($event, $event->dateTimeEvent) === true); // loop until the date is not comprise in exceptions dates } // datetime format : "yyyy-mm-dd hh:mm:ss" @@ -173,7 +179,8 @@ function setOneshotEvent(device &$deviceObject, string $datetime, $property, $va { global $events; $events[] = new event; - $key = key($events); + $key = array_key_last($events); + $events[$key]->key = $key; $events[$key]->dateTimeEvent = new dateTime($datetime); $events[$key]->ieeeAddress = $deviceObject->ieeeAddress; $events[$key]->topic = $deviceObject->topic; @@ -186,30 +193,41 @@ function setOneshotEvent(device &$deviceObject, string $datetime, $property, $va // startDatetime and stopDatetime format : "yyyy-mm-dd hh:mm:ss" -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) +function setRecurrentEvent(string $id, $function, string $ieeeAddress, string $property, $value, int $method=0 , string $startDatetime, string $stopDatetime, bool $isInterval, int $hours=0, int $minutes=0, int $seconds=0, int $days=0, int $weeks=0, int $months=0, int $years=0) { global $events, $indexDevices; + $string =""; + $stringTemp = ""; + logger(INFO, _("Setting recurrent event"), __FILE__ . ":" . __LINE__); - $string = "P"; - if (!empty($years)) $string .= $years . "Y"; - if (!empty($months)) $string .= $months . "M"; - if (!empty($week)) $string .= $week . "W"; - if (!empty($days)) $string .= $days . "D"; - $string .= "T"; - if (!empty($hours)) $string .= $hours . "H"; - if (!empty($minutes)) $string .= $minutes . "M"; - if (!empty($seconds)) $string .= $seconds . "S"; + if (!empty($years)) $stringTemp .= $years . "Y"; + if (!empty($months)) $stringTemp .= $months . "M"; + if (!empty($week)) $stringTemp .= $week . "W"; + if (!empty($days)) $stringTemp .= $days . "D"; + if (!empty($stringTemp)) $string = "P" . $stringTemp; + $stringTemp = ""; + if (!empty($hours)) $stringTemp .= $hours . "H"; + if (!empty($minutes)) $stringTemp .= $minutes . "M"; + if (!empty($seconds)) $stringTemp .= $seconds . "S"; + if (!empty($stringTemp)) $string .= "T" . $stringTemp; + logger(DEBUG, _("reccurrent event string : ") . $string, __FILE__ . ":" . __LINE__); - + $key = searchEventByID($id); + if($key !== false) + { + deleteEvent($key); + } $event = new event; + + $event->id = $id; // pb in recurrent event in case of date and not interval if ($isInterval === true) { if (($event->dateTimeEvent->add($event->recurrence)) === false) { - logger(ERROR, _("Error in event recurrence. event: ") . $key, __FILE__ . ":" . __LINE__); + logger(ERROR, _("Error in event recurrence. event: ") . $id , __FILE__ . ":" . __LINE__); return true; } $event->recurrence = new DateInterval($string); @@ -226,14 +244,16 @@ function setRecurrentEvent($function, $ieeeAddress, string $property, $value, bo }else { $event->startDatetime = now(); + logger(DEBUG, _("Datetime is ") . $event->startDatetime->format("Y-m-d H:i:s"), __FILE__ . ":" . __LINE__); } if (!empty($stopDatetime)) { - $event->stopDatetime = new datetime($stopDatetime); + $event->stopDatetime = new datetime($stopDatetime); } $event->dateTimeEvent = $event->startDatetime; + if (!empty($ieeeAddress)) { $event->ieee_address = $ieeeAddress; @@ -245,10 +265,14 @@ function setRecurrentEvent($function, $ieeeAddress, string $property, $value, bo if ($method !== null) $event->method = $method; $events[] = $event; - return false; + $r = key($events); + $events[$r]->key = $r; + $events[$r]->dateTimeEvent = nextOccurence($events[$r], $r); + + return $r; } -function setDelay(device &$deviceObject, float $delay, string $unit, string $property, $value, $function, bool $replace=false, int $method = null) +function setDelay(device &$deviceObject, float $delay, string $unit, string $property, $value, $function, bool $replace=false, int $method=null) { global $events, $logLevel; $oldLevel = $logLevel; @@ -336,6 +360,20 @@ function searchEvent(device $deviceObject, string $property, $value, $function=n return false; } +function searchEventByID($id) +{ + global $events; + logger(DEBUG, sprintf(_("searching event by ID %s"), $id), __FILE__ . ":" . __LINE__); + foreach($events as $key => $event) + { + if ($event->id == $id) + { + return $key; + } + } + return false; +} + // warning delete event does not manage method of the device (IDLE, ) function deleteEvent(int $eventKey) { diff --git a/hooks/scripts/rdc_portes_ouvertes.php b/hooks/scripts/rdc_portes_ouvertes.php index a85c525..0fc5a49 100644 --- a/hooks/scripts/rdc_portes_ouvertes.php +++ b/hooks/scripts/rdc_portes_ouvertes.php @@ -29,16 +29,16 @@ class alerte_intrusion extends hook switch($property) { case "contact": - if ($value == false) + if (isPresent() === false) { - logger(ALERT, sprintf(_("%s vient de s'ouvrir alors que personne n'est présent"), $device->friendlyName), __FILE__ . ":" . __LINE__); - }else - { - logger(ALERT, sprintf(_("%s vient de se fermer alors que personne n'est présent"), $device->friendlyName), __FILE__ . ":" . __LINE__); + if ($value == false and isPresent() === false) + { + logger(ALERT, sprintf(_("%s vient de s'ouvrir alors que personne n'est présent"), $device->friendlyName), __FILE__ . ":" . __LINE__); + }else + { + logger(ALERT, sprintf(_("%s vient de se fermer alors que personne n'est présent"), $device->friendlyName), __FILE__ . ":" . __LINE__); + } } - - - break; } } @@ -87,6 +87,6 @@ class alerte_intrusion extends hook $hooks["alerte_intrusion"] = new alerte_intrusion(); logger(DEBUG, _("Initializing event"), __FILE__ . ":" . __LINE__); $function = array($hooks["alerte_intrusion"], "testPortes"); -setRecurrentEvent($function, 0, 0, 0, false, 0, 0, 21, 0, 0, 0, 0, 0, 0); +//setRecurrentEvent("alerte_intrusion", $function, "", "", 0, -1, "", "", false, 21); ?> diff --git a/hooks/scripts/rdc_salon_eclairage.php b/hooks/scripts/rdc_salon_eclairage.php index 927bac5..15bf641 100644 --- a/hooks/scripts/rdc_salon_eclairage.php +++ b/hooks/scripts/rdc_salon_eclairage.php @@ -10,11 +10,13 @@ class rdc_salon_eclairage extends hook RDC_SALON_MVMT2 => "occupancy", RDC_ENTREE_PORTE => "contact", RDC_SALON_LUMINOSITE => "illuminance_lux", - RDC_SALON_ECLAIRAGE_PANNEAU => "state" + RDC_SALON_ECLAIRAGE_PANNEAU => "state", + RDC_SALON_PRESENCE => "presence" ); protected $actionneurs = array( array(RDC_SALON_MVMT, "occupancy", 1), - array(RDC_SALON_MVMT2, "occupancy", 1) + array(RDC_SALON_MVMT2, "occupancy", 1), + array(RDC_SALON_PRESENCE => "presence", 1) ); public $delay = 3; // amount of time in $timeunit public $timeUnit = "minute"; // unit of time for delay, second, minute, hour, day, week, month, year @@ -41,6 +43,8 @@ class rdc_salon_eclairage extends hook logger (INFO, _("property => ") . $param . _("value =>") . bool2string($value), __FILE__ . ":" . __LINE__); switch($param) { + case "presence": + logger(INFO, _("CASE: Présence => ") . bool2string($value), __FILE__ . ":" . __LINE__); case "occupancy": $method = $deviceTarget->properties["state"]["method"]; logger(INFO, _("CASE: Occupancy => ") . bool2string($value), __FILE__ . ":" . __LINE__); @@ -57,7 +61,8 @@ class rdc_salon_eclairage extends hook }else { logger(INFO, _("Value is OFF"), __FILE__ . ":" . __LINE__); - if ((getValue(RDC_SALON_MVMT, "occupancy") == OFF) and (getValue(RDC_SALON_MVMT2, "occupancy") == OFF) and $method == AUTO) + if (testActionneurs($this->actionneurs) and $method = AUTO) + //if ((getValue(RDC_SALON_MVMT, "occupancy") == OFF) and (getValue(RDC_SALON_MVMT2, "occupancy") == OFF) and $method == AUTO) { logger(INFO, _("Setting to OFF"), __FILE__ . ":" . __LINE__); $this->send($deviceTarget, "OFF", false, IDLE); @@ -65,6 +70,7 @@ class rdc_salon_eclairage extends hook } } break; + case "contact": $method = $deviceTarget->properties["state"]["method"]; logger(INFO, _("CASE: Contact Door"), __FILE__ . ":" . __LINE__); @@ -78,6 +84,7 @@ class rdc_salon_eclairage extends hook } } break; + case "illuminance_lux": logger(INFO, _("CASE : Illuminance"), __FILE__ . ":" . __LINE__); if ($value >= $this->luminance_max and $deviceTarget->properties["state"]["value"] == "ON") @@ -87,6 +94,7 @@ class rdc_salon_eclairage extends hook removeEvent($deviceTarget, "state", "OFF"); } break; + case "state": logger(INFO, _("CASE : State"), __FILE__ . ":" . __LINE__); $method = $deviceTarget->properties["state"]["method"]; diff --git a/hooks/scripts/rdc_temperature_int_ext.php b/hooks/scripts/rdc_temperature_int_ext.php index c132601..39e7dac 100644 --- a/hooks/scripts/rdc_temperature_int_ext.php +++ b/hooks/scripts/rdc_temperature_int_ext.php @@ -2,7 +2,7 @@ // script to prevent when exterior temperature become inferior or superior to interior one class rdc_temperature_int_ext extends hook { - public $hookName = "rdc_wc_eclairage"; + public $hookName = "rdc_temperature_int_ext"; public $active = true; //enable/disable hook (true => enabled) public $tempSup = 25; public $tempInf = 20; @@ -12,6 +12,13 @@ class rdc_temperature_int_ext extends hook METEO=> "tempc", ); + protected $portesList = array( + ENTREE_PORTE => "contact", + //GARAGE_PORTE => "contact", + RDC_CHAMBRE_BAIE => "contact", + RDC_SALON_BAIE => "contact" + ); + function installHooks(&$indexDevices) { return $this->installHooksFunction($indexDevices); @@ -26,51 +33,60 @@ class rdc_temperature_int_ext extends hook $status = -1; $msg = ""; + logger(DEBUG, _("rdc_temperature_int_ext hook"), null ,$device); + if (empty($time)) $time = now(); - $indoorTemp = $device->properties["indoortempc"]["value"]; + //echo "Time is " . var_dump($time) . EOL; + //echo "minutes since time :" . now()->format("U") - $time->format("U"); + if ((now()->format("U") - $time->format("U")) > 300) + { + + $indoorTemp = $device->properties["indoortempc"]["value"]; - if ( $value > $indoorTemp) - { - if( ($indoorTemp <= $this->tempSup) and empty($portes)) + if ( $value > $indoorTemp) { - $status = 1; - //logger(ALERT, _("Open doors to climate"), null ,$device); - }elseif($indoorTemp >= $this -> tempSup and ! empty($portes)) - { - $status = 0; - //logger(ALERT, _("Close doors to climate"), null, $device); - } - }elseif ( $value < $indoorTemp ) - { - if (($indoorTemp >= $this->tempSup) and empty($portes) ) - { - $status = 1; - //logger(ALERT, _("Open doors to climate"), null ,$device); - }elseif ($indoorTemp <= $this->tempSup) - { - $status = 0; - //logger(ALERT, _("Close doors to climate"), null, $device); - } - logger (INFO, sprintf(_("%s: notification received from MQTT from %s => parameter: %s value: %s"), $this->hookName, $device->friendlyName, $property, bool2string($value)), __FILE__ . ":" . __LINE__, $device); - } - $portes = $hooks["alerte_intrusion"]->testPortes(false, true); - if ($status == 1) - { - if (empty($portes) and ($time->diff(now())->format("i")) > 5) - { - logger(ALERT, _("Open doors to climate"), null, $device); - $time = now(); - } - }else - { - //$portes = $hooks["alerte_intrusion"]->testPortes(false, true); - if (!empty($portes) and ($time.diff(now()).format("i") > 5)) - { - $time = now(); - foreach($portes as $porte) + if( ($indoorTemp <= $this->tempSup) and empty($portes)) { - $msg .= $porte . "\n"; + $status = 1; + //logger(ALERT, _("Open doors to climate"), null ,$device); + }elseif($indoorTemp >= $this -> tempSup and ! empty($portes)) + { + $status = 0; + //logger(ALERT, _("Close doors to climate"), null, $device); + } + }elseif ( $value < $indoorTemp ) + { + if (($indoorTemp >= $this->tempSup) and empty($portes) ) + { + $status = 1; + //logger(ALERT, _("Open doors to climate"), null ,$device); + }elseif ($indoorTemp <= $this->tempSup) + { + $status = 0; + //logger(ALERT, _("Close doors to climate"), null, $device); + } + logger (INFO, sprintf(_("%s: notification received from MQTT from %s => parameter: %s value: %s"), $this->hookName, $device->friendlyName, $property, bool2string($value)), __FILE__ . ":" . __LINE__, $device); + } + $portes = $hooks["alerte_intrusion"]->testPortes($this->portesList, false, true); + print_r($portes); + if ($status == 1) + { + if (empty($portes)) + { + logger(ALERT, _("Open doors to climate"), null, $device); + $time = now(); + } + }else + { + //$portes = $hooks["alerte_intrusion"]->testPortes(false, true); + if (!empty($portes)) + { + $time = now(); + foreach($portes as $porte) + { + $msg .= $porte . "\n"; + } logger(ALERT, _("Close doors to climate\n") . $msg, null, $device); } } diff --git a/moha.php b/moha.php index af21d96..4401bec 100644 --- a/moha.php +++ b/moha.php @@ -38,7 +38,8 @@ $curlErr = 0; // Number of errors returned by curl $configDir = "./config"; // default config dir (production value is /etc/moha/) $hooksInitialized = 0; // are all hooks initialized ? false/true $flagHooks = false; -$devicesRequest = false; //say to true when publishing device request to zigbee2mqtt +$devicesRequest = false; // set to true when publishing device request to zigbee2mqtt +$presence = array(); // name and status of presence if ($testMode) { @@ -60,6 +61,7 @@ if ($testMode) if (!init()) exit(1); + // gettext bindtextdomain("moha", "./locale"); textdomain("moha"); @@ -207,8 +209,11 @@ require $configDir . "/properties2log.php"; require "mqtt_functions.php"; require "events.php"; require "db_functions.php"; +require "config/liste_telephones.php"; +require "presence.php"; require "apiserver/apiserver.php"; + logger(DEBUG, _("Loading stored events datas from ") . $dataPath . "events.db", __FILE__ . ":" . __LINE__); if (file_exists($dataPath . "events.db")) { @@ -362,6 +367,7 @@ while (true) checkEvents(); checkTopicsAvailability(); if ($apiServerIsActive) apiServer($read); + //presence(); } endMoha(); diff --git a/tools/install.sh b/tools/install.sh index 0d801fd..963804c 100755 --- a/tools/install.sh +++ b/tools/install.sh @@ -5,3 +5,6 @@ chown domotique:domotique -R /etc/moha rsync -aP --exclude "*~" --exclude *kate-swp $1/webserver/ /var/www/html/moha/ chmod u+rX -R /var/www/html/moha/ chown apache:apache -R /var/www/html/moha +rsync -aP --exclude "*~" --exclude *kate-swp $1/daemons/ /usr/bin/ +rsync -aP --exclude "*~" --exclude *kate-swp $1/systemd/ /etc/systemd/system/ +#must enable service