Skip to content

Commit b029528

Browse files
authoredFeb 18, 2024
Merge pull request #754 from cschlipf/passive-mode-timeout
Added support for Passive Mode Timeout
2 parents 02e4a68 + 1a642ca commit b029528

File tree

2 files changed

+102
-38
lines changed

2 files changed

+102
-38
lines changed
 

‎custom_components/solax_modbus/plugin_sofar.py

+79-18
Original file line numberDiff line numberDiff line change
@@ -105,10 +105,15 @@ class SofarModbusSensorEntityDescription(BaseModbusSensorEntityDescription):
105105

106106
def value_function_passivemode(initval, descr, datadict):
107107
return [ (REGISTER_S32, datadict.get('passive_mode_grid_power', 0)),
108-
(REGISTER_S32, datadict.get('passive_mode_battery_power_min', 0)),
109-
(REGISTER_S32, datadict.get('passive_mode_battery_power_max', 0)),
108+
(REGISTER_S32, datadict.get('passive_mode_battery_power_min', 0)),
109+
(REGISTER_S32, datadict.get('passive_mode_battery_power_max', 0)),
110110
]
111111

112+
def value_function_passive_timeout(initval, descr, datadict):
113+
return [ ('passive_mode_timeout', datadict.get('passive_mode_timeout', datadict.get('passive_mode_timeout')), ),
114+
('passive_mode_timeout_action', datadict.get('passive_mode_timeout_action', datadict.get('passive_mode_timeout_action')), ),
115+
]
116+
112117
def value_function_refluxcontrol(initval, descr, datadict):
113118
return [ ('reflux_control', datadict.get('reflux_control', datadict.get('ro_reflux_control')), ),
114119
('reflux_power', datadict.get('reflux_power', 0), ),
@@ -145,6 +150,14 @@ def value_function_toumode(initval, descr, datadict):
145150
write_method = WRITE_MULTI_MODBUS,
146151
value_function = value_function_passivemode,
147152
),
153+
SofarModbusButtonEntityDescription(
154+
name = "Passive: Update Timeout",
155+
key = "passive_mode_update_timeout",
156+
register = 0x1184,
157+
allowedtypes = HYBRID,
158+
write_method = WRITE_MULTI_MODBUS,
159+
value_function = value_function_passive_timeout,
160+
),
148161
SofarModbusButtonEntityDescription(
149162
name = "Sync RTC",
150163
key = "sync_rtc",
@@ -206,13 +219,14 @@ def value_function_toumode(initval, descr, datadict):
206219
device_class = NumberDeviceClass.POWER,
207220
unit = REGISTER_S32,
208221
fmt = "i",
209-
native_max_value = 15000,
210-
native_min_value = -15000,
222+
native_max_value = 20000,
223+
native_min_value = -20000,
211224
native_step = 100,
212225
initvalue = 0,
213226
allowedtypes = HYBRID,
214227
prevent_update = True,
215228
write_method = WRITE_DATA_LOCAL,
229+
icon = "mdi:transmission-tower",
216230
),
217231
SofarModbusNumberEntityDescription(
218232
name = "Passive: Minimum Batter Power",
@@ -221,13 +235,14 @@ def value_function_toumode(initval, descr, datadict):
221235
device_class = NumberDeviceClass.POWER,
222236
unit = REGISTER_S32,
223237
fmt = "i",
224-
native_max_value = 15000,
225-
native_min_value = -15000,
238+
native_max_value = 20000,
239+
native_min_value = -20000,
226240
native_step = 100,
227241
initvalue = 0,
228242
allowedtypes = HYBRID,
229243
prevent_update = True,
230244
write_method = WRITE_DATA_LOCAL,
245+
icon = "mdi:battery-arrow-down",
231246
),
232247
SofarModbusNumberEntityDescription(
233248
name = "Passive: Maximum Battery Power",
@@ -236,13 +251,14 @@ def value_function_toumode(initval, descr, datadict):
236251
device_class = NumberDeviceClass.POWER,
237252
unit = REGISTER_S32,
238253
fmt = "i",
239-
native_max_value = 15000,
240-
native_min_value = -15000,
254+
native_max_value = 20000,
255+
native_min_value = -20000,
241256
native_step = 100,
242257
initvalue = 0,
243258
allowedtypes = HYBRID,
244259
prevent_update = True,
245260
write_method = WRITE_DATA_LOCAL,
261+
icon = "mdi:battery-arrow-up",
246262
),
247263
SofarModbusNumberEntityDescription(
248264
name = "Reflux Power",
@@ -483,6 +499,36 @@ def value_function_toumode(initval, descr, datadict):
483499
entity_category = EntityCategory.CONFIG,
484500
icon = "mdi:battery-clock",
485501
),
502+
SofarModbusSelectEntityDescription(
503+
name = "Passive: Timeout",
504+
key = "passive_mode_timeout",
505+
unit = REGISTER_U16,
506+
write_method = WRITE_DATA_LOCAL,
507+
option_dict = {
508+
0: "Disabled",
509+
300: "5 Minutes",
510+
600: "10 Minutes",
511+
900: "15 Minutes",
512+
1800: "30 Minutes",
513+
3600: "60 Minutes",
514+
5400: "90 Minutes",
515+
7200: "120 Minutes",
516+
},
517+
allowedtypes = HYBRID,
518+
icon = "mdi:timer",
519+
),
520+
SofarModbusSelectEntityDescription(
521+
name = "Passive: Timeout Action",
522+
key = "passive_mode_timeout_action",
523+
unit = REGISTER_U16,
524+
write_method = WRITE_DATA_LOCAL,
525+
option_dict = {
526+
0: "Force Standby",
527+
1: "Return to Previous Mode",
528+
},
529+
allowedtypes = HYBRID,
530+
icon = "mdi:timer-cog",
531+
),
486532
###
487533
#
488534
# Normal select types
@@ -558,6 +604,7 @@ def value_function_toumode(initval, descr, datadict):
558604
},
559605
allowedtypes = HYBRID,
560606
write_method = WRITE_MULTISINGLE_MODBUS,
607+
icon = "mdi:battery-charging-60",
561608
),
562609
# Timing Charge Start
563610
# Timing Charge End
@@ -569,7 +616,7 @@ def value_function_toumode(initval, descr, datadict):
569616

570617

571618

572-
# ================================= Sennsor Declarations ============================================================
619+
# ================================= Sensor Declarations ============================================================
573620

574621
SENSOR_TYPES: list[SofarModbusSensorEntityDescription] = [
575622

@@ -936,6 +983,7 @@ def value_function_toumode(initval, descr, datadict):
936983
newblock = True,
937984
unit = REGISTER_STR,
938985
wordcount=7,
986+
entity_category = EntityCategory.DIAGNOSTIC,
939987
allowedtypes = HYBRID | PV,
940988
),
941989
SofarModbusSensorEntityDescription(
@@ -944,6 +992,7 @@ def value_function_toumode(initval, descr, datadict):
944992
register = 0x44D,
945993
unit = REGISTER_STR,
946994
wordcount=2,
995+
entity_category = EntityCategory.DIAGNOSTIC,
947996
allowedtypes = HYBRID | PV,
948997
),
949998
SofarModbusSensorEntityDescription(
@@ -952,6 +1001,7 @@ def value_function_toumode(initval, descr, datadict):
9521001
register = 0x44F,
9531002
unit = REGISTER_STR,
9541003
wordcount=12,
1004+
entity_category = EntityCategory.DIAGNOSTIC,
9551005
allowedtypes = HYBRID | PV,
9561006
),
9571007
###
@@ -2889,36 +2939,47 @@ def value_function_toumode(initval, descr, datadict):
28892939
allowedtypes = HYBRID,
28902940
),
28912941
SofarModbusSensorEntityDescription(
2892-
name = "Passive Mode Timeout",
2893-
key = "passive_mode_timeout",
2942+
name = "RO: Passive: Timeout",
2943+
key = "ro_passive_mode_timeout",
28942944
register = 0x1184,
2895-
entity_registry_enabled_default = False,
2945+
allowedtypes = HYBRID,
2946+
entity_category = EntityCategory.DIAGNOSTIC,
2947+
),
2948+
SofarModbusSensorEntityDescription(
2949+
name = "Passive: Timeout Action",
2950+
key = "ro_passive_mode_timeout_action",
2951+
register = 0x1185,
2952+
scale = { 0: "Force Standby",
2953+
1: "Return to Previous Mode", },
28962954
allowedtypes = HYBRID,
28972955
entity_category = EntityCategory.DIAGNOSTIC,
28982956
),
28992957
SofarModbusSensorEntityDescription(
29002958
name = "Passive: Desired Grid Power",
2901-
key = "ro_passive_mode_gdes",
2959+
key = "passive_mode_grid_power",
29022960
unit = REGISTER_S32,
2961+
entity_registry_enabled_default = False,
29032962
register = 0x1187,
2904-
#entity_registry_enabled_default = False,
29052963
allowedtypes = HYBRID,
2964+
entity_category = EntityCategory.DIAGNOSTIC,
29062965
),
29072966
SofarModbusSensorEntityDescription(
29082967
name = "Passive: Minimum Battery Power",
2909-
key = "ro_passive_mode_lower",
2968+
key = "passive_mode_battery_power_min",
29102969
unit = REGISTER_S32,
29112970
register = 0x1189,
2912-
#entity_registry_enabled_default = False,
2971+
entity_registry_enabled_default = False,
29132972
allowedtypes = HYBRID,
2973+
entity_category = EntityCategory.DIAGNOSTIC,
29142974
),
29152975
SofarModbusSensorEntityDescription(
29162976
name = "Passive: Maximum Battery Power",
2917-
key = "ro_passive_mode_upper",
2977+
key = "passive_mode_battery_power_max",
29182978
unit = REGISTER_S32,
29192979
register = 0x118B,
2920-
#entity_registry_enabled_default = False,
2980+
entity_registry_enabled_default = False,
29212981
allowedtypes = HYBRID,
2982+
entity_category = EntityCategory.DIAGNOSTIC,
29222983
),
29232984
]
29242985

‎docs/sofar-operation-modes.md

+23-20
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
# Sofar Modes of Operation
22

3-
WARNING: Work in progress, some of this information may be inaccurate. Use at your own risk
4-
53
WARNING: most of the writeable parameters are written to EEPROM of the inverter after each modification. EEPROM has a limited (typically 100000) number of write cycles, so be careful that your automations do not modify these parameters too frequently.
64

75
The modes are controlled through "Charger Use Mode", where you can choose one of the following modes by simply selecting one of these values:
@@ -58,25 +56,20 @@ _TBD: Describe how to use Timing Mode with the Integration_
5856
The passive mode is designed for controlling the inverter with external energy management systems and allows fine control over its operations. So as you are using Home Assistant, this might be the most interesting mode for you besides the default "Self Use" mode.
5957

6058
When the inverter is in "Passive Mode" it can be controlled through:
61-
- **Passive: Desired Grid Power**: _Number in Watt_.
62-
63-
Set the desired power that is taken from the Grid. The system will try to achieve this level within the boundaries of the current consumption, the current production, and the boundaries set by the battery parameters below. Positive values indicate power flow from grid to the system (grid consumption). Negative values indicate power flow from system to the grid (feed-in).
64-
65-
- **Passive: Maximum Battery Power**: _Number in Watt_.
6659

67-
Limit the maximum battery power. Must be greater than or equal to "Passive Minimum Battery Power". Positive values indicate charging, negative values indicate discharging.
60+
- **Passive: Desired Grid Power**: _Number in Watt_. Set the desired power that is taken from the Grid. The system will try to achieve this level within the boundaries of the current consumption, the current production, and the boundaries set by the battery parameters below. Positive values indicate power flow from grid to the system (grid consumption). Negative values indicate power flow from system to the grid (feed-in). Note that after changing the value in this field you have two minutes to commit the new value to the system using the button below. After two minutes the value will be restored to the value that's stored in the system.
6861

69-
- **Passive: Minimum Battery Power**: _Number in Watt_.
62+
- **Passive: Maximum Battery Power**: _Number in Watt_. Limit the maximum battery power. Must be greater than or equal to "Passive Minimum Battery Power". Positive values indicate charging, negative values indicate discharging. Note that after changing the value in this field you have two minutes to commit the new value to the system using the button below. After two minutes the value will be restored to the value that's stored in the system.
7063

71-
Limit the minimum battery power. Must be less than or equal to "Passive Maximum Battery Power". Positive values indicate charging, negative values indicate discharging.
64+
- **Passive: Minimum Battery Power**: _Number in Watt_. Limit the minimum battery power. Must be less than or equal to "Passive Maximum Battery Power". Positive values indicate charging, negative values indicate discharging. Note that after changing the value in this field you have two minutes to commit the new value to the system using the button below. After two minutes the value will be restored to the value that's stored in the system.
7265

73-
- **Passive: Update Battery Charge/Discharge**: _Button_.
74-
75-
After changing "Desired Grid Power", "Maximum Battery Power", or "Minimum Battery Power" this button must be pressed to commit these values to the system. Without pressing this button after changing one or multiple of these values nothing will happen.
66+
- **Passive: Update Battery Charge/Discharge**: _Button_. After changing "Desired Grid Power", "Maximum Battery Power", or "Minimum Battery Power" this button must be pressed to commit these values to the system. Without pressing this button after changing one or multiple of these values nothing will happen.
7667

7768
Let's have a look at some examples that illustrate how you can use these values to control the energy flow of your inverter:
7869

79-
### Same Operation like "Self Use"
70+
### Examples
71+
72+
#### Same Operation like "Self Use"
8073

8174
You might rather want to just set the "Self Use" mode, but here is what it would look like it "Passive Mode":
8275

@@ -90,7 +83,7 @@ Result:
9083

9184
System tries to pull no energy from the grid. If that is not possible it discharges the battery. In case there is enough PV generation it charges the battery or feeds-in the excess power to the grid. System operates just like in "Self Use".
9285

93-
### Limit Battery Charging Power
86+
#### Limit Battery Charging Power
9487

9588
You want to limit the charging power to 2kWh to allow more power for other consumers, e.g. charging your car. Useful for example, if you have a 3 phased charger, which requires at least 4.3 kW to start charging, however the PV production is not enough to cover battery charging and minimum power to start charging the car.
9689

@@ -104,7 +97,7 @@ Result:
10497

10598
System operates like in "Self Use", however the battery is charged with a maximum of 2 kWh that can be consumed by other power consumers.
10699

107-
### Prevent Battery Discharging
100+
#### Prevent Battery Discharging
108101

109102
You want to charge the battery with the PV generation, but would like to prevent it from discharging. E.g. in the winter you want to enforce a full charge cycle over the course of multiple days with little power generation while avoiding pulling extra power from the grid for charging the battery.
110103

@@ -120,7 +113,7 @@ Result:
120113
- If PV generation is larger than consumption, battery will be charged with up to 10 kW. If your battery cannot be charged with 10 kW it will automatically be charged with the maximum amount of power the battery can handle (BTS-5K: 2.5 kWh per module). Excess power will be fed-in to the grid.
121114
- If PV generation is less than consumption, power will be pulled from the grid. Battery will not be discharged.
122115

123-
### Force Battery Charging
116+
#### Force Battery Charging
124117

125118
You want to load the battery with a at least 3.5 kWh, but a maximum of 5 kWh.
126119

@@ -136,7 +129,7 @@ Result:
136129

137130
Note: Battery management will override the minimum battery power of course. So when the battery is nearly full, charging power will still be reduced even below the value of "Minimum Battery Power" and when the battery is full, charging will be stopped.
138131

139-
### Provide Feed-in Power If Possible
132+
#### Provide Feed-in Power If Possible
140133

141134
As long as possible you want to prioritize feeding-in at least 1 kW to the grid. Maybe you have the luxury that you get a higher price for feeding in energy than consuming it.
142135

@@ -149,9 +142,19 @@ Values:
149142
Result:
150143

151144
- If PV generation is less than the sum of 1 kW and the consumption of all power consumers, the difference will be fed-in to the grid. Battery will not be discharged.
152-
- If PV generation is more than the sum of 1kW and the consumption of all power consumers, 1 kW will be fed-in to the grid. Additional power will be used to charge the battery up to its maximum charging power. If PV generation exceeds the maximum charging power it will also be ged in
145+
- If PV generation is more than the sum of 1kW and the consumption of all power consumers, 1 kW will be fed-in to the grid. Additional power will be used to charge the battery up to its maximum charging power. If PV generation exceeds the maximum charging power additional excess power will be fed-in to the grid.
146+
147+
**IMPORTANT:** Check your local regulations. Many grid operators do not permit feeding in power from the battery to the grid. If you set minimum battery power to negative values, while setting "Desired Grid Power" and/or "Maximum Battery Power" to negative values, you are potentially feeding in power from the battery. While this is technically possible in "Passive Mode" and actually works it might be prohibited by law.
148+
149+
### Timeout and Timeout Action
150+
151+
When in passive mode the inverter can perform a configurable action after it did not receive any communication for longer than a configurable time. This may not be important for automation, however if set to non-default values, it could lead to unexpected side effects.
152+
153+
- **Passive: Timeout**: _Default: Disabled_. The timeout after which the configured timeout action will be executed. Note that the displayed value in this field does not necessarily reflect the current value that is set in the inverter. See the entity "RO: Passive: Timeout" for checking the current value, which will be displayed in number of seconds, where 0 means 'Disabled'.
154+
155+
- **Passive: Timeout Action**: _Default: Force Standby". The timeout action that will be executed after which the configured timeout has passed. By default "Force Standby" is selected. "Return to Previous Mode" will set the previously selected "Charger Use Mode", i.e. if the inverter was switched from "Self Use" into "Passive Mode" the inverter will switch back to "Self Use" after not receiving any communication for the configured "Passive: Timeout". Note that the displayed value in this field does not necessarily reflect the current value that is set in the inverter. See the entity "RO: Passive: Timeout Action" for checking the current value.
153156

154-
**IMPORTANT:** Check your local regulations. Many grid operators do not permit feeding in power from the battery to the grid. If you set minimum battery power to negative values, while setting "Desired Grid Power" and/or "Maximum Battery Power" to negative values, you are potentially feeding in power from the battery. While this is possible in "Passive Mode" and actually works it might be prohibited by law.
157+
- **Passive: Update Timeout**: _Button_. After chaning "Passive: Timeout" or "Passive: Timeout Action" this button must be pressed to commit the values to the system. Please allow the system several minutes to reflect the changes in the corresponding read-only values.
155158

156159

157160
## Off-Grid (EPS)

0 commit comments

Comments
 (0)