From 834b95629832fc3735756727b6c7cb1826d0e9d8 Mon Sep 17 00:00:00 2001 From: Christian Hofmaier Date: Tue, 16 Mar 2021 20:03:58 +0100 Subject: [rebootcontrol] Handle scheduler overlaps - Overlaps < 5 min are ignored, < 15 triggers reboot - Database: Make 1 line out of 2 --- .../rebootcontrol/inc/scheduler.inc.php | 112 ++++++++++++++------- 1 file changed, 73 insertions(+), 39 deletions(-) (limited to 'modules-available/rebootcontrol/inc/scheduler.inc.php') diff --git a/modules-available/rebootcontrol/inc/scheduler.inc.php b/modules-available/rebootcontrol/inc/scheduler.inc.php index 27a22646..0928d20f 100644 --- a/modules-available/rebootcontrol/inc/scheduler.inc.php +++ b/modules-available/rebootcontrol/inc/scheduler.inc.php @@ -3,63 +3,97 @@ class Scheduler { - public static function updateSchedule($locationid, $action, $options, $openingTimes) { + public static function updateSchedule($locationid, $options, $openingTimes) { if ($openingTimes == '') { - self::deleteSchedule($locationid, $action); + self::deleteSchedule($locationid); return false; } - $nextexec = self::calcNextexec($action, $options, $openingTimes); + $nextexec = self::calculateNext($options, $openingTimes); $json_options = json_encode($options); - self::upsert($locationid, $action, $nextexec, $json_options); + if ($nextexec !== false) self::upsert($locationid, $nextexec['action'], $nextexec['time'], $json_options); + else { + // All times are getting ignored because they are within 5 minutes of each other, delete possible db entries. + self::deleteSchedule($locationid); + } return true; } - public static function deleteSchedule($locationid, $action) { + public static function deleteSchedule($locationid) { Database::exec("DELETE FROM `reboot_scheduler` - WHERE locationid = :lid AND action = :act", array( - 'lid' => $locationid, - 'act' => $action - )); + WHERE locationid = :lid", array('lid' => $locationid)); } - private static function calcNextexec($action, $options, $openingTimes) { + private static function calculateNext($options, $openingTimes) { $openingTimes = json_decode($openingTimes, true); - $now = time(); $times = []; + $now = time(); + $openTimes = []; + $closeTimes = []; foreach ($openingTimes as $row) { - // Fetch hour and minutes of opening / closing time. - $hourmin = explode(':', ($action == 'wol' ? $row['openingtime'] : $row['closingtime'])); - // Calculate time based on offset. - $min = ($action == 'wol' ? $hourmin[0] * 60 + $hourmin[1] - $options['wol-offset'] : $hourmin[0] * 60 + $hourmin[1] + $options['sd-offset']); - // Calculate opening / closing time of each day. + if (!$options['wol'] && !$options['sd']) continue; + if ($options['wol']) { + $open = explode(':', $row['openingtime']); + $openTime = $open[0] * 60 + $open[1] - $options['wol-offset']; + } + if ($options['sd']) { + $close = explode(':', $row['closingtime']); + $closeTime = $close[0] * 60 + $close[1] + $options['sd-offset']; + } foreach ($row['days'] as $day) { - $next = strtotime(date('Y-m-d H:i', strtotime($day . ' ' . $min . ' minutes'))); - if ($next < $now) { - $times[] = strtotime(date('Y-m-d H:i', strtotime('next '.$day . ' ' . $min . ' minutes'))); - } else { - $times[] = $next; + if ($options['wol']) { + $nextOpen = strtotime(date('Y-m-d H:i', strtotime($day . ' ' . $openTime . ' minutes'))); + if ($nextOpen < $now) $openTimes[] = strtotime(date('Y-m-d H:i', strtotime('next '.$day . ' ' . $openTime . ' minutes'))); + else $openTimes[] = $nextOpen; + } + if ($options['sd']) { + $nextClose = strtotime(date('Y-m-d H:i', strtotime($day . ' ' . $closeTime . ' minutes'))); + if ($nextClose < $now) $closeTimes[] = strtotime(date('Y-m-d H:i', strtotime('next '.$day . ' ' . $closeTime . ' minutes'))); + else $closeTimes[] = $nextClose; } } } - // Iterate over days, use timestamp with smallest difference to now. - $res = 0; $smallestDiff = 0; - foreach ($times as $time) { - $diff = $time - $now; - if ($res == 0 || $diff < $smallestDiff) { - $smallestDiff = $diff; - $res = $time; + + sort($openTimes); + sort($closeTimes); + $res = array(); + + if ($options['wol'] && !$options['sd']) { + $res['action'] = 'wol'; + $res['time'] = $openTimes[0]; + return $res; + } else if ($options['sd'] && !$options['wol']) { + $res['action'] = 'sd'; + $res['time'] = $closeTimes[0]; + return $res; + } + + for ($i = 0; $i <= sizeof($openTimes); $i++) { + if (abs($openTimes[$i] - $closeTimes[$i]) < 300) { + // If difference is < 5 min, ignore both events. + continue; + } else if (abs($openTimes[$i] - $closeTimes[$i]) < 900) { + // If difference is < 15 min, reboot at the earlier time. + $res['action'] = 'rb'; + $res['time'] = $openTimes[$i] < $closeTimes[$i] ? $openTimes[$i] : $closeTimes[$i]; + } else { + // Use first event. + if ($openTimes[$i] < $closeTimes[$i]) { + $res['action'] = 'wol'; + $res['time'] = $openTimes[$i]; + } else { + $res['action'] = 'sd'; + $res['time'] =$closeTimes[$i]; + } } + return $res; } - return $res; + return false; } - - private static function upsert($locationid, $action, $nextexec, $options) { - $schedule = Database::queryFirst("SELECT locationid, action + $schedule = Database::queryFirst("SELECT locationid FROM `reboot_scheduler` - WHERE locationid = :lid AND action = :act", array( - 'lid' => $locationid, - 'act' => $action + WHERE locationid = :lid", array( + 'lid' => $locationid )); if ($schedule === false) { Database::exec("INSERT INTO `reboot_scheduler` (locationid, action, nextexecution, options) @@ -71,12 +105,12 @@ class Scheduler )); } else { Database::exec("UPDATE `reboot_scheduler` - SET nextexecution = :next, options = :opt - WHERE locationid = :lid AND action = :act", array( + SET action = :act, nextexecution = :next, options = :opt + WHERE locationid = :lid", array( + 'act' => $action, 'next' => $nextexec, 'opt' => $options, - 'lid' => $locationid, - 'act' => $action + 'lid' => $locationid )); } return true; -- cgit v1.2.3-55-g7522