1 """Service calls for the Teslemetry integration."""
5 import voluptuous
as vol
6 from voluptuous
import All, Range
14 from .const
import DOMAIN
15 from .helpers
import handle_command, handle_vehicle_command, wake_up_vehicle
16 from .models
import TeslemetryEnergyData, TeslemetryVehicleData
18 _LOGGER = logging.getLogger(__name__)
25 ATTR_LOCALE =
"locale"
27 ATTR_TIMESTAMP =
"timestamp"
28 ATTR_FIELDS =
"fields"
29 ATTR_ENABLE =
"enable"
32 ATTR_TOU_SETTINGS =
"tou_settings"
33 ATTR_PRECONDITIONING_ENABLED =
"preconditioning_enabled"
34 ATTR_PRECONDITIONING_WEEKDAYS =
"preconditioning_weekdays_only"
35 ATTR_DEPARTURE_TIME =
"departure_time"
36 ATTR_OFF_PEAK_CHARGING_ENABLED =
"off_peak_charging_enabled"
37 ATTR_OFF_PEAK_CHARGING_WEEKDAYS =
"off_peak_charging_weekdays_only"
38 ATTR_END_OFF_PEAK_TIME =
"end_off_peak_time"
41 SERVICE_NAVIGATE_ATTR_GPS_REQUEST =
"navigation_gps_request"
42 SERVICE_SET_SCHEDULED_CHARGING =
"set_scheduled_charging"
43 SERVICE_SET_SCHEDULED_DEPARTURE =
"set_scheduled_departure"
44 SERVICE_VALET_MODE =
"valet_mode"
45 SERVICE_SPEED_LIMIT =
"speed_limit"
46 SERVICE_TIME_OF_USE =
"time_of_use"
50 hass: HomeAssistant, call: ServiceCall
52 """Get the device entry related to a service call."""
53 device_id = call.data[CONF_DEVICE_ID]
54 device_registry = dr.async_get(hass)
55 if (device_entry := device_registry.async_get(device_id))
is None:
57 translation_domain=DOMAIN,
58 translation_key=
"invalid_device",
59 translation_placeholders={
"device_id": device_id},
66 hass: HomeAssistant, device_entry: dr.DeviceEntry
68 """Get the config entry related to a device entry."""
69 config_entry: ConfigEntry
70 for entry_id
in device_entry.config_entries:
71 if entry := hass.config_entries.async_get_entry(entry_id):
72 if entry.domain == DOMAIN:
78 hass: HomeAssistant, device: dr.DeviceEntry, config: ConfigEntry
79 ) -> TeslemetryVehicleData:
80 """Get the vehicle data for a config entry."""
81 vehicle_data: TeslemetryVehicleData
82 assert device.serial_number
is not None
83 for vehicle
in config.runtime_data.vehicles:
84 if vehicle.vin == device.serial_number:
85 vehicle_data = vehicle
90 hass: HomeAssistant, device: dr.DeviceEntry, config: ConfigEntry
91 ) -> TeslemetryEnergyData:
92 """Get the energy site data for a config entry."""
93 energy_data: TeslemetryEnergyData
94 assert device.serial_number
is not None
95 for energysite
in config.runtime_data.energysites:
96 if str(energysite.id) == device.serial_number:
97 energy_data = energysite
102 """Set up the Teslemetry services."""
104 async
def navigate_gps_request(call: ServiceCall) ->
None:
105 """Send lat,lon,order with a vehicle."""
112 vehicle.api.navigation_gps_request(
113 lat=call.data[ATTR_GPS][CONF_LATITUDE],
114 lon=call.data[ATTR_GPS][CONF_LONGITUDE],
115 order=call.data.get(ATTR_ORDER),
119 hass.services.async_register(
121 SERVICE_NAVIGATE_ATTR_GPS_REQUEST,
122 navigate_gps_request,
125 vol.Required(CONF_DEVICE_ID): cv.string,
126 vol.Required(ATTR_GPS): {
127 vol.Required(CONF_LATITUDE): cv.latitude,
128 vol.Required(CONF_LONGITUDE): cv.longitude,
130 vol.Optional(ATTR_ORDER): cv.positive_int,
135 async
def set_scheduled_charging(call: ServiceCall) ->
None:
136 """Configure fleet telemetry."""
141 time: int |
None =
None
143 if "time" in call.data:
144 (hours, minutes, *seconds) = call.data[
"time"].split(
":")
145 time =
int(hours) * 60 +
int(minutes)
146 elif call.data[
"enable"]:
148 translation_domain=DOMAIN, translation_key=
"set_scheduled_charging_time"
153 vehicle.api.set_scheduled_charging(enable=call.data[
"enable"], time=time)
156 hass.services.async_register(
158 SERVICE_SET_SCHEDULED_CHARGING,
159 set_scheduled_charging,
162 vol.Required(CONF_DEVICE_ID): cv.string,
163 vol.Required(ATTR_ENABLE): bool,
164 vol.Optional(ATTR_TIME): str,
169 async
def set_scheduled_departure(call: ServiceCall) ->
None:
170 """Configure fleet telemetry."""
175 enable = call.data.get(
"enable",
True)
178 preconditioning_enabled = call.data.get(ATTR_PRECONDITIONING_ENABLED,
False)
179 preconditioning_weekdays_only = call.data.get(
180 ATTR_PRECONDITIONING_WEEKDAYS,
False
182 departure_time: int |
None =
None
183 if ATTR_DEPARTURE_TIME
in call.data:
184 (hours, minutes, *seconds) = call.data[ATTR_DEPARTURE_TIME].split(
":")
185 departure_time =
int(hours) * 60 +
int(minutes)
186 elif preconditioning_enabled:
188 translation_domain=DOMAIN,
189 translation_key=
"set_scheduled_departure_preconditioning",
193 off_peak_charging_enabled = call.data.get(ATTR_OFF_PEAK_CHARGING_ENABLED,
False)
194 off_peak_charging_weekdays_only = call.data.get(
195 ATTR_OFF_PEAK_CHARGING_WEEKDAYS,
False
197 end_off_peak_time: int |
None =
None
199 if ATTR_END_OFF_PEAK_TIME
in call.data:
200 (hours, minutes, *seconds) = call.data[ATTR_END_OFF_PEAK_TIME].split(
":")
201 end_off_peak_time =
int(hours) * 60 +
int(minutes)
202 elif off_peak_charging_enabled:
204 translation_domain=DOMAIN,
205 translation_key=
"set_scheduled_departure_off_peak",
210 vehicle.api.set_scheduled_departure(
212 preconditioning_enabled,
213 preconditioning_weekdays_only,
215 off_peak_charging_enabled,
216 off_peak_charging_weekdays_only,
221 hass.services.async_register(
223 SERVICE_SET_SCHEDULED_DEPARTURE,
224 set_scheduled_departure,
227 vol.Required(CONF_DEVICE_ID): cv.string,
228 vol.Optional(ATTR_ENABLE): bool,
229 vol.Optional(ATTR_PRECONDITIONING_ENABLED): bool,
230 vol.Optional(ATTR_PRECONDITIONING_WEEKDAYS): bool,
231 vol.Optional(ATTR_DEPARTURE_TIME): str,
232 vol.Optional(ATTR_OFF_PEAK_CHARGING_ENABLED): bool,
233 vol.Optional(ATTR_OFF_PEAK_CHARGING_WEEKDAYS): bool,
234 vol.Optional(ATTR_END_OFF_PEAK_TIME): str,
239 async
def valet_mode(call: ServiceCall) ->
None:
240 """Configure fleet telemetry."""
247 vehicle.api.set_valet_mode(
248 call.data.get(
"enable"), call.data.get(
"pin",
"")
252 hass.services.async_register(
258 vol.Required(CONF_DEVICE_ID): cv.string,
259 vol.Required(ATTR_ENABLE): cv.boolean,
260 vol.Required(ATTR_PIN): All(cv.positive_int, Range(min=1000, max=9999)),
265 async
def speed_limit(call: ServiceCall) ->
None:
266 """Configure fleet telemetry."""
272 enable = call.data.get(
"enable")
275 vehicle.api.speed_limit_activate(call.data.get(
"pin"))
277 elif enable
is False:
279 vehicle.api.speed_limit_deactivate(call.data.get(
"pin"))
282 hass.services.async_register(
288 vol.Required(CONF_DEVICE_ID): cv.string,
289 vol.Required(ATTR_ENABLE): cv.boolean,
290 vol.Required(ATTR_PIN): All(cv.positive_int, Range(min=1000, max=9999)),
295 async
def time_of_use(call: ServiceCall) ->
None:
296 """Configure time of use settings."""
302 site.api.time_of_use_settings(call.data.get(ATTR_TOU_SETTINGS))
306 translation_domain=DOMAIN,
307 translation_key=
"command_error",
308 translation_placeholders={
"error": resp[
"error"]},
311 hass.services.async_register(
317 vol.Required(CONF_DEVICE_ID): cv.string,
318 vol.Required(ATTR_TOU_SETTINGS): dict,
bool handle_vehicle_command(Awaitable command)
None wake_up_vehicle(TeslaFleetVehicleData vehicle)
dict[str, Any] handle_command(Awaitable command)
None async_register_services(HomeAssistant hass)
TeslemetryVehicleData async_get_vehicle_for_entry(HomeAssistant hass, dr.DeviceEntry device, ConfigEntry config)
dr.DeviceEntry async_get_device_for_service_call(HomeAssistant hass, ServiceCall call)
ConfigEntry async_get_config_for_device(HomeAssistant hass, dr.DeviceEntry device_entry)
TeslemetryEnergyData async_get_energy_site_for_entry(HomeAssistant hass, dr.DeviceEntry device, ConfigEntry config)