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:
2022-03-28 00:40:34 +02:00
parent 80234fc505
commit 0d35b1ff3f
24 changed files with 491 additions and 205 deletions

View File

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

View File

@ -10,11 +10,17 @@ $error_code = null;
$listenHost = "0.0.0.0";
$listenPort = 1025;
$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 . "/dashboard_conf.php";
require_once "class/main.php";
require_once "webserver/cmd_functions.php";
//require_once "webserver/display_stats.php";
// opening listening server
$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 .
"Connection: close" . 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);
}
@ -102,7 +116,10 @@ function askWebServer($read)
break;
case "type":
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:
if (is_numeric(array_key_first($argList)))
{