Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
d660165
Add support for new energy sensor entities for DLQ (circuit breaker) …
zzysszzy Sep 3, 2025
b9427de
Bump aioecowitt to 2025.9.0 (#151608)
edenhaus Sep 3, 2025
c12b638
Adds initial support for tuya category xnyjcn (solar inverter) (#151549)
zzysszzy Sep 3, 2025
34c061d
Add energy consumption/production for Tuya kg category (smart switche…
zzysszzy Sep 3, 2025
1a12c61
Bump hass-nabucasa from 1.0.0 to 1.1.0 (#151606)
klejejs Sep 3, 2025
215603f
Bump asusrouter to 1.21.0 (#151607)
Vaskivskyi Sep 3, 2025
e0b3a53
Handle colliding aliases for areas (#151613)
emontnemery Sep 3, 2025
de90922
Update frontend to 20250903.0 (#151612)
bramkragten Sep 3, 2025
d571857
Handle colliding aliases for floors (#151614)
emontnemery Sep 3, 2025
712c9b9
Fix racing bug in slave entities in Modbus (#151522)
janiversen Sep 3, 2025
9ee9e17
Bump device registry version to 1.12 (#151616)
emontnemery Sep 3, 2025
5fc6fb9
Update frontend to 20250903.1 (#151617)
bramkragten Sep 3, 2025
955ef3b
Remove deprecated target position attributes from ZHA covers (#142534)
jeverley Sep 3, 2025
df46816
Add reload support to schema options flow handler (#151260)
gjohansson-ST Sep 3, 2025
0e1dd04
Simplify Modbus update methods (#151494)
janiversen Sep 3, 2025
1369a98
Fix for deCONZ issue - Detected that integration 'deconz' calls devic…
mattreim Sep 3, 2025
e5a44e5
Fix naming of "State of charge" sensor in `growatt_server` (#151619)
NoRi2909 Sep 3, 2025
aeff62f
Correct critical notification variable name in Flo (#151523)
BenJewell Sep 3, 2025
eccadd4
script/bootstrap to update core deps (#151624)
balloob Sep 3, 2025
18ca959
Sort template config menu step by user language (#151596)
karwosts Sep 3, 2025
b9f24bb
Update frontend to 20250903.2 (#151629)
bramkragten Sep 3, 2025
e67df73
Clarify behavior of ConfigEntry.async_on_state_change (#151628)
emontnemery Sep 3, 2025
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
2 changes: 1 addition & 1 deletion homeassistant/components/asuswrt/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,5 @@
"integration_type": "hub",
"iot_class": "local_polling",
"loggers": ["aioasuswrt", "asusrouter", "asyncssh"],
"requirements": ["aioasuswrt==1.4.0", "asusrouter==1.20.1"]
"requirements": ["aioasuswrt==1.4.0", "asusrouter==1.21.0"]
}
2 changes: 1 addition & 1 deletion homeassistant/components/cloud/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,6 @@
"integration_type": "system",
"iot_class": "cloud_push",
"loggers": ["acme", "hass_nabucasa", "snitun"],
"requirements": ["hass-nabucasa==1.0.0"],
"requirements": ["hass-nabucasa==1.1.0"],
"single_config_entry": true
}
2 changes: 1 addition & 1 deletion homeassistant/components/deconz/entity.py
Original file line number Diff line number Diff line change
Expand Up @@ -177,7 +177,7 @@ def device_info(self) -> DeviceInfo:
"""Return a device description for device registry."""
return DeviceInfo(
identifiers={(DOMAIN, self._group_identifier)},
manufacturer="Dresden Elektronik",
manufacturer="dresden elektronik",
model="deCONZ group",
name=self.group.name,
via_device=(DOMAIN, self.hub.api.config.bridge_id),
Expand Down
13 changes: 1 addition & 12 deletions homeassistant/components/deconz/hub/hub.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@
from homeassistant.config_entries import SOURCE_HASSIO
from homeassistant.core import Event, HomeAssistant, callback
from homeassistant.helpers import device_registry as dr, entity_registry as er
from homeassistant.helpers.device_registry import CONNECTION_NETWORK_MAC
from homeassistant.helpers.dispatcher import async_dispatcher_send

from ..const import CONF_MASTER_GATEWAY, DOMAIN, HASSIO_CONFIGURATION_URL, PLATFORMS
Expand Down Expand Up @@ -169,17 +168,8 @@ def async_connection_status_callback(self, available: bool) -> None:

async def async_update_device_registry(self) -> None:
"""Update device registry."""
if self.api.config.mac is None:
return

device_registry = dr.async_get(self.hass)

# Host device
device_registry.async_get_or_create(
config_entry_id=self.config_entry.entry_id,
connections={(CONNECTION_NETWORK_MAC, self.api.config.mac)},
)

# Gateway service
configuration_url = f"http://{self.config.host}:{self.config.port}"
if self.config_entry.source == SOURCE_HASSIO:
Expand All @@ -189,11 +179,10 @@ async def async_update_device_registry(self) -> None:
configuration_url=configuration_url,
entry_type=dr.DeviceEntryType.SERVICE,
identifiers={(DOMAIN, self.api.config.bridge_id)},
manufacturer="Dresden Elektronik",
manufacturer="dresden elektronik",
model=self.api.config.model_id,
name=self.api.config.name,
sw_version=self.api.config.software_version,
via_device=(CONNECTION_NETWORK_MAC, self.api.config.mac),
)

@staticmethod
Expand Down
2 changes: 1 addition & 1 deletion homeassistant/components/deconz/light.py
Original file line number Diff line number Diff line change
Expand Up @@ -396,7 +396,7 @@ def device_info(self) -> DeviceInfo:
"""Return a device description for device registry."""
return DeviceInfo(
identifiers={(DOMAIN, self.unique_id)},
manufacturer="Dresden Elektronik",
manufacturer="dresden elektronik",
model="deCONZ group",
name=self._device.name,
via_device=(DOMAIN, self.hub.api.config.bridge_id),
Expand Down
13 changes: 2 additions & 11 deletions homeassistant/components/deconz/services.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@
device_registry as dr,
entity_registry as er,
)
from homeassistant.helpers.device_registry import CONNECTION_NETWORK_MAC
from homeassistant.util.read_only_dict import ReadOnlyDict

from .const import CONF_BRIDGE_ID, DOMAIN, LOGGER
Expand Down Expand Up @@ -120,8 +119,8 @@ async def async_configure_service(hub: DeconzHub, data: ReadOnlyDict) -> None:
"field": "/lights/1/state",
"data": {"on": true}
}
See Dresden Elektroniks REST API documentation for details:
http://dresden-elektronik.github.io/deconz-rest-doc/rest/
See deCONZ REST-API documentation for details:
https://dresden-elektronik.github.io/deconz-rest-doc/
"""
field = data.get(SERVICE_FIELD, "")
entity_id = data.get(SERVICE_ENTITY)
Expand Down Expand Up @@ -162,14 +161,6 @@ async def async_remove_orphaned_entries_service(hub: DeconzHub) -> None:
)
]

# Don't remove the Gateway host entry
if hub.api.config.mac:
hub_host = device_registry.async_get_device(
connections={(CONNECTION_NETWORK_MAC, hub.api.config.mac)},
)
if hub_host and hub_host.id in devices_to_be_removed:
devices_to_be_removed.remove(hub_host.id)

# Don't remove the Gateway service entry
hub_service = device_registry.async_get_device(
identifiers={(DOMAIN, hub.api.config.bridge_id)}
Expand Down
2 changes: 1 addition & 1 deletion homeassistant/components/ecowitt/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,5 @@
"dependencies": ["webhook"],
"documentation": "https://www.home-assistant.io/integrations/ecowitt",
"iot_class": "local_push",
"requirements": ["aioecowitt==2025.3.1"]
"requirements": ["aioecowitt==2025.9.0"]
}
2 changes: 1 addition & 1 deletion homeassistant/components/flo/coordinator.py
Original file line number Diff line number Diff line change
Expand Up @@ -190,7 +190,7 @@ def has_alerts(self) -> bool:
return bool(
self.pending_info_alerts_count
or self.pending_warning_alerts_count
or self.pending_warning_alerts_count
or self.pending_critical_alerts_count
)

@property
Expand Down
2 changes: 1 addition & 1 deletion homeassistant/components/frontend/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,5 +20,5 @@
"documentation": "https://www.home-assistant.io/integrations/frontend",
"integration_type": "system",
"quality_scale": "internal",
"requirements": ["home-assistant-frontend==20250902.1"]
"requirements": ["home-assistant-frontend==20250903.2"]
}
4 changes: 2 additions & 2 deletions homeassistant/components/growatt_server/strings.json
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@
"name": "Inverter temperature"
},
"mix_statement_of_charge": {
"name": "Statement of charge"
"name": "State of charge"
},
"mix_battery_charge_today": {
"name": "Battery charged today"
Expand Down Expand Up @@ -425,7 +425,7 @@
"name": "Lifetime total load consumption"
},
"tlx_statement_of_charge": {
"name": "Statement of charge (SoC)"
"name": "State of charge (SoC)"
},
"total_money_today": {
"name": "Total money today"
Expand Down
5 changes: 4 additions & 1 deletion homeassistant/components/modbus/binary_sensor.py
Original file line number Diff line number Diff line change
Expand Up @@ -157,5 +157,8 @@ async def async_added_to_hass(self) -> None:
def _handle_coordinator_update(self) -> None:
"""Handle updated data from the coordinator."""
result = self.coordinator.data
self._attr_is_on = bool(result[self._result_inx] & 1) if result else None
if not result or self._result_inx >= len(result):
self._attr_is_on = None
else:
self._attr_is_on = bool(result[self._result_inx] & 1)
super()._handle_coordinator_update()
8 changes: 4 additions & 4 deletions homeassistant/components/modbus/climate.py
Original file line number Diff line number Diff line change
Expand Up @@ -363,7 +363,7 @@ async def async_set_hvac_mode(self, hvac_mode: HVACMode) -> None:
)
break

await self._async_update_write_state()
await self.async_local_update(cancel_pending_update=True)

async def async_set_fan_mode(self, fan_mode: str) -> None:
"""Set new target fan mode."""
Expand All @@ -385,7 +385,7 @@ async def async_set_fan_mode(self, fan_mode: str) -> None:
CALL_TYPE_WRITE_REGISTER,
)

await self._async_update_write_state()
await self.async_local_update(cancel_pending_update=True)

async def async_set_swing_mode(self, swing_mode: str) -> None:
"""Set new target swing mode."""
Expand All @@ -408,7 +408,7 @@ async def async_set_swing_mode(self, swing_mode: str) -> None:
CALL_TYPE_WRITE_REGISTER,
)
break
await self._async_update_write_state()
await self.async_local_update(cancel_pending_update=True)

async def async_set_temperature(self, **kwargs: Any) -> None:
"""Set new target temperature."""
Expand Down Expand Up @@ -463,7 +463,7 @@ async def async_set_temperature(self, **kwargs: Any) -> None:
CALL_TYPE_WRITE_REGISTERS,
)
self._attr_available = result is not None
await self._async_update_write_state()
await self.async_local_update(cancel_pending_update=True)

async def _async_update(self) -> None:
"""Update Target & Current Temperature."""
Expand Down
4 changes: 2 additions & 2 deletions homeassistant/components/modbus/cover.py
Original file line number Diff line number Diff line change
Expand Up @@ -111,15 +111,15 @@ async def async_open_cover(self, **kwargs: Any) -> None:
self._slave, self._write_address, self._state_open, self._write_type
)
self._attr_available = result is not None
await self._async_update_write_state()
await self.async_local_update(cancel_pending_update=True)

async def async_close_cover(self, **kwargs: Any) -> None:
"""Close cover."""
result = await self._hub.async_pb_call(
self._slave, self._write_address, self._state_closed, self._write_type
)
self._attr_available = result is not None
await self._async_update_write_state()
await self.async_local_update(cancel_pending_update=True)

async def _async_update(self) -> None:
"""Update the state of the cover."""
Expand Down
79 changes: 24 additions & 55 deletions homeassistant/components/modbus/entity.py
Original file line number Diff line number Diff line change
Expand Up @@ -112,14 +112,16 @@ def get_optional_numeric_config(config_name: str) -> int | float | None:
async def _async_update(self) -> None:
"""Virtual function to be overwritten."""

async def async_update(self) -> None:
async def async_update(self, now: datetime | None = None) -> None:
"""Update the entity state."""
if self._cancel_call:
self._cancel_call()
await self.async_local_update()
await self.async_local_update(cancel_pending_update=True)

async def async_local_update(self, now: datetime | None = None) -> None:
async def async_local_update(
self, now: datetime | None = None, cancel_pending_update: bool = False
) -> None:
"""Update the entity state."""
if cancel_pending_update and self._cancel_call:
self._cancel_call()
await self._async_update()
self.async_write_ha_state()
if self._scan_interval > 0:
Expand All @@ -131,62 +133,22 @@ async def async_local_update(self, now: datetime | None = None) -> None:

async def async_will_remove_from_hass(self) -> None:
"""Remove entity from hass."""
_LOGGER.debug(f"Removing entity {self._attr_name}")
if self._cancel_call:
self._cancel_call()
self._cancel_call = None
self.async_disable()

@callback
def async_hold(self) -> None:
def async_disable(self) -> None:
"""Remote stop entity."""
_LOGGER.debug(f"hold entity {self._attr_name}")
self._async_cancel_future_pending_update()
self._attr_available = False
self.async_write_ha_state()

async def _async_update_write_state(self) -> None:
"""Update the entity state and write it to the state machine."""
_LOGGER.info(f"hold entity {self._attr_name}")
if self._cancel_call:
self._cancel_call()
self._cancel_call = None
await self.async_local_update()

async def _async_update_if_not_in_progress(
self, now: datetime | None = None
) -> None:
"""Update the entity state if not already in progress."""
await self._async_update_write_state()

@callback
def async_run(self) -> None:
"""Remote start entity."""
_LOGGER.info(f"start entity {self._attr_name}")
self._async_schedule_future_update(0.1)
self._cancel_call = async_call_later(
self.hass, timedelta(seconds=0.1), self.async_local_update
)
self._attr_available = True
self._attr_available = False
self.async_write_ha_state()

@callback
def _async_schedule_future_update(self, delay: float) -> None:
"""Schedule an update in the future."""
self._async_cancel_future_pending_update()
self._cancel_call = async_call_later(
self.hass, delay, self._async_update_if_not_in_progress
)

@callback
def _async_cancel_future_pending_update(self) -> None:
"""Cancel a future pending update."""
if self._cancel_call:
self._cancel_call()
self._cancel_call = None

async def async_await_connection(self, _now: Any) -> None:
"""Wait for first connect."""
await self._hub.event_connected.wait()
self.async_run()
await self.async_local_update(cancel_pending_update=True)

async def async_base_added_to_hass(self) -> None:
"""Handle entity which will be added."""
Expand All @@ -198,10 +160,12 @@ async def async_base_added_to_hass(self) -> None:
)
)
self.async_on_remove(
async_dispatcher_connect(self.hass, SIGNAL_STOP_ENTITY, self.async_hold)
async_dispatcher_connect(self.hass, SIGNAL_STOP_ENTITY, self.async_disable)
)
self.async_on_remove(
async_dispatcher_connect(self.hass, SIGNAL_START_ENTITY, self.async_run)
async_dispatcher_connect(
self.hass, SIGNAL_START_ENTITY, self.async_local_update
)
)


Expand Down Expand Up @@ -388,10 +352,15 @@ async def async_turn(self, command: int) -> None:
return

if self._verify_delay:
self._async_schedule_future_update(self._verify_delay)
assert self._verify_delay == 1
if self._cancel_call:
self._cancel_call()
self._cancel_call = None
self._cancel_call = async_call_later(
self.hass, self._verify_delay, self.async_update
)
return

await self._async_update_write_state()
await self.async_local_update(cancel_pending_update=True)

async def async_turn_off(self, **kwargs: Any) -> None:
"""Set switch off."""
Expand Down
17 changes: 8 additions & 9 deletions homeassistant/components/modbus/modbus.py
Original file line number Diff line number Diff line change
Expand Up @@ -312,15 +312,14 @@ def _log_error(self, text: str) -> None:
async def async_pb_connect(self) -> None:
"""Connect to device, async."""
while True:
async with self._lock:
try:
if await self._client.connect(): # type: ignore[union-attr]
_LOGGER.info(f"modbus {self.name} communication open")
break
except ModbusException as exception_error:
self._log_error(
f"{self.name} connect failed, please check your configuration ({exception_error!s})"
)
try:
if await self._client.connect(): # type: ignore[union-attr]
_LOGGER.info(f"modbus {self.name} communication open")
break
except ModbusException as exception_error:
self._log_error(
f"{self.name} connect failed, please check your configuration ({exception_error!s})"
)
_LOGGER.info(
f"modbus {self.name} connect NOT a success ! retrying in {PRIMARY_RECONNECT_DELAY} seconds"
)
Expand Down
8 changes: 6 additions & 2 deletions homeassistant/components/modbus/sensor.py
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,10 @@ async def async_added_to_hass(self) -> None:
def _handle_coordinator_update(self) -> None:
"""Handle updated data from the coordinator."""
result = self.coordinator.data
self._attr_native_value = result[self._idx] if result else None
self._attr_available = result is not None
if not result or self._idx >= len(result):
self._attr_native_value = None
self._attr_available = False
else:
self._attr_native_value = result[self._idx]
self._attr_available = True
super()._handle_coordinator_update()
2 changes: 1 addition & 1 deletion homeassistant/components/template/config_flow.py
Original file line number Diff line number Diff line change
Expand Up @@ -514,7 +514,7 @@ async def _validate_user_input(
]

CONFIG_FLOW = {
"user": SchemaFlowMenuStep(TEMPLATE_TYPES),
"user": SchemaFlowMenuStep(TEMPLATE_TYPES, True),
Platform.ALARM_CONTROL_PANEL: SchemaFlowFormStep(
config_schema(Platform.ALARM_CONTROL_PANEL),
preview="template",
Expand Down
Loading
Loading