From 27486a5f991f6dbb42047b43f96f080c706dbf67 Mon Sep 17 00:00:00 2001 From: britkat1980 <69121158+britkat1980@users.noreply.github.com> Date: Sat, 21 Sep 2024 11:55:44 +0100 Subject: [PATCH] 3.0.1 update fixes --- .ppkwhtouch | 0 GivTCP/GivLUT.py | 142 ++++++------ GivTCP/HA_Discovery.py | 21 +- .../givenergy_modbus_async/model/gateway.py | 12 +- .../givenergy_modbus_async/model/register.py | 4 +- GivTCP/panda.py | 1 - GivTCP/read.py | 21 +- README.md | 216 ++++++++++++------ READMEv3.md | 193 ---------------- buildx.bat | 6 +- restresponse.json | 1 + settings.json | 1 + startup_2.py | 63 ++--- 13 files changed, 283 insertions(+), 398 deletions(-) delete mode 100644 .ppkwhtouch delete mode 100644 READMEv3.md create mode 100644 restresponse.json diff --git a/.ppkwhtouch b/.ppkwhtouch deleted file mode 100644 index e69de29b..00000000 diff --git a/GivTCP/GivLUT.py b/GivTCP/GivLUT.py index 98d2fec4..de451473 100644 --- a/GivTCP/GivLUT.py +++ b/GivTCP/GivLUT.py @@ -226,26 +226,26 @@ def put_regcache(regCacheStack): "Timeout_Error":GEType("sensor","string","","","",False,False,False), "GivTCP_Version":GEType("sensor","string","","","",False,False,False), "Stack_Firmware":GEType("sensor","string","","","",False,False,False), - "Export_Energy_Total_kWh":GEType("sensor","energy","",0,'maxTotalEnergy',False,True,True), - "Battery_Throughput_Total_kWh":GEType("sensor","energy","",0,'maxTotalEnergy',False,True,True), - "AC_Charge_Energy_Total_kWh":GEType("sensor","energy","",0,'maxTotalEnergy',False,True,True), - "Import_Energy_Total_kWh":GEType("sensor","energy","",0,'maxTotalEnergy',False,True,True), - "Invertor_Energy_Total_kWh":GEType("sensor","energy","",0,'maxTotalEnergy',False,True,True), - "PV_Energy_Total_kWh":GEType("sensor","energy","",0,'maxTotalEnergy',False,True,True), - "Load_Energy_Total_kWh":GEType("sensor","energy","",0,'maxTotalEnergy',False,True,True), - "Battery_Charge_Energy_Total_kWh":GEType("sensor","energy","",0,'maxTotalEnergy',False,True,True), - "Battery_Discharge_Energy_Total_kWh":GEType("sensor","energy","",0,'maxTotalEnergy',False,True,True), - "Self_Consumption_Energy_Total_kWh":GEType("sensor","energy","",0,'maxTotalEnergy',False,True,True), - "Battery_Throughput_Today_kWh":GEType("sensor","energy","",0,'maxTodayEnergy',True,False,False), - "PV_Energy_Today_kWh":GEType("sensor","energy","",0,'maxTodayEnergy',True,False,False), - "Import_Energy_Today_kWh":GEType("sensor","energy","",0,'maxTodayEnergy',True,False,False), - "Export_Energy_Today_kWh":GEType("sensor","energy","",0,'maxTodayEnergy',True,False,False), - "AC_Charge_Energy_Today_kWh":GEType("sensor","energy","",0,'maxTodayEnergy',True,False,False), - "Invertor_Energy_Today_kWh":GEType("sensor","energy","",0,'maxTodayEnergy',True,False,False), - "Battery_Charge_Energy_Today_kWh":GEType("sensor","energy","",0,'maxTodayEnergy',True,False,False), - "Battery_Discharge_Energy_Today_kWh":GEType("sensor","energy","",0,'maxTodayEnergy',True,False,False), - "Self_Consumption_Energy_Today_kWh":GEType("sensor","energy","",0,'maxTodayEnergy',True,False,False), - "Load_Energy_Today_kWh":GEType("sensor","energy","",0,'maxTodayEnergy',True,False,False), + "Export_Energy_Total_kWh":GEType("sensor","energy","",0,'maxTotalEnergy',False,False,True), + "Battery_Throughput_Total_kWh":GEType("sensor","energy","",0,'maxTotalEnergy',False,False,True), + "AC_Charge_Energy_Total_kWh":GEType("sensor","energy","",0,'maxTotalEnergy',False,False,True), + "Import_Energy_Total_kWh":GEType("sensor","energy","",0,'maxTotalEnergy',False,False,True), + "Invertor_Energy_Total_kWh":GEType("sensor","energy","",0,'maxTotalEnergy',False,False,True), + "PV_Energy_Total_kWh":GEType("sensor","energy","",0,'maxTotalEnergy',False,False,True), + "Load_Energy_Total_kWh":GEType("sensor","energy","",0,'maxTotalEnergy',False,False,True), + "Battery_Charge_Energy_Total_kWh":GEType("sensor","energy","",0,'maxTotalEnergy',False,False,True), + "Battery_Discharge_Energy_Total_kWh":GEType("sensor","energy","",0,'maxTotalEnergy',False,False,True), + "Self_Consumption_Energy_Total_kWh":GEType("sensor","energy","",0,'maxTotalEnergy',False,False,True), + "Battery_Throughput_Today_kWh":GEType("sensor","energy","",0,'maxTodayEnergy',False,False,False), + "PV_Energy_Today_kWh":GEType("sensor","energy","",0,'maxTodayEnergy',False,False,False), + "Import_Energy_Today_kWh":GEType("sensor","energy","",0,'maxTodayEnergy',False,False,False), + "Export_Energy_Today_kWh":GEType("sensor","energy","",0,'maxTodayEnergy',False,False,False), + "AC_Charge_Energy_Today_kWh":GEType("sensor","energy","",0,'maxTodayEnergy',False,False,False), + "Invertor_Energy_Today_kWh":GEType("sensor","energy","",0,'maxTodayEnergy',False,True,False), + "Battery_Charge_Energy_Today_kWh":GEType("sensor","energy","",0,'maxTodayEnergy',False,False,False), + "Battery_Discharge_Energy_Today_kWh":GEType("sensor","energy","",0,'maxTodayEnergy',False,False,False), + "Self_Consumption_Energy_Today_kWh":GEType("sensor","energy","",0,'maxTodayEnergy',False,False,False), + "Load_Energy_Today_kWh":GEType("sensor","energy","",0,'maxTodayEnergy',False,False,False), "PV_Power_String_1":GEType("sensor","power","",0,10000,True,False,False), "PV_Power_String_2":GEType("sensor","power","",0,10000,True,False,False), "PV_Power":GEType("sensor","power","",0,'maxPower',True,False,False), @@ -295,7 +295,7 @@ def put_regcache(regCacheStack): "Meter_Type":GEType("sensor","string","","","",False,False,False), "Export_Limit":GEType("sensor","","",0,22000,False,False,False), "Invertor_Type":GEType("sensor","string","","","",False,False,False), - "Invertor_Temperature":GEType("sensor","temperature","",'-maxTemp','maxTemp',True,True,False), + "Invertor_Temperature":GEType("sensor","temperature","",'-maxTemp','maxTemp',True,False,False), "Discharge_start_time_slot_1":GEType("select","","setDischargeStart1","","",False,False,False), "Discharge_end_time_slot_1":GEType("select","","setDischargeEnd1","","",False,False,False), "Discharge_start_time_slot_2":GEType("select","","setDischargeStart2","","",False,False,False), @@ -349,58 +349,58 @@ def put_regcache(regCacheStack): "Battery_Cells":GEType("sensor","","",0,24,False,True,False), "Battery_Cycles":GEType("sensor","","",0,5000,False,True,False), "Battery_USB_present":GEType("binary_sensor","","",0,8,True,False,False), - "Battery_Temperature":GEType("sensor","temperature","",'-maxTemp','maxTemp',True,True,False), + "Battery_Temperature":GEType("sensor","temperature","",'-maxTemp','maxTemp',True,False,False), "Battery_Voltage":GEType("sensor","voltage","",0,350,False,True,False), - "BMS_Temperature":GEType("sensor","temperature","",'-maxTemp','maxTemp',True,True,False), + "BMS_Temperature":GEType("sensor","temperature","",'-maxTemp','maxTemp',True,False,False), "BMS_Voltage":GEType("sensor","voltage","",0,500,False,True,False), - "Battery_Cell_1_Voltage":GEType("sensor","voltage","",0,'maxCellVoltage',False,True,False), - "Battery_Cell_2_Voltage":GEType("sensor","voltage","",0,'maxCellVoltage',False,True,False), - "Battery_Cell_3_Voltage":GEType("sensor","voltage","",0,'maxCellVoltage',False,True,False), - "Battery_Cell_4_Voltage":GEType("sensor","voltage","",0,'maxCellVoltage',False,True,False), - "Battery_Cell_5_Voltage":GEType("sensor","voltage","",0,'maxCellVoltage',False,True,False), - "Battery_Cell_6_Voltage":GEType("sensor","voltage","",0,'maxCellVoltage',False,True,False), - "Battery_Cell_7_Voltage":GEType("sensor","voltage","",0,'maxCellVoltage',False,True,False), - "Battery_Cell_8_Voltage":GEType("sensor","voltage","",0,'maxCellVoltage',False,True,False), - "Battery_Cell_9_Voltage":GEType("sensor","voltage","",0,'maxCellVoltage',False,True,False), - "Battery_Cell_10_Voltage":GEType("sensor","voltage","",0,'maxCellVoltage',False,True,False), - "Battery_Cell_11_Voltage":GEType("sensor","voltage","",0,'maxCellVoltage',False,True,False), - "Battery_Cell_12_Voltage":GEType("sensor","voltage","",0,'maxCellVoltage',False,True,False), - "Battery_Cell_13_Voltage":GEType("sensor","voltage","",0,'maxCellVoltage',False,True,False), - "Battery_Cell_14_Voltage":GEType("sensor","voltage","",0,'maxCellVoltage',False,True,False), - "Battery_Cell_15_Voltage":GEType("sensor","voltage","",0,'maxCellVoltage',False,True,False), - "Battery_Cell_16_Voltage":GEType("sensor","voltage","",0,'maxCellVoltage',False,True,False), - "Battery_Cell_17_Voltage":GEType("sensor","voltage","",0,'maxCellVoltage',False,True,False), - "Battery_Cell_18_Voltage":GEType("sensor","voltage","",0,'maxCellVoltage',False,True,False), - "Battery_Cell_19_Voltage":GEType("sensor","voltage","",0,'maxCellVoltage',False,True,False), - "Battery_Cell_20_Voltage":GEType("sensor","voltage","",0,'maxCellVoltage',False,True,False), - "Battery_Cell_21_Voltage":GEType("sensor","voltage","",0,'maxCellVoltage',False,True,False), - "Battery_Cell_22_Voltage":GEType("sensor","voltage","",0,'maxCellVoltage',False,True,False), - "Battery_Cell_23_Voltage":GEType("sensor","voltage","",0,'maxCellVoltage',False,True,False), - "Battery_Cell_24_Voltage":GEType("sensor","voltage","",0,'maxCellVoltage',False,True,False), - "Battery_Cell_1_Temperature":GEType("sensor","temperature","",'-maxTemp','maxTemp',True,True,False), - "Battery_Cell_2_Temperature":GEType("sensor","temperature","",'-maxTemp','maxTemp',True,True,False), - "Battery_Cell_3_Temperature":GEType("sensor","temperature","",'-maxTemp','maxTemp',True,True,False), - "Battery_Cell_4_Temperature":GEType("sensor","temperature","",'-maxTemp','maxTemp',True,True,False), - "Battery_Cell_5_Temperature":GEType("sensor","temperature","",'-maxTemp','maxTemp',True,True,False), - "Battery_Cell_6_Temperature":GEType("sensor","temperature","",'-maxTemp','maxTemp',True,True,False), - "Battery_Cell_7_Temperature":GEType("sensor","temperature","",'-maxTemp','maxTemp',True,True,False), - "Battery_Cell_8_Temperature":GEType("sensor","temperature","",'-maxTemp','maxTemp',True,True,False), - "Battery_Cell_9_Temperature":GEType("sensor","temperature","",'-maxTemp','maxTemp',True,True,False), - "Battery_Cell_10_Temperature":GEType("sensor","temperature","",'-maxTemp','maxTemp',True,True,False), - "Battery_Cell_11_Temperature":GEType("sensor","temperature","",'-maxTemp','maxTemp',True,True,False), - "Battery_Cell_12_Temperature":GEType("sensor","temperature","",'-maxTemp','maxTemp',True,True,False), - "Battery_Cell_13_Temperature":GEType("sensor","temperature","",'-maxTemp','maxTemp',True,True,False), - "Battery_Cell_14_Temperature":GEType("sensor","temperature","",'-maxTemp','maxTemp',True,True,False), - "Battery_Cell_15_Temperature":GEType("sensor","temperature","",'-maxTemp','maxTemp',True,True,False), - "Battery_Cell_16_Temperature":GEType("sensor","temperature","",'-maxTemp','maxTemp',True,True,False), - "Battery_Cell_17_Temperature":GEType("sensor","temperature","",'-maxTemp','maxTemp',True,True,False), - "Battery_Cell_18_Temperature":GEType("sensor","temperature","",'-maxTemp','maxTemp',True,True,False), - "Battery_Cell_19_Temperature":GEType("sensor","temperature","",'-maxTemp','maxTemp',True,True,False), - "Battery_Cell_20_Temperature":GEType("sensor","temperature","",'-maxTemp','maxTemp',True,True,False), - "Battery_Cell_21_Temperature":GEType("sensor","temperature","",'-maxTemp','maxTemp',True,True,False), - "Battery_Cell_22_Temperature":GEType("sensor","temperature","",'-maxTemp','maxTemp',True,True,False), - "Battery_Cell_23_Temperature":GEType("sensor","temperature","",'-maxTemp','maxTemp',True,True,False), - "Battery_Cell_24_Temperature":GEType("sensor","temperature","",'-maxTemp','maxTemp',True,True,False), + "Battery_Cell_1_Voltage":GEType("sensor","voltage","",0,'maxCellVoltage',False,False,False), + "Battery_Cell_2_Voltage":GEType("sensor","voltage","",0,'maxCellVoltage',False,False,False), + "Battery_Cell_3_Voltage":GEType("sensor","voltage","",0,'maxCellVoltage',False,False,False), + "Battery_Cell_4_Voltage":GEType("sensor","voltage","",0,'maxCellVoltage',False,False,False), + "Battery_Cell_5_Voltage":GEType("sensor","voltage","",0,'maxCellVoltage',False,False,False), + "Battery_Cell_6_Voltage":GEType("sensor","voltage","",0,'maxCellVoltage',False,False,False), + "Battery_Cell_7_Voltage":GEType("sensor","voltage","",0,'maxCellVoltage',False,False,False), + "Battery_Cell_8_Voltage":GEType("sensor","voltage","",0,'maxCellVoltage',False,False,False), + "Battery_Cell_9_Voltage":GEType("sensor","voltage","",0,'maxCellVoltage',False,False,False), + "Battery_Cell_10_Voltage":GEType("sensor","voltage","",0,'maxCellVoltage',False,False,False), + "Battery_Cell_11_Voltage":GEType("sensor","voltage","",0,'maxCellVoltage',False,False,False), + "Battery_Cell_12_Voltage":GEType("sensor","voltage","",0,'maxCellVoltage',False,False,False), + "Battery_Cell_13_Voltage":GEType("sensor","voltage","",0,'maxCellVoltage',False,False,False), + "Battery_Cell_14_Voltage":GEType("sensor","voltage","",0,'maxCellVoltage',False,False,False), + "Battery_Cell_15_Voltage":GEType("sensor","voltage","",0,'maxCellVoltage',False,False,False), + "Battery_Cell_16_Voltage":GEType("sensor","voltage","",0,'maxCellVoltage',False,False,False), + "Battery_Cell_17_Voltage":GEType("sensor","voltage","",0,'maxCellVoltage',False,False,False), + "Battery_Cell_18_Voltage":GEType("sensor","voltage","",0,'maxCellVoltage',False,False,False), + "Battery_Cell_19_Voltage":GEType("sensor","voltage","",0,'maxCellVoltage',False,False,False), + "Battery_Cell_20_Voltage":GEType("sensor","voltage","",0,'maxCellVoltage',False,False,False), + "Battery_Cell_21_Voltage":GEType("sensor","voltage","",0,'maxCellVoltage',False,False,False), + "Battery_Cell_22_Voltage":GEType("sensor","voltage","",0,'maxCellVoltage',False,False,False), + "Battery_Cell_23_Voltage":GEType("sensor","voltage","",0,'maxCellVoltage',False,False,False), + "Battery_Cell_24_Voltage":GEType("sensor","voltage","",0,'maxCellVoltage',False,False,False), + "Battery_Cell_1_Temperature":GEType("sensor","temperature","",'-maxTemp','maxTemp',True,False,False), + "Battery_Cell_2_Temperature":GEType("sensor","temperature","",'-maxTemp','maxTemp',True,False,False), + "Battery_Cell_3_Temperature":GEType("sensor","temperature","",'-maxTemp','maxTemp',True,False,False), + "Battery_Cell_4_Temperature":GEType("sensor","temperature","",'-maxTemp','maxTemp',True,False,False), + "Battery_Cell_5_Temperature":GEType("sensor","temperature","",'-maxTemp','maxTemp',True,False,False), + "Battery_Cell_6_Temperature":GEType("sensor","temperature","",'-maxTemp','maxTemp',True,False,False), + "Battery_Cell_7_Temperature":GEType("sensor","temperature","",'-maxTemp','maxTemp',True,False,False), + "Battery_Cell_8_Temperature":GEType("sensor","temperature","",'-maxTemp','maxTemp',True,False,False), + "Battery_Cell_9_Temperature":GEType("sensor","temperature","",'-maxTemp','maxTemp',True,False,False), + "Battery_Cell_10_Temperature":GEType("sensor","temperature","",'-maxTemp','maxTemp',True,False,False), + "Battery_Cell_11_Temperature":GEType("sensor","temperature","",'-maxTemp','maxTemp',True,False,False), + "Battery_Cell_12_Temperature":GEType("sensor","temperature","",'-maxTemp','maxTemp',True,False,False), + "Battery_Cell_13_Temperature":GEType("sensor","temperature","",'-maxTemp','maxTemp',True,False,False), + "Battery_Cell_14_Temperature":GEType("sensor","temperature","",'-maxTemp','maxTemp',True,False,False), + "Battery_Cell_15_Temperature":GEType("sensor","temperature","",'-maxTemp','maxTemp',True,False,False), + "Battery_Cell_16_Temperature":GEType("sensor","temperature","",'-maxTemp','maxTemp',True,False,False), + "Battery_Cell_17_Temperature":GEType("sensor","temperature","",'-maxTemp','maxTemp',True,False,False), + "Battery_Cell_18_Temperature":GEType("sensor","temperature","",'-maxTemp','maxTemp',True,False,False), + "Battery_Cell_19_Temperature":GEType("sensor","temperature","",'-maxTemp','maxTemp',True,False,False), + "Battery_Cell_20_Temperature":GEType("sensor","temperature","",'-maxTemp','maxTemp',True,False,False), + "Battery_Cell_21_Temperature":GEType("sensor","temperature","",'-maxTemp','maxTemp',True,False,False), + "Battery_Cell_22_Temperature":GEType("sensor","temperature","",'-maxTemp','maxTemp',True,False,False), + "Battery_Cell_23_Temperature":GEType("sensor","temperature","",'-maxTemp','maxTemp',True,False,False), + "Battery_Cell_24_Temperature":GEType("sensor","temperature","",'-maxTemp','maxTemp',True,False,False), "Mode":GEType("select","","setBatteryMode","","",False,False,False), "Battery_Power_Reserve":GEType("number","","setBatteryReserve",4,100,False,False,False), "Battery_Power_Cutoff":GEType("number","","setBatteryCutoff",4,100,False,False,False), diff --git a/GivTCP/HA_Discovery.py b/GivTCP/HA_Discovery.py index bbbd0654..d37112b5 100644 --- a/GivTCP/HA_Discovery.py +++ b/GivTCP/HA_Discovery.py @@ -185,10 +185,10 @@ def create_device_payload(topic,SN): if entity_type.sensorClass=="energy": tempObj['unit_of_meas']="kWh" tempObj['device_class']="Energy" - if "soc" in str(topic.split("/")[-1]).lower(): - tempObj['state_class']="measurement" - else: + if entity_type.onlyIncrease: #"soc" in str(topic.split("/")[-1]).lower() or "today" in str(topic.split("/")[-1]).lower(): tempObj['state_class']="total_increasing" + else: + tempObj['state_class']="measurement" if entity_type.sensorClass=="money": if "ppkwh" in str(topic).lower() or "rate" in str(topic).lower(): tempObj['unit_of_meas']="{GBP}/kWh" @@ -388,17 +388,18 @@ def removedisco(SN,messages): for message in messages: newmsg[message[0]]=message[1] count=0 - for msg in CheckDisco.msgs: - if SN in msg or SN in CheckDisco.msgs[msg]: # ("GivEnergy" in msg or GiV_Settings.MQTT_Topic in msg): + for topic in CheckDisco.msgs: + msg=CheckDisco.msgs[topic] + if SN in topic or SN in msg: # ("GivEnergy" in msg or GiV_Settings.MQTT_Topic in msg): if exists('/config/GivTCP/.v3upgrade_'+str(GiV_Settings.givtcp_instance)): logger.debug("V3 Upgrade so dropping old Discovery Messages") - client.publish(msg) #delete regardless of if it has changed + client.publish(topic,None,0,True) #delete regardless of if it has changed else: - if msg in newmsg: - old=newmsg[msg] - new=CheckDisco.msgs[msg][2:-1] #.split('}')[:0] + if topic in newmsg: + old=newmsg[topic] + new=msg[2:-1] #.split('}')[:0] if not old == new: #if payload is different delete old one - client.publish(msg) + client.publish(topic,None,0,True) count+=1 logger.debug(str(count)+" discovery messages changed and removed") time.sleep(2) diff --git a/GivTCP/givenergy_modbus_async/model/gateway.py b/GivTCP/givenergy_modbus_async/model/gateway.py index 7363e806..d01de161 100644 --- a/GivTCP/givenergy_modbus_async/model/gateway.py +++ b/GivTCP/givenergy_modbus_async/model/gateway.py @@ -105,12 +105,12 @@ class Gateway(RegisterGetter, metaclass=DynamicDoc): #### Additional Holding Registers ## EMS - "eco_mode": Def(C.uint16, BatteryPowerMode, HR(481), valid=(0, 1)), - "soc_force_adjust": Def(C.uint16, BatteryCalibrationStage, HR(482), valid=(0,3)), - "parallel_aio_soc": Def(C.uint16, None, HR(491)), - "parallel_aio_battery_power": Def(C.uint16, None, HR(492)), - "parallel_aio_load_power": Def(C.uint16, None, HR(493)), - "battery_nominal_capacity": Def(C.battery_capacity, None, HR(512),HR(0)), +# "eco_mode": Def(C.uint16, BatteryPowerMode, HR(481), valid=(0, 1)), +# "soc_force_adjust": Def(C.uint16, BatteryCalibrationStage, HR(482), valid=(0,3)), +# "parallel_aio_soc": Def(C.uint16, None, HR(491)), +# "parallel_aio_battery_power": Def(C.uint16, None, HR(492)), +# "parallel_aio_load_power": Def(C.uint16, None, HR(493)), +# "battery_nominal_capacity": Def(C.battery_capacity, None, HR(512),HR(0)), } REGISTER_LUT=dict(BaseInverter.REGISTER_LUT, **NEW_LUT) diff --git a/GivTCP/givenergy_modbus_async/model/register.py b/GivTCP/givenergy_modbus_async/model/register.py index 3579d8ae..e905c46a 100644 --- a/GivTCP/givenergy_modbus_async/model/register.py +++ b/GivTCP/givenergy_modbus_async/model/register.py @@ -648,7 +648,7 @@ def core_regs(cls, value): '4': ([0, 60, 120, 180, 240,1000,1060,1120,1180,1240,1300,1360],[180,240,1000,1060,1120]), #"Hybrid - 3ph" '5': ([2040],[2040]), #EMS '6': ([0, 60, 120, 180, 240,1000,1060,1120,1180,1240,1300,1360],[180,240,1000,1060,1120]), #AC - 3ph - '7': ([0, 60, 120, 180,1600,1660,1720,1780,1840],[0, 60, 120, 120,180,240,300,480]), #Gateway + '7': ([0, 60, 120, 180,1600,1660,1720,1780,1840],[0, 60, 120, 120,180,240,300]), #Gateway '8': ([0, 60, 120, 180, 240],[0, 60, 120, 120, 180, 240, 300]), #All in One } return regs.get(value) @@ -663,7 +663,7 @@ def add_regs(cls, value): '4': ([240,1000,1060,1120,1180,1240,1300,1360],[180,240,1000,1060,1120]), #"Hybrid - 3ph" '5': ([2040],[2040]), #EMS '6': ([1000,1060,1120,1180,1240,1300,1360],[180,240,1000,1060,1120]), #AC - 3ph - '7': ([1600,1660,1720,1780,1840],[180,240,300,480]), #Gateway + '7': ([1600,1660,1720,1780,1840],[180,240,300]), #Gateway '8': ([240],[180,240,300]), #All in One } return regs.get(value) diff --git a/GivTCP/panda.py b/GivTCP/panda.py index 17c9e02e..6c1ce203 100644 --- a/GivTCP/panda.py +++ b/GivTCP/panda.py @@ -90,7 +90,6 @@ def outlierRemoval(CacheStack): CacheStack[i][path[0]][path[1]][item]=cleanFlatStack[item] elif len(path)==3: CacheStack[i][path[0]][path[1]][path[2]][item]=cleanFlatStack[item] - return CacheStack def find(field_name, d, current_path=''): diff --git a/GivTCP/read.py b/GivTCP/read.py index 20fbf7c9..6d8acc83 100644 --- a/GivTCP/read.py +++ b/GivTCP/read.py @@ -719,7 +719,7 @@ def processInverterInfo(plant: Plant): multi_output_old = regCacheStack[-1] else: regCacheStack = [0] - multi_output_old = [] + multi_output_old = {} # If System Time is wrong (default date) use last good time or local time if all else fails if GEInv.system_time.year == 2000: @@ -867,10 +867,10 @@ def processInverterInfo(plant: Plant): # if int(GiV_Settings.numBatteries) > 0: # only do this if there are batteries if GEInv.battery_percent != 0 or GEInv.soc_force_adjust !=0: #if we're in calibration mode accept any value power_output['SOC'] = GEInv.battery_percent - elif GEInv.battery_percent == 0 and 'multi_output_old' in locals(): + elif GEInv.battery_percent == 0 and len(multi_output_old)>0: power_output['SOC'] = multi_output_old['Power']['Power']['SOC'] logger.debug("\"Battery SOC\" reported as: "+str(GEInv.battery_percent)+"% so using previous value") - elif GEInv.battery_percent == 0 and not 'multi_output_old' in locals(): + elif GEInv.battery_percent == 0 and len(multi_output_old)==0: power_output['SOC'] = 1 logger.debug("\"Battery SOC\" reported as: "+str(GEInv.battery_percent)+"% and no previous value so setting to 1%") else: @@ -1251,10 +1251,10 @@ def processGatewayInfo(plant: Plant): ### Is this bit right? If not parallel then are there multiple aios to check? Can you have multiple AIOs not in parallel mode? - if GEInv.parallel_aio_soc>0: - power_output['SOC']=GEInv.parallel_aio_soc - power_output['SOC_kWh'] = round((int(power_output['SOC'])*(inverterModel.batterycapacity))/100,2) - else: + if GEInv.parallel_aio_num>1: + # power_output['SOC']=GEInv.parallel_aio_soc + # power_output['SOC_kWh'] = round((int(power_output['SOC'])*(inverterModel.batterycapacity))/100,2) + #else: # Calc based on individual SOCs count=0 total=0 @@ -2152,7 +2152,6 @@ def dataSmoother2(dataNew, dataOld, lastUpdate, invtype,inv_time): else: max=lookup.max ## Make sure its a number... - newData=float(newData) now = inv_time then = datetime.datetime.fromisoformat(lastUpdate) @@ -2178,14 +2177,14 @@ def dataSmoother2(dataNew, dataOld, lastUpdate, invtype,inv_time): ## Finally smooth data if its not already Zero (avoid div by Zero) if oldData != 0: ### Run checks against the conditions in GivLUT ### - if "Power" in name: + if "power" in name.lower(): if newData==12179: return oldData if lookup.smooth: # apply smoothing if required if newData != oldData: # Only if its not the same timeDelta = (now-then).total_seconds() dataDelta = abs(newData-oldData)/oldData #Should it be a ratio or an abs value as low values easily meet the threshold - if "Power" in name: + if "power" in name.lower(): if abs(newData-oldData)>abssmooth: if checkRawcache(newData,name,abssmooth): #If new data is persistently outside bounds then use new value return(newData) @@ -2194,7 +2193,7 @@ def dataSmoother2(dataNew, dataOld, lastUpdate, invtype,inv_time): return(oldData) else: if dataDelta > smoothRate and timeDelta < 60: - logger.debug(str(name)+" jumped too far in a single read: "+str(oldData)+"->"+str(newData)+" so using previous value") + logger.info(str(name)+" jumped too far in a single read: "+str(oldData)+"->"+str(newData)+" so using previous value") return(oldData) return(newData) diff --git a/README.md b/README.md index fd67fb4a..7364f77c 100644 --- a/README.md +++ b/README.md @@ -1,123 +1,193 @@ -# GivTCP -## TCP Modbus connection to MQTT/JSON for GivEnergy Battery/PV Invertors +# GivTCP v3 + Version 3 of GivTCP will allow connection to the following GivEnergy Devices: + - Hybrid inverter + - AC Coupled inverter + - Single and Three Phase inverters + - Gateway (Single or Parallel mode) + - EMS + - EV Charger (EVC) + - All-In-One -This project opens a connection to the GivEnergy invertors via TCP Modbus. Access is given through the native Wifi/Ethernet dongle and can be connected via either LAN or directly through the inbuilt SSID AP. +This project uses a modbus connection to the GivEnergy devices through the native Wifi/Ethernet dongle and can be connected via either LAN or directly through the inbuilt SSID AP. +GivTCP can auto-discover devices on the network for a (near) zero config setup -Typically run through the Home Assistant Addon, it is also possible to run as a standalone docker container. +Typically run through the Home Assistant Addon, it is also possible to run as a standalone docker container. + +## Quick Set-up + +### Install GivTCP +#### Addon + - Add https://github.com/britkat1980/ha-addons to the Addon Store repositories in HA + - Refresh addon store and click on GivTCP and click install + +#### Docker +- Use Docker Compose file to create container + +### Run Addon/Container + + - Start the addon/container + - Check logs for any errors and note the web-config url + +### Configure GivTCP + + - Navigate to the web config address (which is typically: http://IPADDRESS:8099/config.html) + - Step through the config stages, noting that GivTCP should have auto populated inverter and MQTT details + - Check settings are as you want them + - Turn on "self_run" + - HA users - turn on "Home Assistant Auto Discovery" + - If you are using an MQTT broker outside HA progress to MQTT page to configure MQTT + - Click "Save and Restart" (if you are running docker you will need to manually restart the container + + + + + +GivTCP should be publishing data to your MQTT broker and Home Assistant should pick this up automatically. + +### (optional) Check Home Assistant + + Once GivTCP has restarted + - Go to HA -> Settings -> Integrations -> MQTT + - Check GivTCP devices have been created + +You should now have lots of data points and controls available in HA and you can begin to integrate into your smart home. + +See [Settings Guide](SETTINGS-GUIDE.md) for more detail on controls available and data points. + +### Parallel AIO + +Users with parallel AIO installations should have 3 (with dual AIO) inverters pre-populated in the "Inverters" page. If any are missing they should be added here. Static / fixed IP addresses should be set for all inverters. The Gateway inverter should be the only inverter that is controlled via GivTCP, the individual AIO inverter data treated for information only. ## Home Assistant Add-on -This container can also be used as an add-on in Home Assistant. -The add-on requires an existing MQTT broker such as Mosquito, also available to install from the Add-on store. -To install GivTCP as an add-on, add this repository (https://github.com/britkat1980/giv_tcp) to the Add-on Store repository list. +To install GivTCP as an add-on, add this repository (https://github.com/britkat1980/ha-addons) to the Add-on Store repository list. + +The addon assumes HA is running Mosquito as an addon, which also available to install from the Add-on store. GivTCP will automatically connect to it if installed. If not, then you will need to install your own MQTT broker and provide the connection details in the config page ### Home Assistant Usage -GivTCP will automatically create Home Assistant devices if "HA_AUTO_D" setting is True. This does require MQTT_OUTPUT to also be true and for GivTCP to publish its data to the same MQTT broker as HA is listening to. -This will populate HA with all devices and entities for control and monitoring. The key entities and their usage are outlined below: - -The Home Assistant Addon config page outlines the configuration environmental variables for set-up of GivTCP - -If you have enabled the "SELF_RUN" setting (recommended) then the container/add-on will automatically call "RunALL" every "SELF_LOOPTIMER" seconds and you will not need to use the REST commands here. If you wish to take data from GivTCP and push to another system, then you should call "getCache" which will return the json data without pushing to MQTT or other defined publish settings. - -## GivTCP Control -| Function | Description | REST URL | REST payload | MQTT Topic | MQTT Payload | -|-------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|--------------------------|------------------------------------------------------------|-------------------------|------------------------------------------------------------| -| enableChargeTarget | Sets inverter to follow setChargeTarget value when charging from grid (will stop charging when battery SOC= ChargeTarget) | /enableChargeTarget | {"state","enable"} | enableChargeTarget | enable | -| disableChargeTarget | Sets inverter to ignore setChargeTarget value when charging from grid (will continue to charge to 100% during ChargeSlot) | /disableChargeTarget | {"state","enable"} | disableChargeTarget | enable | -| enableChargeSchedule | Sets the Charging schedule state, if disabled the battery will not charge as per the schedule | /enableChargeSchedule | {"state","enable"} | enableChargeSchedule | enable | -| enableDischargeSchedule | Sets the Discharging schedule state, if disabled the battery will will ignore rhe discharge schedule and discharge as per demand (similar to eco mode) | /enableDischargeSchedule | {"state","enable"} | enableDischargeSchedule | enable | -| enableDischarge | Enable/Disables Discharging to instantly pause discharging, use 'enable' or 'disable' | /enableDischarge | {"state","enable"} | enableDischarge | enable | -| setChargeRate | Sets the charge power as a percentage. 100% == 2.6kW | /setChargeRate | {"chargeRate","100"} | setChargeRate | 100 | -| setDischargeRate | Sets the discharge power as a percentage. 100% == 2.6kW | /setDischargeRate | {"dischargeRate","100"} | setDischargeRate | 100 | -| setChargeTarget | Sets the Target charge SOC | /setChargeTarget | {"chargeToPercent":"50"} | setChargeTarget | 50 | -| setBatteryReserve | Sets the Battery Reserve discharge cut-off limit | /setBatteryReserve | {"reservePercent":"5"} | setBatteryReserve | 5 | -| setChargeSlot1 | Sets the time and target SOC of the first chargeslot. Times must be expressed in hhmm format. Enable flag show in the battery.api documentation is not needed and chargeToPercent is optional | /setChargeSlot1 | {"start":"0100","finish":"0400","chargeToPercent":"55"} | setChargeSlot1 | {"start":"0100","finish":"0400","chargeToPercent":"55"} | -| setDischargeSlot1 | Sets the time and target SOC of the first dischargeslot. Times must be expressed in hhmm format. Enable flag show in the battery.api documentation is not needed and dischargeToPercent is optional | /setDischargeSlot1 | {"start":"0100","finish":"0400","dischargeToPercent":"55"} | setDischargeSlot1 | {"start":"0100","finish":"0400","dischargeToPercent":"55"} | -| setDischargeSlot2 | Sets the time and target SOC of the first dischargeslot. Times must be expressed in hhmm format. Enable flag show in the battery.api documentation is not needed and dischargeToPercent is optional | /setDischargeSlot2 | {"start":"0100","finish":"0400","dischargeToPercent":"55"} | setDischargeSlot2 | {"start":"0100","finish":"0400","dischargeToPercent":"55"} | -| setBatteryMode | Sets battery operation mode. Mode value must be one of Eco, Timed Demand or Timed Export | /setBatteryMode | {"mode":"Eco"} | setBatteryMode | 1 | -| setDateTime | Sets inverter time, format must be as define in payload | /setDateTime | {"dateTime":"dd/mm/yyyy hh:mm:ss"} | setDateTime | "dd/mm/yyyy hh:mm:ss" | -| setBatteryPauseMode | Sets battery operation mode. Mode value must be one of "Disabled","PauseCharge","PauseDischarge" or "PauseBoth" | /setBatteryPauseMode | {"state":"Disabled"} | setBatteryPauseMode | 1 -| forceExport | Forces battery to Export (discharge at Max power) for a given duration in Minutes. command must be "Cancel" or an integer value. Sending 0 will also call the cancel function | /forceExport | {"15"} | forceExport | 1 -| forceCharge | Forces battery to charge for a given duration in Minutes. Command must be "Cancel" or an integer value. Sending 0 will also call the cancel function | /forceCharge | {"15"} | forceCharge | 1 -| tempPauseCharge | Suspends charging for a for a given duration in Minutes. Command must be "Cancel" or an integer value. Sending 0 will also call the cancel function | /tempPauseCharge | {"15"} | tempPauseCharge | 1 -| tempPauseDischarge | Suspends discharging for a given duration in Minutes. command must be "Cancel" or an integer value. Sending 0 will also call the cancel function | /tempPauseDischarge | {"15"} | tempPauseDischarge | 1 - -## Usage methods: -GivTCP data and control is generally available through two core methods. If you are using the Home Assistant Add-On then these are generally transparent to the user, but are working and available in the background. + +GivTCP is designed to run continuously and has a self-run setting, which should be switched on once the settings have been reviewed. +You can change the frequency of the data collection through the config , but its not recommended to drop the self_run loop time to below 30s. + +GivTCP will automatically create multiple devices in Home Assistant and you can view them through the Integration page under MQTT. + + + +## Other Usage methods: + +GivTCP data and control is also available through either MQTT or REST to allow integration into other systems and processes. ### MQTT -By setting MQTT_OUTPUT = True, the script will publish directly to the nominated MQTT broker (MQTT_ADDRESS) all the requested read data. -Data is published to "GivEnergy//" by default or you can nominate a specific root topic by setting "MQTT_TOPIC" in the settings. +By enabling MQTT in the config, GivTCP will publish directly to the nominated MQTT broker all inverter data. Data is published to "GivEnergy//" by default or you can nominate a specific root topic by setting "MQTT_TOPIC" in the settings. -image + + +Control is also available using MQTT. By publishing data to the same MQTT broker as above you can trigger the control methods as per the above table. -Control is available using MQTT. By publishing data to the same MQTT broker as above you can trigger the control methods as per the above table. Root topic for control is: -"GivEnergy/control//" - Default + +"GivEnergy/control//" - Default (note lower case "control") + "/control//" - If MQTT_TOPIC is set + + ### RESTful Service -GivTCP provides a wrapper function REST.py which uses Flask to expose the read and control functions as RESTful http calls. To utilise this service you will need to either use a WSGI service such as gunicorn or use the pre-built Docker container. -If Docker is running in Host mode then the REST service is available on port 6345 +GivTCP provides a REST API for data output and control. REST service is available at: http://IPADDRESS:8099 +Each available inverter exposes its REST interface on the following endpoints: -#### GivTCP Read data + - /REST1/ + - /REST2/ + - /REST3/ + - /REST4/ + - /REST5/ + You can call REST1/api to discover what api calls are available to you. + -GivTCP collects all inverter and battery data and creates a nested data structure with all data available in a structured format. +If Docker is running in Host mode then the REST service is available on port 6345 + + -| Function | Description | REST URL | -|---------------|------------------------------------------------------------------------------------|-----------| -| getData | This connects to the inverter, collects all data and stores a cache for publishing | /getData | -| readData | Retrieves data from the local cache and publishes data according to the settings | /readData | -| getCache | Retrieves data from the local cache returns it without publishing to MQTT etc... | /getCache | -| RunAll | Runs both getData and pubFromPickle to refresh data and then publish | /runAll | ## Web Dashboard -You can enable the built-in web dashboard if you'd like a way to visualise data for your inverter(s). For more details -please see the [ReadMe file in the separate repository](https://github.com/DanielGallo/GivEnergy-Smart-Home-Display/). + + +You can enable the built-in web dashboard if you'd like a way to visualise data for your inverter(s). This is enabled in the settings page and is found on port 3000. -![Dashboard-Example-Landscape.png](graphics/Dashboard-Example-Landscape.png) +For more details please see the [ReadMe file in the separate repository](https://github.com/DanielGallo/GivEnergy-Smart-Home-Display/). -The web dashboard is able to summarise data for a single inverter, or multiple inverters in either a single-phase -or three-phase environment. + -If you have any issues or feedback regarding the web dashboard, please post a question or issue [here](https://github.com/DanielGallo/GivEnergy-Smart-Home-Display/issues). +The web dashboard is able to summarise data for a single inverter, or multiple inverters in either a single-phase or three-phase environment. If you have any issues or feedback regarding the web dashboard, please post a question or issue [here](https://github.com/DanielGallo/GivEnergy-Smart-Home-Display/issues). -# GivEVC + -## GivEnergy Electric Vehicle Charger +## GivEnergy Electric Vehicle Charger (GivEVC) -From version 2.4 onwards GivTCP incorporates control and monitoring of the GE charger. Connecting via local modbus it can monitor real-time stats and provide simple control features. With the EVC cloud conrol does not use the modbus protocol, so there is minimal opportunity for changes to reflect in the official app/cloud portal. Particularly the Charging modes, which are merely mimiced in GivEVC +GivTCP incorporates control and monitoring of the GE charger. Connecting via local modbus it can monitor real-time stats and provide simple control features. With the EVC cloud conrol does not use the modbus protocol, so there is minimal opportunity for changes to reflect in the official app/cloud portal. Particularly the Charging modes, which are merely mimiced in GivEVC. -## Configuration +NOTE - there is currently a firmware bug with the GivEVC where the Modbus port only available on WiFi. Therefore if your EVC is connected via ethernet is will be necessary to disconnect and re-connect via WiFi to recieve data via GivTCP. + +### Configuration + + All that is required for config are the IP address and the self run timer. Setting EVC_ENABLE to True will turn on the function. -## Control + + +### Control + + Most controls are self explanatory but some require clarification on their function: -### Plug and Go: + + +#### Plug and Go: + When turned on the vehicle will start to charge as soon as it is plugged in. When off charging will commence when triggered by RFID card or "Charge Control" -### Charge Control: + + +#### Charge Control: + This starts and stops vehicle charging, when "Plug and Go" is on. -### Charging Mode: + + +#### Charging Mode: + Mimcs the cloud based "modes" of charging. -#### Grid + + +##### Grid + Charges at current set by "Charge Limit", regardless of what energy is available (typically will pull from Grid) -#### Solar + + +##### Solar + Modulates the Charge Limit based on the amount of "excess solar" available after serving the current house Load. This requires minimum of 1.4kW (6A) excess as required by the EVSE spec. -#### Hybrid + + +##### Hybrid + This will modulate Charge Limit to top up a base 6A grid charge with any excess solar energy. Similar to Solar but uses a constant 6A from Grid plus additional solar energy on top. -### Max Session Energy + + +#### Max Session Energy + This will cap the maximum energy delivered to the vehicle in a single charge session. Setting this to 0kWh disables this setting. -### Import Cap + + +#### Import Cap + This will monitor the Grid current from the first GivTCP inverter and if it is within 5% of the Import Cap setting it will reduce EVC Charge current to stay 10% under the import Cap. Setting this to 0A disables this setting. diff --git a/READMEv3.md b/READMEv3.md deleted file mode 100644 index 7364f77c..00000000 --- a/READMEv3.md +++ /dev/null @@ -1,193 +0,0 @@ -# GivTCP v3 - Version 3 of GivTCP will allow connection to the following GivEnergy Devices: - - Hybrid inverter - - AC Coupled inverter - - Single and Three Phase inverters - - Gateway (Single or Parallel mode) - - EMS - - EV Charger (EVC) - - All-In-One - -This project uses a modbus connection to the GivEnergy devices through the native Wifi/Ethernet dongle and can be connected via either LAN or directly through the inbuilt SSID AP. -GivTCP can auto-discover devices on the network for a (near) zero config setup - -Typically run through the Home Assistant Addon, it is also possible to run as a standalone docker container. - -## Quick Set-up - -### Install GivTCP -#### Addon - - Add https://github.com/britkat1980/ha-addons to the Addon Store repositories in HA - - Refresh addon store and click on GivTCP and click install - -#### Docker -- Use Docker Compose file to create container - -### Run Addon/Container - - - Start the addon/container - - Check logs for any errors and note the web-config url - -### Configure GivTCP - - - Navigate to the web config address (which is typically: http://IPADDRESS:8099/config.html) - - Step through the config stages, noting that GivTCP should have auto populated inverter and MQTT details - - Check settings are as you want them - - Turn on "self_run" - - HA users - turn on "Home Assistant Auto Discovery" - - If you are using an MQTT broker outside HA progress to MQTT page to configure MQTT - - Click "Save and Restart" (if you are running docker you will need to manually restart the container - - - - - -GivTCP should be publishing data to your MQTT broker and Home Assistant should pick this up automatically. - -### (optional) Check Home Assistant - - Once GivTCP has restarted - - Go to HA -> Settings -> Integrations -> MQTT - - Check GivTCP devices have been created - -You should now have lots of data points and controls available in HA and you can begin to integrate into your smart home. - -See [Settings Guide](SETTINGS-GUIDE.md) for more detail on controls available and data points. - -### Parallel AIO - -Users with parallel AIO installations should have 3 (with dual AIO) inverters pre-populated in the "Inverters" page. If any are missing they should be added here. Static / fixed IP addresses should be set for all inverters. The Gateway inverter should be the only inverter that is controlled via GivTCP, the individual AIO inverter data treated for information only. - -## Home Assistant Add-on -To install GivTCP as an add-on, add this repository (https://github.com/britkat1980/ha-addons) to the Add-on Store repository list. - -The addon assumes HA is running Mosquito as an addon, which also available to install from the Add-on store. GivTCP will automatically connect to it if installed. If not, then you will need to install your own MQTT broker and provide the connection details in the config page - -### Home Assistant Usage - -GivTCP is designed to run continuously and has a self-run setting, which should be switched on once the settings have been reviewed. -You can change the frequency of the data collection through the config , but its not recommended to drop the self_run loop time to below 30s. - -GivTCP will automatically create multiple devices in Home Assistant and you can view them through the Integration page under MQTT. - - - -## Other Usage methods: - -GivTCP data and control is also available through either MQTT or REST to allow integration into other systems and processes. - -### MQTT - -By enabling MQTT in the config, GivTCP will publish directly to the nominated MQTT broker all inverter data. Data is published to "GivEnergy//" by default or you can nominate a specific root topic by setting "MQTT_TOPIC" in the settings. - - - -Control is also available using MQTT. By publishing data to the same MQTT broker as above you can trigger the control methods as per the above table. - -Root topic for control is: - -"GivEnergy/control//" - Default (note lower case "control") - -"/control//" - If MQTT_TOPIC is set - - - -### RESTful Service - -GivTCP provides a REST API for data output and control. REST service is available at: http://IPADDRESS:8099 -Each available inverter exposes its REST interface on the following endpoints: - - - /REST1/ - - /REST2/ - - /REST3/ - - /REST4/ - - /REST5/ - You can call REST1/api to discover what api calls are available to you. - - -If Docker is running in Host mode then the REST service is available on port 6345 - - - - -## Web Dashboard - - - -You can enable the built-in web dashboard if you'd like a way to visualise data for your inverter(s). This is enabled in the settings page and is found on port 3000. - -For more details please see the [ReadMe file in the separate repository](https://github.com/DanielGallo/GivEnergy-Smart-Home-Display/). - - - -The web dashboard is able to summarise data for a single inverter, or multiple inverters in either a single-phase or three-phase environment. If you have any issues or feedback regarding the web dashboard, please post a question or issue [here](https://github.com/DanielGallo/GivEnergy-Smart-Home-Display/issues). - - - -## GivEnergy Electric Vehicle Charger (GivEVC) - -GivTCP incorporates control and monitoring of the GE charger. Connecting via local modbus it can monitor real-time stats and provide simple control features. With the EVC cloud conrol does not use the modbus protocol, so there is minimal opportunity for changes to reflect in the official app/cloud portal. Particularly the Charging modes, which are merely mimiced in GivEVC. - -NOTE - there is currently a firmware bug with the GivEVC where the Modbus port only available on WiFi. Therefore if your EVC is connected via ethernet is will be necessary to disconnect and re-connect via WiFi to recieve data via GivTCP. - -### Configuration - - - -All that is required for config are the IP address and the self run timer. Setting EVC_ENABLE to True will turn on the function. - - - -### Control - - - -Most controls are self explanatory but some require clarification on their function: - - - -#### Plug and Go: - -When turned on the vehicle will start to charge as soon as it is plugged in. When off charging will commence when triggered by RFID card or "Charge Control" - - - -#### Charge Control: - -This starts and stops vehicle charging, when "Plug and Go" is on. - - - -#### Charging Mode: - -Mimcs the cloud based "modes" of charging. - - - -##### Grid - -Charges at current set by "Charge Limit", regardless of what energy is available (typically will pull from Grid) - - - -##### Solar - -Modulates the Charge Limit based on the amount of "excess solar" available after serving the current house Load. This requires minimum of 1.4kW (6A) excess as required by the EVSE spec. - - - -##### Hybrid - -This will modulate Charge Limit to top up a base 6A grid charge with any excess solar energy. Similar to Solar but uses a constant 6A from Grid plus additional solar energy on top. - - - -#### Max Session Energy - -This will cap the maximum energy delivered to the vehicle in a single charge session. Setting this to 0kWh disables this setting. - - - -#### Import Cap - -This will monitor the Grid current from the first GivTCP inverter and if it is within 5% of the Import Cap setting it will reduce EVC Charge current to stay 10% under the import Cap. Setting this to 0A disables this setting. diff --git a/buildx.bat b/buildx.bat index ac121b6d..024ee4d5 100644 --- a/buildx.bat +++ b/buildx.bat @@ -1,3 +1,3 @@ -::docker buildx build --platform linux/amd64,linux/arm64,linux/arm/v7,linux/arm/v6 -t britkat/giv_tcp-dev:3.0.0zza -t britkat/giv_tcp-dev:latest --push . -docker buildx build --platform linux/amd64,linux/arm64,linux/arm/v7,linux/arm/v6 -t britkat/giv_tcp-beta:3.0.0i -t britkat/giv_tcp-beta:latest --push . -::docker buildx build --platform linux/amd64,linux/arm64,linux/arm/v7,linux/arm/v6 -t britkat/giv_tcp-ma:latest -t britkat/giv_tcp-ma:2.4.3 --push . \ No newline at end of file +docker buildx build --platform linux/amd64,linux/arm64,linux/arm/v7,linux/arm/v6 -t britkat/giv_tcp-dev:3.0.7 -t britkat/giv_tcp-dev:latest --push . +::docker buildx build --platform linux/amd64,linux/arm64,linux/arm/v7,linux/arm/v6 -t britkat/giv_tcp-beta:3.0.1 -t britkat/giv_tcp-beta:latest --push . +::docker buildx build --platform linux/amd64,linux/arm64,linux/arm/v7,linux/arm/v6 -t britkat/giv_tcp-ma:latest -t britkat/giv_tcp-ma:3.0.1 --push . \ No newline at end of file diff --git a/restresponse.json b/restresponse.json new file mode 100644 index 00000000..0101f68c --- /dev/null +++ b/restresponse.json @@ -0,0 +1 @@ +[{"id": "setChargeSlotStart", "result": "{\"result\": \"Setting Charge Slot 1 Start to: 23:00 was a success\"}"}] \ No newline at end of file diff --git a/settings.json b/settings.json index 4d7ef993..ac9efe1f 100644 --- a/settings.json +++ b/settings.json @@ -25,6 +25,7 @@ "Model_5": "", "serial_number_5": "", "inverterName_5":"GivTCP5", + "Host_IP": "", "MQTT_Output": true, "MQTT_Address": "", "MQTT_Username": "", diff --git a/startup_2.py b/startup_2.py index 3d3a85aa..ac205a96 100644 --- a/startup_2.py +++ b/startup_2.py @@ -47,7 +47,7 @@ def validateEVC(HOST): return False except: e=sys.exc_info() - logger.error(e) + logger.debug(str(HOST)+" isn't a GE EVC, so ignoring. "+e) return False async def getInvDeets(HOST): @@ -336,11 +336,24 @@ def findinv(networks): sleep(2) # Sleep to allow port scanning socket to close -#write ingress data to json file for config page to use -with open('/app/ingress/hostip.json', 'w') as f: - f.write(json.dumps(hostIP,indent=4)) -with open('/app/ingress/ingressurl.json', 'w') as f: - f.write(json.dumps(baseurl,indent=4)) +PATH= "/app/GivTCP_" +SFILE="/config/GivTCP/allsettings.json" +v3upgrade=False #Check if its a new upgrade or already has new json config file +if not exists(SFILE): + v3upgrade=True + logger.debug("Copying in a template settings.json to: "+str(SFILE)) + shutil.copyfile("settings.json",SFILE) +else: + # If theres already a settings file, make sure its got any new elements + with open(SFILE, 'r') as f1: + setts=json.load(f1) + with open("/app/settings.json", 'r') as f2: + templatesetts=json.load(f2) + for setting in templatesetts: + if not setting in setts: + setts[setting]=templatesetts[setting] + with open(SFILE, 'w') as f: + f.write(json.dumps(setts,indent=4)) finv={} i=0 @@ -373,26 +386,6 @@ def findinv(networks): logger.debug("Running nginx") -PATH= "/app/GivTCP_" -SFILE="/config/GivTCP/allsettings.json" -v3upgrade=False #Check if its a new upgrade or already has new json config file -if not exists(SFILE): - v3upgrade=True - logger.debug("Copying in a template settings.json to: "+str(SFILE)) - shutil.copyfile("settings.json",SFILE) -else: - # If theres already a settings file, make sure its got any new elements - with open(SFILE, 'r') as f1: - setts=json.load(f1) - with open("/app/settings.json", 'r') as f2: - templatesetts=json.load(f2) - for setting in templatesetts: - if not setting in setts: - setts[setting]=templatesetts[setting] - with open(SFILE, 'w') as f: - f.write(json.dumps(setts,indent=4)) - - # Update json object with found data logger.debug ("Creating master allsettings.json for all inverters.") with open(SFILE, 'r') as f: @@ -407,6 +400,17 @@ def findinv(networks): if setts["MQTT_Password"]=="": setts["MQTT_Password"]=mqtt_password setts["MQTT_Port"]=mqtt_port if setts["MQTT_Address"]=="": setts['MQTT_Output']=False +if not hostIP=="": + setts["Host_IP"]=hostIP +elif setts["Host_IP"]=="": + logger.error("Unable to determine Host IP, manually configure the allsettings.json file with your HA instance IP") + +#write ingress data to json file for config page to use +with open('/app/ingress/hostip.json', 'w') as f: + f.write(json.dumps(setts["Host_IP"],indent=4)) +with open('/app/ingress/ingressurl.json', 'w') as f: + f.write(json.dumps(baseurl,indent=4)) + for inv in inverterStats: logger.debug("Using found Inverter data to autosetup settings.json") @@ -482,7 +486,10 @@ def findinv(networks): setts["influxBucket"]=envs[0]["INFLUX_BUCKET"] setts["influxOrg"]=envs[0]["INFLUX_ORG"] setts["self_run"]=True - setts['evc_enable']=bool(envs[0]["EVC_ENABLE"]) + if envs[0]["EVC_ENABLE"].lower()=="true": + setts['evc_enable']=True + else: + setts['evc_enable']=False setts['evc_self_run_timer']=envs[0]["EVC_SELF_RUN_TIMER"] ## Match HAPREFIX to inverterIP @@ -684,7 +691,7 @@ def findinv(networks): logger.info ("Starting Mosquitto on port "+str(setts['MQTT_Port'])) mqttBroker=subprocess.Popen(["/usr/sbin/mosquitto", "-c",PATH+"/mqtt.conf"]) - if setts['evc_enable']==True: + if setts['evc_enable']==True and not setts['evc_ip_address'] == '': if not evcSelfRun.poll()==None: evcSelfRun.kill() logger.error("EVC Self Run loop process died. restarting...")