Skip to content

Commit

Permalink
Added initial translations to French and Italian
Browse files Browse the repository at this point in the history
  • Loading branch information
dan-r committed Jan 22, 2024
1 parent d95091f commit 850f7f6
Show file tree
Hide file tree
Showing 10 changed files with 383 additions and 51 deletions.
5 changes: 5 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,11 @@ From the Home Assistant Integrations page, search for and add the Nissan Connect
## Update Time
Following the model of leaf2mqtt, this integration can be set to use a different update time when plugged in. When HVAC is turned on the update time drops to once per minute.

## Translations
I have provided machine translations from English to the following languages as a start, but welcome native speakers to give feedback on these and to improve them:
* French
* Italian

## Entities
This integration exposes the following entities. Please note that entities will only be shown if the functionality is supported by your car.

Expand Down
13 changes: 3 additions & 10 deletions custom_components/nissan_connect/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
class KamereonEntity(Entity):
"""Base class for all Kamereon car entities."""

_attr_has_entity_name = True

def __init__(self, cooordinator, vehicle):
"""Initialize the entity."""
self.vehicle = vehicle
Expand Down Expand Up @@ -32,19 +34,10 @@ def icon(self):
def _vehicle_name(self):
return self.vehicle.nickname or self.vehicle.model_name

@property
def name(self):
"""Return full name of the entity."""
if not self._attr_name:
return self._vehicle_name
return f"{self._vehicle_name} {self._attr_name}"

@property
def unique_id(self):
"""Return unique ID of the entity."""
if not self._attr_name:
return None
return f"{self._vehicle_name}_{self._attr_name}"
return f"{self._vehicle_name}_{self._attr_translation_key}"

@property
def device_info(self):
Expand Down
11 changes: 3 additions & 8 deletions custom_components/nissan_connect/binary_sensor.py
Original file line number Diff line number Diff line change
@@ -1,16 +1,11 @@
"""Support for Kamereon cars."""
import logging

from homeassistant.components.binary_sensor import BinarySensorEntity, BinarySensorDeviceClass
from homeassistant.const import STATE_UNKNOWN

from .base import KamereonEntity
from .kamereon import ChargingStatus, PluggedStatus, LockStatus, Feature
from .const import DOMAIN, DATA_VEHICLES, DATA_COORDINATOR

_LOGGER = logging.getLogger(__name__)


async def async_setup_entry(hass, config, async_add_entities):
"""Set up the Kamereon sensors."""
data = hass.data[DOMAIN][DATA_VEHICLES]
Expand All @@ -31,7 +26,7 @@ async def async_setup_entry(hass, config, async_add_entities):
class ChargingStatusEntity(KamereonEntity, BinarySensorEntity):
"""Representation of charging status."""
_attr_device_class = BinarySensorDeviceClass.BATTERY_CHARGING
_attr_name = "Charging"
_attr_translation_key = "charging"

@property
def icon(self):
Expand All @@ -58,7 +53,7 @@ def device_state_attributes(self):
class PluggedStatusEntity(KamereonEntity, BinarySensorEntity):
"""Representation of plugged status."""
_attr_device_class = BinarySensorDeviceClass.PLUG
_attr_name = "Plugged In"
_attr_translation_key = "plugged"

@property
def icon(self):
Expand All @@ -85,7 +80,7 @@ def device_state_attributes(self):

class LockStatusEntity(KamereonEntity, BinarySensorEntity):
_attr_device_class = BinarySensorDeviceClass.LOCK
_attr_name = "Doors Locked"
_attr_translation_key = "doors_locked"

@property
def icon(self):
Expand Down
10 changes: 5 additions & 5 deletions custom_components/nissan_connect/button.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,16 +21,16 @@ async def async_setup_entry(hass, config, async_add_entities):
entities.append(ForceUpdateButton(coordinator, data[vehicle], hass, stats_coordinator))
if Feature.HORN_AND_LIGHTS in data[vehicle].features:
entities += [
HornLightsButtons(coordinator, data[vehicle], "Flash Lights", "mdi:car-light-high", "lights"),
HornLightsButtons(coordinator, data[vehicle], "Honk Horn", "mdi:bullhorn", "horn_lights")
HornLightsButtons(coordinator, data[vehicle], "flash_lights", "mdi:car-light-high", "lights"),
HornLightsButtons(coordinator, data[vehicle], "honk_horn", "mdi:bullhorn", "horn_lights")
]


async_add_entities(entities, update_before_add=True)


class ForceUpdateButton(KamereonEntity, ButtonEntity):
_attr_name = "Update Data"
_attr_translation_key = "update_data"

def __init__(self, coordinator, vehicle, hass, stats_coordinator):
KamereonEntity.__init__(self, coordinator, vehicle)
Expand All @@ -47,8 +47,8 @@ async def async_press(self):
await self.coordinator_statistics.async_refresh()

class HornLightsButtons(KamereonEntity, ButtonEntity):
def __init__(self, coordinator, vehicle, name, icon, action):
self._attr_name = name
def __init__(self, coordinator, vehicle, translation_key, icon, action):
self._attr_translation_key = translation_key
self._icon = icon
self._action = action
KamereonEntity.__init__(self, coordinator, vehicle)
Expand Down
2 changes: 1 addition & 1 deletion custom_components/nissan_connect/climate.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ class KamereonClimate(KamereonEntity, ClimateEntity):
_attr_supported_features = ClimateEntityFeature.TARGET_TEMPERATURE
_attr_hvac_modes = SUPPORT_HVAC
_attr_temperature_unit = UnitOfTemperature.CELSIUS
_attr_name = "Climate"
_attr_translation_key = "climate"
_attr_min_temp = 16
_attr_max_temp = 26
_attr_target_temperature_step = 1
Expand Down
2 changes: 1 addition & 1 deletion custom_components/nissan_connect/device_tracker.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ async def async_setup_entry(hass, entry, async_add_entities):
return True

class KamereonDeviceTracker(KamereonEntity, TrackerEntity):
_attr_name = "Location"
_attr_translation_key = "location"

@property
def latitude(self) -> float:
Expand Down
50 changes: 26 additions & 24 deletions custom_components/nissan_connect/sensor.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,22 +31,22 @@ async def async_setup_entry(hass, config, async_add_entities):
RangeSensor(coordinator, data[vehicle], False, imperial_distance),
ChargeTimeRequiredSensor(coordinator, data[vehicle], ChargingSpeed.NORMAL),
ChargeTimeRequiredSensor(coordinator, data[vehicle], ChargingSpeed.FAST),
TimestampSensor(coordinator, data[vehicle], 'battery_status_last_updated', 'Last Updated', 'mdi:clock-time-eleven-outline')]
TimestampSensor(coordinator, data[vehicle], 'battery_status_last_updated', 'last_updated', 'mdi:clock-time-eleven-outline')]
if data[vehicle].internal_temperature is not None:
entities.append(InternalTemperatureSensor(coordinator, data[vehicle]))
if data[vehicle].external_temperature is not None:
entities.append(ExternalTemperatureSensor(coordinator, data[vehicle]))
if Feature.DRIVING_JOURNEY_HISTORY in data[vehicle].features:
entities += [
StatisticSensor(coordinator_stats, data[vehicle], 'daily', lambda x: x.total_distance, 'Daily Distance', 'mdi:map-marker-distance', SensorDeviceClass.DISTANCE, UnitOfLength.KILOMETERS, 0, imperial_distance),
StatisticSensor(coordinator_stats, data[vehicle], 'daily', lambda x: x.trip_count, 'Daily Trips', 'mdi:hiking', None, None, 0),
StatisticSensor(coordinator_stats, data[vehicle], 'monthly', lambda x: x.total_distance, 'Monthly Distance', 'mdi:map-marker-distance', SensorDeviceClass.DISTANCE, UnitOfLength.KILOMETERS, 0, imperial_distance),
StatisticSensor(coordinator_stats, data[vehicle], 'monthly', lambda x: x.trip_count, 'Monthly Trips', 'mdi:hiking', None, None, 0),
StatisticSensor(coordinator_stats, data[vehicle], 'daily', lambda x: x.total_distance, 'daily_distance', 'mdi:map-marker-distance', SensorDeviceClass.DISTANCE, UnitOfLength.KILOMETERS, 0, imperial_distance),
StatisticSensor(coordinator_stats, data[vehicle], 'daily', lambda x: x.trip_count, 'daily_trips', 'mdi:hiking', None, None, 0),
StatisticSensor(coordinator_stats, data[vehicle], 'monthly', lambda x: x.total_distance, 'monthly_distance', 'mdi:map-marker-distance', SensorDeviceClass.DISTANCE, UnitOfLength.KILOMETERS, 0, imperial_distance),
StatisticSensor(coordinator_stats, data[vehicle], 'monthly', lambda x: x.trip_count, 'monthly_trips', 'mdi:hiking', None, None, 0),
]
if Feature.BATTERY_STATUS in data[vehicle].features:
entities += [
StatisticSensor(coordinator_stats, data[vehicle], 'daily', lambda x: x.total_distance / x.consumed_electricity, 'Daily Efficiency', 'mdi:ev-station', SensorDeviceClass.DISTANCE, UnitOfLength.KILOMETERS, 2, imperial_distance),
StatisticSensor(coordinator_stats, data[vehicle], 'monthly', lambda x: x.total_distance / x.consumed_electricity, 'Monthly Efficiency', 'mdi:ev-station', SensorDeviceClass.DISTANCE, UnitOfLength.KILOMETERS, 2, imperial_distance),
StatisticSensor(coordinator_stats, data[vehicle], 'daily', lambda x: x.total_distance / x.consumed_electricity, 'daily_efficiency', 'mdi:ev-station', SensorDeviceClass.DISTANCE, UnitOfLength.KILOMETERS, 2, imperial_distance),
StatisticSensor(coordinator_stats, data[vehicle], 'monthly', lambda x: x.total_distance / x.consumed_electricity, 'monthly_efficiency', 'mdi:ev-station', SensorDeviceClass.DISTANCE, UnitOfLength.KILOMETERS, 2, imperial_distance),
]

entities.append(OdometerSensor(coordinator, data[vehicle], imperial_distance))
Expand All @@ -55,10 +55,13 @@ async def async_setup_entry(hass, config, async_add_entities):


class BatteryLevelSensor(KamereonEntity, SensorEntity):
_attr_name = "Battery Level"
_attr_translation_key = "battery_level"
_attr_device_class = SensorDeviceClass.BATTERY
_attr_native_unit_of_measurement = PERCENTAGE

def __init__(self, coordinator, vehicle):
KamereonEntity.__init__(self, coordinator, vehicle)

@property
def state(self):
"""Return the state."""
Expand All @@ -80,7 +83,7 @@ def device_state_attributes(self):


class InternalTemperatureSensor(KamereonEntity, SensorEntity):
_attr_name = "Internal Temperature"
_attr_translation_key = "internal_temperature"
_attr_device_class = SensorDeviceClass.TEMPERATURE
_attr_native_unit_of_measurement = UnitOfTemperature.CELSIUS

Expand All @@ -106,7 +109,7 @@ def device_state_attributes(self):


class ExternalTemperatureSensor(KamereonEntity, SensorEntity):
_attr_name = "External Temperature"
_attr_translation_key = "external_temperature"
_attr_device_class = SensorDeviceClass.TEMPERATURE
_attr_native_unit_of_measurement = UnitOfTemperature.CELSIUS

Expand All @@ -132,15 +135,14 @@ def device_state_attributes(self):


class RangeSensor(KamereonEntity, SensorEntity):
_attr_name = "Range"
_attr_device_class = SensorDeviceClass.DISTANCE
_attr_native_unit_of_measurement = UnitOfLength.KILOMETERS

def __init__(self, coordinator, vehicle, hvac, imperial_distance):
if imperial_distance:
self._attr_suggested_unit_of_measurement = UnitOfLength.MILES

self._attr_name = "Range (AC On)" if hvac else "Range (AC Off)"
self._attr_translation_key = "range_ac_on" if hvac else "range_ac_off"
KamereonEntity.__init__(self, coordinator, vehicle)
self.hvac = hvac

Expand All @@ -158,7 +160,7 @@ def icon(self):


class OdometerSensor(KamereonEntity, SensorEntity):
_attr_name = "Odometer"
_attr_translation_key = "odometer"
_attr_device_class = SensorDeviceClass.DISTANCE
_attr_native_unit_of_measurement = UnitOfLength.KILOMETERS

Expand All @@ -179,13 +181,13 @@ def icon(self):


class StatisticSensor(KamereonEntity, SensorEntity):
def __init__(self, coordinator, vehicle, key, func, name, icon, device_class, unit, precision, imperial_distance=False):
def __init__(self, coordinator, vehicle, key, func, translation_key, icon, device_class, unit, precision, imperial_distance=False):
self._attr_device_class = device_class
self._attr_native_unit_of_measurement = unit
self._attr_suggested_display_precision = precision
if imperial_distance:
self._attr_suggested_unit_of_measurement = UnitOfLength.MILES
self._attr_name = name
self._attr_translation_key = translation_key
self._icon = icon
self._key = key
self._lambda = func
Expand Down Expand Up @@ -227,21 +229,21 @@ def icon(self):


class ChargeTimeRequiredSensor(KamereonEntity, SensorEntity):
_attr_name = "Charge Time"
_attr_translation_key = "charge_time"
_attr_device_class = SensorDeviceClass.DURATION
_attr_native_unit_of_measurement = UnitOfTime.MINUTES

CHARGING_SPEED_NAME = {
ChargingSpeed.FASTEST: '50kW',
ChargingSpeed.FAST: '6kW',
ChargingSpeed.NORMAL: '3kW',
ChargingSpeed.SLOW: '1kW',
ChargingSpeed.FASTEST: '50kw',
ChargingSpeed.FAST: '6kw',
ChargingSpeed.NORMAL: '3kw',
ChargingSpeed.SLOW: '1kw',
}

def __init__(self, coordinator, vehicle, charging_speed):
self._attr_name = f"Charge Time ({self.CHARGING_SPEED_NAME[charging_speed]})"
KamereonEntity.__init__(self, coordinator, vehicle)
self.charging_speed = charging_speed
self._attr_translation_key = "charge_time_" + self.CHARGING_SPEED_NAME[charging_speed]
KamereonEntity.__init__(self, coordinator, vehicle)

@property
def native_value(self):
Expand All @@ -257,8 +259,8 @@ def icon(self):
class TimestampSensor(KamereonEntity, SensorEntity):
_attr_device_class = SensorDeviceClass.TIMESTAMP

def __init__(self, coordinator, vehicle, attribute, name, icon):
self._attr_name = name
def __init__(self, coordinator, vehicle, attribute, translation_key, icon):
self._attr_translation_key = translation_key
self._icon = icon
KamereonEntity.__init__(self, coordinator, vehicle)
self.attribute = attribute
Expand Down
85 changes: 83 additions & 2 deletions custom_components/nissan_connect/translations/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -43,5 +43,86 @@
},
"abort": {}
},
"issues": {}
}
"issues": {},
"entity": {
"binary_sensor": {
"charging": {
"name": "Charging"
},
"doors_locked": {
"name": "Doors Locked"
},
"plugged": {
"name": "Plugged In"
}
},
"button": {
"flash_lights": {
"name": "Flash Lights"
},
"honk_horn": {
"name": "Honk Horn"
},
"update_data": {
"name": "Update Data"
}
},
"climate": {
"climate": {
"name": "Climate"
}
},
"device_tracker": {
"location": {
"name": "Location"
}
},
"sensor": {
"battery_level": {
"name": "Battery Level"
},
"internal_temperature": {
"name": "Internal Temperature"
},
"external_temperature": {
"name": "External Temperature"
},
"range_ac_on": {
"name": "Range (AC On)"
},
"range_ac_off": {
"name": "Range (AC Off)"
},
"odometer": {
"name": "Odometer"
},
"charge_time_3kw": {
"name": "Charge Time (3kW)"
},
"charge_time_6kw": {
"name": "Charge Time (6kW)"
},
"last_updated": {
"name": "Last Updated"
},
"daily_distance": {
"name": "Daily Distance"
},
"daily_efficiency": {
"name": "Daily Efficiency"
},
"daily_trips": {
"name": "Daily Trips"
},
"monthly_distance": {
"name": "Monthly Distance"
},
"monthly_efficiency": {
"name": "Monthly Efficiency"
},
"monthly_trips": {
"name": "Monthly Trips"
}
}
}
}
Loading

0 comments on commit 850f7f6

Please sign in to comment.