Beispiel #1
0
async def periodical_tasks(context):
    """
    Periodical tasks, started from webswitch.WebServer.feed_watchdog
    """
    if context.ntp_last_sync_epoch > 0:  # A NTP sync was successful in the past

        # Sets relay switch on/off on schedule and manual override:

        from power_timer import update_power_timer
        update_power_timer(context)

        del update_power_timer
        del sys.modules['power_timer']
        gc.collect()

    # Ensure that the device is connected to the WiFi:

    from wifi import ensure_connection
    is_connected = ensure_connection(context)

    del ensure_connection
    del sys.modules['wifi']
    gc.collect()

    if is_connected:
        # Sync the RTC time via NTP:

        from ntp import ntp_sync
        ntp_sync(context)

        del ntp_sync
        del sys.modules['ntp']
        gc.collect()
Beispiel #2
0
    def test_update_relay_switch_without_timers(self):
        with mock_py_config_context():
            assert restore_timers() == ()

            update_power_timer(self.context)

            print(get_info_text(self.context))
            self.assertEqual(get_current_timer(self.context),
                             (None, None, None))
    async def get_request(self, request_line):
        update_power_timer(self.context)
        reader = asynctest.mock.Mock(StreamReader)
        writer = StreamWriter()

        reader.readline.return_value = request_line

        await self.web_server.request_handler(reader, writer)

        return writer.get_response()
Beispiel #4
0
def assert_current_timer(reference, context):
    # Load timers:
    context.power_timer_timers = None
    update_power_timer(context)

    previous_epoch, turn_on, next_epoch = get_current_timer(context)
    assert next_epoch is not None, 'No timers?!?'
    text = '%i %s %02i:%02i %s -> %i %s %02i:%02i %s -> %s' % (
        (previous_epoch, ) + epoch_info(previous_epoch) +
        (next_epoch, ) + epoch_info(next_epoch) +
        ('ON' if turn_on else 'OFF', ))
    assert text == reference
Beispiel #5
0
    async def feed_watchdog(self):
        """
        Start some periodical tasks and feed the watchdog
        """
        while True:

            gc.collect()

            from power_timer import update_power_timer
            if update_power_timer(self.context) is not True:
                from reset import ResetDevice
                ResetDevice(reason='Update power timer error').reset()

            del update_power_timer
            del sys.modules['power_timer']
            gc.collect()

            from ntp import ntp_sync
            if ntp_sync(self.context) is not True:
                from reset import ResetDevice
                ResetDevice(reason='NTP sync error').reset()

            del ntp_sync
            del sys.modules['ntp']
            gc.collect()

            self.context.watchdog.feed()

            gc.collect()
            await uasyncio.sleep(constants.WATCHDOG_TIMEOUT)
Beispiel #6
0
    def test_update_relay_switch_in_1min(self):
        machine.RTC().deinit()  # start time from 1.1.2000 00:00
        with mock_py_config_context():
            save_timers((((0, 1), (1, 0)), ))
            save_active_days((0, 1, 2, 3, 4, 5, 6))

            assert machine.RTC().datetime((2000, 1, 1, 6, 0, 0, 0, 0))
            assert localtime_isoformat(sep=' ') == '2000-01-01 00:00:00'

            timers = restore_timers()
            assert pformat_timers(timers) == '00:01 - 01:00'
            assert list(iter_times(timers)) == [(True, (0, 1, 0)),
                                                (False, (1, 0, 0))]

            update_power_timer(self.context)
            self.assertEqual(get_info_text(self.context),
                             'Switch on in 1 min at 00:01 h.')
Beispiel #7
0
    def test_update_relay_switch_today_not_active(self):
        machine.RTC().deinit()  # start time from 1.1.2000 00:00
        with mock_py_config_context():
            save_timers((((1, 0), (2, 0)), ))
            save_active_days((0, 1, 2, 3, 4, 6))  # <- day 5 is missing

            assert machine.RTC().datetime((2000, 1, 1, 5, 0, 0, 0, 0))
            assert localtime_isoformat(sep=' ') == '2000-01-01 00:00:00'

            update_power_timer(self.context)
            print(get_info_text(self.context))

            assert active_today() is False
            assert self.context.power_timer_today_active is False

            self.assertEqual(get_info_text(self.context),
                             'Power timer is not active today.')
Beispiel #8
0
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_get_current_timer(self):
        with mock_py_config_context():
            save_timers((
                ((0, 0), (0, 1)),
                ((0, 2), (0, 3)),
            ))
            update_power_timer(self.context)

            rtc = machine.RTC()
            rtc.datetime((2000, 1, 1, 5, 0, 0, 0, 0))  # 00:00
            assert get_current_timer(self.context) == (0, False, 60)

            rtc.datetime((2000, 1, 1, 5, 0, 1, 0, 0))  # 00:01
            assert get_current_timer(self.context) == (60, True, 120)

            rtc.datetime((2000, 1, 1, 5, 0, 2, 0, 0))  # 00:02
            assert get_current_timer(self.context) == (120, False, 180)

            rtc.datetime((2000, 1, 1, 5, 0, 3, 0, 0))  # 00:03 -> next timer is on next day!
            assert get_current_timer(self.context) == (180, True, 86400)
Beispiel #10
0
def run_all_times_utils_tests():

    print('test parse_timers()...', end=' ')
    results = tuple(
        parse_timers('''
        0:00 - 1:00
        1:23 - 4:56
        19:00 - 20:00
        22:01 - 22:30
        23:12 - 23:59
    '''))
    assert results == (((0, 0), (1, 0)), ((1, 23), (4, 56)), ((19, 0), (20,
                                                                        0)),
                       ((22, 1), (22, 30)), ((23, 12), (23, 59))), results
    print('OK\n')

    print('test not existing "timers.txt"...', end=' ')
    try:
        uos.remove('_config_timers.py')
    except OSError:
        pass
    results = tuple(restore_timers())
    assert results == (), results
    print('OK\n')

    print('test not existing "timer_days.txt"...', end=' ')
    try:
        uos.remove('_config_timer_days.py')
    except OSError:
        pass
    results = tuple(get_active_days())
    assert results == (0, 1, 2, 3, 4, 5, 6), results
    print('OK\n')

    print('test save_active_days()...', end=' ')
    save_active_days(active_days=(0, 1, 2, 3, 4))
    results = tuple(get_active_days())
    assert results == (0, 1, 2, 3, 4), results
    print('OK\n')

    context = Context()

    save_timers([])
    results = tuple(restore_timers())
    assert results == (), results
    update_power_timer(context)
    assert get_current_timer(context) == (None, None, None)

    save_timers([
        ((6, 0), (7, 0)),
    ])
    results = tuple(restore_timers())
    assert results == (((6, 0), (7, 0)), ), results

    rtc = machine.RTC()
    rtc.datetime(
        (2000, 1, 2, 6, 0, 0, 0, 0))  # set RTC time: 2.1.2000 00:00:00
    assert_current_timer(  # Turn ON at 06:00
        '25200 -17 h 07:00 2000-01-01T07:00:00 -> 108000 6 h 06:00 2000-01-02T06:00:00 -> ON',
        context)

    rtc.datetime(
        (2000, 1, 2, 6, 5, 59, 59, 0))  # set RTC time: 2.1.2000 05:59:59
    assert_current_timer(  # Turn ON at 06:00
        '25200 -22 h 07:00 2000-01-01T07:00:00 -> 108000 1 sec 06:00 2000-01-02T06:00:00 -> ON',
        context)

    rtc.datetime(
        (2000, 1, 2, 6, 6, 0, 0, 0))  # set RTC time: 2.1.2000 06:00:00
    assert_current_timer(  # Turn ON at 06:00
        '108000 0 sec 06:00 2000-01-02T06:00:00 -> 111600 60 min 07:00 2000-01-02T07:00:00 -> OFF',
        context)

    rtc.datetime(
        (2000, 1, 2, 6, 6, 59, 59, 0))  # set RTC time: 2.1.2000 06:59:59
    assert_current_timer(  # Turn OFF at 07:00
        '108000 -59 min 06:00 2000-01-02T06:00:00 -> 111600 1 sec 07:00 2000-01-02T07:00:00 -> OFF',
        context)

    rtc.datetime(
        (2000, 1, 2, 6, 7, 0, 0, 0))  # set RTC time: 2.1.2000 07:00:00
    assert_current_timer(  # Turn ON next day at 06:00
        '111600 0 sec 07:00 2000-01-02T07:00:00 -> 194400 23 h 06:00 2000-01-03T06:00:00 -> ON',
        context)

    save_timers([
        ((6, 0), (7, 0)),
        ((19, 30), (22, 30)),
    ])
    rtc.datetime(
        (2000, 1, 2, 6, 0, 0, 0, 0))  # set RTC time: 2.1.2000 00:00:00
    assert_current_timer(  # Turn ON at 06:00
        '81000 -90 min 22:30 2000-01-01T22:30:00 -> 108000 6 h 06:00 2000-01-02T06:00:00 -> ON',
        context)

    rtc.datetime(
        (2000, 1, 2, 6, 7, 0, 1, 0))  # set RTC time: 2.1.2000 07:00:01
    assert_current_timer(  # Turn ON at 19:30
        '111600 -1 sec 07:00 2000-01-02T07:00:00 -> 156600 12 h 19:30 2000-01-02T19:30:00 -> ON',
        context)

    rtc.datetime(
        (2000, 1, 2, 6, 20, 12, 0, 0))  # set RTC time: 2.1.2000 20:12:00
    assert_current_timer(  # Turn OFF at 22:30
        '156600 -42 min 19:30 2000-01-02T19:30:00 -> 167400 2 h 22:30 2000-01-02T22:30:00 -> OFF',
        context)

    rtc.datetime(
        (2000, 1, 2, 6, 22, 30, 1, 0))  # set RTC time: 2.1.2000 22:30:01
    assert_current_timer(  # Turn ON next day at 06:00
        '167400 -1 sec 22:30 2000-01-02T22:30:00 -> 194400 7 h 06:00 2000-01-03T06:00:00 -> ON',
        context)
Beispiel #11
0
    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/')