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/here_travel_time/coordinator.py
Original file line number Diff line number Diff line change
Expand Up @@ -133,8 +133,8 @@ async def _async_update_data(self) -> HERETravelTimeData:
def _parse_routing_response(self, response: dict[str, Any]) -> HERETravelTimeData:
"""Parse the routing response dict to a HERETravelTimeData."""
distance: float = 0.0
duration: float = 0.0
duration_in_traffic: float = 0.0
duration: int = 0
duration_in_traffic: int = 0

for section in response["routes"][0]["sections"]:
distance += DistanceConverter.convert(
Expand Down Expand Up @@ -167,8 +167,8 @@ def _parse_routing_response(self, response: dict[str, Any]) -> HERETravelTimeDat
destination_name = names[0]["value"]
return HERETravelTimeData(
attribution=None,
duration=round(duration / 60),
duration_in_traffic=round(duration_in_traffic / 60),
duration=duration,
duration_in_traffic=duration_in_traffic,
distance=distance,
origin=f"{mapped_origin_lat},{mapped_origin_lon}",
destination=f"{mapped_destination_lat},{mapped_destination_lon}",
Expand Down Expand Up @@ -271,13 +271,13 @@ def _parse_transit_response(self, response: dict[str, Any]) -> HERETravelTimeDat
UnitOfLength.METERS,
UnitOfLength.KILOMETERS,
)
duration: float = sum(
duration: int = sum(
section["travelSummary"]["duration"] for section in sections
)
return HERETravelTimeData(
attribution=attribution,
duration=round(duration / 60),
duration_in_traffic=round(duration / 60),
duration=duration,
duration_in_traffic=duration,
distance=distance,
origin=f"{mapped_origin_lat},{mapped_origin_lon}",
destination=f"{mapped_destination_lat},{mapped_destination_lon}",
Expand Down
6 changes: 4 additions & 2 deletions homeassistant/components/here_travel_time/sensor.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,15 +56,17 @@ def sensor_descriptions(travel_mode: str) -> tuple[SensorEntityDescription, ...]
key=ATTR_DURATION,
state_class=SensorStateClass.MEASUREMENT,
device_class=SensorDeviceClass.DURATION,
native_unit_of_measurement=UnitOfTime.MINUTES,
native_unit_of_measurement=UnitOfTime.SECONDS,
suggested_unit_of_measurement=UnitOfTime.MINUTES,
),
SensorEntityDescription(
translation_key="duration_in_traffic",
icon=ICONS.get(travel_mode, ICON_CAR),
key=ATTR_DURATION_IN_TRAFFIC,
state_class=SensorStateClass.MEASUREMENT,
device_class=SensorDeviceClass.DURATION,
native_unit_of_measurement=UnitOfTime.MINUTES,
native_unit_of_measurement=UnitOfTime.SECONDS,
suggested_unit_of_measurement=UnitOfTime.MINUTES,
),
SensorEntityDescription(
translation_key="distance",
Expand Down
71 changes: 71 additions & 0 deletions homeassistant/components/home_connect/quality_scale.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
rules:
# Bronze
action-setup: done
appropriate-polling:
status: done
comment: |
Full polling is performed at the configuration entry setup and
device polling is performed when a CONNECTED or a PAIRED event is received.
If many CONNECTED or PAIRED events are received for a device within a short time span,
the integration will stop polling for that device and will create a repair issue.
brands: done
common-modules: done
config-flow-test-coverage: done
config-flow: done
dependency-transparency: done
docs-actions: done
docs-high-level-description: done
docs-installation-instructions: done
docs-removal-instructions: done
entity-event-setup: done
entity-unique-id: done
has-entity-name: done
runtime-data: done
test-before-configure: done
test-before-setup: done
unique-config-entry: done

# Silver
action-exceptions: done
config-entry-unloading: done
docs-configuration-parameters: done
docs-installation-parameters: done
entity-unavailable: done
integration-owner: done
log-when-unavailable: done
parallel-updates: done
reauthentication-flow: done
test-coverage: done
# Gold
devices: done
diagnostics: done
discovery-update-info: done
discovery: done
docs-data-update: done
docs-examples: done
docs-known-limitations: done
docs-supported-devices: done
docs-supported-functions: done
docs-troubleshooting: done
docs-use-cases: done
dynamic-devices: done
entity-category: done
entity-device-class: done
entity-disabled-by-default:
status: done
comment: |
Event entities are disabled by default to prevent user confusion regarding
which events are supported by its appliance.
entity-translations: done
exception-translations: done
icon-translations: done
reconfiguration-flow:
status: exempt
comment: |
This integration doesn't have settings in its configuration flow.
repair-issues: done
stale-devices: done
# Platinum
async-dependency: done
inject-websession: done
strict-typing: done
2 changes: 1 addition & 1 deletion homeassistant/components/husqvarna_automower/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,5 @@
"iot_class": "cloud_push",
"loggers": ["aioautomower"],
"quality_scale": "silver",
"requirements": ["aioautomower==2025.5.1"]
"requirements": ["aioautomower==2025.6.0"]
}
55 changes: 55 additions & 0 deletions homeassistant/components/meater/diagnostics.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
"""Diagnostics support for the Meater integration."""

from __future__ import annotations

from typing import Any

from homeassistant.core import HomeAssistant

from . import MeaterConfigEntry


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

return {
identifier: {
"id": probe.id,
"internal_temperature": probe.internal_temperature,
"ambient_temperature": probe.ambient_temperature,
"time_updated": probe.time_updated.isoformat(),
"cook": (
{
"id": probe.cook.id,
"name": probe.cook.name,
"state": probe.cook.state,
"target_temperature": (
probe.cook.target_temperature
if hasattr(probe.cook, "target_temperature")
else None
),
"peak_temperature": (
probe.cook.peak_temperature
if hasattr(probe.cook, "peak_temperature")
else None
),
"time_remaining": (
probe.cook.time_remaining
if hasattr(probe.cook, "time_remaining")
else None
),
"time_elapsed": (
probe.cook.time_elapsed
if hasattr(probe.cook, "time_elapsed")
else None
),
}
if probe.cook
else None
),
}
for identifier, probe in coordinator.data.items()
}
19 changes: 16 additions & 3 deletions homeassistant/components/meater/sensor.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,18 @@
from .const import DOMAIN
from .coordinator import MeaterConfigEntry

COOK_STATES = {
"Not Started": "not_started",
"Configured": "configured",
"Started": "started",
"Ready For Resting": "ready_for_resting",
"Resting": "resting",
"Slightly Underdone": "slightly_underdone",
"Finished": "finished",
"Slightly Overdone": "slightly_overdone",
"OVERCOOK!": "overcooked",
}


@dataclass(frozen=True, kw_only=True)
class MeaterSensorEntityDescription(SensorEntityDescription):
Expand Down Expand Up @@ -80,13 +92,13 @@ def _remaining_time_to_timestamp(probe: MeaterProbe) -> datetime | None:
available=lambda probe: probe is not None and probe.cook is not None,
value=lambda probe: probe.cook.name if probe.cook else None,
),
# One of Not Started, Configured, Started, Ready For Resting, Resting,
# Slightly Underdone, Finished, Slightly Overdone, OVERCOOK!. Not translated.
MeaterSensorEntityDescription(
key="cook_state",
translation_key="cook_state",
available=lambda probe: probe is not None and probe.cook is not None,
value=lambda probe: probe.cook.state if probe.cook else None,
device_class=SensorDeviceClass.ENUM,
options=list(COOK_STATES.values()),
value=lambda probe: COOK_STATES.get(probe.cook.state) if probe.cook else None,
),
# Target temperature
MeaterSensorEntityDescription(
Expand Down Expand Up @@ -170,6 +182,7 @@ def async_update_data():

# Add a subscriber to the coordinator to discover new temperature probes
coordinator.async_add_listener(async_update_data)
async_update_data()


class MeaterProbeTemperature(SensorEntity, CoordinatorEntity[MeaterCoordinator]):
Expand Down
13 changes: 12 additions & 1 deletion homeassistant/components/meater/strings.json
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,18 @@
"name": "Cooking"
},
"cook_state": {
"name": "Cook state"
"name": "Cook state",
"state": {
"not_started": "Not started",
"configured": "Configured",
"started": "Started",
"ready_for_resting": "Ready for resting",
"resting": "Resting",
"slightly_underdone": "Slightly underdone",
"finished": "Finished",
"slightly_overdone": "Slightly overdone",
"overcooked": "Overcooked"
}
},
"cook_target_temp": {
"name": "Target temperature"
Expand Down
14 changes: 9 additions & 5 deletions homeassistant/components/minecraft_server/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import logging
from typing import Any

import dns.asyncresolver
import dns.rdata
import dns.rdataclass
import dns.rdatatype
Expand All @@ -22,20 +23,23 @@
_LOGGER = logging.getLogger(__name__)


def load_dnspython_rdata_classes() -> None:
"""Load dnspython rdata classes used by mcstatus."""
def prevent_dnspython_blocking_operations() -> None:
"""Prevent dnspython blocking operations by pre-loading required data."""

# Blocking import: https://github.com/rthalley/dnspython/issues/1083
for rdtype in dns.rdatatype.RdataType:
if not dns.rdatatype.is_metatype(rdtype) or rdtype == dns.rdatatype.OPT:
dns.rdata.get_rdata_class(dns.rdataclass.IN, rdtype) # type: ignore[no-untyped-call]

# Blocking open: https://github.com/rthalley/dnspython/issues/1200
dns.asyncresolver.get_default_resolver()


async def async_setup_entry(
hass: HomeAssistant, entry: MinecraftServerConfigEntry
) -> bool:
"""Set up Minecraft Server from a config entry."""

# Workaround to avoid blocking imports from dnspython (https://github.com/rthalley/dnspython/issues/1083)
await hass.async_add_executor_job(load_dnspython_rdata_classes)
await hass.async_add_executor_job(prevent_dnspython_blocking_operations)

# Create coordinator instance and store it.
coordinator = MinecraftServerCoordinator(hass, entry)
Expand Down
6 changes: 3 additions & 3 deletions homeassistant/components/nextdns/strings.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,15 @@
"api_key": "[%key:common::config_flow::data::api_key%]"
},
"data_description": {
"api_key": "API Key for your NextDNS account"
"api_key": "The API Key for your NextDNS account"
}
},
"profiles": {
"data": {
"profile": "Profile"
"profile_name": "Profile"
},
"data_description": {
"profile": "NextDNS configuration profile you want to integrate"
"profile_name": "The NextDNS configuration profile you want to integrate"
}
},
"reauth_confirm": {
Expand Down
5 changes: 4 additions & 1 deletion homeassistant/components/smartthings/strings.json
Original file line number Diff line number Diff line change
Expand Up @@ -605,7 +605,10 @@
"name": "Wrinkle prevent"
},
"ice_maker": {
"name": "Ice maker"
"name": "Ice cubes"
},
"ice_maker_2": {
"name": "Ice bites"
},
"sabbath_mode": {
"name": "Sabbath mode"
Expand Down
1 change: 1 addition & 0 deletions homeassistant/components/smartthings/switch.py
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@ class SmartThingsCommandSwitchEntityDescription(SmartThingsSwitchEntityDescripti
status_attribute=Attribute.SWITCH,
component_translation_key={
"icemaker": "ice_maker",
"icemaker-02": "ice_maker_2",
},
),
Capability.SAMSUNG_CE_SABBATH_MODE: SmartThingsSwitchEntityDescription(
Expand Down
2 changes: 1 addition & 1 deletion homeassistant/components/xiaomi_miio/manifest.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"domain": "xiaomi_miio",
"name": "Xiaomi Miio",
"name": "Xiaomi Home",
"codeowners": ["@rytilahti", "@syssi", "@starkillerOG"],
"config_flow": true,
"documentation": "https://www.home-assistant.io/integrations/xiaomi_miio",
Expand Down
Loading
Loading