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
14 changes: 7 additions & 7 deletions homeassistant/components/besen/config_flow.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,13 +34,10 @@ def _normalize_address(address: str) -> str:
return address.strip().upper()


PIN_SCHEMA = vol.All(
selector.TextSelector(
selector.TextSelectorConfig(
type=selector.TextSelectorType.PASSWORD,
)
),
vol.Match(r"^\d{6}$"),
PIN_SCHEMA = selector.TextSelector(
selector.TextSelectorConfig(
type=selector.TextSelectorType.PASSWORD,
)
)

PIN_ONLY_SCHEMA = vol.Schema(
Expand Down Expand Up @@ -77,6 +74,9 @@ async def _async_validate_input(
) -> str:
"""Validate setup by logging into the charger."""

if len(pin) != 6 or not pin.isdecimal():
raise InvalidAuth("PIN must be exactly 6 digits")

def _ble_device_provider() -> BLEDevice | None:
return bluetooth.async_ble_device_from_address(
hass,
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.19.0"],
"requirements": ["pydaikin==2.19.1"],
"zeroconf": ["_dkapi._tcp.local."]
}
4 changes: 4 additions & 0 deletions homeassistant/components/energyzero/coordinator.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
EnergyZeroConnectionError,
EnergyZeroNoDataError,
Interval,
PriceType,
)

from homeassistant.config_entries import ConfigEntry
Expand Down Expand Up @@ -61,12 +62,14 @@ async def _async_update_data(self) -> EnergyZeroData:
start_date=today,
end_date=today,
interval=Interval.HOUR,
price_type=PriceType.MARKET_WITH_VAT,
local_tz=local_tz,
)
try:
gas_today = await self.energyzero.get_gas_prices(
start_date=today,
end_date=today,
price_type=PriceType.MARKET_WITH_VAT,
local_tz=local_tz,
)
except EnergyZeroNoDataError:
Expand All @@ -79,6 +82,7 @@ async def _async_update_data(self) -> EnergyZeroData:
start_date=tomorrow,
end_date=tomorrow,
interval=Interval.HOUR,
price_type=PriceType.MARKET_WITH_VAT,
local_tz=local_tz,
)
except EnergyZeroNoDataError:
Expand Down
4 changes: 2 additions & 2 deletions homeassistant/components/google_assistant/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
SOURCE_CLOUD,
)
from .http import GoogleAssistantView, GoogleConfig
from .services import async_register_services
from .services import async_setup_services

from .const import EVENT_COMMAND_RECEIVED, EVENT_SYNC_RECEIVED # noqa: F401, isort:skip

Expand Down Expand Up @@ -102,7 +102,7 @@ async def async_setup(hass: HomeAssistant, yaml_config: ConfigType) -> bool:
hass.data[DOMAIN][DATA_CONFIG] = yaml_config[DOMAIN]

if CONF_SERVICE_ACCOUNT in yaml_config[DOMAIN]:
async_register_services(hass)
async_setup_services(hass)

hass.async_create_task(
hass.config_entries.flow.async_init(
Expand Down
2 changes: 1 addition & 1 deletion homeassistant/components/google_assistant/services.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@


@callback
def async_register_services(hass: HomeAssistant) -> None:
def async_setup_services(hass: HomeAssistant) -> None:
"""Register Google Assistant services."""

async def request_sync_service_handler(call: ServiceCall) -> None:
Expand Down
10 changes: 6 additions & 4 deletions homeassistant/components/hassio/const.py
Original file line number Diff line number Diff line change
Expand Up @@ -196,25 +196,27 @@
CONTAINER_STATS = "stats"
REQUEST_REFRESH_DELAY = 10

HELP_URLS = {
# Issues offering to uninstall an app, which deletes the app data as well
APP_REMOVE_URLS = {
"help_url": "https://www.home-assistant.io/help/",
"community_url": "https://community.home-assistant.io/",
"backup_url": "/config/backup",
}

EXTRA_PLACEHOLDERS = {
"issue_mount_mount_failed": {
"storage_url": "/config/storage",
},
ISSUE_KEY_ADDON_DETACHED_ADDON_REMOVED: HELP_URLS,
ISSUE_KEY_ADDON_DETACHED_ADDON_REMOVED: APP_REMOVE_URLS,
ISSUE_KEY_SYSTEM_FREE_SPACE: {
"more_info_free_space": "https://www.home-assistant.io/more-info/free-space",
"storage_url": "/config/storage",
},
ISSUE_KEY_ADDON_PWNED: {
"more_info_pwned": "https://www.home-assistant.io/more-info/pwned-passwords",
},
ISSUE_KEY_ADDON_DEPRECATED: HELP_URLS,
ISSUE_KEY_ADDON_DEPRECATED_ARCH: HELP_URLS,
ISSUE_KEY_ADDON_DEPRECATED: APP_REMOVE_URLS,
ISSUE_KEY_ADDON_DEPRECATED_ARCH: APP_REMOVE_URLS,
}


Expand Down
6 changes: 3 additions & 3 deletions homeassistant/components/hassio/strings.json
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@
},
"step": {
"addon_execute_remove": {
"description": "App {addon} is marked deprecated by the developer. This means it is no longer being maintained and so may break or become a security issue over time.\n\nReview the [readme]({addon_info}) and [documentation]({addon_documentation}) of the app to see if the developer provided instructions.\n\nSelecting **Submit** will uninstall this deprecated app. Alternatively, you can check [Home Assistant help]({help_url}) and the [community forum]({community_url}) for alternatives to migrate to."
"description": "App {addon} is marked deprecated by the developer. This means it is no longer being maintained and so may break or become a security issue over time.\n\nReview the [readme]({addon_info}) and [documentation]({addon_documentation}) of the app to see if the developer provided instructions.\n\nSelecting **Submit** will uninstall this deprecated app and permanently delete everything in its private data folder, including any databases, credentials and other internal state it kept there. Create a [backup]({backup_url}) first if you might need that data later.\n\nAlternatively, you can check [Home Assistant help]({help_url}) and the [community forum]({community_url}) for alternatives to migrate to."
}
}
},
Expand All @@ -118,7 +118,7 @@
},
"step": {
"addon_execute_remove": {
"description": "App {addon} only supports architectures and/or machines which are no longer supported by Home Assistant. It will stop working in a future release.\n\nSelecting **Submit** will uninstall this deprecated app. Alternatively, you can check [Home Assistant help]({help_url}) and the [community forum]({community_url}) for alternatives to migrate to."
"description": "App {addon} only supports architectures and/or machines which are no longer supported by Home Assistant. It will stop working in a future release.\n\nSelecting **Submit** will uninstall this deprecated app and permanently delete everything in its private data folder, including any databases, credentials and other internal state it kept there. Create a [backup]({backup_url}) first if you might need that data later.\n\nAlternatively, you can check [Home Assistant help]({help_url}) and the [community forum]({community_url}) for alternatives to migrate to."
}
}
},
Expand All @@ -135,7 +135,7 @@
},
"step": {
"addon_execute_remove": {
"description": "App {addon} has been removed from the repository it was installed from. This means it will not get updates, and backups may not be restored correctly as the Home Assistant Supervisor may not be able to build/download the resources required.\n\nSelecting **Submit** will uninstall this deprecated app. Alternatively, you can check [Home Assistant help]({help_url}) and the [community forum]({community_url}) for alternatives to migrate to."
"description": "App {addon} has been removed from the repository it was installed from. This means it will not get updates, and backups may not be restored correctly as the Home Assistant Supervisor may not be able to build/download the resources required.\n\nSelecting **Submit** will uninstall the app and permanently delete everything in its private data folder, including any databases, credentials and other internal state it kept there. Create a [backup]({backup_url}) first if you might need that data later.\n\nAlternatively, you can check [Home Assistant help]({help_url}) and the [community forum]({community_url}) for alternatives to migrate to."
}
}
},
Expand Down
2 changes: 1 addition & 1 deletion homeassistant/components/jewish_calendar/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,6 @@
"documentation": "https://www.home-assistant.io/integrations/jewish_calendar",
"iot_class": "calculated",
"loggers": ["hdate"],
"requirements": ["hdate[astral]==1.2.1"],
"requirements": ["hdate[astral]==1.2.2"],
"single_config_entry": true
}
13 changes: 6 additions & 7 deletions homeassistant/components/melcloud_home/sensor.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,11 +45,6 @@
)


def _has_energy_meter(unit: ATAUnit | ATWUnit) -> bool:
"""Return whether a unit reports an energy consumption meter."""
return bool(unit.capabilities and unit.capabilities.has_energy_consumed_meter)


@dataclass(frozen=True, kw_only=True)
class MelCloudHomeSensorEntityDescription[_UnitT: ATAUnit | ATWUnit](
SensorEntityDescription
Expand Down Expand Up @@ -148,7 +143,9 @@ async def async_setup_entry(
(
ATAEnergySensor(coordinator, energy_coordinator, unit)
for unit in units
if _has_energy_meter(unit)
if bool(
unit.capabilities and unit.capabilities.has_energy_consumed_meter
)
),
),
lambda units: chain(
Expand All @@ -161,7 +158,9 @@ async def async_setup_entry(
(
ATWEnergySensor(coordinator, energy_coordinator, unit)
for unit in units
if _has_energy_meter(unit)
if bool(
unit.capabilities and unit.capabilities.has_energy_consumed_meter
)
),
),
)
Expand Down
2 changes: 0 additions & 2 deletions homeassistant/components/modbus/const.py
Original file line number Diff line number Diff line change
Expand Up @@ -148,11 +148,9 @@ class DataType(StrEnum):
SERVICE_WRITE_COIL = "write_coil"
SERVICE_WRITE_REGISTER = "write_register"
SERVICE_STOP = "stop"
SERVICE_RESTART = "restart"

# dispatcher signals
SIGNAL_STOP_ENTITY = "modbus.stop"
SIGNAL_START_ENTITY = "modbus.start"

# integration names
DEFAULT_HUB = "modbus_hub"
Expand Down
3 changes: 0 additions & 3 deletions homeassistant/components/modbus/icons.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,6 @@
"reload": {
"service": "mdi:reload"
},
"restart": {
"service": "mdi:restart"
},
"stop": {
"service": "mdi:stop"
},
Expand Down
7 changes: 0 additions & 7 deletions homeassistant/components/modbus/modbus.py
Original file line number Diff line number Diff line change
Expand Up @@ -349,13 +349,6 @@ async def async_setup(self) -> bool:
)
return True

async def async_restart(self) -> None:
"""Reconnect client."""
if self._client:
await self.async_close()

await self.async_setup()

async def async_close(self) -> None:
"""Disconnect client."""
self.event_connected.set()
Expand Down
7 changes: 0 additions & 7 deletions homeassistant/components/modbus/services.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -54,10 +54,3 @@ stop:
default: "modbus_hub"
selector:
text:
restart:
fields:
hub:
example: "hub1"
default: "modbus_hub"
selector:
text:
10 changes: 0 additions & 10 deletions homeassistant/components/modbus/strings.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,16 +26,6 @@
"description": "Reloads all Modbus entities.",
"name": "[%key:common::action::reload%]"
},
"restart": {
"description": "Restarts a Modbus hub (if running, stops then starts).",
"fields": {
"hub": {
"description": "[%key:component::modbus::services::write_coil::fields::hub::description%]",
"name": "[%key:component::modbus::services::write_coil::fields::hub::name%]"
}
},
"name": "[%key:common::action::restart%]"
},
"stop": {
"description": "Stops a Modbus hub.",
"fields": {
Expand Down
17 changes: 7 additions & 10 deletions homeassistant/components/recorder/statistics.py
Original file line number Diff line number Diff line change
Expand Up @@ -382,8 +382,7 @@ def _get_statistic_to_display_unit_converter(
statistic_unit: str | None,
state_unit: str | None,
requested_units: dict[str, str] | None,
allow_none: bool = True,
) -> Callable[[float | None], float | None] | Callable[[float], float] | None:
) -> Callable[[float | None], float | None] | None:
"""Prepare a converter from the statistics unit to display unit."""
if (converter := _get_unit_converter(unit_class, statistic_unit)) is None:
return None
Expand All @@ -402,11 +401,9 @@ def _get_statistic_to_display_unit_converter(
if display_unit == statistic_unit:
return None

if allow_none:
return converter.converter_factory_allow_none(
from_unit=statistic_unit, to_unit=display_unit
)
return converter.converter_factory(from_unit=statistic_unit, to_unit=display_unit)
return converter.converter_factory_allow_none(
from_unit=statistic_unit, to_unit=display_unit
)


def _get_display_to_statistic_unit_converter_func(
Expand Down Expand Up @@ -2566,7 +2563,7 @@ def _build_sum_converted_stats(
table_duration_seconds: float,
start_ts_idx: int,
sum_idx: int,
convert: Callable[[float | None], float | None] | Callable[[float], float],
convert: Callable[[float | None], float | None],
) -> list[StatisticsRow]:
"""Build a list of sum statistics."""
return [
Expand Down Expand Up @@ -2618,7 +2615,7 @@ def _build_converted_stats(
table_duration_seconds: float,
start_ts_idx: int,
row_mapping: tuple[tuple[str, int], ...],
convert: Callable[[float | None], float | None] | Callable[[float], float],
convert: Callable[[float | None], float | None],
) -> list[StatisticsRow]:
"""Build a list of statistics with unit conversion."""
return [
Expand Down Expand Up @@ -2694,7 +2691,7 @@ def _sorted_statistics_to_dict(
EntityStateAttribute.UNIT_OF_MEASUREMENT
)
convert = _get_statistic_to_display_unit_converter(
unit_class, unit, state_unit, units, allow_none=False
unit_class, unit, state_unit, units
)
else:
convert = None
Expand Down
12 changes: 9 additions & 3 deletions homeassistant/components/sensor/recorder.py
Original file line number Diff line number Diff line change
Expand Up @@ -358,7 +358,7 @@ def _normalize_states(
return unit_class, state_unit, fstates

valid_fstates: list[tuple[float, State]] = []
convert: Callable[[float], float] | None = None
convert: Callable[[float | None], float | None] | None = None
last_unit: str | UndefinedType | None = UNDEFINED
valid_units = converter.VALID_UNITS

Expand Down Expand Up @@ -391,11 +391,17 @@ def _normalize_states(
if state_unit == statistics_unit:
convert = None
else:
convert = converter.converter_factory(state_unit, statistics_unit)
convert = converter.converter_factory_allow_none(
state_unit, statistics_unit
)
last_unit = state_unit

if convert is not None:
fstate = convert(fstate)
if (converted_fstate := convert(fstate)) is None:
# Exclude states which can't be converted, e.g. converting 0
# between kWh/100km and km/kWh would divide by zero
continue
fstate = converted_fstate

valid_fstates.append((fstate, state))

Expand Down
4 changes: 2 additions & 2 deletions homeassistant/components/shopping_list/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
_get_shopping_data,
)
from .const import DOMAIN
from .services import async_register_services
from .services import async_setup_services

PLATFORMS = [Platform.TODO]

Expand All @@ -33,7 +33,7 @@

async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool:
"""Initialize the shopping list."""
async_register_services(hass)
async_setup_services(hass)

if DOMAIN not in config:
return True
Expand Down
2 changes: 1 addition & 1 deletion homeassistant/components/shopping_list/services.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@


@callback
def async_register_services(hass: HomeAssistant) -> None:
def async_setup_services(hass: HomeAssistant) -> None:
"""Register shopping list services."""

async def add_item_service(call: ServiceCall) -> None:
Expand Down
Loading
Loading