2021-07-07 01:13:50 +00:00
< ? php
define ( 'FM_TEMP_KEY' , 'kND861svbydCLywutu78tRmlpWdzoRLPcVZSrnxerh3KbLwfwvfvgC5hzax8gvYm' );
define ( 'FM_TEMP_INT' , 10 );
ini_set ( 'display_errors' , 'on' );
error_reporting ( - 1 );
2022-02-04 04:25:57 +00:00
date_default_timezone_set ( 'UTC' );
mb_internal_encoding ( 'UTF-8' );
try {
$pdo = new PDO ( 'mysql:unix_socket=/var/run/mysqld/mysqld.sock;dbname=website;charset=utf8mb4' , 'website' , 'A3NjVvHRkHAxiYgk8MM4ZrCwrLVyPIYX' , [
PDO :: ATTR_CASE => PDO :: CASE_NATURAL ,
PDO :: ATTR_ERRMODE => PDO :: ERRMODE_EXCEPTION ,
PDO :: ATTR_ORACLE_NULLS => PDO :: NULL_NATURAL ,
PDO :: ATTR_STRINGIFY_FETCHES => false ,
PDO :: ATTR_EMULATE_PREPARES => false ,
PDO :: MYSQL_ATTR_INIT_COMMAND => "
SET SESSION
sql_mode = 'STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION' ,
time_zone = '+00:00' ;
" ,
]);
} catch ( Exception $ex ) {
http_response_code ( 500 );
echo '<h3>Unable to connect to database</h3>' ;
die ( $ex -> getMessage ());
}
2021-07-07 01:13:50 +00:00
if ( isset ( $_POST [ 'temp' ]) && isset ( $_POST [ 'hash' ]) && isset ( $_POST [ 'time' ])) {
2022-02-04 20:30:52 +00:00
$temp = ( string ) filter_input ( INPUT_POST , 'temp' );
$hash = ( string ) filter_input ( INPUT_POST , 'hash' );
2021-07-07 01:13:50 +00:00
$time = ( string ) filter_input ( INPUT_POST , 'time' , FILTER_SANITIZE_NUMBER_INT );
if ( ! hash_equals ( hash_hmac ( 'sha256' , $temp . '|' . $time , FM_TEMP_KEY ), $hash ))
return ;
$time = floor (( int ) json_decode ( $time ) / FM_TEMP_INT );
if ( $time !== floor ( time () / FM_TEMP_INT ))
return ;
$insert = $pdo -> prepare ( 'INSERT INTO `fm_temperature` (`temp_celcius`) VALUES (:temp)' );
$insert -> bindValue ( 'temp' , ( string ) json_decode ( $temp ));
$insert -> execute ();
return ;
}
if ( isset ( $_GET [ 'since' ])) {
$since = ( int ) filter_input ( INPUT_GET , 'since' , FILTER_SANITIZE_NUMBER_INT );
$temps = $pdo -> prepare ( 'SELECT `temp_celcius`, UNIX_TIMESTAMP(`temp_datetime`) AS `temp_datetime` FROM `fm_temperature` WHERE `temp_datetime` > FROM_UNIXTIME(:since) AND `temp_datetime` > NOW() - INTERVAL 1 DAY ORDER BY `temp_datetime` ASC LIMIT 288' );
$temps -> bindValue ( 'since' , $since );
$temps -> execute ();
header ( 'Content-Type: application/json; charset=utf-8' );
echo json_encode ( $temps -> fetchAll ( PDO :: FETCH_ASSOC ));
return ;
}
2022-02-04 04:25:57 +00:00
if ( isset ( $_GET [ 'since_3mo' ])) {
$since = ( int ) filter_input ( INPUT_GET , 'since_3mo' , FILTER_SANITIZE_NUMBER_INT );
$temps = $pdo -> prepare ( 'SELECT MAX(`temp_celcius`) AS `temp_celcius_max`, AVG(`temp_celcius`) AS `temp_celcius_avg`, MIN(`temp_celcius`) AS `temp_celcius_min`, UNIX_TIMESTAMP(DATE(`temp_datetime`)) AS `temp_datetime` FROM `fm_temperature` WHERE `temp_datetime` > DATE(FROM_UNIXTIME(:since)) AND `temp_datetime` > NOW() - INTERVAL 3 MONTH GROUP BY DATE(`temp_datetime`) ORDER BY `temp_datetime` ASC LIMIT 92' );
$temps -> bindValue ( 'since' , $since );
$temps -> execute ();
header ( 'Content-Type: application/json; charset=utf-8' );
echo json_encode ( $temps -> fetchAll ( PDO :: FETCH_ASSOC ));
return ;
}
if ( isset ( $_GET [ 'since_6mo' ])) {
$since = ( int ) filter_input ( INPUT_GET , 'since_6mo' , FILTER_SANITIZE_NUMBER_INT );
$temps = $pdo -> prepare ( 'SELECT MAX(`temp_celcius`) AS `temp_celcius_max`, AVG(`temp_celcius`) AS `temp_celcius_avg`, MIN(`temp_celcius`) AS `temp_celcius_min`, UNIX_TIMESTAMP(DATE(`temp_datetime`)) AS `temp_datetime` FROM `fm_temperature` WHERE `temp_datetime` > DATE(FROM_UNIXTIME(:since)) AND `temp_datetime` > NOW() - INTERVAL 6 MONTH GROUP BY DATE(`temp_datetime`) ORDER BY `temp_datetime` ASC LIMIT 92' );
$temps -> bindValue ( 'since' , $since );
$temps -> execute ();
header ( 'Content-Type: application/json; charset=utf-8' );
echo json_encode ( $temps -> fetchAll ( PDO :: FETCH_ASSOC ));
return ;
}
2021-07-07 01:13:50 +00:00
if ( ! empty ( $_GET [ 'siri' ])) {
header ( 'Content-Type: text/plain; charset=utf-8' );
$temps = $pdo -> prepare ( 'SELECT `temp_celcius`, UNIX_TIMESTAMP(`temp_datetime`) AS `temp_datetime` FROM `fm_temperature` ORDER BY `temp_datetime` DESC LIMIT 1' );
$temps -> execute ();
$temps = $temps -> fetch ( PDO :: FETCH_ASSOC );
2022-02-04 04:25:57 +00:00
date_default_timezone_set ( 'Europe/Amsterdam' );
2021-07-07 01:13:50 +00:00
printf ( 'It was %2$.1f°C at %1$s.' , date ( 'H:i:s' , $temps [ 'temp_datetime' ]), $temps [ 'temp_celcius' ]);
return ;
}
?>
<! doctype html >
< html >
< head >
< meta charset = " utf-8 " />
< title > Room Temperature </ title >
< meta name = " viewport " content = " width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no " />
< link href = " /css/electrolize/style.css " type = " text/css " rel = " stylesheet " />
< style type = " text/css " >
* {
margin : 0 ;
padding : 0 ;
box - sizing : border - box ;
position : relative ;
outline - style : none ;
}
html , body {
width : 100 % ;
height : 100 % ;
}
body {
background - color : #111;
color : #fff;
font : 12 px / 20 px Tahoma , Geneva , 'Dejavu Sans' , Arial , Helvetica , sans - serif ;
padding : 1 px ;
}
. current {
text - align : center ;
background - color : #333;
margin : 10 px ;
padding : 10 px ;
border - radius : 10 px ;
}
. current - temp {
font - family : 'Electrolize' , Verdana , 'Dejavu Sans' , Arial , Helvetica , sans - serif ;
font - size : 3 em ;
line - height : 1.2 em ;
}
. current - datetime {
font - size : . 9 em ;
line - height : 1.4 em ;
}
. chart {
background - color : #ddd;
margin : 10 px ;
padding : 10 px ;
border - radius : 10 px ;
}
</ style >
</ head >
< body >
< div class = " main " >
< div class = " current " >
< div class = " current-temp " >
< span id = " -last-temp " >--</ span > °C
</ div >
< div class = " current-datetime " >
< span id = " -last-datetime " >--:--:--</ span >
</ div >
</ div >
< div class = " chart " >
< canvas id = " -chart " width = " 400 " height = " 170 " ></ canvas >
</ div >
2022-02-04 04:25:57 +00:00
< div class = " chart " >
< canvas id = " -chart-mo " width = " 400 " height = " 170 " ></ canvas >
</ div >
2021-07-07 01:13:50 +00:00
</ div >
< script type = " text/javascript " src = " https://cdn.jsdelivr.net/npm/chart.js@3.3.2/dist/chart.min.js " ></ script >
< script type = " text/javascript " >
var temp = {
last : 0 ,
2022-02-04 04:25:57 +00:00
lastMo : 0 ,
2021-07-07 01:13:50 +00:00
history : [],
2022-02-04 04:25:57 +00:00
historyMo : [],
2021-07-07 01:13:50 +00:00
lastTemp : null ,
lastDateTime : null ,
chart : null ,
2022-02-04 04:25:57 +00:00
chartMo : null ,
2021-07-07 01:13:50 +00:00
};
temp . getLastTemperature = function () {
if ( this . history . length === 0 )
return { temp_datetime : 0 , temp_celcius : 0 };
return this . history [ this . history . length - 1 ];
};
temp . refresh = function () {
var xhr = new XMLHttpRequest ;
xhr . onload = function () {
var temps = JSON . parse ( xhr . responseText );
for ( var i = 0 ; i < temps . length ; ++ i ) {
var temp = temps [ i ];
this . last = temp . temp_datetime ;
this . history . push ( temp );
}
this . refreshUI ();
} . bind ( this );
xhr . open ( 'GET' , '/temp.php?since=' + encodeURIComponent ( parseInt ( this . last ) . toString ()));
xhr . send ();
};
temp . refreshUI = function () {
var temp = this . getLastTemperature ();
this . lastTemp . textContent = ( parseInt ( temp . temp_celcius * 10 ) / 10 ) . toFixed ( 1 ) . toLocaleString ();
this . lastDateTime . textContent = new Date ( temp . temp_datetime * 1000 ) . toLocaleString ();
var take = Math . min ( 288 , this . history . length ),
dataset = this . chart . data . datasets [ 0 ];
this . chart . data . labels = [];
dataset . data = [];
for ( var i = this . history . length - take ; i < this . history . length ; ++ i ) {
var temp = this . history [ i ];
this . chart . data . labels . push ( new Date ( temp . temp_datetime * 1000 ) . toLocaleString ());
dataset . data . push ( temp . temp_celcius );
}
this . chart . update ();
};
2022-02-04 04:25:57 +00:00
temp . refreshMo = function () {
var xhr = new XMLHttpRequest ;
xhr . onload = function () {
var temps = JSON . parse ( xhr . responseText );
for ( var i = 0 ; i < temps . length ; ++ i ) {
var temp = temps [ i ];
this . lastMo = temp . temp_datetime ;
this . historyMo . push ( temp );
}
this . refreshUIMo ();
} . bind ( this );
xhr . open ( 'GET' , '/temp.php?since_6mo=' + encodeURIComponent ( parseInt ( this . lastMo ) . toString ()));
xhr . send ();
};
temp . refreshUIMo = function () {
var take = Math . min ( 92 , this . historyMo . length ),
datasetMax = this . chartMo . data . datasets [ 0 ],
datasetAvg = this . chartMo . data . datasets [ 1 ],
datasetMin = this . chartMo . data . datasets [ 2 ];
this . chart . data . labels = [];
datasetMax . data = [];
datasetAvg . data = [];
datasetMin . data = [];
for ( var i = this . historyMo . length - take ; i < this . historyMo . length ; ++ i ) {
var temp = this . historyMo [ i ];
this . chartMo . data . labels . push ( new Date ( temp . temp_datetime * 1000 ) . toDateString ());
datasetMax . data . push ( temp . temp_celcius_max );
datasetAvg . data . push ( temp . temp_celcius_avg );
datasetMin . data . push ( temp . temp_celcius_min );
}
this . chartMo . update ();
};
2021-07-07 01:13:50 +00:00
window . onload = function () {
temp . lastTemp = document . getElementById ( '-last-temp' );
temp . lastDateTime = document . getElementById ( '-last-datetime' );
var ctx = document . getElementById ( '-chart' ) . getContext ( '2d' );
temp . chart = new Chart ( ctx , {
type : 'line' ,
data : {
datasets : [
{
label : 'Temperature' ,
data : [],
borderColor : '#111' ,
backgroundColor : '#222' ,
},
],
},
options : {
responsive : true ,
plugins : {
legend : {
position : 'top' ,
},
title : {
display : true ,
text : 'Temperature History' ,
},
},
scales : {
y : {
suggestedMax : 34 ,
suggestedMin : 20 ,
ticks : {
stepSize : 1 ,
},
},
},
},
});
temp . refresh ();
setInterval ( temp . refresh . bind ( temp ), 5 * 60 * 1000 );
2022-02-04 04:25:57 +00:00
var ctxMo = document . getElementById ( '-chart-mo' ) . getContext ( '2d' );
temp . chartMo = new Chart ( ctxMo , {
type : 'line' ,
data : {
datasets : [
{
label : 'Maximum Temperature' ,
data : [],
borderColor : '#400' ,
backgroundColor : '#800' ,
},
{
label : 'Average Temperature' ,
data : [],
borderColor : '#040' ,
backgroundColor : '#080' ,
},
{
label : 'Minimum Temperature' ,
data : [],
borderColor : '#004' ,
backgroundColor : '#008' ,
},
],
},
options : {
responsive : true ,
plugins : {
legend : {
position : 'top' ,
},
title : {
display : true ,
text : 'Daily Temperature (6 months)' ,
},
},
scales : {
y : {
suggestedMax : 34 ,
suggestedMin : 20 ,
ticks : {
stepSize : 1 ,
},
},
},
},
});
temp . refreshMo ();
setInterval ( temp . refreshMo . bind ( temp ), 31 * 24 * 60 * 1000 );
2021-07-07 01:13:50 +00:00
};
</ script >
</ body >
</ html >