Skip to content
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
6 changes: 1 addition & 5 deletions homeassistant/components/backblaze_b2/quality_scale.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -123,8 +123,4 @@ rules:
comment: |
The b2sdk library does not support custom HTTP session injection.
It manages HTTP connections internally through its own session management.
strict-typing:
status: exempt
comment: |
The b2sdk dependency does not include a py.typed file and is not PEP 561 compliant.
This is outside the integration's control as it's a third-party library requirement.
strict-typing: todo
2 changes: 1 addition & 1 deletion homeassistant/components/blebox/update.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
from .coordinator import BleBoxCoordinator
from .entity import BleBoxEntity

PARALLEL_UPDATES = 0
PARALLEL_UPDATES = 1
SCAN_INTERVAL = timedelta(hours=1)


Expand Down
2 changes: 1 addition & 1 deletion homeassistant/components/daikin/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,6 @@
"integration_type": "device",
"iot_class": "local_polling",
"loggers": ["pydaikin"],
"requirements": ["pydaikin==2.18.1"],
"requirements": ["pydaikin==2.18.2"],
"zeroconf": ["_dkapi._tcp.local."]
}
3 changes: 3 additions & 0 deletions homeassistant/components/energieleser/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,10 @@

from homeassistant.const import CONF_HOST, Platform
from homeassistant.core import HomeAssistant
from homeassistant.helpers import issue_registry as ir
from homeassistant.helpers.aiohttp_client import async_get_clientsession

from .const import DOMAIN
from .coordinator import EnergieleserConfigEntry, EnergieleserCoordinator

PLATFORMS: list[Platform] = [Platform.SENSOR]
Expand All @@ -30,4 +32,5 @@ async def async_unload_entry(
hass: HomeAssistant, entry: EnergieleserConfigEntry
) -> bool:
"""Unload an energieleser config entry."""
ir.async_delete_issue(hass, DOMAIN, f"pin_locked_{entry.entry_id}")
return await hass.config_entries.async_unload_platforms(entry, PLATFORMS)
21 changes: 21 additions & 0 deletions homeassistant/components/energieleser/coordinator.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,13 @@
EnergieleserDevice,
EnergieleserError,
EnergieleserUnknownDeviceError,
StromleserOneDevice,
)

from homeassistant.config_entries import ConfigEntry
from homeassistant.const import CONF_DEVICE_ID
from homeassistant.core import HomeAssistant
from homeassistant.helpers import issue_registry as ir
from homeassistant.helpers.update_coordinator import DataUpdateCoordinator, UpdateFailed

from .const import DOMAIN, LOGGER
Expand Down Expand Up @@ -74,4 +76,23 @@ async def _async_update_data(self) -> EnergieleserDevice:
"device_id": self.device_id,
},
) from err
if isinstance(device, StromleserOneDevice):
issue_id = f"pin_locked_{self.config_entry.entry_id}"
if device.pin_locked:
ir.async_create_issue(
self.hass,
DOMAIN,
issue_id,
is_fixable=False,
is_persistent=False,
learn_more_url="https://docs.energieleser.de/en/docs/stromleser-one/installation/preparation",
severity=ir.IssueSeverity.WARNING,
translation_key="meter_locked",
translation_placeholders={
"device_name": self.config_entry.title,
},
)
else:
ir.async_delete_issue(self.hass, DOMAIN, issue_id)

return device
2 changes: 1 addition & 1 deletion homeassistant/components/energieleser/quality_scale.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ rules:
exception-translations: done
icon-translations: todo
reconfiguration-flow: done
repair-issues: todo
repair-issues: done
stale-devices:
status: exempt
comment: One device per config entry; the device is removed when the entry is removed.
Expand Down
6 changes: 6 additions & 0 deletions homeassistant/components/energieleser/strings.json
Original file line number Diff line number Diff line change
Expand Up @@ -103,5 +103,11 @@
"unknown_device": {
"message": "The device type for {device_id} is unknown or unsupported"
}
},
"issues": {
"meter_locked": {
"description": "The electricity meter connected to {device_name} is not providing high-resolution data. You need to unlock the physical meter by entering the PIN (provided by your electricity company or grid operator) directly on the meter. Once the meter is unlocked, high-resolution data will be provided and this issue will resolve itself automatically. See the linked instructions for details on how to enter the PIN.",
"title": "Meter PIN Required"
}
}
}
18 changes: 9 additions & 9 deletions homeassistant/components/gpslogger/device_tracker.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,11 @@

from typing import override

from homeassistant.components.device_tracker import TrackerEntity
from homeassistant.const import (
ATTR_BATTERY_LEVEL,
ATTR_GPS_ACCURACY,
ATTR_LATITUDE,
ATTR_LONGITUDE,
from homeassistant.components.device_tracker import (
TrackerEntity,
TrackerEntityStateAttribute,
)
from homeassistant.const import ATTR_BATTERY_LEVEL, EntityStateAttribute
from homeassistant.core import HomeAssistant, callback
from homeassistant.helpers import device_registry as dr
from homeassistant.helpers.device_registry import DeviceInfo
Expand Down Expand Up @@ -120,9 +118,11 @@ async def async_added_to_hass(self) -> None:
return

attr = state.attributes
self._attr_latitude = attr.get(ATTR_LATITUDE)
self._attr_longitude = attr.get(ATTR_LONGITUDE)
self._attr_location_accuracy = attr.get(ATTR_GPS_ACCURACY, 0)
self._attr_latitude = attr.get(EntityStateAttribute.LATITUDE)
self._attr_longitude = attr.get(EntityStateAttribute.LONGITUDE)
self._attr_location_accuracy = attr.get(
TrackerEntityStateAttribute.GPS_ACCURACY, 0
)
self._attr_extra_state_attributes = {
ATTR_ALTITUDE: attr.get(ATTR_ALTITUDE),
ATTR_ACTIVITY: attr.get(ATTR_ACTIVITY),
Expand Down
14 changes: 14 additions & 0 deletions homeassistant/components/led_infrared/diagnostics.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
"""Diagnostics platform for the LED Infrared integration."""

from typing import Any

from homeassistant.config_entries import ConfigEntry
from homeassistant.core import HomeAssistant


async def async_get_config_entry_diagnostics(
hass: HomeAssistant, config_entry: ConfigEntry
) -> dict[str, Any]:
"""Return diagnostics for a config entry."""

return dict(config_entry.data)
2 changes: 1 addition & 1 deletion homeassistant/components/led_infrared/quality_scale.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ rules:
test-coverage: todo
# Gold
devices: done
diagnostics: todo
diagnostics: done
discovery-update-info:
status: exempt
comment: |
Expand Down
2 changes: 1 addition & 1 deletion homeassistant/components/modbus_connection/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,5 @@
"iot_class": "local_polling",
"loggers": ["modbus_connection", "tmodbus"],
"quality_scale": "bronze",
"requirements": ["modbus-connection[tmodbus]==3.4.1"]
"requirements": ["modbus-connection[tmodbus]==3.6.0"]
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
)
from homeassistant.const import EntityCategory
from homeassistant.core import HomeAssistant
from homeassistant.helpers.device_registry import DeviceInfo
from homeassistant.helpers.device_registry import DeviceEntryType, DeviceInfo
from homeassistant.helpers.entity_platform import AddConfigEntryEntitiesCallback
from homeassistant.helpers.update_coordinator import CoordinatorEntity

Expand Down Expand Up @@ -109,6 +109,7 @@ def __init__(
name=coordinator.name,
manufacturer=INTEGRATION_TITLE,
model=ROUTE_MODEL,
entry_type=DeviceEntryType.SERVICE,
)

@property
Expand Down
3 changes: 2 additions & 1 deletion homeassistant/components/nederlandse_spoorwegen/sensor.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
)
from homeassistant.const import EntityCategory
from homeassistant.core import HomeAssistant
from homeassistant.helpers.device_registry import DeviceInfo
from homeassistant.helpers.device_registry import DeviceEntryType, DeviceInfo
from homeassistant.helpers.entity_platform import AddConfigEntryEntitiesCallback
from homeassistant.helpers.typing import StateType
from homeassistant.helpers.update_coordinator import CoordinatorEntity
Expand Down Expand Up @@ -202,6 +202,7 @@ def __init__(
name=coordinator.name,
manufacturer=INTEGRATION_TITLE,
model=ROUTE_MODEL,
entry_type=DeviceEntryType.SERVICE,
)

@property
Expand Down
1 change: 0 additions & 1 deletion homeassistant/components/network/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
"domain": "network",
"name": "Network Configuration",
"codeowners": ["@home-assistant/core"],
"dependencies": ["websocket_api"],
"documentation": "https://www.home-assistant.io/integrations/network",
"integration_type": "system",
"iot_class": "local_push",
Expand Down
18 changes: 14 additions & 4 deletions homeassistant/components/nobo_hub/climate.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,8 +56,6 @@ async def async_setup_entry(
async_add_entities: AddConfigEntryEntitiesCallback,
) -> None:
"""Set up the Nobø Ecohub platform from UI configuration."""

# Setup connection with hub
hub = config_entry.runtime_data

override_type = (
Expand All @@ -66,8 +64,20 @@ async def async_setup_entry(
else nobo.API.OVERRIDE_TYPE_CONSTANT
)

# Add zones as entities
async_add_entities(NoboZone(zone_id, hub, override_type) for zone_id in hub.zones)
known_zones: set[str] = set()

@callback
def _add_zones(_hub: nobo) -> None:
"""Add climate entities for zones added to the hub."""
new_zones = [zone_id for zone_id in hub.zones if zone_id not in known_zones]
known_zones.update(new_zones)
async_add_entities(
NoboZone(zone_id, hub, override_type) for zone_id in new_zones
)

_add_zones(hub)
hub.register_callback(_add_zones)
config_entry.async_on_unload(lambda: hub.deregister_callback(_add_zones))


class NoboZone(NoboBaseEntity, ClimateEntity):
Expand Down
4 changes: 2 additions & 2 deletions homeassistant/components/nobo_hub/quality_scale.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -52,13 +52,13 @@ rules:
discovery: done
discovery-update-info: done
docs-data-update: done
docs-examples: todo
docs-examples: done
docs-known-limitations: done
docs-supported-devices: done
docs-supported-functions: done
docs-troubleshooting: done
docs-use-cases: done
dynamic-devices: todo
dynamic-devices: done
entity-category: todo
entity-device-class: done
entity-disabled-by-default: todo
Expand Down
23 changes: 16 additions & 7 deletions homeassistant/components/nobo_hub/select.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,6 @@ async def async_setup_entry(
async_add_entities: AddConfigEntryEntitiesCallback,
) -> None:
"""Set up any temperature sensors connected to the Nobø Ecohub."""

# Setup connection with hub
hub = config_entry.runtime_data

override_type = (
Expand All @@ -42,11 +40,22 @@ async def async_setup_entry(
else nobo.API.OVERRIDE_TYPE_CONSTANT
)

entities: list[SelectEntity] = [
NoboProfileSelector(zone_id, hub) for zone_id in hub.zones
]
entities.append(NoboGlobalSelector(hub, override_type))
async_add_entities(entities, True)
async_add_entities([NoboGlobalSelector(hub, override_type)], True)

known_zones: set[str] = set()

@callback
def _add_profiles(_hub: nobo) -> None:
"""Add week-profile selectors for zones added to the hub."""
new_zones = [zone_id for zone_id in hub.zones if zone_id not in known_zones]
known_zones.update(new_zones)
async_add_entities(
(NoboProfileSelector(zone_id, hub) for zone_id in new_zones), True
)

_add_profiles(hub)
hub.register_callback(_add_profiles)
config_entry.async_on_unload(lambda: hub.deregister_callback(_add_profiles))


class NoboGlobalSelector(NoboBaseEntity, SelectEntity):
Expand Down
25 changes: 18 additions & 7 deletions homeassistant/components/nobo_hub/sensor.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,15 +28,26 @@ async def async_setup_entry(
async_add_entities: AddConfigEntryEntitiesCallback,
) -> None:
"""Set up any temperature sensors connected to the Nobø Ecohub."""

# Setup connection with hub
hub = config_entry.runtime_data

async_add_entities(
NoboTemperatureSensor(component["serial"], hub)
for component in hub.components.values()
if component[ATTR_MODEL].has_temp_sensor
)
known_components: set[str] = set()

@callback
def _add_sensors(_hub: nobo) -> None:
"""Add temperature sensors for components added to the hub."""
new_components = [
serial
for serial, component in hub.components.items()
if component[ATTR_MODEL].has_temp_sensor and serial not in known_components
]
known_components.update(new_components)
async_add_entities(
NoboTemperatureSensor(serial, hub) for serial in new_components
)

_add_sensors(hub)
hub.register_callback(_add_sensors)
config_entry.async_on_unload(lambda: hub.deregister_callback(_add_sensors))


class NoboTemperatureSensor(NoboBaseEntity, SensorEntity):
Expand Down
2 changes: 1 addition & 1 deletion homeassistant/components/overkiz/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
"integration_type": "hub",
"iot_class": "local_polling",
"loggers": ["boto3", "botocore", "pyoverkiz", "s3transfer"],
"requirements": ["pyoverkiz[nexity]==2.0.4"],
"requirements": ["pyoverkiz[nexity]==2.1.0"],
"zeroconf": [
{
"name": "gateway*",
Expand Down
6 changes: 4 additions & 2 deletions homeassistant/components/rympro/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

import logging

from pyrympro import CannotConnectError, RymPro, UnauthorizedError
from pyrympro import CannotConnectError, OperationError, RymPro, UnauthorizedError

from homeassistant.const import CONF_EMAIL, CONF_PASSWORD, CONF_TOKEN, Platform
from homeassistant.core import HomeAssistant
Expand All @@ -22,13 +22,15 @@ async def async_setup_entry(hass: HomeAssistant, entry: RymProConfigEntry) -> bo
rympro.set_token(data[CONF_TOKEN])
try:
await rympro.account_info()
except CannotConnectError as error:
except (CannotConnectError, OperationError) as error:
raise ConfigEntryNotReady from error
except UnauthorizedError:
try:
token = await rympro.login(data[CONF_EMAIL], data[CONF_PASSWORD], "ha")
except UnauthorizedError as error:
raise ConfigEntryAuthFailed from error
except CannotConnectError as error:
raise ConfigEntryNotReady from error
hass.config_entries.async_update_entry(
entry,
data={**data, CONF_TOKEN: token},
Expand Down
17 changes: 16 additions & 1 deletion homeassistant/components/template/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,14 @@
from homeassistant.loader import async_get_integration
from homeassistant.util.hass_dict import HassKey

from .const import CONF_MAX, CONF_MIN, CONF_STEP, DOMAIN, PLATFORMS
from .const import (
CONF_ADDITIONAL_OPTIONS,
CONF_MAX,
CONF_MIN,
CONF_STEP,
DOMAIN,
PLATFORMS,
)
from .coordinator import TriggerUpdateCoordinator
from .helpers import async_get_blueprints

Expand Down Expand Up @@ -141,6 +148,14 @@ async def async_migrate_entry(hass: HomeAssistant, config_entry: ConfigEntry) ->
config_entry, version=1, minor_version=2
)

options = {**config_entry.options}
# The "advanced_options" section was renamed to "additional_options"
if (additional := options.pop("advanced_options", None)) is not None:
options[CONF_ADDITIONAL_OPTIONS] = additional
hass.config_entries.async_update_entry(
config_entry, options=options, version=2, minor_version=1
)

_LOGGER.debug(
"Migration to configuration version %s.%s successful",
config_entry.version,
Expand Down
Loading
Loading