Compare commits

...

7 Commits

11 changed files with 679 additions and 899 deletions

View File

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

1330
composer.lock generated

File diff suppressed because it is too large Load Diff

View File

@ -1,5 +1,5 @@
body {
margin: 2em 1em 2em 70px;
margin: 2em 1em 0 3em;
color: black;
background: white;
background-position: top left;
@ -9,19 +9,19 @@ body {
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}
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 }
img { width: auto; height: auto; max-width: 100%; max-height: 100%; }
main { display: flex; flex-wrap: wrap; }
main div.graph { margin: 5px auto; }
main div.range-select span { color: blue; text-decoration: underline; cursor: pointer; }
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">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="ja" lang="ja">
<!doctype html>
<html lang="en">
<head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8" />
<meta http-equiv="content-language" content="ja" />
<meta http-equiv="Content-Stype-Type" content="text/css" />
<meta http-equiv="Content-Script-Type" content="text/javascript" />
<meta http-equiv="refresh" content="60" />
<link rel="stylesheet" type="text/css" href="css/default.css" />
<title>C407 Server Room Temperature</title>
<meta charset="utf-8">
<title>C407 Server Room Temperature</title>
<meta name="description" content="C407 Server Room Temperature">
<meta name="author" content="Neuroinformatics Unit, RIKEN CBS">
<meta name="viewport" content="width=device-width,initial-scale=1">
<meta http-equiv="refresh" content="300">
<link rel="stylesheet" href="css/default.css">
</head>
<body>
<h1>C407 Server Room Temperature</h1>
<table>
<tbody>
<tr>
<td><img src="./images/graph-hour.png" alt="Hourly Graph" /></td>
<td><img src="./images/graph-day.png" alt="Daily Graph" /></td>
</tr>
<tr>
<td><img src="./images/graph-week.png" alt="Weekly Graph" /></td>
<td><img src="./images/graph-month.png" alt="Monthly Graph" /></td>
</tr>
<tr>
<td><img src="./images/graph-year.png" alt="Yearly Graph" /></td>
<td><img src="./images/graph-3year.png" alt="3 Years Graph" /></td>
</tr>
</tbody>
</table>
<main>
<div class="graph">
<div class="range-select">
Hour:
<span onclick="changeGraph('g1', 'hour', 1)">1</span> ...
<span onclick="changeGraph('g1', 'hour', 3)">3</span> ...
<span onclick="changeGraph('g1', 'hour', 6)">6</span> ...
<span onclick="changeGraph('g1', 'hour', 12)">12</span>
</div>
<div><img id="g1" src="./images/graph-hour.png" alt="Hourly Graph" /></div>
</div>
<div class="graph">
<div class="range-select">
Day:
<span onclick="changeGraph('g2', 'day', 1)">1</span> ...
<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>
</html>

View File

@ -97,32 +97,32 @@ class DigiTemp
$key = array_shift($cols);
$value = array_shift($cols);
switch ($key) {
case 'TTY':
$this->config[$key] = $value;
break;
case 'READ_TIME':
$this->config[$key] = (int) $value;
break;
case 'LOG_TYPE':
$this->config[$key] = (int) $value;
break;
case 'LOG_FORMAT':
$this->config[$key] = '"' === substr($value, 0, 1) ? stripslashes(substr($value, 1, -1)) : $value;
break;
case 'CNT_FORMAT':
$this->config[$key] = '"' === substr($value, 0, 1) ? stripslashes(substr($value, 1, -1)) : $value;
break;
case 'HUM_FORMAT':
$this->config[$key] = '"' === substr($value, 0, 1) ? stripslashes(substr($value, 1, -1)) : $value;
break;
case 'SENSORS':
$this->config[$key] = (int) $value;
break;
case 'ROM':
$this->config[$key][(int) $value] = str_replace('0x', '', implode('', array_reverse($cols)));
break;
default:
return false;
case 'TTY':
$this->config[$key] = $value;
break;
case 'READ_TIME':
$this->config[$key] = (int) $value;
break;
case 'LOG_TYPE':
$this->config[$key] = (int) $value;
break;
case 'LOG_FORMAT':
$this->config[$key] = '"' === substr($value, 0, 1) ? stripslashes(substr($value, 1, -1)) : $value;
break;
case 'CNT_FORMAT':
$this->config[$key] = '"' === substr($value, 0, 1) ? stripslashes(substr($value, 1, -1)) : $value;
break;
case 'HUM_FORMAT':
$this->config[$key] = '"' === substr($value, 0, 1) ? stripslashes(substr($value, 1, -1)) : $value;
break;
case 'SENSORS':
$this->config[$key] = (int) $value;
break;
case 'ROM':
$this->config[$key][(int) $value] = str_replace('0x', '', implode('', array_reverse($cols)));
break;
default:
return false;
}
}

View File

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

View File

@ -9,10 +9,9 @@ class UTF8_Mailer
/**
* send mail.
*
* @param Address $form from email address
* @param array $tos to email addresses
* @param string $subject subject
* @param string $body mail body
* @param array $tos to email addresses
* @param string $subject subject
* @param string $body mail body
*
* @return bool false if failure
*/

View File

@ -112,8 +112,8 @@ class Temperature
$options = [
'--step', '60', // 1min step
sprintf('DS:%s:GAUGE:600:0:100', $id), // 10min hartbeat
'RRA:LAST:0.5:1:1440', // last/m - 1day(1440min)
'RRA:LAST:0.5:30:52560', // last/30m - 3years(365day=30min*17520)*3
'RRA:LAST:0.5:1:10080', // last/m - 7day(10080min)
'RRA:LAST:0.5:30:175200', // last/30m - 10years(365day=30min*17520)*10
];
return rrd_create($fpath, $options);
@ -135,21 +135,22 @@ class Temperature
* output graph.
*
* @param string $type output graph type
* @param int $num output period of graph type
* @param string $fpath output image file path
*
* @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 = [
'#FF0000', '#00FF00', '#0000FF', '#FFFF00', '#00FFFF', '#FF00FF',
'#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)) {
return false;
}
$start = '3year' == $type ? '-3year' : '-1'.$type;
$start = sprintf('-%u%s', $num, $type);
$options = [
'--imgformat', 'PNG',
'--lower-limit', '10',
@ -160,7 +161,7 @@ class Temperature
'--height', '200',
'--units-exponent', '0',
'--vertical-label', "Temperature [\xc2\xb0C]",
'--title', 'Server Room Temperature - by '.$type,
'--title', 'Server Room Temperature - by '.$num.$type.'(s)',
];
$idlen = 0;
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);
$digitemp = new \Orrisroot\DigiTemp($config['digitemp'], APPDIR.'/'.$config['digitemp_config']);
$rrdtemp = new \Orrisroot\Rrd\Temperature(APPDIR.'/'.$config['database_dir']);
$digitemp = new Orrisroot\DigiTemp($config['digitemp'], APPDIR.'/'.$config['digitemp_config']);
$rrdtemp = new Orrisroot\Rrd\Temperature(APPDIR.'/'.$config['database_dir']);
$num = $digitemp->getNumSensors();
$sensors = [];
for ($i = 0; $i < $num; ++$i) {
@ -29,8 +29,8 @@ if ($do_send) {
$from_name = $config['mail_from_name'];
$to = $config['mail_alert_to'];
$subject = $config['mail_alert_subject'];
$loader = new \Twig\Loader\FilesystemLoader(APPDIR.'/'.$config['templates_dir']);
$twig = new \Twig\Environment($loader);
$loader = new Twig\Loader\FilesystemLoader(APPDIR.'/'.$config['templates_dir']);
$twig = new Twig\Environment($loader);
$data = [
'range' => [
'upper' => $upper,
@ -45,7 +45,7 @@ if ($do_send) {
];
$body = $twig->render($config['mail_alert_template'], $data);
$from = new \Orrisroot\Mail\Address($from_name, $from);
$tos = [new \Orrisroot\Mail\Address($to, $to)];
\Orrisroot\Mail\UTF8_Mailer::sendMail($from, $tos, $subject, $body);
$from = new Orrisroot\Mail\Address($from_name, $from);
$tos = [new Orrisroot\Mail\Address($to, $to)];
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);
$digitemp = new \Orrisroot\DigiTemp($config['digitemp'], APPDIR.'/'.$config['digitemp_config']);
$rrdtemp = new \Orrisroot\Rrd\Temperature(APPDIR.'/'.$config['database_dir']);
$digitemp = new Orrisroot\DigiTemp($config['digitemp'], APPDIR.'/'.$config['digitemp_config']);
$rrdtemp = new Orrisroot\Rrd\Temperature(APPDIR.'/'.$config['database_dir']);
$num = $digitemp->getNumSensors();
$sensors = [];
for ($i = 0; $i < $num; ++$i) {
@ -20,8 +20,8 @@ $from = $config['mail_from'];
$from_name = $config['mail_from_name'];
$to = $config['mail_info_to'];
$subject = $config['mail_info_subject'];
$loader = new \Twig\Loader\FilesystemLoader(APPDIR.'/'.$config['templates_dir']);
$twig = new \Twig\Environment($loader);
$loader = new Twig\Loader\FilesystemLoader(APPDIR.'/'.$config['templates_dir']);
$twig = new Twig\Environment($loader);
$data = [
'from' => [
'name' => $from_name,
@ -32,6 +32,6 @@ $data = [
];
$body = $twig->render($config['mail_info_template'], $data);
$from = new \Orrisroot\Mail\Address($from_name, $from);
$tos = [new \Orrisroot\Mail\Address($to, $to)];
\Orrisroot\Mail\UTF8_Mailer::sendMail($from, $tos, $subject, $body);
$from = new Orrisroot\Mail\Address($from_name, $from);
$tos = [new Orrisroot\Mail\Address($to, $to)];
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);
$digitemp = new \Orrisroot\DigiTemp($config['digitemp'], APPDIR.'/'.$config['digitemp_config']);
$rrdtemp = new \Orrisroot\Rrd\Temperature(APPDIR.'/'.$config['database_dir']);
$digitemp = new Orrisroot\DigiTemp($config['digitemp'], APPDIR.'/'.$config['digitemp_config']);
$rrdtemp = new Orrisroot\Rrd\Temperature(APPDIR.'/'.$config['database_dir']);
$num = $digitemp->getNumSensors();
for ($i = 0; $i < $num; ++$i) {
$id = $digitemp->getSensorId($i);
@ -16,7 +16,16 @@ for ($i = 0; $i < $num; ++$i) {
$now = time();
$rrdtemp->update($id, $now, $value);
}
foreach ($types = ['hour', 'day', 'week', 'month', 'year', '3year'] as $type) {
$fpath = APPDIR.'/'.$config['images_dir'].'/graph-'.$type.'.png';
$rrdtemp->outputGraph($type, $fpath);
$types = [
'hour' => [1, 3, 6, 12],
'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);
}
}