1
0

Merge branch 'master' of git.labolyon.fr:DTux/moha

This commit is contained in:
Daniel Tartavel 2022-07-30 22:08:21 +02:00
commit be7db07714
14 changed files with 182 additions and 66 deletions

View File

@ -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)))
{

View File

@ -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();
}
?>

View File

@ -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()
{
@ -72,6 +76,7 @@ class 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

View File

@ -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,15 +40,20 @@ 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");
$event->published = $now;
}
if ($event->method !== null) $event->device->properties[$event->param]["method"] = $event->method;
if (($event->dateTimeEvent->add($event->recurrenceInterval)) === false)
{
@ -53,7 +61,6 @@ function checkEvents()
}
}
}
}
}elseif (!empty($event->dateTimeEvent) and $event->dateTimeEvent < now())
{
logger(DEBUG, sprintf(_("Sending command set %s => %s to %s"),$event->param, bool2string($event->value), $event->device->friendlyName), __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;
// pb in recurrent event in case of date and not interval
if ($isInterval === true)
{
$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);
$event->ieee_address = $deviceObject->ieeeAddress;
$event->topic = $deviceObject->topic;
$event->device = & $deviceObject;
}
if (!empty($ieeeAddress))
{
$event->ieee_address = $ieeeAddress;
$event->topic = $indexDevices[$deviceObject]->topic;
$event->device = &$indexDevices[$deviceObject];
$event->param = $property;
$event->value = $value;
$event->dateTimeEvent = $event->startDatetime;
}
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)

View File

@ -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();
?>

View File

@ -1,4 +1,6 @@
<?php
require_once "events.php";
class alerte_intrusion extends hook
{
public $hookName = "alerte_intrusion";
@ -27,24 +29,30 @@ class alerte_intrusion extends hook
}
}
public function test()
public function testPortes()
{
global $indexDevices;
logger(DEBUG, _("Function alerte_intrusion->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);
?>

View File

@ -237,7 +237,7 @@ class rdc_store extends hook
}
}
private function send($level)
private function send($level, $method)
{
global $indexDevices;
$deviceObject = $indexDevices[RDC_STORE];

View File

@ -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__);

View File

@ -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);
}

View File

@ -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();
?>

View File

@ -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"))
{

View File

@ -7,6 +7,7 @@ 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();
?>

View File

@ -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;