From 385baa85ccf9a41ff55ab6594a177a1044aa0305 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Sun, 5 Feb 2023 11:41:47 +0100 Subject: [PATCH] Update to Home Assistant 2023.2.2 (#55) Co-authored-by: rikroe --- .../bmw_connected_drive/__init__.py | 5 +- .../bmw_connected_drive/binary_sensor.py | 11 ++-- .../bmw_connected_drive/button.py | 20 ++++---- .../bmw_connected_drive/config_flow.py | 7 +-- .../bmw_connected_drive/const.py | 15 ++---- .../bmw_connected_drive/coordinator.py | 2 +- .../bmw_connected_drive/device_tracker.py | 20 +++++--- .../bmw_connected_drive/diagnostics.py | 50 ++++++------------- custom_components/bmw_connected_drive/lock.py | 28 ++++++----- .../bmw_connected_drive/manifest.json | 4 +- .../bmw_connected_drive/sensor.py | 17 ++++--- .../bmw_connected_drive/translations/de.json | 2 +- .../bmw_connected_drive/translations/es.json | 2 +- .../bmw_connected_drive/translations/pt.json | 2 +- .../bmw_connected_drive/translations/sk.json | 22 ++++++++ 15 files changed, 106 insertions(+), 101 deletions(-) diff --git a/custom_components/bmw_connected_drive/__init__.py b/custom_components/bmw_connected_drive/__init__.py index 7023dd7..a47f2be 100644 --- a/custom_components/bmw_connected_drive/__init__.py +++ b/custom_components/bmw_connected_drive/__init__.py @@ -127,7 +127,7 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool: hass.data[DOMAIN][entry.entry_id] = coordinator # Set up all platforms except notify - hass.config_entries.async_setup_platforms( + await hass.config_entries.async_forward_entry_setups( entry, [platform for platform in PLATFORMS if platform != Platform.NOTIFY] ) @@ -163,6 +163,7 @@ class BMWBaseEntity(CoordinatorEntity[BMWDataUpdateCoordinator]): coordinator: BMWDataUpdateCoordinator _attr_attribution = ATTRIBUTION + _attr_has_entity_name = True def __init__( self, @@ -182,7 +183,7 @@ def __init__( identifiers={(DOMAIN, self.vehicle.vin)}, manufacturer=vehicle.brand.name, model=vehicle.name, - name=f"{vehicle.brand.name} {vehicle.name}", + name=vehicle.name, ) async def async_added_to_hass(self) -> None: diff --git a/custom_components/bmw_connected_drive/binary_sensor.py b/custom_components/bmw_connected_drive/binary_sensor.py index 87506cc..df25efb 100644 --- a/custom_components/bmw_connected_drive/binary_sensor.py +++ b/custom_components/bmw_connected_drive/binary_sensor.py @@ -30,6 +30,7 @@ ALLOWED_CONDITION_BASED_SERVICE_KEYS = { "BRAKE_FLUID", + "EMISSION_CHECK", "ENGINE_OIL", "OIL", "TIRE_WEAR_FRONT", @@ -37,10 +38,10 @@ "VEHICLE_CHECK", "VEHICLE_TUV", } -LOGGED_CONDITION_BASED_SERVICE_WARNINGS = set() +LOGGED_CONDITION_BASED_SERVICE_WARNINGS: set[str] = set() ALLOWED_CHECK_CONTROL_MESSAGE_KEYS = {"ENGINE_OIL", "TIRE_PRESSURE"} -LOGGED_CHECK_CONTROL_MESSAGE_WARNINGS = set() +LOGGED_CHECK_CONTROL_MESSAGE_WARNINGS: set[str] = set() def _condition_based_services( @@ -121,7 +122,7 @@ class BMWBinarySensorEntityDescription( SENSOR_TYPES: tuple[BMWBinarySensorEntityDescription, ...] = ( BMWBinarySensorEntityDescription( key="lids", - name="Doors", + name="Lids", device_class=BinarySensorDeviceClass.OPENING, icon="mdi:car-door-lock", # device class opening: On means open, Off means closed @@ -165,7 +166,7 @@ class BMWBinarySensorEntityDescription( ), BMWBinarySensorEntityDescription( key="check_control_messages", - name="Control messages", + name="Check control messages", device_class=BinarySensorDeviceClass.PROBLEM, icon="mdi:car-tire-alert", # device class problem: On means problem detected, Off means no problem @@ -224,8 +225,6 @@ def __init__( super().__init__(coordinator, vehicle) self.entity_description = description self._unit_system = unit_system - - self._attr_name = f"{vehicle.name} {description.key}" self._attr_unique_id = f"{vehicle.vin}-{description.key}" @callback diff --git a/custom_components/bmw_connected_drive/button.py b/custom_components/bmw_connected_drive/button.py index baa7870..873a727 100644 --- a/custom_components/bmw_connected_drive/button.py +++ b/custom_components/bmw_connected_drive/button.py @@ -38,31 +38,31 @@ class BMWButtonEntityDescription(ButtonEntityDescription): BMWButtonEntityDescription( key="light_flash", icon="mdi:car-light-alert", - name="Flash Lights", + name="Flash lights", remote_function=lambda vehicle: vehicle.remote_services.trigger_remote_light_flash(), ), BMWButtonEntityDescription( key="sound_horn", icon="mdi:bullhorn", - name="Sound Horn", + name="Sound horn", remote_function=lambda vehicle: vehicle.remote_services.trigger_remote_horn(), ), BMWButtonEntityDescription( key="activate_air_conditioning", icon="mdi:hvac", - name="Activate Air Conditioning", + name="Activate air conditioning", remote_function=lambda vehicle: vehicle.remote_services.trigger_remote_air_conditioning(), ), BMWButtonEntityDescription( key="deactivate_air_conditioning", icon="mdi:hvac-off", - name="Deactivate Air Conditioning", + name="Deactivate air conditioning", remote_function=lambda vehicle: vehicle.remote_services.trigger_remote_air_conditioning_stop(), ), BMWButtonEntityDescription( key="find_vehicle", icon="mdi:crosshairs-question", - name="Find Vehicle", + name="Find vehicle", remote_function=lambda vehicle: vehicle.remote_services.trigger_remote_vehicle_finder(), ), BMWButtonEntityDescription( @@ -112,8 +112,6 @@ def __init__( """Initialize BMW vehicle sensor.""" super().__init__(coordinator, vehicle) self.entity_description = description - - self._attr_name = f"{vehicle.name} {description.name}" self._attr_unique_id = f"{vehicle.vin}-{description.key}" async def async_press(self) -> None: @@ -122,9 +120,11 @@ async def async_press(self) -> None: await self.entity_description.remote_function(self.vehicle) elif self.entity_description.account_function: _LOGGER.warning( - "The 'Refresh from cloud' button is deprecated. Use the 'homeassistant.update_entity' " - "service with any BMW entity for a full reload. See https://www.home-assistant.io/" - "integrations/bmw_connected_drive/#update-the-state--refresh-from-api for details" + "The 'Refresh from cloud' button is deprecated. Use the" + " 'homeassistant.update_entity' service with any BMW entity for a full" + " reload. See" + " https://www.home-assistant.io/integrations/bmw_connected_drive/#update-the-state--refresh-from-api" + " for details" ) await self.entity_description.account_function(self.coordinator) diff --git a/custom_components/bmw_connected_drive/config_flow.py b/custom_components/bmw_connected_drive/config_flow.py index 3994b07..4f05794 100644 --- a/custom_components/bmw_connected_drive/config_flow.py +++ b/custom_components/bmw_connected_drive/config_flow.py @@ -94,14 +94,9 @@ def async_get_options_flow( return BMWOptionsFlow(config_entry) -class BMWOptionsFlow(config_entries.OptionsFlow): +class BMWOptionsFlow(config_entries.OptionsFlowWithConfigEntry): """Handle a option flow for MyBMW.""" - def __init__(self, config_entry: config_entries.ConfigEntry) -> None: - """Initialize MyBMW option flow.""" - self.config_entry = config_entry - self.options = dict(config_entry.options) - async def async_step_init( self, user_input: dict[str, Any] | None = None ) -> FlowResult: diff --git a/custom_components/bmw_connected_drive/const.py b/custom_components/bmw_connected_drive/const.py index 6a8f82a..50634eb 100644 --- a/custom_components/bmw_connected_drive/const.py +++ b/custom_components/bmw_connected_drive/const.py @@ -1,10 +1,5 @@ """Const file for the MyBMW integration.""" -from homeassistant.const import ( - LENGTH_KILOMETERS, - LENGTH_MILES, - VOLUME_GALLONS, - VOLUME_LITERS, -) +from homeassistant.const import UnitOfLength, UnitOfVolume DOMAIN = "bmw_connected_drive" ATTRIBUTION = "Data provided by MyBMW" @@ -20,8 +15,8 @@ DATA_HASS_CONFIG = "hass_config" UNIT_MAP = { - "KILOMETERS": LENGTH_KILOMETERS, - "MILES": LENGTH_MILES, - "LITERS": VOLUME_LITERS, - "GALLONS": VOLUME_GALLONS, + "KILOMETERS": UnitOfLength.KILOMETERS, + "MILES": UnitOfLength.MILES, + "LITERS": UnitOfVolume.LITERS, + "GALLONS": UnitOfVolume.GALLONS, } diff --git a/custom_components/bmw_connected_drive/coordinator.py b/custom_components/bmw_connected_drive/coordinator.py index 08e90d3..0f03505 100644 --- a/custom_components/bmw_connected_drive/coordinator.py +++ b/custom_components/bmw_connected_drive/coordinator.py @@ -21,7 +21,7 @@ _LOGGER = logging.getLogger(__name__) -class BMWDataUpdateCoordinator(DataUpdateCoordinator): +class BMWDataUpdateCoordinator(DataUpdateCoordinator[None]): """Class to manage fetching BMW data.""" account: MyBMWAccount diff --git a/custom_components/bmw_connected_drive/device_tracker.py b/custom_components/bmw_connected_drive/device_tracker.py index dc71100..12d2973 100644 --- a/custom_components/bmw_connected_drive/device_tracker.py +++ b/custom_components/bmw_connected_drive/device_tracker.py @@ -2,12 +2,11 @@ from __future__ import annotations import logging -from typing import Literal +from typing import Any from bimmer_connected.vehicle import MyBMWVehicle -from homeassistant.components.device_tracker import SOURCE_TYPE_GPS -from homeassistant.components.device_tracker.config_entry import TrackerEntity +from homeassistant.components.device_tracker import SourceType, TrackerEntity from homeassistant.config_entries import ConfigEntry from homeassistant.core import HomeAssistant from homeassistant.helpers.entity_platform import AddEntitiesCallback @@ -32,7 +31,10 @@ async def async_setup_entry( entities.append(BMWDeviceTracker(coordinator, vehicle)) if not vehicle.is_vehicle_tracking_enabled: _LOGGER.info( - "Tracking is (currently) disabled for vehicle %s (%s), defaulting to unknown", + ( + "Tracking is (currently) disabled for vehicle %s (%s), defaulting" + " to unknown" + ), vehicle.name, vehicle.vin, ) @@ -54,10 +56,10 @@ def __init__( super().__init__(coordinator, vehicle) self._attr_unique_id = vehicle.vin - self._attr_name = vehicle.name + self._attr_name = None @property - def extra_state_attributes(self) -> dict: + def extra_state_attributes(self) -> dict[str, Any]: """Return entity specific state attributes.""" return {**self._attrs, ATTR_DIRECTION: self.vehicle.vehicle_location.heading} @@ -67,6 +69,7 @@ def latitude(self) -> float | None: return ( self.vehicle.vehicle_location.location[0] if self.vehicle.is_vehicle_tracking_enabled + and self.vehicle.vehicle_location.location else None ) @@ -76,10 +79,11 @@ def longitude(self) -> float | None: return ( self.vehicle.vehicle_location.location[1] if self.vehicle.is_vehicle_tracking_enabled + and self.vehicle.vehicle_location.location else None ) @property - def source_type(self) -> Literal["gps"]: + def source_type(self) -> SourceType: """Return the source type, eg gps or router, of the device.""" - return SOURCE_TYPE_GPS + return SourceType.GPS diff --git a/custom_components/bmw_connected_drive/diagnostics.py b/custom_components/bmw_connected_drive/diagnostics.py index 5a0b122..c69d06d 100644 --- a/custom_components/bmw_connected_drive/diagnostics.py +++ b/custom_components/bmw_connected_drive/diagnostics.py @@ -1,9 +1,8 @@ """Diagnostics support for the BMW Connected Drive integration.""" from __future__ import annotations +from dataclasses import asdict import json -from pathlib import Path -from tempfile import TemporaryDirectory from typing import TYPE_CHECKING, Any from bimmer_connected.utils import MyBMWJSONEncoder @@ -12,7 +11,6 @@ from homeassistant.config_entries import ConfigEntry from homeassistant.const import CONF_PASSWORD, CONF_USERNAME from homeassistant.core import HomeAssistant -from homeassistant.exceptions import HomeAssistantError from homeassistant.helpers.device_registry import DeviceEntry from .const import CONF_REFRESH_TOKEN, DOMAIN @@ -31,7 +29,6 @@ "heading", "vin", "licensePlate", - "name", "city", "street", "streetNumber", @@ -42,31 +39,7 @@ ] -async def async_get_fingerprints( - coordinator: "BMWDataUpdateCoordinator", -) -> dict[str, Any]: - """Return pre-redacted fingerprints (i.e. the raw API responses).""" - - fingerprints = {} - - try: - # Use the library's fingerprint function to store all relevant - # HTTP requests into a temporary directory and load from there - with TemporaryDirectory() as tempdir: - tempdir_path = Path(tempdir) - coordinator.account.config.log_response_path = tempdir_path - await coordinator.account.get_vehicles() - for logfile in tempdir_path.iterdir(): - with open(logfile, "rb") as fp: - fingerprints[logfile.name] = json.load(fp) - finally: - # Make sure that log_response_path is always set to None afterwards - coordinator.account.config.log_response_path = None - - return fingerprints - - -def vehicle_to_dict(vehicle: MyBMWVehicle) -> dict: +def vehicle_to_dict(vehicle: MyBMWVehicle | None) -> dict: """Convert a MyBMWVehicle to a dictionary using MyBMWJSONEncoder.""" retval: dict = json.loads(json.dumps(vehicle, cls=MyBMWJSONEncoder)) return retval @@ -78,6 +51,9 @@ async def async_get_config_entry_diagnostics( """Return diagnostics for a config entry.""" coordinator: BMWDataUpdateCoordinator = hass.data[DOMAIN][config_entry.entry_id] + coordinator.account.config.log_responses = True + await coordinator.account.get_vehicles(force_init=True) + diagnostics_data = { "info": async_redact_data(config_entry.data, TO_REDACT_INFO), "data": [ @@ -85,10 +61,13 @@ async def async_get_config_entry_diagnostics( for vehicle in coordinator.account.vehicles ], "fingerprint": async_redact_data( - await async_get_fingerprints(coordinator), TO_REDACT_DATA + [asdict(r) for r in coordinator.account.get_stored_responses()], + TO_REDACT_DATA, ), } + coordinator.account.config.log_responses = False + return diagnostics_data @@ -98,19 +77,22 @@ async def async_get_device_diagnostics( """Return diagnostics for a device.""" coordinator: BMWDataUpdateCoordinator = hass.data[DOMAIN][config_entry.entry_id] + coordinator.account.config.log_responses = True + await coordinator.account.get_vehicles(force_init=True) + vin = next(iter(device.identifiers))[1] vehicle = coordinator.account.get_vehicle(vin) - if not vehicle: - raise HomeAssistantError("Vehicle not found") - diagnostics_data = { "info": async_redact_data(config_entry.data, TO_REDACT_INFO), "data": async_redact_data(vehicle_to_dict(vehicle), TO_REDACT_DATA), # Always have to get the full fingerprint as the VIN is redacted beforehand by the library "fingerprint": async_redact_data( - await async_get_fingerprints(coordinator), TO_REDACT_DATA + [asdict(r) for r in coordinator.account.get_stored_responses()], + TO_REDACT_DATA, ), } + coordinator.account.config.log_responses = False + return diagnostics_data diff --git a/custom_components/bmw_connected_drive/lock.py b/custom_components/bmw_connected_drive/lock.py index 0c2c5a1..ffc6cf6 100644 --- a/custom_components/bmw_connected_drive/lock.py +++ b/custom_components/bmw_connected_drive/lock.py @@ -32,27 +32,29 @@ async def async_setup_entry( for vehicle in coordinator.account.vehicles: if not coordinator.read_only: - entities.append(BMWLock(coordinator, vehicle, "lock", "BMW lock")) + entities.append( + BMWLock( + coordinator, + vehicle, + ) + ) async_add_entities(entities) class BMWLock(BMWBaseEntity, LockEntity): """Representation of a MyBMW vehicle lock.""" + _attr_name = "Lock" + def __init__( self, coordinator: BMWDataUpdateCoordinator, vehicle: MyBMWVehicle, - attribute: str, - sensor_name: str, ) -> None: """Initialize the lock.""" super().__init__(coordinator, vehicle) - self._attribute = attribute - self._attr_name = f"{vehicle.name} {attribute}" - self._attr_unique_id = f"{vehicle.vin}-{attribute}" - self._sensor_name = sensor_name + self._attr_unique_id = f"{vehicle.vin}-lock" self.door_lock_state_available = DOOR_LOCK_STATE in vehicle.available_attributes async def async_lock(self, **kwargs: Any) -> None: @@ -81,17 +83,17 @@ async def async_unlock(self, **kwargs: Any) -> None: def _handle_coordinator_update(self) -> None: """Handle updated data from the coordinator.""" _LOGGER.debug("Updating lock data of %s", self.vehicle.name) + # Set default attributes + self._attr_extra_state_attributes = self._attrs + # Only update the HA state machine if the vehicle reliably reports its lock state if self.door_lock_state_available: self._attr_is_locked = self.vehicle.doors_and_windows.door_lock_state in { LockState.LOCKED, LockState.SECURED, } - self._attr_extra_state_attributes = dict( - self._attrs, - **{ - "door_lock_state": self.vehicle.doors_and_windows.door_lock_state.value, - }, - ) + self._attr_extra_state_attributes[ + "door_lock_state" + ] = self.vehicle.doors_and_windows.door_lock_state.value super()._handle_coordinator_update() diff --git a/custom_components/bmw_connected_drive/manifest.json b/custom_components/bmw_connected_drive/manifest.json index ebe4e0c..a68e25b 100644 --- a/custom_components/bmw_connected_drive/manifest.json +++ b/custom_components/bmw_connected_drive/manifest.json @@ -2,10 +2,10 @@ "domain": "bmw_connected_drive", "name": "BMW Connected Drive", "documentation": "https://www.home-assistant.io/integrations/bmw_connected_drive", - "requirements": ["bimmer_connected==0.10.2"], + "requirements": ["bimmer_connected==0.12.0"], "codeowners": ["@gerard33", "@rikroe"], "config_flow": true, "iot_class": "cloud_polling", - "version": "2022.7.5-custom", + "version": "2023.2.2-custom", "loggers": ["bimmer_connected"] } diff --git a/custom_components/bmw_connected_drive/sensor.py b/custom_components/bmw_connected_drive/sensor.py index ae3dc0b..c797de9 100644 --- a/custom_components/bmw_connected_drive/sensor.py +++ b/custom_components/bmw_connected_drive/sensor.py @@ -19,7 +19,6 @@ from homeassistant.core import HomeAssistant, callback from homeassistant.helpers.entity_platform import AddEntitiesCallback from homeassistant.helpers.typing import StateType -from homeassistant.util.unit_system import UnitSystem from . import BMWBaseEntity from .const import DOMAIN, UNIT_MAP @@ -56,23 +55,27 @@ def convert_and_round( # --- Generic --- "charging_start_time": BMWSensorEntityDescription( key="charging_start_time", + name="Charging start time", key_class="fuel_and_battery", device_class=SensorDeviceClass.TIMESTAMP, entity_registry_enabled_default=False, ), "charging_end_time": BMWSensorEntityDescription( key="charging_end_time", + name="Charging end time", key_class="fuel_and_battery", device_class=SensorDeviceClass.TIMESTAMP, ), "charging_status": BMWSensorEntityDescription( key="charging_status", + name="Charging status", key_class="fuel_and_battery", icon="mdi:ev-station", value=lambda x, y: x.value, ), "remaining_battery_percent": BMWSensorEntityDescription( key="remaining_battery_percent", + name="Remaining battery percent", key_class="fuel_and_battery", unit_type=PERCENTAGE, device_class=SensorDeviceClass.BATTERY, @@ -80,12 +83,14 @@ def convert_and_round( # --- Specific --- "mileage": BMWSensorEntityDescription( key="mileage", + name="Mileage", icon="mdi:speedometer", unit_type=LENGTH, value=lambda x, hass: convert_and_round(x, hass.config.units.length, 2), ), "remaining_range_total": BMWSensorEntityDescription( key="remaining_range_total", + name="Remaining range total", key_class="fuel_and_battery", icon="mdi:map-marker-distance", unit_type=LENGTH, @@ -93,6 +98,7 @@ def convert_and_round( ), "remaining_range_electric": BMWSensorEntityDescription( key="remaining_range_electric", + name="Remaining range electric", key_class="fuel_and_battery", icon="mdi:map-marker-distance", unit_type=LENGTH, @@ -100,6 +106,7 @@ def convert_and_round( ), "remaining_range_fuel": BMWSensorEntityDescription( key="remaining_range_fuel", + name="Remaining range fuel", key_class="fuel_and_battery", icon="mdi:map-marker-distance", unit_type=LENGTH, @@ -107,6 +114,7 @@ def convert_and_round( ), "remaining_fuel": BMWSensorEntityDescription( key="remaining_fuel", + name="Remaining fuel", key_class="fuel_and_battery", icon="mdi:gas-station", unit_type=VOLUME, @@ -114,6 +122,7 @@ def convert_and_round( ), "remaining_fuel_percent": BMWSensorEntityDescription( key="remaining_fuel_percent", + name="Remaining fuel percent", key_class="fuel_and_battery", icon="mdi:gas-station", unit_type=PERCENTAGE, @@ -127,7 +136,6 @@ async def async_setup_entry( async_add_entities: AddEntitiesCallback, ) -> None: """Set up the MyBMW sensors from config entry.""" - unit_system = hass.config.units coordinator: BMWDataUpdateCoordinator = hass.data[DOMAIN][config_entry.entry_id] entities: list[BMWSensor] = [] @@ -135,7 +143,7 @@ async def async_setup_entry( for vehicle in coordinator.account.vehicles: entities.extend( [ - BMWSensor(coordinator, vehicle, description, unit_system) + BMWSensor(coordinator, vehicle, description) for attribute_name in vehicle.available_attributes if (description := SENSOR_TYPES.get(attribute_name)) ] @@ -154,13 +162,10 @@ def __init__( coordinator: BMWDataUpdateCoordinator, vehicle: MyBMWVehicle, description: BMWSensorEntityDescription, - unit_system: UnitSystem, ) -> None: """Initialize BMW vehicle sensor.""" super().__init__(coordinator, vehicle) self.entity_description = description - - self._attr_name = f"{vehicle.name} {description.key}" self._attr_unique_id = f"{vehicle.vin}-{description.key}" # Set the correct unit of measurement based on the unit_type diff --git a/custom_components/bmw_connected_drive/translations/de.json b/custom_components/bmw_connected_drive/translations/de.json index 0ee49c1..5eb400d 100644 --- a/custom_components/bmw_connected_drive/translations/de.json +++ b/custom_components/bmw_connected_drive/translations/de.json @@ -21,7 +21,7 @@ "step": { "account_options": { "data": { - "read_only": "Schreibgesch\u00fctzt (nur Sensoren und Notify, keine Ausf\u00fchrung von Diensten, kein Abschlie\u00dfen)" + "read_only": "Schreibgesch\u00fctzt (nur Sensoren und Benachrichtigungen, keine Ausf\u00fchrung von Diensten, kein Abschlie\u00dfen)" } } } diff --git a/custom_components/bmw_connected_drive/translations/es.json b/custom_components/bmw_connected_drive/translations/es.json index 2a4fd84..7d5c215 100644 --- a/custom_components/bmw_connected_drive/translations/es.json +++ b/custom_components/bmw_connected_drive/translations/es.json @@ -21,7 +21,7 @@ "step": { "account_options": { "data": { - "read_only": "S\u00f3lo lectura (s\u00f3lo sensores y notificaci\u00f3n, sin ejecuci\u00f3n de servicios, sin bloqueo)" + "read_only": "S\u00f3lo lectura (s\u00f3lo sensores y notificaci\u00f3n, sin ejecuci\u00f3n de servicios, ni cerraduras)" } } } diff --git a/custom_components/bmw_connected_drive/translations/pt.json b/custom_components/bmw_connected_drive/translations/pt.json index 3814c89..941380d 100644 --- a/custom_components/bmw_connected_drive/translations/pt.json +++ b/custom_components/bmw_connected_drive/translations/pt.json @@ -4,7 +4,7 @@ "already_configured": "Conta j\u00e1 configurada" }, "error": { - "cannot_connect": "Falha na liga\u00e7\u00e3o", + "cannot_connect": "A liga\u00e7\u00e3o falhou", "invalid_auth": "Autentica\u00e7\u00e3o inv\u00e1lida" }, "step": { diff --git a/custom_components/bmw_connected_drive/translations/sk.json b/custom_components/bmw_connected_drive/translations/sk.json index 5ada995..bed4d73 100644 --- a/custom_components/bmw_connected_drive/translations/sk.json +++ b/custom_components/bmw_connected_drive/translations/sk.json @@ -1,7 +1,29 @@ { "config": { + "abort": { + "already_configured": "\u00da\u010det je u\u017e nakonfigurovan\u00fd" + }, "error": { + "cannot_connect": "Nepodarilo sa pripoji\u0165", "invalid_auth": "Neplatn\u00e9 overenie" + }, + "step": { + "user": { + "data": { + "password": "Heslo", + "region": "Regi\u00f3n ConnectedDrive", + "username": "Pou\u017e\u00edvate\u013esk\u00e9 meno" + } + } + } + }, + "options": { + "step": { + "account_options": { + "data": { + "read_only": "Len na \u010d\u00edtanie (len senzory a notifik\u00e1cie, \u017eiadne vykon\u00e1vanie slu\u017eieb, \u017eiadny z\u00e1mok)" + } + } } } } \ No newline at end of file