Compare commits

...

7 Commits

11 changed files with 679 additions and 899 deletions

View File

@ -15,15 +15,15 @@
} }
}, },
"require": { "require": {
"php": ">=7.4.0", "php": ">=8.2",
"ext-json": "*", "ext-json": "*",
"ext-mbstring": "*", "ext-mbstring": "*",
"ext-rrd": "*", "ext-rrd": "*",
"phpmailer/phpmailer": "^6.4", "phpmailer/phpmailer": "^6.9",
"twig/twig": "^3.3" "twig/twig": "^3.8"
}, },
"require-dev": { "require-dev": {
"friendsofphp/php-cs-fixer": "^3.0" "friendsofphp/php-cs-fixer": "^3.48"
}, },
"license": "MIT", "license": "MIT",
"authors": [ "authors": [

1330
composer.lock generated

File diff suppressed because it is too large Load Diff

View File

@ -1,5 +1,5 @@
body { body {
margin: 2em 1em 2em 70px; margin: 2em 1em 0 3em;
color: black; color: black;
background: white; background: white;
background-position: top left; background-position: top left;
@ -9,19 +9,19 @@ body {
text-align: center; text-align: center;
} }
th.requirement { background-color: #ff66ff; color: black; } h1 { text-align: center; }
h2, h3, h4, h5, h6 { text-align: left; }
h1 { color: black; font: 120% sans-serif; font-weight: bold; }
h2 { color: #005A9C; font: 110%; font-weight: medium; }
h3 { color: #001A4C; font: 105% sans-serif; font-weight: medium; }
h4 { color: #007A9C; font: 90% sans-serif; font-weight: medium; }
h5 { color: #005A9C; font: italic 80% sans-serif; }
h6 { font: small-caps 70% sans-serif; }
h1 {text-align: center} img { width: auto; height: auto; max-width: 100%; max-height: 100%; }
h2, h3, h4, h5, h6 { text-align: left }
h1 { color: black; font: 120% sans-serif; font-weight: bold} main { display: flex; flex-wrap: wrap; }
h2 { color: #005A9C; font: 110%; font-weight: medium} main div.graph { margin: 5px auto; }
h3 { color: #001A4C; font: 105% sans-serif; font-weight: medium} main div.range-select span { color: blue; text-decoration: underline; cursor: pointer; }
h4 { color: #007A9C; font: 90% sans-serif; font-weight: medium}
h5 { color: #005A9C; font: italic 80% sans-serif }
h6 { font: small-caps 70% sans-serif }
pre {
background-color: lightcyan;
text-color: black;
}

View File

@ -1,33 +1,72 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <!doctype html>
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="ja" lang="ja"> <html lang="en">
<head> <head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8" /> <meta charset="utf-8">
<meta http-equiv="content-language" content="ja" /> <title>C407 Server Room Temperature</title>
<meta http-equiv="Content-Stype-Type" content="text/css" /> <meta name="description" content="C407 Server Room Temperature">
<meta http-equiv="Content-Script-Type" content="text/javascript" /> <meta name="author" content="Neuroinformatics Unit, RIKEN CBS">
<meta http-equiv="refresh" content="60" /> <meta name="viewport" content="width=device-width,initial-scale=1">
<link rel="stylesheet" type="text/css" href="css/default.css" /> <meta http-equiv="refresh" content="300">
<title>C407 Server Room Temperature</title> <link rel="stylesheet" href="css/default.css">
</head> </head>
<body> <body>
<h1>C407 Server Room Temperature</h1> <h1>C407 Server Room Temperature</h1>
<table> <main>
<tbody> <div class="graph">
<tr> <div class="range-select">
<td><img src="./images/graph-hour.png" alt="Hourly Graph" /></td> Hour:
<td><img src="./images/graph-day.png" alt="Daily Graph" /></td> <span onclick="changeGraph('g1', 'hour', 1)">1</span> ...
</tr> <span onclick="changeGraph('g1', 'hour', 3)">3</span> ...
<tr> <span onclick="changeGraph('g1', 'hour', 6)">6</span> ...
<td><img src="./images/graph-week.png" alt="Weekly Graph" /></td> <span onclick="changeGraph('g1', 'hour', 12)">12</span>
<td><img src="./images/graph-month.png" alt="Monthly Graph" /></td> </div>
</tr> <div><img id="g1" src="./images/graph-hour.png" alt="Hourly Graph" /></div>
<tr> </div>
<td><img src="./images/graph-year.png" alt="Yearly Graph" /></td> <div class="graph">
<td><img src="./images/graph-3year.png" alt="3 Years Graph" /></td> <div class="range-select">
</tr> Day:
</tbody> <span onclick="changeGraph('g2', 'day', 1)">1</span> ...
</table> <span onclick="changeGraph('g2', 'day', 3)">3</span>
</div>
<div><img id="g2" src="./images/graph-day.png" alt="Daily Graph" /></div>
</div>
<div class="graph">
<div class="range-select">
Week:
<span onclick="changeGraph('g3', 'week', 1)">1</span> ...
<span onclick="changeGraph('g3', 'week', 2)">2</span>
</div>
<div><img id="g3" src="./images/graph-week.png" alt="Weekly Graph" /></div>
</div>
<div class="graph">
<div class="range-select">
Month:
<span onclick="changeGraph('g4', 'month', 1)">1</span> ...
<span onclick="changeGraph('g4', 'month', 3)">3</span> ...
<span onclick="changeGraph('g4', 'month', 6)">6</span>
</div>
<div><img id="g4" src="./images/graph-month.png" alt="Monthly Graph" /></div>
</div>
<div class="graph">
<div class="range-select">
Year:
<span onclick="changeGraph('g5', 'year', 1)">1</span> ...
<span onclick="changeGraph('g5', 'year', 3)">3</span> ...
<span onclick="changeGraph('g5', 'year', 5)">5</span> ...
<span onclick="changeGraph('g5', 'year', 10)">10</span>
</div>
<div><img id="g5" src="./images/graph-year.png" alt="Yearly Graph" /></div>
</div>
</main>
<script>
function changeGraph(id, type, num) {
const img = document.getElementById(id);
if (img) {
img.src = './images/graph-' + (num === 1 ? '' : num) + type + '.png';
}
}
</script>
</body> </body>
</html> </html>

View File

@ -58,8 +58,6 @@ class Address
/** /**
* check wheter string is email. * check wheter string is email.
* *
* @param string $text email
*
* @return bool false if not email string * @return bool false if not email string
*/ */
public function validateEmail(string $email): bool public function validateEmail(string $email): bool

View File

@ -9,7 +9,6 @@ class UTF8_Mailer
/** /**
* send mail. * send mail.
* *
* @param Address $form from email address
* @param array $tos to email addresses * @param array $tos to email addresses
* @param string $subject subject * @param string $subject subject
* @param string $body mail body * @param string $body mail body

View File

@ -112,8 +112,8 @@ class Temperature
$options = [ $options = [
'--step', '60', // 1min step '--step', '60', // 1min step
sprintf('DS:%s:GAUGE:600:0:100', $id), // 10min hartbeat sprintf('DS:%s:GAUGE:600:0:100', $id), // 10min hartbeat
'RRA:LAST:0.5:1:1440', // last/m - 1day(1440min) 'RRA:LAST:0.5:1:10080', // last/m - 7day(10080min)
'RRA:LAST:0.5:30:52560', // last/30m - 3years(365day=30min*17520)*3 'RRA:LAST:0.5:30:175200', // last/30m - 10years(365day=30min*17520)*10
]; ];
return rrd_create($fpath, $options); return rrd_create($fpath, $options);
@ -135,21 +135,22 @@ class Temperature
* output graph. * output graph.
* *
* @param string $type output graph type * @param string $type output graph type
* @param int $num output period of graph type
* @param string $fpath output image file path * @param string $fpath output image file path
* *
* @return bool false if failure * @return bool false if failure
*/ */
public function outputGraph(string $type, string $fpath): bool public function outputGraph(string $type, int $num, string $fpath): bool
{ {
static $colors = [ static $colors = [
'#FF0000', '#00FF00', '#0000FF', '#FFFF00', '#00FFFF', '#FF00FF', '#FF0000', '#00FF00', '#0000FF', '#FFFF00', '#00FFFF', '#FF00FF',
'#FF9999', '#99FF99', '#9999FF', '#FFFF99', '#99FFFF', '#FF99FF', '#FF9999', '#99FF99', '#9999FF', '#FFFF99', '#99FFFF', '#FF99FF',
]; ];
static $types = ['hour', 'day', 'week', 'month', 'year', '3year']; static $types = ['hour', 'day', 'week', 'month', 'year'];
if (!in_array($type, $types)) { if (!in_array($type, $types)) {
return false; return false;
} }
$start = '3year' == $type ? '-3year' : '-1'.$type; $start = sprintf('-%u%s', $num, $type);
$options = [ $options = [
'--imgformat', 'PNG', '--imgformat', 'PNG',
'--lower-limit', '10', '--lower-limit', '10',
@ -160,7 +161,7 @@ class Temperature
'--height', '200', '--height', '200',
'--units-exponent', '0', '--units-exponent', '0',
'--vertical-label', "Temperature [\xc2\xb0C]", '--vertical-label', "Temperature [\xc2\xb0C]",
'--title', 'Server Room Temperature - by '.$type, '--title', 'Server Room Temperature - by '.$num.$type.'(s)',
]; ];
$idlen = 0; $idlen = 0;
foreach ($this->sensorIds as $key => $id) { foreach ($this->sensorIds as $key => $id) {

View File

@ -6,8 +6,8 @@ require_once APPDIR.'/vendor/autoload.php';
$config = json_decode(file_get_contents(APPDIR.'/etc/config.json'), true); $config = json_decode(file_get_contents(APPDIR.'/etc/config.json'), true);
$digitemp = new \Orrisroot\DigiTemp($config['digitemp'], APPDIR.'/'.$config['digitemp_config']); $digitemp = new Orrisroot\DigiTemp($config['digitemp'], APPDIR.'/'.$config['digitemp_config']);
$rrdtemp = new \Orrisroot\Rrd\Temperature(APPDIR.'/'.$config['database_dir']); $rrdtemp = new Orrisroot\Rrd\Temperature(APPDIR.'/'.$config['database_dir']);
$num = $digitemp->getNumSensors(); $num = $digitemp->getNumSensors();
$sensors = []; $sensors = [];
for ($i = 0; $i < $num; ++$i) { for ($i = 0; $i < $num; ++$i) {
@ -29,8 +29,8 @@ if ($do_send) {
$from_name = $config['mail_from_name']; $from_name = $config['mail_from_name'];
$to = $config['mail_alert_to']; $to = $config['mail_alert_to'];
$subject = $config['mail_alert_subject']; $subject = $config['mail_alert_subject'];
$loader = new \Twig\Loader\FilesystemLoader(APPDIR.'/'.$config['templates_dir']); $loader = new Twig\Loader\FilesystemLoader(APPDIR.'/'.$config['templates_dir']);
$twig = new \Twig\Environment($loader); $twig = new Twig\Environment($loader);
$data = [ $data = [
'range' => [ 'range' => [
'upper' => $upper, 'upper' => $upper,
@ -45,7 +45,7 @@ if ($do_send) {
]; ];
$body = $twig->render($config['mail_alert_template'], $data); $body = $twig->render($config['mail_alert_template'], $data);
$from = new \Orrisroot\Mail\Address($from_name, $from); $from = new Orrisroot\Mail\Address($from_name, $from);
$tos = [new \Orrisroot\Mail\Address($to, $to)]; $tos = [new Orrisroot\Mail\Address($to, $to)];
\Orrisroot\Mail\UTF8_Mailer::sendMail($from, $tos, $subject, $body); Orrisroot\Mail\UTF8_Mailer::sendMail($from, $tos, $subject, $body);
} }

View File

@ -6,8 +6,8 @@ require_once APPDIR.'/vendor/autoload.php';
$config = json_decode(file_get_contents(APPDIR.'/etc/config.json'), true); $config = json_decode(file_get_contents(APPDIR.'/etc/config.json'), true);
$digitemp = new \Orrisroot\DigiTemp($config['digitemp'], APPDIR.'/'.$config['digitemp_config']); $digitemp = new Orrisroot\DigiTemp($config['digitemp'], APPDIR.'/'.$config['digitemp_config']);
$rrdtemp = new \Orrisroot\Rrd\Temperature(APPDIR.'/'.$config['database_dir']); $rrdtemp = new Orrisroot\Rrd\Temperature(APPDIR.'/'.$config['database_dir']);
$num = $digitemp->getNumSensors(); $num = $digitemp->getNumSensors();
$sensors = []; $sensors = [];
for ($i = 0; $i < $num; ++$i) { for ($i = 0; $i < $num; ++$i) {
@ -20,8 +20,8 @@ $from = $config['mail_from'];
$from_name = $config['mail_from_name']; $from_name = $config['mail_from_name'];
$to = $config['mail_info_to']; $to = $config['mail_info_to'];
$subject = $config['mail_info_subject']; $subject = $config['mail_info_subject'];
$loader = new \Twig\Loader\FilesystemLoader(APPDIR.'/'.$config['templates_dir']); $loader = new Twig\Loader\FilesystemLoader(APPDIR.'/'.$config['templates_dir']);
$twig = new \Twig\Environment($loader); $twig = new Twig\Environment($loader);
$data = [ $data = [
'from' => [ 'from' => [
'name' => $from_name, 'name' => $from_name,
@ -32,6 +32,6 @@ $data = [
]; ];
$body = $twig->render($config['mail_info_template'], $data); $body = $twig->render($config['mail_info_template'], $data);
$from = new \Orrisroot\Mail\Address($from_name, $from); $from = new Orrisroot\Mail\Address($from_name, $from);
$tos = [new \Orrisroot\Mail\Address($to, $to)]; $tos = [new Orrisroot\Mail\Address($to, $to)];
\Orrisroot\Mail\UTF8_Mailer::sendMail($from, $tos, $subject, $body); Orrisroot\Mail\UTF8_Mailer::sendMail($from, $tos, $subject, $body);

View File

@ -6,8 +6,8 @@ require_once APPDIR.'/vendor/autoload.php';
$config = json_decode(file_get_contents(APPDIR.'/etc/config.json'), true); $config = json_decode(file_get_contents(APPDIR.'/etc/config.json'), true);
$digitemp = new \Orrisroot\DigiTemp($config['digitemp'], APPDIR.'/'.$config['digitemp_config']); $digitemp = new Orrisroot\DigiTemp($config['digitemp'], APPDIR.'/'.$config['digitemp_config']);
$rrdtemp = new \Orrisroot\Rrd\Temperature(APPDIR.'/'.$config['database_dir']); $rrdtemp = new Orrisroot\Rrd\Temperature(APPDIR.'/'.$config['database_dir']);
$num = $digitemp->getNumSensors(); $num = $digitemp->getNumSensors();
for ($i = 0; $i < $num; ++$i) { for ($i = 0; $i < $num; ++$i) {
$id = $digitemp->getSensorId($i); $id = $digitemp->getSensorId($i);
@ -16,7 +16,16 @@ for ($i = 0; $i < $num; ++$i) {
$now = time(); $now = time();
$rrdtemp->update($id, $now, $value); $rrdtemp->update($id, $now, $value);
} }
foreach ($types = ['hour', 'day', 'week', 'month', 'year', '3year'] as $type) { $types = [
$fpath = APPDIR.'/'.$config['images_dir'].'/graph-'.$type.'.png'; 'hour' => [1, 3, 6, 12],
$rrdtemp->outputGraph($type, $fpath); 'day' => [1, 3],
'week' => [1, 2],
'month' => [1, 3, 6],
'year' => [1, 3, 5, 10],
];
foreach ($types as $type => $nums) {
foreach ($nums as $num) {
$fpath = APPDIR.'/'.$config['images_dir'].'/graph-'.(1 === $num ? '' : $num).$type.'.png';
$rrdtemp->outputGraph($type, $num, $fpath);
}
} }