Skip to content

Commit

Permalink
Add translations for entity names
Browse files Browse the repository at this point in the history
  • Loading branch information
Necroneco committed Nov 1, 2024
1 parent e1cb634 commit 2ec9a49
Show file tree
Hide file tree
Showing 12 changed files with 1,950 additions and 90 deletions.
7 changes: 6 additions & 1 deletion custom_components/xiaomi_gateway3/hass/entity.py
Original file line number Diff line number Diff line change
Expand Up @@ -69,11 +69,16 @@ def __init__(self, device: "XDevice", conv: "BaseConv"):
via_device=via_device,
)
self._attr_has_entity_name = True
self._attr_name = attr_human_name(conv.attr)
self._attr_should_poll = False
self._attr_unique_id = f"{device.uid}_{conv.attr}"

setup_entity_description(self, conv)
if (
not hasattr(self, "_attr_name")
and not hasattr(self, "_attr_translation_key")
and not self._default_to_device_class_name()
): # unnamed
self._attr_name = attr_human_name(conv.attr)

if entity_name := device.extra.get("entity_name"):
if entity_name.endswith(conv.attr):
Expand Down
99 changes: 60 additions & 39 deletions custom_components/xiaomi_gateway3/hass/entity_description.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
from homeassistant.const import CONDUCTIVITY

from ..core.converters.base import BaseConv
from ..core.converters.const import ENTITY_LAZY

# just to reduce the code
CELSIUS = UnitOfTemperature.CELSIUS
Expand All @@ -51,6 +52,7 @@
"statistics": "_attr_state_class",
"units": "_attr_native_unit_of_measurement",
"visible": "_attr_entity_registry_visible_default",
"translation_key": "_attr_translation_key",
}

# description with class should be used with "domain.attr"
Expand All @@ -63,73 +65,83 @@
"sensor.illuminance": {"class": SENSOR.ILLUMINANCE, "units": LIGHT_LUX},
"sensor.humidity": {"class": SENSOR.HUMIDITY, "units": PERCENTAGE},
"sensor.moisture": {"class": SENSOR.MOISTURE, "units": PERCENTAGE},
"sensor.power": {"class": SENSOR.POWER, "units": UnitOfPower.WATT},
"sensor.power": {"class": SENSOR.POWER, "units": UnitOfPower.WATT, "translation_key": "power"},
"sensor.pressure": {"class": SENSOR.PRESSURE, "units": UnitOfPressure.HPA},
"sensor.temperature": {"class": SENSOR.TEMPERATURE, "units": CELSIUS},
"sensor.voltage": {"class": SENSOR.VOLTAGE, "units": UnitOfElectricPotential.VOLT},
##
# binary sensors with device class
"binary_sensor.contact": {"class": BinarySensorDeviceClass.DOOR},
"binary_sensor.latch": {"class": BinarySensorDeviceClass.LOCK},
"binary_sensor.contact": {"class": BinarySensorDeviceClass.DOOR, "translation_key": "contact"},
"binary_sensor.latch": {"class": BinarySensorDeviceClass.LOCK, "translation_key": "latch"},
"binary_sensor.moisture": {"class": BinarySensorDeviceClass.MOISTURE},
"binary_sensor.plug_detection": {"class": BinarySensorDeviceClass.PLUG},
"binary_sensor.pressure": {"class": BinarySensorDeviceClass.VIBRATION},
"binary_sensor.reverse": {"class": BinarySensorDeviceClass.LOCK},
"binary_sensor.square": {"class": BinarySensorDeviceClass.LOCK},
"binary_sensor.pressure": {"class": BinarySensorDeviceClass.VIBRATION, "translation_key": "pressure"},
"binary_sensor.reverse": {"class": BinarySensorDeviceClass.LOCK, "translation_key": "reverse"},
"binary_sensor.square": {"class": BinarySensorDeviceClass.LOCK, "translation_key": "square"},
"binary_sensor.water_leak": {"class": BinarySensorDeviceClass.MOISTURE},
##
# sensors without device class
"action": {"icon": "mdi:bell"},
"conductivity": {"icon": "mdi:flower", "units": CONDUCTIVITY},
"formaldehyde": {"units": CONCENTRATION_MILLIGRAMS_PER_CUBIC_METER},
"gas_density": {"icon": "mdi:google-circles-communities", "units": "% LEL"},
"rssi": {"units": SIGNAL_STRENGTH_DECIBELS_MILLIWATT},
"smoke_density": {"icon": "mdi:google-circles-communities", "units": "% obs/ft"},
"supply": {"icon": "mdi:gauge", "units": PERCENTAGE},
"tvoc": {"icon": "mdi:cloud", "units": CONCENTRATION_PARTS_PER_BILLION},
"eco_two": {"name": "eCO2", "icon": "mdi:molecule-co2", "units": CONCENTRATION_PARTS_PER_MILLION},
"action": {"icon": "mdi:bell", "translation_key": "action"},
"conductivity": {"icon": "mdi:flower", "units": CONDUCTIVITY, "translation_key": "conductivity"},
"formaldehyde": {"units": CONCENTRATION_MILLIGRAMS_PER_CUBIC_METER, "translation_key": "formaldehyde"},
"gas_density": {"icon": "mdi:google-circles-communities", "units": "% LEL", "translation_key": "gas_density"},
"rssi": {"units": SIGNAL_STRENGTH_DECIBELS_MILLIWATT, "translation_key": "rssi"},
"smoke_density": {"icon": "mdi:google-circles-communities", "units": "% obs/ft", "translation_key": "smoke_density"},
"supply": {"icon": "mdi:gauge", "units": PERCENTAGE, "translation_key": "supply"},
"tvoc": {"icon": "mdi:cloud", "units": CONCENTRATION_PARTS_PER_BILLION, "translation_key": "tvoc"},
"eco_two": {"icon": "mdi:molecule-co2", "units": CONCENTRATION_PARTS_PER_MILLION, "translation_key": "e_co2"},
##
# stats sensors
"binary_sensor.gateway": {
"class": BinarySensorDeviceClass.CONNECTIVITY,
"icon": "mdi:router-wireless",
"translation_key": "gateway",
},
"binary_sensor.ble": {
"class": BinarySensorDeviceClass.CONNECTIVITY,
"category": DIAGNOSTIC,
"icon": "mdi:bluetooth",
"translation_key": "ble",
},
"binary_sensor.mesh": {
"class": BinarySensorDeviceClass.CONNECTIVITY,
"category": DIAGNOSTIC,
"icon": "mdi:bluetooth",
"translation_key": "mesh",
},
"binary_sensor.zigbee": {
"class": BinarySensorDeviceClass.CONNECTIVITY,
"category": DIAGNOSTIC,
"icon": "mdi:zigbee",
"translation_key": "zigbee",
},
"sensor.ble": {
"class": SENSOR.TIMESTAMP,
"category": DIAGNOSTIC,
"icon": "mdi:bluetooth",
"translation_key": "ble",
},
"sensor.mesh": {
"class": SENSOR.TIMESTAMP,
"category": DIAGNOSTIC,
"icon": "mdi:bluetooth",
"translation_key": "mesh",
},
"sensor.zigbee": {
"class": SENSOR.TIMESTAMP,
"category": DIAGNOSTIC,
"icon": "mdi:zigbee",
"translation_key": "zigbee",
},
##
# main controls
"alarm_trigger": {"icon": "mdi:alarm-bell"},
"fan": {"icon": "mdi:fan"},
"outlet": {"icon": "mdi:power-socket-us"},
"plug": {"icon": "mdi:power-plug"},
"alarm_trigger": {"icon": "mdi:alarm-bell", "translation_key": "alarm_trigger"},
"fan": {"icon": "mdi:fan", "translation_key": "fan"},
"light.light": {"name": None},
"switch.channel": {"class": SwitchDeviceClass.SWITCH, "translation_key": "channel"},
"switch.outlet": {"class": SwitchDeviceClass.OUTLET, "icon": "mdi:power-socket-us", "translation_key": "outlet"},
"switch.plug": {"class": SwitchDeviceClass.OUTLET, "icon": "mdi:power-plug", "translation_key": "plug"},
"switch.switch": {"class": SwitchDeviceClass.SWITCH, "translation_key": "switch"},
"usb": {"icon": "mdi:usb-port"},
##
# batteries and energy sensors
Expand All @@ -143,11 +155,13 @@
"units": PERCENTAGE,
"category": DIAGNOSTIC,
"enabled": False,
"translation_key": "battery_original",
},
"sensor.battery_voltage": {
"class": SENSOR.VOLTAGE,
"units": UnitOfElectricPotential.MILLIVOLT,
"category": DIAGNOSTIC,
"translation_key": "battery_voltage",
},
"binary_sensor.battery_charging": {
"class": BinarySensorDeviceClass.BATTERY_CHARGING,
Expand All @@ -163,43 +177,46 @@
"class": SENSOR.ENERGY,
"statistics": SensorStateClass.TOTAL,
"units": UnitOfEnergy.KILO_WATT_HOUR,
"translation_key": "power_consumption",
},
##
# CONFIG controls
"backlight": {"category": CONFIG, "enabled": False},
"blind_time": {"category": CONFIG, "enabled": False},
"charge_protect": {"category": CONFIG, "enabled": False},
"child_lock": {"category": CONFIG, "enabled": False, "icon": "mdi:baby-carriage"},
"display_unit": {"category": CONFIG, "enabled": False},
"flex_switch": {"category": CONFIG, "enabled": False},
"led": {"category": CONFIG, "enabled": False, "icon": "mdi:led-off"},
"led_reverse": {"category": CONFIG, "enabled": False, "icon": "mdi:led-off"},
"mode": {"category": CONFIG, "enabled": False, "icon": "mdi:cog"},
"motor_reverse": {"category": CONFIG, "enabled": False},
"motor_speed": {"category": CONFIG, "enabled": False},
"power_off_memory": {"category": CONFIG, "enabled": False},
"power_on_state": {"category": CONFIG, "enabled": False},
"sensitivity": {"category": CONFIG, "enabled": False},
"wireless": {"category": CONFIG, "enabled": False},
"backlight": {"category": CONFIG, "enabled": False, "translation_key": "backlight"},
"blind_time": {"category": CONFIG, "enabled": False, "translation_key": "blind_time"},
"charge_protect": {"category": CONFIG, "enabled": False, "translation_key": "charge_protect"},
"child_lock": {"category": CONFIG, "enabled": False, "icon": "mdi:baby-carriage", "translation_key": "child_lock"},
"display_unit": {"category": CONFIG, "enabled": False, "translation_key": "display_unit"},
"flex_switch": {"category": CONFIG, "enabled": False, "translation_key": "flex_switch"},
"led": {"category": CONFIG, "enabled": False, "icon": "mdi:led-off", "translation_key": "led"},
"led_reverse": {"category": CONFIG, "enabled": False, "icon": "mdi:led-off", "translation_key": "led_reverse"},
"mode": {"category": CONFIG, "enabled": False, "icon": "mdi:cog", "translation_key": "mode"},
"motor_reverse": {"category": CONFIG, "enabled": False, "translation_key": "motor_reverse"},
"motor_speed": {"category": CONFIG, "enabled": False, "translation_key": "motor_speed"},
"power_off_memory": {"category": CONFIG, "enabled": False, "translation_key": "power_off_memory"},
"power_on_state": {"category": CONFIG, "enabled": False, "translation_key": "power_on_state"},
"sensitivity": {"category": CONFIG, "enabled": False, "translation_key": "sensitivity"},
"wireless": {"category": CONFIG, "enabled": False, "translation_key": "wireless"},
##
# DIAGNOSTIC controls
"command": {"category": DIAGNOSTIC, "icon": "mdi:apple-keyboard-command"},
"data": {"category": DIAGNOSTIC, "icon": "mdi:information-box"},
"command": {"category": DIAGNOSTIC, "icon": "mdi:apple-keyboard-command", "translation_key": "command"},
"data": {"category": DIAGNOSTIC, "icon": "mdi:information-box", "translation_key": "data"},
##
# CONFIG and DIAGNOSTIC sensors
"sensor.chip_temperature": {
"class": SENSOR.TEMPERATURE,
"units": UnitOfTemperature.CELSIUS,
"category": DIAGNOSTIC,
"enabled": False,
"translation_key": "chip_temperature",
},
"fault": {"category": DIAGNOSTIC},
"fault": {"category": DIAGNOSTIC, "translation_key": "fault"},
"sensor.idle_time": {
"class": SENSOR.DURATION,
"icon": "mdi:timer",
"units": UnitOfTime.SECONDS,
"category": DIAGNOSTIC,
"enabled": False,
"translation_key": "idle_time",
},
}

Expand All @@ -215,6 +232,7 @@
def setup_entity_description(entity: Entity, conv: BaseConv) -> bool:
# 1. auto match entity description based on converter domain and attr name
key = conv.attr.rstrip("_01234567890") # remove tail _1, _2, _3
tail_index = conv.attr[len(key)+1:] # get tail 1, 2, 3
domain_key = f"{conv.domain}.{key}"
desc = ENTITY_DESCRIPTIONS.get(domain_key) or ENTITY_DESCRIPTIONS.get(key)

Expand All @@ -223,21 +241,24 @@ def setup_entity_description(entity: Entity, conv: BaseConv) -> bool:
desc = desc | conv.entity if desc else conv.entity

# 3. auto match only device_class based on converter domain
if not desc:
if not desc or desc == ENTITY_LAZY:
if domain_class := DOMAIN_CLASSES.get(conv.domain):
if key in iter(domain_class):
entity._attr_device_class = domain_class(key)
return True
return False

for k, v in desc.items():
if k == "lazy" or v is None:
if k == "lazy" or (v is None and k != "name"):
continue
if k == "category" and type(v) is str:
v = EntityCategory(v)
elif k == "class" and type(v) is str:
if domain_class := DOMAIN_CLASSES.get(conv.domain):
v = domain_class(v)
elif k == "translation_key" and tail_index:
v = f"{v}_n"
setattr(entity, "_attr_translation_placeholders", {"n": tail_index})
setattr(entity, ENTITY_KEYS.get(k) or k, v)

# sensor with unit_of_measurement and without state_class will be MEASUREMENT
Expand Down
2 changes: 0 additions & 2 deletions custom_components/xiaomi_gateway3/select.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,6 @@ class XCommandSelect(XEntity, SelectEntity):
def on_init(self):
self._attr_current_option = CMD_NONE
self._attr_options = [CMD_NONE, CMD_INFO]
self._attr_translation_key = self.attr

# noinspection PyTypeChecker
self.gw = self.device.gateways[0]
Expand Down Expand Up @@ -176,7 +175,6 @@ class XDataSelect(XEntity, SelectEntity):
def on_init(self):
self._attr_current_option = None
self._attr_options = []
self._attr_translation_key = self.attr

self.listen_attrs = {
"data",
Expand Down
Loading

0 comments on commit 2ec9a49

Please sign in to comment.