mirror of
https://github.com/uhi22/pyPLC.git
synced 2024-11-20 01:13:58 +00:00
logging to PevExiLog and interpretation afterwards
This commit is contained in:
parent
8e16179372
commit
82f347c788
8 changed files with 92 additions and 39 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -1,3 +1,4 @@
|
||||||
/__pycache__/
|
/__pycache__/
|
||||||
/doc/*.jar
|
/doc/*.jar
|
||||||
*.bat
|
*.bat
|
||||||
|
PevExiLog*.txt
|
||||||
|
|
|
@ -230,7 +230,7 @@ def testDecoder(strHex, pre="DH", comment=""):
|
||||||
print("---***!!!FAIL!!!***---")
|
print("---***!!!FAIL!!!***---")
|
||||||
nFail+=1
|
nFail+=1
|
||||||
|
|
||||||
def testReadExiFromFile():
|
def testReadExiFromSnifferFile():
|
||||||
file1 = open('results\\tmp.txt', 'r')
|
file1 = open('results\\tmp.txt', 'r')
|
||||||
Lines = file1.readlines()
|
Lines = file1.readlines()
|
||||||
for myLine in Lines:
|
for myLine in Lines:
|
||||||
|
@ -242,6 +242,24 @@ def testReadExiFromFile():
|
||||||
#print(s)
|
#print(s)
|
||||||
testDecoder(s, "DD", "")
|
testDecoder(s, "DD", "")
|
||||||
|
|
||||||
|
def testReadExiFromExiLogFile():
|
||||||
|
file1 = open('PevExiLog.txt', 'r')
|
||||||
|
fileOut = open('PevExiLog_decoded.txt', 'w')
|
||||||
|
# example: "ED 809a02004080c1014181c210b8"
|
||||||
|
Lines = file1.readlines()
|
||||||
|
for myLine in Lines:
|
||||||
|
if (myLine[1:3]=="D "): # it is DIN
|
||||||
|
posOfSpace=2
|
||||||
|
s = myLine[posOfSpace+1:] # The part after the " " contains the EXI hex data.
|
||||||
|
s = s.replace(" ", "") # Remove blanks
|
||||||
|
s = s.replace("\n", "") # Remove line feeds
|
||||||
|
#print(s)
|
||||||
|
decoded=exiDecode(s, "DD")
|
||||||
|
print(decoded)
|
||||||
|
print(myLine.replace("\n", "") + " means:", file=fileOut)
|
||||||
|
print(decoded, file=fileOut)
|
||||||
|
fileOut.close()
|
||||||
|
|
||||||
def testTimeConsumption():
|
def testTimeConsumption():
|
||||||
strHex = "809a001150400000c80006400000"
|
strHex = "809a001150400000c80006400000"
|
||||||
pre = "DD"
|
pre = "DD"
|
||||||
|
@ -268,8 +286,8 @@ if __name__ == "__main__":
|
||||||
if (False):
|
if (False):
|
||||||
testTimeConsumption()
|
testTimeConsumption()
|
||||||
exit()
|
exit()
|
||||||
if (False):
|
if (True):
|
||||||
testReadExiFromFile()
|
testReadExiFromExiLogFile()
|
||||||
exit()
|
exit()
|
||||||
|
|
||||||
if (False):
|
if (False):
|
||||||
|
|
78
fsmPev.py
78
fsmPev.py
|
@ -6,7 +6,7 @@
|
||||||
|
|
||||||
import pyPlcTcpSocket
|
import pyPlcTcpSocket
|
||||||
import time # for time.sleep()
|
import time # for time.sleep()
|
||||||
from helpers import prettyHexMessage
|
from helpers import prettyHexMessage, compactHexMessage
|
||||||
from exiConnector import * # for EXI data handling/converting
|
from exiConnector import * # for EXI data handling/converting
|
||||||
import json
|
import json
|
||||||
|
|
||||||
|
@ -38,6 +38,18 @@ class fsmPev():
|
||||||
def addToTrace(self, s):
|
def addToTrace(self, s):
|
||||||
self.callbackAddToTrace("[PEV] " + s)
|
self.callbackAddToTrace("[PEV] " + s)
|
||||||
|
|
||||||
|
def exiDecode(self, exidata, schema):
|
||||||
|
s = compactHexMessage(exidata)
|
||||||
|
self.exiLogFile.write(schema + " " + s +"\n") # write the EXI data to the exiLogFile
|
||||||
|
return exiDecode(exidata, schema) # call the decoder
|
||||||
|
|
||||||
|
def exiEncode(self, input):
|
||||||
|
schema = input[0:2]
|
||||||
|
exidata = exiEncode(input) # call the encoder
|
||||||
|
s = exidata # it is already a hex string
|
||||||
|
self.exiLogFile.write(schema + " " + s +"\n") # write the EXI data to the exiLogFile
|
||||||
|
return exidata
|
||||||
|
|
||||||
def enterState(self, n):
|
def enterState(self, n):
|
||||||
print("from " + str(self.state) + " entering " + str(n))
|
print("from " + str(self.state) + " entering " + str(n))
|
||||||
self.state = n
|
self.state = n
|
||||||
|
@ -86,12 +98,12 @@ class fsmPev():
|
||||||
self.addToTrace("In state WaitForSupportedApplicationProtocolResponse, received " + prettyHexMessage(self.rxData))
|
self.addToTrace("In state WaitForSupportedApplicationProtocolResponse, received " + prettyHexMessage(self.rxData))
|
||||||
exidata = removeV2GTPHeader(self.rxData)
|
exidata = removeV2GTPHeader(self.rxData)
|
||||||
self.rxData = []
|
self.rxData = []
|
||||||
strConverterResult = exiDecode(exidata, "Dh") # Decode Handshake-response
|
strConverterResult = self.exiDecode(exidata, "Dh") # Decode Handshake-response
|
||||||
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.addToTrace("Will send SessionSetupReq")
|
self.addToTrace("Will send SessionSetupReq")
|
||||||
msg = addV2GTPHeader(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))
|
||||||
self.Tcp.transmit(msg)
|
self.Tcp.transmit(msg)
|
||||||
self.enterState(stateWaitForSessionSetupResponse)
|
self.enterState(stateWaitForSessionSetupResponse)
|
||||||
|
@ -103,7 +115,7 @@ class fsmPev():
|
||||||
self.addToTrace("In state WaitForSessionSetupResponse, received " + prettyHexMessage(self.rxData))
|
self.addToTrace("In state WaitForSessionSetupResponse, received " + prettyHexMessage(self.rxData))
|
||||||
exidata = removeV2GTPHeader(self.rxData)
|
exidata = removeV2GTPHeader(self.rxData)
|
||||||
self.rxData = []
|
self.rxData = []
|
||||||
strConverterResult = exiDecode(exidata, "DD") # Decode DIN
|
strConverterResult = self.exiDecode(exidata, "DD") # Decode DIN
|
||||||
self.addToTrace(strConverterResult)
|
self.addToTrace(strConverterResult)
|
||||||
if (strConverterResult.find("SessionSetupRes")>0):
|
if (strConverterResult.find("SessionSetupRes")>0):
|
||||||
# todo: check the request content, and fill response parameters
|
# todo: check the request content, and fill response parameters
|
||||||
|
@ -115,7 +127,7 @@ class fsmPev():
|
||||||
except:
|
except:
|
||||||
self.addToTrace("ERROR: Could not decode the sessionID")
|
self.addToTrace("ERROR: Could not decode the sessionID")
|
||||||
self.addToTrace("Will send ServiceDiscoveryReq")
|
self.addToTrace("Will send ServiceDiscoveryReq")
|
||||||
msg = addV2GTPHeader(exiEncode("EDB_"+self.sessionId)) # EDB for Encode, Din, ServiceDiscoveryRequest
|
msg = addV2GTPHeader(self.exiEncode("EDB_"+self.sessionId)) # EDB for Encode, Din, ServiceDiscoveryRequest
|
||||||
self.addToTrace("responding " + prettyHexMessage(msg))
|
self.addToTrace("responding " + prettyHexMessage(msg))
|
||||||
self.Tcp.transmit(msg)
|
self.Tcp.transmit(msg)
|
||||||
self.enterState(stateWaitForServiceDiscoveryResponse)
|
self.enterState(stateWaitForServiceDiscoveryResponse)
|
||||||
|
@ -127,12 +139,12 @@ class fsmPev():
|
||||||
self.addToTrace("In state WaitForServiceDiscoveryResponse, received " + prettyHexMessage(self.rxData))
|
self.addToTrace("In state WaitForServiceDiscoveryResponse, received " + prettyHexMessage(self.rxData))
|
||||||
exidata = removeV2GTPHeader(self.rxData)
|
exidata = removeV2GTPHeader(self.rxData)
|
||||||
self.rxData = []
|
self.rxData = []
|
||||||
strConverterResult = exiDecode(exidata, "DD") # Decode DIN
|
strConverterResult = self.exiDecode(exidata, "DD") # Decode DIN
|
||||||
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.addToTrace("Will send ServicePaymentSelectionReq")
|
self.addToTrace("Will send ServicePaymentSelectionReq")
|
||||||
msg = addV2GTPHeader(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))
|
||||||
self.Tcp.transmit(msg)
|
self.Tcp.transmit(msg)
|
||||||
self.enterState(stateWaitForServicePaymentSelectionResponse)
|
self.enterState(stateWaitForServicePaymentSelectionResponse)
|
||||||
|
@ -144,12 +156,12 @@ class fsmPev():
|
||||||
self.addToTrace("In state WaitForServicePaymentSelectionResponse, received " + prettyHexMessage(self.rxData))
|
self.addToTrace("In state WaitForServicePaymentSelectionResponse, received " + prettyHexMessage(self.rxData))
|
||||||
exidata = removeV2GTPHeader(self.rxData)
|
exidata = removeV2GTPHeader(self.rxData)
|
||||||
self.rxData = []
|
self.rxData = []
|
||||||
strConverterResult = exiDecode(exidata, "DD") # Decode DIN
|
strConverterResult = self.exiDecode(exidata, "DD") # Decode DIN
|
||||||
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.addToTrace("Will send ContractAuthenticationReq")
|
self.addToTrace("Will send ContractAuthenticationReq")
|
||||||
msg = addV2GTPHeader(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))
|
||||||
self.Tcp.transmit(msg)
|
self.Tcp.transmit(msg)
|
||||||
self.numberOfContractAuthenticationReq = 1 # This is the first request.
|
self.numberOfContractAuthenticationReq = 1 # This is the first request.
|
||||||
|
@ -164,7 +176,7 @@ class fsmPev():
|
||||||
self.addToTrace("In state WaitForContractAuthentication, received " + prettyHexMessage(self.rxData))
|
self.addToTrace("In state WaitForContractAuthentication, received " + prettyHexMessage(self.rxData))
|
||||||
exidata = removeV2GTPHeader(self.rxData)
|
exidata = removeV2GTPHeader(self.rxData)
|
||||||
self.rxData = []
|
self.rxData = []
|
||||||
strConverterResult = exiDecode(exidata, "DD") # Decode DIN
|
strConverterResult = self.exiDecode(exidata, "DD") # Decode DIN
|
||||||
self.addToTrace(strConverterResult)
|
self.addToTrace(strConverterResult)
|
||||||
if (strConverterResult.find("ContractAuthenticationRes")>0):
|
if (strConverterResult.find("ContractAuthenticationRes")>0):
|
||||||
# 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
|
||||||
|
@ -172,7 +184,7 @@ class fsmPev():
|
||||||
# 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.addToTrace("It is Finished. Will send ChargeParameterDiscoveryReq")
|
self.addToTrace("It is Finished. Will send ChargeParameterDiscoveryReq")
|
||||||
msg = addV2GTPHeader(exiEncode("EDE_"+self.sessionId)) # EDE for Encode, Din, ChargeParameterDiscovery.
|
msg = addV2GTPHeader(self.exiEncode("EDE_"+self.sessionId)) # EDE for Encode, Din, ChargeParameterDiscovery.
|
||||||
self.addToTrace("responding " + prettyHexMessage(msg))
|
self.addToTrace("responding " + prettyHexMessage(msg))
|
||||||
self.Tcp.transmit(msg)
|
self.Tcp.transmit(msg)
|
||||||
self.numberOfChargeParameterDiscoveryReq = 1 # first message
|
self.numberOfChargeParameterDiscoveryReq = 1 # first message
|
||||||
|
@ -186,7 +198,7 @@ class fsmPev():
|
||||||
# Try again.
|
# Try again.
|
||||||
self.numberOfContractAuthenticationReq += 1 # count the number of tries.
|
self.numberOfContractAuthenticationReq += 1 # count the number of tries.
|
||||||
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(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))
|
||||||
self.Tcp.transmit(msg)
|
self.Tcp.transmit(msg)
|
||||||
# We just stay in the same state, until the timeout elapses.
|
# We just stay in the same state, until the timeout elapses.
|
||||||
|
@ -202,7 +214,7 @@ class fsmPev():
|
||||||
self.addToTrace("In state WaitForChargeParameterDiscoveryResponse, received " + prettyHexMessage(self.rxData))
|
self.addToTrace("In state WaitForChargeParameterDiscoveryResponse, received " + prettyHexMessage(self.rxData))
|
||||||
exidata = removeV2GTPHeader(self.rxData)
|
exidata = removeV2GTPHeader(self.rxData)
|
||||||
self.rxData = []
|
self.rxData = []
|
||||||
strConverterResult = exiDecode(exidata, "DD") # Decode DIN
|
strConverterResult = self.exiDecode(exidata, "DD") # Decode DIN
|
||||||
self.addToTrace(strConverterResult)
|
self.addToTrace(strConverterResult)
|
||||||
if (strConverterResult.find("ChargeParameterDiscoveryRes")>0):
|
if (strConverterResult.find("ChargeParameterDiscoveryRes")>0):
|
||||||
# We can have two cases here:
|
# We can have two cases here:
|
||||||
|
@ -212,7 +224,7 @@ class fsmPev():
|
||||||
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()
|
||||||
msg = addV2GTPHeader(exiEncode("EDF_"+self.sessionId)) # EDF for Encode, Din, CableCheck
|
msg = addV2GTPHeader(self.exiEncode("EDF_"+self.sessionId)) # EDF for Encode, Din, CableCheck
|
||||||
self.addToTrace("responding " + prettyHexMessage(msg))
|
self.addToTrace("responding " + prettyHexMessage(msg))
|
||||||
self.Tcp.transmit(msg)
|
self.Tcp.transmit(msg)
|
||||||
self.numberOfCableCheckReq = 1 # This is the first request.
|
self.numberOfCableCheckReq = 1 # This is the first request.
|
||||||
|
@ -226,7 +238,7 @@ class fsmPev():
|
||||||
# Try again.
|
# Try again.
|
||||||
self.numberOfChargeParameterDiscoveryReq += 1 # count the number of tries.
|
self.numberOfChargeParameterDiscoveryReq += 1 # count the number of tries.
|
||||||
self.addToTrace("Not (yet) finished. Will again send ChargeParameterDiscoveryReq #" + str(self.numberOfChargeParameterDiscoveryReq))
|
self.addToTrace("Not (yet) finished. Will again send ChargeParameterDiscoveryReq #" + str(self.numberOfChargeParameterDiscoveryReq))
|
||||||
msg = addV2GTPHeader(exiEncode("EDE_"+self.sessionId)) # EDE for Encode, Din, ChargeParameterDiscovery.
|
msg = addV2GTPHeader(self.exiEncode("EDE_"+self.sessionId)) # EDE for Encode, Din, ChargeParameterDiscovery.
|
||||||
self.addToTrace("responding " + prettyHexMessage(msg))
|
self.addToTrace("responding " + prettyHexMessage(msg))
|
||||||
self.Tcp.transmit(msg)
|
self.Tcp.transmit(msg)
|
||||||
# we stay in the same state
|
# we stay in the same state
|
||||||
|
@ -241,7 +253,7 @@ class fsmPev():
|
||||||
self.addToTrace("In state WaitForCableCheckResponse, received " + prettyHexMessage(self.rxData))
|
self.addToTrace("In state WaitForCableCheckResponse, received " + prettyHexMessage(self.rxData))
|
||||||
exidata = removeV2GTPHeader(self.rxData)
|
exidata = removeV2GTPHeader(self.rxData)
|
||||||
self.rxData = []
|
self.rxData = []
|
||||||
strConverterResult = exiDecode(exidata, "DD") # Decode DIN
|
strConverterResult = self.exiDecode(exidata, "DD") # Decode DIN
|
||||||
self.addToTrace(strConverterResult)
|
self.addToTrace(strConverterResult)
|
||||||
if (strConverterResult.find("CableCheckRes")>0):
|
if (strConverterResult.find("CableCheckRes")>0):
|
||||||
try:
|
try:
|
||||||
|
@ -258,7 +270,7 @@ class fsmPev():
|
||||||
if ((strEVSEProcessing=="Finished") and (strResponseCode=="OK")):
|
if ((strEVSEProcessing=="Finished") and (strResponseCode=="OK")):
|
||||||
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")
|
||||||
msg = addV2GTPHeader(exiEncode("EDG_"+self.sessionId)) # EDG for Encode, Din, PreCharge
|
msg = addV2GTPHeader(self.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)
|
||||||
self.enterState(stateWaitForPreChargeResponse)
|
self.enterState(stateWaitForPreChargeResponse)
|
||||||
|
@ -270,7 +282,7 @@ class fsmPev():
|
||||||
# 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.addToTrace("Will again send CableCheckReq")
|
self.addToTrace("Will again send CableCheckReq")
|
||||||
msg = addV2GTPHeader(exiEncode("EDF_"+self.sessionId)) # EDF for Encode, Din, CableCheck
|
msg = addV2GTPHeader(self.exiEncode("EDF_"+self.sessionId)) # EDF for Encode, Din, CableCheck
|
||||||
self.addToTrace("responding " + prettyHexMessage(msg))
|
self.addToTrace("responding " + prettyHexMessage(msg))
|
||||||
self.Tcp.transmit(msg)
|
self.Tcp.transmit(msg)
|
||||||
# stay in the same state
|
# stay in the same state
|
||||||
|
@ -287,7 +299,7 @@ class fsmPev():
|
||||||
self.addToTrace("In state WaitForPreChargeResponse, received " + prettyHexMessage(self.rxData))
|
self.addToTrace("In state WaitForPreChargeResponse, received " + prettyHexMessage(self.rxData))
|
||||||
exidata = removeV2GTPHeader(self.rxData)
|
exidata = removeV2GTPHeader(self.rxData)
|
||||||
self.rxData = []
|
self.rxData = []
|
||||||
strConverterResult = exiDecode(exidata, "DD") # Decode DIN
|
strConverterResult = self.exiDecode(exidata, "DD") # Decode DIN
|
||||||
self.addToTrace(strConverterResult)
|
self.addToTrace(strConverterResult)
|
||||||
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
|
||||||
|
@ -295,7 +307,7 @@ class fsmPev():
|
||||||
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.hardwareInterface.setPowerRelayOn()
|
||||||
msg = addV2GTPHeader(exiEncode("EDH_"+self.sessionId+"_"+"1")) # EDH for Encode, Din, PowerDeliveryReq, ON
|
msg = addV2GTPHeader(self.exiEncode("EDH_"+self.sessionId+"_"+"1")) # EDH for Encode, Din, PowerDeliveryReq, ON
|
||||||
self.wasPowerDeliveryRequestedOn=True
|
self.wasPowerDeliveryRequestedOn=True
|
||||||
self.addToTrace("responding " + prettyHexMessage(msg))
|
self.addToTrace("responding " + prettyHexMessage(msg))
|
||||||
self.Tcp.transmit(msg)
|
self.Tcp.transmit(msg)
|
||||||
|
@ -303,7 +315,7 @@ class fsmPev():
|
||||||
else:
|
else:
|
||||||
self.addToTrace("Difference too big. Continuing PreCharge.")
|
self.addToTrace("Difference too big. Continuing PreCharge.")
|
||||||
#self.addToTrace("As Demo, we stay in PreCharge forever.")
|
#self.addToTrace("As Demo, we stay in PreCharge forever.")
|
||||||
msg = addV2GTPHeader(exiEncode("EDG_"+self.sessionId)) # EDG for Encode, Din, PreCharge
|
msg = addV2GTPHeader(self.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)
|
||||||
self.DelayCycles=15 # wait with the next evaluation approx half a second
|
self.DelayCycles=15 # wait with the next evaluation approx half a second
|
||||||
|
@ -315,12 +327,12 @@ class fsmPev():
|
||||||
self.addToTrace("In state WaitForPowerDeliveryRes, received " + prettyHexMessage(self.rxData))
|
self.addToTrace("In state WaitForPowerDeliveryRes, received " + prettyHexMessage(self.rxData))
|
||||||
exidata = removeV2GTPHeader(self.rxData)
|
exidata = removeV2GTPHeader(self.rxData)
|
||||||
self.rxData = []
|
self.rxData = []
|
||||||
strConverterResult = exiDecode(exidata, "DD") # Decode DIN
|
strConverterResult = self.exiDecode(exidata, "DD") # Decode DIN
|
||||||
self.addToTrace(strConverterResult)
|
self.addToTrace(strConverterResult)
|
||||||
if (strConverterResult.find("PowerDeliveryRes")>0):
|
if (strConverterResult.find("PowerDeliveryRes")>0):
|
||||||
if (self.wasPowerDeliveryRequestedOn):
|
if (self.wasPowerDeliveryRequestedOn):
|
||||||
self.addToTrace("Starting the charging loop with CurrentDemandReq")
|
self.addToTrace("Starting the charging loop with CurrentDemandReq")
|
||||||
msg = addV2GTPHeader(exiEncode("EDI_"+self.sessionId)) # EDI for Encode, Din, CurrentDemandReq
|
msg = addV2GTPHeader(self.exiEncode("EDI_"+self.sessionId)) # EDI for Encode, Din, CurrentDemandReq
|
||||||
self.addToTrace("responding " + prettyHexMessage(msg))
|
self.addToTrace("responding " + prettyHexMessage(msg))
|
||||||
self.Tcp.transmit(msg)
|
self.Tcp.transmit(msg)
|
||||||
self.enterState(stateWaitForCurrentDemandResponse)
|
self.enterState(stateWaitForCurrentDemandResponse)
|
||||||
|
@ -328,7 +340,7 @@ class fsmPev():
|
||||||
# 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.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()
|
||||||
msg = addV2GTPHeader(exiEncode("EDJ_"+self.sessionId)) # EDI for Encode, Din, WeldingDetectionReq
|
msg = addV2GTPHeader(self.exiEncode("EDJ_"+self.sessionId)) # EDI for Encode, Din, WeldingDetectionReq
|
||||||
self.addToTrace("responding " + prettyHexMessage(msg))
|
self.addToTrace("responding " + prettyHexMessage(msg))
|
||||||
self.Tcp.transmit(msg)
|
self.Tcp.transmit(msg)
|
||||||
self.enterState(stateWaitForWeldingDetectionResponse)
|
self.enterState(stateWaitForWeldingDetectionResponse)
|
||||||
|
@ -340,20 +352,20 @@ class fsmPev():
|
||||||
self.addToTrace("In state WaitForCurrentDemandRes, received " + prettyHexMessage(self.rxData))
|
self.addToTrace("In state WaitForCurrentDemandRes, received " + prettyHexMessage(self.rxData))
|
||||||
exidata = removeV2GTPHeader(self.rxData)
|
exidata = removeV2GTPHeader(self.rxData)
|
||||||
self.rxData = []
|
self.rxData = []
|
||||||
strConverterResult = exiDecode(exidata, "DD") # Decode DIN
|
strConverterResult = self.exiDecode(exidata, "DD") # Decode DIN
|
||||||
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()):
|
||||||
self.addToTrace("Accu is full. Sending PowerDeliveryReq Stop.")
|
self.addToTrace("Accu is full. Sending PowerDeliveryReq Stop.")
|
||||||
msg = addV2GTPHeader(exiEncode("EDH_"+self.sessionId+"_"+"0")) # EDH for Encode, Din, PowerDeliveryReq, OFF
|
msg = addV2GTPHeader(self.exiEncode("EDH_"+self.sessionId+"_"+"0")) # EDH for Encode, Din, PowerDeliveryReq, OFF
|
||||||
self.wasPowerDeliveryRequestedOn=False
|
self.wasPowerDeliveryRequestedOn=False
|
||||||
self.addToTrace("responding " + prettyHexMessage(msg))
|
self.addToTrace("responding " + prettyHexMessage(msg))
|
||||||
self.Tcp.transmit(msg)
|
self.Tcp.transmit(msg)
|
||||||
self.enterState(stateWaitForPowerDeliveryResponse)
|
self.enterState(stateWaitForPowerDeliveryResponse)
|
||||||
else:
|
else:
|
||||||
# continue charging loop
|
# continue charging loop
|
||||||
msg = addV2GTPHeader(exiEncode("EDI_"+self.sessionId)) # EDI for Encode, Din, CurrentDemandReq
|
msg = addV2GTPHeader(self.exiEncode("EDI_"+self.sessionId)) # EDI for Encode, Din, CurrentDemandReq
|
||||||
self.addToTrace("responding " + prettyHexMessage(msg))
|
self.addToTrace("responding " + prettyHexMessage(msg))
|
||||||
self.Tcp.transmit(msg)
|
self.Tcp.transmit(msg)
|
||||||
self.enterState(stateWaitForCurrentDemandResponse)
|
self.enterState(stateWaitForCurrentDemandResponse)
|
||||||
|
@ -366,11 +378,11 @@ class fsmPev():
|
||||||
self.addToTrace("In state WaitForWeldingDetectionResponse, received " + prettyHexMessage(self.rxData))
|
self.addToTrace("In state WaitForWeldingDetectionResponse, received " + prettyHexMessage(self.rxData))
|
||||||
exidata = removeV2GTPHeader(self.rxData)
|
exidata = removeV2GTPHeader(self.rxData)
|
||||||
self.rxData = []
|
self.rxData = []
|
||||||
strConverterResult = exiDecode(exidata, "DD") # Decode DIN
|
strConverterResult = self.exiDecode(exidata, "DD") # Decode DIN
|
||||||
self.addToTrace(strConverterResult)
|
self.addToTrace(strConverterResult)
|
||||||
if (strConverterResult.find("WeldingDetectionRes")>0):
|
if (strConverterResult.find("WeldingDetectionRes")>0):
|
||||||
self.addToTrace("Sending SessionStopReq")
|
self.addToTrace("Sending SessionStopReq")
|
||||||
msg = addV2GTPHeader(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))
|
||||||
self.Tcp.transmit(msg)
|
self.Tcp.transmit(msg)
|
||||||
self.enterState(stateWaitForSessionStopResponse)
|
self.enterState(stateWaitForSessionStopResponse)
|
||||||
|
@ -382,7 +394,7 @@ class fsmPev():
|
||||||
self.addToTrace("In state WaitForSessionStopRes, received " + prettyHexMessage(self.rxData))
|
self.addToTrace("In state WaitForSessionStopRes, received " + prettyHexMessage(self.rxData))
|
||||||
exidata = removeV2GTPHeader(self.rxData)
|
exidata = removeV2GTPHeader(self.rxData)
|
||||||
self.rxData = []
|
self.rxData = []
|
||||||
strConverterResult = exiDecode(exidata, "DD") # Decode DIN
|
strConverterResult = self.exiDecode(exidata, "DD") # Decode DIN
|
||||||
self.addToTrace(strConverterResult)
|
self.addToTrace(strConverterResult)
|
||||||
if (strConverterResult.find("SessionStopRes")>0):
|
if (strConverterResult.find("SessionStopRes")>0):
|
||||||
# req -508
|
# req -508
|
||||||
|
@ -439,6 +451,8 @@ class fsmPev():
|
||||||
def __init__(self, addressManager, callbackAddToTrace, hardwareInterface):
|
def __init__(self, addressManager, callbackAddToTrace, hardwareInterface):
|
||||||
self.callbackAddToTrace = callbackAddToTrace
|
self.callbackAddToTrace = callbackAddToTrace
|
||||||
self.addToTrace("initializing fsmPev")
|
self.addToTrace("initializing fsmPev")
|
||||||
|
self.exiLogFile = open('PevExiLog.txt', 'a')
|
||||||
|
self.exiLogFile.write("init\n")
|
||||||
self.Tcp = pyPlcTcpSocket.pyPlcTcpClientSocket(self.callbackAddToTrace)
|
self.Tcp = pyPlcTcpSocket.pyPlcTcpClientSocket(self.callbackAddToTrace)
|
||||||
self.addressManager = addressManager
|
self.addressManager = addressManager
|
||||||
self.hardwareInterface = hardwareInterface
|
self.hardwareInterface = hardwareInterface
|
||||||
|
@ -449,6 +463,10 @@ class fsmPev():
|
||||||
self.rxData = []
|
self.rxData = []
|
||||||
# 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):
|
||||||
|
self.exiLogFile.write("closing\n")
|
||||||
|
self.exiLogFile.close()
|
||||||
|
|
||||||
def mainfunction(self):
|
def mainfunction(self):
|
||||||
#self.Tcp.mainfunction() # call the lower-level worker
|
#self.Tcp.mainfunction() # call the lower-level worker
|
||||||
if (self.Tcp.isRxDataAvailable()):
|
if (self.Tcp.isRxDataAvailable()):
|
||||||
|
|
|
@ -18,6 +18,13 @@ def prettyHexMessage(mybytearray, description=""):
|
||||||
strHex = strHex + twoCharHex(mybytearray[i]) + " "
|
strHex = strHex + twoCharHex(mybytearray[i]) + " "
|
||||||
return description + "(" + str(packetlength) + "bytes) = " + strHex
|
return description + "(" + str(packetlength) + "bytes) = " + strHex
|
||||||
|
|
||||||
|
def compactHexMessage(mybytearray):
|
||||||
|
packetlength = len(mybytearray)
|
||||||
|
strHex = ""
|
||||||
|
for i in range(0, packetlength):
|
||||||
|
strHex = strHex + twoCharHex(mybytearray[i])
|
||||||
|
return strHex
|
||||||
|
|
||||||
def prettyMac(macByteArray):
|
def prettyMac(macByteArray):
|
||||||
s=""
|
s=""
|
||||||
length = len(macByteArray)
|
length = len(macByteArray)
|
||||||
|
|
1
pyPlc.py
1
pyPlc.py
|
@ -86,5 +86,6 @@ while lastKey!="x":
|
||||||
# print(str(nMainloops) + " " + str(nKeystrokes)) # show something in the console window
|
# print(str(nMainloops) + " " + str(nKeystrokes)) # show something in the console window
|
||||||
root.update()
|
root.update()
|
||||||
worker.mainfunction()
|
worker.mainfunction()
|
||||||
|
del(worker)
|
||||||
|
|
||||||
#---------------------------------------------------------------
|
#---------------------------------------------------------------
|
||||||
|
|
|
@ -751,7 +751,7 @@ class pyPlcHomeplug():
|
||||||
self.pevSequenceCyclesInState+=1
|
self.pevSequenceCyclesInState+=1
|
||||||
if (self.pevSequenceState==STATE_INITIAL): # Initial state.
|
if (self.pevSequenceState==STATE_INITIAL): # Initial state.
|
||||||
# In real life we would check whether we see 5% PWM on the pilot line. We skip this check.
|
# In real life we would check whether we see 5% PWM on the pilot line. We skip this check.
|
||||||
self.isSimulationMode = 0
|
self.isSimulationMode = self.isForcedSimulationMode # from command line, we can force the simulation mode
|
||||||
self.isSDPDone = 0
|
self.isSDPDone = 0
|
||||||
self.numberOfFoundModems = 0
|
self.numberOfFoundModems = 0
|
||||||
self.localModemFound = 0
|
self.localModemFound = 0
|
||||||
|
@ -1034,7 +1034,8 @@ class pyPlcHomeplug():
|
||||||
self.pevSequenceState = 0
|
self.pevSequenceState = 0
|
||||||
self.pevSequenceCyclesInState = 0
|
self.pevSequenceCyclesInState = 0
|
||||||
self.numberOfSoftwareVersionResponses = 0
|
self.numberOfSoftwareVersionResponses = 0
|
||||||
self.isSimulationMode = isSimulationMode # simulation without homeplug modem
|
self.numberOfFoundModems = 0
|
||||||
|
self.isForcedSimulationMode = isSimulationMode # simulation without homeplug modem
|
||||||
#self.sniffer = pcap.pcap(name=None, promisc=True, immediate=True, timeout_ms=50)
|
#self.sniffer = pcap.pcap(name=None, promisc=True, immediate=True, timeout_ms=50)
|
||||||
# eth3 means: Third entry from back, in the list of interfaces, which is provided by pcap.findalldevs.
|
# eth3 means: Third entry from back, in the list of interfaces, which is provided by pcap.findalldevs.
|
||||||
# Improvement necessary: select the interface based on the name.
|
# Improvement necessary: select the interface based on the name.
|
||||||
|
|
|
@ -307,7 +307,9 @@ class ipv6handler():
|
||||||
# 0x8001 EXI encoded V2G message
|
# 0x8001 EXI encoded V2G message
|
||||||
if (v2gptPayloadType == 0x8001):
|
if (v2gptPayloadType == 0x8001):
|
||||||
self.ExiPacket = self.v2gframe[8:] # the exi payload, without the 8 bytes V2GTP header
|
self.ExiPacket = self.v2gframe[8:] # the exi payload, without the 8 bytes V2GTP header
|
||||||
print("[SNIFFER] EXI from " + str(self.tcpsourceport) + " to " + str(self.tcpdestinationport) + " " + prettyHexMessage(self.ExiPacket))
|
s = "[SNIFFER] EXI from " + str(self.tcpsourceport) + " to " + str(self.tcpdestinationport) + " " + prettyHexMessage(self.ExiPacket)
|
||||||
|
print(s)
|
||||||
|
# print(s, file=self.exiLogFile)
|
||||||
# Todo: further process the EXI packet. E.g. write it into file for offline analysis.
|
# Todo: further process the EXI packet. E.g. write it into file for offline analysis.
|
||||||
# And send it to decoder.
|
# And send it to decoder.
|
||||||
|
|
||||||
|
@ -316,7 +318,7 @@ class ipv6handler():
|
||||||
# just want to listen to the conversation of two others, and extract what we hear.
|
# just want to listen to the conversation of two others, and extract what we hear.
|
||||||
self.tcpsourceport = self.myreceivebuffer[54] * 256 + self.myreceivebuffer[55]
|
self.tcpsourceport = self.myreceivebuffer[54] * 256 + self.myreceivebuffer[55]
|
||||||
self.tcpdestinationport = self.myreceivebuffer[56] * 256 + self.myreceivebuffer[57]
|
self.tcpdestinationport = self.myreceivebuffer[56] * 256 + self.myreceivebuffer[57]
|
||||||
if ((self.tcpsourceport == 15118) or (self.tcpdestinationport == 15118)):
|
if (True): # we do not check port, because the TCP port is variable. (self.tcpsourceport == 15118) or (self.tcpdestinationport == 15118))
|
||||||
if (len(self.myreceivebuffer)>=74+9): # 74 is the TCP without any data. A V2GTP has 8 bytes header, plus at least 1 payload byte.
|
if (len(self.myreceivebuffer)>=74+9): # 74 is the TCP without any data. A V2GTP has 8 bytes header, plus at least 1 payload byte.
|
||||||
startOfV2gtp = 74 # the index of the first V2GTP byte in the ethernet buffer
|
startOfV2gtp = 74 # the index of the first V2GTP byte in the ethernet buffer
|
||||||
if ((self.myreceivebuffer[startOfV2gtp] == 0x01) and (self.myreceivebuffer[startOfV2gtp+1] == 0xFE)):
|
if ((self.myreceivebuffer[startOfV2gtp] == 0x01) and (self.myreceivebuffer[startOfV2gtp+1] == 0xFE)):
|
||||||
|
@ -356,6 +358,7 @@ class ipv6handler():
|
||||||
#self.enterListenMode()
|
#self.enterListenMode()
|
||||||
self.transmit = transmitCallback
|
self.transmit = transmitCallback
|
||||||
self.addressManager = addressManager
|
self.addressManager = addressManager
|
||||||
|
#self.exiLogFile = open('SnifferExiLog.txt', 'w')
|
||||||
# 16 bytes, a default IPv6 address for the charging station
|
# 16 bytes, a default IPv6 address for the charging station
|
||||||
# self.SeccIp = [ 0xfe, 0x80, 0, 0, 0, 0, 0, 0, 0x06, 0xaa, 0xaa, 0xff, 0xfe, 0, 0xaa, 0xaa ]
|
# self.SeccIp = [ 0xfe, 0x80, 0, 0, 0, 0, 0, 0, 0x06, 0xaa, 0xaa, 0xff, 0xfe, 0, 0xaa, 0xaa ]
|
||||||
# fe80::e0ad:99ac:52eb:85d3 is the Win10 laptop
|
# fe80::e0ad:99ac:52eb:85d3 is the Win10 laptop
|
||||||
|
|
|
@ -42,6 +42,10 @@ class pyPlcWorker():
|
||||||
self.evse = fsmEvse.fsmEvse(self.workerAddToTrace)
|
self.evse = fsmEvse.fsmEvse(self.workerAddToTrace)
|
||||||
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)
|
||||||
|
def __del__(self):
|
||||||
|
if (self.mode == C_PEV_MODE):
|
||||||
|
print("worker: deleting pev")
|
||||||
|
del(self.pev)
|
||||||
|
|
||||||
def workerAddToTrace(self, s):
|
def workerAddToTrace(self, s):
|
||||||
# The central logging function. All logging messages from the different parts of the project
|
# The central logging function. All logging messages from the different parts of the project
|
||||||
|
|
Loading…
Reference in a new issue