Quellcode durchsuchen

wait for alarm in main loop (fixes alarm after commit 986b9e651add7a2cc913cc8b45fbc73c93fd9f4f)

Fabian Peter Hammerle vor 2 Jahren
Ursprung
Commit
8f88dd0de9
1 geänderte Dateien mit 44 neuen und 37 gelöschten Zeilen
  1. 44 37
      vibrating_alarm_m5stickc.py

+ 44 - 37
vibrating_alarm_m5stickc.py

@@ -39,6 +39,15 @@ def _get_current_daytime() -> int:
     return (hour * 60 + minute) * 60 + seconds
 
 
+def _sleep(duration_seconds: int) -> None:
+    # TODO turn off display
+    axp.setLcdBrightness(30)
+    machine.lightsleep(duration_seconds * 1000)
+    # TODO turn on display
+    axp.setLcdBrightness(100)
+    print("wake reason:", machine.wake_reason())
+
+
 class _AlarmConfig:
     def __init__(self):
         self._hour = 0
@@ -63,9 +72,13 @@ class _AlarmConfig:
         return (self._hour * 60 + self._minute) * 60
 
     @property
-    def seconds_until_next(self) -> int:
+    def _seconds_until_next(self) -> int:
         return (self._daytime - _get_current_daytime() - 1) % (24 * 60 * 60) + 1
 
+    @property
+    def next_time(self) -> int:
+        return utime.time() + self._seconds_until_next
+
     def load(self, path: str) -> None:
         with open(path, "r") as alarm_time_file:
             alarm_time = json.load(alarm_time_file)
@@ -86,11 +99,11 @@ class App:
         self._clock_text_box = None
         self._menu_position = 0
         self._wait_for_sleep_start_time_update = False
-        self._sleep_start_time_seconds = 0.0
+        self._sleep_start_time = 0.0
         self._alarm_config = _AlarmConfig()
+        self._next_alarm_time = self._alarm_config.next_time
         self._alarm_hour_text_box = None
         self._alarm_minute_text_box = None
-        self._alarm_timer = None
         self._battery_status_text_box = None
 
     def _reschedule_sleep(self, interrupt: bool) -> None:
@@ -98,7 +111,7 @@ class App:
             self._wait_for_sleep_start_time_update = True
             micropython.schedule(self._reschedule_sleep, False)
         else:
-            self._sleep_start_time_seconds = utime.time() + _AWAKE_SECONDS
+            self._sleep_start_time = utime.time() + _AWAKE_SECONDS
             self._wait_for_sleep_start_time_update = False
 
     def _update_menu(self, event_arg: None) -> None:
@@ -120,35 +133,28 @@ class App:
         # https://docs.micropython.org/en/latest/library/micropython.html#micropython.schedule
         micropython.schedule(self._update_menu, None)
 
-    @staticmethod
-    def _alert() -> None:
+    def _alarm(self) -> None:
         print("ALARM")
-
-    def _alarm(self, timer: machine.Timer) -> None:
-        # pylint: disable=unused-argument; callback
-        micropython.schedule(lambda n: self._alert(), None)
-        micropython.schedule(lambda n: self._configure_alarm_timer(), None)
-
-    def _configure_alarm_timer(self) -> None:
-        seconds_until_alarm = self._alarm_config.seconds_until_next
-        print("alarm in ", seconds_until_alarm / 60, " min")
-        # TODO configure wake from sleep
-        self._alarm_timer.init(  # type: ignore
-            period=seconds_until_alarm * 1000,  # ms
-            mode=machine.Timer.ONE_SHOT,
-            callback=self._alarm,
-        )
+        utime.sleep(1)  # seconds
+        print("alarm end")
+        self._next_alarm_time = self._alarm_config.next_time
+        print(
+            "new alarm in", (self._next_alarm_time - utime.time()) / 60, "min"
+        )  # TODO remove
 
     def _update_alarm_time(self, event_arg: None) -> None:
         # pylint: disable=unused-argument; callback
+        self._next_alarm_time = self._alarm_config.next_time
+        print(
+            "alarm in", (self._next_alarm_time - utime.time()) / 60, "min"
+        )  # TODO remove
+        self._alarm_config.save(_ALARM_TIME_PATH)
         self._alarm_hour_text_box.setText(  # type: ignore
             "{:02d}".format(self._alarm_config.hour)
         )
         self._alarm_minute_text_box.setText(  # type: ignore
             "{:02d}".format(self._alarm_config.minute)
         )
-        self._alarm_config.save(_ALARM_TIME_PATH)
-        self._configure_alarm_timer()
 
     def _button_b_pressed(self) -> None:
         self._reschedule_sleep(interrupt=True)
@@ -209,9 +215,6 @@ class App:
             _DEFAULT_FONT_COLOR,
             rotate=90,
         )
-        # machine.Timer(1).init(...) breaks button handling
-        self._alarm_timer = machine.Timer(2)
-        self._configure_alarm_timer()
 
     def _update_battery_status_info(self) -> None:
         self._battery_status_text_box.setText(  # type: ignore
@@ -238,19 +241,23 @@ class App:
         # not sure whether ext0 would be better
         esp32.wake_on_ext1([btnA.pin], esp32.WAKEUP_ALL_LOW)
         self._reschedule_sleep(interrupt=False)
+        self._update_battery_status_info()
         while True:
-            self._update_battery_status_info()
-            while utime.time() < self._sleep_start_time_seconds:
-                utime.sleep(1)  # seconds
-            # TODO turn off display
-            axp.setLcdBrightness(30)
-            machine.lightsleep()
-            # TODO turn on display
-            axp.setLcdBrightness(100)
-            print("wake reason:", machine.wake_reason())
-            _handle_pending_events()
-            while self._wait_for_sleep_start_time_update:
+            seconds_until_alarm = self._next_alarm_time - utime.time()
+            print("seconds_until_alarm =", seconds_until_alarm)  # TODO remove
+            if seconds_until_alarm <= 0:
+                self._alarm()
+            elif seconds_until_alarm < _AWAKE_SECONDS:
+                utime.sleep(seconds_until_alarm)
+            elif utime.time() < self._sleep_start_time:
+                utime.sleep(1)  # second
+            else:
+                _sleep(duration_seconds=seconds_until_alarm)
                 _handle_pending_events()
+                self._update_battery_status_info()
+                print("updated battery info")  # TODO remove
+                while self._wait_for_sleep_start_time_update:
+                    _handle_pending_events()
 
 
 App().run()