mirror of
https://github.com/home-assistant/core.git
synced 2025-07-22 20:57:21 +00:00
Move BMW Target SoC to number platform (#91081)
Co-authored-by: Franck Nijhof <frenck@frenck.nl> Co-authored-by: rikroe <rikroe@users.noreply.github.com>
This commit is contained in:
parent
acc4b001cd
commit
1028841690
@ -41,6 +41,7 @@ PLATFORMS = [
|
|||||||
Platform.DEVICE_TRACKER,
|
Platform.DEVICE_TRACKER,
|
||||||
Platform.LOCK,
|
Platform.LOCK,
|
||||||
Platform.NOTIFY,
|
Platform.NOTIFY,
|
||||||
|
Platform.NUMBER,
|
||||||
Platform.SELECT,
|
Platform.SELECT,
|
||||||
Platform.SENSOR,
|
Platform.SENSOR,
|
||||||
]
|
]
|
||||||
|
@ -6,5 +6,5 @@
|
|||||||
"documentation": "https://www.home-assistant.io/integrations/bmw_connected_drive",
|
"documentation": "https://www.home-assistant.io/integrations/bmw_connected_drive",
|
||||||
"iot_class": "cloud_polling",
|
"iot_class": "cloud_polling",
|
||||||
"loggers": ["bimmer_connected"],
|
"loggers": ["bimmer_connected"],
|
||||||
"requirements": ["bimmer_connected==0.13.0"]
|
"requirements": ["bimmer_connected==0.13.2"]
|
||||||
}
|
}
|
||||||
|
120
homeassistant/components/bmw_connected_drive/number.py
Normal file
120
homeassistant/components/bmw_connected_drive/number.py
Normal file
@ -0,0 +1,120 @@
|
|||||||
|
"""Number platform for BMW."""
|
||||||
|
|
||||||
|
from collections.abc import Callable, Coroutine
|
||||||
|
from dataclasses import dataclass
|
||||||
|
import logging
|
||||||
|
from typing import Any
|
||||||
|
|
||||||
|
from bimmer_connected.models import MyBMWAPIError
|
||||||
|
from bimmer_connected.vehicle import MyBMWVehicle
|
||||||
|
|
||||||
|
from homeassistant.components.number import (
|
||||||
|
NumberDeviceClass,
|
||||||
|
NumberEntity,
|
||||||
|
NumberEntityDescription,
|
||||||
|
NumberMode,
|
||||||
|
)
|
||||||
|
from homeassistant.config_entries import ConfigEntry
|
||||||
|
from homeassistant.core import HomeAssistant
|
||||||
|
from homeassistant.exceptions import HomeAssistantError
|
||||||
|
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||||
|
|
||||||
|
from . import BMWBaseEntity
|
||||||
|
from .const import DOMAIN
|
||||||
|
from .coordinator import BMWDataUpdateCoordinator
|
||||||
|
|
||||||
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class BMWRequiredKeysMixin:
|
||||||
|
"""Mixin for required keys."""
|
||||||
|
|
||||||
|
value_fn: Callable[[MyBMWVehicle], float | int | None]
|
||||||
|
remote_service: Callable[[MyBMWVehicle, float | int], Coroutine[Any, Any, Any]]
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class BMWNumberEntityDescription(NumberEntityDescription, BMWRequiredKeysMixin):
|
||||||
|
"""Describes BMW number entity."""
|
||||||
|
|
||||||
|
is_available: Callable[[MyBMWVehicle], bool] = lambda _: False
|
||||||
|
dynamic_options: Callable[[MyBMWVehicle], list[str]] | None = None
|
||||||
|
mode: NumberMode = NumberMode.AUTO
|
||||||
|
|
||||||
|
|
||||||
|
NUMBER_TYPES: list[BMWNumberEntityDescription] = [
|
||||||
|
BMWNumberEntityDescription(
|
||||||
|
key="target_soc",
|
||||||
|
name="Target SoC",
|
||||||
|
device_class=NumberDeviceClass.BATTERY,
|
||||||
|
is_available=lambda v: v.is_remote_set_target_soc_enabled,
|
||||||
|
native_max_value=100.0,
|
||||||
|
native_min_value=20.0,
|
||||||
|
native_step=5.0,
|
||||||
|
mode=NumberMode.SLIDER,
|
||||||
|
value_fn=lambda v: v.fuel_and_battery.charging_target,
|
||||||
|
remote_service=lambda v, o: v.remote_services.trigger_charging_settings_update(
|
||||||
|
target_soc=int(o)
|
||||||
|
),
|
||||||
|
icon="mdi:battery-charging-medium",
|
||||||
|
),
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
async def async_setup_entry(
|
||||||
|
hass: HomeAssistant,
|
||||||
|
config_entry: ConfigEntry,
|
||||||
|
async_add_entities: AddEntitiesCallback,
|
||||||
|
) -> None:
|
||||||
|
"""Set up the MyBMW number from config entry."""
|
||||||
|
coordinator: BMWDataUpdateCoordinator = hass.data[DOMAIN][config_entry.entry_id]
|
||||||
|
|
||||||
|
entities: list[BMWNumber] = []
|
||||||
|
|
||||||
|
for vehicle in coordinator.account.vehicles:
|
||||||
|
if not coordinator.read_only:
|
||||||
|
entities.extend(
|
||||||
|
[
|
||||||
|
BMWNumber(coordinator, vehicle, description)
|
||||||
|
for description in NUMBER_TYPES
|
||||||
|
if description.is_available(vehicle)
|
||||||
|
]
|
||||||
|
)
|
||||||
|
async_add_entities(entities)
|
||||||
|
|
||||||
|
|
||||||
|
class BMWNumber(BMWBaseEntity, NumberEntity):
|
||||||
|
"""Representation of BMW Number entity."""
|
||||||
|
|
||||||
|
entity_description: BMWNumberEntityDescription
|
||||||
|
|
||||||
|
def __init__(
|
||||||
|
self,
|
||||||
|
coordinator: BMWDataUpdateCoordinator,
|
||||||
|
vehicle: MyBMWVehicle,
|
||||||
|
description: BMWNumberEntityDescription,
|
||||||
|
) -> None:
|
||||||
|
"""Initialize an BMW Number."""
|
||||||
|
super().__init__(coordinator, vehicle)
|
||||||
|
self.entity_description = description
|
||||||
|
self._attr_unique_id = f"{vehicle.vin}-{description.key}"
|
||||||
|
self._attr_mode = description.mode
|
||||||
|
|
||||||
|
@property
|
||||||
|
def native_value(self) -> float | None:
|
||||||
|
"""Return the entity value to represent the entity state."""
|
||||||
|
return self.entity_description.value_fn(self.vehicle)
|
||||||
|
|
||||||
|
async def async_set_native_value(self, value: float) -> None:
|
||||||
|
"""Update to the vehicle."""
|
||||||
|
_LOGGER.debug(
|
||||||
|
"Executing '%s' on vehicle '%s' to value '%s'",
|
||||||
|
self.entity_description.key,
|
||||||
|
self.vehicle.vin,
|
||||||
|
value,
|
||||||
|
)
|
||||||
|
try:
|
||||||
|
await self.entity_description.remote_service(self.vehicle, value)
|
||||||
|
except MyBMWAPIError as ex:
|
||||||
|
raise HomeAssistantError(ex) from ex
|
@ -9,7 +9,7 @@ from bimmer_connected.vehicle.charging_profile import ChargingMode
|
|||||||
|
|
||||||
from homeassistant.components.select import SelectEntity, SelectEntityDescription
|
from homeassistant.components.select import SelectEntity, SelectEntityDescription
|
||||||
from homeassistant.config_entries import ConfigEntry
|
from homeassistant.config_entries import ConfigEntry
|
||||||
from homeassistant.const import PERCENTAGE, UnitOfElectricCurrent
|
from homeassistant.const import UnitOfElectricCurrent
|
||||||
from homeassistant.core import HomeAssistant, callback
|
from homeassistant.core import HomeAssistant, callback
|
||||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||||
|
|
||||||
@ -37,19 +37,6 @@ class BMWSelectEntityDescription(SelectEntityDescription, BMWRequiredKeysMixin):
|
|||||||
|
|
||||||
|
|
||||||
SELECT_TYPES: dict[str, BMWSelectEntityDescription] = {
|
SELECT_TYPES: dict[str, BMWSelectEntityDescription] = {
|
||||||
# --- Generic ---
|
|
||||||
"target_soc": BMWSelectEntityDescription(
|
|
||||||
key="target_soc",
|
|
||||||
name="Target SoC",
|
|
||||||
is_available=lambda v: v.is_remote_set_target_soc_enabled,
|
|
||||||
options=[str(i * 5 + 20) for i in range(17)],
|
|
||||||
current_option=lambda v: str(v.fuel_and_battery.charging_target),
|
|
||||||
remote_service=lambda v, o: v.remote_services.trigger_charging_settings_update(
|
|
||||||
target_soc=int(o)
|
|
||||||
),
|
|
||||||
icon="mdi:battery-charging-medium",
|
|
||||||
unit_of_measurement=PERCENTAGE,
|
|
||||||
),
|
|
||||||
"ac_limit": BMWSelectEntityDescription(
|
"ac_limit": BMWSelectEntityDescription(
|
||||||
key="ac_limit",
|
key="ac_limit",
|
||||||
name="AC Charging Limit",
|
name="AC Charging Limit",
|
||||||
|
@ -431,7 +431,7 @@ beautifulsoup4==4.11.1
|
|||||||
bellows==0.35.2
|
bellows==0.35.2
|
||||||
|
|
||||||
# homeassistant.components.bmw_connected_drive
|
# homeassistant.components.bmw_connected_drive
|
||||||
bimmer_connected==0.13.0
|
bimmer_connected==0.13.2
|
||||||
|
|
||||||
# homeassistant.components.bizkaibus
|
# homeassistant.components.bizkaibus
|
||||||
bizkaibus==0.1.1
|
bizkaibus==0.1.1
|
||||||
|
@ -364,7 +364,7 @@ beautifulsoup4==4.11.1
|
|||||||
bellows==0.35.2
|
bellows==0.35.2
|
||||||
|
|
||||||
# homeassistant.components.bmw_connected_drive
|
# homeassistant.components.bmw_connected_drive
|
||||||
bimmer_connected==0.13.0
|
bimmer_connected==0.13.2
|
||||||
|
|
||||||
# homeassistant.components.bluetooth
|
# homeassistant.components.bluetooth
|
||||||
bleak-retry-connector==3.0.2
|
bleak-retry-connector==3.0.2
|
||||||
|
@ -139,6 +139,22 @@
|
|||||||
}),
|
}),
|
||||||
]),
|
]),
|
||||||
}),
|
}),
|
||||||
|
'climate': dict({
|
||||||
|
'account_timezone': dict({
|
||||||
|
'_dst_offset': '0:00:00',
|
||||||
|
'_dst_saved': '0:00:00',
|
||||||
|
'_hasdst': False,
|
||||||
|
'_std_offset': '0:00:00',
|
||||||
|
'_tznames': list([
|
||||||
|
'UTC',
|
||||||
|
'UTC',
|
||||||
|
]),
|
||||||
|
}),
|
||||||
|
'activity': 'STANDBY',
|
||||||
|
'activity_end_time': None,
|
||||||
|
'activity_end_time_no_tz': None,
|
||||||
|
'is_climate_on': False,
|
||||||
|
}),
|
||||||
'condition_based_services': dict({
|
'condition_based_services': dict({
|
||||||
'is_service_required': False,
|
'is_service_required': False,
|
||||||
'messages': list([
|
'messages': list([
|
||||||
@ -808,6 +824,32 @@
|
|||||||
]),
|
]),
|
||||||
'name': 'i4 eDrive40',
|
'name': 'i4 eDrive40',
|
||||||
'timestamp': '2023-01-04T14:57:06+00:00',
|
'timestamp': '2023-01-04T14:57:06+00:00',
|
||||||
|
'tires': dict({
|
||||||
|
'front_left': dict({
|
||||||
|
'current_pressure': 241,
|
||||||
|
'manufacturing_week': '2021-10-04T00:00:00',
|
||||||
|
'season': 2,
|
||||||
|
'target_pressure': 269,
|
||||||
|
}),
|
||||||
|
'front_right': dict({
|
||||||
|
'current_pressure': 255,
|
||||||
|
'manufacturing_week': '2019-06-10T00:00:00',
|
||||||
|
'season': 2,
|
||||||
|
'target_pressure': 269,
|
||||||
|
}),
|
||||||
|
'rear_left': dict({
|
||||||
|
'current_pressure': 324,
|
||||||
|
'manufacturing_week': '2019-03-18T00:00:00',
|
||||||
|
'season': 2,
|
||||||
|
'target_pressure': 303,
|
||||||
|
}),
|
||||||
|
'rear_right': dict({
|
||||||
|
'current_pressure': 331,
|
||||||
|
'manufacturing_week': '2019-03-18T00:00:00',
|
||||||
|
'season': 2,
|
||||||
|
'target_pressure': 303,
|
||||||
|
}),
|
||||||
|
}),
|
||||||
'vehicle_location': dict({
|
'vehicle_location': dict({
|
||||||
'account_region': 'row',
|
'account_region': 'row',
|
||||||
'heading': '**REDACTED**',
|
'heading': '**REDACTED**',
|
||||||
@ -969,6 +1011,22 @@
|
|||||||
'messages': list([
|
'messages': list([
|
||||||
]),
|
]),
|
||||||
}),
|
}),
|
||||||
|
'climate': dict({
|
||||||
|
'account_timezone': dict({
|
||||||
|
'_dst_offset': '0:00:00',
|
||||||
|
'_dst_saved': '0:00:00',
|
||||||
|
'_hasdst': False,
|
||||||
|
'_std_offset': '0:00:00',
|
||||||
|
'_tznames': list([
|
||||||
|
'UTC',
|
||||||
|
'UTC',
|
||||||
|
]),
|
||||||
|
}),
|
||||||
|
'activity': 'UNKNOWN',
|
||||||
|
'activity_end_time': None,
|
||||||
|
'activity_end_time_no_tz': None,
|
||||||
|
'is_climate_on': False,
|
||||||
|
}),
|
||||||
'condition_based_services': dict({
|
'condition_based_services': dict({
|
||||||
'is_service_required': False,
|
'is_service_required': False,
|
||||||
'messages': list([
|
'messages': list([
|
||||||
@ -1466,6 +1524,7 @@
|
|||||||
]),
|
]),
|
||||||
'name': 'i3 (+ REX)',
|
'name': 'i3 (+ REX)',
|
||||||
'timestamp': '2022-07-10T09:25:53+00:00',
|
'timestamp': '2022-07-10T09:25:53+00:00',
|
||||||
|
'tires': None,
|
||||||
'vehicle_location': dict({
|
'vehicle_location': dict({
|
||||||
'account_region': 'row',
|
'account_region': 'row',
|
||||||
'heading': None,
|
'heading': None,
|
||||||
@ -2456,6 +2515,22 @@
|
|||||||
'messages': list([
|
'messages': list([
|
||||||
]),
|
]),
|
||||||
}),
|
}),
|
||||||
|
'climate': dict({
|
||||||
|
'account_timezone': dict({
|
||||||
|
'_dst_offset': '0:00:00',
|
||||||
|
'_dst_saved': '0:00:00',
|
||||||
|
'_hasdst': False,
|
||||||
|
'_std_offset': '0:00:00',
|
||||||
|
'_tznames': list([
|
||||||
|
'UTC',
|
||||||
|
'UTC',
|
||||||
|
]),
|
||||||
|
}),
|
||||||
|
'activity': 'UNKNOWN',
|
||||||
|
'activity_end_time': None,
|
||||||
|
'activity_end_time_no_tz': None,
|
||||||
|
'is_climate_on': False,
|
||||||
|
}),
|
||||||
'condition_based_services': dict({
|
'condition_based_services': dict({
|
||||||
'is_service_required': False,
|
'is_service_required': False,
|
||||||
'messages': list([
|
'messages': list([
|
||||||
@ -2953,6 +3028,7 @@
|
|||||||
]),
|
]),
|
||||||
'name': 'i3 (+ REX)',
|
'name': 'i3 (+ REX)',
|
||||||
'timestamp': '2022-07-10T09:25:53+00:00',
|
'timestamp': '2022-07-10T09:25:53+00:00',
|
||||||
|
'tires': None,
|
||||||
'vehicle_location': dict({
|
'vehicle_location': dict({
|
||||||
'account_region': 'row',
|
'account_region': 'row',
|
||||||
'heading': None,
|
'heading': None,
|
||||||
|
@ -0,0 +1,22 @@
|
|||||||
|
# serializer version: 1
|
||||||
|
# name: test_entity_state_attrs
|
||||||
|
list([
|
||||||
|
StateSnapshot({
|
||||||
|
'attributes': ReadOnlyDict({
|
||||||
|
'attribution': 'Data provided by MyBMW',
|
||||||
|
'device_class': 'battery',
|
||||||
|
'friendly_name': 'i4 eDrive40 Target SoC',
|
||||||
|
'icon': 'mdi:battery-charging-medium',
|
||||||
|
'max': 100.0,
|
||||||
|
'min': 20.0,
|
||||||
|
'mode': <NumberMode.SLIDER: 'slider'>,
|
||||||
|
'step': 5.0,
|
||||||
|
}),
|
||||||
|
'context': <ANY>,
|
||||||
|
'entity_id': 'number.i4_edrive40_target_soc',
|
||||||
|
'last_changed': <ANY>,
|
||||||
|
'last_updated': <ANY>,
|
||||||
|
'state': '80',
|
||||||
|
}),
|
||||||
|
])
|
||||||
|
# ---
|
@ -1,38 +1,6 @@
|
|||||||
# serializer version: 1
|
# serializer version: 1
|
||||||
# name: test_entity_state_attrs
|
# name: test_entity_state_attrs
|
||||||
list([
|
list([
|
||||||
StateSnapshot({
|
|
||||||
'attributes': ReadOnlyDict({
|
|
||||||
'attribution': 'Data provided by MyBMW',
|
|
||||||
'friendly_name': 'i4 eDrive40 Target SoC',
|
|
||||||
'icon': 'mdi:battery-charging-medium',
|
|
||||||
'options': list([
|
|
||||||
'20',
|
|
||||||
'25',
|
|
||||||
'30',
|
|
||||||
'35',
|
|
||||||
'40',
|
|
||||||
'45',
|
|
||||||
'50',
|
|
||||||
'55',
|
|
||||||
'60',
|
|
||||||
'65',
|
|
||||||
'70',
|
|
||||||
'75',
|
|
||||||
'80',
|
|
||||||
'85',
|
|
||||||
'90',
|
|
||||||
'95',
|
|
||||||
'100',
|
|
||||||
]),
|
|
||||||
'unit_of_measurement': '%',
|
|
||||||
}),
|
|
||||||
'context': <ANY>,
|
|
||||||
'entity_id': 'select.i4_edrive40_target_soc',
|
|
||||||
'last_changed': <ANY>,
|
|
||||||
'last_updated': <ANY>,
|
|
||||||
'state': '80',
|
|
||||||
}),
|
|
||||||
StateSnapshot({
|
StateSnapshot({
|
||||||
'attributes': ReadOnlyDict({
|
'attributes': ReadOnlyDict({
|
||||||
'attribution': 'Data provided by MyBMW',
|
'attribution': 'Data provided by MyBMW',
|
||||||
|
123
tests/components/bmw_connected_drive/test_number.py
Normal file
123
tests/components/bmw_connected_drive/test_number.py
Normal file
@ -0,0 +1,123 @@
|
|||||||
|
"""Test BMW numbers."""
|
||||||
|
from unittest.mock import AsyncMock
|
||||||
|
|
||||||
|
from bimmer_connected.models import MyBMWAPIError, MyBMWRemoteServiceError
|
||||||
|
from bimmer_connected.vehicle.remote_services import RemoteServices
|
||||||
|
import pytest
|
||||||
|
import respx
|
||||||
|
from syrupy.assertion import SnapshotAssertion
|
||||||
|
|
||||||
|
from homeassistant.core import HomeAssistant
|
||||||
|
from homeassistant.exceptions import HomeAssistantError
|
||||||
|
|
||||||
|
from . import setup_mocked_integration
|
||||||
|
|
||||||
|
|
||||||
|
async def test_entity_state_attrs(
|
||||||
|
hass: HomeAssistant,
|
||||||
|
bmw_fixture: respx.Router,
|
||||||
|
snapshot: SnapshotAssertion,
|
||||||
|
) -> None:
|
||||||
|
"""Test number options and values.."""
|
||||||
|
|
||||||
|
# Setup component
|
||||||
|
assert await setup_mocked_integration(hass)
|
||||||
|
|
||||||
|
# Get all number entities
|
||||||
|
assert hass.states.async_all("number") == snapshot
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize(
|
||||||
|
("entity_id", "value"),
|
||||||
|
[
|
||||||
|
("number.i4_edrive40_target_soc", "80"),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
async def test_update_triggers_success(
|
||||||
|
hass: HomeAssistant,
|
||||||
|
entity_id: str,
|
||||||
|
value: str,
|
||||||
|
bmw_fixture: respx.Router,
|
||||||
|
) -> None:
|
||||||
|
"""Test allowed values for number inputs."""
|
||||||
|
|
||||||
|
# Setup component
|
||||||
|
assert await setup_mocked_integration(hass)
|
||||||
|
|
||||||
|
# Test
|
||||||
|
await hass.services.async_call(
|
||||||
|
"number",
|
||||||
|
"set_value",
|
||||||
|
service_data={"value": value},
|
||||||
|
blocking=True,
|
||||||
|
target={"entity_id": entity_id},
|
||||||
|
)
|
||||||
|
assert RemoteServices.trigger_remote_service.call_count == 1
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize(
|
||||||
|
("entity_id", "value"),
|
||||||
|
[
|
||||||
|
("number.i4_edrive40_target_soc", "81"),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
async def test_update_triggers_fail(
|
||||||
|
hass: HomeAssistant,
|
||||||
|
entity_id: str,
|
||||||
|
value: str,
|
||||||
|
bmw_fixture: respx.Router,
|
||||||
|
) -> None:
|
||||||
|
"""Test not allowed values for number inputs."""
|
||||||
|
|
||||||
|
# Setup component
|
||||||
|
assert await setup_mocked_integration(hass)
|
||||||
|
|
||||||
|
# Test
|
||||||
|
with pytest.raises(ValueError):
|
||||||
|
await hass.services.async_call(
|
||||||
|
"number",
|
||||||
|
"set_value",
|
||||||
|
service_data={"value": value},
|
||||||
|
blocking=True,
|
||||||
|
target={"entity_id": entity_id},
|
||||||
|
)
|
||||||
|
assert RemoteServices.trigger_remote_service.call_count == 0
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize(
|
||||||
|
("raised", "expected"),
|
||||||
|
[
|
||||||
|
(MyBMWRemoteServiceError, HomeAssistantError),
|
||||||
|
(MyBMWAPIError, HomeAssistantError),
|
||||||
|
(ValueError, ValueError),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
async def test_update_triggers_exceptions(
|
||||||
|
hass: HomeAssistant,
|
||||||
|
raised: Exception,
|
||||||
|
expected: Exception,
|
||||||
|
bmw_fixture: respx.Router,
|
||||||
|
monkeypatch: pytest.MonkeyPatch,
|
||||||
|
) -> None:
|
||||||
|
"""Test not allowed values for number inputs."""
|
||||||
|
|
||||||
|
# Setup component
|
||||||
|
assert await setup_mocked_integration(hass)
|
||||||
|
|
||||||
|
# Setup exception
|
||||||
|
monkeypatch.setattr(
|
||||||
|
RemoteServices,
|
||||||
|
"trigger_remote_service",
|
||||||
|
AsyncMock(side_effect=raised),
|
||||||
|
)
|
||||||
|
|
||||||
|
# Test
|
||||||
|
with pytest.raises(expected):
|
||||||
|
await hass.services.async_call(
|
||||||
|
"number",
|
||||||
|
"set_value",
|
||||||
|
service_data={"value": "80"},
|
||||||
|
blocking=True,
|
||||||
|
target={"entity_id": "number.i4_edrive40_target_soc"},
|
||||||
|
)
|
||||||
|
assert RemoteServices.trigger_remote_service.call_count == 1
|
@ -28,7 +28,6 @@ async def test_entity_state_attrs(
|
|||||||
[
|
[
|
||||||
("select.i3_rex_charging_mode", "IMMEDIATE_CHARGING"),
|
("select.i3_rex_charging_mode", "IMMEDIATE_CHARGING"),
|
||||||
("select.i4_edrive40_ac_charging_limit", "16"),
|
("select.i4_edrive40_ac_charging_limit", "16"),
|
||||||
("select.i4_edrive40_target_soc", "80"),
|
|
||||||
("select.i4_edrive40_charging_mode", "DELAYED_CHARGING"),
|
("select.i4_edrive40_charging_mode", "DELAYED_CHARGING"),
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
@ -58,7 +57,6 @@ async def test_update_triggers_success(
|
|||||||
("entity_id", "value"),
|
("entity_id", "value"),
|
||||||
[
|
[
|
||||||
("select.i4_edrive40_ac_charging_limit", "17"),
|
("select.i4_edrive40_ac_charging_limit", "17"),
|
||||||
("select.i4_edrive40_target_soc", "81"),
|
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
async def test_update_triggers_fail(
|
async def test_update_triggers_fail(
|
||||||
|
Loading…
x
Reference in New Issue
Block a user