Skip to content
Draft
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
7 changes: 4 additions & 3 deletions homeassistant/components/geniushub/climate.py
Original file line number Diff line number Diff line change
Expand Up @@ -77,11 +77,12 @@ def hvac_modes(self) -> list[HVACMode]:
@property
def hvac_action(self) -> HVACAction | None:
"""Return the current running hvac operation if supported."""
if "_state" in self._zone.data: # only for v3 API
if "output" in self._zone.data:
if self._zone.data["output"] == 1:
return HVACAction.HEATING
if not self._zone.data["_state"].get("bIsActive"):
return HVACAction.OFF
if "_state" in self._zone.data: # v3 API has more detail
if not self._zone.data["_state"].get("bIsActive"):
return HVACAction.OFF
return HVACAction.IDLE
return None

Expand Down
2 changes: 1 addition & 1 deletion homeassistant/components/geniushub/entity.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
from . import ATTR_DURATION, ATTR_ZONE_MODE, DOMAIN, SVC_SET_ZONE_OVERRIDE

# temperature is repeated here, as it gives access to high-precision temps
GH_ZONE_ATTRS = ["mode", "temperature", "type", "occupied", "override"]
GH_ZONE_ATTRS = ["mode", "temperature", "type", "occupied", "override", "output"]
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do we add this to the attributes? Ideally we make separate entities for them

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The output field indicates whether a zone is actively calling for heat (1) or satisfied (0). It is present in both the v1 (cloud) and v3 (local) API responses — the existing test fixture zones_cloud_test_data.json confirms this.

The original hvac_action implementation correctly identified _state as v3-only (comment: # only for v3 API), but output was gated behind the same _state check, meaning cloud API users could never reach it despite their data containing it — always returning None.

output was also absent from GH_ZONE_ATTRS, so it was dropped from extra_state_attributes for both API versions. v3 local users had hvac_action as an indirect indicator of heat demand; v1 cloud users had nothing at all.

The separate entities you're describing are being added in the companion feature PR #167632, which creates a binary_sensor entity with device_class: heat for each zone — motivated particularly by the hot water zone, where water_heater entities have no hvac_action equivalent. Happy to drop output from extra_state_attributes if you feel the binary sensor makes it redundant, but I felt both were valid given users may want the raw value for templates.

Hopefully, I've not misunderstood the code.

GH_DEVICE_ATTRS = {
"luminance": "luminance",
"measuredTemperature": "measured_temperature",
Expand Down
14 changes: 14 additions & 0 deletions tests/components/geniushub/snapshots/test_climate.ambr
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@
'attributes': ReadOnlyDict({
'current_temperature': 21.5,
'friendly_name': 'Bedroom',
'hvac_action': <HVACAction.IDLE: 'idle'>,
'hvac_modes': list([
<HVACMode.OFF: 'off'>,
<HVACMode.HEAT: 'heat'>,
Expand All @@ -64,6 +65,7 @@
]),
'status': dict({
'mode': 'off',
'output': 0,
'override': dict({
'duration': 0,
'setpoint': 23.5,
Expand Down Expand Up @@ -135,6 +137,7 @@
'attributes': ReadOnlyDict({
'current_temperature': 21,
'friendly_name': 'Ensuite',
'hvac_action': <HVACAction.IDLE: 'idle'>,
'hvac_modes': list([
<HVACMode.OFF: 'off'>,
<HVACMode.HEAT: 'heat'>,
Expand All @@ -150,6 +153,7 @@
'status': dict({
'mode': 'off',
'occupied': 'False',
'output': 0,
'override': dict({
'duration': 0,
'setpoint': 28,
Expand Down Expand Up @@ -221,6 +225,7 @@
'attributes': ReadOnlyDict({
'current_temperature': 21,
'friendly_name': 'Guest room',
'hvac_action': <HVACAction.IDLE: 'idle'>,
'hvac_modes': list([
<HVACMode.OFF: 'off'>,
<HVACMode.HEAT: 'heat'>,
Expand All @@ -236,6 +241,7 @@
'status': dict({
'mode': 'off',
'occupied': 'True',
'output': 0,
'override': dict({
'duration': 0,
'setpoint': 20,
Expand Down Expand Up @@ -307,6 +313,7 @@
'attributes': ReadOnlyDict({
'current_temperature': 21,
'friendly_name': 'Hall',
'hvac_action': <HVACAction.IDLE: 'idle'>,
'hvac_modes': list([
<HVACMode.OFF: 'off'>,
<HVACMode.HEAT: 'heat'>,
Expand All @@ -322,6 +329,7 @@
'status': dict({
'mode': 'off',
'occupied': 'False',
'output': 0,
'override': dict({
'duration': 0,
'setpoint': 20,
Expand Down Expand Up @@ -393,6 +401,7 @@
'attributes': ReadOnlyDict({
'current_temperature': 21.5,
'friendly_name': 'Kitchen',
'hvac_action': <HVACAction.IDLE: 'idle'>,
'hvac_modes': list([
<HVACMode.OFF: 'off'>,
<HVACMode.HEAT: 'heat'>,
Expand All @@ -408,6 +417,7 @@
'status': dict({
'mode': 'off',
'occupied': 'False',
'output': 0,
'override': dict({
'duration': 0,
'setpoint': 20,
Expand Down Expand Up @@ -478,6 +488,7 @@
'attributes': ReadOnlyDict({
'current_temperature': 20,
'friendly_name': 'Lounge',
'hvac_action': <HVACAction.IDLE: 'idle'>,
'hvac_modes': list([
<HVACMode.OFF: 'off'>,
<HVACMode.HEAT: 'heat'>,
Expand All @@ -491,6 +502,7 @@
]),
'status': dict({
'mode': 'off',
'output': 0,
'override': dict({
'duration': 0,
'setpoint': 20,
Expand Down Expand Up @@ -562,6 +574,7 @@
'attributes': ReadOnlyDict({
'current_temperature': 22,
'friendly_name': 'Study',
'hvac_action': <HVACAction.IDLE: 'idle'>,
'hvac_modes': list([
<HVACMode.OFF: 'off'>,
<HVACMode.HEAT: 'heat'>,
Expand All @@ -577,6 +590,7 @@
'status': dict({
'mode': 'off',
'occupied': 'False',
'output': 0,
'override': dict({
'duration': 0,
'setpoint': 28,
Expand Down
3 changes: 3 additions & 0 deletions tests/components/geniushub/snapshots/test_switch.ambr
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@
'friendly_name': 'Bedroom Socket',
'status': dict({
'mode': 'timer',
'output': 1,
'override': dict({
'duration': 0,
'setpoint': 'True',
Expand Down Expand Up @@ -102,6 +103,7 @@
'friendly_name': 'Kitchen Socket',
'status': dict({
'mode': 'timer',
'output': 1,
'override': dict({
'duration': 0,
'setpoint': 'True',
Expand Down Expand Up @@ -161,6 +163,7 @@
'friendly_name': 'Study Socket',
'status': dict({
'mode': 'off',
'output': 0,
'override': dict({
'duration': 0,
'setpoint': 'True',
Expand Down
Loading