1 """Support for Renault services."""
3 from __future__
import annotations
5 from collections.abc
import Mapping
6 from datetime
import datetime
8 from typing
import TYPE_CHECKING, Any
10 import voluptuous
as vol
17 from .const
import DOMAIN
18 from .renault_vehicle
import RenaultVehicleProxy
21 from .
import RenaultConfigEntry
23 LOGGER = logging.getLogger(__name__)
25 ATTR_SCHEDULES =
"schedules"
26 ATTR_TEMPERATURE =
"temperature"
27 ATTR_VEHICLE =
"vehicle"
30 SERVICE_VEHICLE_SCHEMA = vol.Schema(
32 vol.Required(ATTR_VEHICLE): cv.string,
35 SERVICE_AC_START_SCHEMA = SERVICE_VEHICLE_SCHEMA.extend(
37 vol.Required(ATTR_TEMPERATURE): cv.positive_float,
38 vol.Optional(ATTR_WHEN): cv.datetime,
41 SERVICE_CHARGE_SET_SCHEDULE_DAY_SCHEMA = vol.Schema(
43 vol.Required(
"startTime"): cv.string,
44 vol.Required(
"duration"): cv.positive_int,
47 SERVICE_CHARGE_SET_SCHEDULE_SCHEMA = vol.Schema(
49 vol.Required(
"id"): cv.positive_int,
50 vol.Optional(
"activated"): cv.boolean,
51 vol.Optional(
"monday"): vol.Any(
None, SERVICE_CHARGE_SET_SCHEDULE_DAY_SCHEMA),
52 vol.Optional(
"tuesday"): vol.Any(
None, SERVICE_CHARGE_SET_SCHEDULE_DAY_SCHEMA),
53 vol.Optional(
"wednesday"): vol.Any(
54 None, SERVICE_CHARGE_SET_SCHEDULE_DAY_SCHEMA
56 vol.Optional(
"thursday"): vol.Any(
None, SERVICE_CHARGE_SET_SCHEDULE_DAY_SCHEMA),
57 vol.Optional(
"friday"): vol.Any(
None, SERVICE_CHARGE_SET_SCHEDULE_DAY_SCHEMA),
58 vol.Optional(
"saturday"): vol.Any(
None, SERVICE_CHARGE_SET_SCHEDULE_DAY_SCHEMA),
59 vol.Optional(
"sunday"): vol.Any(
None, SERVICE_CHARGE_SET_SCHEDULE_DAY_SCHEMA),
62 SERVICE_CHARGE_SET_SCHEDULES_SCHEMA = SERVICE_VEHICLE_SCHEMA.extend(
64 vol.Required(ATTR_SCHEDULES): vol.All(
65 cv.ensure_list, [SERVICE_CHARGE_SET_SCHEDULE_SCHEMA]
70 SERVICE_AC_SET_SCHEDULE_DAY_SCHEMA = vol.Schema(
72 vol.Required(
"readyAtTime"): cv.string,
76 SERVICE_AC_SET_SCHEDULE_SCHEMA = vol.Schema(
78 vol.Required(
"id"): cv.positive_int,
79 vol.Optional(
"activated"): cv.boolean,
80 vol.Optional(
"monday"): vol.Any(
None, SERVICE_AC_SET_SCHEDULE_DAY_SCHEMA),
81 vol.Optional(
"tuesday"): vol.Any(
None, SERVICE_AC_SET_SCHEDULE_DAY_SCHEMA),
82 vol.Optional(
"wednesday"): vol.Any(
None, SERVICE_AC_SET_SCHEDULE_DAY_SCHEMA),
83 vol.Optional(
"thursday"): vol.Any(
None, SERVICE_AC_SET_SCHEDULE_DAY_SCHEMA),
84 vol.Optional(
"friday"): vol.Any(
None, SERVICE_AC_SET_SCHEDULE_DAY_SCHEMA),
85 vol.Optional(
"saturday"): vol.Any(
None, SERVICE_AC_SET_SCHEDULE_DAY_SCHEMA),
86 vol.Optional(
"sunday"): vol.Any(
None, SERVICE_AC_SET_SCHEDULE_DAY_SCHEMA),
89 SERVICE_AC_SET_SCHEDULES_SCHEMA = SERVICE_VEHICLE_SCHEMA.extend(
91 vol.Required(ATTR_SCHEDULES): vol.All(
92 cv.ensure_list, [SERVICE_AC_SET_SCHEDULE_SCHEMA]
97 SERVICE_AC_CANCEL =
"ac_cancel"
98 SERVICE_AC_START =
"ac_start"
99 SERVICE_CHARGE_SET_SCHEDULES =
"charge_set_schedules"
100 SERVICE_AC_SET_SCHEDULES =
"ac_set_schedules"
104 SERVICE_CHARGE_SET_SCHEDULES,
105 SERVICE_AC_SET_SCHEDULES,
110 """Register the Renault services."""
112 async
def ac_cancel(service_call: ServiceCall) ->
None:
114 proxy = get_vehicle_proxy(service_call.data)
116 LOGGER.debug(
"A/C cancel attempt")
117 result = await proxy.set_ac_stop()
118 LOGGER.debug(
"A/C cancel result: %s", result)
120 async
def ac_start(service_call: ServiceCall) ->
None:
122 temperature: float = service_call.data[ATTR_TEMPERATURE]
123 when: datetime |
None = service_call.data.get(ATTR_WHEN)
124 proxy = get_vehicle_proxy(service_call.data)
126 LOGGER.debug(
"A/C start attempt: %s / %s", temperature, when)
127 result = await proxy.set_ac_start(temperature, when)
128 LOGGER.debug(
"A/C start result: %s", result.raw_data)
130 async
def charge_set_schedules(service_call: ServiceCall) ->
None:
131 """Set charge schedules."""
132 schedules: list[dict[str, Any]] = service_call.data[ATTR_SCHEDULES]
133 proxy = get_vehicle_proxy(service_call.data)
134 charge_schedules = await proxy.get_charging_settings()
135 for schedule
in schedules:
136 charge_schedules.update(schedule)
139 assert charge_schedules.schedules
is not None
140 LOGGER.debug(
"Charge set schedules attempt: %s", schedules)
141 result = await proxy.set_charge_schedules(charge_schedules.schedules)
143 LOGGER.debug(
"Charge set schedules result: %s", result)
145 "It may take some time before these changes are reflected in your vehicle"
148 async
def ac_set_schedules(service_call: ServiceCall) ->
None:
149 """Set A/C schedules."""
150 schedules: list[dict[str, Any]] = service_call.data[ATTR_SCHEDULES]
151 proxy = get_vehicle_proxy(service_call.data)
152 hvac_schedules = await proxy.get_hvac_settings()
154 for schedule
in schedules:
155 hvac_schedules.update(schedule)
158 assert hvac_schedules.schedules
is not None
159 LOGGER.debug(
"HVAC set schedules attempt: %s", schedules)
160 result = await proxy.set_hvac_schedules(hvac_schedules.schedules)
162 LOGGER.debug(
"HVAC set schedules result: %s", result)
164 "It may take some time before these changes are reflected in your vehicle"
167 def get_vehicle_proxy(service_call_data: Mapping) -> RenaultVehicleProxy:
168 """Get vehicle from service_call data."""
169 device_registry = dr.async_get(hass)
170 device_id = service_call_data[ATTR_VEHICLE]
171 device_entry = device_registry.async_get(device_id)
172 if device_entry
is None:
174 translation_domain=DOMAIN,
175 translation_key=
"invalid_device_id",
176 translation_placeholders={
"device_id": device_id},
179 loaded_entries: list[RenaultConfigEntry] = [
181 for entry
in hass.config_entries.async_entries(DOMAIN)
182 if entry.state == ConfigEntryState.LOADED
183 and entry.entry_id
in device_entry.config_entries
185 for entry
in loaded_entries:
186 for vin, vehicle
in entry.runtime_data.vehicles.items():
187 if (DOMAIN, vin)
in device_entry.identifiers:
190 translation_domain=DOMAIN,
191 translation_key=
"no_config_entry_for_device",
192 translation_placeholders={
"device_id": device_entry.name
or device_id},
195 hass.services.async_register(
199 schema=SERVICE_VEHICLE_SCHEMA,
201 hass.services.async_register(
205 schema=SERVICE_AC_START_SCHEMA,
207 hass.services.async_register(
209 SERVICE_CHARGE_SET_SCHEDULES,
210 charge_set_schedules,
211 schema=SERVICE_CHARGE_SET_SCHEDULES_SCHEMA,
213 hass.services.async_register(
215 SERVICE_AC_SET_SCHEDULES,
217 schema=SERVICE_AC_SET_SCHEDULES_SCHEMA,
None setup_services(HomeAssistant hass)