Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
39 commits
Select commit Hold shift + click to select a range
dfd61f8
Add reauth to Mastodon (#163148)
andrew-codechimp Feb 16, 2026
fdc264c
Change Facebook notify tag from ACCOUNT_UPDATE to HUMAN_AGENT (#162890)
doggyben Feb 16, 2026
a308b84
Use hardware/usb domain constant in tests (#162934)
epenet Feb 16, 2026
0292a8c
Add quality scale to Advantage Air integration (#160476)
Bre77 Feb 16, 2026
be228db
Fix title for onedrive for business (#163134)
zweckj Feb 16, 2026
97df38f
Add MTA New York City Transit integration (#156846)
OnFreund Feb 16, 2026
fed9ed6
Rename DOMAIN aliases in tests (#163176)
epenet Feb 16, 2026
aab4f57
Add missing native_unit_of_measurement in WLED (#157802)
mik-laj Feb 16, 2026
cbc2928
Rename devolo test variables and aliases (#163175)
epenet Feb 16, 2026
2684f4b
Update quality scale of WLED integration to platinum (#162680)
mik-laj Feb 16, 2026
09b122e
KNX Sensor: set device and state class for YAML entities based on DPT…
farmio Feb 16, 2026
80fccae
minecraft_server: do not use mcstatus' internal objects (#163101)
PerchunPak Feb 16, 2026
9e14a64
Add Mastodon reconfigure flow (#163178)
andrew-codechimp Feb 16, 2026
19aaaf6
Add Lux to homee units (#163180)
Taraman17 Feb 16, 2026
d370a73
Mark update method type hints as mandatory (#163182)
epenet Feb 16, 2026
6c433d0
Improve type hints in roomba vacuum (#163184)
epenet Feb 16, 2026
977ee1a
Add snapshot testing to SleepIQ (#163179)
joostlek Feb 16, 2026
a5c1ed5
Improve type hints in atag water_heater (#163192)
epenet Feb 16, 2026
d850400
Improve type hints in aosmith water_heater (#163191)
epenet Feb 16, 2026
66d8a5b
Improve type hints in econet water_heater (#163193)
epenet Feb 16, 2026
168dd36
Mark vacuum method type hints as mandatory (#163185)
epenet Feb 16, 2026
5bb7699
Mark water_heater method type hints as mandatory (#163190)
epenet Feb 16, 2026
66dc566
Add zone temperature support to Daikin integration (#152642)
barneyonline Feb 16, 2026
e6c5e72
add upper and lower shutter of Velux dualrollershutters as entities (…
wollew Feb 16, 2026
e49767d
GIOS quality scale fixes to platinum (#162510)
mik-laj Feb 16, 2026
9dc38ed
Reauthentication flow for Watts Vision + integration (#163141)
theobld-ww Feb 16, 2026
c833cfa
Don't mock out filesystem operations in backup_restore tests (#163172)
emontnemery Feb 16, 2026
957c603
Fix `reboot_gateway` action deprecation message in `velux` (#163201)
NoRi2909 Feb 16, 2026
47d6e3e
Refactor HTML5 integration to use aiohttp instead of requests (#163202)
tr4nt0r Feb 16, 2026
eec8543
bump pyvlx to 0.2.30 (#163203)
wollew Feb 16, 2026
459996b
Add 100% coverage of sensors for Fritz (#163005)
chemelli74 Feb 16, 2026
2418036
Saunum integration fix: close client on unload (#163183)
mettolen Feb 16, 2026
8c14662
Add Celsius Temperature Support for Control4 Integration (#163196)
davidrecordon Feb 16, 2026
667a775
Store nest media in a .cache subdirectory (#163200)
allenporter Feb 16, 2026
76ebc13
Mealie add get shopping list items action (#163090)
andrew-codechimp Feb 16, 2026
5cf37af
Add `quality_scale` with `strict-typing` done for SpaceAPI (#163003)
ximex Feb 16, 2026
4974439
Add on-grid discharge stop SOC control for Growatt MIN devices (#160634)
johanzander Feb 16, 2026
9ec456d
Add port link speed sensor to UniFi integration (#162847)
com6056 Feb 16, 2026
73fa992
Add test coverage for tplink_omada update entities (#162549)
MarkGodwin Feb 16, 2026
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
1 change: 1 addition & 0 deletions .strict-typing
Original file line number Diff line number Diff line change
Expand Up @@ -496,6 +496,7 @@ homeassistant.components.smtp.*
homeassistant.components.snooz.*
homeassistant.components.solarlog.*
homeassistant.components.sonarr.*
homeassistant.components.spaceapi.*
homeassistant.components.speedtestdotnet.*
homeassistant.components.spotify.*
homeassistant.components.sql.*
Expand Down
2 changes: 2 additions & 0 deletions CODEOWNERS

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

108 changes: 108 additions & 0 deletions homeassistant/components/advantage_air/quality_scale.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
rules:
# Bronze
action-setup:
status: todo
comment: https://developers.home-assistant.io/blog/2025/09/25/entity-services-api-changes/
appropriate-polling: done
brands: done
common-modules:
status: todo
comment: |
Move coordinator from __init__.py to coordinator.py.
Consider using entity descriptions for binary_sensor and switch.
Consider simplifying climate supported features flow.
config-flow-test-coverage:
status: todo
comment: |
Add mock_setup_entry common fixture.
Test unique_id of the entry in happy flow.
Split duplicate entry test from happy flow, use mock_config_entry.
Error flow should end in CREATE_ENTRY to test recovery.
Add data_description for ip_address (and port) to strings.json - tests fail with:
"Translation not found for advantage_air: config.step.user.data_description.ip_address"
config-flow:
status: todo
comment: Data descriptions missing
dependency-transparency: done
docs-actions: done
docs-high-level-description: done
docs-installation-instructions: todo
docs-removal-instructions: todo
entity-event-setup:
status: exempt
comment: Entities do not explicitly subscribe to events.
entity-unique-id: done
has-entity-name: done
runtime-data:
status: done
comment: Consider extending coordinator to access API via coordinator and remove extra dataclass.
test-before-configure: done
test-before-setup: done
unique-config-entry: done

# Silver
action-exceptions: done
config-entry-unloading: done
docs-configuration-parameters:
status: exempt
comment: No options to be set.
docs-installation-parameters: done
entity-unavailable:
status: todo
comment: MyZone temp entity should be unavailable when MyZone is disabled rather than returning None.
integration-owner: done
log-when-unavailable: todo
parallel-updates: todo
reauthentication-flow:
status: exempt
comment: Integration connects to local device without authentication.
test-coverage:
status: todo
comment: |
Patch the library instead of mocking at integration level.
Split binary sensor tests into multiple tests (enable entities etc).
Split tests into Creation (right entities with right values), Actions (right library calls), and Other behaviors.

# Gold
devices:
status: todo
comment: Consider making every zone its own device for better naming and room assignment. Breaking change to split cover entities to separate devices.
diagnostics: done
discovery-update-info:
status: exempt
comment: Device is a generic Android device (android-xxxxxxxx) indistinguishable from other Android devices, not discoverable.
discovery:
status: exempt
comment: Check mDNS, DHCP, SSDP confirmed not feasible. Device is a generic Android device (android-xxxxxxxx) indistinguishable from other Android devices.
docs-data-update: todo
docs-examples: todo
docs-known-limitations: todo
docs-supported-devices: todo
docs-supported-functions: done
docs-troubleshooting: todo
docs-use-cases: todo
dynamic-devices:
status: exempt
comment: AC zones are static per unit and configured on the device itself.
entity-category: done
entity-device-class:
status: todo
comment: Consider using UPDATE device class for app update binary sensor instead of custom.
entity-disabled-by-default: done
entity-translations: todo
exception-translations:
status: todo
comment: UpdateFailed in the coordinator
icon-translations: todo
reconfiguration-flow: todo
repair-issues:
status: exempt
comment: Integration does not raise repair issues.
stale-devices:
status: exempt
comment: Zones are part of the AC unit, not separate removable devices.

# Platinum
async-dependency: done
inject-websession: done
strict-typing: todo
2 changes: 1 addition & 1 deletion homeassistant/components/aosmith/water_heater.py
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ def current_operation(self) -> str:
return MODE_AOSMITH_TO_HA.get(self.device.status.current_mode, STATE_OFF)

@property
def is_away_mode_on(self):
def is_away_mode_on(self) -> bool:
"""Return True if away mode is on."""
return self.device.status.current_mode == AOSmithOperationMode.VACATION

Expand Down
8 changes: 4 additions & 4 deletions homeassistant/components/atag/water_heater.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,23 +37,23 @@ class AtagWaterHeater(AtagEntity, WaterHeaterEntity):
_attr_temperature_unit = UnitOfTemperature.CELSIUS

@property
def current_temperature(self):
def current_temperature(self) -> float:
"""Return the current temperature."""
return self.coordinator.atag.dhw.temperature

@property
def current_operation(self):
def current_operation(self) -> str:
"""Return current operation."""
operation = self.coordinator.atag.dhw.current_operation
return operation if operation in self.operation_list else STATE_OFF
return operation if operation in OPERATION_LIST else STATE_OFF

async def async_set_temperature(self, **kwargs: Any) -> None:
"""Set new target temperature."""
if await self.coordinator.atag.dhw.set_temp(kwargs.get(ATTR_TEMPERATURE)):
self.async_write_ha_state()

@property
def target_temperature(self):
def target_temperature(self) -> float:
"""Return the setpoint if water demand, otherwise return base temp (comfort level)."""
return self.coordinator.atag.dhw.target_temperature

Expand Down
97 changes: 72 additions & 25 deletions homeassistant/components/control4/climate.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,20 +34,33 @@
# Control4 variable names
CONTROL4_HVAC_STATE = "HVAC_STATE"
CONTROL4_HVAC_MODE = "HVAC_MODE"
CONTROL4_CURRENT_TEMPERATURE = "TEMPERATURE_F"
CONTROL4_HUMIDITY = "HUMIDITY"
CONTROL4_COOL_SETPOINT = "COOL_SETPOINT_F"
CONTROL4_HEAT_SETPOINT = "HEAT_SETPOINT_F"
CONTROL4_SCALE = "SCALE" # "FAHRENHEIT" or "CELSIUS"

# Temperature variables - Fahrenheit
CONTROL4_CURRENT_TEMPERATURE_F = "TEMPERATURE_F"
CONTROL4_COOL_SETPOINT_F = "COOL_SETPOINT_F"
CONTROL4_HEAT_SETPOINT_F = "HEAT_SETPOINT_F"

# Temperature variables - Celsius
CONTROL4_CURRENT_TEMPERATURE_C = "TEMPERATURE_C"
CONTROL4_COOL_SETPOINT_C = "COOL_SETPOINT_C"
CONTROL4_HEAT_SETPOINT_C = "HEAT_SETPOINT_C"

CONTROL4_FAN_MODE = "FAN_MODE"
CONTROL4_FAN_MODES_LIST = "FAN_MODES_LIST"

VARIABLES_OF_INTEREST = {
CONTROL4_HVAC_STATE,
CONTROL4_HVAC_MODE,
CONTROL4_CURRENT_TEMPERATURE,
CONTROL4_HUMIDITY,
CONTROL4_COOL_SETPOINT,
CONTROL4_HEAT_SETPOINT,
CONTROL4_CURRENT_TEMPERATURE_F,
CONTROL4_CURRENT_TEMPERATURE_C,
CONTROL4_COOL_SETPOINT_F,
CONTROL4_HEAT_SETPOINT_F,
CONTROL4_COOL_SETPOINT_C,
CONTROL4_HEAT_SETPOINT_C,
CONTROL4_SCALE,
CONTROL4_FAN_MODE,
CONTROL4_FAN_MODES_LIST,
}
Expand Down Expand Up @@ -156,7 +169,6 @@ class Control4Climate(Control4Entity, ClimateEntity):
"""Control4 climate entity."""

_attr_has_entity_name = True
_attr_temperature_unit = UnitOfTemperature.FAHRENHEIT
_attr_translation_key = "thermostat"
_attr_hvac_modes = [HVACMode.OFF, HVACMode.HEAT, HVACMode.COOL, HVACMode.HEAT_COOL]

Expand Down Expand Up @@ -213,13 +225,45 @@ def supported_features(self) -> ClimateEntityFeature:
features |= ClimateEntityFeature.FAN_MODE
return features

@property
def temperature_unit(self) -> str:
"""Return the temperature unit based on the thermostat's SCALE setting."""
data = self._thermostat_data
if data is None:
return UnitOfTemperature.CELSIUS # Default per HA conventions
if data.get(CONTROL4_SCALE) == "FAHRENHEIT":
return UnitOfTemperature.FAHRENHEIT
return UnitOfTemperature.CELSIUS

@property
def _cool_setpoint(self) -> float | None:
"""Return the cooling setpoint from the appropriate variable."""
data = self._thermostat_data
if data is None:
return None
if self.temperature_unit == UnitOfTemperature.CELSIUS:
return data.get(CONTROL4_COOL_SETPOINT_C)
return data.get(CONTROL4_COOL_SETPOINT_F)

@property
def _heat_setpoint(self) -> float | None:
"""Return the heating setpoint from the appropriate variable."""
data = self._thermostat_data
if data is None:
return None
if self.temperature_unit == UnitOfTemperature.CELSIUS:
return data.get(CONTROL4_HEAT_SETPOINT_C)
return data.get(CONTROL4_HEAT_SETPOINT_F)

@property
def current_temperature(self) -> float | None:
"""Return the current temperature."""
data = self._thermostat_data
if data is None:
return None
return data.get(CONTROL4_CURRENT_TEMPERATURE)
if self.temperature_unit == UnitOfTemperature.CELSIUS:
return data.get(CONTROL4_CURRENT_TEMPERATURE_C)
return data.get(CONTROL4_CURRENT_TEMPERATURE_F)

@property
def current_humidity(self) -> int | None:
Expand Down Expand Up @@ -257,34 +301,25 @@ def hvac_action(self) -> HVACAction | None:
@property
def target_temperature(self) -> float | None:
"""Return the target temperature."""
data = self._thermostat_data
if data is None:
return None
hvac_mode = self.hvac_mode
if hvac_mode == HVACMode.COOL:
return data.get(CONTROL4_COOL_SETPOINT)
return self._cool_setpoint
if hvac_mode == HVACMode.HEAT:
return data.get(CONTROL4_HEAT_SETPOINT)
return self._heat_setpoint
return None

@property
def target_temperature_high(self) -> float | None:
"""Return the high target temperature for auto mode."""
data = self._thermostat_data
if data is None:
return None
if self.hvac_mode == HVACMode.HEAT_COOL:
return data.get(CONTROL4_COOL_SETPOINT)
return self._cool_setpoint
return None

@property
def target_temperature_low(self) -> float | None:
"""Return the low target temperature for auto mode."""
data = self._thermostat_data
if data is None:
return None
if self.hvac_mode == HVACMode.HEAT_COOL:
return data.get(CONTROL4_HEAT_SETPOINT)
return self._heat_setpoint
return None

@property
Expand Down Expand Up @@ -326,15 +361,27 @@ async def async_set_temperature(self, **kwargs: Any) -> None:
# Handle temperature range for auto mode
if self.hvac_mode == HVACMode.HEAT_COOL:
if low_temp is not None:
await c4_climate.setHeatSetpointF(low_temp)
if self.temperature_unit == UnitOfTemperature.CELSIUS:
await c4_climate.setHeatSetpointC(low_temp)
else:
await c4_climate.setHeatSetpointF(low_temp)
if high_temp is not None:
await c4_climate.setCoolSetpointF(high_temp)
if self.temperature_unit == UnitOfTemperature.CELSIUS:
await c4_climate.setCoolSetpointC(high_temp)
else:
await c4_climate.setCoolSetpointF(high_temp)
# Handle single temperature setpoint
elif temp is not None:
if self.hvac_mode == HVACMode.COOL:
await c4_climate.setCoolSetpointF(temp)
if self.temperature_unit == UnitOfTemperature.CELSIUS:
await c4_climate.setCoolSetpointC(temp)
else:
await c4_climate.setCoolSetpointF(temp)
elif self.hvac_mode == HVACMode.HEAT:
await c4_climate.setHeatSetpointF(temp)
if self.temperature_unit == UnitOfTemperature.CELSIUS:
await c4_climate.setHeatSetpointC(temp)
else:
await c4_climate.setHeatSetpointF(temp)

await self.coordinator.async_request_refresh()

Expand Down
Loading
Loading