From a89d097948457b041d31b1ee1dfeb81239338ed7 Mon Sep 17 00:00:00 2001 From: johannes Date: Thu, 14 Nov 2024 19:54:19 +0100 Subject: [PATCH 1/2] Bodged in vehicle SoC --- fsmEvse.py | 4 ++-- hardwareInterface.py | 5 +++-- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/fsmEvse.py b/fsmEvse.py index 042ee6e..6038758 100644 --- a/fsmEvse.py +++ b/fsmEvse.py @@ -270,7 +270,7 @@ class fsmEvse(): strPresentVoltage = str(self.hardwareInterface.getInletVoltage()) # in case we control a real power supply: give the precharge target to it - self.hardwareInterface.setPowerSupplyVoltageAndCurrent(uTarget, 1) + self.hardwareInterface.setPowerSupplyVoltageAndCurrent(uTarget, 1, 0) self.callbackShowStatus(strPresentVoltage, "EVSEPresentVoltage") msg = addV2GTPHeader(exiEncode("E"+self.schemaSelection+"g_"+strPresentVoltage)) # EDg for Encode, Din, PreChargeResponse if (testsuite_faultinjection_is_triggered(TC_EVSE_Shutdown_during_PreCharge)): @@ -329,11 +329,11 @@ class fsmEvse(): strEVTargetCurrentMultiplier = jsondict["EVTargetCurrent.Multiplier"] iTarget = combineValueAndMultiplier(strEVTargetCurrentValue, strEVTargetCurrentMultiplier) self.addToTrace("EV wants EVTargetVoltage " + str(uTarget) + " and EVTargetCurrent " + str(iTarget)) - self.hardwareInterface.setPowerSupplyVoltageAndCurrent(uTarget, iTarget) current_soc = int(jsondict.get("DC_EVStatus.EVRESSSOC", -1)) full_soc = int(jsondict.get("FullSOC", -1)) energy_capacity = int(jsondict.get("EVEnergyCapacity.Value", -1)) energy_request = int(jsondict.get("EVEnergyRequest.Value", -1)) + self.hardwareInterface.setPowerSupplyVoltageAndCurrent(uTarget, iTarget, current_soc) self.publishSoCs(current_soc, full_soc, energy_capacity, energy_request, origin="CurrentDemandReq") diff --git a/hardwareInterface.py b/hardwareInterface.py index d8a296b..559d4b8 100644 --- a/hardwareInterface.py +++ b/hardwareInterface.py @@ -185,13 +185,14 @@ class hardwareInterface(): self.mqttclient.publish(getConfigValue("mqtt_topic") + "/charger_voltage", voltageNow) self.mqttclient.publish(getConfigValue("mqtt_topic") + "/charger_current", currentNow) - def setPowerSupplyVoltageAndCurrent(self, targetVoltage, targetCurrent): + def setPowerSupplyVoltageAndCurrent(self, targetVoltage, targetCurrent, soc): # if we are the charger, and have a real power supply which we want to control, we do it here self.homeplughandler.sendSpecialMessageToControlThePowerSupply(targetVoltage, targetCurrent) #here we can publish the voltage and current requests received from the PEV side if getConfigValue("charge_parameter_backend") == "mqtt": self.mqttclient.publish(getConfigValue("mqtt_topic") + "/pev_voltage", str(targetVoltage)) - self.mqttclient.publish(getConfigValue("mqtt_topic") + "/pev_current", str(targetVoltage)) + self.mqttclient.publish(getConfigValue("mqtt_topic") + "/pev_current", str(targetCurrent)) + self.mqttclient.publish(getConfigValue("mqtt_topic") + "/soc", str(soc)) def getInletVoltage(self): # uncomment this line, to take the simulated inlet voltage instead of the really measured From 2cfa5169b9c4a22071a846fc276e5656952bd459 Mon Sep 17 00:00:00 2001 From: johannes Date: Tue, 19 Nov 2024 21:57:37 +0100 Subject: [PATCH 2/2] Reshuffled topics, see also https://openinverter.org/wiki/PyPLC#pyPLC_MQTT_interface --- fsmEvse.py | 7 +++--- hardwareInterface.py | 55 ++++++++++++++++++++++++++++++++------------ 2 files changed, 44 insertions(+), 18 deletions(-) diff --git a/fsmEvse.py b/fsmEvse.py index 6038758..1a9d0af 100644 --- a/fsmEvse.py +++ b/fsmEvse.py @@ -30,6 +30,7 @@ class fsmEvse(): self.hardwareInterface.displayState(s) def publishSoCs(self, current_soc: int, full_soc: int = -1, energy_capacity: int = -1, energy_request: int = -1, evccid: str = "", origin: str = ""): + self.hardwareInterface.displaySoc(current_soc) if self.callbackSoCStatus is not None: self.callbackSoCStatus(current_soc, full_soc, energy_capacity, energy_request, self.evccid, origin) @@ -270,7 +271,7 @@ class fsmEvse(): strPresentVoltage = str(self.hardwareInterface.getInletVoltage()) # in case we control a real power supply: give the precharge target to it - self.hardwareInterface.setPowerSupplyVoltageAndCurrent(uTarget, 1, 0) + self.hardwareInterface.setPowerSupplyVoltageAndCurrent(uTarget, 1) self.callbackShowStatus(strPresentVoltage, "EVSEPresentVoltage") msg = addV2GTPHeader(exiEncode("E"+self.schemaSelection+"g_"+strPresentVoltage)) # EDg for Encode, Din, PreChargeResponse if (testsuite_faultinjection_is_triggered(TC_EVSE_Shutdown_during_PreCharge)): @@ -333,7 +334,7 @@ class fsmEvse(): full_soc = int(jsondict.get("FullSOC", -1)) energy_capacity = int(jsondict.get("EVEnergyCapacity.Value", -1)) energy_request = int(jsondict.get("EVEnergyRequest.Value", -1)) - self.hardwareInterface.setPowerSupplyVoltageAndCurrent(uTarget, iTarget, current_soc) + self.hardwareInterface.setPowerSupplyVoltageAndCurrent(uTarget, iTarget) self.publishSoCs(current_soc, full_soc, energy_capacity, energy_request, origin="CurrentDemandReq") @@ -346,7 +347,7 @@ class fsmEvse(): strPresentVoltage = str(self.hardwareInterface.getInletVoltage()) #str(self.simulatedPresentVoltage) self.callbackShowStatus(strPresentVoltage, "EVSEPresentVoltage") strEVSEPresentCurrent = str(self.hardwareInterface.getAccuMaxCurrent()) #"1" # Just as a dummy current - if (self.blChargeStopTrigger == 1): + if (self.blChargeStopTrigger == 1 or self.hardwareInterface.stopRequest()): # User pressed the STOP button on the charger. Send EVSE_Shutdown. self.addToTrace("User pressed the STOP button on the charger. Sending EVSE_Shutdown.") strEVSEStatus = "2" # 2=EVSE_Shutdown, means the user stopped the session on the charger. diff --git a/hardwareInterface.py b/hardwareInterface.py index 559d4b8..bba1dbe 100644 --- a/hardwareInterface.py +++ b/hardwareInterface.py @@ -7,6 +7,7 @@ # python -m serial.tools.list_ports import serial # the pyserial +from pyPlcModes import * from serial.tools.list_ports import comports from time import sleep, time from configmodule import getConfigValue, getConfigValueBool @@ -93,6 +94,10 @@ class hardwareInterface(): if (getConfigValue("digital_output_device")=="mqtt"): self.mqttclient.publish(getConfigValue("mqtt_topic") + "/fsm_state", state) + def displaySoc(self, soc): + if getConfigValue("charge_parameter_backend") == "mqtt": + self.mqttclient.publish(getConfigValue("mqtt_topic") + "/soc", str(soc)) + def setStateB(self): self.addToTrace("Setting CP line into state B.") if (getConfigValue("digital_output_device")=="beaglebone"): @@ -185,14 +190,13 @@ class hardwareInterface(): self.mqttclient.publish(getConfigValue("mqtt_topic") + "/charger_voltage", voltageNow) self.mqttclient.publish(getConfigValue("mqtt_topic") + "/charger_current", currentNow) - def setPowerSupplyVoltageAndCurrent(self, targetVoltage, targetCurrent, soc): + def setPowerSupplyVoltageAndCurrent(self, targetVoltage, targetCurrent): # if we are the charger, and have a real power supply which we want to control, we do it here self.homeplughandler.sendSpecialMessageToControlThePowerSupply(targetVoltage, targetCurrent) #here we can publish the voltage and current requests received from the PEV side if getConfigValue("charge_parameter_backend") == "mqtt": - self.mqttclient.publish(getConfigValue("mqtt_topic") + "/pev_voltage", str(targetVoltage)) - self.mqttclient.publish(getConfigValue("mqtt_topic") + "/pev_current", str(targetCurrent)) - self.mqttclient.publish(getConfigValue("mqtt_topic") + "/soc", str(soc)) + self.mqttclient.publish(getConfigValue("mqtt_topic") + "/target_voltage", str(targetVoltage)) + self.mqttclient.publish(getConfigValue("mqtt_topic") + "/target_current", str(targetCurrent)) def getInletVoltage(self): # uncomment this line, to take the simulated inlet voltage instead of the really measured @@ -247,6 +251,9 @@ class hardwareInterface(): self.callbackShowStatus(format(self.simulatedSoc,".1f"), "soc") return self.simulatedSoc + def stopRequest(self): + return not self.enabled + def isUserAuthenticated(self): # If the user needs to authorize, fill this function in a way that it returns False as long as # we shall wait for the users authorization, and returns True if the authentication was successfull. @@ -273,20 +280,22 @@ class hardwareInterface(): GPIO.setup(PinCp, GPIO.OUT) #output for CP if (getConfigValue("digital_output_device") == "mqtt"): - self.mqttclient = mqtt.Client() + self.mqttclient = mqtt.Client(client_id="pyplc") self.mqttclient.on_connect = self.mqtt_on_connect self.mqttclient.on_message = self.mqtt_on_message self.mqttclient.connect(getConfigValue("mqtt_broker"), 1883, 60) - def __init__(self, callbackAddToTrace=None, callbackShowStatus=None, homeplughandler=None): + def __init__(self, callbackAddToTrace=None, callbackShowStatus=None, homeplughandler=None, mode=C_EVSE_MODE): self.callbackAddToTrace = callbackAddToTrace self.callbackShowStatus = callbackShowStatus self.homeplughandler = homeplughandler + self.mode = mode self.loopcounter = 0 self.outvalue = 0 self.simulatedSoc = 20.0 # percent self.demoAuthenticationCounter = 0 + self.enabled = True #Charging enabled self.inletVoltage = 0.0 # volts self.accuVoltage = 0.0 @@ -528,25 +537,41 @@ class hardwareInterface(): # Subscribing in on_connect() means that if we lose the connection and # reconnect then subscriptions will be renewed. - client.subscribe(getConfigValue("mqtt_topic") + "/#") + if self.mode == C_EVSE_MODE: + client.subscribe(getConfigValue("mqtt_topic") + "/charger_max_voltage") #todo + client.subscribe(getConfigValue("mqtt_topic") + "/charger_max_current") #todo + client.subscribe(getConfigValue("mqtt_topic") + "/charger_voltage") + client.subscribe(getConfigValue("mqtt_topic") + "/charger_current") + client.subscribe(getConfigValue("mqtt_topic") + "/enabled") + elif self.mode == C_EVSE_MODE: + client.subscribe(getConfigValue("mqtt_topic") + "/battery_voltage") + client.subscribe(getConfigValue("mqtt_topic") + "/target_voltage") + client.subscribe(getConfigValue("mqtt_topic") + "/target_current") + client.subscribe(getConfigValue("mqtt_topic") + "/soc") + client.subscribe(getConfigValue("mqtt_topic") + "/inlet_voltage") def mqtt_on_message(self, client, userdata, msg): - if msg.topic == getConfigValue("mqtt_topic") + "/battery_voltage": + baseTopic = getConfigValue("mqtt_topic") + + if msg.topic == (f"{baseTopic}/battery_voltage"): self.accuVoltage = float(msg.payload) self.addToTrace("MQTT: Set battery voltage to %f V" % self.accuVoltage) - elif msg.topic == getConfigValue("mqtt_topic") + "/target_voltage": + elif msg.topic == (f"{baseTopic}/target_voltage"): self.accuMaxVoltage = float(msg.payload) self.addToTrace("MQTT: Set target voltage to %f V" % self.accuMaxVoltage) - elif msg.topic == getConfigValue("mqtt_topic") + "/target_current": + elif msg.topic == (f"{baseTopic}/target_current") or msg.topic == (f"{baseTopic}/charger_current"): self.accuMaxCurrent = float(msg.payload) - self.addToTrace("MQTT: Set current request to %f A" % self.accuMaxCurrent) - elif msg.topic == getConfigValue("mqtt_topic") + "/soc": + self.addToTrace("MQTT: Set current request to %s A" % self.accuMaxCurrent) + elif msg.topic == (f"{baseTopic}/soc"): self.simulatedSoc = float(msg.payload) self.soc_percent = self.simulatedSoc self.addToTrace("MQTT: Set SoC to %f %%" % self.simulatedSoc) - elif msg.topic == getConfigValue("mqtt_topic") + "/inlet_voltage": - self.inletVoltage = float(msg.payload) - self.addToTrace("MQTT: Set inlet voltage to %f V" % self.inletVoltage) + elif msg.topic == (f"{baseTopic}/inlet_voltage") or msg.topic == (f"{baseTopic}/charger_voltage"): + self.inletVoltage = float(msg.payload) #in EVSE mode this is present charger voltage + self.addToTrace("MQTT: Set present voltage to %f V" % self.inletVoltage) + elif msg.topic == (f"{baseTopic}/enabled"): + self.enabled = bool(int(msg.payload)) + self.addToTrace("MQTT: Setting enable flag to %d" % self.enabled) def myPrintfunction(s): print("myprint " + s)