Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 8 additions & 5 deletions lib/TWCManager/Control/HTTPControl.py
Original file line number Diff line number Diff line change
Expand Up @@ -270,6 +270,7 @@ def do_API_GET(self):
elif self.url.path == "/api/getSlaveTWCs":
data = {}
totals = {
"carsCharging": 0,
"lastAmpsOffered": 0,
"lifetimekWh": 0,
"maxAmps": 0,
Expand All @@ -278,15 +279,15 @@ def do_API_GET(self):
for slaveTWC in master.getSlaveTWCs():
TWCID = "%02X%02X" % (slaveTWC.TWCID[0], slaveTWC.TWCID[1])
data[TWCID] = {
"carsCharging": slaveTWC.isCharging,
"chargerLoadInW": round(slaveTWC.getCurrentChargerLoad()),
"currentVIN": slaveTWC.currentVIN,
"lastAmpsOffered": round(slaveTWC.lastAmpsOffered, 2),
"lastHeartbeat": round(time.time() - slaveTWC.timeLastRx, 2),
"carsCharging": slaveTWC.isCharging,
"lastVIN": slaveTWC.lastVIN,
"lifetimekWh": slaveTWC.lifetimekWh,
"maxAmps": float(slaveTWC.maxAmps),
"reportedAmpsActual": float(slaveTWC.reportedAmpsActual),
"chargerLoadInW": round(slaveTWC.getCurrentChargerLoad()),
"state": slaveTWC.reportedState,
"version": slaveTWC.protocolVersion,
"voltsPhaseA": slaveTWC.voltsPhaseA,
Expand All @@ -307,21 +308,23 @@ def do_API_GET(self):
# Adding some vehicle data
vehicle = slaveTWC.getLastVehicle()
if vehicle != None:
data[TWCID]["lastAtHome"] = vehicle.atHome
data[TWCID]["lastBatterySOC"] = vehicle.batteryLevel
data[TWCID]["lastChargeLimit"] = vehicle.chargeLimit
data[TWCID]["lastAtHome"] = vehicle.atHome
data[TWCID]["lastTimeToFullCharge"] = vehicle.timeToFullCharge

totals["carsCharging"] += slaveTWC.isCharging
totals["lastAmpsOffered"] += slaveTWC.lastAmpsOffered
totals["lifetimekWh"] += slaveTWC.lifetimekWh
totals["maxAmps"] += slaveTWC.maxAmps
totals["maxAmps"] = slaveTWC.maxAmps if totals["maxAmps"] == 0 else min(totals["maxAmps"], slaveTWC.maxAmps)
totals["reportedAmpsActual"] += slaveTWC.reportedAmpsActual

data["total"] = {
"carsCharging": totals["carsCharging"],
"lastAmpsOffered": round(totals["lastAmpsOffered"], 2),
"lifetimekWh": totals["lifetimekWh"],
"maxAmps": totals["maxAmps"],
"reportedAmpsActual": round(totals["reportedAmpsActual"], 2),
"reportedAmpsActual": totals["reportedAmpsActual"],
"TWCID": "total",
}

Expand Down
64 changes: 64 additions & 0 deletions lib/TWCManager/EMS/Victron.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
import logging
from pyModbusTCP.client import ModbusClient

logger = logging.getLogger("Victron")

class Victron:
def __init__(self, master):
self.master = master
self.config = master.config.get("sources", {}).get("CerboGX", {})
self.enabled = self.config.get("enabled", False)
self.server_ip = self.config.get("serverIP", "192.168.30.101")
self.server_port = int(self.config.get("serverPort", 502))
self.unit_id = int(self.config.get("unitID", 100))

self.client = ModbusClient(host=self.server_ip, port=self.server_port, unit_id=self.unit_id, auto_open=True)

if not self.enabled:
logger.info("Victron EMS Module Disabled.")

def getConsumption(self):
if not self.enabled:
return 0
return self.update("consumption")

def getGeneration(self):
if not self.enabled:
return 0
return self.update("generation")

def update(self, data_type):
try:
if not self.client.is_open:
self.client.open()

if data_type == "consumption":
# Addresses for Output Power (per phase)
registers = [(817,100), (818,100), (819,100)]
scale_factor = 1
elif data_type == "generation":
# Addresses for PV AC-coupled output (per phase)
registers = [(808,100), (809,100), (810,100)]
scale_factor = 1
else:
return 0

total_power = 0
for reg, unit_id in registers:
# Set the unit_id dynamically for each read operation
self.client.unit_id = unit_id
result = self.client.read_input_registers(reg, 1)
if result:
total_power += result[0] * scale_factor
else:
logger.warning(f"Failed to read register {reg} on unit {unit_id}")

return total_power

except Exception as e:
logger.error(f"Error communicating with Victron: {e}")
return 0

finally:
if self.client.is_open:
self.client.close()
1 change: 1 addition & 0 deletions lib/TWCManager/TWCManager.py
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,7 @@
"EMS.SolarLog",
"EMS.TeslaPowerwall2",
"EMS.TED",
"EMS.Victron",
"EMS.Volkszahler",
"EMS.URL",
"Status.HASSStatus",
Expand Down