def test_mock_py_config_context_with_timers(self):
        with mock_py_config_context():
            save_timers((((1, 2), (3, 4)), ))
            assert restore_timers() == (((1, 2), (3, 4)), )

            save_timers((((5, 6), (7, 8)), ))
            assert restore_timers() == (((5, 6), (7, 8)), )
async def get_form(server, reader, writer, querystring, body):
    from times_utils import restore_timers, pformat_timers, get_active_days
    timers = pformat_timers(restore_timers())
    active_days = get_active_days()
    del restore_timers
    del pformat_timers
    del get_active_days
    del sys.modules['times_utils']
    gc.collect()

    context = {
        'timers': timers,
        'on_selected': 'selected' if server.context.power_timer_active else '',
        'off_selected':
        '' if server.context.power_timer_active else 'selected',
    }
    for day_no in range(7):
        context['d%i' % day_no] = 'checked' if day_no in active_days else ''

    from template import render
    await server.send_html_page(
        writer,
        filename='webswitch.html',
        content_iterator=render(filename='http_set_timer.html',
                                context=context,
                                content_iterator=None),
    )
예제 #3
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 test_sort_timers(self):

        # send not ordered timer list:
        #   21:30 - 22:45
        #   07:00 - 08:00

        response = await self.get_request(
            request_line=(b"GET"
                          b" /set_timer/submit/"
                          b"?timers=21%3A30+-+22%3A45%0D%0A07%3A00+-+08%3A00"
                          b" HTTP/1.1"))
        assert response == b'HTTP/1.0 303 Moved\r\nLocation: /set_timer/form/\r\n\r\n'
        assert self.web_server.message == 'Timers saved and deactivated.'

        timers = pformat_timers(restore_timers())
        assert timers == '07:00 - 08:00\n21:30 - 22:45'
예제 #5
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.')
    async def test_set_timer(self):

        # Set timer:

        response = await self.get_request(request_line=(
            b"GET"
            b" /set_timer/submit/"
            b"?timers=07%3A00+-+08%3A00%0D%0A20%3A00+-+22%3A35"
            b"&d0=on&d1=on&d2=on&d3=on&d4=on"  # only MO-FR, not SA+SU
            b"&active=on"
            b" HTTP/1.1"))
        assert response == b'HTTP/1.0 303 Moved\r\nLocation: /set_timer/form/\r\n\r\n'
        assert self.web_server.message == 'Timers saved and activated.'

        timers = pformat_timers(restore_timers())
        assert timers == '07:00 - 08:00\n20:00 - 22:35'

        active_days = tuple(get_active_days())
        assert active_days == (0, 1, 2, 3, 4)  # only MO-FR, not SA+SU

        assert get_dict_from_rtc() == {'active': True, 'manual-type': None}

        assert active_today() is True

        # Request the form:

        response = await self.get_request(
            request_line=b"GET /set_timer/form/ HTTP/1.1")
        self.assert_response_parts(
            response,
            parts=('HTTP/1.0 200 OK', '<html>',
                   '<title>network name-04030201 - OFF</title>',
                   '<p>Power switch state: <strong>OFF</strong></p>',
                   '<p><strong>Switch on in 6 h at 20:00 h.</strong></p>',
                   '<p>Timers saved and activated.</p>',
                   '<textarea name="timers" rows="6" cols="13">07:00 - 08:00',
                   '20:00 - 22:35</textarea>',
                   '<option value="on" selected>ON</option>',
                   'RAM total: 1.95 KB, used: 0.98 KB, free: 0.98 KB<br>',
                   'Server local time: 2019-05-01 13:12:11', '</html>'))
        assert self.web_server.message == 'Timers saved and activated.'
예제 #7
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)
예제 #8
0
        '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)


if __name__ == '__main__':
    print('Run tests on device...')

    import sys
    sys.modules.clear()

    import gc
    gc.collect()

    timers = restore_timers()
    active_days = tuple(get_active_days())
    try:
        run_all_times_utils_tests()
    finally:
        if timers is not None:
            save_timers(timers)
        if active_days is None:
            save_active_days(active_days)

    print('OK\n')
예제 #9
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.')
예제 #10
0
def update_power_timer(context):
    """
    Sets relay switch on/off on schedule and manual override.
    Called from tasks.periodical_tasks()
    """
    gc.collect()
    if __debug__:
        print('Update power timer:', utime.time())

    from times_utils import restore_timers
    context.power_timer_timers = restore_timers()
    del restore_timers
    del sys.modules['times_utils']
    gc.collect()

    from rtc import get_dict_from_rtc
    rtc_memory_dict = get_dict_from_rtc()

    context.power_timer_active = rtc_memory_dict.get(
        constants.POWER_TIMER_ACTIVE_KEY, True)

    manual_overwrite = rtc_memory_dict.get(constants.RTC_KEY_MANUAL_OVERWRITE,
                                           0)
    current_state = rtc_memory_dict.get(
        constants.RTC_KEY_MANUAL_OVERWRITE_TYPE)
    if __debug__ and current_state:
        print('manual overwrite:', repr(current_state))

    del rtc_memory_dict
    del sys.modules['rtc']
    gc.collect()

    context.power_timer_today_active = active_today()

    if context.power_timer_active and context.power_timer_today_active:
        if __debug__:
            print('Update power timer state')
        from times_utils import get_current_timer
        last_timer_epoch, turn_on, context.power_timer_next_timer_epoch = get_current_timer(
            context)

        del get_current_timer
        del sys.modules['times_utils']
        gc.collect()

        context.power_timer_turn_on = turn_on

        if last_timer_epoch is None:
            if __debug__:
                print('No timer scheduled')
        else:
            if current_state is None or manual_overwrite < last_timer_epoch:
                if __debug__:
                    print('Set state from timer')
                # Note:
                # The current power state is the **opposite** of the next one.
                # In other words: If the **next** timer will "turn on" (==True) then we are
                # now in a "OFF" phase ;)
                current_state = not turn_on

    if current_state is None:
        if __debug__:
            print('No timer to scheduled and no manual overwrite')
    elif current_state:
        if __debug__:
            print('Switch on')
        Pins.relay.on()
    else:
        if __debug__:
            print('Switch off')
        Pins.relay.off()

    gc.collect()