Skip to content

Commit ffc4145

Browse files
committed
Add more validation, be more gentle writing blocks
1 parent 5671f15 commit ffc4145

File tree

2 files changed

+48
-11
lines changed

2 files changed

+48
-11
lines changed

SOFAR-HYD-3PH-AND-G3.json

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,8 @@
8282
"register": "0x1044",
8383
"desc": "battery id",
8484
"type": "U16",
85+
"min": 0,
86+
"max": 7,
8587
"ha": {
8688
"name": "Battery ID",
8789
"icon": "mdi:identifier",
@@ -102,6 +104,8 @@
102104
"register": "0x1045",
103105
"desc": "battery address",
104106
"type": "U16",
107+
"min": 0,
108+
"max": 99,
105109
"ha": {
106110
"name": "Battery Address",
107111
"icon": "mdi:identifier",
@@ -164,6 +168,8 @@
164168
"type": "U16",
165169
"function": "divide",
166170
"factor": 10,
171+
"min": 0.0,
172+
"max": 65535.0,
167173
"ha": {
168174
"name": "Battery Over Voltage",
169175
"icon": "mdi:alpha-v-box",
@@ -208,6 +214,8 @@
208214
"type": "U16",
209215
"function": "divide",
210216
"factor": 10,
217+
"min": 0.0,
218+
"max": 65535.0,
211219
"ha": {
212220
"name": "Battery Lack Voltage",
213221
"icon": "mdi:alpha-v-box",
@@ -230,6 +238,8 @@
230238
"type": "U16",
231239
"function": "divide",
232240
"factor": 10,
241+
"min": 0.0,
242+
"max": 65535.0,
233243
"ha": {
234244
"name": "Battery Discharge Stop Voltage",
235245
"icon": "mdi:alpha-v-box",
@@ -252,6 +262,8 @@
252262
"type": "U16",
253263
"function": "divide",
254264
"factor": 100,
265+
"min": 0,
266+
"max": 65535,
255267
"ha": {
256268
"name": "Battery Charge Current Limit",
257269
"icon": "mdi:alpha-a-box",
@@ -274,6 +286,8 @@
274286
"type": "U16",
275287
"function": "divide",
276288
"factor": 100,
289+
"min": 0,
290+
"max": 65535,
277291
"ha": {
278292
"name": "Battery Discharge Current Limit",
279293
"icon": "mdi:alpha-a-box",
@@ -302,7 +316,7 @@
302316
"name": "Battery Depth of Discharge SOC",
303317
"icon": "mdi:percent-outline",
304318
"entity_category": "config",
305-
"min": 10,
319+
"min": 1,
306320
"max": 90,
307321
"mode": "box",
308322
"command_topic": "sofar/rw/battery_config/depth_of_discharge",
@@ -317,6 +331,8 @@
317331
"register": "0x104E",
318332
"desc": "EOD indicate the max discharge power on off grid mode, when SOC<1-EOD, inverter will stop power discharge , inverter will stop power discharge caused by other issues",
319333
"type": "U16",
334+
"min": 1,
335+
"max": 90,
320336
"ha": {
321337
"name": "Battery Off-Grid Depth of Discharge",
322338
"icon": "mdi:percent-outline",
@@ -405,6 +421,8 @@
405421
"register": "0x1052",
406422
"desc": "battery eps buffer",
407423
"type": "U16",
424+
"min": 5,
425+
"max": 100,
408426
"ha": {
409427
"name": "Battery EPS Buffer",
410428
"icon": "mdi:percent-outline",

sofar2mqtt-v2.py

Lines changed: 29 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -713,14 +713,17 @@ def write_register_block(self, block_name, update_register, new_value):
713713
return
714714

715715
start_register = int(block['start_register'], 16)
716-
length = int(block['length'])
716+
required_length = int(block['length'])
717717
values = []
718718
raw_value = None
719719
for register_name in block['registers']:
720720
if register_name == update_register:
721721
register = self.get_register(register_name)
722722
if register:
723-
raw_value = self.translate_to_raw_value(register, new_value)
723+
new_raw_value = self.translate_to_raw_value(register, new_value)
724+
if not validate_new_value(register, new_raw_value):
725+
return
726+
raw_value = new_raw_value
724727
else:
725728
logging.error(f"Register {register_name} not found in configuration")
726729
continue
@@ -733,10 +736,6 @@ def write_register_block(self, block_name, update_register, new_value):
733736
if 'append' in block:
734737
for append_item in block['append']:
735738
values.append(append_item)
736-
#logging.info(f"Would write {block['start_register']} with {values[:length]}")
737-
#logging.info(f"Reference values: {[0, 0, 1, 560, 540, 425, 470, 10000, 10000, 90, 90, 250, 480, 1, 10, 1]}")
738-
# [0, 0, 1, 540, 530, 425, 470, 10000, 10000, 89, 90, 250, 480, 1, 10, 1]
739-
#self.write_registers_with_retry(block['start_register'], [0, 0, 1, 560, 540, 425, 470, 10000, 10000, 90, 90, 250, 480, 1, 10, 1])
740739

741740
register = self.get_register(update_register)
742741
new_raw_value = self.translate_to_raw_value(register, new_value)
@@ -749,9 +748,16 @@ def write_register_block(self, block_name, update_register, new_value):
749748
logging.info(f"Current value for {register['name']}: {current_raw_value} ({current_value}). Matches desired value: {new_raw_value} ({new_value}).")
750749
retry = 0
751750
else:
751+
if len(values) < required_length:
752+
logging.error(f"Length of values in block is less than required length for block {block['name']}. Skipping write operation. Values: {values}")
753+
return
752754
logging.info(f"Current value for {register['name']}: {current_raw_value} ({current_value}), attempting to set it to: {new_raw_value} ({new_value}). Retries remaining: {retry}")
753-
self.write_registers_with_retry(block['start_register'], values[:length])
754-
time.sleep(self.write_retry_delay)
755+
logging.info(f"Would write {block['start_register']} with {values[:required_length]}")
756+
self.write_registers_with_retry(block['start_register'], values[:required_length])
757+
#logging.info(f"Reference values: {[0, 0, 1, 560, 540, 425, 470, 10000, 10000, 90, 90, 250, 480, 1, 10, 1]}")
758+
# [0, 0, 1, 540, 530, 425, 470, 10000, 10000, 89, 90, 250, 480, 1, 10, 1]
759+
#self.write_registers_with_retry(block['start_register'], [0, 0, 1, 560, 540, 425, 470, 10000, 10000, 90, 90, 250, 480, 1, 10, 1])
760+
time.sleep(self.write_retry_delay + 5)
755761
retry = retry - 1
756762

757763
def get_register(self, register_name):
@@ -793,7 +799,7 @@ def translate_to_raw_value(self, register, value):
793799
elif register['function'] == 'divide':
794800
return int(float(value) * register['factor'])
795801
elif register['function'] == 'mode':
796-
return next((k for k, v in register['modes'].items() if v == value), value)
802+
return int(next((k for k, v in register['modes'].items() if v == value), value))
797803
elif register['function'] == 'bit_field':
798804
fields = value.split(',')
799805
raw_value = 0
@@ -804,7 +810,20 @@ def translate_to_raw_value(self, register, value):
804810
elif register['function'] == 'high_bit_low_bit':
805811
high, low = map(int, value.split(register['join']))
806812
return (high << 8) | low
807-
return value
813+
return int(value)
814+
815+
def validate_new_value(register, new_value):
816+
""" Validate the new value based on the register's min, max, and modes """
817+
if 'min' in register and new_value < register['min']:
818+
logging.error(f"Value {new_value} is less than the minimum allowed value {register['min']} for register {register['name']}")
819+
return False
820+
if 'max' in register and new_value > register['max']:
821+
logging.error(f"Value {new_value} is greater than the maximum allowed value {register['max']} for register {register['name']}")
822+
return False
823+
if 'function' in register and register['function'] == 'mode' and str(new_value) not in register['modes']:
824+
logging.error(f"Value {new_value} is not a valid mode for register {register['name']}")
825+
return False
826+
return True
808827

809828
@click.command("cli", context_settings={'show_default': True})
810829
@click.option(

0 commit comments

Comments
 (0)