extended the state machines until SessionStop

This commit is contained in:
uhi22 2022-12-09 00:22:18 +01:00
parent 658e022e2e
commit 8e16179372
3 changed files with 171 additions and 7 deletions

View file

@ -135,6 +135,24 @@ class fsmEvse():
self.addToTrace("responding " + prettyHexMessage(msg)) self.addToTrace("responding " + prettyHexMessage(msg))
self.Tcp.transmit(msg) self.Tcp.transmit(msg)
self.enterState(stateWaitForFlexibleRequest) # todo: not clear, what is specified in DIN self.enterState(stateWaitForFlexibleRequest) # todo: not clear, what is specified in DIN
if (strConverterResult.find("CurrentDemandReq")>0):
# todo: check the request content, and fill response parameters
msg = addV2GTPHeader(exiEncode("EDi")) # EDi for Encode, Din, CurrentDemandRes
self.addToTrace("responding " + prettyHexMessage(msg))
self.Tcp.transmit(msg)
self.enterState(stateWaitForFlexibleRequest) # todo: not clear, what is specified in DIN
if (strConverterResult.find("WeldingDetectionReq")>0):
# todo: check the request content, and fill response parameters
msg = addV2GTPHeader(exiEncode("EDj")) # EDj for Encode, Din, WeldingDetectionRes
self.addToTrace("responding " + prettyHexMessage(msg))
self.Tcp.transmit(msg)
self.enterState(stateWaitForFlexibleRequest) # todo: not clear, what is specified in DIN
if (strConverterResult.find("SessionStopReq")>0):
# todo: check the request content, and fill response parameters
msg = addV2GTPHeader(exiEncode("EDk")) # EDk for Encode, Din, SessionStopRes
self.addToTrace("responding " + prettyHexMessage(msg))
self.Tcp.transmit(msg)
self.enterState(stateWaitForFlexibleRequest) # todo: not clear, what is specified in DIN

113
fsmPev.py
View file

@ -10,6 +10,8 @@ from helpers import prettyHexMessage
from exiConnector import * # for EXI data handling/converting from exiConnector import * # for EXI data handling/converting
import json import json
PARAM_U_DELTA_MAX_FOR_END_OF_PRECHARGE = 10 # volts between inlet and accu, to change from PreCharge to PowerDelivery
stateNotYetInitialized = 0 stateNotYetInitialized = 0
stateConnecting = 1 stateConnecting = 1
stateConnected = 2 stateConnected = 2
@ -22,6 +24,10 @@ stateWaitForChargeParameterDiscoveryResponse = 8
stateWaitForCableCheckResponse = 9 stateWaitForCableCheckResponse = 9
stateWaitForPreChargeResponse = 10 stateWaitForPreChargeResponse = 10
stateWaitForPowerDeliveryResponse = 11 stateWaitForPowerDeliveryResponse = 11
stateWaitForCurrentDemandResponse = 12
stateWaitForWeldingDetectionResponse = 13
stateWaitForSessionStopResponse = 14
stateChargingFinished = 15
stateSequenceTimeout = 99 stateSequenceTimeout = 99
@ -286,7 +292,17 @@ class fsmPev():
if (strConverterResult.find("PreChargeRes")>0): if (strConverterResult.find("PreChargeRes")>0):
# todo: check the request content, and fill response parameters # todo: check the request content, and fill response parameters
self.addToTrace("PreCharge aknowledge received.") self.addToTrace("PreCharge aknowledge received.")
self.addToTrace("As Demo, we stay in PreCharge forever.") if (abs(self.hardwareInterface.getInletVoltage()-self.hardwareInterface.getAccuVoltage()) < PARAM_U_DELTA_MAX_FOR_END_OF_PRECHARGE):
self.addToTrace("Difference between accu voltage and inlet voltage is small. Sending PowerDeliveryReq.")
self.hardwareInterface.setPowerRelayOn()
msg = addV2GTPHeader(exiEncode("EDH_"+self.sessionId+"_"+"1")) # EDH for Encode, Din, PowerDeliveryReq, ON
self.wasPowerDeliveryRequestedOn=True
self.addToTrace("responding " + prettyHexMessage(msg))
self.Tcp.transmit(msg)
self.enterState(stateWaitForPowerDeliveryResponse)
else:
self.addToTrace("Difference too big. Continuing PreCharge.")
#self.addToTrace("As Demo, we stay in PreCharge forever.")
msg = addV2GTPHeader(exiEncode("EDG_"+self.sessionId)) # EDG for Encode, Din, PreCharge msg = addV2GTPHeader(exiEncode("EDG_"+self.sessionId)) # EDG for Encode, Din, PreCharge
self.addToTrace("responding " + prettyHexMessage(msg)) self.addToTrace("responding " + prettyHexMessage(msg))
self.Tcp.transmit(msg) self.Tcp.transmit(msg)
@ -294,6 +310,93 @@ class fsmPev():
if (self.isTooLong()): if (self.isTooLong()):
self.enterState(stateSequenceTimeout) self.enterState(stateSequenceTimeout)
def stateFunctionWaitForPowerDeliveryResponse(self):
if (len(self.rxData)>0):
self.addToTrace("In state WaitForPowerDeliveryRes, received " + prettyHexMessage(self.rxData))
exidata = removeV2GTPHeader(self.rxData)
self.rxData = []
strConverterResult = exiDecode(exidata, "DD") # Decode DIN
self.addToTrace(strConverterResult)
if (strConverterResult.find("PowerDeliveryRes")>0):
if (self.wasPowerDeliveryRequestedOn):
self.addToTrace("Starting the charging loop with CurrentDemandReq")
msg = addV2GTPHeader(exiEncode("EDI_"+self.sessionId)) # EDI for Encode, Din, CurrentDemandReq
self.addToTrace("responding " + prettyHexMessage(msg))
self.Tcp.transmit(msg)
self.enterState(stateWaitForCurrentDemandResponse)
else:
# We requested "OFF". So we turn-off the Relay and continue with the Welding detection.
self.addToTrace("Turning off the relay and starting the WeldingDetection")
self.hardwareInterface.setPowerRelayOff()
msg = addV2GTPHeader(exiEncode("EDJ_"+self.sessionId)) # EDI for Encode, Din, WeldingDetectionReq
self.addToTrace("responding " + prettyHexMessage(msg))
self.Tcp.transmit(msg)
self.enterState(stateWaitForWeldingDetectionResponse)
if (self.isTooLong()):
self.enterState(stateSequenceTimeout)
def stateFunctionWaitForCurrentDemandResponse(self):
if (len(self.rxData)>0):
self.addToTrace("In state WaitForCurrentDemandRes, received " + prettyHexMessage(self.rxData))
exidata = removeV2GTPHeader(self.rxData)
self.rxData = []
strConverterResult = exiDecode(exidata, "DD") # Decode DIN
self.addToTrace(strConverterResult)
if (strConverterResult.find("CurrentDemandRes")>0):
# as long as the accu is not full and no stop-demand from the user, we continue charging
if (self.hardwareInterface.getIsAccuFull()):
self.addToTrace("Accu is full. Sending PowerDeliveryReq Stop.")
msg = addV2GTPHeader(exiEncode("EDH_"+self.sessionId+"_"+"0")) # EDH for Encode, Din, PowerDeliveryReq, OFF
self.wasPowerDeliveryRequestedOn=False
self.addToTrace("responding " + prettyHexMessage(msg))
self.Tcp.transmit(msg)
self.enterState(stateWaitForPowerDeliveryResponse)
else:
# continue charging loop
msg = addV2GTPHeader(exiEncode("EDI_"+self.sessionId)) # EDI for Encode, Din, CurrentDemandReq
self.addToTrace("responding " + prettyHexMessage(msg))
self.Tcp.transmit(msg)
self.enterState(stateWaitForCurrentDemandResponse)
if (self.isTooLong()):
self.enterState(stateSequenceTimeout)
def stateFunctionWaitForWeldingDetectionResponse(self):
if (len(self.rxData)>0):
self.addToTrace("In state WaitForWeldingDetectionResponse, received " + prettyHexMessage(self.rxData))
exidata = removeV2GTPHeader(self.rxData)
self.rxData = []
strConverterResult = exiDecode(exidata, "DD") # Decode DIN
self.addToTrace(strConverterResult)
if (strConverterResult.find("WeldingDetectionRes")>0):
self.addToTrace("Sending SessionStopReq")
msg = addV2GTPHeader(exiEncode("EDK_"+self.sessionId)) # EDI for Encode, Din, SessionStopReq
self.addToTrace("responding " + prettyHexMessage(msg))
self.Tcp.transmit(msg)
self.enterState(stateWaitForSessionStopResponse)
if (self.isTooLong()):
self.enterState(stateSequenceTimeout)
def stateFunctionWaitForSessionStopResponse(self):
if (len(self.rxData)>0):
self.addToTrace("In state WaitForSessionStopRes, received " + prettyHexMessage(self.rxData))
exidata = removeV2GTPHeader(self.rxData)
self.rxData = []
strConverterResult = exiDecode(exidata, "DD") # Decode DIN
self.addToTrace(strConverterResult)
if (strConverterResult.find("SessionStopRes")>0):
# req -508
# Todo: close the TCP connection here.
# Todo: Unlock the connector lock.
self.addToTrace("Charging is finished")
self.enterState(stateChargingFinished)
if (self.isTooLong()):
self.enterState(stateSequenceTimeout)
def stateFunctionChargingFinished(self):
# charging is finished. Nothing to do. Just stay here, until we get re-initialized after a new SLAC/SDP.
pass
def stateFunctionSequenceTimeout(self): def stateFunctionSequenceTimeout(self):
# Here we end, if we run into a timeout in the state machine. This is an error case, and # Here we end, if we run into a timeout in the state machine. This is an error case, and
# we should re-initalize and try again to get a communication. # we should re-initalize and try again to get a communication.
@ -314,13 +417,21 @@ class fsmPev():
stateWaitForChargeParameterDiscoveryResponse: stateFunctionWaitForChargeParameterDiscoveryResponse, stateWaitForChargeParameterDiscoveryResponse: stateFunctionWaitForChargeParameterDiscoveryResponse,
stateWaitForCableCheckResponse: stateFunctionWaitForCableCheckResponse, stateWaitForCableCheckResponse: stateFunctionWaitForCableCheckResponse,
stateWaitForPreChargeResponse: stateFunctionWaitForPreChargeResponse, stateWaitForPreChargeResponse: stateFunctionWaitForPreChargeResponse,
stateWaitForPowerDeliveryResponse: stateFunctionWaitForPowerDeliveryResponse,
stateWaitForCurrentDemandResponse: stateFunctionWaitForCurrentDemandResponse,
stateWaitForWeldingDetectionResponse: stateFunctionWaitForWeldingDetectionResponse,
stateWaitForSessionStopResponse: stateFunctionWaitForSessionStopResponse,
stateChargingFinished: stateFunctionChargingFinished,
stateSequenceTimeout: stateFunctionSequenceTimeout stateSequenceTimeout: stateFunctionSequenceTimeout
} }
def reInit(self): def reInit(self):
self.addToTrace("re-initializing fsmPev") self.addToTrace("re-initializing fsmPev")
self.Tcp.disconnect() self.Tcp.disconnect()
self.hardwareInterface.setStateB() self.hardwareInterface.setStateB()
self.hardwareInterface.setPowerRelayOff()
self.state = stateConnecting self.state = stateConnecting
self.cyclesInState = 0 self.cyclesInState = 0
self.rxData = [] self.rxData = []

View file

@ -36,16 +36,47 @@ class hardwareInterface():
def setStateB(self): def setStateB(self):
self.addToTrace("Setting CP line into state B.") self.addToTrace("Setting CP line into state B.")
self.outvalue = 0 self.outvalue &= ~1
def setStateC(self): def setStateC(self):
self.addToTrace("Setting CP line into state C.") self.addToTrace("Setting CP line into state C.")
self.outvalue = 1 self.outvalue |= 1
def setPowerRelayOn(self):
self.addToTrace("Switching PowerRelay ON.")
self.outvalue |= 2
def setPowerRelayOff(self):
self.addToTrace("Switching PowerRelay OFF.")
self.outvalue &= ~2
def getInletVoltage(self):
#todo: get real measured voltage from the inlet
self.inletVoltage = 230
return self.inletVoltage
def getAccuVoltage(self):
#todo: get real measured voltage from the accu
self.accuVoltage = 230
return self.accuVoltage
def getAccuMaxCurrent(self):
#todo: get max charging current from the BMS
self.accuMaxCurrent = 10
return self.accuMaxCurrent
def getIsAccuFull(self):
#todo: get "full" indication from the BMS
self.IsAccuFull = (self.simulatedSoc >= 98)
return self.IsAccuFull
def __init__(self, callbackAddToTrace=None): def __init__(self, callbackAddToTrace=None):
self.callbackAddToTrace = callbackAddToTrace self.callbackAddToTrace = callbackAddToTrace
self.loopcounter = 0 self.loopcounter = 0
self.outvalue = 0 self.outvalue = 0
self.simulatedSoc = 20.0 # percent
self.inletVoltage = 0.0 # volts
self.findSerialPort() self.findSerialPort()
def close(self): def close(self):
@ -53,6 +84,10 @@ class hardwareInterface():
self.ser.close() self.ser.close()
def mainfunction(self): def mainfunction(self):
if (self.simulatedSoc<100):
if ((self.outvalue & 2)!=0):
# while the relay is closes, simulate increasing SOC
self.simulatedSoc = self.simulatedSoc + 0.2
self.loopcounter+=1 self.loopcounter+=1
if (self.isInterfaceOk): if (self.isInterfaceOk):
if (self.loopcounter>15): if (self.loopcounter>15):