From 4b89da389646b8fd3866cdd6a9c43709aa4eca3e Mon Sep 17 00:00:00 2001 From: Muka Schultze Date: Thu, 6 Feb 2025 18:19:40 +0000 Subject: [PATCH] feat: repair serial number not being unique --- custom_components/must_inverter/__init__.py | 13 +++- custom_components/must_inverter/mapper.py | 2 +- custom_components/must_inverter/repairs.py | 60 +++++++++++++++++++ .../must_inverter/translations/en.json | 20 +++++++ 4 files changed, 93 insertions(+), 2 deletions(-) create mode 100644 custom_components/must_inverter/repairs.py diff --git a/custom_components/must_inverter/__init__.py b/custom_components/must_inverter/__init__.py index dcd8f03..7b3ab3c 100644 --- a/custom_components/must_inverter/__init__.py +++ b/custom_components/must_inverter/__init__.py @@ -8,6 +8,7 @@ from homeassistant.const import Platform from homeassistant.core import HomeAssistant, callback from homeassistant.exceptions import ConfigEntryNotReady +from homeassistant.helpers import issue_registry as ir from homeassistant.helpers.event import async_track_time_interval from pymodbus.client import AsyncModbusSerialClient, AsyncModbusTcpClient, AsyncModbusUdpClient @@ -24,7 +25,6 @@ from .const import ( DOMAIN, - DEFAULT_SCAN_INTERVAL, CONF_BAUDRATE, CONF_PARITY, CONF_STOPBITS, @@ -359,6 +359,17 @@ async def read_modbus_data(self): self._reading = False # _LOGGER.debug("Data: %s", self.data) + if self.data["InverterSerialNumber"] == 0xFFFFFFFF or self.data["InverterSerialNumber"] == 0: + ir.async_create_issue( + self._hass, + DOMAIN, + "no_serial_number", + is_fixable=True, + severity=ir.IssueSeverity.WARNING, + translation_key="no_serial_number", + data={"entry_id": self._entry.entry_id}, + ) + return True def _device_info(self): diff --git a/custom_components/must_inverter/mapper.py b/custom_components/must_inverter/mapper.py index 2723119..ec62ac7 100644 --- a/custom_components/must_inverter/mapper.py +++ b/custom_components/must_inverter/mapper.py @@ -28,7 +28,7 @@ def time(address, registers): def serial(address, registers): - return hex(registers[address] << 16 | registers[address + 1]) + return registers[address] << 16 | registers[address + 1] def model(address, registers): diff --git a/custom_components/must_inverter/repairs.py b/custom_components/must_inverter/repairs.py new file mode 100644 index 0000000..9950416 --- /dev/null +++ b/custom_components/must_inverter/repairs.py @@ -0,0 +1,60 @@ +from __future__ import annotations + +import voluptuous as vol +import time + +from homeassistant import data_entry_flow +from homeassistant.components.repairs import RepairsFlow +from homeassistant.core import HomeAssistant + +from .__init__ import MustInverter +from .const import DOMAIN + + +class NoSerialNumber(RepairsFlow): + """Handler for an issue fixing flow.""" + + def __init__(self, hass: HomeAssistant, data: dict[str, str | int | float | None] | None) -> None: + """Initialize the flow.""" + self._hass = hass + self._data = data + + async def async_step_init(self, user_input: dict[str, str] | None = None) -> data_entry_flow.FlowResult: + """Handle the first step of a fix flow.""" + return await self.async_step_confirm() + + async def async_step_confirm(self, user_input: dict[str, str] | None = None) -> data_entry_flow.FlowResult: + """Handle the confirm step of a fix flow.""" + if user_input is not None: + entry_id = self._data["entry_id"] + device: MustInverter = self._hass.data[DOMAIN][entry_id]["inverter"] + new_serial_number = user_input["new_serial"] + + lower = new_serial_number & 0xFFFF + upper = (new_serial_number >> 16) & 0xFFFF + + await device.write_modbus_data(20002, upper) + await device.write_modbus_data(20003, lower) + + self._hass.config_entries.async_schedule_reload(entry_id) + + return self.async_create_entry(title="", data={}) + + return self.async_show_form( + step_id="confirm", + data_schema=vol.Schema( + { + vol.Required("new_serial", default=int(time.time())): int, + } + ), + ) + + +async def async_create_fix_flow( + hass: HomeAssistant, + issue_id: str, + data: dict[str, str | int | float | None] | None, +) -> RepairsFlow: + """Create flow.""" + if issue_id == "no_serial_number": + return NoSerialNumber(hass, data) diff --git a/custom_components/must_inverter/translations/en.json b/custom_components/must_inverter/translations/en.json index 9e9791f..0fe5bdc 100644 --- a/custom_components/must_inverter/translations/en.json +++ b/custom_components/must_inverter/translations/en.json @@ -128,6 +128,26 @@ } } }, + "issues": { + "no_serial_number": { + "title": "No serial number set", + "fix_flow": { + "step": { + "confirm": { + "title": "No serial number set", + "description": "Your inverter does not have a serial number written to it. This will cause issues with the integration when attempting to add multiple inverters.\n\nThis repair will write a serial number to the inverter. This will not affect the operation of the inverter, but it will allow the integration to work correctly with more than one device simultaneously.", + "data": { + "new_serial": "Serial number to set", + "confirm": "I understand and want to proceed with the repair" + }, + "data_description": { + "new_serial": "You can find your serial number written on the side of the device. Otherwise, you can leave this unchanged to use a random value." + } + } + } + } + } + }, "selector": { "model": { "options": {