Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix energy group won't get unavailable when some member sensors are unavailable #1665

Merged
merged 2 commits into from
May 8, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 9 additions & 28 deletions custom_components/powercalc/sensors/group.py
Original file line number Diff line number Diff line change
Expand Up @@ -531,34 +531,12 @@ def on_state_change(self, event: Event) -> None:
for state in states
if state and state.state not in [STATE_UNKNOWN, STATE_UNAVAILABLE]
]
unavailable_entities = [
state.entity_id
for state in states
if state and state.state == STATE_UNAVAILABLE
]
if unavailable_entities and isinstance(self, GroupedEnergySensor):
for entity_id in unavailable_entities:
prev_state = self._prev_state_store.get_entity_state(entity_id)
if prev_state:
available_states.append(prev_state)
unavailable_entities.remove(entity_id)

if unavailable_entities:
_LOGGER.warning(
"%s: One or more members of the group are unavailable, setting group to unavailable (%s)",
self.entity_id,
",".join(unavailable_entities),
)
self._attr_available = False
self.async_schedule_update_ha_state(True)
return

if not available_states:
self._attr_available = False
self.async_schedule_update_ha_state(True)
return

summed = self.calculate_new_state(available_states)
summed = self.calculate_new_state(available_states, states)
self._attr_native_value = round(summed, self._rounding_digits)
self._attr_available = True
self.async_schedule_update_ha_state(True)
Expand All @@ -584,7 +562,7 @@ def _get_state_value_in_native_unit(self, state: State) -> Decimal:
return Decimal(value)

@abstractmethod
def calculate_new_state(self, member_states: list[State]) -> Decimal:
def calculate_new_state(self, member_available_states: list[State], member_states: list[State]) -> Decimal:
...


Expand All @@ -595,9 +573,9 @@ class GroupedPowerSensor(GroupedSensor, PowerSensor):
_attr_state_class = SensorStateClass.MEASUREMENT
_attr_native_unit_of_measurement = POWER_WATT

def calculate_new_state(self, member_states: list[State]) -> Decimal:
def calculate_new_state(self, member_available_states: list[State], member_states: list[State]) -> Decimal:
values = [
self._get_state_value_in_native_unit(state) for state in member_states
self._get_state_value_in_native_unit(state) for state in member_available_states
]
return Decimal(sum([value for value in values if value is not None]))

Expand Down Expand Up @@ -655,13 +633,16 @@ def async_reset(self) -> None:
self._attr_last_reset = dt_util.utcnow()
self.async_write_ha_state()

def calculate_new_state(self, member_states: list[State]) -> Decimal:
def calculate_new_state(self, member_available_states: list[State], member_states: list[State]) -> Decimal:
"""Calculate the new group energy sensor state
For each member sensor we calculate the delta by looking at the previous known state and compare it to the current.
"""
group_sum = Decimal(self._attr_native_value) if self._attr_native_value else Decimal(0) # type: ignore
_LOGGER.debug(f"{self.entity_id}: Recalculate, current value: {group_sum}")
for entity_state in member_states:
if entity_state.state in [STATE_UNKNOWN, STATE_UNAVAILABLE]:
_LOGGER.debug(f"skipping state for {entity_state.entity_id}, sensor unavailable or unknown")
continue
prev_state = self._prev_state_store.get_entity_state(entity_state.entity_id)
cur_state_value = self._get_state_value_in_native_unit(entity_state)

Expand All @@ -677,7 +658,7 @@ def calculate_new_state(self, member_states: list[State]) -> Decimal:
)

delta = cur_state_value - prev_state_value
_LOGGER.debug(f"delta for entity {entity_state.entity_id}: {delta}")
_LOGGER.debug(f"delta for entity {entity_state.entity_id}: {delta}, prev={prev_state_value}, cur={cur_state_value}")
if delta < 0:
_LOGGER.warning(
f"skipping state for {entity_state.entity_id}, probably erroneous value or sensor was reset",
Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ source = ["custom_components/powercalc"]

[tool.ruff]
select = ["E", "W", "F", "B", "C", "I", "N", "UP", "ANN", "BLE", "A", "COM", "C4", "G", "ISC", "NPY", "INP", "PIE", "T20", "PYI", "Q", "RET", "SLF", "SIM", "TID", "RUF"]
ignore = ["ANN101", "ANN401"]
ignore = ["ANN101", "ANN401", "I001"]
line-length = 150
target-version = "py310"

Expand Down
Loading