diff --git a/custom_components/localthings/config_flow.py b/custom_components/localthings/config_flow.py index d892bf4..38dd0b4 100644 --- a/custom_components/localthings/config_flow.py +++ b/custom_components/localthings/config_flow.py @@ -9,9 +9,17 @@ from typing import Any import voluptuous as vol from homeassistant import config_entries from homeassistant.data_entry_flow import FlowResult +from homeassistant.helpers.selector import ( + TextSelector, + TextSelectorConfig, + TextSelectorType, +) from .const import DOMAIN, CONF_HOST, CONF_PORT, CONF_CERT_PEM, CONF_KEY_PEM, PROBE_PORTS +_TEXT = TextSelector(TextSelectorConfig(type=TextSelectorType.TEXT)) +_MULTILINE = TextSelector(TextSelectorConfig(type=TextSelectorType.TEXT, multiline=True)) + _LOGGER = logging.getLogger(__name__) @@ -151,13 +159,13 @@ class LocalThingsConfigFlow(config_entries.ConfigFlow, domain=DOMAIN): ) if has_creds: - schema = vol.Schema({vol.Required(CONF_HOST): str}) + schema = vol.Schema({vol.Required(CONF_HOST): _TEXT}) reuse_note = "Certificate and key will be reused from the existing device." else: schema = vol.Schema({ - vol.Required(CONF_HOST): str, - vol.Required(CONF_CERT_PEM): str, - vol.Required(CONF_KEY_PEM): str, + vol.Required(CONF_HOST): _TEXT, + vol.Required(CONF_CERT_PEM): _MULTILINE, + vol.Required(CONF_KEY_PEM): _MULTILINE, }) reuse_note = "" diff --git a/custom_components/localthings/entity.py b/custom_components/localthings/entity.py index 84fd250..253cabf 100644 --- a/custom_components/localthings/entity.py +++ b/custom_components/localthings/entity.py @@ -1,6 +1,8 @@ """Base entity for Local Things.""" from __future__ import annotations +import re + from homeassistant.helpers.update_coordinator import CoordinatorEntity from homeassistant.helpers.device_registry import DeviceInfo @@ -11,6 +13,16 @@ from .const import DOMAIN from .coordinator import LocalThingsCoordinator +def _derive_name(state_key: str) -> str: + """Turn a snake_case state key into a title-cased display name. + + Strips a trailing instance number of 0 (singleton), promotes any other + instance number with a space: "door_cooler_open1" → "Door Cooler Open 1". + """ + name = re.sub(r'(\d+)$', lambda m: f' {m.group()}' if int(m.group()) > 0 else '', state_key) + return name.replace('_', ' ').title().strip() + + class LocalThingsEntity(CoordinatorEntity[LocalThingsCoordinator]): """Base class for all Local Things entities.""" @@ -21,7 +33,7 @@ class LocalThingsEntity(CoordinatorEntity[LocalThingsCoordinator]): self._bound = bound self._state_key = _key(bound) self._attr_unique_id = f"{DOMAIN}_{coordinator.device_serial}_{self._state_key}" - self._attr_name = bound.desc.name + self._attr_name = bound.desc.name if bound.desc.name is not None else _derive_name(self._state_key) self._attr_icon = bound.desc.icon self._attr_entity_category = bound.desc.entity_category self._attr_entity_registry_enabled_default = bound.desc.enabled_default diff --git a/custom_components/localthings/strings.json b/custom_components/localthings/strings.json index f53dcc1..bc861d1 100644 --- a/custom_components/localthings/strings.json +++ b/custom_components/localthings/strings.json @@ -3,17 +3,22 @@ "step": { "user": { "title": "Add Samsung Appliance", - "description": "Enter the IP address of your Samsung appliance. {reuse_note}", + "description": "Enter the IP address of your Samsung appliance on the local network. {reuse_note}", "data": { "host": "IP Address", "cert_pem": "Certificate (PEM)", "key_pem": "Private Key (PEM)" + }, + "data_description": { + "host": "Local IP address of your Samsung appliance (e.g. 192.168.1.50).", + "cert_pem": "The PEM-encoded client certificate used to authenticate with the appliance. Paste the full contents including the BEGIN/END CERTIFICATE header and footer.", + "key_pem": "The PEM-encoded private key matching the certificate above. Paste the full contents including the BEGIN/END PRIVATE KEY header and footer." } } }, "error": { - "cannot_connect": "Cannot connect to the device. Check the IP address and credentials.", - "unknown": "Unexpected error." + "cannot_connect": "Cannot connect to the device. Verify the IP address is reachable and the certificate and key are correct.", + "unknown": "Unexpected error. Check the Home Assistant logs for details." }, "abort": { "already_configured": "This device is already configured." diff --git a/custom_components/localthings/translations/en.json b/custom_components/localthings/translations/en.json new file mode 100644 index 0000000..bc861d1 --- /dev/null +++ b/custom_components/localthings/translations/en.json @@ -0,0 +1,27 @@ +{ + "config": { + "step": { + "user": { + "title": "Add Samsung Appliance", + "description": "Enter the IP address of your Samsung appliance on the local network. {reuse_note}", + "data": { + "host": "IP Address", + "cert_pem": "Certificate (PEM)", + "key_pem": "Private Key (PEM)" + }, + "data_description": { + "host": "Local IP address of your Samsung appliance (e.g. 192.168.1.50).", + "cert_pem": "The PEM-encoded client certificate used to authenticate with the appliance. Paste the full contents including the BEGIN/END CERTIFICATE header and footer.", + "key_pem": "The PEM-encoded private key matching the certificate above. Paste the full contents including the BEGIN/END PRIVATE KEY header and footer." + } + } + }, + "error": { + "cannot_connect": "Cannot connect to the device. Verify the IP address is reachable and the certificate and key are correct.", + "unknown": "Unexpected error. Check the Home Assistant logs for details." + }, + "abort": { + "already_configured": "This device is already configured." + } + } +}