use battery cold signal instead of temperature for heat battery controller in Cerbo

This commit is contained in:
Yinyin Liu 2024-06-24 15:35:18 +02:00
parent f0edc262bd
commit c787c823bc
2 changed files with 115 additions and 91 deletions

View File

@ -386,6 +386,11 @@ def init_signals(hardware_version, firmware_version, n_batteries):
read_current = c.read_float(register=1000, scale_factor=0.01, offset=-10000, places=2) read_current = c.read_float(register=1000, scale_factor=0.01, offset=-10000, places=2)
read_limb_bitmap = c.read_bitmap(1059) read_limb_bitmap = c.read_bitmap(1059)
def read_battery_cold(status):
return \
c.read_led_state(register=1004, led=LedColor.green)(status) >= LedState.blinking_slow and \
c.read_led_state(register=1004, led=LedColor.blue)(status) >= LedState.blinking_slow
def read_power(status): def read_power(status):
return int(read_current(status) * read_voltage(status)) return int(read_current(status) * read_voltage(status))
@ -429,6 +434,7 @@ def init_signals(hardware_version, firmware_version, n_batteries):
# Node Red related dbus paths # Node Red related dbus paths
Signal('/TimeToTOCRequest', max, c.read_float(register=1052)), Signal('/TimeToTOCRequest', max, c.read_float(register=1052)),
Signal('/EOCReached', c.return_in_list, read_eoc_reached), Signal('/EOCReached', c.return_in_list, read_eoc_reached),
Signal('/BatteryCold',c.return_in_list, read_battery_cold),
Signal('/NumOfLimbStrings', c.return_in_list, get_value=limp_strings_value), Signal('/NumOfLimbStrings', c.return_in_list, get_value=limp_strings_value),
Signal('/NumOfBatteries', max, get_value=n_batteries), Signal('/NumOfBatteries', max, get_value=n_batteries),
Signal('/Dc/0/Voltage', c.mean, get_value=read_voltage, get_text=c.append_unit('V')), Signal('/Dc/0/Voltage', c.mean, get_value=read_voltage, get_text=c.append_unit('V')),
@ -438,7 +444,7 @@ def init_signals(hardware_version, firmware_version, n_batteries):
Signal('/Soc', min, c.read_float(register=1053, scale_factor=0.1, offset=0, places=1), c.append_unit('%')), Signal('/Soc', min, c.read_float(register=1053, scale_factor=0.1, offset=0, places=1), c.append_unit('%')),
Signal('/LowestSoc', min, c.read_float(register=1053, scale_factor=0.1, offset=0, places=1), c.append_unit('%')), Signal('/LowestSoc', min, c.read_float(register=1053, scale_factor=0.1, offset=0, places=1), c.append_unit('%')),
Signal('/Dc/0/Temperature', c.mean, c.read_float(register=1003, scale_factor=0.1, offset=-400, places=1), c.append_unit(u'°C')), Signal('/Dc/0/Temperature', c.mean, c.read_float(register=1003, scale_factor=0.1, offset=-400, places=1), c.append_unit(u'°C')),
Signal('/Dc/0/LowestTemperature', min, c.read_float(register=1003, scale_factor=0.1, offset=-400, places=1), c.append_unit(u'°C')),
# Charge/Discharge current, voltage and power # Charge/Discharge current, voltage and power
Signal('/Info/MaxDischargeCurrent', c.ssum, max_discharge_current,c.append_unit('A')), Signal('/Info/MaxDischargeCurrent', c.ssum, max_discharge_current,c.append_unit('A')),
Signal('/Info/MaxChargeCurrent', c.ssum, max_charge_current, c.append_unit('A')), Signal('/Info/MaxChargeCurrent', c.ssum, max_charge_current, c.append_unit('A')),
@ -454,8 +460,7 @@ def init_signals(hardware_version, firmware_version, n_batteries):
Signal('/Connected', c.first, 1), Signal('/Connected', c.first, 1),
Signal('/FirmwareVersion', c.return_in_list, firmware_version), Signal('/FirmwareVersion', c.return_in_list, firmware_version),
Signal('/HardwareVersion', c.first, cfg.HARDWARE_VERSION, hardware_version), Signal('/HardwareVersion', c.first, cfg.HARDWARE_VERSION, hardware_version),
# Diagnostics Signal('/BmsVersion', c.first, lambda s: s.battery.bms_version),
Signal('/Diagnostics/BmsVersion', c.first, lambda s: s.battery.bms_version),
# Warnings # Warnings
Signal('/WarningFlags/TaM1', c.return_in_list, c.read_bool(register=1005, bit=1)), Signal('/WarningFlags/TaM1', c.return_in_list, c.read_bool(register=1005, bit=1)),
Signal('/WarningFlags/TbM1', c.return_in_list, c.read_bool(register=1005, bit=4)), Signal('/WarningFlags/TbM1', c.return_in_list, c.read_bool(register=1005, bit=4)),
@ -504,18 +509,18 @@ def init_signals(hardware_version, firmware_version, n_batteries):
Signal('/AlarmFlags/HEBT', c.return_in_list, c.read_bool(register=1005, bit=46)), Signal('/AlarmFlags/HEBT', c.return_in_list, c.read_bool(register=1005, bit=46)),
Signal('/AlarmFlags/CURM', c.return_in_list, c.read_bool(register=1005, bit=48)), Signal('/AlarmFlags/CURM', c.return_in_list, c.read_bool(register=1005, bit=48)),
# LedStatus # LedStatus
Signal('/Diagnostics/LedStatus/Red', c.first, c.read_led_state(register=1004, led=LedColor.red)), Signal('/LedStatus/Red', c.first, c.read_led_state(register=1004, led=LedColor.red)),
Signal('/Diagnostics/LedStatus/Blue', c.first, c.read_led_state(register=1004, led=LedColor.blue)), Signal('/LedStatus/Blue', c.first, c.read_led_state(register=1004, led=LedColor.blue)),
Signal('/Diagnostics/LedStatus/Green', c.first, c.read_led_state(register=1004, led=LedColor.green)), Signal('/LedStatus/Green', c.first, c.read_led_state(register=1004, led=LedColor.green)),
Signal('/Diagnostics/LedStatus/Amber', c.first, c.read_led_state(register=1004, led=LedColor.amber)), Signal('/LedStatus/Amber', c.first, c.read_led_state(register=1004, led=LedColor.amber)),
# IO Status # IO Status
Signal('/Diagnostics/IoStatus/MainSwitchClosed', c.return_in_list, read_switch_closed), Signal('/IoStatus/MainSwitchClosed', c.return_in_list, read_switch_closed),
Signal('/Diagnostics/IoStatus/AlarmOutActive', c.return_in_list, read_alarm_out_active), Signal('/IoStatus/AlarmOutActive', c.return_in_list, read_alarm_out_active),
Signal('/Diagnostics/IoStatus/InternalFanActive', c.return_in_list, c.read_bool(register=1013, bit=2)), Signal('/IoStatus/InternalFanActive', c.return_in_list, c.read_bool(register=1013, bit=2)),
Signal('/Diagnostics/IoStatus/VoltMeasurementAllowed', c.return_in_list, c.read_bool(register=1013, bit=3)), Signal('/IoStatus/VoltMeasurementAllowed', c.return_in_list, c.read_bool(register=1013, bit=3)),
Signal('/Diagnostics/IoStatus/AuxRelay', c.return_in_list, read_aux_relay), Signal('/IoStatus/AuxRelay', c.return_in_list, read_aux_relay),
Signal('/Diagnostics/IoStatus/RemoteState', c.return_in_list, c.read_bool(register=1013, bit=5)), Signal('/IoStatus/RemoteState', c.return_in_list, c.read_bool(register=1013, bit=5)),
Signal('/Diagnostics/IoStatus/RiscOn', c.return_in_list, c.read_bool(register=1013, bit=6)), Signal('/IoStatus/RiscOn', c.return_in_list, c.read_bool(register=1013, bit=6)),
] ]
def init_modbus(tty): def init_modbus(tty):

View File

@ -1447,33 +1447,6 @@
] ]
] ]
}, },
{
"id": "7630c78072545444",
"type": "change",
"z": "58aeeaac02a3a4c7",
"name": "lowest_battery_temperature",
"rules": [
{
"t": "set",
"p": "topic",
"pt": "msg",
"to": "lowest_battery_temperature",
"tot": "str"
}
],
"action": "",
"property": "",
"from": "",
"to": "",
"reg": false,
"x": 640,
"y": 440,
"wires": [
[
"464455af5139ee7f"
]
]
},
{ {
"id": "b02c86727cdd38f1", "id": "b02c86727cdd38f1",
"type": "victron-input-custom", "type": "victron-input-custom",
@ -1601,31 +1574,6 @@
] ]
] ]
}, },
{
"id": "005a521093d8c181",
"type": "victron-input-custom",
"z": "58aeeaac02a3a4c7",
"service": "com.victronenergy.battery/1",
"path": "/Dc/0/LowestTemperature",
"serviceObj": {
"service": "com.victronenergy.battery/1",
"name": "FZS 48TL200 x2 (1)"
},
"pathObj": {
"path": "/Dc/0/LowestTemperature",
"name": "/Dc/0/LowestTemperature",
"type": "number"
},
"name": "",
"onlyChanges": false,
"x": 220,
"y": 440,
"wires": [
[
"7630c78072545444"
]
]
},
{ {
"id": "49537ad0e4d9df8a", "id": "49537ad0e4d9df8a",
"type": "victron-output-custom", "type": "victron-output-custom",
@ -1729,7 +1677,6 @@
}, },
"name": "", "name": "",
"onlyChanges": false, "onlyChanges": false,
"roundValues": "0",
"x": 210, "x": 210,
"y": 1320, "y": 1320,
"wires": [ "wires": [
@ -1873,7 +1820,7 @@
"type": "function", "type": "function",
"z": "58aeeaac02a3a4c7", "z": "58aeeaac02a3a4c7",
"name": "Battery Controller", "name": "Battery Controller",
"func": "// get inverter num of phases\nif(msg.payload.num_phases == null){\n num_phases = 10000000000;// mimic to make power setpoint be 0 when there is no inverter phase there \n}else{\n num_phases = msg.payload.num_phases;\n}\n\n// get max charge power\nif(msg.payload.max_configured_charge_power == null ||msg.payload.max_configured_charge_power<0){\n max_charge_power=msg.payload.max_battery_charge_power;\n}else{\n max_charge_power=Math.min(msg.payload.max_configured_charge_power,msg.payload.max_battery_charge_power);\n}\n\n// get battery number\nif(msg.payload.num_batteries == null){\n n_batteries = 0;\n}else{\n n_batteries = msg.payload.num_batteries;\n}\n\n// get current battery power\nif(msg.payload.battery_power == null){\n battery_power = 0;\n}else{\n battery_power = msg.payload.battery_power;\n}\n\n// get current power setpoint\nif(msg.payload.L1_AcPowerSetpoint == null){\n L1_AcPowerSetpoint = 0;\n}else{\n L1_AcPowerSetpoint=msg.payload.L1_AcPowerSetpoint;\n}\n\nif(msg.payload.L2_AcPowerSetpoint == null){\n L2_AcPowerSetpoint = 0;\n}else{\n L2_AcPowerSetpoint=msg.payload.L2_AcPowerSetpoint;\n}\n\nif(msg.payload.L3_AcPowerSetpoint == null){\n L3_AcPowerSetpoint = 0;\n}else{\n L3_AcPowerSetpoint=msg.payload.L3_AcPowerSetpoint;\n}\n\ninverter_power_setpoint= L1_AcPowerSetpoint+L2_AcPowerSetpoint+L3_AcPowerSetpoint;\n\n// get AC Out whihc is critical loads\nif(msg.payload.L1_AC_Out == null ||msg.payload.L2_AC_Out == null || msg.payload.L3_AC_Out == null){\n AC_out=0;\n}else{\n AC_out = msg.payload.L1_AC_Out + msg.payload.L2_AC_Out+msg.payload.L3_AC_Out;\n}\n\n// get PV production\nif(msg.payload.PVs_Power == null){\n PV_production = 0;\n}else{\n PV_production = msg.payload.PVs_Power;\n}\n\n// cal calculated max inverter power based on limb strings<=1 and DC Bus voltage >=44V when discharging, further details in flow 3\nconfigured_max_inverter_power = num_phases*10000;//3000W for each phase\nmax_discharge_current_batteries = 15*(5*n_batteries-msg.payload.num_limb_string);\nDC_BUS_Voltage = msg.payload.DC_BUS_Voltage;\n\nif(44.1<DC_BUS_Voltage && DC_BUS_Voltage <=45){\n max_discharge_current_batteries -=(45-DC_BUS_Voltage)*20*n_batteries;\n}\n\nif(DC_BUS_Voltage <=44.1){\n max_discharge_current_batteries = 0;\n}\n \nmax_discharge_power_inverter = Math.floor(msg.payload.DC_BUS_Voltage*max_discharge_current_batteries+PV_production);\ncal_max_inverter_discharge_power = Math.min(max_discharge_power_inverter,configured_max_inverter_power);\n\n// variables for hold_min_soc controller\nBatterySelfDischargePower=150;//W\nHoldSocZone=3;\nP_CONST = 0.2;\nsoc = msg.payload.lowest_soc;\nmin_soc = msg.payload.min_soc;\na=-2*BatterySelfDischargePower*n_batteries/HoldSocZone;\nb=-a*(min_soc+HoldSocZone);\ntarget_dc_power_to_hold_min_soc=soc*a+b;\n\n// set batterylife state\nbatterylife_state = msg.payload.batterylife_state;\nif(soc <= min_soc -5){\n batterylife_state = 12;\n}else if(min_soc -5 < soc && soc < min_soc){\n batterylife_state = 11;\n}else{\n batterylife_state = 10;\n}\n\n// calibration charge\nif(global.get('start_calibration_charge_now_button','file') == true || global.get('start_calibration_charge_now','file')==1){\n inverter_setpower = AC_out+max_charge_power;\n msg.payload.inverter_setpower = Math.floor(inverter_setpower/num_phases);\n msg.payload.max_inverter_discharge_power = PV_production;\n msg.payload.ess_mode = 3;\n msg.payload.batterylife_state = batterylife_state;\n msg.payload.controller_info = \"Calibration charge\";\n return msg;\n}\n\ntest = target_dc_power_to_hold_min_soc;\nif(min_soc<=soc&&soc<=min_soc+HoldSocZone){// hold min SOC controller\n inverter_setpower = inverter_power_setpoint+P_CONST*target_dc_power_to_hold_min_soc;\n max_inverter_discharge_power = PV_production;\n ess_mode =1;\n controller_info = \"Hold min SOC\";\n}else if(soc<min_soc){// charge to min SOC controller\n inverter_setpower = AC_out+max_charge_power;\n max_inverter_discharge_power = PV_production;\n ess_mode =3;\n controller_info = \"Charge to min SOC\";\n}else if(msg.payload.lowest_battery_temperature<250){ // heat battery controller\n inverter_setpower = AC_out+max_charge_power;\n max_inverter_discharge_power = PV_production;\n ess_mode =3;\n controller_info = \"Heat Battery\";\n}else{// ESS self-consumption controller\n inverter_setpower = inverter_power_setpoint;\n max_inverter_discharge_power = cal_max_inverter_discharge_power;\n ess_mode =1;\n controller_info = \"ESS self-consumption\";\n}\n\npowerperphase = Math.floor(inverter_setpower/num_phases);\n\nmsg.payload.inverter_setpower = powerperphase;\nmsg.payload.ess_mode = ess_mode;\nmsg.payload.controller_info = controller_info;\nmsg.payload.max_inverter_discharge_power = max_inverter_discharge_power;\nmsg.payload.batterylife_state = batterylife_state;\nmsg.payload.test = test;\n\nreturn msg;", "func": "// get inverter num of phases\nif(msg.payload.num_phases == null){\n num_phases = 10000000000;// mimic to make power setpoint be 0 when there is no inverter phase there \n}else{\n num_phases = msg.payload.num_phases;\n}\n\n// get max charge power\nif(msg.payload.max_configured_charge_power == null ||msg.payload.max_configured_charge_power<0){\n max_charge_power=msg.payload.max_battery_charge_power;\n}else{\n max_charge_power=Math.min(msg.payload.max_configured_charge_power,msg.payload.max_battery_charge_power);\n}\n\n// get battery number\nif(msg.payload.num_batteries == null){\n n_batteries = 0;\n}else{\n n_batteries = msg.payload.num_batteries;\n}\n\n// get current battery power\nif(msg.payload.battery_power == null){\n battery_power = 0;\n}else{\n battery_power = msg.payload.battery_power;\n}\n\n// get current power setpoint\nif(msg.payload.L1_AcPowerSetpoint == null){\n L1_AcPowerSetpoint = 0;\n}else{\n L1_AcPowerSetpoint=msg.payload.L1_AcPowerSetpoint;\n}\n\nif(msg.payload.L2_AcPowerSetpoint == null){\n L2_AcPowerSetpoint = 0;\n}else{\n L2_AcPowerSetpoint=msg.payload.L2_AcPowerSetpoint;\n}\n\nif(msg.payload.L3_AcPowerSetpoint == null){\n L3_AcPowerSetpoint = 0;\n}else{\n L3_AcPowerSetpoint=msg.payload.L3_AcPowerSetpoint;\n}\n\ninverter_power_setpoint= L1_AcPowerSetpoint+L2_AcPowerSetpoint+L3_AcPowerSetpoint;\n\n// get AC Out whihc is critical loads\nif(msg.payload.L1_AC_Out == null ||msg.payload.L2_AC_Out == null || msg.payload.L3_AC_Out == null){\n AC_out=0;\n}else{\n AC_out = msg.payload.L1_AC_Out + msg.payload.L2_AC_Out+msg.payload.L3_AC_Out;\n}\n\n// get PV production\nif(msg.payload.PVs_Power == null){\n PV_production = 0;\n}else{\n PV_production = msg.payload.PVs_Power;\n}\n\n// cal calculated max inverter power based on limb strings<=1 and DC Bus voltage >=44V when discharging, further details in flow 3\nconfigured_max_inverter_power = num_phases*10000;//3000W for each phase\nmax_discharge_current_batteries = 15*(5*n_batteries-msg.payload.num_limb_string);\nDC_BUS_Voltage = msg.payload.DC_BUS_Voltage;\n\nif(44.1<DC_BUS_Voltage && DC_BUS_Voltage <=45){\n max_discharge_current_batteries -=(45-DC_BUS_Voltage)*20*n_batteries;\n}\n\nif(DC_BUS_Voltage <=44.1){\n max_discharge_current_batteries = 0;\n}\n \nmax_discharge_power_inverter = Math.floor(msg.payload.DC_BUS_Voltage*max_discharge_current_batteries+PV_production);\ncal_max_inverter_discharge_power = Math.min(max_discharge_power_inverter,configured_max_inverter_power);\n\n// variables for hold_min_soc controller\nBatterySelfDischargePower=150;//W\nHoldSocZone=3;\nP_CONST = 0.2;\nsoc = msg.payload.lowest_soc;\nmin_soc = msg.payload.min_soc;\na=-2*BatterySelfDischargePower*n_batteries/HoldSocZone;\nb=-a*(min_soc+HoldSocZone);\ntarget_dc_power_to_hold_min_soc=soc*a+b;\n\n// set batterylife state\nbatterylife_state = msg.payload.batterylife_state;\nif(soc <= min_soc -5){\n batterylife_state = 12;\n}else if(min_soc -5 < soc && soc < min_soc){\n batterylife_state = 11;\n}else{\n batterylife_state = 10;\n}\n\n// calibration charge\nif(global.get('start_calibration_charge_now_button','file') == true || global.get('start_calibration_charge_now','file')==1){\n inverter_setpower = AC_out+max_charge_power;\n msg.payload.inverter_setpower = Math.floor(inverter_setpower/num_phases);\n msg.payload.max_inverter_discharge_power = PV_production;\n msg.payload.ess_mode = 3;\n msg.payload.batterylife_state = batterylife_state;\n msg.payload.controller_info = \"Calibration charge\";\n return msg;\n}\n\ntest = target_dc_power_to_hold_min_soc;\nif(min_soc<=soc&&soc<=min_soc+HoldSocZone){// hold min SOC controller\n inverter_setpower = inverter_power_setpoint+P_CONST*target_dc_power_to_hold_min_soc;\n max_inverter_discharge_power = PV_production;\n ess_mode =1;\n controller_info = \"Hold min SOC\";\n}else if(soc<min_soc){// charge to min SOC controller\n inverter_setpower = AC_out+max_charge_power;\n max_inverter_discharge_power = PV_production;\n ess_mode =3;\n controller_info = \"Charge to min SOC\";\n}else if(msg.payload.BatteryCold.some(value => value === true)){ // heat battery controller\n inverter_setpower = AC_out+max_charge_power;\n max_inverter_discharge_power = PV_production;\n ess_mode =3;\n controller_info = \"Heat Battery\";\n}else{// ESS self-consumption controller\n inverter_setpower = inverter_power_setpoint;\n max_inverter_discharge_power = cal_max_inverter_discharge_power;\n ess_mode =1;\n controller_info = \"ESS self-consumption\";\n}\n\npowerperphase = Math.floor(inverter_setpower/num_phases);\n\nmsg.payload.inverter_setpower = powerperphase;\nmsg.payload.ess_mode = ess_mode;\nmsg.payload.controller_info = controller_info;\nmsg.payload.max_inverter_discharge_power = max_inverter_discharge_power;\nmsg.payload.batterylife_state = batterylife_state;\nmsg.payload.test = test;\n\nreturn msg;",
"outputs": 1, "outputs": 1,
"timeout": 0, "timeout": 0,
"noerr": 0, "noerr": 0,
@ -1888,9 +1835,9 @@
"b4b77872b62e2859", "b4b77872b62e2859",
"8575f4390d7502bb", "8575f4390d7502bb",
"2066c1a0f48b4e2c", "2066c1a0f48b4e2c",
"e121ac014fa242c5",
"52f0fa857f1d3a3c", "52f0fa857f1d3a3c",
"283f5123601abd28", "283f5123601abd28"
"e121ac014fa242c5"
] ]
] ]
}, },
@ -2294,7 +2241,7 @@
], ],
[ [
"bcfea00921e46714", "bcfea00921e46714",
"664a018fc9f6bbc6" "ae0a6a009c8b9781"
] ]
] ]
}, },
@ -2329,7 +2276,7 @@
"id": "bcfea00921e46714", "id": "bcfea00921e46714",
"type": "debug", "type": "debug",
"z": "58aeeaac02a3a4c7", "z": "58aeeaac02a3a4c7",
"name": "Main Switch is on or there are >=2 limb strings", "name": " >=2 limb strings",
"active": false, "active": false,
"tosidebar": true, "tosidebar": true,
"console": false, "console": false,
@ -2338,7 +2285,7 @@
"targetType": "msg", "targetType": "msg",
"statusVal": "payload", "statusVal": "payload",
"statusType": "auto", "statusType": "auto",
"x": 2120, "x": 2020,
"y": 540, "y": 540,
"wires": [] "wires": []
}, },
@ -2385,7 +2332,7 @@
"type": "function", "type": "function",
"z": "58aeeaac02a3a4c7", "z": "58aeeaac02a3a4c7",
"name": "get_total_number_of_limb_strings", "name": "get_total_number_of_limb_strings",
"func": "let total_num_limb_string=0;\nlimb_string_list = msg.payload.limb_string_list;\nmain_switch_state_list = msg.payload.main_switch_state;\nbattery_health = [];\nif (limb_string_list == null){\n msg.payload.battery_health = \"BMS connection lost!\";\n msg.payload.num_limb_string = -1\n return msg;\n}\n\nfor (let i = 0; i < limb_string_list.length; i++) {\n num_limb_string = limb_string_list[i][1][0];\n\n if(num_limb_string>1){\n total_num_limb_string = -1;//if there are more than 1 limb string in a battery, should give alarm to stop use this battery\n battery_health.push(\"Battery \"+(i+2)+\" has more than 1 limb string!\");\n }\n \n if(num_limb_string<=1){\n total_num_limb_string+=num_limb_string;\n battery_health.push(\"Battery \"+(i+2)+\" has \" + num_limb_string+ \" limb strings.\");\n }\n}\nmsg.payload.num_limb_string = total_num_limb_string;\nmsg.payload.battery_health = battery_health;\n\nreturn msg;", "func": "let total_num_limb_string=0;\nlimb_string_list = msg.payload.limb_string_list;\nmain_switch_state_list = msg.payload.main_switch_state;\nbattery_health = [];\nif (limb_string_list == null){\n msg.payload.battery_health = \"BMS connection lost!\";\n msg.payload.num_limb_string = -1\n return msg;\n}\n\nfor (let i = 0; i < limb_string_list.length; i++) {\n num_limb_string = limb_string_list[i][1][0];\n \n if(num_limb_string>1){\n total_num_limb_string = -1;//if there are more than 1 limb string in a battery, should give alarm to stop use this battery\n battery_health.push(\"Battery \"+(i+2)+\" has more than 1 limb string!\");\n }\n \n if(num_limb_string<=1){\n total_num_limb_string+=num_limb_string;\n battery_health.push(\"Battery \"+(i+2)+\" has \" + num_limb_string+ \" limb strings.\");\n }\n}\nmsg.payload.num_limb_string = total_num_limb_string;\nmsg.payload.battery_health = battery_health;\n\nreturn msg;",
"outputs": 1, "outputs": 1,
"timeout": 0, "timeout": 0,
"noerr": 0, "noerr": 0,
@ -2431,7 +2378,7 @@
"path": "/Ac/NumberOfPhases", "path": "/Ac/NumberOfPhases",
"serviceObj": { "serviceObj": {
"service": "com.victronenergy.vebus/276", "service": "com.victronenergy.vebus/276",
"name": "MultiPlus-II 48/3000/35-32" "name": "MultiGrid 48/3000/35-50"
}, },
"pathObj": { "pathObj": {
"path": "/Ac/NumberOfPhases", "path": "/Ac/NumberOfPhases",
@ -2440,7 +2387,7 @@
}, },
"name": "", "name": "",
"onlyChanges": false, "onlyChanges": false,
"x": 200, "x": 190,
"y": 1560, "y": 1560,
"wires": [ "wires": [
[ [
@ -2473,7 +2420,7 @@
"path": "/Dc/0/Voltage", "path": "/Dc/0/Voltage",
"serviceObj": { "serviceObj": {
"service": "com.victronenergy.vebus/276", "service": "com.victronenergy.vebus/276",
"name": "MultiPlus-II 48/3000/35-32" "name": "MultiGrid 48/3000/35-50"
}, },
"pathObj": { "pathObj": {
"path": "/Dc/0/Voltage", "path": "/Dc/0/Voltage",
@ -2483,7 +2430,7 @@
"name": "", "name": "",
"onlyChanges": false, "onlyChanges": false,
"roundValues": "0", "roundValues": "0",
"x": 220, "x": 210,
"y": 660, "y": 660,
"wires": [ "wires": [
[ [
@ -2499,7 +2446,7 @@
"path": "/Hub4/L1/AcPowerSetpoint", "path": "/Hub4/L1/AcPowerSetpoint",
"serviceObj": { "serviceObj": {
"service": "com.victronenergy.vebus/276", "service": "com.victronenergy.vebus/276",
"name": "MultiPlus-II 48/3000/35-32" "name": "MultiGrid 48/3000/35-50"
}, },
"pathObj": { "pathObj": {
"path": "/Hub4/L1/AcPowerSetpoint", "path": "/Hub4/L1/AcPowerSetpoint",
@ -2508,7 +2455,7 @@
}, },
"name": "", "name": "",
"onlyChanges": false, "onlyChanges": false,
"x": 240, "x": 230,
"y": 760, "y": 760,
"wires": [ "wires": [
[ [
@ -2524,7 +2471,7 @@
"path": "/Hub4/L2/AcPowerSetpoint", "path": "/Hub4/L2/AcPowerSetpoint",
"serviceObj": { "serviceObj": {
"service": "com.victronenergy.vebus/276", "service": "com.victronenergy.vebus/276",
"name": "MultiPlus-II 48/3000/35-32" "name": "MultiGrid 48/3000/35-50"
}, },
"pathObj": { "pathObj": {
"path": "/Hub4/L2/AcPowerSetpoint", "path": "/Hub4/L2/AcPowerSetpoint",
@ -2533,7 +2480,7 @@
}, },
"name": "", "name": "",
"onlyChanges": false, "onlyChanges": false,
"x": 240, "x": 230,
"y": 840, "y": 840,
"wires": [ "wires": [
[ [
@ -2549,7 +2496,7 @@
"path": "/Hub4/L3/AcPowerSetpoint", "path": "/Hub4/L3/AcPowerSetpoint",
"serviceObj": { "serviceObj": {
"service": "com.victronenergy.vebus/276", "service": "com.victronenergy.vebus/276",
"name": "MultiPlus-II 48/3000/35-32" "name": "MultiGrid 48/3000/35-50"
}, },
"pathObj": { "pathObj": {
"path": "/Hub4/L3/AcPowerSetpoint", "path": "/Hub4/L3/AcPowerSetpoint",
@ -2558,7 +2505,7 @@
}, },
"name": "", "name": "",
"onlyChanges": false, "onlyChanges": false,
"x": 240, "x": 230,
"y": 920, "y": 920,
"wires": [ "wires": [
[ [
@ -2574,7 +2521,7 @@
"path": "/Hub4/L3/AcPowerSetpoint", "path": "/Hub4/L3/AcPowerSetpoint",
"serviceObj": { "serviceObj": {
"service": "com.victronenergy.vebus/276", "service": "com.victronenergy.vebus/276",
"name": "MultiPlus-II 48/3000/35-32" "name": "MultiGrid 48/3000/35-50"
}, },
"pathObj": { "pathObj": {
"path": "/Hub4/L3/AcPowerSetpoint", "path": "/Hub4/L3/AcPowerSetpoint",
@ -2584,7 +2531,7 @@
}, },
"name": "", "name": "",
"onlyChanges": false, "onlyChanges": false,
"x": 3100, "x": 3090,
"y": 460, "y": 460,
"wires": [] "wires": []
}, },
@ -2596,7 +2543,7 @@
"path": "/Hub4/L2/AcPowerSetpoint", "path": "/Hub4/L2/AcPowerSetpoint",
"serviceObj": { "serviceObj": {
"service": "com.victronenergy.vebus/276", "service": "com.victronenergy.vebus/276",
"name": "MultiPlus-II 48/3000/35-32" "name": "MultiGrid 48/3000/35-50"
}, },
"pathObj": { "pathObj": {
"path": "/Hub4/L2/AcPowerSetpoint", "path": "/Hub4/L2/AcPowerSetpoint",
@ -2606,7 +2553,7 @@
}, },
"name": "", "name": "",
"onlyChanges": false, "onlyChanges": false,
"x": 3100, "x": 3090,
"y": 400, "y": 400,
"wires": [] "wires": []
}, },
@ -2618,7 +2565,7 @@
"path": "/Hub4/L1/AcPowerSetpoint", "path": "/Hub4/L1/AcPowerSetpoint",
"serviceObj": { "serviceObj": {
"service": "com.victronenergy.vebus/276", "service": "com.victronenergy.vebus/276",
"name": "MultiPlus-II 48/3000/35-32" "name": "MultiGrid 48/3000/35-50"
}, },
"pathObj": { "pathObj": {
"path": "/Hub4/L1/AcPowerSetpoint", "path": "/Hub4/L1/AcPowerSetpoint",
@ -2628,7 +2575,7 @@
}, },
"name": "", "name": "",
"onlyChanges": false, "onlyChanges": false,
"x": 3100, "x": 3090,
"y": 340, "y": 340,
"wires": [] "wires": []
}, },
@ -2650,7 +2597,7 @@
"wires": [] "wires": []
}, },
{ {
"id": "664a018fc9f6bbc6", "id": "ae0a6a009c8b9781",
"type": "change", "type": "change",
"z": "58aeeaac02a3a4c7", "z": "58aeeaac02a3a4c7",
"name": "Please replace battery first!", "name": "Please replace battery first!",
@ -2676,6 +2623,78 @@
] ]
] ]
}, },
{
"id": "53bdfc638f96e640",
"type": "victron-input-custom",
"z": "58aeeaac02a3a4c7",
"service": "com.victronenergy.battery/1",
"path": "/BatteryCold",
"serviceObj": {
"service": "com.victronenergy.battery/1",
"name": "FZS 48TL200 x2 (1)"
},
"pathObj": {
"path": "/BatteryCold",
"name": "/BatteryCold",
"type": "object"
},
"name": "",
"onlyChanges": false,
"x": 180,
"y": 440,
"wires": [
[
"4c26a8ddb2e1881c"
]
]
},
{
"id": "4c26a8ddb2e1881c",
"type": "function",
"z": "58aeeaac02a3a4c7",
"name": "Parse BatteryCold list",
"func": "BatteryCold_list = [];\n\nBatteryCold = msg.payload;\n\n//equals to the number of battery\nn=BatteryCold.length;\n\nfor (i = 0; i < n; i++) {\n BatteryCold_list.push(BatteryCold[i][1][0]);\n}\n\nmsg.payload = BatteryCold_list;\nreturn msg;",
"outputs": 1,
"timeout": 0,
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 480,
"y": 440,
"wires": [
[
"0f50a64d808a5b06"
]
]
},
{
"id": "0f50a64d808a5b06",
"type": "change",
"z": "58aeeaac02a3a4c7",
"name": "BatteryCold",
"rules": [
{
"t": "set",
"p": "topic",
"pt": "msg",
"to": "BatteryCold",
"tot": "str"
}
],
"action": "",
"property": "",
"from": "",
"to": "",
"reg": false,
"x": 690,
"y": 440,
"wires": [
[
"464455af5139ee7f"
]
]
},
{ {
"id": "bf31818b5561403e", "id": "bf31818b5561403e",
"type": "comment", "type": "comment",