This repository has been archived on 2020-03-25. You can view files and clone it, but cannot push or open issues or pull requests.
lightscontrol-server/functions.php

187 lines
6 KiB
PHP

<?php
// -------------------------------------------
// outdoor lights control -- server
// copyright: Jannik Beyerstedt | https://jannikbeyerstedt.de
// license: http://www.gnu.org/licenses/gpl-3.0.txt GPLv3 License
// -------------------------------------------
$config_filename = 'config_times.json';
$timeRegex = '/^((2[0-3]|1[0-9]|0[0-9]|[^0-9][0-9]):([0-5][0-9]|[0-9]))/';
$sunsetTrue = 90+50/60; /* "true" sunrise/ sunset */
$sunsetCivilian = 96; /* Civilian Twilight */
$sunsetNautical = 102; /* Nauticla Twilight */
$sun_zenith = $sunsetCivilian;
$timezone = "Europe/Berlin";
class LightStatus {
public $state = true; /* current state: lights on/off */
public $changeTime = 1; /* minutes until next state change */
public $waitTime = 0; /* minutes the client should wait until next request */
public $times = null; /* config array */
public $sunrise, $sunset; /* time string hh:mm */
public $isNight; /* bool, true if it's at night */
function __construct() {
return $this->readTimes();
}
/* return string for the service API */
function __toString() {
return 's='.(int)$this->state.' t='.$this->waitTime;
}
/* re-calculate values */
public function update() {
global $sun_zenith;
global $timezone;
// calculate sunset and sunrise times
date_default_timezone_set($timezone);
$gmtOffset = date("Z") / (60*60);
$this->sunrise = date_sunrise(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);
$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);
// -- first check, if an instant-on time is set --
if ($this->times['instant-on'] != null) {
if ($this->times['instant-on'] > time()) {
$this->state = true;
$this->changeTime = (int)(($this->times['instant-on']-time())/60);
$this->waitTime = $this->changeTime;
return true;
} else {
// reset instant-on
$this->state = false;
$this->times['instant-on'] = null;
$this->saveTimes();
}
}
// -- otherwise check, if the ruleset requires the lights on --
// first check, if it's at daylight
$currentTime = time();
if ($currentTime < $sunrise || $currentTime > $sunset) {
$this->isNight = true;
// it's night: check, if we are in one of the time intervals
for ($i = 1; $i <= 3; $i++) {
$timeKey = 'time'.$i;
$startTime = strtotime($this->times[$timeKey]['on']);
$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->changeTime = (int)(($stopTime - $currentTime) / 60);
$this->waitTime = 1;
return true;
} elseif ( ($startTime - $currentTime) < (12*60*60) || ($startTime+(24*60*60) - $currentTime) < (12*60*60) ) {
// right before the next time interval
$this->state = false;
if ($currentTime < $startTime) {
$this->changeTime = (int)( ($startTime - $currentTime) / 60 );
} else {
$this->changeTime = (int)( (($startTime+(24*60*60)) - $currentTime) / 60 );
}
$this->waitTime = 1;
return true;
}
}
$this->state = false;
$this->changeTime = (int)(($stopTime - $currentTime) / 60);
$this->waitTime = 1;
return true;
} else if ($currentTime > $sunrise && $currentTime < $sunset) {
$this->isNight = false;
// it's day: nothing else check
$this->state = false;
$this->changeTime = (int)(($sunset - $currentTime) / 60);
$this->waitTime = $this->changeTime;
return true;
} else {
echo "ERROR: invalid time of day.";
return 'ERROR';
}
}
/* save modified $times array to config file */
public function saveTimes() {
global $config_filename;
if (empty($this->times)) {
return 'ERROR';
} else {
$json_string = json_encode($this->times, JSON_PRETTY_PRINT);
file_put_contents($config_filename, $json_string);
return true;
}
}
public function setClientLastSeen() {
$this->times['clientLastSeen'] = time();
$this->saveTimes();
}
public function getClientLastSeen() {
return $this->times['clientLastSeen'];
}
private function readTimes() {
global $config_filename;
$file_content = file_get_contents($config_filename);
if ($file_content == FALSE) {
return 'ERROR';
} else {
$this->times = json_decode($file_content, true);
return true;
}
}
}
function checkTimesInput($times) {
global $timeRegex;
if (!isset($_POST['time1-start']) || !preg_match($timeRegex, $_POST['time1-start'])) {
return "time1-start not valid";
}
if (!isset($_POST['time1-stop']) || !preg_match($timeRegex, $_POST['time1-stop'])) {
return "time1-stop not valid";
}
if (!isset($_POST['time2-start']) || !preg_match($timeRegex, $_POST['time2-start'])) {
return "time2-start not valid";
}
if (!isset($_POST['time2-stop']) || !preg_match($timeRegex, $_POST['time2-stop'])) {
return "time2-stop not valid";
}
if (!isset($_POST['time3-start']) || !preg_match($timeRegex, $_POST['time3-start'])) {
return "time3-start not valid";
}
if (!isset($_POST['time3-stop']) || !preg_match($timeRegex, $_POST['time3-stop'])) {
return "time3-stop not valid";
}
return true;
}
?>