Skip to content

Commit c0e7e50

Browse files
committed
feat: Add support for all three configurations H1, H2 and H3 of Pylontech Force
Signed-off-by: David Rapan <[email protected]>
1 parent 30f3a43 commit c0e7e50

File tree

15 files changed

+666
-432
lines changed

15 files changed

+666
-432
lines changed

custom_components/solarman/__init__.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,10 @@ async def async_migrate_entry(hass: HomeAssistant, config_entry: SolarmanConfigE
9999
bulk_safe_delete(new_data, OLD_)
100100
bulk_safe_delete(new_options, OLD_ | to_dict(CONF_BATTERY_NOMINAL_VOLTAGE, CONF_BATTERY_LIFE_CYCLE_RATING))
101101

102-
if not new_options.get(CONF_ADDITIONAL_OPTIONS):
102+
if a := new_options.get(CONF_ADDITIONAL_OPTIONS):
103+
if isinstance(m := a.get(CONF_MOD), bool):
104+
m = int(m)
105+
else:
103106
del new_options[CONF_ADDITIONAL_OPTIONS]
104107

105108
hass.config_entries.async_update_entry(config_entry, unique_id = None, data = new_data, options = new_options, minor_version = ConfigFlowHandler.MINOR_VERSION, version = ConfigFlowHandler.VERSION)

custom_components/solarman/common.py

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -172,19 +172,21 @@ def strepr(value):
172172

173173
def unwrap(source: dict, key: Any, mod: int = 0):
174174
if (c := source.get(key)) is not None and isinstance(c, list):
175-
source[key] = c[mod]
175+
source[key] = c[mod] if mod < len(c) else c[-1]
176176
return source
177177

178178
def entity_key(object: dict):
179179
return slugify('_'.join(filter(None, (object["name"], object["platform"]))))
180180

181181
def preprocess_descriptions(item, group, table, code, parameters):
182182
def modify(source: dict):
183-
for i in source:
183+
for i in dict(source):
184184
if i in ("scale", "min", "max"):
185-
unwrap(source, i, parameters["mod"])
185+
unwrap(source, i, parameters[CONF_MOD])
186186
if i == "registers" and source[i] and (isinstance(source[i], list) and isinstance(source[i][0], list)):
187-
unwrap(source, i, parameters["mod"])
187+
unwrap(source, i, parameters[CONF_MOD])
188+
if not source[i]:
189+
source["disabled"] = True
188190
elif isinstance(source[i], dict):
189191
modify(source[i])
190192

@@ -209,7 +211,7 @@ def modify(source: dict):
209211
g = dict(group)
210212
g.pop("items")
211213
bulk_inherit(item, g, *() if "registers" in item else REQUEST_UPDATE_INTERVAL)
212-
if not REQUEST_CODE in item and (r := item.get("registers")) is not None and (addr := min(r)) is not None:
214+
if not REQUEST_CODE in item and (r := item.get("registers")) and (addr := min(r)) is not None:
213215
item[REQUEST_CODE] = table.get(addr, code)
214216
return item
215217

custom_components/solarman/config_flow.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@
3838
vol.Required(CONF_ADDITIONAL_OPTIONS): section(
3939
vol.Schema(
4040
{
41-
vol.Optional(CONF_MOD, default = DEFAULT_[CONF_MOD], description = {SUGGESTED_VALUE: DEFAULT_[CONF_MOD]}): bool,
41+
vol.Optional(CONF_MOD, default = DEFAULT_[CONF_MOD], description = {SUGGESTED_VALUE: DEFAULT_[CONF_MOD]}): vol.All(vol.Coerce(int), vol.Range(min = 0, max = 2)),
4242
vol.Optional(CONF_MPPT, default = DEFAULT_[CONF_MPPT], description = {SUGGESTED_VALUE: DEFAULT_[CONF_MPPT]}): vol.All(vol.Coerce(int), vol.Range(min = 1, max = 12)),
4343
vol.Optional(CONF_PHASE, default = DEFAULT_[CONF_PHASE], description = {SUGGESTED_VALUE: DEFAULT_[CONF_PHASE]}): vol.All(vol.Coerce(int), vol.Range(min = 1, max = 3)),
4444
vol.Optional(CONF_PACK, default = DEFAULT_[CONF_PACK], description = {SUGGESTED_VALUE: DEFAULT_[CONF_PACK]}): vol.All(vol.Coerce(int), vol.Range(min = -1, max = 20)),
@@ -90,8 +90,8 @@ def remove_defaults(user_input: dict[str, Any]):
9090
return user_input
9191

9292
class ConfigFlowHandler(ConfigFlow, domain = DOMAIN):
93-
MINOR_VERSION = 9
94-
VERSION = 1
93+
MINOR_VERSION = 0
94+
VERSION = 2
9595

9696
async def async_step_dhcp(self, discovery_info: DhcpServiceInfo) -> ConfigFlowResult:
9797
_LOGGER.debug(f"ConfigFlowHandler.async_step_dhcp: {discovery_info}")

custom_components/solarman/const.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@
4747
CONF_TRANSPORT: "tcp",
4848
CONF_MB_SLAVE_ID: 1,
4949
CONF_LOOKUP_FILE: "Auto",
50-
CONF_MOD: False,
50+
CONF_MOD: 0,
5151
CONF_MPPT: 4,
5252
CONF_PHASE: 3,
5353
CONF_PACK: -1,
@@ -77,7 +77,7 @@
7777
AUTODETECTION_BATTERY_REQUEST_DEYE = (AUTODETECTION_CODE_DEYE, *AUTODETECTION_BATTERY_REGISTERS_DEYE)
7878
AUTODETECTION_BATTERY_NUMBER_DEYE = (AUTODETECTION_CODE_DEYE, AUTODETECTION_BATTERY_REGISTERS_DEYE[0])
7979

80-
PROFILE_REDIRECT = { "sofar_hyd3k-6k-es.yaml": "sofar_wifikit.yaml:mod=True", "hyd-zss-hp-3k-6k.yaml": "sofar_g3.yaml:pack=1", "solis_1p8k-5g.yaml": "solis_1p-5g.yaml", "solis_3p-4g+.yaml": "solis_3p-4g.yaml", "sofar_hyd-es.yaml": "sofar_wifikit.yaml:mod=True", "sofar_tlx-g3.yaml": "sofar_g3.yaml", "zcs_azzurro-1ph-tl-v3.yaml": "sofar_lsw3.yaml:mppt=1&l=1", "zcs_azzurro-hyd-zss-hp.yaml": "sofar_g3.yaml:pack=1", "zcs_azzurro-ktl-v3.yaml": "sofar_g3.yaml" }
80+
PROFILE_REDIRECT = { "sofar_hyd3k-6k-es.yaml": "sofar_wifikit.yaml:mod=1", "hyd-zss-hp-3k-6k.yaml": "sofar_g3.yaml:pack=1", "solis_1p8k-5g.yaml": "solis_1p-5g.yaml", "solis_3p-4g+.yaml": "solis_3p-4g.yaml", "sofar_hyd-es.yaml": "sofar_wifikit.yaml:mod=1", "sofar_tlx-g3.yaml": "sofar_g3.yaml", "zcs_azzurro-1ph-tl-v3.yaml": "sofar_lsw3.yaml:mppt=1&l=1", "zcs_azzurro-hyd-zss-hp.yaml": "sofar_g3.yaml:pack=1", "zcs_azzurro-ktl-v3.yaml": "sofar_g3.yaml" }
8181

8282
PARAM_ = { CONF_MOD: CONF_MOD, CONF_MPPT: CONF_MPPT, CONF_PHASE: "l", CONF_PACK: CONF_PACK }
8383

0 commit comments

Comments
 (0)