From 57263bb65a0da9c3c76556ea28bbbaaf0a7d6d39 Mon Sep 17 00:00:00 2001 From: 0xFEEDC0DE64 Date: Wed, 15 Sep 2021 21:25:23 +0200 Subject: [PATCH] goe_charger cleanups and improvements --- .../components/goe_charger/__init__.py | 19 +- .../components/goe_charger/binary_sensor.py | 9 +- .../components/goe_charger/common.py | 26 ++- .../components/goe_charger/config_flow.py | 26 ++- homeassistant/components/goe_charger/const.py | 4 +- .../components/goe_charger/number.py | 20 ++- .../components/goe_charger/select.py | 28 +-- .../components/goe_charger/sensor.py | 170 +++++++++++------- .../components/goe_charger/strings.json | 4 + .../goe_charger/translations/en.json | 4 + 10 files changed, 205 insertions(+), 105 deletions(-) diff --git a/homeassistant/components/goe_charger/__init__.py b/homeassistant/components/goe_charger/__init__.py index 83817e26e2b..63e9f802835 100644 --- a/homeassistant/components/goe_charger/__init__.py +++ b/homeassistant/components/goe_charger/__init__.py @@ -16,6 +16,7 @@ _LOGGER = logging.getLogger(__name__) PLATFORMS: list[str] = ["binary_sensor", "number", "select", "sensor"] + async def async_setup(hass: HomeAssistant, config_entry: ConfigEntry) -> bool: """Set up the go-eCharger integration.""" @@ -23,25 +24,31 @@ async def async_setup(hass: HomeAssistant, config_entry: ConfigEntry) -> bool: return True + async def async_setup_entry(hass: HomeAssistant, config_entry: ConfigEntry) -> bool: """Set up go-e Charger from a config entry.""" async def async_update_data(): """Fetch data from API endpoint.""" - hub = GoeChargerHub(config_entry.data["host"]) + hub = GoeChargerHub(config_entry.data["secure"], config_entry.data["host"], config_entry.data["pathprefix"]) try: - data = await hub.get_data(hass, ["alw","acu","adi","sse","eto","ccw","rssi","lmo","amp","fna","car","err","cbl","wh","fwv","oem","typ","tma","nrg","modelStatus","var","fhz","ust","acs","frc","psm","loc"]) + keys = [ + "alw", "acu", "adi", "sse", "eto", "ccw", "rssi", "lmo", "amp", "fna", "car", "err", "cbl", "wh", "fwv", + "oem", "typ", + "tma", "nrg", "modelStatus", "var", "fhz", "ust", "acs", "frc", "psm", "loc" + ] + data = await hub.get_data(hass, keys) dr = await device_registry.async_get_registry(hass) dr.async_get_or_create( name=data["fna"], config_entry_id=config_entry.entry_id, - #connections={(device_registry.CONNECTION_NETWORK_MAC, "11:22:33:44:55:66")}, + # connections={(device_registry.CONNECTION_NETWORK_MAC, "11:22:33:44:55:66")}, identifiers={(DOMAIN, config_entry.data["serial"])}, manufacturer=data["oem"], model=data["typ"] + " (" + str(data["var"]) + "kW)", - #suggested_area="Kitchen", + # suggested_area="Kitchen", sw_version=data["fwv"], ) @@ -67,11 +74,11 @@ async def async_setup_entry(hass: HomeAssistant, config_entry: ConfigEntry) -> b dr.async_get_or_create( name="go-e_Charger_" + config_entry.data["serial"], config_entry_id=config_entry.entry_id, - #connections={(device_registry.CONNECTION_NETWORK_MAC, "11:22:33:44:55:66")}, + # connections={(device_registry.CONNECTION_NETWORK_MAC, "11:22:33:44:55:66")}, identifiers={(DOMAIN, config_entry.data["serial"])}, manufacturer="", model="", - #suggested_area="Kitchen", + # suggested_area="Kitchen", sw_version="", ) diff --git a/homeassistant/components/goe_charger/binary_sensor.py b/homeassistant/components/goe_charger/binary_sensor.py index b3adee98c74..87adf679b88 100644 --- a/homeassistant/components/goe_charger/binary_sensor.py +++ b/homeassistant/components/goe_charger/binary_sensor.py @@ -45,7 +45,9 @@ class GoeChargerBinary(CoordinatorEntity, BinarySensorEntity): @property def available(self) -> bool: """Return True if entity is available.""" - return self.coordinator.data is not None and self._key in self.coordinator.data + return (self.coordinator.data is not None and + self._key in self.coordinator.data and + self.coordinator.data[self._key] is not None) @property def is_on(self) -> bool | None: @@ -62,8 +64,5 @@ class GoeChargerBinary(CoordinatorEntity, BinarySensorEntity): def device_info(self): """Get attributes about the device.""" return { - "identifiers": {(DOMAIN, self._serial)}, - #"name": self._device.label, - #"model": self._device.device_type_name, - #"manufacturer": "Unavailable", + "identifiers": {(DOMAIN, self._serial)} } diff --git a/homeassistant/components/goe_charger/common.py b/homeassistant/components/goe_charger/common.py index 0c8e044c79b..1b703eeb856 100644 --- a/homeassistant/components/goe_charger/common.py +++ b/homeassistant/components/goe_charger/common.py @@ -16,15 +16,26 @@ import urllib.parse _LOGGER = logging.getLogger(__name__) + class GoeChargerHub: - def __init__(self, host: str) -> None: + def __init__(self, secure: bool, host: str, pathprefix: str) -> None: """Initialize.""" + self._secure = secure self._host = host + self._pathprefix = pathprefix + + def get_urlbase(self): + url = 'http' + if self._secure: + url += 's' + url += '://' + self._host + self._pathprefix + + return url async def get_data(self, hass: HomeAssistant, keys: list[str]) -> bool: """Get the data from the charger.""" - url = 'http://' + self._host + '/api/status?filter=' + urllib.parse.quote_plus(','.join(keys)) + url = self.get_urlbase() + '/api/status?filter=' + urllib.parse.quote_plus(','.join(keys)) session = async_get_clientsession(hass) @@ -68,7 +79,7 @@ class GoeChargerHub: async def set_data(self, hass: HomeAssistant, data: dict[str, Any]) -> None: """Set data to the charger.""" - url = 'http://' + self._host + '/api/set?' + url = self.get_urlbase() + '/api/set?' for key, value in data.items(): url += urllib.parse.quote_plus(key) + '=' + urllib.parse.quote_plus(json.dumps(value)) + '&' @@ -114,31 +125,40 @@ class GoeChargerHub: _LOGGER.debug("Data set successfully for %s!", self._host) + class CannotConnect(HomeAssistantError): """Error to indicate we cannot connect.""" + def __init__(self, url: str) -> None: """Initialize.""" self.url = url + class TimeoutOccured(HomeAssistantError): """Error to indicate we cannot connect.""" + def __init__(self, url: str) -> None: """Initialize.""" self.url = url + class InvalidRespStatus(HomeAssistantError): """Error to indicate we got an invalid response status.""" + def __init__(self, status: int, response: str) -> None: """Initialize.""" self.status = status self.response = response + class InvalidJson(HomeAssistantError): """Error to indicate we got an invalid json response.""" + def __init__(self, details: str, response: str) -> None: """Initialize.""" self.details = details self.response = response + class NotImplemented(HomeAssistantError): """Error to indicate that something is not yet implemented.""" diff --git a/homeassistant/components/goe_charger/config_flow.py b/homeassistant/components/goe_charger/config_flow.py index 550ba105145..cb669998308 100644 --- a/homeassistant/components/goe_charger/config_flow.py +++ b/homeassistant/components/goe_charger/config_flow.py @@ -19,11 +19,14 @@ _LOGGER = logging.getLogger(__name__) # TODO adjust the data schema to the data that you need STEP_USER_DATA_SCHEMA = vol.Schema( { + vol.Required("secure", default=False): bool, vol.Required("host"): str, + vol.Optional("pathprefix"): str, vol.Required("interval", default=5): int, } ) + class ConfigFlow(config_entries.ConfigFlow, domain=DOMAIN): """Handle a config flow for go-e Charger.""" @@ -39,20 +42,26 @@ class ConfigFlow(config_entries.ConfigFlow, domain=DOMAIN): if user_input is None: return self.async_show_form(step_id="user", data_schema=STEP_USER_DATA_SCHEMA) - hub = GoeChargerHub(user_input["host"]) + hub = GoeChargerHub(user_input["secure"], user_input["host"], + user_input["pathprefix"] if "pathprefix" in user_input else "") try: data = await hub.get_data(self.hass, ["sse"]); except CannotConnect: - return self.async_show_form(step_id="user", data_schema=STEP_USER_DATA_SCHEMA, errors={"base": "cannot_connect"}) + return self.async_show_form(step_id="user", data_schema=STEP_USER_DATA_SCHEMA, + errors={"base": "cannot_connect"}) except TimeoutOccured: - return self.async_show_form(step_id="user", data_schema=STEP_USER_DATA_SCHEMA, errors={"base": "timeout_occured"}) + return self.async_show_form(step_id="user", data_schema=STEP_USER_DATA_SCHEMA, + errors={"base": "timeout_occured"}) except InvalidRespStatus: - return self.async_show_form(step_id="user", data_schema=STEP_USER_DATA_SCHEMA, errors={"base": "invalid_resp_status"}) + return self.async_show_form(step_id="user", data_schema=STEP_USER_DATA_SCHEMA, + errors={"base": "invalid_resp_status"}) except InvalidJson: - return self.async_show_form(step_id="user", data_schema=STEP_USER_DATA_SCHEMA, errors={"base": "invalid_json"}) + return self.async_show_form(step_id="user", data_schema=STEP_USER_DATA_SCHEMA, + errors={"base": "invalid_json"}) except NotImplemented: - return self.async_show_form(step_id="user", data_schema=STEP_USER_DATA_SCHEMA, errors={"base": "not_implemented"}) + return self.async_show_form(step_id="user", data_schema=STEP_USER_DATA_SCHEMA, + errors={"base": "not_implemented"}) except Exception as e: # pylint: disable=broad-except _LOGGER.exception("Unexpected exception %s", str(e)) return self.async_show_form(step_id="user", data_schema=STEP_USER_DATA_SCHEMA, errors={"base": "unknown"}) @@ -60,12 +69,15 @@ class ConfigFlow(config_entries.ConfigFlow, domain=DOMAIN): # TODO duplicate search result = self.async_create_entry(title="go-e Charger " + data["sse"], data={ + "secure": user_input["secure"], "host": user_input["host"], + "pathprefix": user_input["pathprefix"] if "pathprefix" in user_input else "", "serial": data["sse"], }) return result + class OptionsFlowHandler(config_entries.OptionsFlow): def __init__(self, config_entry: ConfigEntry) -> None: """Initialize options flow.""" @@ -76,7 +88,9 @@ class OptionsFlowHandler(config_entries.OptionsFlow): data_schema = vol.Schema( { + vol.Required("secure", default=self._config_entry.data.get("secure")): bool, vol.Required("host", default=self._config_entry.data.get("host")): str, + vol.Optional("pathprefix", default=self._config_entry.data.get("pathprefix")): str, vol.Required("interval", default=self._config_entry.data.get("interval")): int, } ) diff --git a/homeassistant/components/goe_charger/const.py b/homeassistant/components/goe_charger/const.py index 6ade031b17c..b35d55bf527 100644 --- a/homeassistant/components/goe_charger/const.py +++ b/homeassistant/components/goe_charger/const.py @@ -1,3 +1,5 @@ """Constants for the go-e Charger integration.""" -DOMAIN = "goe_charger" +from typing import Final + +DOMAIN: Final = "goe_charger" diff --git a/homeassistant/components/goe_charger/number.py b/homeassistant/components/goe_charger/number.py index 3bb9e872c35..18d41da5d3d 100644 --- a/homeassistant/components/goe_charger/number.py +++ b/homeassistant/components/goe_charger/number.py @@ -14,18 +14,22 @@ from .common import GoeChargerHub _LOGGER = logging.getLogger(__name__) + async def async_setup_entry(hass: HomeAssistant, config_entry: ConfigEntry, async_add_entities) -> None: coordinator = hass.data[DOMAIN][config_entry.entry_id] serial = config_entry.data["serial"] async_add_entities([ - GoeChargerNumber(coordinator, config_entry, "Requested current", serial, "requested_current", ELECTRIC_CURRENT_AMPERE, DEVICE_CLASS_CURRENT, "amp") + GoeChargerNumber(coordinator, config_entry, "Requested current", serial, "requested_current", + ELECTRIC_CURRENT_AMPERE, DEVICE_CLASS_CURRENT, "amp") ]) + class GoeChargerNumber(CoordinatorEntity, NumberEntity): """Representation of a Sensor.""" - def __init__(self, coordinator: DataUpdateCoordinator, config_entry: ConfigEntry, name: str, serial: str, unique_id: str, unit_of_measurement: str, device_class: str | None, key: str): + def __init__(self, coordinator: DataUpdateCoordinator, config_entry: ConfigEntry, name: str, serial: str, + unique_id: str, unit_of_measurement: str, device_class: str | None, key: str): """Pass coordinator to CoordinatorEntity.""" super().__init__(coordinator) self._config_entry = config_entry @@ -59,7 +63,9 @@ class GoeChargerNumber(CoordinatorEntity, NumberEntity): @property def available(self) -> bool: """Return True if entity is available.""" - return self.coordinator.data is not None and self._key in self.coordinator.data + return (self.coordinator.data is not None and + self._key in self.coordinator.data and + self.coordinator.data[self._key] is not None) @property def value(self) -> float: @@ -84,7 +90,8 @@ class GoeChargerNumber(CoordinatorEntity, NumberEntity): async def async_set_value(self, value: float) -> None: """Update the current value.""" - hub = GoeChargerHub(self._config_entry.data["host"]) + hub = GoeChargerHub(self._config_entry.data["secure"], self._config_entry.data["host"], + self._config_entry.data["pathprefix"]) await hub.set_data(self.hass, { self._key: int(value) }) @@ -99,8 +106,5 @@ class GoeChargerNumber(CoordinatorEntity, NumberEntity): def device_info(self): """Get attributes about the device.""" return { - "identifiers": {(DOMAIN, self._serial)}, - #"name": self._device.label, - #"model": self._device.device_type_name, - #"manufacturer": "Unavailable", + "identifiers": {(DOMAIN, self._serial)} } diff --git a/homeassistant/components/goe_charger/select.py b/homeassistant/components/goe_charger/select.py index 960137817cc..e94200f613c 100644 --- a/homeassistant/components/goe_charger/select.py +++ b/homeassistant/components/goe_charger/select.py @@ -14,6 +14,7 @@ from .common import GoeChargerHub _LOGGER = logging.getLogger(__name__) + async def async_setup_entry(hass: HomeAssistant, config_entry: ConfigEntry, async_add_entities) -> None: coordinator = hass.data[DOMAIN][config_entry.entry_id] serial = config_entry.data["serial"] @@ -34,21 +35,24 @@ async def async_setup_entry(hass: HomeAssistant, config_entry: ConfigEntry, asyn 0: "Open", 1: "Wait" }), - GoeChargerSelect(coordinator, config_entry, "Force state", serial, "force_state", None, None, "acs", { + GoeChargerSelect(coordinator, config_entry, "Force state", serial, "force_state", None, None, "frc", { 0: "Neutral", 1: "Off", 2: "On" }), - GoeChargerSelect(coordinator, config_entry, "Phase switch mode", serial, "phase_switch_mode", None, None, "psm", { - 1: "Force_1", - 2: "Force_3" - }) + GoeChargerSelect(coordinator, config_entry, "Phase switch mode", serial, "phase_switch_mode", None, None, "psm", + { + 1: "Force_1", + 2: "Force_3" + }) ]) + class GoeChargerSelect(CoordinatorEntity, SelectEntity): """Representation of a Sensor.""" - def __init__(self, coordinator: DataUpdateCoordinator, config_entry: ConfigEntry, name: str, serial: str, unique_id: str, unit_of_measurement: str, device_class: str | None, key: str, options: dict[int, str]): + def __init__(self, coordinator: DataUpdateCoordinator, config_entry: ConfigEntry, name: str, serial: str, + unique_id: str, unit_of_measurement: str, device_class: str | None, key: str, options: dict[int, str]): """Pass coordinator to CoordinatorEntity.""" super().__init__(coordinator) self._name = name @@ -83,7 +87,9 @@ class GoeChargerSelect(CoordinatorEntity, SelectEntity): @property def available(self) -> bool: """Return True if entity is available.""" - return self.coordinator.data is not None and self._key in self.coordinator.data + return (self.coordinator.data is not None and + self._key in self.coordinator.data and + self.coordinator.data[self._key] is not None) @property def current_option(self) -> str | None: @@ -111,7 +117,8 @@ class GoeChargerSelect(CoordinatorEntity, SelectEntity): index = val_list.index(option) - hub = GoeChargerHub(self._config_entry.data["host"]) + hub = GoeChargerHub(self._config_entry.data["secure"], self._config_entry.data["host"], + self._config_entry.data["pathprefix"]) await hub.set_data(self.hass, { self._key: key_list[index] }) @@ -126,8 +133,5 @@ class GoeChargerSelect(CoordinatorEntity, SelectEntity): def device_info(self): """Get attributes about the device.""" return { - "identifiers": {(DOMAIN, self._serial)}, - #"name": self._device.label, - #"model": self._device.device_type_name, - #"manufacturer": "Unavailable", + "identifiers": {(DOMAIN, self._serial)} } diff --git a/homeassistant/components/goe_charger/sensor.py b/homeassistant/components/goe_charger/sensor.py index 98ea73dced1..ff1a1173ca7 100644 --- a/homeassistant/components/goe_charger/sensor.py +++ b/homeassistant/components/goe_charger/sensor.py @@ -2,12 +2,15 @@ from __future__ import annotations import logging -from typing import Any +from typing import Final from homeassistant.core import HomeAssistant from homeassistant.config_entries import ConfigEntry -from homeassistant.const import (ELECTRIC_POTENTIAL_VOLT, ELECTRIC_CURRENT_AMPERE, POWER_WATT, POWER_KILO_WATT, FREQUENCY_HERTZ, ENERGY_WATT_HOUR, ENERGY_KILO_WATT_HOUR, TEMP_CELSIUS, - SIGNAL_STRENGTH_DECIBELS, DEVICE_CLASS_CURRENT, DEVICE_CLASS_ENERGY, DEVICE_CLASS_POWER_FACTOR, DEVICE_CLASS_POWER, DEVICE_CLASS_SIGNAL_STRENGTH, DEVICE_CLASS_TEMPERATURE, DEVICE_CLASS_VOLTAGE) +from homeassistant.const import (ELECTRIC_POTENTIAL_VOLT, ELECTRIC_CURRENT_AMPERE, POWER_WATT, POWER_KILO_WATT, + FREQUENCY_HERTZ, ENERGY_WATT_HOUR, ENERGY_KILO_WATT_HOUR, TEMP_CELSIUS, + SIGNAL_STRENGTH_DECIBELS, DEVICE_CLASS_CURRENT, DEVICE_CLASS_ENERGY, + DEVICE_CLASS_POWER_FACTOR, DEVICE_CLASS_POWER, DEVICE_CLASS_SIGNAL_STRENGTH, + DEVICE_CLASS_TEMPERATURE, DEVICE_CLASS_VOLTAGE) from homeassistant.helpers.update_coordinator import CoordinatorEntity, DataUpdateCoordinator from homeassistant.components.sensor import STATE_CLASS_MEASUREMENT, STATE_CLASS_TOTAL_INCREASING from homeassistant.components.sensor import SensorEntity @@ -18,18 +21,19 @@ POWER_FACTOR: Final = "%" _LOGGER = logging.getLogger(__name__) + async def async_setup_entry(hass: HomeAssistant, config_entry: ConfigEntry, async_add_entities) -> None: coordinator = hass.data[DOMAIN][config_entry.entry_id] serial = config_entry.data["serial"] def car_state_data(data): car_state_texts = { - 0: "Unknown", - 1: "Idle", - 2: "Charging", - 3: "WaitCar", - 4: "Complete", - 5: "Error" + 0: "Unknown", + 1: "Idle", + 2: "Charging", + 3: "WaitCar", + 4: "Complete", + 5: "Error" } if data["car"] in car_state_texts: @@ -39,16 +43,16 @@ async def async_setup_entry(hass: HomeAssistant, config_entry: ConfigEntry, asyn def error_data(data): error_texts = { - 0: "None", - 1: "FiAc", - 2: "FiDc", - 3: "Phase", - 4: "Overvolt", - 5: "Overamp", - 6: "Diode", - 7: "PpInvalid", - 8: "GndInvalid", - 9: "ContactorStuck", + 0: "None", + 1: "FiAc", + 2: "FiDc", + 3: "Phase", + 4: "Overvolt", + 5: "Overamp", + 6: "Diode", + 7: "PpInvalid", + 8: "GndInvalid", + 9: "ContactorStuck", 10: "ContactorMiss", 11: "FiUnknown", 12: "Unknown", @@ -70,16 +74,16 @@ async def async_setup_entry(hass: HomeAssistant, config_entry: ConfigEntry, asyn def model_status_data(data): model_status_texts = { - 0: "NotChargingBecauseNoChargeCtrlData", - 1: "NotChargingBecauseOvertemperature", - 2: "NotChargingBecauseAccessControlWait", - 3: "ChargingBecauseForceStateOn", - 4: "NotChargingBecauseForceStateOff", - 5: "NotChargingBecauseScheduler", - 6: "NotChargingBecauseEnergyLimit", - 7: "ChargingBecauseAwattarPriceLow", - 8: "ChargingBecauseAutomaticStopTestLadung", - 9: "ChargingBecauseAutomaticStopNotEnoughTime", + 0: "NotChargingBecauseNoChargeCtrlData", + 1: "NotChargingBecauseOvertemperature", + 2: "NotChargingBecauseAccessControlWait", + 3: "ChargingBecauseForceStateOn", + 4: "NotChargingBecauseForceStateOff", + 5: "NotChargingBecauseScheduler", + 6: "NotChargingBecauseEnergyLimit", + 7: "ChargingBecauseAwattarPriceLow", + 8: "ChargingBecauseAutomaticStopTestLadung", + 9: "ChargingBecauseAutomaticStopNotEnoughTime", 10: "ChargingBecauseAutomaticStop", 11: "ChargingBecauseAutomaticStopNoClock", 12: "ChargingBecausePvSurplus", @@ -102,39 +106,74 @@ async def async_setup_entry(hass: HomeAssistant, config_entry: ConfigEntry, asyn return "Unknown (" + str(data["modelStatus"]) + ")" async_add_entities([ - GoeChargerSensor(coordinator, "Voltage L1", serial, "voltage_l1", ELECTRIC_POTENTIAL_VOLT, DEVICE_CLASS_VOLTAGE, STATE_CLASS_MEASUREMENT, "nrg", lambda data: data["nrg"][0] ), - GoeChargerSensor(coordinator, "Voltage L2", serial, "voltage_l2", ELECTRIC_POTENTIAL_VOLT, DEVICE_CLASS_VOLTAGE, STATE_CLASS_MEASUREMENT, "nrg", lambda data: data["nrg"][1] ), - GoeChargerSensor(coordinator, "Voltage L3", serial, "voltage_l3", ELECTRIC_POTENTIAL_VOLT, DEVICE_CLASS_VOLTAGE, STATE_CLASS_MEASUREMENT, "nrg", lambda data: data["nrg"][2] ), - GoeChargerSensor(coordinator, "Voltage N", serial, "voltage_n", ELECTRIC_POTENTIAL_VOLT, DEVICE_CLASS_VOLTAGE, STATE_CLASS_MEASUREMENT, "nrg", lambda data: data["nrg"][3] ), - GoeChargerSensor(coordinator, "Current L1", serial, "current_l1", ELECTRIC_CURRENT_AMPERE, DEVICE_CLASS_CURRENT, STATE_CLASS_MEASUREMENT, "nrg", lambda data: data["nrg"][4] ), - GoeChargerSensor(coordinator, "Current L2", serial, "current_l2", ELECTRIC_CURRENT_AMPERE, DEVICE_CLASS_CURRENT, STATE_CLASS_MEASUREMENT, "nrg", lambda data: data["nrg"][5] ), - GoeChargerSensor(coordinator, "Current L3", serial, "current_l3", ELECTRIC_CURRENT_AMPERE, DEVICE_CLASS_CURRENT, STATE_CLASS_MEASUREMENT, "nrg", lambda data: data["nrg"][6] ), - GoeChargerSensorNative(coordinator, "Power L1", serial, "power_l1", POWER_KILO_WATT, DEVICE_CLASS_POWER, STATE_CLASS_MEASUREMENT, "nrg", (lambda data: data["nrg"][7] / 1000) , POWER_KILO_WATT, lambda data: data["nrg"][7] ), - GoeChargerSensorNative(coordinator, "Power L2", serial, "power_l2", POWER_KILO_WATT, DEVICE_CLASS_POWER, STATE_CLASS_MEASUREMENT, "nrg", (lambda data: data["nrg"][8] / 1000) , POWER_KILO_WATT, lambda data: data["nrg"][8] ), - GoeChargerSensorNative(coordinator, "Power L3", serial, "power_l3", POWER_KILO_WATT, DEVICE_CLASS_POWER, STATE_CLASS_MEASUREMENT, "nrg", (lambda data: data["nrg"][9] / 1000) , POWER_KILO_WATT, lambda data: data["nrg"][9] ), - GoeChargerSensorNative(coordinator, "Power N", serial, "power_n", POWER_KILO_WATT, DEVICE_CLASS_POWER, STATE_CLASS_MEASUREMENT, "nrg", (lambda data: data["nrg"][10] / 1000) , POWER_KILO_WATT, lambda data: data["nrg"][10] ), - GoeChargerSensorNative(coordinator, "Power Total", serial, "power_total", POWER_KILO_WATT, DEVICE_CLASS_POWER, STATE_CLASS_MEASUREMENT, "nrg", (lambda data: data["nrg"][11] / 1000) , POWER_KILO_WATT, lambda data: data["nrg"][11] ), - GoeChargerSensor(coordinator, "Powerfactor L1", serial, "powerfactor_l1", POWER_FACTOR, DEVICE_CLASS_POWER_FACTOR, STATE_CLASS_MEASUREMENT, "nrg", lambda data: data["nrg"][12] ), - GoeChargerSensor(coordinator, "Powerfactor L2", serial, "powerfactor_l2", POWER_FACTOR, DEVICE_CLASS_POWER_FACTOR, STATE_CLASS_MEASUREMENT, "nrg", lambda data: data["nrg"][13] ), - GoeChargerSensor(coordinator, "Powerfactor L3", serial, "powerfactor_l3", POWER_FACTOR, DEVICE_CLASS_POWER_FACTOR, STATE_CLASS_MEASUREMENT, "nrg", lambda data: data["nrg"][14] ), - GoeChargerSensor(coordinator, "Powerfactor N", serial, "powerfactor_n", POWER_FACTOR, DEVICE_CLASS_POWER_FACTOR, STATE_CLASS_MEASUREMENT, "nrg", lambda data: data["nrg"][15] ), - GoeChargerSensor(coordinator, "Frequency", serial, "frequency", FREQUENCY_HERTZ, None, STATE_CLASS_MEASUREMENT, "fhz", lambda data: data["fhz"] ), - GoeChargerSensorNative(coordinator, "Charged", serial, "charged", ENERGY_KILO_WATT_HOUR, DEVICE_CLASS_ENERGY, STATE_CLASS_TOTAL_INCREASING, "wh", (lambda data: data["wh"] / 1000) , POWER_KILO_WATT, lambda data: data["wh"] ), - GoeChargerSensorNative(coordinator, "Charged total", serial, "charged_total", ENERGY_KILO_WATT_HOUR, DEVICE_CLASS_ENERGY, STATE_CLASS_TOTAL_INCREASING, "eto", (lambda data: data["eto"] / 1000) , POWER_KILO_WATT, lambda data: data["eto"] ), - GoeChargerSensor(coordinator, "Temperature 1", serial, "temperature_1", TEMP_CELSIUS, DEVICE_CLASS_TEMPERATURE, STATE_CLASS_MEASUREMENT, "tma", lambda data: data["tma"][0] ), - GoeChargerSensor(coordinator, "Temperature 2", serial, "temperature_2", TEMP_CELSIUS, DEVICE_CLASS_TEMPERATURE, STATE_CLASS_MEASUREMENT, "tma", lambda data: data["tma"][1] ), - GoeChargerSensor(coordinator, "WiFi RSSI", serial, "wifi_rssi", SIGNAL_STRENGTH_DECIBELS, DEVICE_CLASS_SIGNAL_STRENGTH, STATE_CLASS_MEASUREMENT, "rssi", lambda data: data["rssi"] ), - GoeChargerSensor(coordinator, "Cable current limit", serial, "cable_current_limit", ELECTRIC_CURRENT_AMPERE, DEVICE_CLASS_CURRENT, None, "cbl", lambda data: data["cbl"]), - GoeChargerSensor(coordinator, "Allowed current", serial, "allowed_current", ELECTRIC_CURRENT_AMPERE, DEVICE_CLASS_CURRENT, None, "acu", lambda data: "" if data["acu"] is None else data["acu"] ), - GoeChargerSensor(coordinator, "Car state", serial, "car_state", None, None, None, "car", car_state_data ), - GoeChargerSensor(coordinator, "Error", serial, "error", None, None, None, "err", error_data ), - GoeChargerSensor(coordinator, "Model status", serial, "model_status", None, None, None, "modelStatus", model_status_data ), + GoeChargerSensor(coordinator, "Voltage L1", serial, "voltage_l1", ELECTRIC_POTENTIAL_VOLT, DEVICE_CLASS_VOLTAGE, + STATE_CLASS_MEASUREMENT, "nrg", lambda data: data["nrg"][0]), + GoeChargerSensor(coordinator, "Voltage L2", serial, "voltage_l2", ELECTRIC_POTENTIAL_VOLT, DEVICE_CLASS_VOLTAGE, + STATE_CLASS_MEASUREMENT, "nrg", lambda data: data["nrg"][1]), + GoeChargerSensor(coordinator, "Voltage L3", serial, "voltage_l3", ELECTRIC_POTENTIAL_VOLT, DEVICE_CLASS_VOLTAGE, + STATE_CLASS_MEASUREMENT, "nrg", lambda data: data["nrg"][2]), + GoeChargerSensor(coordinator, "Voltage N", serial, "voltage_n", ELECTRIC_POTENTIAL_VOLT, DEVICE_CLASS_VOLTAGE, + STATE_CLASS_MEASUREMENT, "nrg", lambda data: data["nrg"][3]), + GoeChargerSensor(coordinator, "Current L1", serial, "current_l1", ELECTRIC_CURRENT_AMPERE, DEVICE_CLASS_CURRENT, + STATE_CLASS_MEASUREMENT, "nrg", lambda data: data["nrg"][4]), + GoeChargerSensor(coordinator, "Current L2", serial, "current_l2", ELECTRIC_CURRENT_AMPERE, DEVICE_CLASS_CURRENT, + STATE_CLASS_MEASUREMENT, "nrg", lambda data: data["nrg"][5]), + GoeChargerSensor(coordinator, "Current L3", serial, "current_l3", ELECTRIC_CURRENT_AMPERE, DEVICE_CLASS_CURRENT, + STATE_CLASS_MEASUREMENT, "nrg", lambda data: data["nrg"][6]), + GoeChargerSensorNative(coordinator, "Power L1", serial, "power_l1", POWER_KILO_WATT, DEVICE_CLASS_POWER, + STATE_CLASS_MEASUREMENT, "nrg", (lambda data: data["nrg"][7] / 1000), POWER_KILO_WATT, + lambda data: data["nrg"][7]), + GoeChargerSensorNative(coordinator, "Power L2", serial, "power_l2", POWER_KILO_WATT, DEVICE_CLASS_POWER, + STATE_CLASS_MEASUREMENT, "nrg", (lambda data: data["nrg"][8] / 1000), POWER_KILO_WATT, + lambda data: data["nrg"][8]), + GoeChargerSensorNative(coordinator, "Power L3", serial, "power_l3", POWER_KILO_WATT, DEVICE_CLASS_POWER, + STATE_CLASS_MEASUREMENT, "nrg", (lambda data: data["nrg"][9] / 1000), POWER_KILO_WATT, + lambda data: data["nrg"][9]), + GoeChargerSensorNative(coordinator, "Power N", serial, "power_n", POWER_KILO_WATT, DEVICE_CLASS_POWER, + STATE_CLASS_MEASUREMENT, "nrg", (lambda data: data["nrg"][10] / 1000), POWER_KILO_WATT, + lambda data: data["nrg"][10]), + GoeChargerSensorNative(coordinator, "Power Total", serial, "power_total", POWER_KILO_WATT, DEVICE_CLASS_POWER, + STATE_CLASS_MEASUREMENT, "nrg", (lambda data: data["nrg"][11] / 1000), POWER_KILO_WATT, + lambda data: data["nrg"][11]), + GoeChargerSensor(coordinator, "Powerfactor L1", serial, "powerfactor_l1", POWER_FACTOR, + DEVICE_CLASS_POWER_FACTOR, STATE_CLASS_MEASUREMENT, "nrg", lambda data: data["nrg"][12]), + GoeChargerSensor(coordinator, "Powerfactor L2", serial, "powerfactor_l2", POWER_FACTOR, + DEVICE_CLASS_POWER_FACTOR, STATE_CLASS_MEASUREMENT, "nrg", lambda data: data["nrg"][13]), + GoeChargerSensor(coordinator, "Powerfactor L3", serial, "powerfactor_l3", POWER_FACTOR, + DEVICE_CLASS_POWER_FACTOR, STATE_CLASS_MEASUREMENT, "nrg", lambda data: data["nrg"][14]), + GoeChargerSensor(coordinator, "Powerfactor N", serial, "powerfactor_n", POWER_FACTOR, DEVICE_CLASS_POWER_FACTOR, + STATE_CLASS_MEASUREMENT, "nrg", lambda data: data["nrg"][15]), + GoeChargerSensor(coordinator, "Frequency", serial, "frequency", FREQUENCY_HERTZ, None, STATE_CLASS_MEASUREMENT, + "fhz", lambda data: data["fhz"]), + GoeChargerSensorNative(coordinator, "Charged", serial, "charged", ENERGY_KILO_WATT_HOUR, DEVICE_CLASS_ENERGY, + STATE_CLASS_TOTAL_INCREASING, "wh", (lambda data: data["wh"] / 1000), POWER_KILO_WATT, + lambda data: data["wh"]), + GoeChargerSensorNative(coordinator, "Charged total", serial, "charged_total", ENERGY_KILO_WATT_HOUR, + DEVICE_CLASS_ENERGY, STATE_CLASS_TOTAL_INCREASING, "eto", + (lambda data: data["eto"] / 1000), POWER_KILO_WATT, lambda data: data["eto"]), + GoeChargerSensor(coordinator, "Temperature 1", serial, "temperature_1", TEMP_CELSIUS, DEVICE_CLASS_TEMPERATURE, + STATE_CLASS_MEASUREMENT, "tma", lambda data: data["tma"][0]), + GoeChargerSensor(coordinator, "Temperature 2", serial, "temperature_2", TEMP_CELSIUS, DEVICE_CLASS_TEMPERATURE, + STATE_CLASS_MEASUREMENT, "tma", lambda data: data["tma"][1]), + GoeChargerSensor(coordinator, "WiFi RSSI", serial, "wifi_rssi", SIGNAL_STRENGTH_DECIBELS, + DEVICE_CLASS_SIGNAL_STRENGTH, STATE_CLASS_MEASUREMENT, "rssi", lambda data: data["rssi"]), + GoeChargerSensor(coordinator, "Cable current limit", serial, "cable_current_limit", ELECTRIC_CURRENT_AMPERE, + DEVICE_CLASS_CURRENT, None, "cbl", lambda data: data["cbl"]), + GoeChargerSensor(coordinator, "Allowed current", serial, "allowed_current", ELECTRIC_CURRENT_AMPERE, + DEVICE_CLASS_CURRENT, None, "acu", lambda data: "" if data["acu"] is None else data["acu"]), + GoeChargerSensor(coordinator, "Car state", serial, "car_state", None, None, None, "car", car_state_data), + GoeChargerSensor(coordinator, "Error", serial, "error", None, None, None, "err", error_data), + GoeChargerSensor(coordinator, "Model status", serial, "model_status", None, None, None, "modelStatus", + model_status_data), ]) + class GoeChargerSensor(CoordinatorEntity, SensorEntity): """Representation of a Sensor.""" - def __init__(self, coordinator: DataUpdateCoordinator, name: str, serial: str, unique_id: str, unit_of_measurement: str | None, device_class: str | None, state_class: str | None, key: str, state_cb): + def __init__(self, coordinator: DataUpdateCoordinator, name: str, serial: str, unique_id: str, + unit_of_measurement: str | None, device_class: str | None, state_class: str | None, key: str, + state_cb): """Pass coordinator to CoordinatorEntity.""" super().__init__(coordinator) self._name = name @@ -159,7 +198,9 @@ class GoeChargerSensor(CoordinatorEntity, SensorEntity): @property def available(self) -> bool: """Return True if entity is available.""" - return self.coordinator.data is not None and self._key in self.coordinator.data + return (self.coordinator.data is not None and + self._key in self.coordinator.data and + self.coordinator.data[self._key] is not None) @property def state(self): @@ -191,18 +232,19 @@ class GoeChargerSensor(CoordinatorEntity, SensorEntity): def device_info(self): """Get attributes about the device.""" return { - "identifiers": {(DOMAIN, self._serial)}, - #"name": self._device.label, - #"model": self._device.device_type_name, - #"manufacturer": "Unavailable", + "identifiers": {(DOMAIN, self._serial)} } + class GoeChargerSensorNative(GoeChargerSensor): """Representation of a Sensor with separated native unit/value.""" - def __init__(self, coordinator: DataUpdateCoordinator, name: str, serial: str, unique_id: str, unit_of_measurement: str | None, device_class: str | None, state_class: str | None, key: str, state_cb, native_unit_of_measurement: str | None, native_state_cb): + def __init__(self, coordinator: DataUpdateCoordinator, name: str, serial: str, unique_id: str, + unit_of_measurement: str | None, device_class: str | None, state_class: str | None, key: str, state_cb, + native_unit_of_measurement: str | None, native_state_cb): """Pass coordinator to GoeChargerSensor.""" - super().__init__(coordinator, name, serial, unique_id, unit_of_measurement, device_class, state_class, key, state_cb) + super().__init__(coordinator, name, serial, unique_id, unit_of_measurement, device_class, state_class, key, + state_cb) self._native_unit_of_measurement = native_unit_of_measurement self._native_state_cb = native_state_cb diff --git a/homeassistant/components/goe_charger/strings.json b/homeassistant/components/goe_charger/strings.json index 6150ce51f98..01f9763eb3f 100644 --- a/homeassistant/components/goe_charger/strings.json +++ b/homeassistant/components/goe_charger/strings.json @@ -3,13 +3,17 @@ "step": { "user": { "data": { + "secure": "[%key:common::config_flow::data::secure%]", "host": "[%key:common::config_flow::data::host%]", + "pathprefix": "[%key:common::config_flow::data::pathprefix%]", "interval": "[%key:common::config_flow::data::interval%]" } }, "init": { "data": { + "secure": "[%key:common::config_flow::data::secure%]", "host": "[%key:common::config_flow::data::host%]", + "pathprefix": "[%key:common::config_flow::data::pathprefix%]", "interval": "[%key:common::config_flow::data::interval%]" } } diff --git a/homeassistant/components/goe_charger/translations/en.json b/homeassistant/components/goe_charger/translations/en.json index 9d61ceb3131..3ff543ef482 100644 --- a/homeassistant/components/goe_charger/translations/en.json +++ b/homeassistant/components/goe_charger/translations/en.json @@ -14,13 +14,17 @@ "step": { "user": { "data": { + "secure": "Secure (ssl/https)", "host": "Host", + "pathprefix": "Path prefix (for reverse proxies; typical empty)", "interval": "Interval" } }, "init": { "data": { + "secure": "Secure (ssl/https)", "host": "Host", + "pathprefix": "Path prefix (for reverse proxies; typical empty)", "interval": "Interval" } }