Skip to content

Commit

Permalink
Bugfix/random fixes (#63)
Browse files Browse the repository at this point in the history
fixes #61
  • Loading branch information
Pho3niX90 committed May 31, 2024
1 parent a253363 commit 151e9a3
Show file tree
Hide file tree
Showing 6 changed files with 51 additions and 32 deletions.
12 changes: 11 additions & 1 deletion custom_components/solis_modbus/const.py
Original file line number Diff line number Diff line change
@@ -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'
2 changes: 1 addition & 1 deletion custom_components/solis_modbus/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -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"
}
11 changes: 6 additions & 5 deletions custom_components/solis_modbus/number.py
Original file line number Diff line number Diff line change
Expand Up @@ -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__)

Expand Down Expand Up @@ -76,22 +77,22 @@ 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
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]]
)


Expand Down Expand Up @@ -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()

Expand Down
34 changes: 20 additions & 14 deletions custom_components/solis_modbus/sensor.py
Original file line number Diff line number Diff line change
Expand Up @@ -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__)
Expand All @@ -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 = [
{
Expand Down Expand Up @@ -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))
Expand All @@ -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)

Expand All @@ -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):
Expand All @@ -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

Expand Down Expand Up @@ -757,17 +761,17 @@ 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"""
if drift_counter > 5:
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):
Expand Down Expand Up @@ -909,17 +913,19 @@ 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'):
n_value = hex(round(get_value(self)))[2:]
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:
Expand Down
13 changes: 7 additions & 6 deletions custom_components/solis_modbus/switch.py
Original file line number Diff line number Diff line change
Expand Up @@ -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__)

Expand All @@ -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
Expand Down Expand Up @@ -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:
Expand Down Expand Up @@ -101,15 +102,15 @@ 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(
f"Attempting bit {self._bit_position} to {value} in register {self._read_register}. New value for register {new_register_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

Expand Down
11 changes: 6 additions & 5 deletions custom_components/solis_modbus/time.py
Original file line number Diff line number Diff line change
Expand Up @@ -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__)

Expand Down Expand Up @@ -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))
Expand Down Expand Up @@ -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)
Expand Down

0 comments on commit 151e9a3

Please sign in to comment.