Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/string inverters #86

Open
wants to merge 6 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 13 additions & 1 deletion custom_components/solis_modbus/config_flow.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,18 @@ async def async_step_user(self, user_input=None):
step_id="user", data_schema=self._get_user_schema(), errors=errors
)

# string inverters => RS485_MODBUS%20Communication%20Protocol_Solis%20Inverters%20(1).pdf

async def _validate_config(self, user_input):
"""Validate the configuration by trying to connect to the Modbus device."""
modbus_controller = ModbusController(user_input["host"], user_input.get("port", 502))
try:
if user_input["type"] == "string":
await modbus_controller.async_read_input_register(3262)
else:
await modbus_controller.async_read_input_register(33263)

await modbus_controller.connect()
await modbus_controller.async_read_input_register(33093)
return True
except ConnectionError:
return False
Expand All @@ -44,5 +50,11 @@ def _get_user_schema(self):
{
vol.Required("host", default="", description="your solis ip"): str,
vol.Required("port", default=502, description="port of your modbus, typically 502 or 8899"): int,
vol.Optional("type", default="hybrid", description="type of your modbus connection"): vol.In(["string", "hybrid"]),
}
)

def _get_config(self, config):
"""Ensure 'type' defaults to 'hybrid' if not previously set."""
config.setdefault("type", "hybrid")
return config
633 changes: 633 additions & 0 deletions custom_components/solis_modbus/data/hybrid_sensors.py

Large diffs are not rendered by default.

122 changes: 122 additions & 0 deletions custom_components/solis_modbus/data/string_sensors.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
from homeassistant.components.sensor.const import SensorDeviceClass, SensorStateClass
from homeassistant.const import UnitOfElectricPotential, UnitOfElectricCurrent, UnitOfPower, UnitOfTime, UnitOfEnergy, \
UnitOfReactivePower, UnitOfFrequency, UnitOfTemperature, UnitOfApparentPower, PERCENTAGE

string_sensors = [
{
"register_start": 36013,
"scan_interval": 0,
"entities": [
{"type": "SS", "name": "Solis Model No", "unique": "solis_modbus_inverter_model_no",
"register": ['36013'], "multiplier": 0},
{"type": "SS", "name": "Solis Inverter EPM Firmware Version", "unique": "solis_modbus_inverter_epm_firmware_version",
"register": ['36014'], "multiplier": 0},
]
},
{
"register_start": 36022,
"scan_interval": 60,
"entities": [

{"type": "SS", "name": "Solis Clock (Hours)",
"unique": "solis_modbus_inverter_clock_hours",
"register": ['36022'], "multiplier": 0,
"unit_of_measurement": UnitOfTime.HOURS, "state_class": SensorStateClass.MEASUREMENT},
{"type": "SS", "name": "Solis Clock (Minutes)",
"unique": "solis_modbus_inverter_clock_minutes",
"register": ['36023'], "multiplier": 0,
"unit_of_measurement": UnitOfTime.MINUTES, "state_class": SensorStateClass.MEASUREMENT},
{"type": "SS", "name": "Solis Clock (Seconds)",
"unique": "solis_modbus_inverter_clock_seconds",
"register": ['36024'], "multiplier": 0,
"unit_of_measurement": UnitOfTime.SECONDS, "state_class": SensorStateClass.MEASUREMENT},
]
},
{
"register_start": 36028,
"scan_interval": 60,
"entities": [
{"type": "SS", "name": "Solis Total Load power",
"unique": "solis_modbus_inverter_total_load_power",
"register": ['36028', '36029'], "device_class": SensorDeviceClass.POWER, "multiplier": 100,
"unit_of_measurement": UnitOfPower.WATT, "state_class": SensorStateClass.MEASUREMENT}
]
},
{
"register_start": 36050,
"scan_interval": 60,
"entities": [
{"type": "SS", "name": "Solis Total Generation Energy",
"unique": "solis_modbus_inverter_total_generation_energy",
"register": ['36050', '36051'], "device_class": SensorDeviceClass.ENERGY, "multiplier": 0.01,
"unit_of_measurement": UnitOfEnergy.KILO_WATT_HOUR, "state_class": SensorStateClass.TOTAL_INCREASING},

{"type": "SS", "name": "Solis Load Total Consumption Energy",
"unique": "solis_modbus_inverter_total_load_power",
"register": ['36052', '36053'], "device_class": SensorDeviceClass.ENERGY, "multiplier": 0.01,
"unit_of_measurement": UnitOfEnergy.KILO_WATT_HOUR, "state_class": SensorStateClass.TOTAL_INCREASING},

{"type": "SS", "name": "Solis Grid Import Total Active Energy",
"unique": "solis_modbus_inverter_grid_import_total_active_energy",
"register": ['36054', '36055'], "device_class": SensorDeviceClass.ENERGY, "multiplier": 0.01,
"unit_of_measurement": UnitOfEnergy.KILO_WATT_HOUR, "state_class": SensorStateClass.TOTAL_INCREASING},

{"type": "SS", "name": "Solis Grid Export Total Active Energy",
"unique": "solis_modbus_inverter_grid_export_total_active_energy",
"register": ['36056', '36057'], "device_class": SensorDeviceClass.ENERGY, "multiplier": 0.01,
"unit_of_measurement": UnitOfEnergy.KILO_WATT_HOUR, "state_class": SensorStateClass.TOTAL_INCREASING},
]
},
{
"register_start": 33005,
"scan_interval": 15,
"entities": [
{"type": "SS", "name": "Solis Active Power",
"unique": "solis_modbus_inverter_active_power",
"register": ['33005', '33006'], "device_class": SensorDeviceClass.POWER, "multiplier": 1,
"unit_of_measurement": UnitOfPower.WATT, "state_class": SensorStateClass.MEASUREMENT},

{"type": "SS", "name": "Solis Total DC Output Power",
"unique": "solis_modbus_inverter_total_dc_output_power",
"register": ['33007', '33008'], "device_class": SensorDeviceClass.POWER, "multiplier": 1,
"unit_of_measurement": UnitOfPower.WATT, "state_class": SensorStateClass.MEASUREMENT},
]
},
]

string_sensors_derived = [
{"type": "SDS", "name": "Solis Status String",
"unique": "solis_modbus_inverter_current_status_string", "multiplier": 0,
"register": ['33095']},

{"type": "SDS", "name": "Solis PV Power 1",
"unique": "solis_modbus_inverter_dc_power_1", "device_class": SensorDeviceClass.POWER, "multiplier": 0.1,
"unit_of_measurement": UnitOfPower.WATT, "state_class": SensorStateClass.MEASUREMENT,
"register": ['33049', '33050']},

{"type": "SDS", "name": "Solis PV Power 2",
"unique": "solis_modbus_inverter_dc_power_2", "device_class": SensorDeviceClass.POWER, "multiplier": 0.1,
"unit_of_measurement": UnitOfPower.WATT, "state_class": SensorStateClass.MEASUREMENT,
"register": ['33051', '33052']},

{"type": "SDS", "name": "Solis PV Power 3",
"unique": "solis_modbus_inverter_dc_power_3", "device_class": SensorDeviceClass.POWER, "multiplier": 0.1,
"unit_of_measurement": UnitOfPower.WATT, "state_class": SensorStateClass.MEASUREMENT,
"register": ['33053', '33054']},

{"type": "SDS", "name": "Solis PV Power 4",
"unique": "solis_modbus_inverter_dc_power_4", "device_class": SensorDeviceClass.POWER, "multiplier": 0.1,
"unit_of_measurement": UnitOfPower.WATT, "state_class": SensorStateClass.MEASUREMENT,
"register": ['33055', '33056']},

{"type": "SDS", "name": "Solis Battery Charge Power",
"unique": "solis_modbus_inverter_battery_charge_power", "device_class": SensorDeviceClass.POWER,
"multiplier": 0.1,
"unit_of_measurement": UnitOfPower.WATT, "state_class": SensorStateClass.MEASUREMENT,
"register": ['33149', '33150', '33135', '0']},
{"type": "SDS", "name": "Solis Battery Discharge Power",
"unique": "solis_modbus_inverter_battery_discharge_power", "device_class": SensorDeviceClass.POWER,
"multiplier": 0.1,
"unit_of_measurement": UnitOfPower.WATT, "state_class": SensorStateClass.MEASUREMENT,
"register": ['33149', '33150', '33135', '1']}
]
14 changes: 9 additions & 5 deletions custom_components/solis_modbus/modbus_controller.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ async def connect(self):
return True

except Exception as e:
_LOGGER.error(f"Failed to connect to Modbus device. Will retry. Exception: {e}")
_LOGGER.debug(f"Failed to connect to Modbus device. Will retry. Exception: {e}")
return False # Return False if an exception occurs


Expand All @@ -42,7 +42,8 @@ async def async_read_input_register(self, register, count=1):
_LOGGER.debug(f'register value, register = {register}, result = {result.registers}')
return result.registers
except Exception as e:
raise _LOGGER.error(f"Failed to read Modbus register: {str(e)}")
_LOGGER.debug(f"Failed to read Modbus holding register: {str(e)}")
return None

async def async_read_holding_register(self, register: int, count=1):
try:
Expand All @@ -52,7 +53,8 @@ async def async_read_holding_register(self, register: int, count=1):
_LOGGER.debug(f'holding register value, register = {register}, result = {result.registers}')
return result.registers
except Exception as e:
raise _LOGGER.error(f"Failed to read Modbus holding register: {str(e)}")
_LOGGER.debug(f"Failed to read Modbus holding register: {str(e)}")
return None

async def async_write_holding_register(self, register: int, value):
try:
Expand All @@ -61,7 +63,8 @@ async def async_write_holding_register(self, register: int, value):
result = await self.client.write_register(register, value, slave=1)
return result
except Exception as e:
raise _LOGGER.error(f"Failed to write Modbus holding register ({register}): {str(e)}")
_LOGGER.debug(f"Failed to write Modbus holding register ({register}): {str(e)}")
return None

async def async_write_holding_registers(self, start_register: int, values: list[int]):
try:
Expand All @@ -70,8 +73,9 @@ async def async_write_holding_registers(self, start_register: int, values: list[
result = await self.client.write_registers(start_register, values, slave=1)
return result
except Exception as e:
raise _LOGGER.error(
_LOGGER.debug(
f"Failed to write Modbus holding registers ({start_register}), values = {values}: {str(e)}")
return None

def close_connection(self):
self.client.close()
Expand Down
5 changes: 5 additions & 0 deletions custom_components/solis_modbus/number.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,11 @@ async def async_setup_entry(hass, config_entry: ConfigEntry, async_add_devices):
# We only want this platform to be set up via discovery.
_LOGGER.info("Options %s", len(config_entry.options))

inverter_type = config_entry.data.get("type", "hybrid")

if inverter_type == 'string':
return False

platform_config = config_entry.data or {}
if len(config_entry.options) > 0:
platform_config = config_entry.options
Expand Down
Loading
Loading