diff --git a/custom_components/solis_modbus/const.py b/custom_components/solis_modbus/const.py index db53d95..2388803 100644 --- a/custom_components/solis_modbus/const.py +++ b/custom_components/solis_modbus/const.py @@ -1,6 +1,16 @@ DOMAIN = "solis_modbus" CONTROLLER = "modbus_controller" -VERSION = "1.5.0" +VERSION = "1.5.1" POLL_INTERVAL_SECONDS = 15 MANUFACTURER = "Solis" MODEL = "S6" + +DATA_RECEIVED = 'data_received' +VALUES = 'values' +SENSOR_ENTITIES = 'sensor_entities' +TIME_ENTITIES = 'time_entities' +SWITCH_ENTITIES = 'switch_entities' +NUMBER_ENTITIES = 'number_entities' +SENSOR_DERIVED_ENTITIES = 'sensor_derived_entities' +DRIFT_COUNTER = 'drift_counter' +ENTITIES = 'entities' diff --git a/custom_components/solis_modbus/manifest.json b/custom_components/solis_modbus/manifest.json index d2beeeb..62c9585 100644 --- a/custom_components/solis_modbus/manifest.json +++ b/custom_components/solis_modbus/manifest.json @@ -10,5 +10,5 @@ "issue_tracker": "https://github.com/Pho3niX90/solis_modbus/issues", "quality_scale": "silver", "requirements": ["pymodbus>=3.6.8"], - "version": "1.5.0" + "version": "1.5.1" } diff --git a/custom_components/solis_modbus/number.py b/custom_components/solis_modbus/number.py index 560929c..cda99f5 100644 --- a/custom_components/solis_modbus/number.py +++ b/custom_components/solis_modbus/number.py @@ -19,7 +19,8 @@ from homeassistant.helpers.entity import DeviceInfo from homeassistant.helpers.event import async_track_time_interval -from custom_components.solis_modbus.const import DOMAIN, CONTROLLER, VERSION, POLL_INTERVAL_SECONDS, MANUFACTURER, MODEL +from custom_components.solis_modbus.const import DOMAIN, CONTROLLER, VERSION, POLL_INTERVAL_SECONDS, MANUFACTURER, \ + MODEL, VALUES, NUMBER_ENTITIES _LOGGER = logging.getLogger(__name__) @@ -76,7 +77,7 @@ async def async_setup_entry(hass, config_entry: ConfigEntry, async_add_devices): type = entity_definition["type"] if type == "SNE": numberEntities.append(SolisNumberEntity(hass, modbus_controller, entity_definition)) - hass.data[DOMAIN]['number_entities'] = numberEntities + hass.data[DOMAIN][NUMBER_ENTITIES] = numberEntities async_add_devices(numberEntities, True) @callback @@ -84,14 +85,14 @@ def update(now): """Update Modbus data periodically.""" controller = hass.data[DOMAIN][CONTROLLER] - _LOGGER.info(f"calling number update for {len(hass.data[DOMAIN]['number_entities'])} groups") + _LOGGER.info(f"calling number update for {len(hass.data[DOMAIN][NUMBER_ENTITIES])} groups") hass.create_task(get_modbus_updates(hass, controller)) async def get_modbus_updates(hass, controller): if not controller.connected(): await controller.connect() await asyncio.gather( - *[asyncio.to_thread(entity.update) for entity in hass.data[DOMAIN]["number_entities"]] + *[asyncio.to_thread(entity.update) for entity in hass.data[DOMAIN][NUMBER_ENTITIES]] ) @@ -143,7 +144,7 @@ def update(self): """Update Modbus data periodically.""" self._attr_available = True - value: float = self._hass.data[DOMAIN]['values'][str(self._register)] + value: float = self._hass.data[DOMAIN][VALUES][str(self._register)] self._hass.create_task(self.update_values(value)) self.schedule_update_ha_state() diff --git a/custom_components/solis_modbus/sensor.py b/custom_components/solis_modbus/sensor.py index f63fa3d..1e6060d 100644 --- a/custom_components/solis_modbus/sensor.py +++ b/custom_components/solis_modbus/sensor.py @@ -14,7 +14,8 @@ from homeassistant.helpers.device_registry import DeviceInfo from homeassistant.helpers.event import async_track_time_interval -from custom_components.solis_modbus.const import DOMAIN, CONTROLLER, VERSION, POLL_INTERVAL_SECONDS, MANUFACTURER, MODEL +from custom_components.solis_modbus.const import DOMAIN, CONTROLLER, VERSION, POLL_INTERVAL_SECONDS, MANUFACTURER, \ + MODEL, DATA_RECEIVED, VALUES, SENSOR_DERIVED_ENTITIES, SENSOR_ENTITIES, DRIFT_COUNTER from custom_components.solis_modbus.status_mapping import STATUS_MAPPING _LOGGER = logging.getLogger(__name__) @@ -25,7 +26,8 @@ async def async_setup_entry(hass: HomeAssistant, config_entry: ConfigEntry, asyn modbus_controller = hass.data[DOMAIN][CONTROLLER] sensor_entities: List[SensorEntity] = [] sensor_derived_entities: List[SensorEntity] = [] - hass.data[DOMAIN]['values'] = {} + hass.data[DOMAIN][VALUES] = {} + hass.data[DOMAIN][DATA_RECEIVED] = False sensors = [ { @@ -649,7 +651,7 @@ async def async_setup_entry(hass: HomeAssistant, config_entry: ConfigEntry, asyn for sensor_group in sensors: for entity_definition in sensor_group['entities']: for register in entity_definition['register']: - hass.data[DOMAIN]['values'][register] = 0 + hass.data[DOMAIN][VALUES][register] = 0 type = entity_definition["type"] if type == 'SS': sensor_entities.append(SolisSensor(hass, modbus_controller, entity_definition)) @@ -659,8 +661,8 @@ async def async_setup_entry(hass: HomeAssistant, config_entry: ConfigEntry, asyn if type == 'SDS': sensor_derived_entities.append(SolisDerivedSensor(hass, sensor_group)) - hass.data[DOMAIN]['sensor_entities'] = sensor_entities - hass.data[DOMAIN]['sensor_derived_entities'] = sensor_derived_entities + hass.data[DOMAIN][SENSOR_ENTITIES] = sensor_entities + hass.data[DOMAIN][SENSOR_DERIVED_ENTITIES] = sensor_derived_entities async_add_entities(sensor_entities, True) async_add_entities(sensor_derived_entities, True) @@ -672,8 +674,8 @@ def update(now): hass.create_task(get_modbus_updates(hass, controller)) asyncio.gather( - *[asyncio.to_thread(entity.update) for entity in hass.data[DOMAIN]["sensor_entities"]], - *[asyncio.to_thread(entity.update) for entity in hass.data[DOMAIN]["sensor_derived_entities"]] + *[asyncio.to_thread(entity.update) for entity in hass.data[DOMAIN][SENSOR_ENTITIES]], + *[asyncio.to_thread(entity.update) for entity in hass.data[DOMAIN][SENSOR_DERIVED_ENTITIES]] ) async def get_modbus_updates(hass, controller): @@ -696,6 +698,8 @@ async def get_modbus_updates(hass, controller): hass.data[DOMAIN]['values'][register_key] = value _LOGGER.debug(f'register_key = {register_key}, value = {value}') + hass.data[DOMAIN][DATA_RECEIVED] = True + async_track_time_interval(hass, update, timedelta(seconds=POLL_INTERVAL_SECONDS)) return True @@ -757,7 +761,7 @@ async def clock_drift_test(hass, controller, hours, minutes, seconds): d_seconds = r_seconds - seconds total_drift = (d_hours * 60 * 60) + (d_minutes * 60) + d_seconds - drift_counter = hass.data[DOMAIN].get('drift_counter', 0) + drift_counter = hass.data[DOMAIN].get(DRIFT_COUNTER, 0) if abs(total_drift) > 5: """this is to make sure that we do not accidentally roll back the time, resetting all stats""" @@ -765,9 +769,9 @@ async def clock_drift_test(hass, controller, hours, minutes, seconds): if controller.connected(): await controller.async_write_holding_registers(43003, [current_time.hour, current_time.minute, current_time.second]) else: - hass.data[DOMAIN]['drift_counter'] = drift_counter + 1 + hass.data[DOMAIN][DRIFT_COUNTER] = drift_counter + 1 else: - hass.data[DOMAIN]['drift_counter'] = 0 + hass.data[DOMAIN][DRIFT_COUNTER] = 0 class SolisDerivedSensor(RestoreSensor, SensorEntity): @@ -909,9 +913,9 @@ def update(self): return if '33027' in self._register: - hours = self._hass.data[DOMAIN]['values'][str(int(self._register[0]) - 2)] - minutes = self._hass.data[DOMAIN]['values'][str(int(self._register[0]) - 1)] - seconds = self._hass.data[DOMAIN]['values'][self._register[0]] + hours = self._hass.data[DOMAIN][VALUES][str(int(self._register[0]) - 2)] + minutes = self._hass.data[DOMAIN][VALUES][str(int(self._register[0]) - 1)] + seconds = self._hass.data[DOMAIN][VALUES][self._register[0]] self.hass.create_task(clock_drift_test(self._hass, self._modbus_controller, hours, minutes, seconds)) if len(self._register) == 1 and self._register[0] in ('33001', '33002', '33003'): @@ -919,7 +923,9 @@ def update(self): else: n_value = get_value(self) - if n_value == 0: + if (n_value == 0 + and self.state_class != SensorStateClass.MEASUREMENT + and self._hass.data[DOMAIN][DATA_RECEIVED] is not True): n_value = self.async_get_last_sensor_data() if n_value is not None: diff --git a/custom_components/solis_modbus/switch.py b/custom_components/solis_modbus/switch.py index 22f7526..be873ea 100644 --- a/custom_components/solis_modbus/switch.py +++ b/custom_components/solis_modbus/switch.py @@ -8,7 +8,8 @@ from homeassistant.helpers.device_registry import DeviceInfo from homeassistant.helpers.event import async_track_time_interval -from custom_components.solis_modbus.const import POLL_INTERVAL_SECONDS, DOMAIN, CONTROLLER, VERSION, MANUFACTURER, MODEL +from custom_components.solis_modbus.const import POLL_INTERVAL_SECONDS, DOMAIN, CONTROLLER, VERSION, MANUFACTURER, \ + MODEL, VALUES, ENTITIES, SWITCH_ENTITIES _LOGGER = logging.getLogger(__name__) @@ -34,14 +35,14 @@ async def async_setup_entry(hass, config_entry: ConfigEntry, async_add_devices): switchEntities: List[SolisBinaryEntity] = [] for main_entity in switch_sensors: - for child_entity in main_entity['entities']: + for child_entity in main_entity[ENTITIES]: type = child_entity["type"] if type == "SBS": child_entity['read_register'] = main_entity['read_register'] child_entity['write_register'] = main_entity['write_register'] switchEntities.append(SolisBinaryEntity(hass, modbus_controller, child_entity)) - hass.data[DOMAIN]['switch_entities'] = switchEntities + hass.data[DOMAIN][SWITCH_ENTITIES] = switchEntities async_add_devices(switchEntities, True) @callback @@ -73,7 +74,7 @@ def __init__(self, hass, modbus_controller, entity_definition): def update(self): """Update Modbus data periodically.""" - value: int = self._hass.data[DOMAIN]['values'][str(self._read_register)] + value: int = self._hass.data[DOMAIN][VALUES][str(self._read_register)] initial_state = self._attr_is_on if not self._attr_available: @@ -101,7 +102,7 @@ def turn_off(self, **kwargs: Any) -> None: def set_register_bit(self, value): """Set or clear a specific bit in the Modbus register.""" controller = self._hass.data[DOMAIN][CONTROLLER] - current_register_value: int = self._hass.data[DOMAIN]['values'][str(self._read_register)] + current_register_value: int = self._hass.data[DOMAIN][VALUES][str(self._read_register)] new_register_value: int = set_bit(current_register_value, self._bit_position, value) _LOGGER.debug( @@ -109,7 +110,7 @@ def set_register_bit(self, value): # we only want to write when values has changed. After, we read the register again to make sure it applied. if current_register_value != new_register_value and controller.connected(): self._hass.create_task(controller.async_write_holding_register(self._write_register, new_register_value)) - self._hass.data[DOMAIN]['values'][str(self._read_register)] = new_register_value + self._hass.data[DOMAIN][VALUES][str(self._read_register)] = new_register_value self._attr_is_on = value diff --git a/custom_components/solis_modbus/time.py b/custom_components/solis_modbus/time.py index 6d7db4e..e2b7e7a 100644 --- a/custom_components/solis_modbus/time.py +++ b/custom_components/solis_modbus/time.py @@ -18,7 +18,8 @@ from homeassistant.helpers.entity import DeviceInfo from homeassistant.helpers.event import async_track_time_interval -from custom_components.solis_modbus.const import DOMAIN, CONTROLLER, VERSION, POLL_INTERVAL_SECONDS, MANUFACTURER, MODEL +from custom_components.solis_modbus.const import DOMAIN, CONTROLLER, VERSION, POLL_INTERVAL_SECONDS, MANUFACTURER, \ + MODEL, TIME_ENTITIES, VALUES _LOGGER = logging.getLogger(__name__) @@ -60,13 +61,13 @@ async def async_setup_entry(hass, config_entry: ConfigEntry, async_add_devices): type = entity_definition["type"] if type == "STE": timeEntities.append(SolisTimeEntity(hass, modbus_controller, entity_definition)) - hass.data[DOMAIN]['time_entities'] = timeEntities + hass.data[DOMAIN][TIME_ENTITIES] = timeEntities async_add_devices(timeEntities, True) @callback async def async_update(now): """Update Modbus data periodically.""" - await asyncio.gather(*[entity.async_update() for entity in hass.data[DOMAIN]["time_entities"]]) + await asyncio.gather(*[entity.async_update() for entity in hass.data[DOMAIN][TIME_ENTITIES]]) # Schedule the update function to run every X seconds async_track_time_interval(hass, async_update, timedelta(seconds=POLL_INTERVAL_SECONDS * 5)) @@ -109,8 +110,8 @@ async def async_update(self): controller = self._hass.data[DOMAIN][CONTROLLER] self._attr_available = True - hour = self._hass.data[DOMAIN]['values'][str(self._register)] - minute = self._hass.data[DOMAIN]['values'][str(self._register + 1)] + hour = self._hass.data[DOMAIN][VALUES][str(self._register)] + minute = self._hass.data[DOMAIN][VALUES][str(self._register + 1)] if (hour == 0 or minute == 0) and controller.connected(): new_vals = await controller.async_read_holding_register(self._register, count=2)