diff --git a/custom_components/ocpp/api.py b/custom_components/ocpp/api.py index 91d953c5..a2a58005 100644 --- a/custom_components/ocpp/api.py +++ b/custom_components/ocpp/api.py @@ -19,10 +19,6 @@ from homeassistant.core import HomeAssistant from homeassistant.helpers import device_registry, entity_component, entity_registry import homeassistant.helpers.config_validation as cv -import voluptuous as vol -import websockets.protocol -import websockets.server - from ocpp.exceptions import NotImplementedError from ocpp.messages import CallError from ocpp.routing import on @@ -51,6 +47,9 @@ UnitOfMeasure, UnlockStatus, ) +import voluptuous as vol +import websockets.protocol +import websockets.server from .const import ( CONF_AUTH_LIST, @@ -64,6 +63,7 @@ CONF_IDLE_INTERVAL, CONF_METER_INTERVAL, CONF_MONITORED_VARIABLES, + CONF_MONITORED_VARIABLES_AUTOCONFIG, CONF_PORT, CONF_SKIP_SCHEMA_VALIDATION, CONF_SSL, @@ -83,6 +83,7 @@ DEFAULT_IDLE_INTERVAL, DEFAULT_MEASURAND, DEFAULT_METER_INTERVAL, + DEFAULT_MONITORED_VARIABLES_AUTOCONFIG, DEFAULT_PORT, DEFAULT_POWER_UNIT, DEFAULT_SKIP_SCHEMA_VALIDATION, @@ -469,30 +470,46 @@ async def handle_set_charge_rate(call): all_measurands = self.entry.data.get( CONF_MONITORED_VARIABLES, DEFAULT_MEASURAND ) + autodetect_measurands = self.entry.data.get( + CONF_MONITORED_VARIABLES_AUTOCONFIG, + DEFAULT_MONITORED_VARIABLES_AUTOCONFIG, + ) + key = ckey.meter_values_sampled_data.value - try: - chgr_measurands = await self.get_configuration(key) - except Exception: - _LOGGER.debug( - f"'{self.id}' had error while returning measurands, ignoring" - ) - chgr_measurands = all_measurands - - accepted_measurands = [] - cfg_ok = [ - ConfigurationStatus.accepted, - ConfigurationStatus.reboot_required, - ] - - for measurand in all_measurands.split(","): - _LOGGER.debug(f"'{self.id}' trying measurand: '{measurand}'") - req = call.ChangeConfiguration(key=key, value=measurand) - resp = await self.call(req) - if resp.status in cfg_ok: - _LOGGER.debug(f"'{self.id}' adding measurand: '{measurand}'") - accepted_measurands.append(measurand) - - accepted_measurands = ",".join(accepted_measurands) + + if autodetect_measurands: + accepted_measurands = [] + cfg_ok = [ + ConfigurationStatus.accepted, + ConfigurationStatus.reboot_required, + ] + + for measurand in all_measurands.split(","): + _LOGGER.debug(f"'{self.id}' trying measurand: '{measurand}'") + req = call.ChangeConfiguration(key=key, value=measurand) + resp = await self.call(req) + if resp.status in cfg_ok: + _LOGGER.debug(f"'{self.id}' adding measurand: '{measurand}'") + accepted_measurands.append(measurand) + + accepted_measurands = ",".join(accepted_measurands) + else: + accepted_measurands = all_measurands + + # Quirk: + # Workaround for a bug on chargers that have invalid MeterValuesSampledData + # configuration and reboot while the server requests MeterValuesSampledData. + # By setting the configuration directly without checking current configuration + # as done when calling self.configure, the server avoids charger reboot. + # Corresponding issue: https://github.com/lbbrhzn/ocpp/issues/1275 + if len(accepted_measurands) > 0: + req = call.ChangeConfiguration(key=key, value=accepted_measurands) + resp = await self.call(req) + _LOGGER.debug( + f"'{self.id}' measurands set manually to {accepted_measurands}" + ) + + chgr_measurands = await self.get_configuration(key) if len(accepted_measurands) > 0: _LOGGER.debug( diff --git a/custom_components/ocpp/config_flow.py b/custom_components/ocpp/config_flow.py index 65b13bb0..802a3a14 100644 --- a/custom_components/ocpp/config_flow.py +++ b/custom_components/ocpp/config_flow.py @@ -12,6 +12,7 @@ CONF_MAX_CURRENT, CONF_METER_INTERVAL, CONF_MONITORED_VARIABLES, + CONF_MONITORED_VARIABLES_AUTOCONFIG, CONF_PORT, CONF_SKIP_SCHEMA_VALIDATION, CONF_SSL, @@ -27,8 +28,10 @@ DEFAULT_HOST, DEFAULT_IDLE_INTERVAL, DEFAULT_MAX_CURRENT, + DEFAULT_MEASURAND, DEFAULT_METER_INTERVAL, DEFAULT_MONITORED_VARIABLES, + DEFAULT_MONITORED_VARIABLES_AUTOCONFIG, DEFAULT_PORT, DEFAULT_SKIP_SCHEMA_VALIDATION, DEFAULT_SSL, @@ -39,6 +42,7 @@ DEFAULT_WEBSOCKET_PING_TIMEOUT, DEFAULT_WEBSOCKET_PING_TRIES, DOMAIN, + MEASURANDS, ) STEP_USER_DATA_SCHEMA = vol.Schema( @@ -52,8 +56,9 @@ vol.Required(CONF_CPID, default=DEFAULT_CPID): str, vol.Required(CONF_MAX_CURRENT, default=DEFAULT_MAX_CURRENT): int, vol.Required( - CONF_MONITORED_VARIABLES, default=DEFAULT_MONITORED_VARIABLES - ): str, + CONF_MONITORED_VARIABLES_AUTOCONFIG, + default=DEFAULT_MONITORED_VARIABLES_AUTOCONFIG, + ): bool, vol.Required(CONF_METER_INTERVAL, default=DEFAULT_METER_INTERVAL): int, vol.Required(CONF_IDLE_INTERVAL, default=DEFAULT_IDLE_INTERVAL): int, vol.Required( @@ -77,6 +82,13 @@ } ) +STEP_USER_MEASURANDS_SCHEMA = vol.Schema( + { + vol.Required(m, default=(True if m == DEFAULT_MEASURAND else False)): bool + for m in MEASURANDS + } +) + class ConfigFlow(config_entries.ConfigFlow, domain=DOMAIN): """Handle a config flow for OCPP.""" @@ -93,11 +105,33 @@ async def async_step_user(self, user_input=None): errors: dict[str, str] = {} if user_input is not None: - # Todo: validate the user input self._data = user_input - self._data[CONF_MONITORED_VARIABLES] = DEFAULT_MONITORED_VARIABLES - return self.async_create_entry(title=self._data[CONF_CSID], data=self._data) + if user_input[CONF_MONITORED_VARIABLES_AUTOCONFIG]: + self._data[CONF_MONITORED_VARIABLES] = DEFAULT_MONITORED_VARIABLES + return self.async_create_entry( + title=self._data[CONF_CSID], data=self._data + ) + return await self.async_step_measurands() return self.async_show_form( step_id="user", data_schema=STEP_USER_DATA_SCHEMA, errors=errors ) + + async def async_step_measurands(self, user_input=None): + """Select the measurands to be shown.""" + + errors: dict[str, str] = {} + if user_input is not None: + selected_measurands = [m for m, value in user_input.items() if value] + if set(selected_measurands).issubset(set(MEASURANDS)): + self._data[CONF_MONITORED_VARIABLES] = ",".join(selected_measurands) + return self.async_create_entry( + title=self._data[CONF_CSID], data=self._data + ) + else: + errors["base"] = "measurand" + return self.async_show_form( + step_id="measurands", + data_schema=STEP_USER_MEASURANDS_SCHEMA, + errors=errors, + ) diff --git a/custom_components/ocpp/const.py b/custom_components/ocpp/const.py index d8dce89f..74e3b2cf 100644 --- a/custom_components/ocpp/const.py +++ b/custom_components/ocpp/const.py @@ -5,7 +5,6 @@ import homeassistant.components.input_number as input_number from homeassistant.components.sensor import SensorDeviceClass import homeassistant.const as ha - from ocpp.v16.enums import Measurand, UnitOfMeasure CONF_AUTH_LIST = "authorization_list" @@ -22,6 +21,7 @@ CONF_METER_INTERVAL = "meter_interval" CONF_MODE = ha.CONF_MODE CONF_MONITORED_VARIABLES = ha.CONF_MONITORED_VARIABLES +CONF_MONITORED_VARIABLES_AUTOCONFIG = "monitored_variables_autoconfig" CONF_NAME = ha.CONF_NAME CONF_PASSWORD = ha.CONF_PASSWORD CONF_PORT = ha.CONF_PORT @@ -96,6 +96,7 @@ ] DEFAULT_MEASURAND = Measurand.energy_active_import_register.value DEFAULT_MONITORED_VARIABLES = ",".join(MEASURANDS) +DEFAULT_MONITORED_VARIABLES_AUTOCONFIG = True DEFAULT_ENERGY_UNIT = UnitOfMeasure.wh.value DEFAULT_POWER_UNIT = UnitOfMeasure.w.value HA_ENERGY_UNIT = UnitOfMeasure.kwh.value diff --git a/custom_components/ocpp/switch.py b/custom_components/ocpp/switch.py index f46f6adc..fb486896 100644 --- a/custom_components/ocpp/switch.py +++ b/custom_components/ocpp/switch.py @@ -12,7 +12,6 @@ ) from homeassistant.const import UnitOfPower from homeassistant.helpers.entity import DeviceInfo - from ocpp.v16.enums import ChargePointStatus from .api import CentralSystem diff --git a/custom_components/ocpp/translations/de.json b/custom_components/ocpp/translations/de.json index 2400971d..37b44537 100644 --- a/custom_components/ocpp/translations/de.json +++ b/custom_components/ocpp/translations/de.json @@ -24,28 +24,28 @@ "title": "OCPP-Messwerte", "description": "Wähle aus welche Messwerte in Home Assistant angezeigt werden sollen.", "data": { - "Current.Export": "Momentane Stromstärke vom E-Auto", - "Current.Import": "Momentaner Stromstärke zum E-Auto", - "Current.Offered": "Maximale dem E-Auto angebotene Stromstärke", - "Energy.Active.Export.Register": "In das Netz exportierte Wirkenergie", - "Energy.Active.Import.Register": "Aus dem Netz importierte Wirkenergie", - "Energy.Reactive.Export.Register": "In das Netz exportierte Blindenergie", - "Energy.Reactive.Import.Register": "Aus dem Netz importierte Blindenergie", - "Energy.Active.Export.Interval": "Im letzten Intervall in das Netz exportierte Wirkenergie", - "Energy.Active.Import.Interval": "Im letzten Intervall aus dem Netz importierte Wirkenergie", - "Energy.Reactive.Export.Interval": "Im letzten Intervall ins Netz exportierte Blindenergie", - "Energy.Reactive.Import.Interval": "Im letzten Intervall aus dem Netz importierte Blindenergie", - "Frequency": "Netzfrequenz", - "Power.Active.Export": "Von E-Auto exportierte momentane Wirkleistung", - "Power.Active.Import": "Von E-Auto importierte momentane Wirkleistung", - "Power.Factor": "Unmittelbarer Leistungsfaktor des gesamten Energieflusses", - "Power.Offered": "Maximale dem E-Auto angebotene Leistung", - "Power.Reactive.Export": "Von E-Auto exportierte momentane Blindleistung", - "Power.Reactive.Import": "Von E-Auto importierte momentane Blindleistung", - "RPM": "Lüfterdrehzahl in RPM", - "SoC": "Ladezustand des E-Autos in Prozent", - "Temperature": "Temperaturmesswert in der Ladestation", - "Voltage": "Momentane AC-Effektivspannung" + "Current.Export": "Current.Export: Momentane Stromstärke vom E-Auto", + "Current.Import": "Current.Import: Momentaner Stromstärke zum E-Auto", + "Current.Offered": "Current.Offered: Maximale dem E-Auto angebotene Stromstärke", + "Energy.Active.Export.Register": "Energy.Active.Export.Register: In das Netz exportierte Wirkenergie", + "Energy.Active.Import.Register": "Energy.Active.Import.Register: Aus dem Netz importierte Wirkenergie", + "Energy.Reactive.Export.Register": "Energy.Reactive.Export.Register: In das Netz exportierte Blindenergie", + "Energy.Reactive.Import.Register": "Energy.Reactive.Import.Register: Aus dem Netz importierte Blindenergie", + "Energy.Active.Export.Interval": "Energy.Active.Export.Interval: Im letzten Intervall in das Netz exportierte Wirkenergie", + "Energy.Active.Import.Interval": "Energy.Active.Import.Interval: Im letzten Intervall aus dem Netz importierte Wirkenergie", + "Energy.Reactive.Export.Interval": "Energy.Reactive.Export.Interval: Im letzten Intervall ins Netz exportierte Blindenergie", + "Energy.Reactive.Import.Interval": "Energy.Reactive.Import.Interval: Im letzten Intervall aus dem Netz importierte Blindenergie", + "Frequency": "Frequency: Netzfrequenz", + "Power.Active.Export": "Power.Active.Export: Von E-Auto exportierte momentane Wirkleistung", + "Power.Active.Import": "Power.Active.Import: Von E-Auto importierte momentane Wirkleistung", + "Power.Factor": "Power.Factor: Unmittelbarer Leistungsfaktor des gesamten Energieflusses", + "Power.Offered": "Power.Offered: Maximale dem E-Auto angebotene Leistung", + "Power.Reactive.Export": "Power.Reactive.Export: Von E-Auto exportierte momentane Blindleistung", + "Power.Reactive.Import": "Power.Reactive.Import: Von E-Auto importierte momentane Blindleistung", + "RPM": "RPM: Lüfterdrehzahl in RPM", + "SoC": "SoC: Ladezustand des E-Autos in Prozent", + "Temperature": "Temperature: Temperaturmesswert in der Ladestation", + "Voltage": "Voltage: Momentane AC-Effektivspannung" } } }, @@ -57,4 +57,4 @@ "single_instance_allowed": "Es ist nur eine Instanz erlaubt." } } -} +} \ No newline at end of file diff --git a/custom_components/ocpp/translations/en.json b/custom_components/ocpp/translations/en.json index 2f3940e5..0015e11b 100644 --- a/custom_components/ocpp/translations/en.json +++ b/custom_components/ocpp/translations/en.json @@ -14,6 +14,7 @@ "cpid": "Charge point identity", "max_current": "Maximum charging current", "meter_interval": "Charging sample interval (seconds)", + "monitored_variables_autoconfig": "Automatic detection of OCPP Measurands", "idle_interval": "Charger idle sampling interval (seconds)", "websocket_close_timeout": "Websocket close timeout (seconds)", "websocket_ping_tries": "Websocket successive times to try connection before closing", @@ -25,30 +26,30 @@ }, "measurands": { "title": "OCPP Measurands", - "description": "Select which measurand(s) should be shown in Home Assistant.", + "description": "Select which measurand(s) should be used in Home Assistant.", "data": { - "Current.Export": "Instantaneous current flow from EV", - "Current.Import": "Instantaneous current flow to EV", - "Current.Offered": "Maximum current offered to EV", - "Energy.Active.Export.Register": "Active energy exported to the grid", - "Energy.Active.Import.Register": "Active energy imported from the grid", - "Energy.Reactive.Export.Register": "Reactive energy exported to the grid", - "Energy.Reactive.Import.Register": "Reactive energy imported from the grid", - "Energy.Active.Export.Interval": "Active energy exported to the grid during last interval", - "Energy.Active.Import.Interval": "Active energy imported from the grid during last interval", - "Energy.Reactive.Export.Interval": "Reactive energy exported to the grid during last interval", - "Energy.Reactive.Import.Interval": "Reactive energy imported from the grid during last interval", - "Frequency": "Powerline frequency", - "Power.Active.Export": "Instantaneous active power exported by EV", - "Power.Active.Import": "Instantaneous active power imported by EV", - "Power.Factor": "Instantaneous power factor of total energy flow", - "Power.Offered": "Maximum power offered to EV", - "Power.Reactive.Export": "Instantaneous reactive power exported by EV", - "Power.Reactive.Import": "Instantaneous reactive power imported by EV", - "RPM": "Fan speed in RPM", - "SoC": "State of charge of EV in percentage", - "Temperature": "Temperature reading inside Charge Point", - "Voltage": "Instantaneous AC RMS supply voltage" + "Current.Export": "Current.Export: Instantaneous current flow from EV", + "Current.Import": "Current.Import: Instantaneous current flow to EV", + "Current.Offered": "Current.Offered: Maximum current offered to EV", + "Energy.Active.Export.Register": "Energy.Active.Export.Register: Active energy exported to the grid", + "Energy.Active.Import.Register": "Energy.Active.Import.Register: Active energy imported from the grid", + "Energy.Reactive.Export.Register": "Energy.Reactive.Export.Register: Reactive energy exported to the grid", + "Energy.Reactive.Import.Register": "Energy.Reactive.Import.Register: Reactive energy imported from the grid", + "Energy.Active.Export.Interval": "Energy.Active.Export.Interval: Active energy exported to the grid during last interval", + "Energy.Active.Import.Interval": "Energy.Active.Import.Interval: Active energy imported from the grid during last interval", + "Energy.Reactive.Export.Interval": "Energy.Reactive.Export.Interval: Reactive energy exported to the grid during last interval", + "Energy.Reactive.Import.Interval": "Energy.Reactive.Import.Interval: Reactive energy imported from the grid during last interval", + "Frequency": "Frequency: Powerline frequency", + "Power.Active.Export": "Power.Active.Export: Instantaneous active power exported by EV", + "Power.Active.Import": "Power.Active.Import: Instantaneous active power imported by EV", + "Power.Factor": "Power.Factor: Instantaneous power factor of total energy flow", + "Power.Offered": "Power.Offered: Maximum power offered to EV", + "Power.Reactive.Export": "Power.Reactive.Export: Instantaneous reactive power exported by EV", + "Power.Reactive.Import": "Power.Reactive.Import: Instantaneous reactive power imported by EV", + "RPM": "RPM: Fan speed in RPM", + "SoC": "SoC: State of charge of EV in percentage", + "Temperature": "Temperature: Temperature reading inside Charge Point", + "Voltage": "Voltage: Instantaneous AC RMS supply voltage" } } }, @@ -60,4 +61,4 @@ "single_instance_allowed": "Only a single instance is allowed." } } -} +} \ No newline at end of file diff --git a/custom_components/ocpp/translations/es.json b/custom_components/ocpp/translations/es.json index f1c6397e..352eb2ef 100644 --- a/custom_components/ocpp/translations/es.json +++ b/custom_components/ocpp/translations/es.json @@ -23,28 +23,28 @@ "title": "Mediciones OCPP", "description": "Seleccione qué medida(s) debe(n) mostrarse en el Asistente de Inicio.", "data": { - "Current.Export": "Flujo de corriente instantáneo del VE", - "Current.Import": "Flujo instantáneo de corriente hacia el VE", - "Current.Offered": "Corriente máxima ofrecida al VE", - "Energy.Active.Export.Register": "Energía activa exportada a la red", - "Energy.Active.Import.Register": "Energía activa importada de la red", - "Energy.Reactive.Export.Register": "Energía reactiva exportada a la red", - "Energy.Reactive.Import.Register": "Energía reactiva importada de la red", - "Energy.Active.Export.Interval": "Energía activa exportada a la red durante el último intervalo", - "Energy.Active.Import.Interval": "Energía activa importada de la red durante el último intervalo", - "Energy.Reactive.Export.Interval": "Energía reactiva exportada a la red durante el último intervalo", - "Energy.Reactive.Import.Interval": "Energía reactiva importada de la red durante el último intervalo", - "Frequency": "Frecuencia de la línea eléctrica", - "Power.Active.Export": "Potencia activa instantánea exportada por el VE", - "Power.Active.Import": "Potencia activa instantánea importada por el VE", - "Power.Factor": "Factor de potencia instantáneo del flujo de energía total", - "Power.Offered": "Potencia máxima ofrecida al VE", - "Power.Reactive.Export": "Potencia reactiva instantánea exportada por el VE", - "Power.Reactive.Import": "Potencia reactiva instantánea importada por el VE", - "RPM": "Velocidad del ventilador en RPM", - "SoC": "Estado de carga del VE en porcentaje", - "Temperature": "Lectura de la temperatura en el interior del punto de carga", - "Voltage": "Tensión de alimentación AC RMS instantánea" + "Current.Export": "Current.Export: Flujo de corriente instantáneo del VE", + "Current.Import": "Current.Import: Flujo instantáneo de corriente hacia el VE", + "Current.Offered": "Current.Offered: Corriente máxima ofrecida al VE", + "Energy.Active.Export.Register": "Energy.Active.Export.Register: Energía activa exportada a la red", + "Energy.Active.Import.Register": "Energy.Active.Import.Register: Energía activa importada de la red", + "Energy.Reactive.Export.Register": "Energy.Reactive.Export.Register: Energía reactiva exportada a la red", + "Energy.Reactive.Import.Register": "Energy.Reactive.Import.Register: Energía reactiva importada de la red", + "Energy.Active.Export.Interval": "Energy.Active.Export.Interval: Energía activa exportada a la red durante el último intervalo", + "Energy.Active.Import.Interval": "Energy.Active.Import.Interval: Energía activa importada de la red durante el último intervalo", + "Energy.Reactive.Export.Interval": "Energy.Reactive.Export.Interval: Energía reactiva exportada a la red durante el último intervalo", + "Energy.Reactive.Import.Interval": "Energy.Reactive.Import.Interval: Energía reactiva importada de la red durante el último intervalo", + "Frequency": "Frequency: Frecuencia de la línea eléctrica", + "Power.Active.Export": "Power.Active.Export: Potencia activa instantánea exportada por el VE", + "Power.Active.Import": "Power.Active.Import: Potencia activa instantánea importada por el VE", + "Power.Factor": "Power.Factor: Factor de potencia instantáneo del flujo de energía total", + "Power.Offered": "Power.Offered: Potencia máxima ofrecida al VE", + "Power.Reactive.Export": "Power.Reactive.Export: Potencia reactiva instantánea exportada por el VE", + "Power.Reactive.Import": "Power.Reactive.Import: Potencia reactiva instantánea importada por el VE", + "RPM": "RPM: Velocidad del ventilador en RPM", + "SoC": "SoC: Estado de carga del VE en porcentaje", + "Temperature": "Temperature: Lectura de la temperatura en el interior del punto de carga", + "Voltage": "Voltage: Tensión de alimentación AC RMS instantánea" } } }, @@ -56,4 +56,4 @@ "single_instance_allowed": "Sólo se permite una única instancia." } } -} +} \ No newline at end of file diff --git a/custom_components/ocpp/translations/i-default.json b/custom_components/ocpp/translations/i-default.json index 2f3940e5..0015e11b 100644 --- a/custom_components/ocpp/translations/i-default.json +++ b/custom_components/ocpp/translations/i-default.json @@ -14,6 +14,7 @@ "cpid": "Charge point identity", "max_current": "Maximum charging current", "meter_interval": "Charging sample interval (seconds)", + "monitored_variables_autoconfig": "Automatic detection of OCPP Measurands", "idle_interval": "Charger idle sampling interval (seconds)", "websocket_close_timeout": "Websocket close timeout (seconds)", "websocket_ping_tries": "Websocket successive times to try connection before closing", @@ -25,30 +26,30 @@ }, "measurands": { "title": "OCPP Measurands", - "description": "Select which measurand(s) should be shown in Home Assistant.", + "description": "Select which measurand(s) should be used in Home Assistant.", "data": { - "Current.Export": "Instantaneous current flow from EV", - "Current.Import": "Instantaneous current flow to EV", - "Current.Offered": "Maximum current offered to EV", - "Energy.Active.Export.Register": "Active energy exported to the grid", - "Energy.Active.Import.Register": "Active energy imported from the grid", - "Energy.Reactive.Export.Register": "Reactive energy exported to the grid", - "Energy.Reactive.Import.Register": "Reactive energy imported from the grid", - "Energy.Active.Export.Interval": "Active energy exported to the grid during last interval", - "Energy.Active.Import.Interval": "Active energy imported from the grid during last interval", - "Energy.Reactive.Export.Interval": "Reactive energy exported to the grid during last interval", - "Energy.Reactive.Import.Interval": "Reactive energy imported from the grid during last interval", - "Frequency": "Powerline frequency", - "Power.Active.Export": "Instantaneous active power exported by EV", - "Power.Active.Import": "Instantaneous active power imported by EV", - "Power.Factor": "Instantaneous power factor of total energy flow", - "Power.Offered": "Maximum power offered to EV", - "Power.Reactive.Export": "Instantaneous reactive power exported by EV", - "Power.Reactive.Import": "Instantaneous reactive power imported by EV", - "RPM": "Fan speed in RPM", - "SoC": "State of charge of EV in percentage", - "Temperature": "Temperature reading inside Charge Point", - "Voltage": "Instantaneous AC RMS supply voltage" + "Current.Export": "Current.Export: Instantaneous current flow from EV", + "Current.Import": "Current.Import: Instantaneous current flow to EV", + "Current.Offered": "Current.Offered: Maximum current offered to EV", + "Energy.Active.Export.Register": "Energy.Active.Export.Register: Active energy exported to the grid", + "Energy.Active.Import.Register": "Energy.Active.Import.Register: Active energy imported from the grid", + "Energy.Reactive.Export.Register": "Energy.Reactive.Export.Register: Reactive energy exported to the grid", + "Energy.Reactive.Import.Register": "Energy.Reactive.Import.Register: Reactive energy imported from the grid", + "Energy.Active.Export.Interval": "Energy.Active.Export.Interval: Active energy exported to the grid during last interval", + "Energy.Active.Import.Interval": "Energy.Active.Import.Interval: Active energy imported from the grid during last interval", + "Energy.Reactive.Export.Interval": "Energy.Reactive.Export.Interval: Reactive energy exported to the grid during last interval", + "Energy.Reactive.Import.Interval": "Energy.Reactive.Import.Interval: Reactive energy imported from the grid during last interval", + "Frequency": "Frequency: Powerline frequency", + "Power.Active.Export": "Power.Active.Export: Instantaneous active power exported by EV", + "Power.Active.Import": "Power.Active.Import: Instantaneous active power imported by EV", + "Power.Factor": "Power.Factor: Instantaneous power factor of total energy flow", + "Power.Offered": "Power.Offered: Maximum power offered to EV", + "Power.Reactive.Export": "Power.Reactive.Export: Instantaneous reactive power exported by EV", + "Power.Reactive.Import": "Power.Reactive.Import: Instantaneous reactive power imported by EV", + "RPM": "RPM: Fan speed in RPM", + "SoC": "SoC: State of charge of EV in percentage", + "Temperature": "Temperature: Temperature reading inside Charge Point", + "Voltage": "Voltage: Instantaneous AC RMS supply voltage" } } }, @@ -60,4 +61,4 @@ "single_instance_allowed": "Only a single instance is allowed." } } -} +} \ No newline at end of file diff --git a/custom_components/ocpp/translations/nl.json b/custom_components/ocpp/translations/nl.json index 3923a1fa..50164f70 100644 --- a/custom_components/ocpp/translations/nl.json +++ b/custom_components/ocpp/translations/nl.json @@ -23,28 +23,28 @@ "title": "OCPP Meetgrootheden", "description": "Selecteer welke meetgrootheden weergegeven worden.", "data": { - "Current.Export": "Instantane stroom van EV", - "Current.Import": "Instantane stroom naar EV", - "Current.Offered": "Maximale stroom aangeboden aan EV", - "Energy.Active.Export.Register": "Actieve energie geexporteerd naar het net", - "Energy.Active.Import.Register": "Actieve energie geimporteed vanaf het net", - "Energy.Reactive.Export.Register": "Reactieve energie gexporteerd naar het net", - "Energy.Reactive.Import.Register": "Reactieve energie geimporteerd van het net", - "Energy.Active.Export.Interval": "Actieve energie geexporteerd naar het net tijdens het laatste meetinterval", - "Energy.Active.Import.Interval": "Actieve energie geimporteerd van het net tijdens het laatste meetinterval", - "Energy.Reactive.Export.Interval": "Reactieve energie geexporteerd naar het net tijdens het laatste meetinterval", - "Energy.Reactive.Import.Interval": "Reactieve energie geimporteerd van het net tijdens het laatste meetinterval", - "Frequency": "Netfrequentie", - "Power.Active.Export": "Instantane actieve vermogen geexporteerd door EV", - "Power.Active.Import": "Instantane active vermorgen geimporteerd door EV", - "Power.Factor": "Instantane vermogensfactor can de totale energiestroom", - "Power.Offered": "Maximale vermogen aangeboden aan EV", - "Power.Reactive.Export": "Instantane reactive vermogen geexporteerd door EV", - "Power.Reactive.Import": "Instantane reactieve vermogen geimporteerd door EV", - "RPM": "Ventilator snelheid in RPM", - "SoC": "Laadstand in procent", - "Temperature": "Temperatuur in het laadpunt", - "Voltage": "Instantane RMS waarde voedingsspanning" + "Current.Export": "Current.Export: Instantane stroom van EV", + "Current.Import": "Current.Import: Instantane stroom naar EV", + "Current.Offered": "Current.Offered: Maximale stroom aangeboden aan EV", + "Energy.Active.Export.Register": "Energy.Active.Export.Register: Actieve energie geexporteerd naar het net", + "Energy.Active.Import.Register": "Energy.Active.Import.Register: Actieve energie geimporteed vanaf het net", + "Energy.Reactive.Export.Register": "Energy.Reactive.Export.Register: Reactieve energie gexporteerd naar het net", + "Energy.Reactive.Import.Register": "Energy.Reactive.Import.Register: Reactieve energie geimporteerd van het net", + "Energy.Active.Export.Interval": "Energy.Active.Export.Interval: Actieve energie geexporteerd naar het net tijdens het laatste meetinterval", + "Energy.Active.Import.Interval": "Energy.Active.Import.Interval: Actieve energie geimporteerd van het net tijdens het laatste meetinterval", + "Energy.Reactive.Export.Interval": "Energy.Reactive.Export.Interval: Reactieve energie geexporteerd naar het net tijdens het laatste meetinterval", + "Energy.Reactive.Import.Interval": "Energy.Reactive.Import.Interval: Reactieve energie geimporteerd van het net tijdens het laatste meetinterval", + "Frequency": "Frequency: Netfrequentie", + "Power.Active.Export": "Power.Active.Export: Instantane actieve vermogen geexporteerd door EV", + "Power.Active.Import": "Power.Active.Import: Instantane active vermorgen geimporteerd door EV", + "Power.Factor": "Power.Factor: Instantane vermogensfactor can de totale energiestroom", + "Power.Offered": "Power.Offered: Maximale vermogen aangeboden aan EV", + "Power.Reactive.Export": "Power.Reactive.Export: Instantane reactive vermogen geexporteerd door EV", + "Power.Reactive.Import": "Power.Reactive.Import: Instantane reactieve vermogen geimporteerd door EV", + "RPM": "RPM: Ventilator snelheid in RPM", + "SoC": "SoC: Laadstand in procent", + "Temperature": "Temperature: Temperatuur in het laadpunt", + "Voltage": "Voltage: Instantane RMS waarde voedingsspanning" } } }, diff --git a/docs/installation.md b/docs/installation.md index d349335c..ee493166 100644 --- a/docs/installation.md +++ b/docs/installation.md @@ -41,7 +41,7 @@ If you do not use HTTPS for your Home Assistant instance: ### Measurands - Most chargers only support a subset of all possible measurands. This depends most on the Feature profiles that are supported by the charger. -- The integration will autodetect the supported measurands when the charger connects. +- The integration will autodetect the supported measurands when the charger connects. This can be disabled for chargers that do not support autodetection. ## Add the entities to your Dashboard - On the OCPP integration, click on devices to navigate to your Charge Point device. diff --git a/docs/supported-devices.md b/docs/supported-devices.md index 51dff441..3739c8e2 100644 --- a/docs/supported-devices.md +++ b/docs/supported-devices.md @@ -3,13 +3,48 @@ Supported devices All OCPP 1.6j compatible devices should be supported, but not every device offers the same level of functionality. So far, we've tried: -## [ABB Terra AC-W7-G5-R-0](https://new.abb.com/products/6AGC082156/tac-w7-g5-r-0) +## ABB Terra AC chargers -## [ABB Terra AC-W11-G5-R-0](https://new.abb.com/products/6AGC082156/tac-w11-g5-r-0) +ABB Terra AC chargers with firmware version 1.8.21 and earlier fail to respond correctly when OCPP measurands are automatically detected by the OCPP integration. As of this writing, ABB has been notified, but no corresponding firmware fix is available. -## [ABB Terra AC-W22-T-0](https://new.abb.com/products/6AGC081279/tac-w22-t-0) +### Issue Description -## [ABB Terra TAC-W22-T-RD-MC-0](https://new.abb.com/products/6AGC081281/tac-w22-t-rd-mc-0) +When automatic measurand detection is used in the OCPP integration with ABB Terra AC chargers: + +1. The charger responds as if it supports all proposed measurands. +2. The integration then asks for all measurands to be reported. +3. When the integration tries to query which measurands are available after this configuration, the ABB Terra AC reboots. + +As a result, the ABB charger becomes unusable with the OCPP integration, as the integration checks for available measurands on every charger boot, leading to a boot loop. + +For more details and symptoms, see [Issue #1275](https://github.com/lbbrhzn/ocpp/issues/1275). + +### Workaround + +Fortunately, it is possible to configure the charger using manual configuration and to restore correct settings. + +To use these chargers: + +1. Disable "Automatic detection of OCPP Measurands". + - Note: Automatic detection is enabled by default. Until configuration changes can be made online, you may need to remove the devices from this integration and add them again. + - If "Automatic detection of OCPP Measurands" is disabled during configuration, you will be presented with a list of possible measurands. + +2. When presented with the list of measurands, select only the following: + - `Current.Import` + - `Current.Offered` + - `Energy.Active.Import.Register` + - `Power.Active.Import` + - `Voltage` + +This list is based on the overview of OCPP 1.6 implementation for ABB Terra AC (firmware 1.6.6). + +### [ABB Terra AC-W7-G5-R-0](https://new.abb.com/products/6AGC082156/tac-w7-g5-r-0) + +### [ABB Terra AC-W11-G5-R-0](https://new.abb.com/products/6AGC082156/tac-w11-g5-r-0) + +### [ABB Terra AC-W22-T-0](https://new.abb.com/products/6AGC081279/tac-w22-t-0) + +### [ABB Terra TAC-W22-T-RD-MC-0](https://new.abb.com/products/6AGC081281/tac-w22-t-rd-mc-0) ## [Alfen - Eve Single Pro-line](https://alfen.com/en/ev-charge-points/alfen-product-range) diff --git a/docs/user-guide.md b/docs/user-guide.md index 53af6557..43703844 100644 --- a/docs/user-guide.md +++ b/docs/user-guide.md @@ -23,6 +23,8 @@ The `Charge point identity` shown above with a default of `charger` is a little Measurands (according to OCPP terminology) are actually metrics provided by the charger. Each charger supports a subset of the available metrics and for each one supported, a sensor entity is available in HA. Some of these sensor entities will give erroneous readings whilst others give no readings at all. Sensor entities not supported by the charger will show as `Unknown` if you try to create a sensor entity for them. Below is a table of the metrics I've found useful for the Wallbox Pulsar Plus. Tables for other chargers will follow as contributions come in from owners of each supported charger. +OCPP integration can automatically detect supported measurands. However, some chargers have faulty firmware that causes the detection mechanism to fail. For such chargers, it is possible to disable automatic measurand detection and manually set the measurands to those supported by the charger. When set manually, selected measurands are not checked for compatibility with the charger and are requested from it. See below for OCPP compliance notes and charger-specific instructions in [supported devices](supported-devices.md). + ## Useful Entities for Wallbox Pulsar Plus ### Metrics @@ -46,6 +48,16 @@ Measurands (according to OCPP terminology) are actually metrics provided by the * `Maximum Current` (sets maximum charging current available) * `Reset` +## Useful Entities for ABB Terra AC + +### Metrics + +* `Current.Import` (instantaneous current flow to EV) +* `Energy.Active.Import.Register` (active energy imported from the grid) +* `Power.Active.Import` (instantaneous active power imported by EV) +* `Voltage` (instantaneous AC RMS supply voltage) + + ## Useful Entities for EVBox Elvi ### Metrics @@ -68,7 +80,7 @@ Measurands (according to OCPP terminology) are actually metrics provided by the ## Useful Entities and Workarounds for United Chargers Grizzl-E -Comments below relate to Grizzl-E firmware version 5.633, tested Oct-Nov 2022. +Comments below relate to Grizzl-E firmware version 5.633, tested Oct-Nov 2022. ### Metrics The Grizzl-E updates these metrics every 30s during charging sessions: @@ -114,6 +126,12 @@ The Grizzl-E updates these metrics every 30s during charging sessions: ### OCPP Compatibility Issues +### ABB Terra AC + +ABB Terra AC firmware 1.8.21 and earlier versions fail to respond correctly when OCPP measurands are automatically detected by the OCPP integration. As of this writing, ABB has been notified, but no corresponding firmware fix is available. As a result, users must configure measurands manually. See the suggested ABB Terra AC configuration in [supported devices](supported-devices.md). + +### Grizzl-E + Grizzl-E firmware has a few OCPP-compliance defects, including responding to certain OCPP server messages with invalid JSON. Symptoms of this problem include repeated reboots of the charger. By editing the OCPP server source code, one can avoid these problematic messages and obtain useful charger behaviour. ChargeLabs (the company working on the Grizzl-E firmware) expects to release version 6 of the firmware in early 2023, which may fix these problems. The workaround consists of: diff --git a/tests/const.py b/tests/const.py index 7acb1d5d..e66520be 100644 --- a/tests/const.py +++ b/tests/const.py @@ -9,6 +9,7 @@ CONF_MAX_CURRENT, CONF_METER_INTERVAL, CONF_MONITORED_VARIABLES, + CONF_MONITORED_VARIABLES_AUTOCONFIG, CONF_PORT, CONF_SKIP_SCHEMA_VALIDATION, CONF_SSL, @@ -32,7 +33,7 @@ CONF_IDLE_INTERVAL: 900, CONF_MAX_CURRENT: 32, CONF_METER_INTERVAL: 60, - CONF_MONITORED_VARIABLES: DEFAULT_MONITORED_VARIABLES, + CONF_MONITORED_VARIABLES_AUTOCONFIG: True, CONF_SKIP_SCHEMA_VALIDATION: False, CONF_FORCE_SMART_CHARGING: True, CONF_WEBSOCKET_CLOSE_TIMEOUT: 1, @@ -50,6 +51,7 @@ CONF_MAX_CURRENT: 32, CONF_METER_INTERVAL: 60, CONF_MONITORED_VARIABLES: DEFAULT_MONITORED_VARIABLES, + CONF_MONITORED_VARIABLES_AUTOCONFIG: True, CONF_SKIP_SCHEMA_VALIDATION: False, CONF_FORCE_SMART_CHARGING: True, CONF_SSL: False,