updated apps
This commit is contained in:
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -9,6 +9,7 @@ from typing import Any
|
||||
|
||||
from homeassistant.const import CONF_ATTRIBUTE, CONF_CONDITION, CONF_ENTITY_ID, STATE_OFF
|
||||
from homeassistant.core import HomeAssistant, State
|
||||
from homeassistant.exceptions import ConditionError
|
||||
from homeassistant.helpers.condition import ConditionCheckerType
|
||||
import homeassistant.helpers.config_validation as cv
|
||||
from homeassistant.helpers.event import TrackTemplate
|
||||
@@ -152,15 +153,13 @@ class CompositeStrategy(PowerCalculationStrategyInterface):
|
||||
for sub_strategy in self.strategies:
|
||||
strategy = sub_strategy.strategy
|
||||
|
||||
if sub_strategy.condition and not sub_strategy.condition(self.hass, {"state": entity_state}):
|
||||
if sub_strategy.condition and not self._condition_matches(sub_strategy.condition, entity_state):
|
||||
continue
|
||||
|
||||
if isinstance(strategy, PlaybookStrategy):
|
||||
await self.activate_playbook(strategy)
|
||||
|
||||
if (
|
||||
entity_state.state == STATE_OFF and strategy.can_calculate_standby()
|
||||
) or entity_state.state != STATE_OFF:
|
||||
if entity_state.state != STATE_OFF or strategy.can_calculate_standby():
|
||||
value = await strategy.calculate(entity_state)
|
||||
if value is not None:
|
||||
if self.mode == CompositeMode.STOP_AT_FIRST:
|
||||
@@ -169,6 +168,13 @@ class CompositeStrategy(PowerCalculationStrategyInterface):
|
||||
|
||||
return total if self.mode == CompositeMode.SUM_ALL else None
|
||||
|
||||
def _condition_matches(self, condition: ConditionCheckerType, entity_state: State) -> bool:
|
||||
try:
|
||||
return condition(self.hass, {"state": entity_state})
|
||||
except ConditionError:
|
||||
_LOGGER.debug("Skipping composite sub-strategy because condition evaluation failed", exc_info=True)
|
||||
return False
|
||||
|
||||
async def stop_active_playbooks(self) -> None:
|
||||
"""Stop any active playbooks from sub strategies."""
|
||||
for playbook in self.playbook_strategies:
|
||||
|
||||
@@ -211,7 +211,8 @@ class PowerCalculatorStrategyFactory:
|
||||
"""Create instance of multi switch strategy."""
|
||||
multi_switch_config: ConfigType = {}
|
||||
if power_profile and power_profile.multi_switch_config:
|
||||
multi_switch_config = power_profile.multi_switch_config
|
||||
# Copy to avoid mutating the (potentially cached) profile config with the user's config below.
|
||||
multi_switch_config = dict(power_profile.multi_switch_config)
|
||||
multi_switch_config.update(config.get(CONF_MULTI_SWITCH, {}))
|
||||
|
||||
if not multi_switch_config:
|
||||
|
||||
@@ -12,7 +12,7 @@ import voluptuous as vol
|
||||
from custom_components.powercalc.common import SourceEntity
|
||||
from custom_components.powercalc.const import CONF_POWER, CONF_STATES_POWER
|
||||
from custom_components.powercalc.errors import StrategyConfigurationError
|
||||
from custom_components.powercalc.helpers import evaluate_power
|
||||
from custom_components.powercalc.unit import evaluate_to_decimal
|
||||
|
||||
from .strategy_interface import PowerCalculationStrategyInterface
|
||||
|
||||
@@ -46,21 +46,21 @@ class FixedStrategy(PowerCalculationStrategyInterface):
|
||||
if self._per_state_power is not None:
|
||||
# Lookup by state
|
||||
if entity_state.state in self._per_state_power:
|
||||
return evaluate_power(
|
||||
return evaluate_to_decimal(
|
||||
self._per_state_power.get(entity_state.state) or 0,
|
||||
)
|
||||
|
||||
# Lookup by state attribute (attribute|value)
|
||||
for state_key, power in self._per_state_power.items():
|
||||
if "|" in state_key:
|
||||
attribute, value = state_key.split("|", 2)
|
||||
attribute, value = state_key.split("|", 1)
|
||||
if str(entity_state.attributes.get(attribute)) == value:
|
||||
return evaluate_power(power)
|
||||
return evaluate_to_decimal(power)
|
||||
|
||||
if self._power is None:
|
||||
return None
|
||||
|
||||
return evaluate_power(self._power)
|
||||
return evaluate_to_decimal(self._power)
|
||||
|
||||
async def validate_config(self) -> None:
|
||||
"""Validate correct setup of the strategy."""
|
||||
|
||||
@@ -119,7 +119,7 @@ class LinearStrategy(PowerCalculationStrategyInterface):
|
||||
|
||||
def is_enabled(self, entity_state: State) -> bool:
|
||||
"""Return if this strategy is enabled based on entity state."""
|
||||
return not (self._source_entity.domain == media_player.DOMAIN and entity_state.state is not STATE_PLAYING)
|
||||
return not (self._source_entity.domain == media_player.DOMAIN and entity_state.state != STATE_PLAYING)
|
||||
|
||||
def get_min_calibrate(self, value: int) -> tuple[int, float]:
|
||||
"""Get closest lower value from calibration table."""
|
||||
@@ -176,7 +176,7 @@ class LinearStrategy(PowerCalculationStrategyInterface):
|
||||
return self.get_value_from_attribute(entity_state)
|
||||
|
||||
value_entity = self.get_initialized_value_entity()
|
||||
if value_entity.entity_id is not self._source_entity.entity_id:
|
||||
if value_entity.entity_id != self._source_entity.entity_id:
|
||||
# If the value entity is different from the source entity, we need to fetch the state of the value entity
|
||||
entity_state = self._hass.states.get(value_entity.entity_id)
|
||||
if not entity_state:
|
||||
|
||||
@@ -188,7 +188,7 @@ class LutRegistry:
|
||||
_LOGGER.debug("Loading LUT data file: %s", path)
|
||||
return open(path)
|
||||
|
||||
raise LutFileNotFoundError("Data file not found: %s")
|
||||
raise LutFileNotFoundError(f"Data file not found: {path}")
|
||||
|
||||
|
||||
class LutStrategy(PowerCalculationStrategyInterface):
|
||||
@@ -312,7 +312,7 @@ class LutStrategy(PowerCalculationStrategyInterface):
|
||||
)
|
||||
light_setting.hue = int(hs[0] / 360 * 65535)
|
||||
light_setting.saturation = int(hs[1] / 100 * 255)
|
||||
except (KeyError, TypeError, ValueError):
|
||||
except KeyError, TypeError, ValueError:
|
||||
_LOGGER.error(
|
||||
"%s: Could not calculate power. no hue/sat set. "
|
||||
"Please check the attributes of your light in the developer tools.",
|
||||
|
||||
@@ -4,7 +4,6 @@ from decimal import Decimal
|
||||
import logging
|
||||
|
||||
from homeassistant.components.sensor import SensorDeviceClass
|
||||
from homeassistant.const import STATE_UNAVAILABLE, STATE_UNKNOWN
|
||||
from homeassistant.core import HomeAssistant, State
|
||||
from homeassistant.helpers import entity_registry
|
||||
from homeassistant.helpers.event import TrackTemplate
|
||||
@@ -16,9 +15,11 @@ from custom_components.powercalc.const import (
|
||||
CONF_POWER_FACTOR,
|
||||
CONF_VOLTAGE,
|
||||
OFF_STATES,
|
||||
UNAVAILABLE_STATES,
|
||||
)
|
||||
from custom_components.powercalc.errors import StrategyConfigurationError
|
||||
from custom_components.powercalc.helpers import evaluate_power, get_related_entity_by_device_class
|
||||
from custom_components.powercalc.helpers import get_related_entity_by_device_class
|
||||
from custom_components.powercalc.unit import evaluate_to_decimal
|
||||
|
||||
from .strategy_interface import PowerCalculationStrategyInterface
|
||||
|
||||
@@ -53,14 +54,21 @@ class WledStrategy(PowerCalculationStrategyInterface):
|
||||
if entity_state.entity_id == self._light_entity.entity_id
|
||||
else self._hass.states.get(self._light_entity.entity_id)
|
||||
)
|
||||
if light_state is None:
|
||||
return None
|
||||
|
||||
if light_state.state in OFF_STATES and self._standby_power:
|
||||
return self._standby_power
|
||||
|
||||
if entity_state.entity_id != self._estimated_current_entity:
|
||||
entity_state = self._hass.states.get(self._estimated_current_entity)
|
||||
current_state = (
|
||||
entity_state
|
||||
if entity_state.entity_id == self._estimated_current_entity
|
||||
else self._hass.states.get(self._estimated_current_entity)
|
||||
)
|
||||
if current_state is None:
|
||||
return None
|
||||
|
||||
if entity_state.state in [STATE_UNAVAILABLE, STATE_UNKNOWN]:
|
||||
if current_state.state in UNAVAILABLE_STATES:
|
||||
_LOGGER.warning(
|
||||
"%s: Estimated current entity %s is not available",
|
||||
self._light_entity.entity_id,
|
||||
@@ -71,12 +79,12 @@ class WledStrategy(PowerCalculationStrategyInterface):
|
||||
_LOGGER.debug(
|
||||
"%s: Estimated current %s (voltage=%d, power_factor=%.2f)",
|
||||
self._light_entity.entity_id,
|
||||
entity_state.state,
|
||||
current_state.state,
|
||||
self._voltage,
|
||||
self._power_factor,
|
||||
)
|
||||
power = float(entity_state.state) / 1000 * self._voltage * self._power_factor
|
||||
return evaluate_power(power)
|
||||
power = float(current_state.state) / 1000 * self._voltage * self._power_factor
|
||||
return evaluate_to_decimal(power)
|
||||
|
||||
async def find_estimated_current_entity(self) -> str:
|
||||
entity_reg = entity_registry.async_get(self._hass)
|
||||
|
||||
Reference in New Issue
Block a user