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

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

View file

@ -38,6 +38,9 @@ class fsmPev():
def addToTrace(self, s):
self.callbackAddToTrace("[PEV] " + s)
def publishStatus(self, s):
self.callbackShowStatus(s, "pevState")
def exiDecode(self, exidata, schema):
s = compactHexMessage(exidata)
self.exiLogFile.write(schema + " " + s +"\n") # write the EXI data to the exiLogFile
@ -110,6 +113,8 @@ class fsmPev():
else:
# Good case: We are connected. Change to the next state.
self.addToTrace("connected")
self.publishStatus("TCP connected")
self.isUserStopRequest = False
self.enterState(stateConnected)
return
@ -130,6 +135,7 @@ class fsmPev():
self.addToTrace(strConverterResult)
if (strConverterResult.find("supportedAppProtocolRes")>0):
# todo: check the request content, and fill response parameters
self.publishStatus("Schema negotiated")
self.addToTrace("Will send SessionSetupReq")
msg = addV2GTPHeader(self.exiEncode("EDA")) # EDA for Encode, Din, SessionSetupReq
self.addToTrace("responding " + prettyHexMessage(msg))
@ -151,6 +157,7 @@ class fsmPev():
y = json.loads(strConverterResult)
strSessionId = y["header.SessionID"]
self.addToTrace("The Evse decided for SessionId " + strSessionId)
self.publishStatus("Session established")
self.sessionId = strSessionId
except:
self.addToTrace("ERROR: Could not decode the sessionID")
@ -171,6 +178,7 @@ class fsmPev():
self.addToTrace(strConverterResult)
if (strConverterResult.find("ServiceDiscoveryRes")>0):
# todo: check the request content, and fill response parameters
self.publishStatus("ServiceDiscovery finished")
self.addToTrace("Will send ServicePaymentSelectionReq")
msg = addV2GTPHeader(self.exiEncode("EDC_"+self.sessionId)) # EDC for Encode, Din, ServicePaymentSelection
self.addToTrace("responding " + prettyHexMessage(msg))
@ -188,6 +196,7 @@ class fsmPev():
self.addToTrace(strConverterResult)
if (strConverterResult.find("ServicePaymentSelectionRes")>0):
# todo: check the request content, and fill response parameters
self.publishStatus("ServicePaymentSelection finished")
self.addToTrace("Will send ContractAuthenticationReq")
msg = addV2GTPHeader(self.exiEncode("EDL_"+self.sessionId)) # EDL for Encode, Din, ContractAuthenticationReq.
self.addToTrace("responding " + prettyHexMessage(msg))
@ -211,6 +220,7 @@ class fsmPev():
# needs to authorize by RFID card or app, or something like this.
# Or, the authorization is finished. This is shown by EVSEProcessing=Finished.
if (strConverterResult.find('"EVSEProcessing": "Finished"')>0):
self.publishStatus("Authorization finished")
self.addToTrace("It is Finished. Will send ChargeParameterDiscoveryReq")
self.sendChargeParameterDiscoveryReq()
self.numberOfChargeParameterDiscoveryReq = 1 # first message
@ -223,6 +233,7 @@ class fsmPev():
else:
# Try again.
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))
msg = addV2GTPHeader(self.exiEncode("EDL_"+self.sessionId)) # EDL for Encode, Din, ContractAuthenticationReq.
self.addToTrace("responding " + prettyHexMessage(msg))
@ -247,6 +258,7 @@ class fsmPev():
# (A) The charger needs more time to show the charge parameters.
# (B) The charger finished to tell the charge parameters.
if (strConverterResult.find('"EVSEProcessing": "Finished"')>0):
self.publishStatus("ChargeParameters discovered")
self.addToTrace("It is Finished. Will change to state C and send CableCheckReq.")
# pull the CP line to state C here:
self.hardwareInterface.setStateC()
@ -261,6 +273,7 @@ class fsmPev():
else:
# Try again.
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.sendChargeParameterDiscoveryReq()
# 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.
# 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")):
self.publishStatus("CableCheck done")
self.addToTrace("The EVSE says that the CableCheck is finished and ok.")
self.addToTrace("Will send PreChargeReq")
soc = self.hardwareInterface.getSoc()
@ -305,6 +319,7 @@ class fsmPev():
else:
# cable check not yet finished or finished with bad result -> try again
self.numberOfCableCheckReq += 1
self.publishStatus("CableCheck ongoing")
self.addToTrace("Will again send CableCheckReq")
self.sendCableCheckReq()
# stay in the same state
@ -332,7 +347,13 @@ class fsmPev():
self.addToTrace(s)
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()
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()
msg = addV2GTPHeader(self.exiEncode("EDH_"+self.sessionId+"_"+ str(soc) + "_" + "1")) # EDH for Encode, Din, PowerDeliveryReq, ON
self.wasPowerDeliveryRequestedOn=True
@ -340,6 +361,7 @@ class fsmPev():
self.Tcp.transmit(msg)
self.enterState(stateWaitForPowerDeliveryResponse)
else:
self.publishStatus("PreCharge ongoing")
self.addToTrace("Difference too big. Continuing PreCharge.")
soc = self.hardwareInterface.getSoc()
EVTargetVoltage = self.hardwareInterface.getAccuVoltage()
@ -359,13 +381,17 @@ class fsmPev():
self.addToTrace(strConverterResult)
if (strConverterResult.find("PowerDeliveryRes")>0):
if (self.wasPowerDeliveryRequestedOn):
self.publishStatus("PowerDelivery ON success")
self.addToTrace("Starting the charging loop with CurrentDemandReq")
self.sendCurrentDemandReq()
self.enterState(stateWaitForCurrentDemandResponse)
else:
# 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.hardwareInterface.setPowerRelayOff()
self.hardwareInterface.setRelay2Off()
self.isBulbOn = False
self.sendWeldingDetectionReq()
self.enterState(stateWaitForWeldingDetectionResponse)
if (self.isTooLong()):
@ -380,8 +406,13 @@ class fsmPev():
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.")
if (self.hardwareInterface.getIsAccuFull() or self.isUserStopRequest):
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()
msg = addV2GTPHeader(self.exiEncode("EDH_"+self.sessionId+"_"+ str(soc) + "_" + "0")) # EDH for Encode, Din, PowerDeliveryReq, OFF
self.wasPowerDeliveryRequestedOn=False
@ -390,9 +421,18 @@ class fsmPev():
self.enterState(stateWaitForPowerDeliveryResponse)
else:
# continue charging loop
self.publishStatus("Charging")
self.sendCurrentDemandReq()
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()):
self.enterState(stateSequenceTimeout)
@ -405,6 +445,7 @@ class fsmPev():
self.addToTrace(strConverterResult)
if (strConverterResult.find("WeldingDetectionRes")>0):
# todo: add real welding detection here, run in welding detection loop until finished.
self.publishStatus("WeldingDetection done")
self.addToTrace("Sending SessionStopReq")
msg = addV2GTPHeader(self.exiEncode("EDK_"+self.sessionId)) # EDI for Encode, Din, SessionStopReq
self.addToTrace("responding " + prettyHexMessage(msg))
@ -424,6 +465,7 @@ class fsmPev():
# req -508
# Todo: close the TCP connection here.
# Todo: Unlock the connector lock.
self.publishStatus("Session stopped normally")
self.hardwareInterface.setStateB()
self.addToTrace("Charging is finished")
self.enterState(stateChargingFinished)
@ -439,6 +481,7 @@ class fsmPev():
# we should re-initalize and try again to get a communication.
# Todo: Maybe we want even inform the pyPlcHomeplug to do a new SLAC.
# For the moment, we just re-establish the TCP connection.
self.publishStatus("ERROR Timeout")
self.reInit()
@ -462,6 +505,9 @@ class fsmPev():
stateSequenceTimeout: stateFunctionSequenceTimeout
}
def stopCharging(self):
# API function to stop the charging.
self.isUserStopRequest = True
def reInit(self):
@ -469,12 +515,16 @@ class fsmPev():
self.Tcp.disconnect()
self.hardwareInterface.setStateB()
self.hardwareInterface.setPowerRelayOff()
self.hardwareInterface.setRelay2Off()
self.isBulbOn = False
self.cyclesLightBulbDelay = 0
self.state = stateConnecting
self.cyclesInState = 0
self.rxData = []
def __init__(self, addressManager, callbackAddToTrace, hardwareInterface):
def __init__(self, addressManager, callbackAddToTrace, hardwareInterface, callbackShowStatus):
self.callbackAddToTrace = callbackAddToTrace
self.callbackShowStatus = callbackShowStatus
self.addToTrace("initializing fsmPev")
self.exiLogFile = open('PevExiLog.txt', 'a')
self.exiLogFile.write("init\n")
@ -486,6 +536,10 @@ class fsmPev():
self.cyclesInState = 0
self.DelayCycles = 0
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
def __del__(self):

View file

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

View file

@ -39,6 +39,15 @@ def cbShowStatus(s, selection=""):
if (selection == "uInlet"):
lblUInlet['text']= "UInlet " + s + "V"
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):
lblStatus['text']=s
root.update()
@ -64,20 +73,27 @@ if (myMode == C_EVSE_MODE):
print("starting in EVSE_MODE")
root = tk.Tk()
root.geometry("400x300")
lastKey = ''
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()
lblStatus = tk.Label(root, text="(Status)")
lblStatus.pack()
lblPevMac = tk.Label(root, text="(pev mac)")
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.config(font=('Helvetica bold', 26))
lblUInlet.pack()
lblMode = tk.Label(root, text="(mode)")
lblMode.pack()
nKeystrokes=0
# Bind the keyboard handler to all relevant elements:
root.bind('<Key>', storekeyname)
cbShowStatus("initialized")
@ -85,7 +101,6 @@ root.update()
worker=pyPlcWorker.pyPlcWorker(cbAddToTrace, cbShowStatus, myMode, isSimulationMode)
nMainloops=0
nKeystrokes=0
while lastKey!="x":
time.sleep(.03) # 'do some calculation'
nMainloops+=1

View file

@ -808,6 +808,7 @@ class pyPlcHomeplug():
self.enterState(STATE_READY_FOR_SLAC)
return
if (self.pevSequenceState==STATE_READY_FOR_SLAC):
self.showStatus("Starting SLAC", "pevState")
self.addToTrace("[PEVSLAC] Sending SLAC_PARAM.REQ...")
self.composeSlacParamReq()
self.transmit(self.mytransmitbuffer)
@ -881,6 +882,7 @@ class pyPlcHomeplug():
self.pevSequenceDelayCycles-=1
return
self.composeSlacMatchReq()
self.showStatus("SLAC match", "pevState")
self.addToTrace("[PEVSLAC] transmitting SLAC_MATCH.REQ...")
self.transmit(self.mytransmitbuffer)
self.enterState(STATE_WAITING_FOR_SLAC_MATCH_CNF)
@ -957,6 +959,7 @@ class pyPlcHomeplug():
self.enterState(STATE_WAITING_FOR_RESTART2)
return
# 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.")
# Next step is to discover the chargers communication controller (SECC) using discovery protocol (SDP).
self.pevSequenceDelayCycles=0
@ -967,6 +970,7 @@ class pyPlcHomeplug():
if (self.pevSequenceState==STATE_SDP): # SDP request transmission and waiting for SDP response.
if (len(self.addressManager.getSeccIp())>0):
# 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.")
self.isSDPDone = 1
self.callbackReadyForTcp(1)

View file

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