New apps Added
This commit is contained in:
@@ -0,0 +1,9 @@
|
||||
"""Domain entities - objects with identity and lifecycle."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from .heating_pilot import HeatingPilot
|
||||
|
||||
__all__ = [
|
||||
"HeatingPilot",
|
||||
]
|
||||
@@ -0,0 +1,96 @@
|
||||
"""Heating pilot - the aggregate root for heating decisions."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import logging
|
||||
|
||||
from ..interfaces import IDecisionStrategy, ISchedulerCommander
|
||||
from ..value_objects import (
|
||||
EnvironmentState,
|
||||
HeatingDecision,
|
||||
)
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class HeatingPilot:
|
||||
"""Coordinates heating decisions for a single VTherm.
|
||||
|
||||
This is the aggregate root that orchestrates all domain logic
|
||||
for intelligent heating control. It delegates decision-making to
|
||||
a configurable strategy, allowing users to choose between:
|
||||
|
||||
- Simple rule-based decisions (no ML required)
|
||||
- ML-powered decisions (requires IHP-ML-Models add-on)
|
||||
|
||||
This design follows the Strategy pattern, making the pilot
|
||||
independent of the decision algorithm complexity.
|
||||
|
||||
Attributes:
|
||||
_decision_strategy: Strategy for making heating decisions
|
||||
_scheduler_commander: Interface to control scheduler actions
|
||||
"""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
decision_strategy: IDecisionStrategy,
|
||||
scheduler_commander: ISchedulerCommander,
|
||||
) -> None:
|
||||
"""Initialize the heating pilot.
|
||||
|
||||
Args:
|
||||
decision_strategy: Strategy for making heating decisions
|
||||
(simple rules or ML-based)
|
||||
scheduler_commander: Implementation of scheduler control interface
|
||||
"""
|
||||
_LOGGER.debug("Initializing HeatingPilot")
|
||||
self._decision_strategy = decision_strategy
|
||||
self._scheduler_commander = scheduler_commander
|
||||
_LOGGER.info(f"HeatingPilot initialized with strategy: {type(decision_strategy).__name__}")
|
||||
|
||||
async def decide_heating_action(
|
||||
self,
|
||||
environment: EnvironmentState,
|
||||
) -> HeatingDecision:
|
||||
"""Decide what heating action to take based on current conditions.
|
||||
|
||||
This method delegates the decision to the configured strategy,
|
||||
which can be either simple rule-based or ML-powered.
|
||||
|
||||
Args:
|
||||
environment: Current environmental conditions
|
||||
|
||||
Returns:
|
||||
A heating decision with the action to take
|
||||
"""
|
||||
_LOGGER.debug("HeatingPilot.decide_heating_action called")
|
||||
_LOGGER.debug(f"Delegating decision to {type(self._decision_strategy).__name__}")
|
||||
|
||||
decision = await self._decision_strategy.decide_heating_action(environment)
|
||||
|
||||
_LOGGER.info(f"HeatingPilot decision: {decision.action.value}")
|
||||
return decision
|
||||
|
||||
async def check_overshoot_risk(
|
||||
self,
|
||||
environment: EnvironmentState,
|
||||
current_slope: float,
|
||||
) -> HeatingDecision:
|
||||
"""Check if heating should stop to prevent overshooting target.
|
||||
|
||||
This method delegates the overshoot check to the configured strategy.
|
||||
|
||||
Args:
|
||||
environment: Current environmental conditions
|
||||
current_slope: Current heating rate in °C/hour
|
||||
|
||||
Returns:
|
||||
Decision to stop heating if overshoot is detected
|
||||
"""
|
||||
_LOGGER.debug("HeatingPilot.check_overshoot_risk called")
|
||||
_LOGGER.debug(f"Delegating overshoot check to {type(self._decision_strategy).__name__}")
|
||||
|
||||
decision = await self._decision_strategy.check_overshoot_risk(environment, current_slope)
|
||||
|
||||
_LOGGER.info(f"HeatingPilot overshoot check: {decision.action.value}")
|
||||
return decision
|
||||
Reference in New Issue
Block a user