245 lines
4.6 KiB
Python
245 lines
4.6 KiB
Python
import asyncio
|
|
from types import SimpleNamespace
|
|
|
|
from app.auto.config import TemperatureConfig
|
|
from app.auto.controller import AutoController
|
|
from app.auto.temperature_policy import TemperaturePolicy
|
|
from app.my_dataclasses import MAX_TARGET_TEMP
|
|
|
|
|
|
class FakeQingpingService:
|
|
|
|
def __init__(self):
|
|
self.online = True
|
|
|
|
self.state = SimpleNamespace(
|
|
temperature=19.0,
|
|
)
|
|
|
|
|
|
class FakeTionController:
|
|
|
|
def __init__(self):
|
|
self.calls = []
|
|
|
|
async def set_target_temperature(
|
|
self,
|
|
temperature: int,
|
|
):
|
|
self.calls.append(
|
|
(
|
|
"set_target_temperature",
|
|
temperature,
|
|
)
|
|
)
|
|
|
|
async def heater_on(self):
|
|
self.calls.append(
|
|
(
|
|
"heater_on",
|
|
None,
|
|
)
|
|
)
|
|
|
|
async def heater_off(self):
|
|
self.calls.append(
|
|
(
|
|
"heater_off",
|
|
None,
|
|
)
|
|
)
|
|
|
|
|
|
class FakeTionService:
|
|
|
|
def __init__(self):
|
|
self.online = True
|
|
|
|
self.state = SimpleNamespace(
|
|
in_temp=22,
|
|
)
|
|
|
|
self.controller = FakeTionController()
|
|
|
|
async def execute(
|
|
self,
|
|
operation,
|
|
):
|
|
return await operation(
|
|
self.controller
|
|
)
|
|
|
|
|
|
def make_controller():
|
|
|
|
qingping = FakeQingpingService()
|
|
tion = FakeTionService()
|
|
|
|
temperature_policy = TemperaturePolicy(
|
|
TemperatureConfig(
|
|
hysteresis=0.5,
|
|
)
|
|
)
|
|
|
|
controller = AutoController(
|
|
schedule_service=None,
|
|
qingping_service=qingping,
|
|
tion_service=tion,
|
|
temperature_policy=temperature_policy,
|
|
)
|
|
|
|
return (
|
|
controller,
|
|
qingping,
|
|
tion,
|
|
)
|
|
|
|
|
|
def make_resolution(
|
|
target_temp: int,
|
|
):
|
|
return SimpleNamespace(
|
|
auto_target_temp=target_temp,
|
|
)
|
|
|
|
|
|
async def test_heating_sets_tion_target_first():
|
|
|
|
controller, qingping, tion = (
|
|
make_controller()
|
|
)
|
|
|
|
resolution = make_resolution(
|
|
target_temp=20
|
|
)
|
|
|
|
# Qingping = 19.0
|
|
# AUTO target = 20
|
|
#
|
|
# Нужно греть.
|
|
#
|
|
# Сначала Tion.target_temp поднимается
|
|
# до технического максимума,
|
|
# затем включается heater.
|
|
await controller._process_heater(
|
|
resolution
|
|
)
|
|
|
|
assert tion.controller.calls == [
|
|
(
|
|
"set_target_temperature",
|
|
MAX_TARGET_TEMP,
|
|
),
|
|
(
|
|
"heater_on",
|
|
None,
|
|
),
|
|
]
|
|
|
|
assert (
|
|
controller._target_temperature
|
|
== MAX_TARGET_TEMP
|
|
)
|
|
|
|
assert (
|
|
controller._target_heater
|
|
is True
|
|
)
|
|
|
|
assert (
|
|
controller._auto_heater
|
|
is True
|
|
)
|
|
|
|
|
|
async def test_repeated_heating_does_not_repeat_commands():
|
|
|
|
controller, qingping, tion = (
|
|
make_controller()
|
|
)
|
|
|
|
resolution = make_resolution(
|
|
target_temp=20
|
|
)
|
|
|
|
await controller._process_heater(
|
|
resolution
|
|
)
|
|
|
|
tion.controller.calls.clear()
|
|
|
|
# Температура всё ещё ниже цели.
|
|
# AUTO продолжает хотеть нагрев,
|
|
# но повторно слать команды Tion не нужно.
|
|
qingping.state.temperature = 19.2
|
|
|
|
await controller._process_heater(
|
|
resolution
|
|
)
|
|
|
|
assert tion.controller.calls == []
|
|
|
|
|
|
async def test_target_reached_turns_heater_off():
|
|
|
|
controller, qingping, tion = (
|
|
make_controller()
|
|
)
|
|
|
|
resolution = make_resolution(
|
|
target_temp=20
|
|
)
|
|
|
|
# Сначала включаем нагрев.
|
|
await controller._process_heater(
|
|
resolution
|
|
)
|
|
|
|
tion.controller.calls.clear()
|
|
|
|
# Цель достигнута.
|
|
qingping.state.temperature = 20.0
|
|
|
|
await controller._process_heater(
|
|
resolution
|
|
)
|
|
|
|
# MAX_TARGET_TEMP обратно сейчас не меняем.
|
|
# Достаточно запретить нагрев.
|
|
assert tion.controller.calls == [
|
|
(
|
|
"heater_off",
|
|
None,
|
|
)
|
|
]
|
|
|
|
assert (
|
|
controller._auto_heater
|
|
is False
|
|
)
|
|
|
|
assert (
|
|
controller._target_heater
|
|
is False
|
|
)
|
|
|
|
|
|
async def main():
|
|
|
|
await test_heating_sets_tion_target_first()
|
|
|
|
await test_repeated_heating_does_not_repeat_commands()
|
|
|
|
await test_target_reached_turns_heater_off()
|
|
|
|
print()
|
|
print("=" * 70)
|
|
print(
|
|
"ALL AUTO HEATER TION TARGET "
|
|
"TESTS PASSED"
|
|
)
|
|
print("=" * 70)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
asyncio.run(main()) |