mirror of
https://github.com/uhi22/pyPLC.git
synced 2024-11-20 01:13:58 +00:00
PevMode: added contractAuthentication
This commit is contained in:
parent
a9b6e826cd
commit
0f7c7122b5
5 changed files with 1450 additions and 16 deletions
20
doc/bug_analysis.md
Normal file
20
doc/bug_analysis.md
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
# Open issues
|
||||||
|
|
||||||
|
## Issue12: Alpi reports "sequence error" for CableCheck
|
||||||
|
- with version v0.3.
|
||||||
|
- maybe he expects the state C, or something is wrong with the sequence before.
|
||||||
|
|
||||||
|
# Closed issues
|
||||||
|
|
||||||
|
## [Solved] Issue10: Alpi says SequenceError in ChargeParameterDiscoveryRes
|
||||||
|
- ServicePaymentSelectionRes says "ResponseCode": "OK", and has no more fields.
|
||||||
|
- Afterwards we send ChargeParameterDiscoveryReq and get ChargeParameterDiscoveryRes containing "ResponseCode": "FAILED_SequenceError".
|
||||||
|
- Analysis: In the ISO case, the ChargeParameterDiscoveryReq comes after the AuthorizationRes with EVSEProcessing=Finished. But we are using DIN, and here there is no AuthorizationRes, but ContractAuthentication instead. But, this does not
|
||||||
|
have a field EVSEProcessing. And in DIN, we have dinContractAuthenticationResType, which contains ResponseCode and EVSEProcessing (see OpenV2G, dinEXIDatatypes.h).
|
||||||
|
- Solution: Send ContractAuthenticationReq after ServicePaymentSelectionRes, and repeat it until it says "finished". Test pass with v0.3.
|
||||||
|
|
||||||
|
## [Solved] Issue11: TCP connection fails on Alpi
|
||||||
|
- Observation: On Alpitronics, the SDP works, but the TCP connect fails. The connection is rejected by the charger.
|
||||||
|
- Root cause: We used fixed port 15118 for the TCP. This is not intended, even it works on other chargers (ABB).
|
||||||
|
- Solution: use the TCP port, which was announced in the SDP response.
|
||||||
|
- Test pass with version v0.2-9-ga9b6e82.
|
|
@ -27,15 +27,16 @@ Test results tbd
|
||||||
|
|
||||||
Test site: e.g. https://www.goingelectric.de/stromtankstellen/Deutschland/Ingolstadt/Dehner-Garten-Center-Degenhartstrasse-Degenhartstrasse-2/71112/
|
Test site: e.g. https://www.goingelectric.de/stromtankstellen/Deutschland/Ingolstadt/Dehner-Garten-Center-Degenhartstrasse-Degenhartstrasse-2/71112/
|
||||||
|
|
||||||
Test results of version v0.2
|
Test results of version v0.3
|
||||||
- [x] SLAC
|
- [x] SLAC
|
||||||
- [x] SDP
|
- [x] SDP
|
||||||
- [ ] TCP connection
|
- [x] TCP connection
|
||||||
- [ ] EXI
|
- [x] EXI
|
||||||
- [ ] DIN SupportedApplicationProtocol
|
- [x] DIN SupportedApplicationProtocol
|
||||||
- [ ] DIN SessionSetup
|
- [x] DIN SessionSetup
|
||||||
- [ ] DIN ServiceDiscovery
|
- [x] DIN ServiceDiscovery
|
||||||
- [ ] DIN ChargeParameterDiscovery
|
- [x] DIN ChargeParameterDiscovery
|
||||||
|
- [x] DIN ContractAuthentication
|
||||||
- [ ] DIN CableCheck
|
- [ ] DIN CableCheck
|
||||||
- [ ] DIN PreCharge
|
- [ ] DIN PreCharge
|
||||||
- [ ] DIN PowerDelivery, CurrentDemand
|
- [ ] DIN PowerDelivery, CurrentDemand
|
||||||
|
|
49
fsmPev.py
49
fsmPev.py
|
@ -17,7 +17,7 @@ stateWaitForSupportedApplicationProtocolResponse = 3
|
||||||
stateWaitForSessionSetupResponse = 4
|
stateWaitForSessionSetupResponse = 4
|
||||||
stateWaitForServiceDiscoveryResponse = 5
|
stateWaitForServiceDiscoveryResponse = 5
|
||||||
stateWaitForServicePaymentSelectionResponse = 6
|
stateWaitForServicePaymentSelectionResponse = 6
|
||||||
stateWaitForAuthorizationResponse = 7
|
stateWaitForContractAuthenticationResponse = 7
|
||||||
stateWaitForChargeParameterDiscoveryResponse = 8
|
stateWaitForChargeParameterDiscoveryResponse = 8
|
||||||
stateWaitForCableCheckResponse = 9
|
stateWaitForCableCheckResponse = 9
|
||||||
stateWaitForPreChargeResponse = 10
|
stateWaitForPreChargeResponse = 10
|
||||||
|
@ -142,14 +142,52 @@ 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.addToTrace("Will send ChargeParameterDiscoveryReq")
|
self.addToTrace("Will send ContractAuthenticationReq")
|
||||||
msg = addV2GTPHeader(exiEncode("EDE_"+self.sessionId)) # EDE for Encode, Din, ChargeParameterDiscovery. We ignore Authorization, not specified in DIN.
|
msg = addV2GTPHeader(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.enterState(stateWaitForChargeParameterDiscoveryResponse)
|
self.numberOfContractAuthenticationReq = 1 # This is the first request.
|
||||||
|
self.enterState(stateWaitForContractAuthenticationResponse)
|
||||||
if (self.isTooLong()):
|
if (self.isTooLong()):
|
||||||
self.enterState(stateSequenceTimeout)
|
self.enterState(stateSequenceTimeout)
|
||||||
|
|
||||||
|
def stateFunctionWaitForContractAuthenticationResponse(self):
|
||||||
|
if (self.cyclesInState<30): # The first second in the state just do nothing.
|
||||||
|
return
|
||||||
|
if (len(self.rxData)>0):
|
||||||
|
self.addToTrace("In state WaitForContractAuthentication, received " + prettyHexMessage(self.rxData))
|
||||||
|
exidata = removeV2GTPHeader(self.rxData)
|
||||||
|
self.rxData = []
|
||||||
|
strConverterResult = exiDecode(exidata, "DD") # Decode DIN
|
||||||
|
self.addToTrace(strConverterResult)
|
||||||
|
if (strConverterResult.find("ContractAuthenticationRes")>0):
|
||||||
|
# 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.
|
||||||
|
# Or, the authorization is finished. This is shown by EVSEProcessing=Finished.
|
||||||
|
if (strConverterResult.find('"EVSEProcessing": "Finished"')>0):
|
||||||
|
self.addToTrace("It is Finished. Will send ChargeParameterDiscoveryReq")
|
||||||
|
msg = addV2GTPHeader(exiEncode("EDE_"+self.sessionId)) # EDE for Encode, Din, ChargeParameterDiscovery.
|
||||||
|
self.addToTrace("responding " + prettyHexMessage(msg))
|
||||||
|
self.Tcp.transmit(msg)
|
||||||
|
self.enterState(stateWaitForChargeParameterDiscoveryResponse)
|
||||||
|
else:
|
||||||
|
# Not (yet) finished.
|
||||||
|
if (self.numberOfContractAuthenticationReq>=120): # approx 120 seconds, maybe the user searches two minutes for his RFID card...
|
||||||
|
self.addToTrace("Authentication lasted too long. " + str(self.numberOfContractAuthenticationReq) + " Giving up.")
|
||||||
|
self.enterState(stateSequenceTimeout)
|
||||||
|
else:
|
||||||
|
# Try again.
|
||||||
|
self.numberOfContractAuthenticationReq += 1 # count the number of tries.
|
||||||
|
self.addToTrace("Not (yet) finished. Will again send ContractAuthenticationReq #" + str(self.numberOfContractAuthenticationReq))
|
||||||
|
msg = addV2GTPHeader(exiEncode("EDL_"+self.sessionId)) # EDL for Encode, Din, ContractAuthenticationReq.
|
||||||
|
self.addToTrace("responding " + prettyHexMessage(msg))
|
||||||
|
self.Tcp.transmit(msg)
|
||||||
|
# We just stay in the same state, until the timeout elapses.
|
||||||
|
self.enterState(stateWaitForContractAuthenticationResponse)
|
||||||
|
if (self.isTooLong()):
|
||||||
|
# The timeout in case if nothing is received at all.
|
||||||
|
self.enterState(stateSequenceTimeout)
|
||||||
|
|
||||||
def stateFunctionWaitForChargeParameterDiscoveryResponse(self):
|
def stateFunctionWaitForChargeParameterDiscoveryResponse(self):
|
||||||
if (len(self.rxData)>0):
|
if (len(self.rxData)>0):
|
||||||
self.addToTrace("In state WaitForChargeParameterDiscoveryResponse, received " + prettyHexMessage(self.rxData))
|
self.addToTrace("In state WaitForChargeParameterDiscoveryResponse, received " + prettyHexMessage(self.rxData))
|
||||||
|
@ -159,6 +197,8 @@ class fsmPev():
|
||||||
self.addToTrace(strConverterResult)
|
self.addToTrace(strConverterResult)
|
||||||
if (strConverterResult.find("ChargeParameterDiscoveryRes")>0):
|
if (strConverterResult.find("ChargeParameterDiscoveryRes")>0):
|
||||||
# todo: check the request content, and fill response parameters
|
# todo: check the request content, and fill response parameters
|
||||||
|
# todo: if the response is "OK", pull the CP line to state C here.
|
||||||
|
# self.hardwareInterface.changeToStateC()
|
||||||
self.addToTrace("Will send CableCheckReq")
|
self.addToTrace("Will send CableCheckReq")
|
||||||
msg = addV2GTPHeader(exiEncode("EDF_"+self.sessionId)) # EDF for Encode, Din, CableCheck
|
msg = addV2GTPHeader(exiEncode("EDF_"+self.sessionId)) # EDF for Encode, Din, CableCheck
|
||||||
self.addToTrace("responding " + prettyHexMessage(msg))
|
self.addToTrace("responding " + prettyHexMessage(msg))
|
||||||
|
@ -240,6 +280,7 @@ class fsmPev():
|
||||||
stateWaitForSessionSetupResponse: stateFunctionWaitForSessionSetupResponse,
|
stateWaitForSessionSetupResponse: stateFunctionWaitForSessionSetupResponse,
|
||||||
stateWaitForServiceDiscoveryResponse: stateFunctionWaitForServiceDiscoveryResponse,
|
stateWaitForServiceDiscoveryResponse: stateFunctionWaitForServiceDiscoveryResponse,
|
||||||
stateWaitForServicePaymentSelectionResponse: stateFunctionWaitForServicePaymentSelectionResponse,
|
stateWaitForServicePaymentSelectionResponse: stateFunctionWaitForServicePaymentSelectionResponse,
|
||||||
|
stateWaitForContractAuthenticationResponse: stateFunctionWaitForContractAuthenticationResponse,
|
||||||
stateWaitForChargeParameterDiscoveryResponse: stateFunctionWaitForChargeParameterDiscoveryResponse,
|
stateWaitForChargeParameterDiscoveryResponse: stateFunctionWaitForChargeParameterDiscoveryResponse,
|
||||||
stateWaitForCableCheckResponse: stateFunctionWaitForCableCheckResponse,
|
stateWaitForCableCheckResponse: stateFunctionWaitForCableCheckResponse,
|
||||||
stateWaitForPreChargeResponse: stateFunctionWaitForPreChargeResponse,
|
stateWaitForPreChargeResponse: stateFunctionWaitForPreChargeResponse,
|
||||||
|
|
16
readme.md
16
readme.md
|
@ -168,11 +168,14 @@ a new, non-zero SessionID. This SessionID is used in all the upcoming messages f
|
||||||
36. The charger confirms with ServiceDiscoveryResponse. This contains the offered services and payment options. Usually it says which type
|
36. The charger confirms with ServiceDiscoveryResponse. This contains the offered services and payment options. Usually it says which type
|
||||||
of charging the charger supports (e.g. AC 1phase, AC 3phase, or DC according CCS https://en.wikipedia.org/wiki/IEC_62196#FF), and that
|
of charging the charger supports (e.g. AC 1phase, AC 3phase, or DC according CCS https://en.wikipedia.org/wiki/IEC_62196#FF), and that
|
||||||
the payment should be handled externally by the user, or by the car.
|
the payment should be handled externally by the user, or by the car.
|
||||||
37. The car sends PaymentServiceSelectionRequest. Usually (in non-plug-and-charge case), the car says "I cannot pay, something else should
|
37. The car sends ServicePaymentSelectionRequest. Usually (in non-plug-and-charge case), the car says "I cannot pay, something else should
|
||||||
handle the payment", by setting paymentOption=ExternalPayment. Optionally it could announce other services than charging, e.g. internet access.
|
handle the payment", by setting paymentOption=ExternalPayment. Optionally it could announce other services than charging, e.g. internet access.
|
||||||
38. The charger confirms with PaymentServiceSelectionResponse.
|
38. The charger confirms with ServicePaymentSelectionResponse.
|
||||||
39. The car sends AuthorizationRequest. In non-plug-and-charge case this is most likely not containing relevant data.
|
39. The car sends ContractAuthenticationRequest. In non-plug-and-charge case this is most likely not containing relevant data.
|
||||||
40. The charger confirms with AuthorizationResponse.
|
40. The charger confirms with ContractAuthenticationResponse. In case, the user needs to authenticate before charging, this
|
||||||
|
response does NOT yet say EVSEProcessing=Finished. The car repeats the request.
|
||||||
|
41. The user authorizes, e.g. with RFID card or app or however.
|
||||||
|
42. The charger sends ContractAuthenticationResponse with EVSEProcessing=Finished.
|
||||||
41. The car sends ChargeParameterRequest. This contains the wanted RequestedEnergyTransferMode, e.g. to select
|
41. The car sends ChargeParameterRequest. This contains the wanted RequestedEnergyTransferMode, e.g. to select
|
||||||
DC or AC and which power pins are used. The car announces the maximum current limit and the maximum voltage limit.
|
DC or AC and which power pins are used. The car announces the maximum current limit and the maximum voltage limit.
|
||||||
42. The charger confirms with ChargeParameterResponse. The contains the limits from charger side, e.g. min and max voltage,
|
42. The charger confirms with ChargeParameterResponse. The contains the limits from charger side, e.g. min and max voltage,
|
||||||
|
@ -282,10 +285,13 @@ is not yet implemented.
|
||||||
- The TCP port, which is announced in the SDP response, is ignored. This can be the root cause of failing TCP connection on Alpitronics.
|
- The TCP port, which is announced in the SDP response, is ignored. This can be the root cause of failing TCP connection on Alpitronics.
|
||||||
- The SLAC timing includes too long wait times. This may be the root cause for failing SLAC on Supercharger and Compleo.
|
- The SLAC timing includes too long wait times. This may be the root cause for failing SLAC on Supercharger and Compleo.
|
||||||
|
|
||||||
|
### 2022-12-02 v0.3 On Alpitonics until ChargeParameterDiscovery
|
||||||
|
- TCP connection works now on Alpitronics charger
|
||||||
|
- ContractAuthentication loop works
|
||||||
|
|
||||||
### Ongoing improvements
|
### Ongoing improvements
|
||||||
|
|
||||||
- SLAC timing: improvement to be tested.
|
- SLAC timing: improvement to be tested.
|
||||||
- TCP port from SDP response: bugfix to be tested.
|
|
||||||
|
|
||||||
### Test results on real-world chargers
|
### Test results on real-world chargers
|
||||||
|
|
||||||
|
|
1366
results/2022-12-02_alpi_until_cableCheckSequenceError.txt
Normal file
1366
results/2022-12-02_alpi_until_cableCheckSequenceError.txt
Normal file
File diff suppressed because it is too large
Load diff
Loading…
Reference in a new issue