doc: поправил зависимости и расписание
This commit is contained in:
@@ -0,0 +1,304 @@
|
||||
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,
|
||||
)
|
||||
|
||||
|
||||
class FakeQingpingService:
|
||||
|
||||
def __init__(self):
|
||||
|
||||
self.online = True
|
||||
|
||||
self.state = SimpleNamespace(
|
||||
temperature=19.4,
|
||||
)
|
||||
|
||||
|
||||
class FakeTionController:
|
||||
|
||||
def __init__(self):
|
||||
self.calls = []
|
||||
|
||||
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=18,
|
||||
)
|
||||
|
||||
self.controller = (
|
||||
FakeTionController()
|
||||
)
|
||||
|
||||
async def execute(
|
||||
self,
|
||||
operation,
|
||||
):
|
||||
return await operation(
|
||||
self.controller
|
||||
)
|
||||
|
||||
|
||||
def make_resolution(
|
||||
target_temp=20.0,
|
||||
):
|
||||
|
||||
return SimpleNamespace(
|
||||
scheduled_settings=(
|
||||
SimpleNamespace(
|
||||
target_temp=target_temp,
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
def make_controller():
|
||||
|
||||
qingping = (
|
||||
FakeQingpingService()
|
||||
)
|
||||
|
||||
tion = FakeTionService()
|
||||
|
||||
policy = TemperaturePolicy(
|
||||
TemperatureConfig(
|
||||
hysteresis=0.5,
|
||||
)
|
||||
)
|
||||
|
||||
controller = AutoController(
|
||||
schedule_service=None,
|
||||
qingping_service=qingping,
|
||||
tion_service=tion,
|
||||
temperature_policy=policy,
|
||||
)
|
||||
|
||||
return (
|
||||
controller,
|
||||
qingping,
|
||||
tion,
|
||||
)
|
||||
|
||||
|
||||
async def test_qingping_heating():
|
||||
|
||||
controller, qingping, tion = (
|
||||
make_controller()
|
||||
)
|
||||
|
||||
resolution = make_resolution()
|
||||
|
||||
# 19.4 < 19.5
|
||||
# Heater должен включиться.
|
||||
|
||||
await controller._process_heater(
|
||||
resolution
|
||||
)
|
||||
|
||||
assert tion.controller.calls == [
|
||||
("heater_on", None)
|
||||
]
|
||||
|
||||
assert (
|
||||
controller._auto_heater
|
||||
is True
|
||||
)
|
||||
|
||||
assert (
|
||||
controller._temperature
|
||||
== 19.4
|
||||
)
|
||||
|
||||
assert (
|
||||
controller._temperature_source
|
||||
== "qingping"
|
||||
)
|
||||
|
||||
tion.controller.calls.clear()
|
||||
|
||||
# ----------------------------------------------
|
||||
# 19.8
|
||||
#
|
||||
# Heater уже ON.
|
||||
# До 20 градусов ещё не дошли.
|
||||
# Продолжаем греть.
|
||||
#
|
||||
# Новую команду отправлять не нужно.
|
||||
# ----------------------------------------------
|
||||
|
||||
qingping.state.temperature = 19.8
|
||||
|
||||
await controller._process_heater(
|
||||
resolution
|
||||
)
|
||||
|
||||
assert tion.controller.calls == []
|
||||
|
||||
assert (
|
||||
controller._auto_heater
|
||||
is True
|
||||
)
|
||||
|
||||
# ----------------------------------------------
|
||||
# 20.0
|
||||
#
|
||||
# Цель достигнута.
|
||||
# ----------------------------------------------
|
||||
|
||||
qingping.state.temperature = 20.0
|
||||
|
||||
await controller._process_heater(
|
||||
resolution
|
||||
)
|
||||
|
||||
assert tion.controller.calls == [
|
||||
("heater_off", None)
|
||||
]
|
||||
|
||||
assert (
|
||||
controller._auto_heater
|
||||
is False
|
||||
)
|
||||
|
||||
|
||||
async def test_tion_temperature_fallback():
|
||||
|
||||
controller, qingping, tion = (
|
||||
make_controller()
|
||||
)
|
||||
|
||||
resolution = make_resolution()
|
||||
|
||||
# Qingping отключился.
|
||||
qingping.online = False
|
||||
|
||||
# Используем Tion.
|
||||
tion.state.in_temp = 19
|
||||
|
||||
await controller._process_heater(
|
||||
resolution
|
||||
)
|
||||
|
||||
assert tion.controller.calls == [
|
||||
("heater_on", None)
|
||||
]
|
||||
|
||||
assert (
|
||||
controller._temperature
|
||||
== 19
|
||||
)
|
||||
|
||||
assert (
|
||||
controller._temperature_source
|
||||
== "tion"
|
||||
)
|
||||
|
||||
assert (
|
||||
controller._auto_heater
|
||||
is True
|
||||
)
|
||||
|
||||
|
||||
async def test_no_temperature():
|
||||
|
||||
controller, qingping, tion = (
|
||||
make_controller()
|
||||
)
|
||||
|
||||
resolution = make_resolution()
|
||||
|
||||
qingping.online = False
|
||||
tion.online = False
|
||||
|
||||
await controller._process_heater(
|
||||
resolution
|
||||
)
|
||||
|
||||
assert tion.controller.calls == [
|
||||
("heater_off", None)
|
||||
]
|
||||
|
||||
assert (
|
||||
controller._temperature
|
||||
is None
|
||||
)
|
||||
|
||||
assert (
|
||||
controller._temperature_source
|
||||
is None
|
||||
)
|
||||
|
||||
assert (
|
||||
controller._auto_heater
|
||||
is False
|
||||
)
|
||||
|
||||
|
||||
async def test_target_temperature_missing():
|
||||
|
||||
controller, qingping, tion = (
|
||||
make_controller()
|
||||
)
|
||||
|
||||
resolution = make_resolution(
|
||||
target_temp=None
|
||||
)
|
||||
|
||||
await controller._process_heater(
|
||||
resolution
|
||||
)
|
||||
|
||||
assert tion.controller.calls == [
|
||||
("heater_off", None)
|
||||
]
|
||||
|
||||
assert (
|
||||
controller._auto_heater
|
||||
is False
|
||||
)
|
||||
|
||||
|
||||
async def main():
|
||||
|
||||
await test_qingping_heating()
|
||||
|
||||
await test_tion_temperature_fallback()
|
||||
|
||||
await test_no_temperature()
|
||||
|
||||
await test_target_temperature_missing()
|
||||
|
||||
print()
|
||||
print("=" * 70)
|
||||
print(
|
||||
"ALL AUTO HEATER PROCESS "
|
||||
"TESTS PASSED"
|
||||
)
|
||||
print("=" * 70)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
asyncio.run(main())
|
||||
Reference in New Issue
Block a user