[FIX] several bugs at the time calculations fixes by rewriting them

This commit is contained in:
Jannik Beyerstedt 2017-10-10 11:03:49 +02:00
parent 492674393f
commit 8f470e37ef
3 changed files with 162 additions and 45 deletions

View file

@ -5,15 +5,15 @@
}, },
"time1": { "time1": {
"on": "16:00", "on": "16:00",
"off": "23:00" "off": "23:30"
}, },
"time2": { "time2": {
"on": "05:45", "on": "04:45",
"off": "06:15" "off": "05:15"
}, },
"time3": { "time3": {
"on": "06:45", "on": "06:30",
"off": "08:00" "off": "08:30"
}, },
"instant-on": null "instant-on": null
} }

View file

@ -33,20 +33,68 @@ class LightStatus {
return 's='.(int)$this->state.' t='.$this->waitTime; return 's='.(int)$this->state.' t='.$this->waitTime;
} }
/* re-calculate values */ /* re-calculate values, returns true if successful */
public function update() { public function update($currentTime = null) {
global $sun_zenith; global $sun_zenith;
global $timezone; global $timezone;
// calculate sunset and sunrise times if (null == $currentTime) {
$currentTime = time();
}
$sunset = null;
$sunrise = null;
$times = [];
// calculate times
date_default_timezone_set($timezone); date_default_timezone_set($timezone);
$gmtOffset = date("Z") / (60*60); $gmtOffset = date("Z") / (60*60);
$this->sunrise = date_sunrise(time(), SUNFUNCS_RET_STRING, $this->times['position']['lat'], $this->times['position']['long'], $sun_zenith, $gmtOffset); if (($currentTime - strtotime("12:00")) > 0) {
// currentTime is in the evening
$this->sunset = date_sunset(time(), SUNFUNCS_RET_STRING, $this->times['position']['lat'], $this->times['position']['long'], $sun_zenith, $gmtOffset); $this->sunset = date_sunset(time(), SUNFUNCS_RET_STRING, $this->times['position']['lat'], $this->times['position']['long'], $sun_zenith, $gmtOffset);
$this->sunrise = date_sunrise((time() + 24*60*60), SUNFUNCS_RET_STRING, $this->times['position']['lat'], $this->times['position']['long'], $sun_zenith, $gmtOffset);
$sunrise = date_sunrise(time(), SUNFUNCS_RET_TIMESTAMP, $this->times['position']['lat'], $this->times['position']['long'], $sun_zenith, $gmtOffset);
$sunset = date_sunset(time(), SUNFUNCS_RET_TIMESTAMP, $this->times['position']['lat'], $this->times['position']['long'], $sun_zenith, $gmtOffset); $sunset = date_sunset(time(), SUNFUNCS_RET_TIMESTAMP, $this->times['position']['lat'], $this->times['position']['long'], $sun_zenith, $gmtOffset);
$sunrise = date_sunrise((time() + 24*60*60), SUNFUNCS_RET_TIMESTAMP, $this->times['position']['lat'], $this->times['position']['long'], $sun_zenith, $gmtOffset);
for ($i = 1; $i <= 3; $i++) {
$timeKey = 'time'.$i;
$startTime = strtotime($this->times[$timeKey]['on']);
if ((strtotime("00:00")+24*60*60) - $startTime > 12*60*60) {
$startTime += 24*60*60;
}
$stopTime = strtotime($this->times[$timeKey]['off']);
if ((strtotime("00:00")+24*60*60) - $stopTime > 12*60*60) {
$stopTime += 24*60*60;
}
$times[] = ["on"=>$startTime, "off"=>$stopTime];
}
} else {
// currentTime is in the morning
$this->sunset = date_sunset((time() - 24*60*60), SUNFUNCS_RET_STRING, $this->times['position']['lat'], $this->times['position']['long'], $sun_zenith, $gmtOffset);
$this->sunrise = date_sunrise(time(), SUNFUNCS_RET_STRING, $this->times['position']['lat'], $this->times['position']['long'], $sun_zenith, $gmtOffset);
$sunset = date_sunset((time() - 24*60*60), SUNFUNCS_RET_TIMESTAMP, $this->times['position']['lat'], $this->times['position']['long'], $sun_zenith, $gmtOffset);
$sunrise = date_sunrise(time(), SUNFUNCS_RET_TIMESTAMP, $this->times['position']['lat'], $this->times['position']['long'], $sun_zenith, $gmtOffset);
for ($i = 1; $i <= 3; $i++) {
$timeKey = 'time'.$i;
$startTime = strtotime($this->times[$timeKey]['on']);
if ($startTime - strtotime("00:00") > 12*60*60) {
$startTime -= 24*60*60;
}
$stopTime = strtotime($this->times[$timeKey]['off']);
if ($stopTime - strtotime("00:00") > 12*60*60) {
$stopTime -= 24*60*60;
}
$times[] = ["on"=>$startTime, "off"=>$stopTime];
}
}
// -- first check, if an instant-on time is set -- // -- first check, if an instant-on time is set --
if ($this->times['instant-on'] != null) { if ($this->times['instant-on'] != null) {
@ -65,55 +113,46 @@ class LightStatus {
} }
} }
// -- otherwise check, if the ruleset requires the lights on -- // -- if no instant-on time is set, follow normal conditions --
// first check, if it's at daylight if ($sunset < $currentTime && $sunrise > $currentTime) {
$currentTime = time();
if ($currentTime < $sunrise || $currentTime > $sunset) {
$this->isNight = true; $this->isNight = true;
// it's night: check, if we are in one of the time intervals // it's night: check, if we are in one of the time intervals
for ($i = 1; $i <= 3; $i++) { $this->changeTime = null;
$timeKey = 'time'.$i; foreach ($times as $t) {
if ($t["on"] < $currentTime && $t["off"] > $currentTime) {
$startTime = strtotime($this->times[$timeKey]['on']); // we are in this interval
$stopTime = strtotime($this->times[$timeKey]['off']);
if ($stopTime < $startTime) {
$stopTime += (24*60*60);
if (($stopTime - $currentTime) > (24*60*60)) {
$startTime -= (24*60*60);
$stopTime -= (24*60*60);
}
}
if ($currentTime > $startTime && $currentTime < $stopTime) {
$this->state = true; $this->state = true;
$this->changeTime = (int)(($stopTime - $currentTime) / 60); $this->changeTime = (int)(($t["off"] - $currentTime) / 60);
$this->waitTime = 1; $this->waitTime = 1;
return true; return true;
} elseif ( ($startTime - $currentTime) < (12*60*60) || ($startTime+(24*60*60) - $currentTime) < (12*60*60) ) { } else if ($t["on"] > $currentTime) {
// right before the next time interval // we are right before this interval
$this->state = false; $this->state = false;
if ($currentTime < $startTime) { $this->changeTime = (int)(($t["on"] - $currentTime) / 60);
$this->changeTime = (int)( ($startTime - $currentTime) / 60 );
} else {
$this->changeTime = (int)( (($startTime+(24*60*60)) - $currentTime) / 60 );
}
$this->waitTime = 1; $this->waitTime = 1;
return true; return true;
} }
// otherwise we are after this interval, but potentioally before next interval
} }
if ($this->changeTime == null) {
// we are after the last interval, so changeTime is not set yet
$this->state = false; $this->state = false;
$this->changeTime = (int)(($stopTime - $currentTime) / 60); $this->changeTime = (int)(($sunrise - $currentTime) / 60);
$this->waitTime = 1; $this->waitTime = $this->changeTime;
return true; return true;
}
} else if ($currentTime > $sunrise && $currentTime < $sunset) { } else if ($currentTime > $sunrise || $sunset > $currentTime) {
$this->isNight = false; $this->isNight = false;
// it's day: nothing else check // it's day: nothing else to check
$this->state = false; $this->state = false;
$this->changeTime = (int)(($sunset - $currentTime) / 60); $this->changeTime = (int)(($sunset - $currentTime) / 60);
if ($this->changeTime < 0) {
$this->changeTime += 24*60; // changeTime is in Minutes
}
$this->waitTime = $this->changeTime; $this->waitTime = $this->changeTime;
return true; return true;
@ -123,7 +162,7 @@ class LightStatus {
} }
} }
/* save modified $times array to config file */ /* save modified $times array to config file, returns true if successful */
public function saveTimes() { public function saveTimes() {
global $config_filename; global $config_filename;

78
tests.php Normal file
View file

@ -0,0 +1,78 @@
<?php
// -------------------------------------------
// outdoor lights control -- server
// -- Manual "Unit Tests" --
// copyright: Jannik Beyerstedt | https://jannikbeyerstedt.de
// license: http://www.gnu.org/licenses/gpl-3.0.txt GPLv3 License
// -------------------------------------------
include "functions.php";
$light = new LightStatus();
$light->update();
$testTimes = ["09:00",
"11:00",
"15:00",
"20:00",
"23:55",
"00:05 +1day",
"05:00 +1day",
"06:00 +1day",
"07:00 +1day",
"09:00 +1day",
"11:00 +1day",];
?>
<!DOCTYPE html>
<html lang="de">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<meta name="format-detection" content="telephone=no">
<title>Lightscontrol Manual Tests</title>
<meta name="robots" content="noindex, nofollow">
<link rel="stylesheet" href="bootstrap/css/bootstrap.min.css">
<link rel="stylesheet" href="style.css?v1.1">
</head>
<body class="container">
Standard Metrics:
<table>
<tr>
<td>Sonnenaufgang:</td><td><?php echo $light->sunrise ?></td>
</tr>
<tr>
<td>Sonnenuntergang:</td><td><?php echo $light->sunset ?></td>
</tr>
<tr>
<td>Aktuelle Zeit:</td><td><?php echo date("H:i, Y-m-d",time()) ?></td>
</tr>
<tr>
<td>Nacht (ja/nein):</td><td><?php echo ($light->isNight) ? "ja" : "nein" ?></td>
</tr>
</table>
Test Sequences:
<table>
<tr>
<td>now:</td>
<td>Night: <?php echo ($light->isNight)?"1":"0" ?>, State: <?php echo ($light->state)?"1":"0" ?>,
Change: <?php echo $light->changeTime ?> (<?php echo (int)($light->changeTime/60) ?>:<?php echo $light->changeTime%60 ?>h),
API: <?php echo $light ?></td>
</tr>
<?php foreach ($testTimes as $t): ?>
<tr><?php $light->update(strtotime($t));?>
<td><?php echo $t ?>:</td>
<td>Night: <?php echo ($light->isNight)?"1":"0" ?>, State: <?php echo ($light->state)?"1":"0" ?>,
Change: <?php echo $light->changeTime ?> (<?php echo (int)($light->changeTime/60) ?>:<?php echo $light->changeTime%60 ?>h),
API: <?php echo $light ?></td>
</tr>
<?php endforeach; ?>
</table>
Config Array:
<pre><?php echo var_dump($light->times) ?></pre>
</body>