feature: showing status in the GUI

This commit is contained in:
uhi22 2022-12-19 18:09:39 +01:00
parent 3da03c011e
commit 4db1f0d13f
6 changed files with 118 additions and 19 deletions

View file

@ -22,6 +22,9 @@ stateWaitForPowerDeliveryRequest = 8
class fsmEvse(): class fsmEvse():
def addToTrace(self, s): def addToTrace(self, s):
self.callbackAddToTrace("[EVSE] " + s) self.callbackAddToTrace("[EVSE] " + s)
def publishStatus(self, s):
self.callbackShowStatus(s, "evseState")
def enterState(self, n): def enterState(self, n):
self.addToTrace("from " + str(self.state) + " entering " + str(n)) self.addToTrace("from " + str(self.state) + " entering " + str(n))
@ -47,6 +50,7 @@ class fsmEvse():
msg = addV2GTPHeader(exiEncode("Eh")) msg = addV2GTPHeader(exiEncode("Eh"))
self.addToTrace("responding " + prettyHexMessage(msg)) self.addToTrace("responding " + prettyHexMessage(msg))
self.Tcp.transmit(msg) self.Tcp.transmit(msg)
self.publishStatus("Schema negotiated")
self.enterState(stateWaitForSessionSetupRequest) self.enterState(stateWaitForSessionSetupRequest)
def stateFunctionWaitForSessionSetupRequest(self): def stateFunctionWaitForSessionSetupRequest(self):
@ -60,7 +64,8 @@ class fsmEvse():
# todo: check the request content, and fill response parameters # todo: check the request content, and fill response parameters
msg = addV2GTPHeader(exiEncode("EDa")) # EDa for Encode, Din, SessionSetupResponse msg = addV2GTPHeader(exiEncode("EDa")) # EDa for Encode, Din, SessionSetupResponse
self.addToTrace("responding " + prettyHexMessage(msg)) self.addToTrace("responding " + prettyHexMessage(msg))
self.Tcp.transmit(msg) self.Tcp.transmit(msg)
self.publishStatus("Session established")
self.enterState(stateWaitForServiceDiscoveryRequest) self.enterState(stateWaitForServiceDiscoveryRequest)
if (self.isTooLong()): if (self.isTooLong()):
self.enterState(0) self.enterState(0)
@ -76,7 +81,8 @@ class fsmEvse():
# todo: check the request content, and fill response parameters # todo: check the request content, and fill response parameters
msg = addV2GTPHeader(exiEncode("EDb")) # EDb for Encode, Din, ServiceDiscoveryResponse msg = addV2GTPHeader(exiEncode("EDb")) # EDb for Encode, Din, ServiceDiscoveryResponse
self.addToTrace("responding " + prettyHexMessage(msg)) self.addToTrace("responding " + prettyHexMessage(msg))
self.Tcp.transmit(msg) self.Tcp.transmit(msg)
self.publishStatus("Services discovered")
self.enterState(stateWaitForServicePaymentSelectionRequest) self.enterState(stateWaitForServicePaymentSelectionRequest)
if (self.isTooLong()): if (self.isTooLong()):
self.enterState(0) self.enterState(0)
@ -92,7 +98,8 @@ class fsmEvse():
# todo: check the request content, and fill response parameters # todo: check the request content, and fill response parameters
msg = addV2GTPHeader(exiEncode("EDc")) # EDc for Encode, Din, ServicePaymentSelectionResponse msg = addV2GTPHeader(exiEncode("EDc")) # EDc for Encode, Din, ServicePaymentSelectionResponse
self.addToTrace("responding " + prettyHexMessage(msg)) self.addToTrace("responding " + prettyHexMessage(msg))
self.Tcp.transmit(msg) self.Tcp.transmit(msg)
self.publishStatus("ServicePayment selected")
self.enterState(stateWaitForFlexibleRequest) # todo: not clear, what is specified. The Ioniq sends PowerDeliveryReq as next. self.enterState(stateWaitForFlexibleRequest) # todo: not clear, what is specified. The Ioniq sends PowerDeliveryReq as next.
if (self.isTooLong()): if (self.isTooLong()):
self.enterState(0) self.enterState(0)
@ -108,18 +115,21 @@ class fsmEvse():
# todo: check the request content, and fill response parameters # todo: check the request content, and fill response parameters
msg = addV2GTPHeader(exiEncode("EDh")) # EDh for Encode, Din, PowerDeliveryResponse msg = addV2GTPHeader(exiEncode("EDh")) # EDh for Encode, Din, PowerDeliveryResponse
self.addToTrace("responding " + prettyHexMessage(msg)) self.addToTrace("responding " + prettyHexMessage(msg))
self.publishStatus("PowerDelivery")
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("ChargeParameterDiscoveryReq")>0): if (strConverterResult.find("ChargeParameterDiscoveryReq")>0):
# todo: check the request content, and fill response parameters # todo: check the request content, and fill response parameters
msg = addV2GTPHeader(exiEncode("EDe")) # EDe for Encode, Din, ChargeParameterDiscoveryResponse msg = addV2GTPHeader(exiEncode("EDe")) # EDe for Encode, Din, ChargeParameterDiscoveryResponse
self.addToTrace("responding " + prettyHexMessage(msg)) self.addToTrace("responding " + prettyHexMessage(msg))
self.publishStatus("ChargeParamDiscovery")
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("CableCheckReq")>0): if (strConverterResult.find("CableCheckReq")>0):
# todo: check the request content, and fill response parameters # todo: check the request content, and fill response parameters
msg = addV2GTPHeader(exiEncode("EDf")) # EDf for Encode, Din, CableCheckResponse msg = addV2GTPHeader(exiEncode("EDf")) # EDf for Encode, Din, CableCheckResponse
self.addToTrace("responding " + prettyHexMessage(msg)) self.addToTrace("responding " + prettyHexMessage(msg))
self.publishStatus("CableCheck")
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("PreChargeReq")>0): if (strConverterResult.find("PreChargeReq")>0):
@ -127,30 +137,35 @@ class fsmEvse():
strPresentVoltage = "345" strPresentVoltage = "345"
msg = addV2GTPHeader(exiEncode("EDg_"+strPresentVoltage)) # EDg for Encode, Din, PreChargeResponse msg = addV2GTPHeader(exiEncode("EDg_"+strPresentVoltage)) # EDg for Encode, Din, PreChargeResponse
self.addToTrace("responding " + prettyHexMessage(msg)) self.addToTrace("responding " + prettyHexMessage(msg))
self.publishStatus("PreCharging")
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("ContractAuthenticationReq")>0): if (strConverterResult.find("ContractAuthenticationReq")>0):
# todo: check the request content, and fill response parameters # todo: check the request content, and fill response parameters
msg = addV2GTPHeader(exiEncode("EDl")) # EDl for Encode, Din, ContractAuthenticationResponse msg = addV2GTPHeader(exiEncode("EDl")) # EDl for Encode, Din, ContractAuthenticationResponse
self.addToTrace("responding " + prettyHexMessage(msg)) self.addToTrace("responding " + prettyHexMessage(msg))
self.publishStatus("ContractAuthentication")
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): if (strConverterResult.find("CurrentDemandReq")>0):
# todo: check the request content, and fill response parameters # todo: check the request content, and fill response parameters
msg = addV2GTPHeader(exiEncode("EDi")) # EDi for Encode, Din, CurrentDemandRes msg = addV2GTPHeader(exiEncode("EDi")) # EDi for Encode, Din, CurrentDemandRes
self.addToTrace("responding " + prettyHexMessage(msg)) self.addToTrace("responding " + prettyHexMessage(msg))
self.publishStatus("CurrentDemand")
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("WeldingDetectionReq")>0): if (strConverterResult.find("WeldingDetectionReq")>0):
# todo: check the request content, and fill response parameters # todo: check the request content, and fill response parameters
msg = addV2GTPHeader(exiEncode("EDj")) # EDj for Encode, Din, WeldingDetectionRes msg = addV2GTPHeader(exiEncode("EDj")) # EDj for Encode, Din, WeldingDetectionRes
self.addToTrace("responding " + prettyHexMessage(msg)) self.addToTrace("responding " + prettyHexMessage(msg))
self.publishStatus("WeldingDetection")
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("SessionStopReq")>0): if (strConverterResult.find("SessionStopReq")>0):
# todo: check the request content, and fill response parameters # todo: check the request content, and fill response parameters
msg = addV2GTPHeader(exiEncode("EDk")) # EDk for Encode, Din, SessionStopRes msg = addV2GTPHeader(exiEncode("EDk")) # EDk for Encode, Din, SessionStopRes
self.addToTrace("responding " + prettyHexMessage(msg)) self.addToTrace("responding " + prettyHexMessage(msg))
self.publishStatus("SessionStop")
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
@ -199,8 +214,11 @@ class fsmEvse():
self.cyclesInState = 0 self.cyclesInState = 0
self.rxData = [] self.rxData = []
def __init__(self, callbackAddToTrace): def __init__(self, addressManager, callbackAddToTrace, hardwareInterface, callbackShowStatus):
self.callbackAddToTrace = callbackAddToTrace self.callbackAddToTrace = callbackAddToTrace
self.callbackShowStatus = callbackShowStatus
#todo self.addressManager = addressManager
#todo self.hardwareInterface = hardwareInterface
self.addToTrace("initializing fsmEvse") self.addToTrace("initializing fsmEvse")
self.faultInjectionDelayUntilSocketOpen_s = 0 self.faultInjectionDelayUntilSocketOpen_s = 0
if (self.faultInjectionDelayUntilSocketOpen_s>0): if (self.faultInjectionDelayUntilSocketOpen_s>0):

View file

@ -38,6 +38,9 @@ class fsmPev():
def addToTrace(self, s): def addToTrace(self, s):
self.callbackAddToTrace("[PEV] " + s) self.callbackAddToTrace("[PEV] " + s)
def publishStatus(self, s):
self.callbackShowStatus(s, "pevState")
def exiDecode(self, exidata, schema): def exiDecode(self, exidata, schema):
s = compactHexMessage(exidata) s = compactHexMessage(exidata)
self.exiLogFile.write(schema + " " + s +"\n") # write the EXI data to the exiLogFile self.exiLogFile.write(schema + " " + s +"\n") # write the EXI data to the exiLogFile
@ -110,6 +113,8 @@ class fsmPev():
else: else:
# Good case: We are connected. Change to the next state. # Good case: We are connected. Change to the next state.
self.addToTrace("connected") self.addToTrace("connected")
self.publishStatus("TCP connected")
self.isUserStopRequest = False
self.enterState(stateConnected) self.enterState(stateConnected)
return return
@ -130,6 +135,7 @@ class fsmPev():
self.addToTrace(strConverterResult) self.addToTrace(strConverterResult)
if (strConverterResult.find("supportedAppProtocolRes")>0): if (strConverterResult.find("supportedAppProtocolRes")>0):
# todo: check the request content, and fill response parameters # todo: check the request content, and fill response parameters
self.publishStatus("Schema negotiated")
self.addToTrace("Will send SessionSetupReq") self.addToTrace("Will send SessionSetupReq")
msg = addV2GTPHeader(self.exiEncode("EDA")) # EDA for Encode, Din, SessionSetupReq msg = addV2GTPHeader(self.exiEncode("EDA")) # EDA for Encode, Din, SessionSetupReq
self.addToTrace("responding " + prettyHexMessage(msg)) self.addToTrace("responding " + prettyHexMessage(msg))
@ -151,6 +157,7 @@ class fsmPev():
y = json.loads(strConverterResult) y = json.loads(strConverterResult)
strSessionId = y["header.SessionID"] strSessionId = y["header.SessionID"]
self.addToTrace("The Evse decided for SessionId " + strSessionId) self.addToTrace("The Evse decided for SessionId " + strSessionId)
self.publishStatus("Session established")
self.sessionId = strSessionId self.sessionId = strSessionId
except: except:
self.addToTrace("ERROR: Could not decode the sessionID") self.addToTrace("ERROR: Could not decode the sessionID")
@ -171,6 +178,7 @@ class fsmPev():
self.addToTrace(strConverterResult) self.addToTrace(strConverterResult)
if (strConverterResult.find("ServiceDiscoveryRes")>0): if (strConverterResult.find("ServiceDiscoveryRes")>0):
# todo: check the request content, and fill response parameters # todo: check the request content, and fill response parameters
self.publishStatus("ServiceDiscovery finished")
self.addToTrace("Will send ServicePaymentSelectionReq") self.addToTrace("Will send ServicePaymentSelectionReq")
msg = addV2GTPHeader(self.exiEncode("EDC_"+self.sessionId)) # EDC for Encode, Din, ServicePaymentSelection msg = addV2GTPHeader(self.exiEncode("EDC_"+self.sessionId)) # EDC for Encode, Din, ServicePaymentSelection
self.addToTrace("responding " + prettyHexMessage(msg)) self.addToTrace("responding " + prettyHexMessage(msg))
@ -188,6 +196,7 @@ class fsmPev():
self.addToTrace(strConverterResult) self.addToTrace(strConverterResult)
if (strConverterResult.find("ServicePaymentSelectionRes")>0): if (strConverterResult.find("ServicePaymentSelectionRes")>0):
# todo: check the request content, and fill response parameters # todo: check the request content, and fill response parameters
self.publishStatus("ServicePaymentSelection finished")
self.addToTrace("Will send ContractAuthenticationReq") self.addToTrace("Will send ContractAuthenticationReq")
msg = addV2GTPHeader(self.exiEncode("EDL_"+self.sessionId)) # EDL for Encode, Din, ContractAuthenticationReq. msg = addV2GTPHeader(self.exiEncode("EDL_"+self.sessionId)) # EDL for Encode, Din, ContractAuthenticationReq.
self.addToTrace("responding " + prettyHexMessage(msg)) self.addToTrace("responding " + prettyHexMessage(msg))
@ -210,7 +219,8 @@ class fsmPev():
# In normal case, we can have two results here: either the Authentication is needed (the user # In normal case, we can have two results here: either the Authentication is needed (the user
# needs to authorize by RFID card or app, or something like this. # needs to authorize by RFID card or app, or something like this.
# Or, the authorization is finished. This is shown by EVSEProcessing=Finished. # Or, the authorization is finished. This is shown by EVSEProcessing=Finished.
if (strConverterResult.find('"EVSEProcessing": "Finished"')>0): if (strConverterResult.find('"EVSEProcessing": "Finished"')>0):
self.publishStatus("Authorization finished")
self.addToTrace("It is Finished. Will send ChargeParameterDiscoveryReq") self.addToTrace("It is Finished. Will send ChargeParameterDiscoveryReq")
self.sendChargeParameterDiscoveryReq() self.sendChargeParameterDiscoveryReq()
self.numberOfChargeParameterDiscoveryReq = 1 # first message self.numberOfChargeParameterDiscoveryReq = 1 # first message
@ -223,6 +233,7 @@ class fsmPev():
else: else:
# Try again. # Try again.
self.numberOfContractAuthenticationReq += 1 # count the number of tries. self.numberOfContractAuthenticationReq += 1 # count the number of tries.
self.publishStatus("Waiting for Authorization")
self.addToTrace("Not (yet) finished. Will again send ContractAuthenticationReq #" + str(self.numberOfContractAuthenticationReq)) self.addToTrace("Not (yet) finished. Will again send ContractAuthenticationReq #" + str(self.numberOfContractAuthenticationReq))
msg = addV2GTPHeader(self.exiEncode("EDL_"+self.sessionId)) # EDL for Encode, Din, ContractAuthenticationReq. msg = addV2GTPHeader(self.exiEncode("EDL_"+self.sessionId)) # EDL for Encode, Din, ContractAuthenticationReq.
self.addToTrace("responding " + prettyHexMessage(msg)) self.addToTrace("responding " + prettyHexMessage(msg))
@ -246,7 +257,8 @@ class fsmPev():
# We can have two cases here: # We can have two cases here:
# (A) The charger needs more time to show the charge parameters. # (A) The charger needs more time to show the charge parameters.
# (B) The charger finished to tell the charge parameters. # (B) The charger finished to tell the charge parameters.
if (strConverterResult.find('"EVSEProcessing": "Finished"')>0): if (strConverterResult.find('"EVSEProcessing": "Finished"')>0):
self.publishStatus("ChargeParameters discovered")
self.addToTrace("It is Finished. Will change to state C and send CableCheckReq.") self.addToTrace("It is Finished. Will change to state C and send CableCheckReq.")
# pull the CP line to state C here: # pull the CP line to state C here:
self.hardwareInterface.setStateC() self.hardwareInterface.setStateC()
@ -261,6 +273,7 @@ class fsmPev():
else: else:
# Try again. # Try again.
self.numberOfChargeParameterDiscoveryReq += 1 # count the number of tries. self.numberOfChargeParameterDiscoveryReq += 1 # count the number of tries.
self.publishStatus("discovering ChargeParameters")
self.addToTrace("Not (yet) finished. Will again send ChargeParameterDiscoveryReq #" + str(self.numberOfChargeParameterDiscoveryReq)) self.addToTrace("Not (yet) finished. Will again send ChargeParameterDiscoveryReq #" + str(self.numberOfChargeParameterDiscoveryReq))
self.sendChargeParameterDiscoveryReq() self.sendChargeParameterDiscoveryReq()
# we stay in the same state # we stay in the same state
@ -290,6 +303,7 @@ class fsmPev():
# 1) The charger says "cable check is finished and cable ok", by setting ResponseCode=OK and EVSEProcessing=Finished. # 1) The charger says "cable check is finished and cable ok", by setting ResponseCode=OK and EVSEProcessing=Finished.
# 2) Else: The charger says "need more time or cable not ok". In this case, we just run into timeout and start from the beginning. # 2) Else: The charger says "need more time or cable not ok". In this case, we just run into timeout and start from the beginning.
if ((strEVSEProcessing=="Finished") and (strResponseCode=="OK")): if ((strEVSEProcessing=="Finished") and (strResponseCode=="OK")):
self.publishStatus("CableCheck done")
self.addToTrace("The EVSE says that the CableCheck is finished and ok.") self.addToTrace("The EVSE says that the CableCheck is finished and ok.")
self.addToTrace("Will send PreChargeReq") self.addToTrace("Will send PreChargeReq")
soc = self.hardwareInterface.getSoc() soc = self.hardwareInterface.getSoc()
@ -305,6 +319,7 @@ class fsmPev():
else: else:
# cable check not yet finished or finished with bad result -> try again # cable check not yet finished or finished with bad result -> try again
self.numberOfCableCheckReq += 1 self.numberOfCableCheckReq += 1
self.publishStatus("CableCheck ongoing")
self.addToTrace("Will again send CableCheckReq") self.addToTrace("Will again send CableCheckReq")
self.sendCableCheckReq() self.sendCableCheckReq()
# stay in the same state # stay in the same state
@ -332,7 +347,13 @@ class fsmPev():
self.addToTrace(s) self.addToTrace(s)
if (abs(self.hardwareInterface.getInletVoltage()-self.hardwareInterface.getAccuVoltage()) < PARAM_U_DELTA_MAX_FOR_END_OF_PRECHARGE): 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.addToTrace("Difference between accu voltage and inlet voltage is small. Sending PowerDeliveryReq.")
self.hardwareInterface.setPowerRelayOn() self.publishStatus("PreCharge done")
if (self.isLightBulbDemo):
# For light-bulb-demo, nothing to do here.
self.addToTrace("This is a light bulb demo. Do not turn-on the relay at end of precharge.")
else:
# In real-world-case, turn the power relay on.
self.hardwareInterface.setPowerRelayOn()
soc = self.hardwareInterface.getSoc() soc = self.hardwareInterface.getSoc()
msg = addV2GTPHeader(self.exiEncode("EDH_"+self.sessionId+"_"+ str(soc) + "_" + "1")) # EDH for Encode, Din, PowerDeliveryReq, ON msg = addV2GTPHeader(self.exiEncode("EDH_"+self.sessionId+"_"+ str(soc) + "_" + "1")) # EDH for Encode, Din, PowerDeliveryReq, ON
self.wasPowerDeliveryRequestedOn=True self.wasPowerDeliveryRequestedOn=True
@ -340,6 +361,7 @@ class fsmPev():
self.Tcp.transmit(msg) self.Tcp.transmit(msg)
self.enterState(stateWaitForPowerDeliveryResponse) self.enterState(stateWaitForPowerDeliveryResponse)
else: else:
self.publishStatus("PreCharge ongoing")
self.addToTrace("Difference too big. Continuing PreCharge.") self.addToTrace("Difference too big. Continuing PreCharge.")
soc = self.hardwareInterface.getSoc() soc = self.hardwareInterface.getSoc()
EVTargetVoltage = self.hardwareInterface.getAccuVoltage() EVTargetVoltage = self.hardwareInterface.getAccuVoltage()
@ -359,13 +381,17 @@ class fsmPev():
self.addToTrace(strConverterResult) self.addToTrace(strConverterResult)
if (strConverterResult.find("PowerDeliveryRes")>0): if (strConverterResult.find("PowerDeliveryRes")>0):
if (self.wasPowerDeliveryRequestedOn): if (self.wasPowerDeliveryRequestedOn):
self.publishStatus("PowerDelivery ON success")
self.addToTrace("Starting the charging loop with CurrentDemandReq") self.addToTrace("Starting the charging loop with CurrentDemandReq")
self.sendCurrentDemandReq() self.sendCurrentDemandReq()
self.enterState(stateWaitForCurrentDemandResponse) self.enterState(stateWaitForCurrentDemandResponse)
else: else:
# We requested "OFF". So we turn-off the Relay and continue with the Welding detection. # We requested "OFF". So we turn-off the Relay and continue with the Welding detection.
self.publishStatus("PowerDelivery OFF success")
self.addToTrace("Turning off the relay and starting the WeldingDetection") self.addToTrace("Turning off the relay and starting the WeldingDetection")
self.hardwareInterface.setPowerRelayOff() self.hardwareInterface.setPowerRelayOff()
self.hardwareInterface.setRelay2Off()
self.isBulbOn = False
self.sendWeldingDetectionReq() self.sendWeldingDetectionReq()
self.enterState(stateWaitForWeldingDetectionResponse) self.enterState(stateWaitForWeldingDetectionResponse)
if (self.isTooLong()): if (self.isTooLong()):
@ -380,8 +406,13 @@ class fsmPev():
self.addToTrace(strConverterResult) self.addToTrace(strConverterResult)
if (strConverterResult.find("CurrentDemandRes")>0): if (strConverterResult.find("CurrentDemandRes")>0):
# as long as the accu is not full and no stop-demand from the user, we continue charging # as long as the accu is not full and no stop-demand from the user, we continue charging
if (self.hardwareInterface.getIsAccuFull()): if (self.hardwareInterface.getIsAccuFull() or self.isUserStopRequest):
self.addToTrace("Accu is full. Sending PowerDeliveryReq Stop.") if (self.hardwareInterface.getIsAccuFull()):
self.publishStatus("Accu full")
self.addToTrace("Accu is full. Sending PowerDeliveryReq Stop.")
else:
self.publishStatus("User requested stop")
self.addToTrace("User requested stop. Sending PowerDeliveryReq Stop.")
soc = self.hardwareInterface.getSoc() soc = self.hardwareInterface.getSoc()
msg = addV2GTPHeader(self.exiEncode("EDH_"+self.sessionId+"_"+ str(soc) + "_" + "0")) # EDH for Encode, Din, PowerDeliveryReq, OFF msg = addV2GTPHeader(self.exiEncode("EDH_"+self.sessionId+"_"+ str(soc) + "_" + "0")) # EDH for Encode, Din, PowerDeliveryReq, OFF
self.wasPowerDeliveryRequestedOn=False self.wasPowerDeliveryRequestedOn=False
@ -390,9 +421,18 @@ class fsmPev():
self.enterState(stateWaitForPowerDeliveryResponse) self.enterState(stateWaitForPowerDeliveryResponse)
else: else:
# continue charging loop # continue charging loop
self.publishStatus("Charging")
self.sendCurrentDemandReq() self.sendCurrentDemandReq()
self.enterState(stateWaitForCurrentDemandResponse) self.enterState(stateWaitForCurrentDemandResponse)
if (self.isLightBulbDemo):
if (self.cyclesLightBulbDelay<=33*5):
self.cyclesLightBulbDelay+=1
else:
if (not self.isBulbOn):
self.addToTrace("This is a light bulb demo. Turning-on the bulb when 5s in the main charging loop.")
self.hardwareInterface.setPowerRelayOn()
self.hardwareInterface.setRelay2On()
self.isBulbOn = True
if (self.isTooLong()): if (self.isTooLong()):
self.enterState(stateSequenceTimeout) self.enterState(stateSequenceTimeout)
@ -405,6 +445,7 @@ class fsmPev():
self.addToTrace(strConverterResult) self.addToTrace(strConverterResult)
if (strConverterResult.find("WeldingDetectionRes")>0): if (strConverterResult.find("WeldingDetectionRes")>0):
# todo: add real welding detection here, run in welding detection loop until finished. # todo: add real welding detection here, run in welding detection loop until finished.
self.publishStatus("WeldingDetection done")
self.addToTrace("Sending SessionStopReq") self.addToTrace("Sending SessionStopReq")
msg = addV2GTPHeader(self.exiEncode("EDK_"+self.sessionId)) # EDI for Encode, Din, SessionStopReq msg = addV2GTPHeader(self.exiEncode("EDK_"+self.sessionId)) # EDI for Encode, Din, SessionStopReq
self.addToTrace("responding " + prettyHexMessage(msg)) self.addToTrace("responding " + prettyHexMessage(msg))
@ -424,6 +465,7 @@ class fsmPev():
# req -508 # req -508
# Todo: close the TCP connection here. # Todo: close the TCP connection here.
# Todo: Unlock the connector lock. # Todo: Unlock the connector lock.
self.publishStatus("Session stopped normally")
self.hardwareInterface.setStateB() self.hardwareInterface.setStateB()
self.addToTrace("Charging is finished") self.addToTrace("Charging is finished")
self.enterState(stateChargingFinished) self.enterState(stateChargingFinished)
@ -439,6 +481,7 @@ class fsmPev():
# we should re-initalize and try again to get a communication. # we should re-initalize and try again to get a communication.
# Todo: Maybe we want even inform the pyPlcHomeplug to do a new SLAC. # Todo: Maybe we want even inform the pyPlcHomeplug to do a new SLAC.
# For the moment, we just re-establish the TCP connection. # For the moment, we just re-establish the TCP connection.
self.publishStatus("ERROR Timeout")
self.reInit() self.reInit()
@ -462,19 +505,26 @@ class fsmPev():
stateSequenceTimeout: stateFunctionSequenceTimeout stateSequenceTimeout: stateFunctionSequenceTimeout
} }
def stopCharging(self):
# API function to stop the charging.
self.isUserStopRequest = True
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.hardwareInterface.setPowerRelayOff()
self.hardwareInterface.setRelay2Off()
self.isBulbOn = False
self.cyclesLightBulbDelay = 0
self.state = stateConnecting self.state = stateConnecting
self.cyclesInState = 0 self.cyclesInState = 0
self.rxData = [] self.rxData = []
def __init__(self, addressManager, callbackAddToTrace, hardwareInterface): def __init__(self, addressManager, callbackAddToTrace, hardwareInterface, callbackShowStatus):
self.callbackAddToTrace = callbackAddToTrace self.callbackAddToTrace = callbackAddToTrace
self.callbackShowStatus = callbackShowStatus
self.addToTrace("initializing fsmPev") self.addToTrace("initializing fsmPev")
self.exiLogFile = open('PevExiLog.txt', 'a') self.exiLogFile = open('PevExiLog.txt', 'a')
self.exiLogFile.write("init\n") self.exiLogFile.write("init\n")
@ -486,6 +536,10 @@ class fsmPev():
self.cyclesInState = 0 self.cyclesInState = 0
self.DelayCycles = 0 self.DelayCycles = 0
self.rxData = [] self.rxData = []
self.isLightBulbDemo = True
self.isBulbOn = False
self.cyclesLightBulbDelay = 0
self.isUserStopRequest = False
# we do NOT call the reInit, because we want to wait with the connection until external trigger comes # we do NOT call the reInit, because we want to wait with the connection until external trigger comes
def __del__(self): def __del__(self):

View file

@ -51,11 +51,11 @@ class hardwareInterface():
self.outvalue &= ~2 self.outvalue &= ~2
def setRelay2On(self): def setRelay2On(self):
self.addToTrace("Switching PowerRelay ON.") self.addToTrace("Switching Relay2 ON.")
self.outvalue |= 4 self.outvalue |= 4
def setRelay2Off(self): def setRelay2Off(self):
self.addToTrace("Switching PowerRelay OFF.") self.addToTrace("Switching Relay2 OFF.")
self.outvalue &= ~4 self.outvalue &= ~4
def getInletVoltage(self): def getInletVoltage(self):
@ -85,6 +85,7 @@ class hardwareInterface():
def getSoc(self): def getSoc(self):
#todo: get SOC from the BMS #todo: get SOC from the BMS
self.callbackShowStatus(format(self.simulatedSoc,".1f"), "soc")
return self.simulatedSoc return self.simulatedSoc
@ -131,6 +132,8 @@ class hardwareInterface():
if ((self.outvalue & 2)!=0): if ((self.outvalue & 2)!=0):
# while the relay is closed, simulate increasing SOC # while the relay is closed, simulate increasing SOC
self.simulatedSoc = self.simulatedSoc + 0.05 self.simulatedSoc = self.simulatedSoc + 0.05
self.loopcounter+=1 self.loopcounter+=1
if (self.isInterfaceOk): if (self.isInterfaceOk):
if (self.loopcounter>15): if (self.loopcounter>15):

View file

@ -39,6 +39,15 @@ def cbShowStatus(s, selection=""):
if (selection == "uInlet"): if (selection == "uInlet"):
lblUInlet['text']= "UInlet " + s + "V" lblUInlet['text']= "UInlet " + s + "V"
s="" s=""
if (selection == "pevState"):
lblState['text']= s
s=""
if (selection == "evseState"):
lblState['text']= s
s=""
if (selection == "soc"):
lblSoc['text']= "SOC " + s + "%"
s=""
if (len(s)>0): if (len(s)>0):
lblStatus['text']=s lblStatus['text']=s
root.update() root.update()
@ -64,20 +73,27 @@ if (myMode == C_EVSE_MODE):
print("starting in EVSE_MODE") print("starting in EVSE_MODE")
root = tk.Tk() root = tk.Tk()
root.geometry("400x300")
lastKey = '' lastKey = ''
lblHelp = tk.Label(root, justify= "left") lblHelp = tk.Label(root, justify= "left")
lblHelp['text']="x=exit \nS=GET_SW \nP=PEV mode \nE=EVSE mode \nL=Listen mode \ns=SET_KEY \nG=GET_KEY (try twice) \nt=SET_KEY modified" lblHelp['text']="x=exit \nS=GET_SW \nP=PEV mode \nE=EVSE mode \nL=Listen mode \ns=SET_KEY \nG=GET_KEY (try twice) \nt=SET_KEY modified \n space=stop charging"
lblHelp.pack() lblHelp.pack()
lblStatus = tk.Label(root, text="(Status)") lblStatus = tk.Label(root, text="(Status)")
lblStatus.pack() lblStatus.pack()
lblPevMac = tk.Label(root, text="(pev mac)") lblPevMac = tk.Label(root, text="(pev mac)")
lblPevMac.pack() lblPevMac.pack()
lblState = tk.Label(root, text="(state)")
lblState.config(font=('Helvetica bold', 20))
lblState.pack()
lblSoc = tk.Label(root, text="(soc)")
lblSoc.pack()
lblUInlet = tk.Label(root, text="(U Inlet)") lblUInlet = tk.Label(root, text="(U Inlet)")
lblUInlet.config(font=('Helvetica bold', 26)) lblUInlet.config(font=('Helvetica bold', 26))
lblUInlet.pack() lblUInlet.pack()
lblMode = tk.Label(root, text="(mode)") lblMode = tk.Label(root, text="(mode)")
lblMode.pack() lblMode.pack()
nKeystrokes=0
# Bind the keyboard handler to all relevant elements: # Bind the keyboard handler to all relevant elements:
root.bind('<Key>', storekeyname) root.bind('<Key>', storekeyname)
cbShowStatus("initialized") cbShowStatus("initialized")
@ -85,7 +101,6 @@ root.update()
worker=pyPlcWorker.pyPlcWorker(cbAddToTrace, cbShowStatus, myMode, isSimulationMode) worker=pyPlcWorker.pyPlcWorker(cbAddToTrace, cbShowStatus, myMode, isSimulationMode)
nMainloops=0 nMainloops=0
nKeystrokes=0
while lastKey!="x": while lastKey!="x":
time.sleep(.03) # 'do some calculation' time.sleep(.03) # 'do some calculation'
nMainloops+=1 nMainloops+=1

View file

@ -808,6 +808,7 @@ class pyPlcHomeplug():
self.enterState(STATE_READY_FOR_SLAC) self.enterState(STATE_READY_FOR_SLAC)
return return
if (self.pevSequenceState==STATE_READY_FOR_SLAC): if (self.pevSequenceState==STATE_READY_FOR_SLAC):
self.showStatus("Starting SLAC", "pevState")
self.addToTrace("[PEVSLAC] Sending SLAC_PARAM.REQ...") self.addToTrace("[PEVSLAC] Sending SLAC_PARAM.REQ...")
self.composeSlacParamReq() self.composeSlacParamReq()
self.transmit(self.mytransmitbuffer) self.transmit(self.mytransmitbuffer)
@ -881,6 +882,7 @@ class pyPlcHomeplug():
self.pevSequenceDelayCycles-=1 self.pevSequenceDelayCycles-=1
return return
self.composeSlacMatchReq() self.composeSlacMatchReq()
self.showStatus("SLAC match", "pevState")
self.addToTrace("[PEVSLAC] transmitting SLAC_MATCH.REQ...") self.addToTrace("[PEVSLAC] transmitting SLAC_MATCH.REQ...")
self.transmit(self.mytransmitbuffer) self.transmit(self.mytransmitbuffer)
self.enterState(STATE_WAITING_FOR_SLAC_MATCH_CNF) self.enterState(STATE_WAITING_FOR_SLAC_MATCH_CNF)
@ -957,6 +959,7 @@ class pyPlcHomeplug():
self.enterState(STATE_WAITING_FOR_RESTART2) self.enterState(STATE_WAITING_FOR_RESTART2)
return return
# SDP was not done yet. Now we start it. # SDP was not done yet. Now we start it.
self.showStatus("SDP ongoing", "pevState")
self.addToTrace("[PEVSLAC] SDP was not done yet. Now we start it.") self.addToTrace("[PEVSLAC] SDP was not done yet. Now we start it.")
# Next step is to discover the chargers communication controller (SECC) using discovery protocol (SDP). # Next step is to discover the chargers communication controller (SECC) using discovery protocol (SDP).
self.pevSequenceDelayCycles=0 self.pevSequenceDelayCycles=0
@ -967,6 +970,7 @@ class pyPlcHomeplug():
if (self.pevSequenceState==STATE_SDP): # SDP request transmission and waiting for SDP response. if (self.pevSequenceState==STATE_SDP): # SDP request transmission and waiting for SDP response.
if (len(self.addressManager.getSeccIp())>0): if (len(self.addressManager.getSeccIp())>0):
# we received an SDP response, and can start the high-level communication # we received an SDP response, and can start the high-level communication
self.showStatus("SDP finished", "pevState")
print("[PEVSLAC] Now we know the chargers IP.") print("[PEVSLAC] Now we know the chargers IP.")
self.isSDPDone = 1 self.isSDPDone = 1
self.callbackReadyForTcp(1) self.callbackReadyForTcp(1)

View file

@ -39,9 +39,9 @@ class pyPlcWorker():
strLabel = "(unknown version. 'git describe --tags' failed.)" strLabel = "(unknown version. 'git describe --tags' failed.)"
self.workerAddToTrace("[pyPlcWorker] Software version " + strLabel) self.workerAddToTrace("[pyPlcWorker] Software version " + strLabel)
if (self.mode == C_EVSE_MODE): if (self.mode == C_EVSE_MODE):
self.evse = fsmEvse.fsmEvse(self.workerAddToTrace) self.evse = fsmEvse.fsmEvse(self.addressManager, self.workerAddToTrace, self.hardwareInterface, self.callbackShowStatus)
if (self.mode == C_PEV_MODE): if (self.mode == C_PEV_MODE):
self.pev = fsmPev.fsmPev(self.addressManager, self.workerAddToTrace, self.hardwareInterface) self.pev = fsmPev.fsmPev(self.addressManager, self.workerAddToTrace, self.hardwareInterface, self.callbackShowStatus)
def __del__(self): def __del__(self):
if (self.mode == C_PEV_MODE): if (self.mode == C_PEV_MODE):
print("worker: deleting pev") print("worker: deleting pev")
@ -84,6 +84,7 @@ class pyPlcWorker():
def handleUserAction(self, strAction): def handleUserAction(self, strAction):
self.strUserAction = strAction self.strUserAction = strAction
print("user action " + strAction)
if (strAction == "P"): if (strAction == "P"):
print("switching to PEV mode") print("switching to PEV mode")
self.mode = C_PEV_MODE self.mode = C_PEV_MODE
@ -93,7 +94,7 @@ class pyPlcWorker():
self.hp.enterPevMode() self.hp.enterPevMode()
if (not hasattr(self, 'pev')): if (not hasattr(self, 'pev')):
print("creating pev") print("creating pev")
self.pev = fsmPev.fsmPev(self.addressManager, self.workerAddToTrace, self.hardwareInterface) self.pev = fsmPev.fsmPev(self.addressManager, self.workerAddToTrace, self.hardwareInterface, self.callbackShowStatus)
self.pev.reInit() self.pev.reInit()
if (strAction == "E"): if (strAction == "E"):
print("switching to EVSE mode") print("switching to EVSE mode")
@ -116,6 +117,10 @@ class pyPlcWorker():
if (hasattr(self, 'pev')): if (hasattr(self, 'pev')):
print("deleting pev") print("deleting pev")
del self.pev del self.pev
if (strAction == "space"):
print("stopping the charge process")
if (hasattr(self, 'pev')):
self.pev.stopCharging()
# self.addToTrace("UserAction " + strAction) # self.addToTrace("UserAction " + strAction)
self.hp.sendTestFrame(strAction) self.hp.sendTestFrame(strAction)