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
|
from abc import ABCMeta, abstractmethod
from datetime import datetime, timedelta
from typing import Optional, Union
from ..utils import property_fetcher
class Relay(metaclass=ABCMeta):
def __init__(self, device, index, *args, **kwargs):
self._device = device
self._index = index
self._ison = None
self._timer_start = None
self._timer_end = None
def __repr__(self):
class_name = self.__class__.__name__
return f"{class_name}{self.index}(on={self.ison})"
@abstractmethod
def toggle(self, timer: Optional[int] = None):
pass
@abstractmethod
def on(self, timer: Optional[int] = None):
pass
@abstractmethod
def off(self, timer: Optional[int] = None):
pass
def turn(self, value: Union[str, bool], timer: Optional[int] = None):
value_method = {
"toggle": self.toggle,
"on": self.on,
"off": self.off,
True: self.on,
False: self.off
}
return value_method[value](timer)
@property
def index(self) -> int:
return self._index
@property
@property_fetcher()
def ison(self) -> bool:
return bool(self._ison)
@property
def has_timer(self) -> bool:
"""
return true when the timer is primed and has not happened yet
"""
start = self._timer_start
end = self._timer_end
if not start or not end:
return False
date_now = datetime.now()
return end > date_now and start < date_now
@property
@property_fetcher()
def timer_started(self) -> Optional[datetime]:
if self.has_timer:
return self._timer_start
return None
@property
def timer_duration(self) -> Optional[timedelta]:
# fetch the start before to populate the implementation values
if not self.has_timer:
return None
start = self.timer_started
end = self._timer_end
return end - start
@abstractmethod
def update(self) -> None:
pass
|