1
0

- lots of debugging

- beginning to add graphical stats
- beginning to add device by type
- added a dashboard "etage"
- begining to add notification to multiple recipients in freemobile hook
This commit is contained in:
daniel Tartavel 2022-03-28 00:40:34 +02:00
parent 80234fc505
commit 0d35b1ff3f
24 changed files with 491 additions and 205 deletions

View File

@ -47,7 +47,7 @@ class db extends mysqli
$ieeeAddress = $device->ieeeAddress; $ieeeAddress = $device->ieeeAddress;
//print_r($ieeeAddress); //print_r($ieeeAddress);
$query = "INSERT INTO logs (device, property, value) VALUES('" . $this->protect($ieeeAddress) . "', '" . $this->protect($property) . "', '" . $this->protect(bool2string($value)) . "')"; $query = "INSERT INTO logs (device, property, value) VALUES('" . $this->protect($ieeeAddress) . "', '" . $this->protect($property) . "', '" . $this->protect(bool2string($value)) . "')";
echo $query; echo $query . EOL;
if (is_numeric($value) and !empty($properties2log[$property])) if (is_numeric($value) and !empty($properties2log[$property]))
{ {
// calculate a min/max value for storing data // calculate a min/max value for storing data
@ -56,6 +56,10 @@ class db extends mysqli
{ {
$minMax = $minMax($value); $minMax = $minMax($value);
} }
var_dump($value) . EOL;
var_dump($minMax) . EOL;
var_dump($oldValue) . EOL;
if ( !is_numeric($oldValue)) $oldValue = 0;
//echo "minMax = " .$minMax . EOL; //echo "minMax = " .$minMax . EOL;
//echo "oldValue = " . $oldValue . EOL; //echo "oldValue = " . $oldValue . EOL;
//echo "Value = " . $value . EOL; //echo "Value = " . $value . EOL;
@ -81,12 +85,15 @@ class db extends mysqli
function moyenne($deviceObject, $property, $time) function moyenne($deviceObject, $property, $time)
{ {
$query = "SELECT AVG(value) FROM logs WHERE device='" . $deviceObject->ieeeAddress . "' AND property='" . $property . "' AND TIMEDIFF(NOW(), 'date') < " . $time; $query = "SELECT AVG(value) as value FROM logs WHERE device='" . $deviceObject->ieeeAddress . "' AND property='" . $property . "' AND TIMEDIFF(NOW(), date) < '00:" . $time . "'";
if(!$this->result = $this->query($query)) if(!$this->result = $this->query($query))
{ {
logger(ERROR, _("mysql query errror: ") . $this->error, __FILE__ . ":" . __LINE__); logger(ERROR, _("mysql query errror: ") . $this->error, __FILE__ . ":" . __LINE__);
} }
var_dump($this->result);
$value = $this->result->fetch_array(MYSQLI_NUM);
//var_dump($value);
return $value[0];
} }
} }

View File

@ -17,4 +17,12 @@
array(METEO, "UV"), array(METEO, "UV"),
array(METEO, "solarradiation") array(METEO, "solarradiation")
); );
$dashboards["etage"] = array(
array(ETAGE_SALON_RADIATEUR,"current_heating_setpoint"),
array(ETAGE_BUREAU_RADIATEUR,"current_heating_setpoint"),
array(ETAGE_BUREAU_PANNEAU, "state"),
array(ETAGE_CUISINE_PLAN_TRAVAIL_ECLAIRAGE, "state"),
array(ETAGE_CUISINE_PLAN_TRAVAIL_SPOT, "state_l1")
);
?> ?>

View File

@ -31,11 +31,14 @@ $deviceTable = array(
// "" => "ETAGE_SDB_RADIATEUR", // "" => "ETAGE_SDB_RADIATEUR",
"0x5c0272fffec4de9e" => "ETAGE_BUREAU_RADIATEUR", "0x5c0272fffec4de9e" => "ETAGE_BUREAU_RADIATEUR",
"0x00158d0001a0028c" => "ETAGE_BUREAU_FENETRE", "0x00158d0001a0028c" => "ETAGE_BUREAU_FENETRE",
"0x14b457fffe42a2c9" => "ETAGE_BUREAU_PANNEAU",
"0x842e14fffe8e3b67" => "ETAGE_BUREAU_ECLAIRAGE_INTER",
"0x00158d0001de080d" => "ETAGE_CHAMBRE_FENETRE", "0x00158d0001de080d" => "ETAGE_CHAMBRE_FENETRE",
"0x842e14fffe8c53a5" => "ETAGE_CUISINE_PLAN_TRAVAIL_INTER", "0x00124b00251ea4a7" => "ETAGE_CUISINE_PLAN_TRAVAIL_INTER",
"0x680ae2fffe403f22" => "ETAGE_CUISINE_PLAN_TRAVAIL_ECLAIRAGE", "0x680ae2fffe403f22" => "ETAGE_CUISINE_PLAN_TRAVAIL_ECLAIRAGE",
"0xbc33acfffe65621b" => "ETAGE_CUISINE_PLAN_TRAVAIL_SPOT", "0xbc33acfffe65621b" => "ETAGE_CUISINE_PLAN_TRAVAIL_SPOT",
"0x00158d0001ddefe1" => "ETAGE_ENTREE_PORTE", "1" => "ETAGE_CUISINE_PLAN_TRAVAIL_GROUPE_ECLAIRAGE",
"0x00158d00019f370e" => "ETAGE_PORTE_ENTREE",
"0x00158d00044fd579" => "ETAGE_SALON_FENETRE", "0x00158d00044fd579" => "ETAGE_SALON_FENETRE",
"0x00158d0004621e1f" => "ETAGE_CUISINE_FENETRE", "0x00158d0004621e1f" => "ETAGE_CUISINE_FENETRE",
"0x00158d0001ddefe1" => "ETAGE_PORTE_FENETRE", "0x00158d0001ddefe1" => "ETAGE_PORTE_FENETRE",

View File

@ -13,22 +13,22 @@ $properties2log = array(
"local_temperature" => 0.5, "local_temperature" => 0.5,
"state_l1" => null, "state_l1" => null,
"state_l2" => null, "state_l2" => null,
"humidity" => null, "humidity" => 0.9,
"current_heating_setpoint" => null, "current_heating_setpoint" => null,
"position" => null, "position" => null,
"pressure" => 10, "pressure" => 10,
"occupancy" => null, "occupancy" => null,
"illuminance_lux" => function($value) {($value < 500?50:$value*10/100); return $value;}, "illuminance_lux" => function($value) {$r = ($value < 500?50:$value*10/100); return $r;},
// "illuminance" => 8, // "illuminance" => 8,
"requested_brightness_level" => function($value) {($value < 500?50:$value*10/100);return $value;}, "requested_brightness_level" => function($value) {$r = ($value < 500?50:$value*10/100);return $r;},
"tempc" => 0.5, "tempc" => 0.5,
"humidity" => null, "humidity" => 1,
"dewptc" => 0.5, "dewptc" => 0.5,
"windchillc" => 0.5, "windchillc" => 0.5,
"winddir" => 40, "winddir" => 40,
"windspeedkmh" => 5, "windspeedkmh" => 5,
"windgustkmh" => 5, "windgustkmh" => 5,
"rainin" => null, "rainin" => 0.5,
//"dailyrainin" => null, //"dailyrainin" => null,
//"weeklyrainin" => null, //"weeklyrainin" => null,
//"monthlyrainin" => null, //"monthlyrainin" => null,
@ -36,7 +36,7 @@ $properties2log = array(
"solarradiation" => 10, "solarradiation" => 10,
"UV" => null, "UV" => null,
"indoortempc" => 0.5, "indoortempc" => 0.5,
"indoorhumidity" => null, "indoorhumidity" => 0.5,
"baromin" => 10 "baromin" => 10
); );

View File

@ -6,7 +6,7 @@ $propertyByType = array(
"brightness", "brightness",
"state_l1", "state_l1",
"state_l2" "state_l2"
) ),
"climate" => array( "climate" => array(
"local_temperature", "local_temperature",
"value", "value",

31
config/types.php Normal file
View File

@ -0,0 +1,31 @@
<?php
$types = array(
"light" => array(
"0xbc33acfffe6561e4",
"0xbc33acfffe65621b",
"0x086bd7fffe5aeab6",
"0x588e81fffe343e8f",
"0x680ae2fffe403f22",
"0x14b457fffe42a2c9"
),
"switch" => array(
"0xbc33acfffe458c65",
"0xbc33acfffe4583f7",
"0x00158d0005c1a998",
"0x842e14fffe9be0fc",
"0x086bd7fffe40482d",
"0x5c0272fffec4de9"
),
"climate" => array(
"0x00158d0001923c21",
"0xbc33acfffe458c65",
"0x5c0272fffec4de9e",
"0xbc33acfffe4583f7"
),
"cover" => array(
"0x842e14fffe9be0fc"
),
"hvac" =>
);
?>

View File

@ -63,6 +63,7 @@ function mkDevicesDB($topic, $json, $group=false)
{ {
//print_r($device); //print_r($device);
$device["device"]->groupID = $jsonDevice->id; $device["device"]->groupID = $jsonDevice->id;
$device["device"]->ieeeAddress = $jsonDevice->id;
//$indexDevices[$device["device"]->groupID] = & $device["device"]; //$indexDevices[$device["device"]->groupID] = & $device["device"];
//$indexFriendlyNames[$topic][$fn] = & $device["device"]; //$indexFriendlyNames[$topic][$fn] = & $device["device"];
}else }else
@ -266,8 +267,15 @@ function changeValue(&$property, $value, &$parentDevice, $propertyTree, $key)
{ {
logger(DEBUG,_("executing notifications functions"), __FILE__ . ":" . __LINE__); logger(DEBUG,_("executing notifications functions"), __FILE__ . ":" . __LINE__);
foreach($property["functions"] as $function) foreach($property["functions"] as $function)
{
try
{ {
$function($parentDevice, $key, $value); $function($parentDevice, $key, $value);
}catch (Exception $e)
{
$s = 'Exception reçue : ' . $e->getMessage();
logger(ERROR, $parentDevice->friendlyName . "/" . $property .": " . $s);
}
} }
} }
} }

View File

@ -10,6 +10,10 @@ function checkEvents()
$oldLevel = $logLevel; $oldLevel = $logLevel;
$logLevel = DEBUG; $logLevel = DEBUG;
$exception = false; $exception = false;
if ($events === null)
{
$events = array();
}
foreach ($events as $key => &$event) foreach ($events as $key => &$event)
{ {
$now = now(); $now = now();
@ -37,7 +41,7 @@ function checkEvents()
{ {
if (is_callable($this->function)) if (is_callable($this->function))
{ {
$this->function(&$event); $this->function($event);
}else }else
{ {
logger(DEBUG, sprintf(_("sending command set %s => %s for %s"), $event->param ,bool2string($event->value), $event->device->friendlyName), __FILE__ . ":" . __LINE__); logger(DEBUG, sprintf(_("sending command set %s => %s for %s"), $event->param ,bool2string($event->value), $event->device->friendlyName), __FILE__ . ":" . __LINE__);

View File

@ -1,17 +1,20 @@
<?php <?php
class notificationFreemobile class notificationFreemobile
{ {
private $url = "https://smsapi.free-mobile.fr/sendmsg?user=32886706&pass=JTGUY6l5OG73zX&msg="; private $url = "https://smsapi.free-mobile.fr/sendmsg?user=";
private $name = "freemobile"; private $name = "freemobile";
public $active = true; public $active = true;
public $level; public $level;
private $dest = array(
"32886706&pass=JTGUY6l5OG73zX", //daniel
);
function __construct() function __construct()
{ {
$this->level = ALERT | ERROR; $this->level = ALERT | ERROR;
} }
function send($message) function send($message, $destinataire=0)
{ {
global $curlErr; global $curlErr;
$result = false; $result = false;
@ -19,25 +22,22 @@ class notificationFreemobile
{ {
$ch = curl_init(); $ch = curl_init();
// set url // set url
curl_setopt($ch, CURLOPT_URL, $this->url . urlencode(trim($message))); curl_setopt($ch, CURLOPT_URL, $this->url . $dest["destinataire"] . "&msg=" . urlencode(trim($message)));
echo $this->url . urlencode(trim($message)) . EOL; echo $this->url . urlencode(trim($message)) . EOL;
//return the transfer as a string //return the transfer as a string
//curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); //curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
// $result contains the output string // $result contains the output string
//echo "1 curlErr =>"; var_dump($curlErr); echo EOL;
if ($curlErr <= 10) if ($curlErr <= 10)
{ {
$result = curl_exec($ch); $result = curl_exec($ch);
//echo "1 result => "; var_dump($result);echo EOL;
if ($result === false) if ($result === false)
{ {
$curlErr += 1; $curlErr += 1;
logger(ERROR, sprintf( _("Curl return error %d: %s when sending notification"), curl_errno($ch), curl_error($ch)), false, __FILE__ . ":" . __LINE__); logger(ERROR, sprintf( _("Curl return error %d: %s when sending notification"), curl_errno($ch), curl_error($ch)), false, __FILE__ . ":" . __LINE__);
}/*else }else
{ {
logger(INFO, sprintf(_("Curl return: %s when sending notification"), $result), false); logger(DEBUG, sprintf(_("Curl return: %s when sending notification"), $result), false);
}*/ }
} //TODO managing curl errors } //TODO managing curl errors
// close curl resource to free up system resources // close curl resource to free up system resources
curl_close($ch); curl_close($ch);

View File

@ -11,33 +11,31 @@ class radiateurs extends hook
public $delay = 3; // amount of time in $timeunit public $delay = 3; // amount of time in $timeunit
public $delayManual = 15; // amount of time in $timeunit for manual mode public $delayManual = 15; // amount of time in $timeunit for manual mode
public $timeUnit = "minute"; // unit of time for delay, second, minute, day, week, month, year public $timeUnit = "minute"; // unit of time for delay, second, minute, day, week, month, year
// list of devices we are listening to
// devicelist[$ieeAddress][0] => property to watch // list of devices we are listening to: ieeeAddress => property to watch
// devicelist[$ieeAddress][1] => initialized = true
protected $devicelist = array( protected $devicelist = array(
RDC_CHAMBRE_BAIE => "contact", RDC_CHAMBRE_BAIE => "contact",
RDC_SALON_BAIE => "contact", // RDC_SALON_BAIE => "contact",
RDC_ENTREE_PORTE => "contact", // RDC_ENTREE_PORTE => "contact",
ETAGE_ENTREE_PORTE => "contact", ETAGE_PORTE_ENTREE => "contact",
ETAGE_CUISINE_FENETRE => "contact", ETAGE_CUISINE_FENETRE => "contact",
ETAGE_SALON_FENETRE => "contact", ETAGE_SALON_FENETRE => "contact",
ETAGE_SALON_PORTE_FENETRE => "contact", ETAGE_PORTE_FENETRE => "contact",
ETAGE_CHAMBRE_FENETRE => "contact", // ETAGE_CHAMBRE_FENETRE => "contact",
ETAGE_BUREAU_FENETRE => "contact" // ETAGE_BUREAU_FENETRE => "contact"
); );
PROTECTED $hvac = array( protected $hvac = array(
RDC_CHAMBRE_BAIE => RDC_CHAMBRE_RADIATEUR, RDC_CHAMBRE_BAIE => RDC_CHAMBRE_RADIATEUR,
RDC_SALON_BAIE => RDC_SALON_RADIATEUR, RDC_SALON_BAIE => RDC_SALON_RADIATEUR,
RDC_ENTREE_PORTE => RDC_SALON_RADIATEUR, RDC_ENTREE_PORTE => RDC_SALON_RADIATEUR,
RDC_GARAGE_PORTE => RDC_SDB_RADIATEUR, GARAGE_PORTE => RDC_SDB_RADIATEUR,
ETAGE_ENTREE_PORTE => ETAGE_SALON_RADIATEUR, ETAGE_PORTE_ENTREE => ETAGE_SALON_RADIATEUR,
ETAGE_CUISINE_FENETRE => ETAGE_SALON_RADIATEUR, ETAGE_CUISINE_FENETRE => ETAGE_SALON_RADIATEUR,
ETAGE_SALON_FENETRE => ETAGE_SALON_RADIATEUR, ETAGE_SALON_FENETRE => ETAGE_SALON_RADIATEUR,
ETAGE_SALON_PORTE_FENETRE => ETAGE_SALON_RADIATEUR, ETAGE_PORTE_FENETRE => ETAGE_SALON_RADIATEUR,
// ETAGE_CHAMBRE_FENETRE => ETAGE_CHAMBRE_RADIATEUR, // ETAGE_CHAMBRE_FENETRE => ETAGE_CHAMBRE_RADIATEUR,
ETAGE_BUREAU_FENETRE => ETAGE_BUREAU_RADIATEUR, // ETAGE_BUREAU_FENETRE => ETAGE_BUREAU_RADIATEUR,
// ETAGE_SDB_FENETRE => ETAGE_SDB_RADIATEUR // ETAGE_SDB_FENETRE => ETAGE_SDB_RADIATEUR
); );
@ -55,13 +53,16 @@ class radiateurs extends hook
public function callBack(&$device, $property, $value) public function callBack(&$device, $property, $value)
{ {
global $indexDevices; global $indexDevices;
logger(DEBUG, "Callback : " . $this->hookName, __FILE__ . ":" . __LINE__);
if ($this->active === true)
{
$now = date("MM"); $now = date("MM");
if ($now <= 5 or $now >= 11) if ($now <= 5 or $now >= 11)
{ {
if ($value === false) if ($value === false)
{ {
send($indexDevices[$hvac[$device->ieeeAddress]], true); $this->send($indexDevices[$this->hvac[$device->ieeeAddress]], true);
/* switch ($device->$ieeeAdress) /* switch ($device->$ieeeAddress)
{ {
send($indexDevices[$hvac[$device->ieeeAddress]], false); send($indexDevices[$hvac[$device->ieeeAddress]], false);
case RDC_CHAMBRE_BAIE: case RDC_CHAMBRE_BAIE:
@ -86,7 +87,8 @@ class radiateurs extends hook
}*/ }*/
}else }else
{ {
send($indexDevices[$hvac[$device->ieeeAddress]], false); $this->send($indexDevices[$this->hvac[$device->ieeeAddress]], false);
}
} }
} }
} }
@ -94,31 +96,33 @@ class radiateurs extends hook
function send($device, $state) function send($device, $state)
{ {
global $indexDevices; global $indexDevices;
$flag = false;
if ($state === false) if ($state === false)
{ {
$t = getValue($device, "current_heating_setpoint"); $t = getValue($device->ieeeAddress, "current_heating_setpoint");
if ($t != $minTemp) if ($t != $this->minTemp)
{ {
$prevTemp[$device] = getValue($device, "current_heating_setpoint"); $this->prevTemp[$device->ieeeAddress] = getValue($device->ieeeAddress, "current_heating_setpoint");
} }
}else }else
{ {
$r = array_keys($hvac, $device->ieeeAddress); $r = array_keys($this->hvac, $device->ieeeAddress);
foreach($r as $value) foreach($r as $value)
{ {
if (getValue($indexDevices[$value], "contact") === true) logger(DEBUG, "Device to test for contact " . $value, __FILE__ . ":" . __LINE__);
if (getValue($device->ieeeAddress, "contact") === true)
{ {
$flag = true; $flag &= true;
break; break;
} }
} }
if ($flag === false) if ($flag === false)
{ {
$msg = array("current_heating_setpoint" => (!empty($prevTemp[$device])?$prevTemp[$device]:19)); $msg = array("current_heating_setpoint" => (!empty($this->prevTemp[$device->ieeeAddress])?$this->prevTemp[$device->ieeeAddress]:19));
logger(INFO, sprintf(_("publishing message: %s to %s"), json_encode($msg), $deviceTarget->friendlyName), __FILE__ . ":" . __LINE__); logger(INFO, sprintf(_("publishing message: %s to %s"), json_encode($msg), $device->friendlyName), __FILE__ . ":" . __LINE__);
$deviceTarget->payload = $msg; $device->payload = $msg;
$deviceTarget->set(); $device->set();
$deviceTarget->method = AUTO; $device->method = AUTO;
} }
} }
} }

View File

@ -22,6 +22,7 @@ class rdc_chambre_eclairage extends hook
public function callBack($device, $property, $value) public function callBack($device, $property, $value)
{ {
global $devices, $indexDevices; global $devices, $indexDevices;
logger(DEBUG, sprintf(_("property=%s, value=%s"), $property, $value), __FILE__ . ":" . __LINE__);
$lux = $indexDevices[RDC_CHAMBRE_LUMINOSITE]->properties["illuminance_lux"]; $lux = $indexDevices[RDC_CHAMBRE_LUMINOSITE]->properties["illuminance_lux"];
$targetAmbiance = $indexDevices[RDC_CHAMBRE_AMBIANCE]; $targetAmbiance = $indexDevices[RDC_CHAMBRE_AMBIANCE];
$targetEclairage = $indexDevices[RDC_CHAMBRE_ECLAIRAGE]; $targetEclairage = $indexDevices[RDC_CHAMBRE_ECLAIRAGE];
@ -32,12 +33,12 @@ class rdc_chambre_eclairage extends hook
$this->send($targetAmbiance, "state", "ON", "OFF", AUTO); $this->send($targetAmbiance, "state", "ON", "OFF", AUTO);
}elseif ($property == "contact") }elseif ($property == "contact")
{ {
if ($value == false and getValue(RDC_CHAMBRE_ECLAIRAGE, "state_l1") == "OFF") if ($value == false)
{ {
$this->send($targetEclairage, "state_l1", "ON", "OFF", AUTO); $this->send($targetEclairage, "state_l1", "ON", "OFF", AUTO);
}elseif ($value == true and getValue(RDC_CHAMBRE_ECLAIRAGE, "state_l1") == "ON") }elseif ($value == true)
{ {
$this->send($targetEclairage, "state_l1", "OFF", null, null); $this->send($targetEclairage, "state_l1", "OFF", false, null);
} }
} }
logger (INFO, sprintf(_("%s: notification received from MQTT from %s => parameter: %s value: %s"), $this->hookName, $device->friendlyName, $property, bool2string($value)), __FILE__ . ":" . __LINE__); logger (INFO, sprintf(_("%s: notification received from MQTT from %s => parameter: %s value: %s"), $this->hookName, $device->friendlyName, $property, bool2string($value)), __FILE__ . ":" . __LINE__);
@ -47,17 +48,17 @@ class rdc_chambre_eclairage extends hook
{ {
global $indexDevices; global $indexDevices;
$msg = array($property => $state); $msg = array($property => $state);
if ($deviceObject->properties[$property]["value"] != $state) //if ($deviceObject->properties[$property]["value"] != $state)
{ //{
logger(INFO, sprintf(_("publishing message: %s to %s"), json_encode($msg), $deviceObject->friendlyName), __FILE__ . ":" . __LINE__); logger(INFO, sprintf(_("publishing message: %s to %s"), json_encode($msg), $deviceObject->friendlyName), __FILE__ . ":" . __LINE__);
$deviceObject->payload = $msg; $deviceObject->payload = $msg;
$deviceObject->set(); $deviceObject->set();
$deviceObject->method = $method; $deviceObject->method = $method;
}else ///}else
{ /*{
logger(INFO, sprintf(_("not publishing message: %s to %s, already set"), json_encode($msg), $deviceObject->friendlyName), __FILE__ . ":" . __LINE__); logger(INFO, sprintf(_("not publishing message: %s to %s, already set"), json_encode($msg), $deviceObject->friendlyName), __FILE__ . ":" . __LINE__);
} }*/
//echo 'delaystate = ' . var_dump($delayState); //echo 'delaystate = ' . var_dump($delayState);
if ($delayState !== false) setDelay($deviceObject, $this->delay, $this->timeUnit, "state", $delayState, true); if ($delayState !== false) setDelay($deviceObject, $this->delay, $this->timeUnit, "state", $delayState, true);
} }

View File

@ -18,7 +18,7 @@ class alerte_intrusion extends hook
// callback fonction. Is called with these 4 parameters // callback fonction. Is called with these 4 parameters
public function callBack($device, $property, $value) public function callBack($device, $property, $value)
{ {
logger(DEBUG, sprintf(_("property=%s, value=%s"), $property, $value), __FILE__ . ":" . __LINE__);
switch($property) switch($property)
{ {
case "contact": case "contact":

View File

@ -21,7 +21,7 @@ class rdc_salon_eclairage extends hook
public function callBack($device, $param, $value) public function callBack($device, $param, $value)
{ {
global $indexDevices; global $indexDevices;
logger(INFO, _("hook : rdc_salon_eclairage"), __FILE__ . ":" . __LINE__); logger(DEBUG, "Callback : " . $this->hookName, __FILE__ . ":" . __LINE__);
$deviceTarget = &$indexDevices[RDC_SALON_ECLAIRAGE_PANNEAU]; $deviceTarget = &$indexDevices[RDC_SALON_ECLAIRAGE_PANNEAU];
$lux = $indexDevices[RDC_SALON_LUMINOSITE]; $lux = $indexDevices[RDC_SALON_LUMINOSITE];
$mvmt = $indexDevices[RDC_SALON_MVMT]; $mvmt = $indexDevices[RDC_SALON_MVMT];
@ -40,7 +40,7 @@ class rdc_salon_eclairage extends hook
if ($illuminance <= $this->luminance_min) if ($illuminance <= $this->luminance_min)
{ {
logger(INFO, _("setting to ON"), __FILE__ . ":" . __LINE__); logger(INFO, _("setting to ON"), __FILE__ . ":" . __LINE__);
$this->send($deviceTarget, "ON", null, AUTO); $this->send($deviceTarget, "ON", false, AUTO);
removeEvent($deviceTarget, "state", "OFF"); removeEvent($deviceTarget, "state", "OFF");
} }
}else }else
@ -61,7 +61,7 @@ class rdc_salon_eclairage extends hook
logger(INFO, _("Door is open and illumance < min"), __FILE__ . ":" . __LINE__); logger(INFO, _("Door is open and illumance < min"), __FILE__ . ":" . __LINE__);
if (getValue(RDC_SALON_MVMT, "occupancy") == ON or getValue(RDC_SALON_MVMT2, "occupancy") == ON) if (getValue(RDC_SALON_MVMT, "occupancy") == ON or getValue(RDC_SALON_MVMT2, "occupancy") == ON)
{ {
$this->send($deviceTarget, "ON", null, AUTO); $this->send($deviceTarget, "ON", false, AUTO);
}else }else
{ {
$this->send($deviceTarget, "ON", "OFF", AUTO); $this->send($deviceTarget, "ON", "OFF", AUTO);
@ -82,7 +82,7 @@ class rdc_salon_eclairage extends hook
}elseif ($value <= $this->luminance_min and (getValue(RDC_SALON_MVMT, "occupancy") == ON || getValue(RDC_SALON_MVMT2,"occupancy") == ON)) }elseif ($value <= $this->luminance_min and (getValue(RDC_SALON_MVMT, "occupancy") == ON || getValue(RDC_SALON_MVMT2,"occupancy") == ON))
{ {
logger(INFO, _("illuminance < min and movement detected"), __FILE__ . ":" . __LINE__); logger(INFO, _("illuminance < min and movement detected"), __FILE__ . ":" . __LINE__);
$this->send($deviceTarget, "ON", null, AUTO); $this->send($deviceTarget, "ON", false, AUTO);
} }
break; break;
} }
@ -94,16 +94,16 @@ class rdc_salon_eclairage extends hook
global $indexDevices; global $indexDevices;
$msg = array("state" => $state); $msg = array("state" => $state);
if ($deviceTarget->properties["state"]["value"] != $state) //if ($deviceTarget->properties["state"]["value"] != $state)
{ //{
logger(INFO, sprintf(_("publishing message: %s to %s"), json_encode($msg), $deviceTarget->friendlyName), __FILE__ . ":" . __LINE__); logger(INFO, sprintf(_("publishing message: %s to %s"), json_encode($msg), $deviceTarget->friendlyName), __FILE__ . ":" . __LINE__);
$deviceTarget->payload = $msg; $deviceTarget->payload = $msg;
$deviceTarget->set(); $deviceTarget->set();
$deviceTarget->method = $method; $deviceTarget->method = $method;
}else /*}else
{ {
logger(INFO, sprintf(_("not publishing message: %s to %s, already set"), json_encode($msg), $deviceTarget->friendlyName), __FILE__ . ":" . __LINE__); logger(INFO, sprintf(_("not publishing message: %s to %s, already set"), json_encode($msg), $deviceTarget->friendlyName), __FILE__ . ":" . __LINE__);
} }*/
//echo 'delaystate = ' . var_dump($delayState); //echo 'delaystate = ' . var_dump($delayState);
if ($delayState !== false) setDelay($deviceTarget, $this->delay, $this->timeUnit, "state", $delayState, true); if ($delayState !== false) setDelay($deviceTarget, $this->delay, $this->timeUnit, "state", $delayState, true);
} }

View File

@ -29,18 +29,14 @@ class rdc_sdb_eclairage extends hook
global $indexDevices; global $indexDevices;
//var_dump($value); //var_dump($value);
$deviceTarget = $indexDevices[RDC_SDB_WC_ECLAIRAGE]; $deviceTarget = $indexDevices[RDC_SDB_WC_ECLAIRAGE];
logger(DEBUG, sprintf(_("property=%s, value=%s"), $property, $value), __FILE__ . ":" . __LINE__); logger(DEBUG, "Callback : " . $this->hookName, __FILE__ . ":" . __LINE__);
switch($property) switch($property)
{ {
case "occupancy": case "occupancy":
logger(DEBUG, _("CASE: occupancy"), __FILE__ . ":" . __LINE__); logger(DEBUG, _("CASE: occupancy"), __FILE__ . ":" . __LINE__);
if ($value == ON ) if ($value == ON )
{
if (getValue($deviceTarget->ieeeAddress, "state_l1") != "ON")
{ {
$this->send("ON"); $this->send("ON");
}
//setDelay($indexDevices[RDC_SDB_WC_ECLAIRAGE], $this->delay, $this->timeUnit, "state_l1", "OFF", true);
$device->method = AUTO; $device->method = AUTO;
} }
break; break;
@ -48,11 +44,20 @@ class rdc_sdb_eclairage extends hook
logger(DEBUG, _("CASE: state_l1"), __FILE__ . ":" . __LINE__); logger(DEBUG, _("CASE: state_l1"), __FILE__ . ":" . __LINE__);
if ($value == "ON") if ($value == "ON")
{ {
setDelay($deviceTarget, $this->delay, $this->timeUnit, "state_l1", "OFF", true); if ($device->method != MANUAL)
{
$delay = $this->delay;
$device->method = AUTO;
}else
{
$delay = $this->delayManual;
$device->method = MANUAL; $device->method = MANUAL;
}elseif ($value = "OFF") }
setDelay($deviceTarget, $delay, $this->timeUnit, "state_l1", "OFF", true);
}elseif ($value == "OFF")
{ {
removeEvent($deviceTarget, "state_l1", "OFF"); removeEvent($deviceTarget, "state_l1", "OFF");
$device->method = null;
} }
break; break;
} }

View File

@ -9,12 +9,13 @@ class rdc_store extends hook
public $luminance_max = 3000; public $luminance_max = 3000;
public $storeDownTime = 38; public $storeDownTime = 38;
public $storeUpTime = 41; public $storeUpTime = 41;
public $maxLevel;
protected $storeLevel; protected $storeLevel;
protected $propertyInitialized =array(); protected $propertyInitialized =array();
protected $devicelist = array( protected $devicelist = array(
RDC_EXTERIEUR_LUMINOSITE => "illuminance_lux", // "ON"/"OFF" RDC_EXTERIEUR_LUMINOSITE => "illuminance_lux",
METEO => "rainin", METEO => "rainin",
//METEO => array("solarradiation", false), //METEO => "solarradiation",
METEO => "windspeedkmh", METEO => "windspeedkmh",
METEO => "windgustkmh" METEO => "windgustkmh"
); );
@ -30,62 +31,86 @@ class rdc_store extends hook
logger(DEBUG, "Callback : RDC_STORE", __FILE__ . ":" . __LINE__); logger(DEBUG, "Callback : RDC_STORE", __FILE__ . ":" . __LINE__);
$rain = 0; $rain = 0;
$exterieur_lux = 0; $exterieur_lux = 0;
$salon_lux = 0;
$rafale = 0; $rafale = 0;
$soleil = 0; $soleil = 0;
$storeDevice = $indexDevices[RDC_STORE]; $storeDevice = $indexDevices[RDC_STORE];
if (array_key_exists("position", $storeDevice->properties)) if (array_key_exists("position", $storeDevice->properties))
{ {
$storeLevel = $storeDevice->properties["position"]; $this->storeLevel = 100 - $storeDevice->properties["position"]["value"];
logger(DEBUG, "storeLevel=" . $this->storeLevel, __FILE__ . ":" . __LINE__);
}else }else
{ {
return true; $this->storeLevel = 0;
//return true;
} }
if (array_key_exists("illuminance_lux", $indexDevices[RDC_EXTERIEUR_LUMINOSITE]->properties)) if (array_key_exists("illuminance_lux", $indexDevices[RDC_EXTERIEUR_LUMINOSITE]->properties))
{ {
$exterieur_lux = $mohaDB->moyenne($indexDevices[RDC_EXTERIEUR_LUMINOSITE], "illuminance_lux", 15); $exterieur_lux = $mohaDB->moyenne($indexDevices[RDC_EXTERIEUR_LUMINOSITE], "illuminance_lux", 15);
logger(DEBUG, "exterieur_lux=" . $exterieur_lux, __FILE__ . ":" . __LINE__);
} }
if (array_key_exists("illuminance_lux", $indexDevices[RDC_SALON_LUMINOSITE]->properties))
{
$salon_lux = $mohaDB->moyenne($indexDevices[RDC_SALON_LUMINOSITE], "illuminance_lux", 10);
logger(DEBUG, "salon_lux=" . $salon_lux, __FILE__ . ":" . __LINE__);
}
if (array_key_exists(METEO, $indexDevices))
{
if (array_key_exists("rainin", $indexDevices[METEO]->properties)) if (array_key_exists("rainin", $indexDevices[METEO]->properties))
{ {
$rain = $indexDevices[METEO]->properties["rainin"]; $rain = $indexDevices[METEO]->properties["rainin"]["value"];
logger(DEBUG, "rain=" . var_dump($rain), __FILE__ . ":" . __LINE__);
} }
if (array_key_exists("windgustkmh", $indexDevices[METEO]->properties)) if (array_key_exists("windgustkmh", $indexDevices[METEO]->properties))
{ {
$rafale = $mohaDB->moyenne($indexDevices[METEO], "windgustkmh", 12); $rafale = $mohaDB->moyenne($indexDevices[METEO], "windgustkmh", 12);
logger(DEBUG, "rafale=" . $rafale, __FILE__ . ":" . __LINE__);
} }
if (array_key_exists("solarradiation", $indexDevices[METEO]->properties)) if (array_key_exists("solarradiation", $indexDevices[METEO]->properties))
{ {
$soleil = $mohaDB->moyenne($indexDevices[METEO], "solarradiation", 12); $soleil = $mohaDB->moyenne($indexDevices[METEO], "solarradiation", 12);
logger(DEBUG, "soleil=" . $exterieur_lux, __FILE__ . ":" . __LINE__);
}
} }
logger(DEBUG, sprintf(_("property=%s, value=%s"), $property, $value), __FILE__ . ":" . __LINE__); logger(DEBUG, sprintf(_("property=%s, value=%s"), $property, $value), __FILE__ . ":" . __LINE__);
if ($rafale >= 6 or $rain != 0) if ($rafale >= 60 or $rain != 0)
{ {
$maxLevel = 0; $this->maxLevel = 0;
}else logger(DEBUG, sprintf("rafale = %s and rain = %s",$rafale, $rain), __FILE__ . ":" . __LINE__);
$this->close("vent trop fort ou pluie");
return 0;
}elseif ($rafale != 0)
{ {
if ($rafale != 0) $this->maxLevel = ($r = 100 - round(($rafale-10)/5, 0, PHP_ROUND_HALF_UP)*20)<0 ? 0 : $r;
{ //$this->maxLevel = 100 / $rafale;
$maxLevel = 100 / $rafale; logger(DEBUG, "rafale=" . $rafale, __FILE__ . ":" . __LINE__);
}
} }
logger(DEBUG, "maxlevel=" . $this->maxLevel, __FILE__ . ":" . __LINE__);
//$store2level = $this->maxLevel;
switch ($property) switch ($property)
{ {
case "illuminance_lux": case "illuminance_lux":
logger(DEBUG, "CASE: illuminance_lux:" . $value, __FILE__ . ":" . __LINE__); logger(DEBUG, "CASE: illuminance_lux:" . $value, __FILE__ . ":" . __LINE__);
if ($exterieur_lux > 3000) if ($exterieur_lux > 40000)
{ {
if ($rain == 0 and $maxLevel != 0) logger(DEBUG, "exterieur_lux > 40000", __FILE__ . ":" . __LINE__);
if ($this->maxLevel != 0 and $salon_lux > 150)
{ {
$store2level = storeLevel + 15; $store2level = $this->storeLevel + 15;
if ( $store2level > $maxLevel ) if ( $store2level > $this->maxLevel )
{ {
$this->open($maxLevel); logger(DEBUG, "store2level > maxLevel", __FILE__ . ":" . __LINE__);
$this->set($this->maxLevel);
}else }else
{ {
$this->open($max2level); logger(DEBUG, "store2level <= maxLevel", __FILE__ . ":" . __LINE__);
$this->set($store2level);
} }
} }
}elseif ($exterieur_lux < 25000) }elseif ($exterieur_lux < 35000)
{ {
logger(DEBUG, "exterieur_lux < 35000", __FILE__ . ":" . __LINE__);
$this->close("Luminosité faible"); $this->close("Luminosité faible");
} }
break; break;
@ -94,40 +119,25 @@ class rdc_store extends hook
$this->close("Pluie"); $this->close("Pluie");
break; break;
case "windgustkmh"; case "windgustkmh";
logger(DEBUG, "CASE: windgustkmh:" . $value, __FILE__ . ":" . __LINE__); logger(DEBUG, "CASE: windgustkmh:" . $rafale, __FILE__ . ":" . __LINE__);
case "windspeedkmh": //case "windspeedkmh":
logger(DEBUG, "CASE: windspeedkmh:" . $value, __FILE__ . ":" . __LINE__); // logger(DEBUG, "CASE: windspeedkmh:" . $value, __FILE__ . ":" . __LINE__);
if($value > 50)
logger(DEBUG, "maxLevel = " . $this->maxLevel . ' result => $r = ' . $r, __FILE__ . ":" . __LINE__);
if ($this->storeLevel > $this->maxLevel)
{ {
$this->close("Trop de vent"); $this->set($this->maxLevel);
}elseif ($value > 40 and $this->storeLevel > 20)
{
$this->maxLevel = 20;
$this->send(20);
}elseif ($value > 30 and $this->storeLevel > 40)
{
$this->maxLevel = 40;
$this->send(40);
}elseif ($value >20 and $this->storeLevel > 60)
{
$this->maxLevel = 60;
$this->send(60);
}elseif ($value >10 and $this->storeLevel > 80)
{
$this->maxLevel = 80;
$this->send(80);
}else
{
$this->maxLevel = 100;
} }
$this->close("Fortes rafales de vent");
break; break;
default: default:
}
if ($store2level <= $this->storeLevel)
{
$this->set($store2level);
} }
} }
private function open ($level) private function set ($level)
{ {
if ($this->storeLevel < $level) if ($this->storeLevel < $level)
{ {
@ -140,8 +150,7 @@ class rdc_store extends hook
{ {
if ($this->storeLevel != 0) if ($this->storeLevel != 0)
{ {
logger(DEBUG, "Close store :" . $level, __FILE__ . ":" . __LINE__); logger(DEBUG, "Close store :" . $reason, __FILE__ . ":" . __LINE__);
print ( "store fermé " . $reason);
$this->send(100); $this->send(100);
} }
} }

View File

@ -10,7 +10,7 @@ class rdc_wc_eclairage extends hook
); );
public $delay = 3; // amount of time in $timeunit public $delay = 3; // amount of time in $timeunit
public $delayManual = 8; // amount of time in $timeunit for manual mode public $delayManual = 15; // amount of time in $timeunit for manual mode
public $timeUnit = "minute"; // unit of time for delay, second, minute, day, week, month, year public $timeUnit = "minute"; // unit of time for delay, second, minute, day, week, month, year
// callback fonction. Is called with these 4 parameters // callback fonction. Is called with these 4 parameters
@ -18,23 +18,32 @@ class rdc_wc_eclairage extends hook
{ {
global $indexDevices; global $indexDevices;
//var_dump($value); //var_dump($value);
logger(DEBUG, "Callback : " . $this->hookName, __FILE__ . ":" . __LINE__);
switch($property) switch($property)
{ {
case "state_l2": case "state_l2":
logger(DEBUG, _("CASE: state_l2"), __FILE__ . ":" . __LINE__); logger(DEBUG, "CASE: state_l2", __FILE__ . ":" . __LINE__);
if ($value == "ON") if ($value == "ON")
{ {
setDelay($device, $this->delayManual, $this->timeUnit, "state_l2", "OFF", true); if ($device->method == AUTO)
{
setDelay($device, $this->delay, $this->timeUnit, "state_l2", "OFF", true);
}else
{
$device->method = MANUAL; $device->method = MANUAL;
setDelay($device, $this->delayManual, $this->timeUnit, "state_l2", "OFF", true);
}
}elseif ($value == "OFF") }elseif ($value == "OFF")
{ {
deleteEvent(searchEvent($device, "state_l2", "OFF")); removeEvent($device, "state_l2", "OFF");
$device->method = null;
} }
break; break;
case "occupancy": case "occupancy":
logger(DEBUG, _("CASE: occupancy"), __FILE__ . ":" . __LINE__); logger(DEBUG, "CASE: occupancy", __FILE__ . ":" . __LINE__);
if ($value == true) if ($value == true)
{ {
$device->method = AUTO;
$this->send("ON"); $this->send("ON");
} }
} }
@ -48,11 +57,6 @@ class rdc_wc_eclairage extends hook
logger(INFO, sprintf(_("publishing message: %s to %s"), json_encode($msg), $deviceObject->friendlyName), __FILE__ . ":" . __LINE__); logger(INFO, sprintf(_("publishing message: %s to %s"), json_encode($msg), $deviceObject->friendlyName), __FILE__ . ":" . __LINE__);
$deviceObject->payload = $msg; $deviceObject->payload = $msg;
$deviceObject->set(null); $deviceObject->set(null);
if ($deviceObject->method != MANUAL)
{
$deviceObject->method = AUTO;
}
setDelay($deviceObject, $this->delay, $this->timeUnit, "state_l2", "OFF", true);
} }
} }

View File

@ -132,7 +132,7 @@ function listHooks($dir, &$hookList)
function endMoha() function endMoha()
{ {
global $testMode, $devices, $topics, $nSubscribed ,$client, $logFh, $connected, $dataPath; global $testMode, $devices, $topics, $events, $nSubscribed ,$client, $logFh, $connected, $dataPath;
$x = 0; $x = 0;
logger(WARNING, _("moha is ending"), __FILE__ . ":" . __LINE__); logger(WARNING, _("moha is ending"), __FILE__ . ":" . __LINE__);
@ -144,6 +144,10 @@ function endMoha()
{ {
logger(ERROR, _("Can not store topics db" ), __FILE__ . ":" . __LINE__); logger(ERROR, _("Can not store topics db" ), __FILE__ . ":" . __LINE__);
} }
if (storeDB($events, $dataPath . "events.db") === false)
{
logger(ERROR, _("Can not store events db" ), __FILE__ . ":" . __LINE__);
}
if($testMode) file_put_contents($dataPath . "moha.devices", var_export($devices, true)); if($testMode) file_put_contents($dataPath . "moha.devices", var_export($devices, true));
if ($connected) if ($connected)
{ {
@ -177,10 +181,10 @@ if (is_readable($configDir . "/devices_constants.php"))
{ {
include $configDir . "/devices_constants.php"; include $configDir . "/devices_constants.php";
//echo "hooklist"; print_r($hooksList); echo EOL; //echo "hooklist"; print_r($hooksList); echo EOL;
logger(INFO, sprintf(_("%s/devices_constants.define found, so it has been included :-)"), $configDir), __FILE__ . ":" . __LINE__, false); logger(INFO, sprintf(_("%s/devices_constants.php found, so it has been included :-)"), $configDir), __FILE__ . ":" . __LINE__, false);
}else }else
{ {
logger(WARNING, sprintf(_("%s/devices_constants.define not found, so not included :-)"), $configDir), __FILE__ . ":" . __LINE__, false); logger(WARNING, sprintf(_("%s/devices_constants.php not found, so not included :-)"), $configDir), __FILE__ . ":" . __LINE__, false);
} }
logger(DEBUG, _("requiring php modules"), __FILE__ . ":" . __LINE__); logger(DEBUG, _("requiring php modules"), __FILE__ . ":" . __LINE__);
@ -224,24 +228,42 @@ if (!empty($hooksList)) // some hooks to include if hooklist is not empty
logger(DEBUG, _("Loading stored topics datas from ") . $dataPath . "topics.db", __FILE__ . ":" . __LINE__); logger(DEBUG, _("Loading stored topics datas from ") . $dataPath . "topics.db", __FILE__ . ":" . __LINE__);
if (file_exists($dataPath . "topics.db")) if (file_exists($dataPath . "topics.db"))
{ {
if (($topics = loadDB($dataPath . "topics.db")) === false) if (($db = loadDB($dataPath . "topics.db")) === false)
{ {
logger(ERROR, _("Can not load topics db"), __FILE__ . ":" . __LINE__); logger(ERROR, _("Can not load topics db"), __FILE__ . ":" . __LINE__);
}else
{
$topics = $db;
} }
} }
logger(DEBUG, _("Loading stored devices datas from ") . $dataPath . "devices.db", __FILE__ . ":" . __LINE__); logger(DEBUG, _("Loading stored devices datas from ") . $dataPath . "devices.db", __FILE__ . ":" . __LINE__);
if (file_exists($dataPath . "devices.db")) if (file_exists($dataPath . "devices.db"))
{ {
if (($devices = loadDB($dataPath . "devices.db")) === false) if (($db = loadDB($dataPath . "devices.db")) === false)
{ {
logger(ERROR, _("Can not load devices db"), __FILE__ . ":" . __LINE__); logger(ERROR, _("Can not load devices db"), __FILE__ . ":" . __LINE__);
}else }else
{ {
$devices = $db;
mkIndexes(); mkIndexes();
} }
} }
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 // Program start
logger(DEBUG, _("Program start"), __FILE__ . ":" . __LINE__, false); logger(DEBUG, _("Program start"), __FILE__ . ":" . __LINE__, false);
$client = new Mosquitto\Client(); $client = new Mosquitto\Client();

View File

@ -54,9 +54,9 @@ function zigbee2mqttCallback($topic, $message)
$fnTreeEnd = end($fnTree); $fnTreeEnd = end($fnTree);
switch($fnTreeEnd) switch($fnTreeEnd)
{ {
case "l1": /*case "l1":
case "l2": case "l2":
$fnTreeEnd = "state_" . $fnTreeEnd; $fnTreeEnd = "state_" . $fnTreeEnd;*/
case "set": case "set":
case "mode": case "mode":
case "contact": case "contact":
@ -77,6 +77,7 @@ function zigbee2mqttCallback($topic, $message)
logger(ERROR, sprintf(_("device with friendlyname %s not found"), $fn), __FILE__ . ":" . __LINE__); logger(ERROR, sprintf(_("device with friendlyname %s not found"), $fn), __FILE__ . ":" . __LINE__);
}else }else
{ {
logger(DEBUG, "PayloadArray = " . print_r($payloadArray,true), __FILE__ . ":" . __LINE__);
changeDevice($topicName, $fn, $indexFriendlyNames[$topicName][$fn], $payloadArray); changeDevice($topicName, $fn, $indexFriendlyNames[$topicName][$fn], $payloadArray);
} }

View File

@ -18,6 +18,12 @@ function bool2string($var)
} }
} }
function validateDate($date, $format = 'Y-m-d H:i:s')
{
$d = DateTime::createFromFormat($format, $date);
return $d && $d->format($format) == $date;
}
function now() function now()
{ {
$now = new datetime(); $now = new datetime();
@ -75,7 +81,10 @@ function getDevice($topic, $fn)
function getValue($ieeeAddress, $property) function getValue($ieeeAddress, $property)
{ {
global $indexDevices; global $indexDevices;
return $indexDevices[$ieeeAddress]->properties[$property]["value"]; $r = $indexDevices[$ieeeAddress]->properties[$property]["value"];
logger(DEBUG, "device: " . $indexDevices[$ieeeAddress]->friendlyName . " value: " . $r, __FILE__ . ":" . __LINE__ );
return $r;
} }
function setValue($fn, $property, $value) function setValue($fn, $property, $value)

View File

@ -21,42 +21,54 @@ function webDashboard($socket, $n="Général")
$propertyObject = $device->properties[$property]; $propertyObject = $device->properties[$property];
$value = $propertyObject["value"]; $value = $propertyObject["value"];
logger(DEBUG, $device->friendlyName . " => " . bool2string(_($value))); logger(DEBUG, $device->friendlyName . " => " . bool2string(_($value)));
$response .= $device->friendlyName . aliases($device->friendlyName, $property) . " => " . bool2string(_($value)) . EOL; $response .= $device->friendlyName . aliases($device->friendlyName, $property) . ' => ';
if (array_key_exists("access", $propertyObject)) if (array_key_exists("access", $propertyObject))
{ {
logger(DEBUG, _("Access = ") . $propertyObject["access"], __FILE__ . ":" . __LINE__); logger(DEBUG, _("Access = ") . $propertyObject["access"], __FILE__ . ":" . __LINE__);
if(($propertyObject["access"] & 2)) if(($propertyObject["access"] & 2))
{ {
logger(DEBUG, _("Write Access OK ") . ($propertyObject["access"] & 2), __FILE__ . ":" . __LINE__); logger(DEBUG, _("Write Access OK ") . ($propertyObject["access"] & 2), __FILE__ . ":" . __LINE__);
$response .= "&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;" . displayChoice($device, $property); $response .= "&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;" . displayChoice($device, $property, $value);
} }
if(($propertyObject["access"] & 4)) if(($propertyObject["access"] & 4))
{ {
logger(DEBUG, _("can get value") . ($propertyObject["access"] & 4), __FILE__ . ":" . __LINE__); logger(DEBUG, _("can get value") . ($propertyObject["access"] & 4), __FILE__ . ":" . __LINE__);
$response .= '&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<input type="button" id="' . $device->topic ."/" . $device->friendlyName . "/" . $propertyObject["name"] . '" value="' . _("Update") . "\" onmouseup=\"getPropertyValue('" . $device->topic . "','" . $device->friendlyName . "','" . $propertyObject["name"] . "')\">"; $response .= '<input type="button" id="' . $device->topic ."/" . $device->friendlyName . "/" . $propertyObject["name"] . '" value="' . _("Update") . "\" onmouseup=\"getPropertyValue('" . $device->topic . "','" . $device->friendlyName . "','" . $propertyObject["name"] . "')\">";
}
} }
$response .= EOLH; $response .= EOLH;
}else }else
{ {
logger(ERROR, _("Property do not exist"), __FILE__ . ":" . __LINE__); $response .= bool2string(_($value));
} if(array_key_exists("unit", $propertyObject))
}else
{ {
logger(ERROR, _("Device do not exist"), __FILE__ . ":" . __LINE__); $response .= $propertyObject["unit"];
logger(DEBUG, _("unit = ") . $unit, __FILE__ . ":" . __LINE__);
} }
} $response .= EOLH;
}else
{
$response = _("dashboard not found");
}
htmlSend($socket, $response);
} }
function displayChoice($device, $propertyName) }else
{
logger(ERROR, _("Property does not exists"), __FILE__ . ":" . __LINE__);
}
}else
{
logger(ERROR, _("Device does not exists"), __FILE__ . ":" . __LINE__);
}
}
}else
{
logger(ERROR, _("Dashboard does not exists"), __FILE__ . ":" . __LINE__);
$response = _("dashboard not found");
}
htmlSend($socket, $response, '<meta http-equiv="refresh" content="10">');
}
function displayChoice($device, $propertyName, $value)
{ {
logger(INFO, _("function displayChoice"), __FILE__ . ":" . __LINE__); logger(INFO, _("function displayChoice"), __FILE__ . ":" . __LINE__);
$propertyObject = $device->properties[$propertyName]; $propertyObject = $device->properties[$propertyName];
$unit = '';
if(array_key_exists("unit", $propertyObject)) if(array_key_exists("unit", $propertyObject))
{ {
@ -68,43 +80,54 @@ function displayChoice($device, $propertyName)
{ {
case "binary": case "binary":
logger(DEBUG, _("type is binary"), __FILE__ . ":" . __LINE__); logger(DEBUG, _("type is binary"), __FILE__ . ":" . __LINE__);
$formHTML = bool2string($value);
$choice["on"] = $propertyObject["value_on"]; $choice["on"] = $propertyObject["value_on"];
$choice["off"] = $propertyObject["value_off"]; $choice["off"] = $propertyObject["value_off"];
if (array_key_exists("toggle", $propertyObject)) if (array_key_exists("toggle", $propertyObject))
{ {
$choice["toggle"] = $propertyObject["toggle"]; $choice["toggle"] = $propertyObject["toggle"];
} }
$formHTML = mkHTML($device, $propertyName, $choice); $formHTML .= mkHTML($device, $propertyName, $choice);
break; break;
case "numeric": case "numeric":
logger(DEBUG, _("type is numeric"), __FILE__ . ":" . __LINE__); logger(DEBUG, _("type is numeric") . "#" . $value . "#", __FILE__ . ":" . __LINE__);
$formHTML = '<input type="range" id="' . $propertyObject["name"] . '"'; $step = '';
if (array_key_exists("value_step", $propertyObject))
{
$step = ' step="' . $propertyObject["value_step"] . '"';
}
//$formHTML .= $device->friendlyName . aliases($device->friendlyName, $property) . ' => ';
$formHTML = '<input type="number" id="' . $device->topic . "/"
. $device->friendlyName . "/"
. $propertyObject["name"] ."/value" . '"'
. ' min="' . $propertyObject["value_min"] . '"'
. ' max="' . $propertyObject["value_max"] . '"'
. $step
. ' value="' . $value . '">' . $unit . EOL;
$formHTML .= '<input type="range" id="' . $device->topic . "/" . $device->friendlyName . "/" . $propertyObject["name"] . '"';
$formHTML .= ' name="' . $propertyObject["name"] . '"'; $formHTML .= ' name="' . $propertyObject["name"] . '"';
$formHTML .= ' min="' . $propertyObject["value_min"] . '"'; $formHTML .= ' min="' . $propertyObject["value_min"] . '"';
$formHTML .= ' max="' . $propertyObject["value_max"] . '"'; $formHTML .= ' max="' . $propertyObject["value_max"] . '"';
$formHTML .= ' value="' . $propertyObject["value"] . '"'; $formHTML .= ' value="' . $propertyObject["value"] . '"';
$formHTML .= $step;
if (array_key_exists("value_step", $propertyObject)) $formHTML .= " oninput=\"setPropertyValue('" . $device->topic . "', '" . $device->friendlyName . "', this.value, '" . $propertyObject["name"] . "')\">";
{
$formHTML .= ' step="' . $propertyObject["value_step"] . '"';
}
$formHTML .= " onchange=\"setPropertyValue('" . $device->topic . "', '" . $device->friendlyName . "', this.value, '" . $propertyObject["name"] . "')\">";
break; break;
case "enum": case "enum":
logger(DEBUG, _("type is enum"), __FILE__ . ":" . __LINE__); logger(DEBUG, _("type is enum"), __FILE__ . ":" . __LINE__);
$formHTML = bool2string($value);
$choice = $propertyObject["values"]; $choice = $propertyObject["values"];
$formHTML = mkHTML($device, $propertyName, $choice); $formHTML .= mkHTML($device, $propertyName, $choice);
break; break;
default:
logger(DEBUG, "type of property not recognized:" . $propertyObject["type"] , __FILE__ . ":" . __LINE__);
} }
return $formHTML; return $formHTML;
} }
function mkHTML($device, $propertyName, $choice) function mkHTML($device, $propertyName, $choice)
{ {
global $listenPort, $httpServerIp;
$html = ""; $html = "";
logger(DEBUG, _("function mkHTML"), __FILE__ . ":" . __LINE__); logger(DEBUG, "function mkHTML", __FILE__ . ":" . __LINE__);
foreach ($choice as $key => $value) foreach ($choice as $key => $value)
{ {
$html .= '<input type="button" id="' . $device->topic ."/" . $device->friendlyName . "/" . $propertyName . "/" . $key . '" value="' . $value . "\" onmouseup=\"setPropertyValue('" . $device->topic . "', '" . $device->friendlyName . "', '" . $value . "', '" . $propertyName . "')\">"; $html .= '<input type="button" id="' . $device->topic ."/" . $device->friendlyName . "/" . $propertyName . "/" . $key . '" value="' . $value . "\" onmouseup=\"setPropertyValue('" . $device->topic . "', '" . $device->friendlyName . "', '" . $value . "', '" . $propertyName . "')\">";
@ -205,13 +228,14 @@ function webBrowse($socket, $argList, $page="/browse")
function displayProperty($device, $key, $value, $response) function displayProperty($device, $key, $value, $response)
{ {
$tab="";
$response .= $key . "&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"; $response .= $key . "&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;";
if (array_key_exists("access", $value)) if (array_key_exists("access", $value))
{ {
if(($value["access"] & 2)) if(($value["access"] & 2))
{ {
logger(DEBUG, _("Write Access OK ") . ($value["access"] & 2), __FILE__ . ":" . __LINE__); logger(DEBUG, _("Write Access OK: ") . ($value["access"] & 2) . "value:" . $value["value"], __FILE__ . ":" . __LINE__);
$response .= displayChoice($device, $key); $response .= displayChoice($device, $key, $value["value"]);
} }
if(($value["access"] & 4)) if(($value["access"] & 4))
{ {
@ -276,8 +300,11 @@ function webGet($argList)
$response = sprintf(_('"%s" or "%s" does not exists'), $argList["topic"], $argList["fn"]); $response = sprintf(_('"%s" or "%s" does not exists'), $argList["topic"], $argList["fn"]);
}else }else
{ {
logger(DEBUG, _("Getting "), __FILE__ . ":" . __LINE__ );
$property = $argList["property"]; $property = $argList["property"];
$response = "GET: " . bool2string($device->$property["value"]); $response = "Sending GET command for: " . $argList["topic"] . $argList["fn"];
$payload = array($argList["property"] => "");
publish($argList["topic"] . "/" . $argList["fn"], $payload, "get");
} }
} }
return $response; return $response;
@ -301,7 +328,7 @@ function webSet($argList)
{ {
$response = "setting property " . $argList["property"] . " of " . $argList["fn"] . " to value: " . $argList["value"]; $response = "setting property " . $argList["property"] . " of " . $argList["fn"] . " to value: " . $argList["value"];
$payload = array($argList["property"] => $argList["value"]); $payload = array($argList["property"] => $argList["value"]);
publish(Z2M . "/" . $argList["fn"], $payload); publish($argList["topic"] . "/" . $argList["fn"], $payload);
//removeEvent($indexFriendlyName($argList["fn"]), $argList["property"], "OFF"); //removeEvent($indexFriendlyName($argList["fn"]), $argList["property"], "OFF");
} }
return $response; return $response;

125
webserver/display_stats.php Normal file
View File

@ -0,0 +1,125 @@
<?php
/****************************************************************/
/* */
/*need device ieeeAddress, property, startDate and finalDate */
/* */
/****************************************************************/
function displayStats($socket, $argList)
{
global $indexFriendlyNames;
// Validation of the dates
if (validateDate($argList["startDate"]) && validateDate($argList["finalDate"]))
{
$query = "SELECT date, value FROM logs WHERE device='" . indexFriendlyNames[$argList->device] . "' AND property='" . $$argList["property"] . "' AND '" . $argList["startDate"] . ">= date AND '" . $argList["finalDate"] . "' <= date";
if(!$this->result = $this->query($query))
{
logger(ERROR, _("mysql query errror: ") . $this->error, __FILE__ . ":" . __LINE__);
}
$datas = $this->result->fetch_all(MYSQLI_ASSOC);
diagramDisplay($datas);
}else
{
htmlSend($socket, _("Dates are not of the form: YYYY-MM-DD"));
}
}
/************************************************************/
/* $datas => array of datas to display {date,value} */
/* $ndata => n datas to display */
/* $min => minimal value to display */
/* $max => maximal value to dispaly */
/************************************************************/
function diagramDisplay($datas)
{
global $months;
$ndata = count($datas);
$min = min($datas);
$max = max($datas);
//Type mime de l'image
//Chemin vers le police à utiliser
$font_file = '/usr/share/fonts/TTF/dejavu/DejaVuSans.ttf';
//Adapter la largeur de l'image avec le nombre de donnée
$largeur = $i * 50 + 90;
$hauteur = 400;
//Hauteur de l'abscisse par rapport au bas de l'image
$absis = 80;
//Création de l'image
$courbe = imagecreatetruecolor($largeur, $hauteur);
//Allouer les couleurs à utiliser
$bleu = imagecolorallocate($courbe, 0, 0, 255);
$ligne = imagecolorallocate($courbe, 220, 220, 220);
$fond = imagecolorallocate($courbe, 250, 250, 250);
$noir = imagecolorallocate($courbe, 0, 0, 0);
$rouge = imagecolorallocate($courbe, 255, 0, 0);
//Colorier le fond
imagefilledrectangle($courbe,0 , 0, $largeur, $hauteur, $fond);
//Tracer l'axe des abscisses
imageline($courbe, 50, $hauteur - $absis, $largeur - 10, $hauteur - $absis, $noir);
//Tracer l'axe des ordonnées
imageline($courbe, 50, $hauteur - $absis, 50, 20, $noir);
//Decaler 10px vers le haut le si le minimum est différent de 0
if($min != 0)
{
$absis += 10;
$a = 10;
}
//Nombres des grides verticales
$nbOrdonne = 10;
//Calcul de l'echelle des abscisses
$echelleX = ($largeur - 100) / $i;
//Calcul de l'echelle des ordonnees
$echelleY = ($hauteur - $absis - 20) / $nbOrdonne;
$i = $min;
//Calcul des ordonnees des grides
$py = ($max - $min) / $nbOrdonne;
$pasY = $absis;
while( $pasY < ($hauteur - 19))
{
//Affiche la valeur de l'ordonnee
imagestring($courbe, 2, 10 , $hauteur - $pasY - 6, round($i), $noir);
//Trace la gride
imageline($courbe, 50, $hauteur - $pasY, $largeur - 20, $hauteur - $pasY, $ligne);
//Decaller vers le haut pour la prochaine gride
$pasY += $echelleY;
//Valeur de l'ordonnee suivante
$i += $py;
}
$j = -1;
$pasX = 90;
//Parcourir le tableau pour le traçage de la diagramme
foreach ($datas as $mois => $quantite)
{
//calculer la hateur du point par rapport à sa valeur
$y = ($hauteur) - (($quantite - $min) * ($echelleY / $py)) - $absis;
//dessiner le point
imagefilledellipse($courbe, $pasX, $y, 6, 6, $rouge);
//Afficher le mois en français avec une inclinaison de 315°
imagefttext($courbe, 10, 315, $pasX, $hauteur - $absis + 20, $noir, $font_file, $months[$mois-1]);
//Tacer une ligne veticale de l'axe de l'abscisse vers le point
imageline($courbe, $pasX, $hauteur - $absis + $a, $pasX, $y, $noir);
if($j!==-1)
{
//liée le point actuel avec la précédente
imageline($courbe, ($pasX - $echelleX), $yprev, $pasX, $y, $noir);
}
//Afficher la valeur au dessus du point
imagestring($courbe, 2, $pasX - 15, $y - 14, $quantite, $bleu);
$j = $quantite;
//enregister la hauteur du point actuel pour la liaison avec la suivante
$yprev = $y;
//Decaller l'abscisse suivante par rapport à son echelle
$pasX +=$echelleX;
}
//Envoyer le flux de l'image
imagepng($courbe);
//Desallouer le memoire utiliser par l'image
imagedestroy($courbe);
}
?>

View File

@ -6,6 +6,7 @@ return '<script language="javascript">
<!-- <!--
function setPropertyValue(topic, fn, value, property) function setPropertyValue(topic, fn, value, property)
{ {
document.getElementById(topic+"/"+fn+"/"+property+"/value").value = value;
let xhr = new XMLHttpRequest(); let xhr = new XMLHttpRequest();
xhr.open("GET", "http://192.168.1.253:' . $listenPort . '/set&fn="+fn+"&property="+property+"&topic="+topic+"&value="+value); xhr.open("GET", "http://192.168.1.253:' . $listenPort . '/set&fn="+fn+"&property="+property+"&topic="+topic+"&value="+value);
xhr.onload = function () {}; xhr.onload = function () {};

View File

@ -10,11 +10,17 @@ $error_code = null;
$listenHost = "0.0.0.0"; $listenHost = "0.0.0.0";
$listenPort = 1025; $listenPort = 1025;
$Dashboards = array(); $Dashboards = array();
for ($m=1; $m<=12; $m++)
{
$months[$m] = date('F', mktime(0,0,0,$m, 1));
}
require_once $configDir . "/aliases.php"; require_once $configDir . "/aliases.php";
require_once $configDir . "/dashboard_conf.php"; require_once $configDir . "/dashboard_conf.php";
require_once "class/main.php"; require_once "class/main.php";
require_once "webserver/cmd_functions.php"; require_once "webserver/cmd_functions.php";
//require_once "webserver/display_stats.php";
// opening listening server // opening listening server
$socket = stream_socket_server("tcp://" . $listenHost . ":" . $listenPort, $error_code, $error_message) or logger(ERROR, _("Could not create socket"), __FILE__ . ":" . __LINE__); $socket = stream_socket_server("tcp://" . $listenHost . ":" . $listenPort, $error_code, $error_message) or logger(ERROR, _("Could not create socket"), __FILE__ . ":" . __LINE__);
@ -27,7 +33,15 @@ function htmlSend($socket, $text, $meta="")
"Date: " . date("r") . EOLR . "Date: " . date("r") . EOLR .
"Connection: close" . EOLR . "Connection: close" . EOLR .
"Content-Type: text/html; charset=UTF-8" . EOLR . EOLR; "Content-Type: text/html; charset=UTF-8" . EOLR . EOLR;
$response = $httpHeader . '<!doctype html>' . EOL . '<html lang="fr">' . EOL . '<head>' . EOL . $meta . EOL . '<meta charset="utf-8">' . EOL . '<title>Moha</title>' . EOL . '</head><body>' . EOL . $text . "</body></html>"; $response = $httpHeader
. '<!doctype html>' . EOL
. '<html lang="fr">' . EOL
. '<head>' . EOL
. $meta . EOL
. '<meta charset="utf-8">' . EOL
. '<title>Moha</title>' . EOL
. '</head><body>' . EOL
. $text . "</body></html>";
stream_socket_sendto($socket, $response); stream_socket_sendto($socket, $response);
} }
@ -102,7 +116,10 @@ function askWebServer($read)
break; break;
case "type": case "type":
logger(DEBUG, $command . _(" reached"), __FILE__ . ":" . __LINE__); logger(DEBUG, $command . _(" reached"), __FILE__ . ":" . __LINE__);
htmlSend($spawn, webDisplayByType($argList)); //htmlSend($spawn, webDisplayByType($argList));
case "stat":
logger(DEBUG, $command . _(" reached"), __FILE__ . ":" . __LINE__);
htmlSend($spawn, displayStats($argList));
default: default:
if (is_numeric(array_key_first($argList))) if (is_numeric(array_key_first($argList)))
{ {