def irq_handler(self, pin): Pins.power_led.off() button_value = get_debounced_value(pin) print('button_value:', button_value) if button_value == 0: # button pressed self.down_start = utime.ticks_ms() elif button_value == 1: # button released Pins.power_led.on() duration_ms = utime.ticks_diff(utime.ticks_ms(), self.down_start) print('duration_ms:', duration_ms) if duration_ms > 2000: from reset import ResetDevice ResetDevice('After button long press').reset() else: print('Overwrite via button press') if Pins.relay.is_on: Pins.relay.off() overwrite_type = False else: Pins.relay.on() overwrite_type = True from rtc import update_rtc_dict update_rtc_dict({ constants.RTC_KEY_MANUAL_OVERWRITE: utime.time(), constants.RTC_KEY_MANUAL_OVERWRITE_TYPE: overwrite_type })
def __init__(self, reason): print('Reset reason: %r' % reason) self.reason = reason from rtc import update_rtc_dict # Save reason in RTC RAM: update_rtc_dict(data={constants.RTC_KEY_RESET_REASON: reason})
def main(): import sys sys.modules.clear() from button_handler import Button from pins import Pins # Init device button IRQ: Pins.button_pin.irq(Button().irq_handler) from context import Context context = Context() import wifi wifi.init(context) del sys.modules['wifi'] _RTC_KEY_RUN = 'run' _RUN_WEB_SERVER = 'web-server' _RUN_SOFT_OTA = 'soft-ota' from rtc import get_rtc_value if get_rtc_value(_RTC_KEY_RUN) == _RUN_WEB_SERVER: print('start webserver') from rtc import update_rtc_dict update_rtc_dict(data={_RTC_KEY_RUN: _RUN_SOFT_OTA}) # run OTA client on next boot del update_rtc_dict del get_rtc_value del sys.modules['rtc'] # init Watchdog timer from watchdog import Watchdog context.watchdog = Watchdog(context) from webswitch import WebServer WebServer(context=context, version=__version__).run() else: print('start "soft" OTA') Pins.power_led.off() from rtc import update_rtc_dict update_rtc_dict(data={_RTC_KEY_RUN: _RUN_WEB_SERVER}) # run web server on next boot from ota_client import SoftOtaUpdate SoftOtaUpdate().run() from reset import ResetDevice ResetDevice(reason='unknown').reset()
async def _switch(server, writer, turn_on): """ We only save the 'manual overwrite' information to RTC RAM and set the 'message'. The update_relay_switch() will turn on/off the relay switch """ server.message = 'power %s' % ('on' if turn_on else 'off') from rtc import update_rtc_dict update_rtc_dict({ constants.RTC_KEY_MANUAL_OVERWRITE: utime.time(), constants.RTC_KEY_MANUAL_OVERWRITE_TYPE: turn_on }) from power_timer import update_power_timer update_power_timer(context=server.context) from http_utils import send_redirect await send_redirect(writer)
def test_relay_switch_timers_and_overwrite(self): rtc = machine.RTC() with mock_py_config_context(): save_timers((((10, 0), (20, 0)), )) timers = restore_timers() assert pformat_timers(timers) == '10:00 - 20:00' assert list(iter_times(timers)) == [(True, (10, 0, 0)), (False, (20, 0, 0))] save_active_days((0, 1, 2, 3, 4, 5, 6)) assert get_active_days() == (0, 1, 2, 3, 4, 5, 6) rtc.datetime( (2000, 1, 2, 6, 0, 0, 0, 0)) # set RTC time: 2.1.2000 00:00:00 assert localtime_isoformat(sep=' ') == '2000-01-02 00:00:00' assert_current_timer( # Turn ON at 10:00 '72000 -4 h 20:00 2000-01-01T20:00:00' ' -> 122400 10 h 10:00 2000-01-02T10:00:00 -> ON', self.context) # init relay in state 'OFF' Pins.relay.off() assert Pins.relay.state == 'OFF' # No manual overwrite and ON timer not yet reached -> OFF and turn ON at 10:00 update_power_timer(self.context) assert active_today() is True assert self.context.power_timer_today_active is True assert Pins.relay.state == 'OFF' self.assertEqual(get_info_text(self.context), 'Switch on in 10 h at 10:00 h.') # 2000-01-01 09:59:59 - timer not yet reached rtc.datetime((2000, 1, 2, 6, 9, 59, 59, 0)) update_power_timer(self.context) assert Pins.relay.state == 'OFF' self.assertEqual(get_info_text(self.context), 'Switch on in 1 sec at 10:00 h.') # 2000-01-01 10:00:00 - turn ON by timer rtc.datetime((2000, 1, 2, 6, 10, 0, 0, 0)) update_power_timer(self.context) assert Pins.relay.state == 'ON' self.assertEqual(get_info_text(self.context), 'Switch off in 10 h at 20:00 h.') # 2000-01-01 20:00:00 - turn OFF by timer rtc.datetime((2000, 1, 2, 6, 20, 0, 0, 0)) update_power_timer(self.context) assert Pins.relay.state == 'OFF' self.assertEqual(get_info_text(self.context), 'Switch on in 14 h at 10:00 h.') # 2000-01-02 09:00:00 - manual overwrite rtc.datetime((2000, 1, 2, 6, 9, 0, 0, 0)) update_rtc_dict({ constants.RTC_KEY_MANUAL_OVERWRITE: utime.time(), constants.RTC_KEY_MANUAL_OVERWRITE_TYPE: True # -> turn ON }) update_power_timer(self.context) assert Pins.relay.state == 'ON' self.assertEqual(get_info_text(self.context), 'Switch on in 60 min at 10:00 h.') # 2000-01-02 09:59:59 - manual overwrite is still active rtc.datetime((2000, 1, 2, 6, 9, 59, 59, 0)) update_power_timer(self.context) assert Pins.relay.state == 'ON' self.assertEqual(get_info_text(self.context), 'Switch on in 1 sec at 10:00 h.') # 2000-01-02 12:00:00 - Normal timer mode, still ON rtc.datetime((2000, 1, 2, 6, 12, 0, 0, 0)) update_power_timer(self.context) assert Pins.relay.state == 'ON' self.assertEqual(get_info_text(self.context), 'Switch off in 8 h at 20:00 h.') # manual overwrite update_rtc_dict({ constants.RTC_KEY_MANUAL_OVERWRITE: utime.time(), constants.RTC_KEY_MANUAL_OVERWRITE_TYPE: False # -> turn OFF }) update_power_timer(self.context) assert Pins.relay.state == 'OFF' self.assertEqual(get_info_text(self.context), 'Switch off in 8 h at 20:00 h.') # 2000-01-02 20:00:00 - Normal timer mode -> switch OFF rtc.datetime((2000, 1, 2, 6, 20, 0, 0, 0)) update_power_timer(self.context) assert Pins.relay.state == 'OFF' self.assertEqual(get_info_text(self.context), 'Switch on in 14 h at 10:00 h.') # manual overwrite update_rtc_dict({ constants.RTC_KEY_MANUAL_OVERWRITE: utime.time(), constants.RTC_KEY_MANUAL_OVERWRITE_TYPE: True # -> turn ON }) update_power_timer(self.context) assert Pins.relay.state == 'ON' self.assertEqual(get_info_text(self.context), 'Switch on in 14 h at 10:00 h.') # 2000-01-01 09:59:59 - timer not yet reached rtc.datetime((2000, 1, 2, 6, 9, 59, 59, 0)) update_power_timer(self.context) assert Pins.relay.state == 'ON' self.assertEqual(get_info_text(self.context), 'Switch on in 1 sec at 10:00 h.')
async def get_submit(server, reader, writer, querystring, body): """ Note: POST request doesn't work: https://forum.micropython.org/viewtopic.php?f=2&t=7432 """ from urllib_parse import request_query2dict data = request_query2dict(querystring) del request_query2dict gc.collect() import times_utils try: timers = tuple(times_utils.parse_timers(data['timers'])) gc.collect() except ValueError as e: gc.collect() server.message = 'Timers error: %s' % e else: print('Save timers:', timers) # Save timers to flash: from config_files import save_py_config save_py_config(module_name=constants.TIMERS_PY_CFG_NAME, value=timers) save_py_config(module_name=constants.ACTIVE_DAYS_PY_CFG_NAME, value=tuple( [no for no in range(7) if 'd%i' % no in data])) del save_py_config del sys.modules['config_files'] gc.collect() power_timer_active = data.get('active') == 'on' del data # can be collected gc.collect() from rtc import update_rtc_dict update_rtc_dict( data={ constants.POWER_TIMER_ACTIVE_KEY: power_timer_active, # # Deactivate manual overwrite, so that timers are used: constants.RTC_KEY_MANUAL_OVERWRITE_TYPE: None, }) del update_rtc_dict del sys.modules['rtc'] gc.collect() # Update power timer: if power_timer_active: server.message = 'Timers saved and activated.' else: server.message = 'Timers saved and deactivated.' # Force set values by update_power_timer(): server.context.power_timer_active = None server.context.power_timer_today_active = None from power_timer import update_power_timer update_power_timer(context=server.context) gc.collect() from http_utils import send_redirect await send_redirect(writer, url='/set_timer/form/')
""" Start "soft" OTA update client. This is normally not needed, see main.py """ if __name__ == '__main__': print('Start "soft" OTA update') import sys sys.modules.clear() import gc gc.collect() from rtc import update_rtc_dict update_rtc_dict(data={'run': 'web-server'}) # run web server on next boot import sys sys.modules.clear() import gc gc.collect() from ota_client import SoftOtaUpdate SoftOtaUpdate().run()
""" Force start OTA update client. This is normally not needed, see main.py """ import gc import sys from rtc import update_rtc_dict if __name__ == '__main__': print('Schedule OTA update via RTC RAM') gc.collect() update_rtc_dict(data={'run': None}) # Save to RTC RAM for next boot print('reset your device by pressing Ctrl-D to start OTA ;)') sys.exit()