Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
e04ecc6
Move HTTP views into their own module in HTML5 integration (#181889)
tr4nt0r Sep 13, 2026
8a18719
Add a maximum volume sensor to Lyngdorf (#181800)
fishloa Sep 13, 2026
6eff43c
Add device_id support for MCP Server (#182057)
Shulyaka Sep 13, 2026
9a0190e
Allow to configure the FRITZ!Smarthome integration with an URL (#179839)
mib1185 Sep 13, 2026
e333e97
Bump nextdns to 5.1.0 (#182099)
bieniu Sep 13, 2026
4abc131
Add price type and interval options to EnergyZero energy price action…
klaasnicolaas Sep 13, 2026
80a2ea2
Bump aiolibrenms to 0.0.4 (#182097)
mib1185 Sep 13, 2026
0ab651a
Bump probatio to 0.12.1 (#182101)
frenck Sep 13, 2026
862adee
Remove deprecated openai_conversation services (#181750)
Shulyaka Sep 13, 2026
7830a1f
Fix swallowed exceptions in mochad action handlers (#181869)
hktitof Sep 13, 2026
6c0b484
Bump earn-e-p1 to 0.3.0 (#182104)
Miggets7 Sep 13, 2026
0e181a8
Add L2 and L3 voltage and current sensors to EARN-E P1 Meter (#181833)
Miggets7 Sep 13, 2026
d4466a8
Update Airly to Bronze (#181024)
bieniu Sep 13, 2026
ba84f9b
Update IQS rules list for Airly (#181924)
bieniu Sep 13, 2026
5b42aae
Fix function name in external statistics mean_type message (#182031)
Booyaka101 Sep 13, 2026
ee14c3b
Require the IRK in the Private BLE Device config flow (#181969)
frenck Sep 13, 2026
eb5024a
Add quality scale file for vizio declaring platinum (#180066)
raman325 Sep 13, 2026
fdb882c
Advertise required tool parameters in MCP Server (#182105)
balloob Sep 13, 2026
743b148
Use probatio directly in tests, scripts and pylint plugins (#182113)
frenck Sep 13, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
1 change: 1 addition & 0 deletions homeassistant/components/airly/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,6 @@
"integration_type": "service",
"iot_class": "cloud_polling",
"loggers": ["airly"],
"quality_scale": "bronze",
"requirements": ["airly==1.1.0"]
}
6 changes: 2 additions & 4 deletions homeassistant/components/airly/quality_scale.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ rules:
comment: This integration does not have any conditions.
docs-high-level-description: done
docs-installation-instructions: done
docs-removal-instructions: todo
docs-removal-instructions: done
entity-event-setup: done
entity-unique-id: done
has-entity-name: done
Expand All @@ -37,9 +37,7 @@ rules:
docs-configuration-parameters:
status: exempt
comment: The integration does not have an options flow.
docs-installation-parameters:
status: todo
comment: The documentation does not describe all setup parameters.
docs-installation-parameters: done
entity-unavailable: done
integration-owner: done
log-when-unavailable: done
Expand Down
3 changes: 3 additions & 0 deletions homeassistant/components/earn_e_p1/coordinator.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ def __init__(
self.mac = mac
self.model: str | None = None
self.sw_version: str | None = None
self.data_complete = False
self._listener = listener

def _handle_update(self, device: EarnEP1Device, _raw: dict[str, Any]) -> None:
Expand All @@ -62,6 +63,8 @@ def _handle_update(self, device: EarnEP1Device, _raw: dict[str, Any]) -> None:
model=self.model,
sw_version=self.sw_version,
)
# Listeners run synchronously from async_set_updated_data and read this.
self.data_complete = device.data_complete
self.async_set_updated_data(device.data)

def start(self) -> None:
Expand Down
2 changes: 1 addition & 1 deletion homeassistant/components/earn_e_p1/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,5 +15,5 @@
"integration_type": "device",
"iot_class": "local_push",
"quality_scale": "bronze",
"requirements": ["earn-e-p1==0.2.0"]
"requirements": ["earn-e-p1==0.3.0"]
}
46 changes: 42 additions & 4 deletions homeassistant/components/earn_e_p1/sensor.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,15 +46,53 @@
),
SensorEntityDescription(
key="voltage_l1",
translation_key="voltage_l1",
translation_key="voltage_phase",
translation_placeholders={"phase": "1"},
native_unit_of_measurement=UnitOfElectricPotential.VOLT,
device_class=SensorDeviceClass.VOLTAGE,
state_class=SensorStateClass.MEASUREMENT,
suggested_display_precision=0,
),
SensorEntityDescription(
key="voltage_l2",
translation_key="voltage_phase",
translation_placeholders={"phase": "2"},
native_unit_of_measurement=UnitOfElectricPotential.VOLT,
device_class=SensorDeviceClass.VOLTAGE,
state_class=SensorStateClass.MEASUREMENT,
suggested_display_precision=0,
),
SensorEntityDescription(
key="voltage_l3",
translation_key="voltage_phase",
translation_placeholders={"phase": "3"},
native_unit_of_measurement=UnitOfElectricPotential.VOLT,
device_class=SensorDeviceClass.VOLTAGE,
state_class=SensorStateClass.MEASUREMENT,
suggested_display_precision=0,
),
SensorEntityDescription(
key="current_l1",
translation_key="current_l1",
translation_key="current_phase",
translation_placeholders={"phase": "1"},
native_unit_of_measurement=UnitOfElectricCurrent.AMPERE,
device_class=SensorDeviceClass.CURRENT,
state_class=SensorStateClass.MEASUREMENT,
suggested_display_precision=2,
),
SensorEntityDescription(
key="current_l2",
translation_key="current_phase",
translation_placeholders={"phase": "2"},
native_unit_of_measurement=UnitOfElectricCurrent.AMPERE,
device_class=SensorDeviceClass.CURRENT,
state_class=SensorStateClass.MEASUREMENT,
suggested_display_precision=2,
),
SensorEntityDescription(
key="current_l3",
translation_key="current_phase",
translation_placeholders={"phase": "3"},
native_unit_of_measurement=UnitOfElectricCurrent.AMPERE,
device_class=SensorDeviceClass.CURRENT,
state_class=SensorStateClass.MEASUREMENT,
Expand Down Expand Up @@ -140,11 +178,11 @@ def _async_add_sensors() -> None:
for description in SENSOR_DESCRIPTIONS
if description.key in new_keys
)
if not pending_keys:
if not pending_keys or coordinator.data_complete:
_async_remove_listener()

_async_add_sensors()
if pending_keys:
if pending_keys and not coordinator.data_complete:
remove_listener = coordinator.async_add_listener(_async_add_sensors)
entry.async_on_unload(_async_remove_listener)

Expand Down
8 changes: 4 additions & 4 deletions homeassistant/components/earn_e_p1/strings.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,8 @@
},
"entity": {
"sensor": {
"current_l1": {
"name": "Current L1"
"current_phase": {
"name": "Current phase {phase}"
},
"energy_exported_tariff1": {
"name": "Energy exported tariff 1"
Expand All @@ -52,8 +52,8 @@
"power_imported": {
"name": "Power imported"
},
"voltage_l1": {
"name": "Voltage L1"
"voltage_phase": {
"name": "Voltage phase {phase}"
},
"wifi_rssi": {
"name": "Wi-Fi RSSI"
Expand Down
20 changes: 18 additions & 2 deletions homeassistant/components/energyzero/services.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,10 @@
ATTR_START: Final = "start"
ATTR_END: Final = "end"
ATTR_INCL_VAT: Final = "incl_vat"
ATTR_PRICE_TYPE: Final = "price_type"
ATTR_INTERVAL: Final = "interval"

ENERGY_INTERVALS = {"hour": Interval.HOUR, "quarter": Interval.QUARTER}

GAS_SERVICE_NAME: Final = "get_gas_prices"
ENERGY_SERVICE_NAME: Final = "get_energy_prices"
Expand All @@ -43,6 +47,13 @@
}
)

ENERGY_SERVICE_SCHEMA: Final = SERVICE_SCHEMA.extend(
{
vol.Optional(ATTR_PRICE_TYPE, default="market"): vol.In(("market", "all_in")),
vol.Optional(ATTR_INTERVAL, default="hour"): vol.In(ENERGY_INTERVALS),
}
)


class ServicePriceType(Enum):
"""Type of service."""
Expand Down Expand Up @@ -142,6 +153,11 @@ async def __get_prices(
PriceType.MARKET_WITH_VAT if call.data[ATTR_INCL_VAT] else PriceType.MARKET
)

if price_type is ServicePriceType.ENERGY and call.data[ATTR_PRICE_TYPE] == "all_in":
selected_price_type = (
PriceType.ALL_IN if call.data[ATTR_INCL_VAT] else PriceType.ALL_IN_EXCL_VAT
)

price_data: list[EnergyPrices] = []
for day_offset in range((end_date - start_date).days + 1):
request_date = start_date + timedelta(days=day_offset)
Expand All @@ -156,7 +172,7 @@ async def __get_prices(
prices = coordinator.energyzero.get_electricity_prices(
start_date=request_date,
end_date=request_date,
interval=Interval.HOUR,
interval=ENERGY_INTERVALS[call.data[ATTR_INTERVAL]],
price_type=selected_price_type,
local_tz=local_tz,
)
Expand Down Expand Up @@ -190,6 +206,6 @@ def async_setup_services(hass: HomeAssistant) -> None:
DOMAIN,
ENERGY_SERVICE_NAME,
partial(__get_prices, price_type=ServicePriceType.ENERGY),
schema=SERVICE_SCHEMA,
schema=ENERGY_SERVICE_SCHEMA,
supports_response=SupportsResponse.ONLY,
)
16 changes: 16 additions & 0 deletions homeassistant/components/energyzero/services.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,22 @@ get_energy_prices:
default: true
selector:
boolean:
price_type:
default: market
selector:
select:
translation_key: price_type
options:
- market
- all_in
interval:
default: hour
selector:
select:
translation_key: interval
options:
- hour
- quarter
start:
required: false
example: "2023-01-01 00:00:00"
Expand Down
20 changes: 20 additions & 0 deletions homeassistant/components/energyzero/strings.json
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,18 @@
"hourly": "Hourly",
"quarter_hourly": "Quarter-hourly"
}
},
"interval": {
"options": {
"hour": "[%key:component::energyzero::selector::electricity_price_interval::options::hourly%]",
"quarter": "[%key:component::energyzero::selector::electricity_price_interval::options::quarter_hourly%]"
}
},
"price_type": {
"options": {
"all_in": "All-in",
"market": "Market"
}
}
},
"services": {
Expand All @@ -105,6 +117,14 @@
"description": "[%key:component::energyzero::services::get_gas_prices::fields::incl_vat::description%]",
"name": "[%key:component::energyzero::services::get_gas_prices::fields::incl_vat::name%]"
},
"interval": {
"description": "The interval of electricity prices to retrieve. Defaults to hourly, independently of the electricity price interval configured for entities.",
"name": "Interval"
},
"price_type": {
"description": "The type of electricity prices to retrieve. Defaults to market prices.",
"name": "Price type"
},
"start": {
"description": "[%key:component::energyzero::services::get_gas_prices::fields::start::description%]",
"name": "[%key:component::energyzero::services::get_gas_prices::fields::start::name%]"
Expand Down
53 changes: 51 additions & 2 deletions homeassistant/components/fritzbox/__init__.py
Original file line number Diff line number Diff line change
@@ -1,14 +1,20 @@
"""Support for AVM FRITZ!SmartHome devices."""

from requests.exceptions import ConnectionError as RequestConnectionError, HTTPError
from yarl import URL

from homeassistant.components.binary_sensor import DOMAIN as BINARY_SENSOR_DOMAIN
from homeassistant.const import EVENT_HOMEASSISTANT_STOP, UnitOfTemperature
from homeassistant.const import (
CONF_HOST,
CONF_VERIFY_SSL,
EVENT_HOMEASSISTANT_STOP,
UnitOfTemperature,
)
from homeassistant.core import Event, HomeAssistant
from homeassistant.helpers.device_registry import AnyDeviceEntry
from homeassistant.helpers.entity_registry import RegistryEntry, async_migrate_entries

from .const import DOMAIN, LOGGER, PLATFORMS
from .const import DEFAULT_VERIFY_SSL, DOMAIN, LOGGER, PLATFORMS
from .coordinator import FritzboxConfigEntry, FritzboxDataUpdateCoordinator


Expand Down Expand Up @@ -65,6 +71,49 @@ async def async_unload_entry(hass: HomeAssistant, entry: FritzboxConfigEntry) ->
return await hass.config_entries.async_unload_platforms(entry, PLATFORMS)


async def async_migrate_entry(
hass: HomeAssistant, config_entry: FritzboxConfigEntry
) -> bool:
"""Migrate old config entry to a new format."""
LOGGER.debug(
"Migrating configuration from version %s.%s",
config_entry.version,
config_entry.minor_version,
)
if config_entry.version > 1:
# This means the user has downgraded from a future version
return False

if config_entry.version == 1:
new_data = {**config_entry.data}
if config_entry.minor_version < 2:
LOGGER.debug("Migrate config entry data to URL based configuration")
if "://" not in config_entry.data[CONF_HOST]:
host = URL().build(
scheme="http",
host=config_entry.data[CONF_HOST],
)
else:
host = config_entry.data[CONF_HOST]

new_data = {
**config_entry.data,
CONF_HOST: str(host),
CONF_VERIFY_SSL: DEFAULT_VERIFY_SSL,
}

hass.config_entries.async_update_entry(
config_entry, data=new_data, version=1, minor_version=2
)

LOGGER.debug(
"Migration to configuration version %s.%s successful",
config_entry.version,
config_entry.minor_version,
)
return True


async def async_remove_config_entry_device(
hass: HomeAssistant, entry: FritzboxConfigEntry, device: AnyDeviceEntry
) -> bool:
Expand Down
Loading
Loading