Sfoglia il codice sorgente

day_state and day_events implemented as helpers

tags/v1.2.2^0
Dirk Alders 1 anno fa
parent
commit
f0a05612bd
4 ha cambiato i file con 118 aggiunte e 9 eliminazioni
  1. 13
    0
      function/first_floor_east.py
  2. 101
    5
      function/helpers.py
  3. 3
    2
      function/modules.py
  4. 1
    2
      smart_brain.py

+ 13
- 0
function/first_floor_east.py Vedi File

@@ -4,6 +4,7 @@
4 4
 
5 5
 import config
6 6
 import devices
7
+from function.helpers import day_event
7 8
 from function.modules import brightness_choose_n_action, timer_on_activation, heating_function
8 9
 from function.rooms import room, room_collection
9 10
 from function.videv import videv_switching, videv_switch_brightness, videv_switching_timer, videv_switch_brightness_color_temp, videv_heating, videv_multistate
@@ -81,6 +82,8 @@ class first_floor_east_dining(room):
81 82
         #
82 83
         # Device initialisation
83 84
         #
85
+        self.day_events = day_event((6, 0), (22, 0), 30, -30)
86
+
84 87
         # http://shelly1l-84CCA8ADD055
85 88
         self.main_light_shelly = devices.shelly(mqtt_client, config.TOPIC_FFE_DININGROOM_MAIN_LIGHT_SHELLY)
86 89
         self.floorlamp_powerplug = devices.silvercrest_powerplug(mqtt_client, config.TOPIC_FFE_DININGROOM_FLOOR_LAMP_POWERPLUG)
@@ -91,6 +94,8 @@ class first_floor_east_dining(room):
91 94
         #
92 95
         # Functionality initialisation
93 96
         #
97
+        self.day_events.add_callback(None, True, self.__day_events__, True)
98
+
94 99
         self.main_light_shelly.add_callback(devices.shelly.KEY_OUTPUT_0, None, self.floorlamp_powerplug.set_output_0_mcb, True)
95 100
 
96 101
         #
@@ -110,6 +115,14 @@ class first_floor_east_dining(room):
110 115
                 self.garland_powerplug, devices.silvercrest_powerplug.KEY_OUTPUT_0
111 116
             )
112 117
 
118
+    def __day_events__(self, device, key, data):
119
+        if key in (self.day_events.KEY_SUNSET, self.day_events.KEY_START_OF_DAY):
120
+            if config.CHRISTMAS:
121
+                self.garland_powerplug.set_output_0(True)
122
+        elif key in (self.day_events.KEY_START_OF_NIGHT, self.day_events.KEY_SUNRISE):
123
+            if config.CHRISTMAS:
124
+                self.garland_powerplug.set_output_0(False)
125
+
113 126
 
114 127
 class first_floor_east_sleep(room):
115 128
     def __init__(self, mqtt_client):

+ 101
- 5
function/helpers.py Vedi File

@@ -1,9 +1,10 @@
1 1
 #!/usr/bin/env python
2 2
 # -*- coding: utf-8 -*-
3 3
 #
4
+from base import common_base
4 5
 import config
5 6
 import geo
6
-import inspect
7
+import task
7 8
 import time
8 9
 
9 10
 
@@ -11,9 +12,104 @@ def now():
11 12
     return time.mktime(time.localtime())
12 13
 
13 14
 
14
-def sunrise_time(time_offs_min=30):
15
-    return time.mktime(geo.sun.sunrise(config.GEO_POSITION)) + time_offs_min * 60
15
+def next_sunrise_time(time_offs_min=30):
16
+    tm = now()
17
+    rv = time.mktime(geo.sun.sunrise(config.GEO_POSITION)) + time_offs_min * 60
18
+    if tm > rv:
19
+        rv = time.mktime(geo.sun.sunrise(config.GEO_POSITION, date=time.localtime(tm + 24 * 60 * 60))) + time_offs_min * 60
20
+    return rv
16 21
 
17 22
 
18
-def sunset_time(time_offs_min=-30):
19
-    return time.mktime(geo.sun.sunset(config.GEO_POSITION)) + time_offs_min * 60
23
+def next_sunset_time(time_offs_min=-30):
24
+    tm = now()
25
+    rv = time.mktime(geo.sun.sunset(config.GEO_POSITION)) + time_offs_min * 60
26
+    if tm > rv:
27
+        rv = time.mktime(geo.sun.sunset(config.GEO_POSITION, date=time.localtime(tm + 24 * 60 * 60))) + time_offs_min * 60
28
+    return rv
29
+
30
+
31
+def next_user_time(hh, mm):
32
+    ts = time.localtime()
33
+    tm = time.mktime(ts)
34
+    ut_ts = list(ts)
35
+    ut_ts[3] = hh
36
+    ut_ts[4] = mm
37
+    ut = time.mktime(time.struct_time(list(ts[:3]) + [hh, mm, 0] + list(ts[6:])))
38
+    if ts[3] > hh or (ts[3] == hh and ts[4] >= mm):
39
+        ut += 24 * 60 * 60
40
+    #
41
+    return ut
42
+
43
+
44
+class day_state(common_base):
45
+    """
46
+    Class to subscribe day events as a callback (see add_callback)
47
+
48
+    :param time_start_of_day: Time of a day (tuple including hour and minute) for start of day or None for no start of day state.
49
+    :type time_start_of_day: tuple
50
+    :param time_start_of_night: Time of a day (tuple including hour and minute) for start of night or None for no end of day state.
51
+    :type time_start_of_night:  tuple
52
+    :param time_offset_sunrise: time offset for sunrise in minutes (negative values lead to earlier sunrise state) or None for no sunrise state.
53
+    :type time_start_of_day: int
54
+    :param time_offset_sunset: time offset for sunset in minutes (negative values lead to earlier sunset state) or None for no sunrise state.
55
+    :type time_start_of_day: int
56
+    """
57
+    KEY_SUNRISE = 'sunrise'
58
+    KEY_SUNSET = 'sunset'
59
+    KEY_START_OF_NIGHT = 'start_of_night'
60
+    KEY_START_OF_DAY = 'start_of_day'
61
+    #
62
+    STATES = (KEY_START_OF_DAY, KEY_SUNRISE, KEY_SUNSET, KEY_START_OF_NIGHT)
63
+
64
+    def __init__(self, time_start_of_day, time_start_of_night, time_offset_sunrise, time_offset_sunset):
65
+        self.__time_start_of_day__ = time_start_of_day
66
+        self.__time_start_of_night__ = time_start_of_night
67
+        self.__time_offset_sunrise__ = time_offset_sunrise
68
+        self.__time_offset_sunset__ = time_offset_sunset
69
+        super().__init__()
70
+        #
71
+
72
+    def get_state(self):
73
+        tm = {}
74
+        if self.__time_offset_sunrise__ is not None:
75
+            tm[next_sunrise_time(self.__time_offset_sunrise__)] = self.KEY_SUNRISE
76
+        if self.__time_start_of_day__ is not None:
77
+            tm[next_user_time(*(self.__time_start_of_day__))] = self.KEY_START_OF_DAY
78
+        if self.__time_offset_sunset__ is not None:
79
+            tm[next_sunset_time(self.__time_offset_sunset__)] = self.KEY_SUNSET
80
+        if self.__time_start_of_night__ is not None:
81
+            tm[next_user_time(*(self.__time_start_of_night__))] = self.KEY_START_OF_NIGHT
82
+        #
83
+        tms = list(tm.keys())
84
+        tms.sort()
85
+        return tm[tms[-1]]
86
+
87
+
88
+class day_event(day_state):
89
+    """
90
+    Class to subscribe day events as a callback (see add_callback)
91
+
92
+    :param time_start_of_day: Time of a day (tuple including hour and minute) for start of day or None for no start of day state.
93
+    :type time_start_of_day: tuple
94
+    :param time_start_of_night: Time of a day (tuple including hour and minute) for start of night or None for no end of day state.
95
+    :type time_start_of_night:  tuple
96
+    :param time_offset_sunrise: time offset for sunrise in seconds (negative values lead to earlier sunrise state) or None for no sunrise state.
97
+    :type time_start_of_day: int
98
+    :param time_offset_sunset: time offset for sunset in seconds (negative values lead to earlier sunset state) or None for no sunrise state.
99
+    :type time_start_of_day: int
100
+    """
101
+
102
+    def __init__(self, time_start_of_day=(6, 0), time_start_of_night=(22, 0), time_offset_sunrise=30, time_offset_sunset=-30):
103
+        super().__init__(time_start_of_day, time_start_of_night, time_offset_sunrise, time_offset_sunset)
104
+        #
105
+        current_day_state = self.get_state()
106
+        for key in self.STATES:
107
+            self[key] = current_day_state == key
108
+        #
109
+        cyclic = task.periodic(30, self.__cyclic__)
110
+        cyclic.run()
111
+
112
+    def __cyclic__(self, a):
113
+        current_day_state = self.get_state()
114
+        for key in self.STATES:
115
+            self.set(key, current_day_state == key)

+ 3
- 2
function/modules.py Vedi File

@@ -15,7 +15,7 @@ from base import common_base
15 15
 import config
16 16
 import devices
17 17
 from function.db import get_radiator_data, set_radiator_data
18
-from function.helpers import now, sunset_time, sunrise_time
18
+from function.helpers import day_state
19 19
 import logging
20 20
 import task
21 21
 
@@ -300,7 +300,8 @@ class motion_sensor_light(common_base):
300 300
             if arg_device.topic == device.topic:
301 301
                 break
302 302
         self.set(self.KEY_MOTION_SENSOR % sensor_index, data)
303
-        if now() < sunrise_time(60) or now() > sunset_time(-60):
303
+        # auto light on with state sunset -> time_offset_sunrise=60 (longer sunset) and time_offset_sunset=-60 (longer sunset)
304
+        if day_state(None, None, 60, -60).get_state() == self.day_status.KEY_SUNSET:
304 305
             if data is True:
305 306
                 logger.info("%s: Motion detected - Switching on main light %s", device.topic, self.sw_device.topic)
306 307
                 self.sw_method(True)

+ 1
- 2
smart_brain.py Vedi File

@@ -10,11 +10,10 @@ import time
10 10
 
11 11
 logger = logging.getLogger(config.APP_NAME)
12 12
 
13
-# TODO: implement garland (incl. day events like sunset, sunrise, ...)
14 13
 
15 14
 VERS_MAJOR = 1
16 15
 VERS_MINOR = 2
17
-VERS_PATCH = 1
16
+VERS_PATCH = 2
18 17
 
19 18
 INFO_TOPIC = "__info__"
20 19
 INFO_DATA = {

Loading…
Annulla
Salva