1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
|
<?php
class Scheduler
{
public static function updateSchedule($locationid, $options, $openingTimes) {
if ($openingTimes == '') {
self::deleteSchedule($locationid);
return false;
}
$nextexec = self::calculateNext($options, $openingTimes);
$json_options = json_encode($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) {
Database::exec("DELETE FROM `reboot_scheduler`
WHERE locationid = :lid", array('lid' => $locationid));
}
private static function calculateNext($options, $openingTimes) {
$openingTimes = json_decode($openingTimes, true);
$now = time();
$openTimes = [];
$closeTimes = [];
foreach ($openingTimes as $row) {
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) {
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;
}
}
}
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 false;
}
private static function upsert($locationid, $action, $nextexec, $options) {
$schedule = Database::queryFirst("SELECT locationid
FROM `reboot_scheduler`
WHERE locationid = :lid", array(
'lid' => $locationid
));
if ($schedule === false) {
Database::exec("INSERT INTO `reboot_scheduler` (locationid, action, nextexecution, options)
VALUES (:lid, :act, :next, :opt)", array(
'lid' => $locationid,
'act' => $action,
'next' => $nextexec,
'opt' => $options
));
} else {
Database::exec("UPDATE `reboot_scheduler`
SET action = :act, nextexecution = :next, options = :opt
WHERE locationid = :lid", array(
'act' => $action,
'next' => $nextexec,
'opt' => $options,
'lid' => $locationid
));
}
return true;
}
}
|