Skip to content
2 changes: 1 addition & 1 deletion homeassistant/components/alexa_devices/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,5 @@
"iot_class": "cloud_polling",
"loggers": ["aioamazondevices"],
"quality_scale": "platinum",
"requirements": ["aioamazondevices==6.2.7"]
"requirements": ["aioamazondevices==6.2.8"]
}
27 changes: 20 additions & 7 deletions homeassistant/components/google_travel_time/sensor.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
from homeassistant.components.sensor import (
SensorDeviceClass,
SensorEntity,
SensorEntityDescription,
SensorStateClass,
)
from homeassistant.config_entries import ConfigEntry
Expand Down Expand Up @@ -91,6 +92,16 @@ def convert_time(time_str: str) -> timestamp_pb2.Timestamp | None:
return timestamp


SENSOR_DESCRIPTIONS = [
SensorEntityDescription(
key="duration",
state_class=SensorStateClass.MEASUREMENT,
device_class=SensorDeviceClass.DURATION,
native_unit_of_measurement=UnitOfTime.MINUTES,
)
]


async def async_setup_entry(
hass: HomeAssistant,
config_entry: ConfigEntry,
Expand All @@ -105,20 +116,20 @@ async def async_setup_entry(
client_options = ClientOptions(api_key=api_key)
client = RoutesAsyncClient(client_options=client_options)

sensor = GoogleTravelTimeSensor(
config_entry, name, api_key, origin, destination, client
)
sensors = [
GoogleTravelTimeSensor(
config_entry, name, api_key, origin, destination, client, sensor_description
)
for sensor_description in SENSOR_DESCRIPTIONS
]

async_add_entities([sensor], False)
async_add_entities(sensors, False)


class GoogleTravelTimeSensor(SensorEntity):
"""Representation of a Google travel time sensor."""

_attr_attribution = ATTRIBUTION
_attr_native_unit_of_measurement = UnitOfTime.MINUTES
_attr_device_class = SensorDeviceClass.DURATION
_attr_state_class = SensorStateClass.MEASUREMENT

def __init__(
self,
Expand All @@ -128,8 +139,10 @@ def __init__(
origin: str,
destination: str,
client: RoutesAsyncClient,
sensor_description: SensorEntityDescription,
) -> None:
"""Initialize the sensor."""
self.entity_description = sensor_description
self._attr_name = name
self._attr_unique_id = config_entry.entry_id
self._attr_device_info = DeviceInfo(
Expand Down
1 change: 0 additions & 1 deletion homeassistant/components/hassio/switch.py
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,6 @@ async def async_turn_on(self, **kwargs: Any) -> None:
try:
await supervisor_client.addons.start_addon(self._addon_slug)
except SupervisorError as err:
_LOGGER.error("Failed to start addon %s: %s", self._addon_slug, err)
raise HomeAssistantError(err) from err

await self.coordinator.force_addon_info_data_refresh(self._addon_slug)
Expand Down
4 changes: 2 additions & 2 deletions homeassistant/components/local_todo/todo.py
Original file line number Diff line number Diff line change
Expand Up @@ -196,11 +196,11 @@ async def async_move_todo_item(
item_idx: dict[str, int] = {itm.uid: idx for idx, itm in enumerate(todos)}
if uid not in item_idx:
raise HomeAssistantError(
"Item '{uid}' not found in todo list {self.entity_id}"
f"Item '{uid}' not found in todo list {self.entity_id}"
)
if previous_uid and previous_uid not in item_idx:
raise HomeAssistantError(
"Item '{previous_uid}' not found in todo list {self.entity_id}"
f"Item '{previous_uid}' not found in todo list {self.entity_id}"
)
dst_idx = item_idx[previous_uid] + 1 if previous_uid else 0
src_idx = item_idx[uid]
Expand Down
2 changes: 1 addition & 1 deletion homeassistant/components/nordpool/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,6 @@
"iot_class": "cloud_polling",
"loggers": ["pynordpool"],
"quality_scale": "platinum",
"requirements": ["pynordpool==0.3.0"],
"requirements": ["pynordpool==0.3.1"],
"single_config_entry": true
}
4 changes: 2 additions & 2 deletions homeassistant/components/roborock/config_flow.py
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ async def _request_code(self) -> dict:
assert self._client
errors: dict[str, str] = {}
try:
await self._client.request_code()
await self._client.request_code_v4()
except RoborockAccountDoesNotExist:
errors["base"] = "invalid_email"
except RoborockUrlException:
Expand Down Expand Up @@ -111,7 +111,7 @@ async def async_step_code(
code = user_input[CONF_ENTRY_CODE]
_LOGGER.debug("Logging into Roborock account using email provided code")
try:
user_data = await self._client.code_login(code)
user_data = await self._client.code_login_v4(code)
except RoborockInvalidCode:
errors["base"] = "invalid_code"
except RoborockException:
Expand Down
6 changes: 6 additions & 0 deletions homeassistant/components/roborock/icons.json
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,12 @@
"total_cleaning_time": {
"default": "mdi:history"
},
"cleaning_brush_time_left": {
"default": "mdi:brush"
},
"strainer_time_left": {
"default": "mdi:filter-variant"
},
"status": {
"default": "mdi:information-outline"
},
Expand Down
18 changes: 18 additions & 0 deletions homeassistant/components/roborock/sensor.py
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,24 @@ def _dock_error_value_fn(properties: DeviceProp) -> str | None:
entity_category=EntityCategory.DIAGNOSTIC,
protocol_listener=RoborockDataProtocol.FILTER_WORK_TIME,
),
RoborockSensorDescription(
native_unit_of_measurement=UnitOfTime.HOURS,
key="cleaning_brush_time_left",
device_class=SensorDeviceClass.DURATION,
translation_key="cleaning_brush_time_left",
value_fn=lambda data: data.consumable.cleaning_brush_time_left,
entity_category=EntityCategory.DIAGNOSTIC,
is_dock_entity=True,
),
RoborockSensorDescription(
native_unit_of_measurement=UnitOfTime.HOURS,
key="strainer_time_left",
device_class=SensorDeviceClass.DURATION,
translation_key="strainer_time_left",
value_fn=lambda data: data.consumable.strainer_time_left,
entity_category=EntityCategory.DIAGNOSTIC,
is_dock_entity=True,
),
RoborockSensorDescription(
native_unit_of_measurement=UnitOfTime.SECONDS,
key="sensor_time_left",
Expand Down
6 changes: 6 additions & 0 deletions homeassistant/components/roborock/strings.json
Original file line number Diff line number Diff line change
Expand Up @@ -220,6 +220,12 @@
"sensor_time_left": {
"name": "Sensor time left"
},
"cleaning_brush_time_left": {
"name": "Maintenance brush time left"
},
"strainer_time_left": {
"name": "Strainer time left"
},
"status": {
"name": "Status",
"state": {
Expand Down
7 changes: 1 addition & 6 deletions homeassistant/components/roborock/vacuum.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,6 @@
from roborock.code_mappings import RoborockStateCode
from roborock.roborock_message import RoborockDataProtocol
from roborock.roborock_typing import RoborockCommand
from vacuum_map_parser_base.config.color import ColorsPalette
from vacuum_map_parser_base.config.image_config import ImageConfig
from vacuum_map_parser_base.config.size import Sizes
from vacuum_map_parser_roborock.map_data_parser import RoborockMapDataParser
import voluptuous as vol

from homeassistant.components.vacuum import (
Expand Down Expand Up @@ -223,8 +219,7 @@ async def get_vacuum_current_position(self) -> ServiceResponse:
translation_domain=DOMAIN,
translation_key="map_failure",
)
parser = RoborockMapDataParser(ColorsPalette(), Sizes(), [], ImageConfig(), [])
parsed_map = parser.parse(map_data)
parsed_map = self.coordinator.map_parser.parse(map_data)
robot_position = parsed_map.vacuum_position

if robot_position is None:
Expand Down
4 changes: 2 additions & 2 deletions requirements_all.txt

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions requirements_test_all.txt

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

16 changes: 16 additions & 0 deletions tests/components/enphase_envoy/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,22 @@ def _load_json_2_meter_data(
mocked_data: EnvoyData, json_fixture: dict[str, Any]
) -> None:
"""Fill envoy meter data from fixture."""
if meters := json_fixture["data"].get("ctmeters"):
mocked_data.ctmeters = {}
[
mocked_data.ctmeters.update({meter: EnvoyMeterData(**meter_data)})
for meter, meter_data in meters.items()
]
if meters := json_fixture["data"].get("ctmeters_phases"):
mocked_data.ctmeters_phases = {}
for meter, meter_data in meters.items():
meter_phase_data: dict[str, EnvoyMeterData] = {}
[
meter_phase_data.update({phase: EnvoyMeterData(**phase_data)})
for phase, phase_data in meter_data.items()
]
mocked_data.ctmeters_phases.update({meter: meter_phase_data})

if item := json_fixture["data"].get("ctmeter_production"):
mocked_data.ctmeter_production = EnvoyMeterData(**item)
if item := json_fixture["data"].get("ctmeter_consumption"):
Expand Down
2 changes: 2 additions & 0 deletions tests/components/enphase_envoy/fixtures/envoy.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@
"system_consumption_phases": null,
"system_net_consumption_phases": null,
"system_production_phases": null,
"ctmeters": {},
"ctmeters_phases": {},
"ctmeter_production": null,
"ctmeter_consumption": null,
"ctmeter_storage": null,
Expand Down
33 changes: 33 additions & 0 deletions tests/components/enphase_envoy/fixtures/envoy_1p_metered.json
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,39 @@
"system_consumption_phases": null,
"system_net_consumption_phases": null,
"system_production_phases": null,
"ctmeters": {
"production": {
"eid": "100000010",
"timestamp": 1708006110,
"energy_delivered": 11234,
"energy_received": 12345,
"active_power": 100,
"power_factor": 0.11,
"voltage": 111,
"current": 0.2,
"frequency": 50.1,
"state": "enabled",
"measurement_type": "production",
"metering_status": "normal",
"status_flags": ["production-imbalance", "power-on-unused-phase"]
},
"net-consumption": {
"eid": "100000020",
"timestamp": 1708006120,
"energy_delivered": 21234,
"energy_received": 22345,
"active_power": 101,
"power_factor": 0.21,
"voltage": 112,
"current": 0.3,
"frequency": 50.2,
"state": "enabled",
"measurement_type": "net-consumption",
"metering_status": "normal",
"status_flags": []
}
},
"ctmeters_phases": {},
"ctmeter_production": {
"eid": "100000010",
"timestamp": 1708006110,
Expand Down
Loading
Loading