Esempio n. 1
0
def test_rounding():
    e = datetime(2018, 12, 13, 2, 0, 0)
    assert time_utils.ceil_dt_hour(datetime.now()) == e
    assert time_utils.ceil_dt_hour(e) == e
    e = time_utils.dt_now_utc().replace(2018, 12, 13, 1, 20, 0)
    assert time_utils.ceil_dt(time_utils.dt_now_utc(),
                              timedelta(minutes=20)) == e
    assert time_utils.ceil_dt(e, timedelta(minutes=20)) == e

    e = datetime(2018, 12, 13, 1, 0, 0)
    assert time_utils.floor_dt_hour(datetime.now()) == e
    assert time_utils.floor_dt_hour(e) == e
    e = time_utils.dt_now_utc().replace(2018, 12, 13, 1, 2, 0)
    assert time_utils.floor_dt(time_utils.dt_now_utc(),
                               timedelta(minutes=1)) == e
    assert time_utils.floor_dt(e, timedelta(minutes=1)) == e

    e = datetime(2018, 12, 13, 1, 0, 0)
    assert time_utils.round_nearest(datetime.now(), timedelta(hours=1)) == e
    assert time_utils.round_nearest(e, timedelta(hours=1)) == e

    assert time_utils.round_nearest(e + timedelta(minutes=30),
                                    timedelta(hours=1)) == e
    assert time_utils.round_nearest(
        e + timedelta(minutes=31),
        timedelta(hours=1)) == e + timedelta(hours=1)
def test_state_storage():
    central_heating_log.clear_old_entries(time_utils.dt_now_local())

    rsp = central_heating_log.query_last_available_state(None)
    assert rsp.success
    assert len(
        rsp.log_entries
    ) <= 1  # Can also be 1 if we have a current state stored in the dbase
    rsp = central_heating_log.query_last_available_state(
        time_utils.dt_now_local())
    assert rsp.success
    assert len(rsp.log_entries) == 0

    def _check(exp_flag, exp_task):
        flag, task = central_heating_log.load_state()
        assert flag == exp_flag
        assert task == exp_task

    central_heating_log.save_state(False, None)
    _check(False, None)

    rsp = central_heating_log.query_last_available_state(None)
    assert rsp.success
    assert len(rsp.log_entries) == 1

    central_heating_log.save_state(True, None)
    _check(True, None)

    for _tp in [RequestType.MANUAL, RequestType.SCHEDULED]:
        for duration in [None, timedelta(seconds=7320)]:
            for temperature in [None, 17.3, 55.01]:
                for hysteresis in [None, 0.5, 1]:
                    t = HeatingTask(request_type=_tp,
                                    user='******',
                                    duration=duration,
                                    temperature_target=temperature,
                                    temperature_hysteresis=hysteresis)  #,
                    # started_at=started_at, ends_at=ends_at)
                    central_heating_log.save_state(False, t)
                    _check(False, t)

    for start in [time_utils.dt_now_utc(), time_utils.dt_now_local()]:
        for duration in [timedelta(minutes=25), timedelta(hours=2, minutes=3)]:
            t = HeatingTask(RequestType.SCHEDULED, 'PyTest',
                            timedelta(minutes=15), None, None)
            t.start()  # To automatically set the end time
            central_heating_log.save_state(True, t)
            _check(True, t)

    assert central_heating_log.query(None, None).success
    assert central_heating_log.query(None, time_utils.dt_now_local()).success
    dfrom = time_utils.dt_now_local() - datetime.timedelta(days=3)
    assert central_heating_log.query(dfrom, None).success
    assert central_heating_log.query(dfrom, time_utils.dt_now_local()).success

    # Clean up table for other tests.
    central_heating_log.clear_old_entries(None)
Esempio n. 3
0
def test_time_utils():
    # Test splitting seconds into days, hours, ...
    data = {
        0: (0, 0, 0, 0),
        1: (0, 0, 0, 1),
        60: (0, 0, 1, 0),
        70: (0, 0, 1, 10),
        1800: (0, 0, 30, 0),
        3600: (0, 1, 0, 0),
        9004: (0, 2, 30, 4),
        86399: (0, 23, 59, 59),
        86400: (1, 0, 0, 0),
        86401: (1, 0, 0, 1),
        86460: (1, 0, 1, 0),
        86461: (1, 0, 1, 1),
        90000: (1, 1, 0, 0),
        90001: (1, 1, 0, 1),
        90060: (1, 1, 1, 0),
        90067: (1, 1, 1, 7)
    }
    for insec in data:
        d, h, m, s = time_utils.days_hours_minutes_seconds_from_sec(insec)
        assert d == data[insec][0]
        assert h == data[insec][1]
        assert m == data[insec][2]
        assert s == data[insec][3]

    assert time_utils.t_fromstr(None) is None
    assert time_utils.t_fromstr('5:30') == time(hour=5, minute=30)
    assert time_utils.t_fromstr('12:01:30') == time(hour=12,
                                                    minute=1,
                                                    second=30)
    with pytest.raises(ValueError):
        time_utils.t_fromstr('a')

    assert time_utils.time_as_local(None) is None

    assert time_utils.assume_local(None) is None
    dt_now = time_utils.dt_now_utc()
    assert time_utils.assume_local(dt_now) != dt_now
    assert time_utils.assume_local(dt_now).tzinfo == tz.tzlocal()
    assert time_utils.assume_local(dt_now.timetz()) != dt_now.timetz()
    res = time_utils.assume_local(dt_now.timetz())
    assert res.hour == dt_now.hour
    assert res.minute == dt_now.minute
    assert res.second == dt_now.second

    tmr = time_utils.tomorrow_local()
    now = time_utils.dt_now_local().date()
    assert (tmr.day == now.day + 1) or (tmr.day == 1
                                        and tmr.month == now.month + 1)
Esempio n. 4
0
def test_conversions():
    assert time_utils.dt_as_local(None) is None
    assert time_utils.dt_as_utc(None) is None
    now_utc = time_utils.dt_now_utc()
    now_local = time_utils.dt_now_local()
    assert time_utils.dt_as_utc(now_local) == time_utils.dt_now_utc()
    assert time_utils.t_now_utc() == now_utc.timetz()
    assert time_utils.t_now_local() == time_utils.time_as_local(
        now_utc.timetz())
    # time has no timezone, thus, time_as_local() should assume it is in UTC and convert correctly
    assert time_utils.t_now_local() == time_utils.time_as_local(now_utc.time())

    t_local = time_utils.t_now_local()
    assert time_utils.local_time_as_utc(t_local.hour, t_local.minute,
                                        t_local.second) == now_utc.timetz()
    assert time_utils.t_now_local() == time_utils.time_as_local(
        time_utils.t_now_local())
    # Format as local time:
    assert time_utils.format_time(
        t_local) == f"{t_local.hour:02d}:{t_local.minute:02d}"
    t_utc = time_utils.t_now_utc()
    assert time_utils.format_time(
        t_utc) == f"{t_local.hour:02d}:{t_local.minute:02d}"
def test_heating_task_start():
    for delta in [
            MIN_HEATING_DURATION, MAX_HEATING_DURATION,
            timedelta(minutes=59, seconds=59),
            timedelta(hours=1, minutes=30),
            timedelta(hours=5, seconds=3)
    ]:
        t = _mk_valid_manual()
        assert t.residual_heating_time is None
        t.duration = delta
        assert t.residual_heating_time is None
        assert t.started_at is None
        t.start()
        now = time_utils.dt_now_utc()
        end_time = now + delta
        assert t.started_at == now
        assert t.ends_at == end_time
        assert t.residual_heating_time == delta
def test_heating_controller():
    # Skip these tests - we may have an active task in the database upon
    # creation of the heating singleton (when the module is loaded). Then,
    # these tests would fail.
    # # assert not hc.is_heater_on
    # # assert not hc.is_heating_task_active

    def _validate_dev_state(expected):
        for state in central_heater.power_socket_states:
            assert state.is_powered_on == expected

    _validate_dev_state(False)

    # Pause the controller (scheduled tasks should be ignored)
    assert not central_heater.is_paused
    assert central_heater.toggle_pause('pytester')
    assert central_heater.is_paused

    assert central_heater.start_controller()
    # We shouldn't be able to start the controller twice
    assert not central_heater.start_controller()

    assert not central_heater.start_heating(None).success

    # Start a scheduled task
    ts = HeatingTask(RequestType.SCHEDULED, 'another pytester')
    rsp = central_heater.start_heating(ts)
    assert not rsp.success  # This task is invalid
    ts.duration = MIN_HEATING_DURATION
    assert not central_heater.start_heating(ts).success  # We're still paused
    assert not central_heater.toggle_pause('another pytester')
    assert central_heater.start_heating(ts).success  # Now it should work
    # Wait a bit to let the heater start
    _sleep()
    assert central_heater.is_heater_on
    assert central_heater.is_heating_task_active
    _validate_dev_state(True)
    assert central_heater.residual_heating_time is not None
    assert central_heater.residual_heating_time < MIN_HEATING_DURATION
    # Stop the task again
    assert central_heater.stop_heating('pytester').success
    _sleep()
    assert not central_heater.is_heater_on
    assert not central_heater.is_heating_task_active
    _validate_dev_state(False)

    # Pause the controller (manual tasks should overrule this)
    assert central_heater.toggle_pause('pytester')
    assert central_heater.is_paused

    # Start a manual task without feedback controller
    tm = HeatingTask(RequestType.MANUAL, 'Overruler')
    assert not tm.needs_feedback_controller
    assert central_heater.start_heating(tm).success
    assert not central_heater.is_paused  # System must be "unpaused" now
    _sleep()
    assert central_heater.is_heater_on
    assert central_heater.is_heating_task_active
    assert central_heater.residual_heating_time is None
    _validate_dev_state(True)

    assert not central_heater.start_heating(
        ts).success  # A scheduled task cannot replace an active manual task

    assert central_heater.stop_heating('pytester').success
    _sleep()
    assert not central_heater.is_heater_on
    assert not central_heater.is_heating_task_active
    _validate_dev_state(False)

    # Start a manual task with feedback controller
    assert not central_heater.is_paused
    tm = HeatingTask(RequestType.MANUAL,
                     'Standard user',
                     temperature_target=30)
    assert tm.needs_feedback_controller
    assert central_heater.start_heating(tm).success
    assert not central_heater.is_paused
    _sleep()
    assert central_heater.is_heater_on
    assert central_heater.is_heating_task_active
    _validate_dev_state(True)

    assert central_heater.stop_heating('pytester').success
    _sleep()
    assert not central_heater.is_heater_on
    assert not central_heater.is_heating_task_active
    _validate_dev_state(False)

    # Test if a task times out properly
    with freeze_time(time_utils.dt_now_utc()) as frozen_datetime:
        tm = HeatingTask(RequestType.MANUAL,
                         'Time Out User',
                         duration=MIN_HEATING_DURATION)
        assert central_heater.start_heating(tm).success
        frozen_datetime.tick(delta=timedelta(seconds=1) + MIN_HEATING_DURATION)
        central_heater._force_loop_iteration()
        _sleep()
        assert not central_heater.is_heating_task_active

    central_heater.shutdown()