mirror of
https://github.com/uhi22/pyPLC.git
synced 2024-11-20 01:13:58 +00:00
extended the state machines until SessionStop
This commit is contained in:
parent
658e022e2e
commit
8e16179372
3 changed files with 171 additions and 7 deletions
18
fsmEvse.py
18
fsmEvse.py
|
@ -135,6 +135,24 @@ class fsmEvse():
|
|||
self.addToTrace("responding " + prettyHexMessage(msg))
|
||||
self.Tcp.transmit(msg)
|
||||
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
113
fsmPev.py
|
@ -10,6 +10,8 @@ from helpers import prettyHexMessage
|
|||
from exiConnector import * # for EXI data handling/converting
|
||||
import json
|
||||
|
||||
PARAM_U_DELTA_MAX_FOR_END_OF_PRECHARGE = 10 # volts between inlet and accu, to change from PreCharge to PowerDelivery
|
||||
|
||||
stateNotYetInitialized = 0
|
||||
stateConnecting = 1
|
||||
stateConnected = 2
|
||||
|
@ -22,6 +24,10 @@ stateWaitForChargeParameterDiscoveryResponse = 8
|
|||
stateWaitForCableCheckResponse = 9
|
||||
stateWaitForPreChargeResponse = 10
|
||||
stateWaitForPowerDeliveryResponse = 11
|
||||
stateWaitForCurrentDemandResponse = 12
|
||||
stateWaitForWeldingDetectionResponse = 13
|
||||
stateWaitForSessionStopResponse = 14
|
||||
stateChargingFinished = 15
|
||||
stateSequenceTimeout = 99
|
||||
|
||||
|
||||
|
@ -286,7 +292,17 @@ class fsmPev():
|
|||
if (strConverterResult.find("PreChargeRes")>0):
|
||||
# todo: check the request content, and fill response parameters
|
||||
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
|
||||
self.addToTrace("responding " + prettyHexMessage(msg))
|
||||
self.Tcp.transmit(msg)
|
||||
|
@ -294,6 +310,93 @@ class fsmPev():
|
|||
if (self.isTooLong()):
|
||||
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):
|
||||
# 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.
|
||||
|
@ -314,13 +417,21 @@ class fsmPev():
|
|||
stateWaitForChargeParameterDiscoveryResponse: stateFunctionWaitForChargeParameterDiscoveryResponse,
|
||||
stateWaitForCableCheckResponse: stateFunctionWaitForCableCheckResponse,
|
||||
stateWaitForPreChargeResponse: stateFunctionWaitForPreChargeResponse,
|
||||
stateWaitForPowerDeliveryResponse: stateFunctionWaitForPowerDeliveryResponse,
|
||||
stateWaitForCurrentDemandResponse: stateFunctionWaitForCurrentDemandResponse,
|
||||
stateWaitForWeldingDetectionResponse: stateFunctionWaitForWeldingDetectionResponse,
|
||||
stateWaitForSessionStopResponse: stateFunctionWaitForSessionStopResponse,
|
||||
stateChargingFinished: stateFunctionChargingFinished,
|
||||
stateSequenceTimeout: stateFunctionSequenceTimeout
|
||||
}
|
||||
|
||||
|
||||
|
||||
def reInit(self):
|
||||
self.addToTrace("re-initializing fsmPev")
|
||||
self.Tcp.disconnect()
|
||||
self.hardwareInterface.setStateB()
|
||||
self.hardwareInterface.setPowerRelayOff()
|
||||
self.state = stateConnecting
|
||||
self.cyclesInState = 0
|
||||
self.rxData = []
|
||||
|
|
|
@ -36,16 +36,47 @@ class hardwareInterface():
|
|||
|
||||
def setStateB(self):
|
||||
self.addToTrace("Setting CP line into state B.")
|
||||
self.outvalue = 0
|
||||
self.outvalue &= ~1
|
||||
|
||||
def setStateC(self):
|
||||
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):
|
||||
self.callbackAddToTrace = callbackAddToTrace
|
||||
self.loopcounter = 0
|
||||
self.outvalue = 0
|
||||
self.simulatedSoc = 20.0 # percent
|
||||
self.inletVoltage = 0.0 # volts
|
||||
self.findSerialPort()
|
||||
|
||||
def close(self):
|
||||
|
@ -53,6 +84,10 @@ class hardwareInterface():
|
|||
self.ser.close()
|
||||
|
||||
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
|
||||
if (self.isInterfaceOk):
|
||||
if (self.loopcounter>15):
|
||||
|
|
Loading…
Reference in a new issue