diff --git a/.gitignore b/.gitignore index 9bea4330..064cd6a4 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ .DS_Store +__pycache__ \ No newline at end of file diff --git a/custom_components/solax_modbus/__init__.py b/custom_components/solax_modbus/__init__.py index 68dd3013..93bcf627 100644 --- a/custom_components/solax_modbus/__init__.py +++ b/custom_components/solax_modbus/__init__.py @@ -14,10 +14,10 @@ import homeassistant.helpers.config_validation as cv import voluptuous as vol from homeassistant.config_entries import ConfigEntry -from homeassistant.const import CONF_HOST, CONF_NAME, CONF_PORT, CONF_SCAN_INTERVAL +from homeassistant.const import CONF_HOST, CONF_NAME, CONF_PORT, CONF_SCAN_INTERVAL, Platform from homeassistant.core import HomeAssistant, callback from homeassistant.helpers.event import async_track_time_interval -from homeassistant.components.button import ButtonEntity +from homeassistant.const import EVENT_HOMEASSISTANT_STARTED _LOGGER = logging.getLogger(__name__) #try: # pymodbus 3.0.x @@ -69,7 +69,7 @@ from .const import REGISTER_S32, REGISTER_U32, REGISTER_U16, REGISTER_S16, REGISTER_ULSB16MSB16, REGISTER_STR, REGISTER_WORDS, REGISTER_U8H, REGISTER_U8L -PLATFORMS = ["button", "number", "select", "sensor"] +PLATFORMS = [Platform.BUTTON, Platform.NUMBER, Platform.SELECT, Platform.SENSOR] #seriesnumber = 'unknown' @@ -101,7 +101,6 @@ async def async_migrate_entry(hass, config_entry: ConfigEntry): async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry): """Set up a SolaX mobus.""" - await asyncio.sleep(5) _LOGGER.debug(f"setup entries - data: {entry.data}, options: {entry.options}") config = entry.options name = config[CONF_NAME] @@ -139,16 +138,15 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry): _LOGGER.debug(f"Setup {DOMAIN}.{name}") _LOGGER.debug(f"solax serial port {serial_port} interface {interface}") - hub = SolaXModbusHub(hass, name, host, port, tcp_type, modbus_addr, interface, serial_port, baudrate, scan_interval, plugin, config) + hub = SolaXModbusHub(hass, name, host, port, tcp_type, modbus_addr, interface, serial_port, + baudrate, scan_interval, plugin, config, entry) """Register the hub.""" hass.data[DOMAIN][name] = { "hub": hub, } - await hub.async_get_inverter_type() + # Tests on some systems have shown that establishing the Modbus connection + # can occasionally lead to errors if Home Assistant is not fully loaded. + hass.bus.async_listen_once(EVENT_HOMEASSISTANT_STARTED, hub.async_init()) - for component in PLATFORMS: - hass.async_create_task( - hass.config_entries.async_forward_entry_setup(entry, component) - ) entry.async_on_unload(entry.add_update_listener(config_entry_update_listener)) return True @@ -193,7 +191,8 @@ def __init__( baudrate, scan_interval, plugin, - config + config, + entry ): """Initialize the Modbus hub.""" _LOGGER.debug(f"solax modbushub creation with interface {interface} baudrate (only for serial): {baudrate}") @@ -253,14 +252,20 @@ def __init__( self.localsUpdated = False self.localsLoaded = False self.config = config + self.entry = entry _LOGGER.debug("solax modbushub done %s", self.__dict__) - async def async_get_inverter_type(self): + async def async_init(self): await self.async_connect() self._invertertype = await self.plugin.async_determineInverterType( self, self.config ) + for component in PLATFORMS: + self._hass.async_create_task( + self._hass.config_entries.async_forward_entry_setup(self.entry, component) + ) + # save and load local data entity values to make them persistent DATAFORMAT_VERSION = 1 @@ -289,10 +294,11 @@ def loadLocalData(self): # end of save and load section @callback - def async_add_solax_modbus_sensor(self, update_callback): + async def async_add_solax_modbus_sensor(self, update_callback): """Listen for data updates.""" # This is the first sensor, set up interval. if not self._sensor_callbacks: + await self.async_connect() self._unsub_interval_method = async_track_time_interval( self._hass, self.async_refresh_modbus_data, self._scan_interval ) @@ -409,6 +415,7 @@ async def async_write_register(self, unit, address, payload): async def async_write_registers_single(self, unit, address, payload): # Needs adapting for regiater que """Write registers multi, but write only one register of type 16bit""" + await self.async_connect() async with self._lock: kwargs = {"slave": unit} if unit else {} builder = BinaryPayloadBuilder(byteorder=self.plugin.order16, wordorder=self.plugin.order32) @@ -422,13 +429,14 @@ async def async_write_registers_multi(self, unit, address, payload): # Needs ada unit is the modbus address of the device that will be writen to address us the start register address payload is a list of tuples containing - - a select or number entity keys names or alternatively REGISTER_xx type declarations - - the values are the values that will be encoded according to the spec of that entity + - a select or number entity keys names or alternatively REGISTER_xx type declarations + - the values are the values that will be encoded according to the spec of that entity The list of tuples will be converted to a modbus payload with the proper encoding and written to modbus device with address=unit All register descriptions referenced in the payload must be consecutive (without leaving holes) 32bit integers will be converted to 2 modbus register values according to the endian strategy of the plugin """ + await self.async_connect() async with self._lock: kwargs = {'slave': unit} if unit else {} builder = BinaryPayloadBuilder(byteorder=self.plugin.order16, wordorder=self.plugin.order32) diff --git a/custom_components/solax_modbus/number.py b/custom_components/solax_modbus/number.py index 33585781..8f43df29 100644 --- a/custom_components/solax_modbus/number.py +++ b/custom_components/solax_modbus/number.py @@ -79,7 +79,7 @@ def __init__(self, async def async_added_to_hass(self) -> None: """Register callbacks.""" - self._hub.async_add_solax_modbus_sensor(self._modbus_data_updated) + await self._hub.async_add_solax_modbus_sensor(self._modbus_data_updated) async def async_will_remove_from_hass(self) -> None: await self._hub.async_remove_solax_modbus_sensor(self._modbus_data_updated) diff --git a/custom_components/solax_modbus/select.py b/custom_components/solax_modbus/select.py index 6ef9adfc..97a2f9a2 100644 --- a/custom_components/solax_modbus/select.py +++ b/custom_components/solax_modbus/select.py @@ -68,7 +68,7 @@ def __init__(self, async def async_added_to_hass(self): """Register callbacks.""" - self._hub.async_add_solax_modbus_sensor(self._modbus_data_updated) + await self._hub.async_add_solax_modbus_sensor(self._modbus_data_updated) async def async_will_remove_from_hass(self) -> None: await self._hub.async_remove_solax_modbus_sensor(self._modbus_data_updated) diff --git a/custom_components/solax_modbus/sensor.py b/custom_components/solax_modbus/sensor.py index 5707abcc..4db64b1d 100644 --- a/custom_components/solax_modbus/sensor.py +++ b/custom_components/solax_modbus/sensor.py @@ -164,7 +164,7 @@ def __init__( async def async_added_to_hass(self): """Register callbacks.""" - self._hub.async_add_solax_modbus_sensor(self._modbus_data_updated) + await self._hub.async_add_solax_modbus_sensor(self._modbus_data_updated) async def async_will_remove_from_hass(self) -> None: await self._hub.async_remove_solax_modbus_sensor(self._modbus_data_updated)