add initial project files.
This commit is contained in:
commit
b692151385
13
.gitignore
vendored
Normal file
13
.gitignore
vendored
Normal file
@ -0,0 +1,13 @@
|
||||
/vendor
|
||||
|
||||
/db/*.rrd
|
||||
/html/images/graph-*.png
|
||||
|
||||
.php_cs.cache
|
||||
|
||||
*~
|
||||
*.orig
|
||||
*.bak
|
||||
*.tmp
|
||||
.DS_Store
|
||||
Thumbs.db
|
16
.php_cs
Normal file
16
.php_cs
Normal file
@ -0,0 +1,16 @@
|
||||
<?php
|
||||
|
||||
$finder = PhpCsFixer\Finder::create()
|
||||
->exclude('vendor')
|
||||
->in(__DIR__)
|
||||
;
|
||||
|
||||
return PhpCsFixer\Config::create()
|
||||
->setRules([
|
||||
'@Symfony' => true,
|
||||
'@DoctrineAnnotation' => true,
|
||||
'array_indentation' => true,
|
||||
'array_syntax' => ['syntax' => 'short'],
|
||||
])
|
||||
->setFinder($finder)
|
||||
;
|
35
composer.json
Normal file
35
composer.json
Normal file
@ -0,0 +1,35 @@
|
||||
{
|
||||
"name": "niu-admin/temperature",
|
||||
"type": "project",
|
||||
"scripts": {
|
||||
"fix-diff": [
|
||||
"./vendor/bin/php-cs-fixer fix --dry-run --diff"
|
||||
],
|
||||
"fix": [
|
||||
"./vendor/bin/php-cs-fixer fix"
|
||||
]
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Orrisroot\\": "lib/"
|
||||
}
|
||||
},
|
||||
|
||||
"require": {
|
||||
"php": ">=7.4.0",
|
||||
"ext-mbstring": "*",
|
||||
"ext-json": "*",
|
||||
"phpmailer/phpmailer": "^6.1",
|
||||
"twig/twig": "^3.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"friendsofphp/php-cs-fixer": "^2.16"
|
||||
},
|
||||
"license": "MIT",
|
||||
"authors": [
|
||||
{
|
||||
"name": "Yoshihiro OKUMURA",
|
||||
"email": "orrisroot@gmail.com"
|
||||
}
|
||||
]
|
||||
}
|
2132
composer.lock
generated
Normal file
2132
composer.lock
generated
Normal file
File diff suppressed because it is too large
Load Diff
0
db/.gitkeep
Normal file
0
db/.gitkeep
Normal file
18
etc/config.json
Normal file
18
etc/config.json
Normal file
@ -0,0 +1,18 @@
|
||||
{
|
||||
"url": "https://www.ni.riken.jp/temperature/",
|
||||
"digitemp": "/bin/digitemp_DS9097",
|
||||
"digitemp_config": "etc/digitemp.conf",
|
||||
"database_dir": "db",
|
||||
"images_dir": "html/images",
|
||||
"templates_dir": "templates",
|
||||
"mail_alert_upper": 35,
|
||||
"mail_alert_lower": 15,
|
||||
"mail_from": "cbs-is@ml.riken.jp",
|
||||
"mail_from_name": "C407 温度監視プログラム",
|
||||
"mail_info_to": "niu-logs@ml.riken.jp",
|
||||
"mail_info_subject": "C407 温度監視 定期報告",
|
||||
"mail_info_template": "mail_info.twig",
|
||||
"mail_alert_to": "cbs-is@ml.riken.jp",
|
||||
"mail_alert_subject": "C407 温度監視 警告",
|
||||
"mail_alert_template": "mail_alert.twig"
|
||||
}
|
9
etc/crontab
Normal file
9
etc/crontab
Normal file
@ -0,0 +1,9 @@
|
||||
#
|
||||
# Server Room Temperature Monitoring System
|
||||
#
|
||||
# update minutely temperature sensor data
|
||||
* * * * * niu-admin php /data/temperature/sbin/update.php
|
||||
# send daily temperature informations
|
||||
1 12 * * * niu-admin php /data/temperature/sbin/send_info.php
|
||||
# check alert thresholds on every 15 minutes
|
||||
0,15,30,45 * * * * niu-admin php /data/temperature/sbin/check_alert.php
|
9
etc/digitemp.conf
Normal file
9
etc/digitemp.conf
Normal file
@ -0,0 +1,9 @@
|
||||
TTY /dev/ttyS1
|
||||
READ_TIME 1000
|
||||
LOG_TYPE 1
|
||||
LOG_FORMAT "%b %d %H:%M:%S Sensor %s C: %.2C F: %.2F"
|
||||
CNT_FORMAT "%b %d %H:%M:%S Sensor %s #%n %C"
|
||||
HUM_FORMAT "%b %d %H:%M:%S Sensor %s C: %.2C F: %.2F H: %h%%"
|
||||
SENSORS 2
|
||||
ROM 0 0x10 0xF5 0x89 0xB7 0x00 0x08 0x00 0x3B
|
||||
ROM 1 0x10 0xA3 0x85 0xB7 0x00 0x08 0x00 0x86
|
27
html/css/default.css
Normal file
27
html/css/default.css
Normal file
@ -0,0 +1,27 @@
|
||||
body {
|
||||
margin: 2em 1em 2em 70px;
|
||||
color: black;
|
||||
background: white;
|
||||
background-position: top left;
|
||||
background-attachment: fixed;
|
||||
background-repeat: no-repeat;
|
||||
background-image: url(logo.png);
|
||||
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 }
|
||||
|
||||
pre {
|
||||
background-color: lightcyan;
|
||||
text-color: black;
|
||||
}
|
||||
|
BIN
html/css/logo.png
Normal file
BIN
html/css/logo.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 3.1 KiB |
0
html/images/.gitkeep
Normal file
0
html/images/.gitkeep
Normal file
33
html/index.html
Normal file
33
html/index.html
Normal file
@ -0,0 +1,33 @@
|
||||
<!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">
|
||||
<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>C047 Server Room Temperature</title>
|
||||
</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>
|
||||
|
||||
</body>
|
||||
</html>
|
131
lib/DigiTemp.php
Normal file
131
lib/DigiTemp.php
Normal file
@ -0,0 +1,131 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Orrisroot;
|
||||
|
||||
class DigiTemp
|
||||
{
|
||||
/**
|
||||
* @var string digitemp command path
|
||||
*/
|
||||
private string $commandPath;
|
||||
|
||||
/**
|
||||
* @var string config file path
|
||||
*/
|
||||
private string $configPath;
|
||||
|
||||
/**
|
||||
* @var array config data
|
||||
*/
|
||||
private array $config = [
|
||||
'TTY' => '',
|
||||
'READ_TIME' => 0,
|
||||
'LOG_TYPE' => 0,
|
||||
'LOG_FORMAT' => '',
|
||||
'CNT_FORMAT' => '',
|
||||
'HUM_FORMAT' => '',
|
||||
'SENSORS' => 0,
|
||||
'ROM' => [],
|
||||
];
|
||||
|
||||
/**
|
||||
* constructor.
|
||||
*
|
||||
* @param string $commandPath digitemp command path
|
||||
* @param string $configPath config file path
|
||||
*/
|
||||
public function __construct(string $commandPath, string $configPath)
|
||||
{
|
||||
$this->commandPath = $commandPath;
|
||||
$this->configPath = $configPath;
|
||||
$this->parseConfig();
|
||||
}
|
||||
|
||||
/**
|
||||
* get number of sensors.
|
||||
*/
|
||||
public function getNumSensors(): int
|
||||
{
|
||||
return $this->config['SENSORS'];
|
||||
}
|
||||
|
||||
/**
|
||||
* get sensor id.
|
||||
*
|
||||
* @param int $num sensor number
|
||||
*
|
||||
* @return ?string
|
||||
*/
|
||||
public function getSensorId(int $num): ?string
|
||||
{
|
||||
return isset($this->config['ROM'][$num]) ? $this->config['ROM'][$num] : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* read sensor.
|
||||
*
|
||||
* @param int $num sensor number
|
||||
*
|
||||
* @return ?float
|
||||
*/
|
||||
public function readSensor(int $num): ?float
|
||||
{
|
||||
$cmd = escapeshellcmd($this->commandPath.' -c '.$this->configPath.' -q -t '.$num.' -o"%.2C" 2>/dev/null');
|
||||
exec($cmd, $output, $ret);
|
||||
if (0 !== $ret) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (float) $output[0];
|
||||
}
|
||||
|
||||
/**
|
||||
* parse config file.
|
||||
*
|
||||
* @return false if failure
|
||||
*/
|
||||
private function parseConfig(): bool
|
||||
{
|
||||
foreach (file($this->configPath) as $line) {
|
||||
preg_match_all('/"(?:\\\\.|[^\\\\"])*"|\S+/', trim($line), $matches);
|
||||
if (empty($matches[0])) {
|
||||
continue;
|
||||
}
|
||||
$cols = $matches[0];
|
||||
$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;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
69
lib/Mail/Address.php
Normal file
69
lib/Mail/Address.php
Normal file
@ -0,0 +1,69 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Orrisroot\Mail;
|
||||
|
||||
class Address
|
||||
{
|
||||
const EMAIL_REGEX = '[a-zA-Z0-9]+(?:[_\\.\\-][a-zA-Z0-9]+)*@(?:[a-zA-Z0-9]+(?:[\\.\\-][a-zA-Z0-9]+)*)+\\.[a-zA-Z]{2,}';
|
||||
|
||||
/**
|
||||
* @var string name
|
||||
*/
|
||||
private string $name;
|
||||
|
||||
/**
|
||||
* @var string email address
|
||||
*/
|
||||
private string $email;
|
||||
|
||||
/**
|
||||
* constructor.
|
||||
*
|
||||
* @param string $name name
|
||||
* @param string $email email address
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
public function __construct(string $name, string $email)
|
||||
{
|
||||
$this->name = $name;
|
||||
if (!$this->validateEmail($email)) {
|
||||
throw new \Exception('Invalid email address found: '.$email);
|
||||
}
|
||||
$this->email = $email;
|
||||
}
|
||||
|
||||
/**
|
||||
* get name.
|
||||
*
|
||||
* @return string name
|
||||
*/
|
||||
public function getName(): string
|
||||
{
|
||||
return $this->name;
|
||||
}
|
||||
|
||||
/**
|
||||
* get email.
|
||||
*
|
||||
* @return string email
|
||||
*/
|
||||
public function getEmail(): string
|
||||
{
|
||||
return $this->email;
|
||||
}
|
||||
|
||||
/**
|
||||
* check wheter string is email.
|
||||
*
|
||||
* @param string $text email
|
||||
*
|
||||
* @return bool false if not email string
|
||||
*/
|
||||
public function validateEmail(string $email): bool
|
||||
{
|
||||
return false !== preg_match('/^'.self::EMAIL_REGEX.'$/', $email);
|
||||
}
|
||||
}
|
32
lib/Mail/UTF8_Mailer.php
Normal file
32
lib/Mail/UTF8_Mailer.php
Normal file
@ -0,0 +1,32 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Orrisroot\Mail;
|
||||
|
||||
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
|
||||
*
|
||||
* @return bool false if failure
|
||||
*/
|
||||
public static function sendMail(Address $from, array $tos, string $subject, string $body): bool
|
||||
{
|
||||
$mailer = new \PHPMailer\PHPMailer\PHPMailer();
|
||||
$mailer->CharSet = 'UTF-8';
|
||||
$mailer->setFrom($from->getEmail(), $from->getName());
|
||||
$mailer->Subject = $subject;
|
||||
$mailer->Body = $body;
|
||||
foreach ($tos as $to) {
|
||||
$mailer->AddAddress($to->getEmail(), $to->getName());
|
||||
}
|
||||
|
||||
return $mailer->Send();
|
||||
}
|
||||
}
|
188
lib/Rrd/Temperature.php
Normal file
188
lib/Rrd/Temperature.php
Normal file
@ -0,0 +1,188 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Orrisroot\Rrd;
|
||||
|
||||
class Temperature
|
||||
{
|
||||
/**
|
||||
* @var string database directory path
|
||||
*/
|
||||
private string $databasePath;
|
||||
|
||||
/**
|
||||
* @var array sensor ids
|
||||
*/
|
||||
private array $sensorIds;
|
||||
|
||||
/**
|
||||
* constructor.
|
||||
*
|
||||
* @param string $fpath database directory path
|
||||
*/
|
||||
public function __construct(string $fpath)
|
||||
{
|
||||
$this->databasePath = $fpath;
|
||||
$this->sensorIds = [];
|
||||
}
|
||||
|
||||
/**
|
||||
* add sensor.
|
||||
*
|
||||
* @param string $id sensor id
|
||||
*/
|
||||
public function addSensor(string $id)
|
||||
{
|
||||
$this->sensorIds[] = $id;
|
||||
}
|
||||
|
||||
/**
|
||||
* update database.
|
||||
*
|
||||
* @param string $id sensor id
|
||||
* @param int $time timestamp
|
||||
* @param float $value temperature value
|
||||
*
|
||||
* @return bool false if failure
|
||||
*/
|
||||
public function update(string $id, int $time, float $value): bool
|
||||
{
|
||||
$fpath = $this->getFilePath($id);
|
||||
if (!file_exists($fpath)) {
|
||||
if (!$this->_createDatabase($fpath)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
$options = [sprintf('%u:%lf', $time, $value)];
|
||||
|
||||
return rrd_update($fpath, $options);
|
||||
}
|
||||
|
||||
/**
|
||||
* read last data.
|
||||
*
|
||||
* @param string $id sensor id
|
||||
*
|
||||
* @return ?array last data
|
||||
*/
|
||||
public function readLastData(string $id): ?array
|
||||
{
|
||||
static $options = [
|
||||
'LAST',
|
||||
];
|
||||
$fpath = $this->getFilePath($id);
|
||||
$res = rrd_fetch($fpath, $options);
|
||||
if (false === $res) {
|
||||
return null;
|
||||
}
|
||||
$latest = 0;
|
||||
$start = $res['start'];
|
||||
$step = $res['step'];
|
||||
$data = [];
|
||||
foreach ($res['data'][$id] as $key => $datum) {
|
||||
if (!is_nan($datum) && 0 != $datum) {
|
||||
$data[] = $datum;
|
||||
$latest = $start + ($key + 1) * $step;
|
||||
}
|
||||
}
|
||||
if (empty($data)) {
|
||||
return null;
|
||||
}
|
||||
$ret['id'] = $id;
|
||||
$ret['min'] = min($data);
|
||||
$ret['max'] = max($data);
|
||||
$ret['average'] = array_sum($data) / count($data);
|
||||
$ret['latest'] = $data[count($data) - 1];
|
||||
$ret['timestamp'] = $latest;
|
||||
|
||||
return $ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* create database.
|
||||
*
|
||||
* @param string $id sensor id
|
||||
*
|
||||
* @return bool false if failure
|
||||
*/
|
||||
private function create(string $id): boolean
|
||||
{
|
||||
$fpath = $this->getFilePath($id);
|
||||
$options = [
|
||||
'--step', '60', // 1min step
|
||||
sprintf('DS:%s:GAUGE:600:0:100', $this->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
|
||||
];
|
||||
|
||||
return rrd_create($fpath, $options);
|
||||
}
|
||||
|
||||
/**
|
||||
* get rrd file path.
|
||||
*
|
||||
* @param string $id sensor id
|
||||
*
|
||||
* @return string rrd file path
|
||||
*/
|
||||
private function getFilePath(string $id): string
|
||||
{
|
||||
return $this->databasePath.'/'.$id.'.rrd';
|
||||
}
|
||||
|
||||
/**
|
||||
* output graph.
|
||||
*
|
||||
* @param string $type output graph type
|
||||
* @param string $fpath output image file path
|
||||
*
|
||||
* @return bool false if failure
|
||||
*/
|
||||
public function outputGraph(string $type, 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'];
|
||||
if (!in_array($type, $types)) {
|
||||
return false;
|
||||
}
|
||||
$start = '3year' == $type ? '-3year' : '-1'.$type;
|
||||
$options = [
|
||||
'--imgformat', 'PNG',
|
||||
'--lower-limit', '10',
|
||||
'--upper-limit', '40',
|
||||
'--start', $start,
|
||||
'--end', 'now',
|
||||
'--width', '400',
|
||||
'--height', '200',
|
||||
'--units-exponent', '0',
|
||||
'--vertical-label', "Temperature [\xc2\xb0C]",
|
||||
'--title', 'Server Room Temperature - by '.$type,
|
||||
];
|
||||
$idlen = 0;
|
||||
foreach ($this->sensorIds as $key => $id) {
|
||||
if (strlen($id) > $idlen) {
|
||||
$idlen = strlen($id);
|
||||
}
|
||||
$options[] = sprintf('DEF:B%d=%s:%s:LAST', $key, $this->getFilePath($id), $id);
|
||||
}
|
||||
$options[] = sprintf('COMMENT: %s Cur\: Min\: Avg\: Max\:', str_repeat(' ', $idlen));
|
||||
$options[] = sprintf('COMMENT:\l');
|
||||
foreach ($this->sensorIds as $key => $id) {
|
||||
$color = $colors[$key % count($colors)];
|
||||
$options[] = sprintf('LINE2:B%d%s:%s%s', $key, $color, $id, str_repeat(' ', $idlen - strlen($id)));
|
||||
$options[] = sprintf('GPRINT:B%d:LAST: %%-6.2lf', $key);
|
||||
$options[] = sprintf('GPRINT:B%d:MIN: %%-6.2lf', $key);
|
||||
$options[] = sprintf('GPRINT:B%d:AVERAGE: %%-6.2lf', $key);
|
||||
$options[] = sprintf('GPRINT:B%d:MAX: %%-6.2lf\l', $key);
|
||||
}
|
||||
$options[] = sprintf('COMMENT:Last update\: %s\r', str_replace(':', '\:', date('Y-m-d H:i:s T')));
|
||||
|
||||
$res = rrd_graph($fpath, $options);
|
||||
|
||||
return false !== $res;
|
||||
}
|
||||
}
|
51
sbin/check_alert.php
Normal file
51
sbin/check_alert.php
Normal file
@ -0,0 +1,51 @@
|
||||
<?php
|
||||
|
||||
define('APPDIR', dirname(__DIR__));
|
||||
|
||||
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']);
|
||||
$num = $digitemp->getNumSensors();
|
||||
$sensors = [];
|
||||
for ($i = 0; $i < $num; ++$i) {
|
||||
$id = $digitemp->getSensorId($i);
|
||||
$rrdtemp->addSensor($id);
|
||||
$sensors[] = $rrdtemp->readLastData($id);
|
||||
}
|
||||
$upper = $config['mail_alert_upper'];
|
||||
$lower = $config['mail_alert_lower'];
|
||||
$do_send = false;
|
||||
foreach ($sensors as $sensor) {
|
||||
if ($sensor['latest'] < $lower || $sensor['latest'] > $upper) {
|
||||
$do_send = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ($do_send) {
|
||||
$from = $config['mail_from'];
|
||||
$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);
|
||||
$data = [
|
||||
'range' => [
|
||||
'upper' => $upper,
|
||||
'lower' => $lower,
|
||||
],
|
||||
'sensors' => $sensors,
|
||||
'from' => [
|
||||
'name' => $from_name,
|
||||
'email' => $from,
|
||||
],
|
||||
'url' => $config['url'],
|
||||
];
|
||||
$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);
|
||||
}
|
37
sbin/send_info.php
Normal file
37
sbin/send_info.php
Normal file
@ -0,0 +1,37 @@
|
||||
<?php
|
||||
|
||||
define('APPDIR', dirname(__DIR__));
|
||||
|
||||
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']);
|
||||
$num = $digitemp->getNumSensors();
|
||||
$sensors = [];
|
||||
for ($i = 0; $i < $num; ++$i) {
|
||||
$id = $digitemp->getSensorId($i);
|
||||
$rrdtemp->addSensor($id);
|
||||
$sensors[] = $rrdtemp->readLastData($id);
|
||||
}
|
||||
|
||||
$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);
|
||||
$data = [
|
||||
'from' => [
|
||||
'name' => $from_name,
|
||||
'email' => $from,
|
||||
],
|
||||
'sensors' => $sensors,
|
||||
'url' => $config['url'],
|
||||
];
|
||||
$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);
|
22
sbin/update.php
Normal file
22
sbin/update.php
Normal file
@ -0,0 +1,22 @@
|
||||
<?php
|
||||
|
||||
define('APPDIR', dirname(__DIR__));
|
||||
|
||||
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']);
|
||||
$num = $digitemp->getNumSensors();
|
||||
for ($i = 0; $i < $num; ++$i) {
|
||||
$id = $digitemp->getSensorId($i);
|
||||
$value = $digitemp->readSensor($i);
|
||||
$rrdtemp->addSensor($id);
|
||||
$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);
|
||||
}
|
14
templates/mail_alert.twig
Normal file
14
templates/mail_alert.twig
Normal file
@ -0,0 +1,14 @@
|
||||
C407 温度監視 警告
|
||||
|
||||
警告温度に到達しました。
|
||||
許容範囲({{ '%5.2f'|format(range.lower) }} 〜 {{ '%5.2f'|format(range.upper) }} ℃)外の温度です。
|
||||
|
||||
C407 サーバ室の環境を確認してください。
|
||||
|
||||
{% for sensor in sensors %}
|
||||
{{ include('mail_sensor.inc.twig') }}
|
||||
{% endfor %}
|
||||
|
||||
--
|
||||
{{ from.name }} <{{ from.email }}>
|
||||
{{ url }}
|
9
templates/mail_info.twig
Normal file
9
templates/mail_info.twig
Normal file
@ -0,0 +1,9 @@
|
||||
C407 温度監視 定期報告
|
||||
|
||||
{% for sensor in sensors %}
|
||||
{{ include('mail_sensor.inc.twig') }}
|
||||
{% endfor %}
|
||||
|
||||
--
|
||||
{{ from.name }} <{{ from.email }}>
|
||||
{{ url }}
|
6
templates/mail_sensor.inc.twig
Normal file
6
templates/mail_sensor.inc.twig
Normal file
@ -0,0 +1,6 @@
|
||||
--- センサー #{{ sensor.id }} ---
|
||||
最新測定日時:{{ sensor.date|date('Y-m-d H:i:s T') }}
|
||||
最新温度: {{ '%5.2f'|format(sensor.latest) }} ℃
|
||||
平均/日: {{ '%5.2f'|format(sensor.average) }} ℃
|
||||
最高値/日: {{ '%5.2f'|format(sensor.max) }} ℃
|
||||
最低値/日: {{ '%5.2f'|format(sensor.min) }} ℃
|
Loading…
x
Reference in New Issue
Block a user