fix: setpoint clamp, thread safety, error handling, real-time kWh counters; cleanup repo
This commit is contained in:
+41
-7
@@ -1,5 +1,8 @@
|
||||
|
||||
import logging
|
||||
import threading
|
||||
import time
|
||||
import functools
|
||||
import victronclient
|
||||
import mqttpublisher
|
||||
import tibberclient
|
||||
@@ -7,6 +10,15 @@ from enum import IntEnum
|
||||
|
||||
logger = logging.getLogger('main')
|
||||
|
||||
|
||||
def _locked(method):
|
||||
# Serialise access to controller state: MQTT callbacks and the main loop run in different threads
|
||||
@functools.wraps(method)
|
||||
def wrapper(self, *args, **kwargs):
|
||||
with self.lock:
|
||||
return method(self, *args, **kwargs)
|
||||
return wrapper
|
||||
|
||||
charge_max_price_level = 0.024
|
||||
|
||||
MAX_POWER=4000
|
||||
@@ -27,6 +39,8 @@ class Chargemode(IntEnum):
|
||||
class chargeman_controller:
|
||||
|
||||
def __init__(self, victronconn: victronclient.client, tibber: tibberclient.client) -> None:
|
||||
self.lock = threading.RLock()
|
||||
self.last_update = None
|
||||
self.chargemode=Chargemode.FLOATING
|
||||
self.chargevalue=0
|
||||
self.consump_updated=False
|
||||
@@ -57,17 +71,20 @@ class chargeman_controller:
|
||||
return self.battery_total_net_usage
|
||||
|
||||
|
||||
@_locked
|
||||
def set_net_consumption(self, value):
|
||||
self.consumption = value
|
||||
self.consump_updated = True
|
||||
self.check_net_usage()
|
||||
|
||||
|
||||
@_locked
|
||||
def set_net_delivery(self, value):
|
||||
self.return_delivery = value
|
||||
self.return_updated = True
|
||||
self.check_net_usage()
|
||||
|
||||
@_locked
|
||||
def check_net_usage(self):
|
||||
|
||||
|
||||
@@ -86,7 +103,12 @@ class chargeman_controller:
|
||||
#logger.info("Update P1 usage: {}".format(netp1usage))
|
||||
if self.chargemode in [Chargemode.BALANCE_DYN,Chargemode.CHARGE_DYN,Chargemode.DISCHARGE_DYN]:
|
||||
|
||||
setpoint = -1 * self.victronconn.get_power_usage()
|
||||
power_usage = self.victronconn.get_power_usage()
|
||||
if power_usage is None:
|
||||
logger.warning("Victron power usage unknown, skipping dynamic setpoint")
|
||||
return
|
||||
|
||||
setpoint = -1 * power_usage
|
||||
|
||||
setpoint = self.netp1usage+setpoint
|
||||
|
||||
@@ -101,22 +123,25 @@ class chargeman_controller:
|
||||
if self.setpoint > MAX_CHARGE_POWER:
|
||||
self.setpoint = MAX_CHARGE_POWER
|
||||
elif self.setpoint < -MAX_POWER:
|
||||
self.setpoint = MAX_POWER
|
||||
self.setpoint = -MAX_POWER
|
||||
|
||||
#logger.info ("Dynamic setpoint: {}".format(setpoint))
|
||||
self.apply_charge_mode()
|
||||
|
||||
|
||||
@_locked
|
||||
def set_chargemode(self, mode: Chargemode):
|
||||
self.chargemode = mode
|
||||
|
||||
self.apply_charge_mode()
|
||||
|
||||
|
||||
@_locked
|
||||
def set_chargemode_int(self, mode: int):
|
||||
self.chargemode = Chargemode(mode)
|
||||
self.apply_charge_mode()
|
||||
|
||||
@_locked
|
||||
def set_chargevalue(self,value):
|
||||
self.chargevalue = value
|
||||
|
||||
@@ -142,6 +167,7 @@ class chargeman_controller:
|
||||
self.valuekwh = value
|
||||
|
||||
|
||||
@_locked
|
||||
def update(self):
|
||||
|
||||
logger.debug("Run controller update")
|
||||
@@ -150,10 +176,17 @@ class chargeman_controller:
|
||||
|
||||
logger.debug("Controller update mqtt loop done")
|
||||
|
||||
if self.victronconn.get_power_usage() > 0:
|
||||
self.battery_total_net_usage += self.victronconn.get_power_usage() /60/60*10
|
||||
elif self.victronconn.get_power_usage() < 0:
|
||||
self.battery_total_net_delivery += (self.victronconn.get_power_usage() * -1 ) /60/60*10
|
||||
now = time.monotonic()
|
||||
elapsed = 0.0 if self.last_update is None else now - self.last_update
|
||||
self.last_update = now
|
||||
|
||||
power_usage = self.victronconn.get_power_usage()
|
||||
if power_usage is not None:
|
||||
# W * s / 3600 = Wh, as kWh counter: elapsed real time instead of a fixed interval
|
||||
if power_usage > 0:
|
||||
self.battery_total_net_usage += power_usage / 60 / 60 * elapsed
|
||||
elif power_usage < 0:
|
||||
self.battery_total_net_delivery += (power_usage * -1) / 60 / 60 * elapsed
|
||||
|
||||
self.apply_charge_mode()
|
||||
|
||||
@@ -175,7 +208,7 @@ class chargeman_controller:
|
||||
self.netp1usage,
|
||||
self.victronconn.get_power_usage(),
|
||||
self.victronconn.get_soc() ,
|
||||
float(self.victronconn.get_battery_current() ),
|
||||
float(self.victronconn.get_battery_current() or 0),
|
||||
self.battery_total_net_usage,
|
||||
self.battery_total_net_delivery,
|
||||
self.tibber.getPrice() ))
|
||||
@@ -187,6 +220,7 @@ class chargeman_controller:
|
||||
|
||||
|
||||
|
||||
@_locked
|
||||
def apply_charge_mode(self):
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user