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
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
|
import bisect
import time
from enigma import *
class TimerEntry:
EventPrepare = 0
EventStart = 1
EventEnd = 2
EventAbort = 3
StateWait = 0
StatePrepare = 1
StateRunning = 2
StateEnded = 3
def __init__(self, begin, end):
self.begin = begin
self.prepare_time = 10
self.end = end
self.state = 0
self.resetRepeated()
def resetRepeated(self):
self.repeated = int(0)
def setRepeated(self, day):
self.repeated |= (2 ** day)
print "Repeated: " + str(self.repeated)
# update self.begin and self.end according to the self.repeated-flags
def processRepeated(self):
print "ProcessRepeated"
if (self.repeated != 0):
now = int(time.time())
day = []
flags = self.repeated
for x in range(0, 7):
if (flags & 1 == 1):
day.append(0)
else:
day.append(1)
flags = flags >> 1
while ((day[time.localtime(self.begin).tm_wday] != 0) and (self.end < now)):
print str(now) + " " + str(self.end) + " " + str(self.begin)
self.begin += 86400
self.end += 86400
def getTime(self):
if self.state == self.StateWait:
return self.begin - self.prepare_time
elif self.state == self.StatePrepare:
return self.begin
else:
return self.end
def __lt__(self, o):
return self.getTime() < o.getTime()
def activate(self, event):
print "[timer.py] timer %s got activated (%d)!" % (self.description, event)
class Timer:
# the time between "polls". We do this because
# we want to account for time jumps etc.
# of course if they occur <100s before starting,
# it's not good. thus, you have to repoll when
# you change the time.
#
# this is just in case. We don't want the timer
# hanging. we use this "edge-triggered-polling-scheme"
# anyway, so why don't make it a bit more fool-proof?
MaxWaitTime = 100
def __init__(self):
self.timer_list = [ ]
self.processed_timers = [ ]
self.timer = eTimer()
self.timer.timeout.get().append(self.calcNextActivation)
self.lastActivation = time.time()
self.calcNextActivation()
def addTimerEntry(self, entry, noRecalc=0):
entry.processRepeated()
# we either go trough Prepare/Start/End-state if the timer is still running,
# or skip it when it's alrady past the end.
if entry.end > time.time():
bisect.insort(self.timer_list, entry)
if not noRecalc:
self.calcNextActivation()
else:
bisect.insort(self.processed_timers, entry)
def setNextActivation(self, when):
delay = int((when - time.time()) * 1000)
print "[timer.py] next activation: %d (in %d ms)" % (when, delay)
self.timer.start(delay, 1)
self.next = when
def calcNextActivation(self):
if self.lastActivation > time.time():
print "[timer.py] timewarp - re-evaluating all processed timers."
tl = self.processed_timers
self.processed_timers = [ ]
for x in tl:
self.addTimerEntry(x, noRecalc=1)
self.processActivation()
self.lastActivation = time.time()
min = int(time.time()) + self.MaxWaitTime
# calculate next activation point
if len(self.timer_list):
w = self.timer_list[0].getTime()
if w < min:
min = w
self.setNextActivation(min)
def timeChanged(self, timer):
try:
self.timer_list.remove(timer)
except:
pass
self.addTimerEntry(timer)
def doActivate(self, w):
w.activate(w.state)
try:
self.timer_list.remove(w)
except:
pass
w.state += 1
if w.state < TimerEntry.StateEnded:
bisect.insort(self.timer_list, w)
else:
if (w.repeated == 0):
bisect.insort(self.processed_timers, w)
else:
w.processRepeated()
w.state = TimerEntry.StateWait
self.timeChanged(w)
def processActivation(self):
t = int(time.time()) + 1
# we keep on processing the first entry until it goes into the future.
while len(self.timer_list) and self.timer_list[0].getTime() < t:
self.doActivate(self.timer_list[0])
|