Skip to content

Commit

Permalink
Enable AC ISO 15118 properly with two payment modes
Browse files Browse the repository at this point in the history
- Use a nodered flow that only supports AC ISO 15118-2 EIM and PnC
- Patch SwitchEV to plumb through the payment option to the ISO 15118 library
  by following the EnergyTransfer route
  EVerest#44 (comment)
  https://lfenergy.zulipchat.com/#narrow/stream/417677-EVerest.3A-Car-com.2E/topic/.E2.9C.94.20Update.20Node-red.20flows.20because.20of.20JsEvManager.20commit/near/443617217
- Enable `iso15118car` debug logging so that we can see the decoded EXI messages in the absence of
  https://lfenergy.zulipchat.com/#narrow/stream/417677-EVerest.3A-Car-com.2E/topic/EXI.20V2G.20Decoder.20Recommendations/near/442318988
- disable the maeve patches to remove the LB since it is already removed in the updated branch

Testing done:

```
patching file docker-compose.yml
Patching the CSMS to enable local mo root
patching file 'config/manager/config.toml'
Patching the CSMS to enable local mo root
patching file 'manager/handlers/ocpp201/authorize.go'
Starting the CSMS
```

```
[+] Running 4/4
 ✔ Container maeve-csms-firestore-1  Running                                                              0.0s
 ✔ Container maeve-csms-mqtt-1       Healthy                                                              0.1s
 ✔ Container maeve-csms-manager-1    Healthy                                                              0.2s
 ✔ Container maeve-csms-gateway-1    Started                                                              0.2s
Waiting 5s for CSMS to start...
MaEVe CSMS started, adding charge station with Security Profile 3 (note: profiles in MaEVe start with 0 so SP-2 == OCPP SP-3)
Charge station added, adding user token
API calls to CSMS finished, starting EVerest...
```

```
 ✔ Network everest-ac-demo_default          Created                                                       0.1s
 ✔ Container everest-ac-demo-mqtt-server-1  Healthy                                                       0.1s
 ✔ Container everest-ac-demo-nodered-1      Healthy                                                       0.2s
 ✔ Container everest-ac-demo-manager-1      Healthy                                                       0.1s
Successfully copied 60.9kB to everest-ac-demo-nodered-1:/config/config-sil-two-evse-flow.json
everest-ac-demo-nodered-1
Successfully copied 6.66kB to everest-ac-demo-manager-1:/ext/source/config/config-sil-ocpp201-pnc.yaml
Successfully copied 8.19kB to everest-ac-demo-manager-1:/tmp/
Successfully copied 3.58kB to everest-ac-demo-manager-1:/ext/source/build/dist/etc/everest/default_logging.cfg
fetch https://dl-cdn.alpinelinux.org/alpine/v3.17/main/x86_64/APKINDEX.tar.gz
fetch https://dl-cdn.alpinelinux.org/alpine/v3.17/community/x86_64/APKINDEX.tar.gz
fetch https://dl-cdn.alpinelinux.org/alpine/edge/testing/x86_64/APKINDEX.tar.gz
(1/1) Installing patch (2.7.6-r9)
Executing busybox-1.35.0-r29.trigger
OK: 1379 MiB in 230 packages
patching file source/build/dist/libexec/everest/3rd_party/josev/iso15118/evcc/controller/interface.py
patching file source/build/dist/libexec/everest/3rd_party/josev/iso15118/evcc/controller/simulator.py
patching file source/build/dist/libexec/everest/3rd_party/josev/iso15118/evcc/states/iso15118_2_states.py
Successfully copied 29.2kB to everest-ac-demo-manager-1:/ext/source/build
```

```
2024-06-09 19:41:31.667368 [DEBG] iso15118_car    pybind11_init_everestpy(pybind11::module_&)::<lambda(const std::string&)> :: Decoded message (ns=urn:iso:15118:2:2013:MsgDef): {"V2G_Message":{"Header":{"SessionID":"04337FC4777FB77D"},"Body":{"ServiceDiscoveryRes":{"ResponseCode":"OK","PaymentOptionList":{"PaymentOption":["ExternalPayment","Contract"]},"ChargeService":{"ServiceID":1,"ServiceCategory":"EVCharging","FreeService":false,"SupportedEnergyTransferMode":{"EnergyTransferMode":["AC_single_phase_core","AC_three_phase_core"]}},"ServiceList":{"Service":[{"ServiceID":2,"ServiceName":"Certificate","ServiceCategory":"ContractCertificate","FreeService":true}]}}}}}
2024-06-09 19:41:31.670311 [WARN] iso15118_car    pybind11_init_everestpy(pybind11::module_&)::<lambda(const std::string&)> :: V2G_PAYMENT: in function read value from state AuthEnum.PNC_V2
2024-06-09 19:41:31.671413 [DEBG] iso15118_car    pybind11_init_everestpy(pybind11::module_&)::<lambda(const std::string&)> :: Message to encode (ns=urn:iso:15118:2:2013:MsgDef): {"V2G_Message": {"Header": {"SessionID": "04337FC4777FB77D"}, "Body": {"PaymentServiceSelectionReq": {"SelectedPaymentOption": "Contract", "SelectedServiceList": {"SelectedService": [{"ServiceID": 1}]}}}}}
2024-06-09 19:41:34.155595 [INFO] ocpp:OCPP201     :: CSMS certificate status: Accepted
2024-06-09 19:41:34.159815 [INFO] auth:Auth        :: Providing authorization to connector#1
2024-06-09 19:41:35.873697 [DEBG] iso15118_car    pybind11_init_everestpy(pybind11::module_&)::<lambda(const std::string&)> :: Message to encode (ns=urn:iso:15118:2:2013:MsgDef): {"V2G_Message": {"Header": {"SessionID": "04337FC4777FB77D"}, "Body": {"ChargeParameterDiscoveryReq": {"RequestedEnergyTransferMode": "AC_three_phase_core", "AC_EVChargeParameter": {"DepartureTime": 0, "EAmount": {"Value": 60, "Multiplier": 0, "Unit": "Wh"}, "EVMaxVoltage": {"Value": 400, "Multiplier": 0, "Unit": "V"}, "EVMaxCurrent": {"Value": 32000, "Multiplier": -3, "Unit": "A"}, "EVMinCurrent": {"Value": 10, "Multiplier": 0, "Unit": "A"}}}}}}
2024-06-09 19:41:36.948664 [DEBG] iso15118_car    pybind11_init_everestpy(pybind11::module_&)::<lambda(const std::string&)> :: Decoded message (ns=urn:iso:15118:2:2013:MsgDef): {"V2G_Message":{"Header":{"SessionID":"04337FC4777FB77D"},"Body":{"ChargeParameterDiscoveryRes":{"ResponseCode":"OK","EVSEProcessing":"Finished","SAScheduleList":{"SAScheduleTuple":[{"SAScheduleTupleID":1,"PMaxSchedule":{"PMaxScheduleEntry":[{"RelativeTimeInterval":{"start":0,"duration":86400},"PMax":{"Multiplier":0,"Unit":"W","Value":22080}}]}}]},"AC_EVSEChargeParameter":{"AC_EVSEStatus":{"NotificationMaxDelay":0,"EVSENotification":"None","RCD":false},"EVSENominalVoltage":{"Multiplier":-1,"Unit":"V","Value":2300},"EVSEMaxCurrent":{"Multiplier":-1,"Unit":"A","Value":320}}}}}}
```

Signed-off-by: Shankari <k.shankari@ee.doe.gov>
  • Loading branch information
shankari committed Jun 9, 2024
1 parent 14c4acf commit 714da6a
Show file tree
Hide file tree
Showing 4 changed files with 2,405 additions and 3 deletions.
14 changes: 11 additions & 3 deletions demo-iso15118-2-ac-plus-ocpp.sh
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@ cd "${DEMO_DIR}" || exit 1

echo "Cloning EVerest from ${DEMO_REPO} into ${DEMO_DIR}/everest-demo"
git clone --branch "${DEMO_BRANCH}" "${DEMO_REPO}" everest-demo
# cp -r "${DEMO_REPO}" everest-demo

if [[ "$DEMO_VERSION" != v1.6j ]]; then
echo "Cloning ${CSMS} CSMS from ${CSMS_REPO} into ${DEMO_DIR}/${CSMS}-csms and starting it"
Expand Down Expand Up @@ -120,9 +121,6 @@ if [[ "$DEMO_VERSION" != v1.6j ]]; then
fi
else
cp ../everest-demo/manager/cached_certs_correct_name_emaid.tar.gz .

echo "Patching the CSMS to disable load balancer"
patch -p1 -i ../everest-demo/maeve/maeve-csms-no-lb.patch
fi

# Set up certificates for SP2 and SP3
Expand Down Expand Up @@ -347,7 +345,17 @@ fi

pushd everest-demo || exit 1
docker compose --project-name everest-ac-demo --file "${DEMO_COMPOSE_FILE_NAME}" up -d --wait

# Configure and restart nodered
docker cp nodered/config/config-sil-iso15118-ac-flow.json everest-ac-demo-nodered-1:/config/config-sil-two-evse-flow.json
docker restart everest-ac-demo-nodered-1

# Configure and restart EVerest
docker cp config-sil-ocpp201-pnc.yaml everest-ac-demo-manager-1:/ext/source/config/config-sil-ocpp201-pnc.yaml
docker cp manager/enable_payment_method.patch everest-ac-demo-manager-1:/tmp/
docker cp manager/enable_evcc_logging.cfg everest-ac-demo-manager-1:/ext/source/build/dist/etc/everest/default_logging.cfg
docker exec everest-ac-demo-manager-1 /bin/bash -c "apk add patch && cd /ext && patch -p0 -i /tmp/enable_payment_method.patch"

if [[ "$DEMO_VERSION" =~ sp2 || "$DEMO_VERSION" =~ sp3 ]]; then
docker cp manager/cached_certs_correct_name_emaid.tar.gz everest-ac-demo-manager-1:/ext/source/build
docker exec everest-ac-demo-manager-1 /bin/bash -c "pushd /ext/source/build && tar xf cached_certs_correct_name_emaid.tar.gz"
Expand Down
24 changes: 24 additions & 0 deletions manager/enable_evcc_logging.cfg
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# for documentation on this file format see:
# https://www.boost.org/doc/libs/1_54_0/libs/log/doc/html/log/detailed/utilities.html#log.detailed.utilities.setup.filter_formatter

[Core]
DisableLogging=false

# To get debug logs of only one module, add the "%Process% contains" filter, e.g.:
#
# "(%Process% contains OCPP201 and %Severity% >= DEBG)"
#
# whereas "OCPP201" is the value of the field `active_modules.NAME.module` in the respective /config/config-*.yaml.
Filter="%Severity% >= INFO or (%Process% contains iso15118_car and %Severity% >= DEBG)"

[Sinks.Console]
Destination=Console
# Filter="%Target% contains \"MySink1\""
Format="%TimeStamp% [%Severity%] \033[1;32m%Process%\033[0m \033[1;36m%function%\033[0m \033[1;30m%file%:\033[0m\033[1;32m%line%\033[0m: %Message%"
Asynchronous=false
AutoFlush=true
SeverityStringColorDebug="\033[1;30m"
SeverityStringColorInfo="\033[1;37m"
SeverityStringColorWarning="\033[1;33m"
SeverityStringColorError="\033[1;31m"
SeverityStringColorCritical="\033[1;35m"
114 changes: 114 additions & 0 deletions manager/enable_payment_method.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
--- ext-switchev-iso15118/iso15118/evcc/controller/interface.py
+++ source/build/dist/libexec/everest/3rd_party/josev/iso15118/evcc/controller/interface.py
@@ -109,6 +109,15 @@
raise NotImplementedError

@abstractmethod
+ async def get_selected_auth_option(
+ self, protocol: Protocol
+ ) -> AuthEnum:
+ """
+ Gets the auth transfer mode requested for the current charging session.
+ """
+ raise NotImplementedError
+
+ @abstractmethod
async def get_energy_transfer_mode(
self, protocol: Protocol
) -> EnergyTransferModeEnum:
--- ext-switchev-iso15118/iso15118/evcc/controller/simulator.py
+++ source/build/dist/libexec/everest/3rd_party/josev/iso15118/evcc/controller/simulator.py
@@ -53,6 +53,7 @@
SAScheduleTupleEntry as SAScheduleTupleEntryDINSPEC,
)
from iso15118.shared.messages.enums import (
+ AuthEnum,
ControlMode,
DCEVErrorCode,
EnergyTransferModeEnum,
@@ -233,11 +234,18 @@
logger.error(f"Invalid protocol '{protocol}', can't determine EVCCID")
raise InvalidProtocolError

+ async def get_selected_auth_option(
+ self, protocol: Protocol
+ ) -> AuthEnum:
+ """Overrides EVControllerInterface.get_selected_auth_option()."""
+ return AuthEnum(EVEREST_EV_STATE.PaymentOption)
+
async def get_energy_transfer_mode(
self, protocol: Protocol
) -> EnergyTransferModeEnum:
"""Overrides EVControllerInterface.get_energy_transfer_mode()."""
return EnergyTransferModeEnum(EVEREST_EV_STATE.EnergyTransferMode)
+

async def get_supported_energy_services(self) -> List[ServiceV20]:
"""Overrides EVControllerInterface.get_energy_transfer_service()."""
--- ext-switchev-iso15118/iso15118/evcc/states/iso15118_2_states.py
+++ source/build/dist/libexec/everest/3rd_party/josev/iso15118/evcc/states/iso15118_2_states.py
@@ -193,8 +193,9 @@
self.stop_state_machine("ChargeService not offered")
return

- self.select_auth_mode(service_discovery_res.auth_option_list.auth_options)
+ logger.warn("received auth options list %s" % service_discovery_res.auth_option_list.auth_options)
await self.select_services(service_discovery_res)
+ await self.select_auth_mode(service_discovery_res.auth_option_list.auth_options)
await self.select_energy_transfer_mode()

charge_service: ChargeService = service_discovery_res.charge_service
@@ -262,12 +263,13 @@
self.comm_session.selected_energy_mode.value.startswith("AC")
)

- def select_auth_mode(self, auth_option_list: List[AuthEnum]):
+ async def select_auth_mode(self, auth_option_list: List[AuthEnum]):
"""
Check if an authorization mode (aka payment option in ISO 15118-2) was
saved from a previously paused communication session and reuse for
resumed session, otherwise request from EV controller.
"""
+ logger.warn("V2G_PAYMENT: in function received auth options list %s" % auth_option_list)
if evcc_settings.ev_session_context.selected_auth_option:
logger.debug(
"Reusing authorization option "
@@ -279,15 +281,30 @@
)
evcc_settings.ev_session_context.selected_auth_option = None
else:
- # Choose Plug & Charge (pnc) or External Identification Means (eim)
- # as the selected authorization option. The car manufacturer might
- # have a mechanism to determine a user-defined or default
- # authorization option. This implementation favors pnc, but
- # feel free to change if need be.
- if AuthEnum.PNC_V2 in auth_option_list and self.comm_session.is_tls:
- self.comm_session.selected_auth_option = AuthEnum.PNC_V2
+ logger.warn("V2G_PAYMENT: about to read value from state")
+ self.comm_session.selected_auth_option = (
+ await self.comm_session.ev_controller.get_selected_auth_option(
+ Protocol.ISO_15118_2
+ )
+ )
+ logger.warn("V2G_PAYMENT: in function read value from state %s" % self.comm_session.selected_auth_option)
+ if self.comm_session.selected_auth_option is not None:
+ logger.debug(
+ "V2G_PAYMENT: Found Payment Option %s passed in from the PyJoseV module, using it" % self.comm_session.selected_auth_option
+ )
else:
- self.comm_session.selected_auth_option = AuthEnum.EIM_V2
+ logger.debug(
+ "V2G_PAYMENT: No previous paused session, no PaymentOption set, using TLS flag %s to decide auth method" % self.comm_session.is_tls
+ )
+ # Choose Plug & Charge (pnc) or External Identification Means (eim)
+ # as the selected authorization option. The car manufacturer might
+ # have a mechanism to determine a user-defined or default
+ # authorization option. This implementation favors pnc, but
+ # feel free to change if need be.
+ if AuthEnum.PNC_V2 in auth_option_list and self.comm_session.is_tls:
+ self.comm_session.selected_auth_option = AuthEnum.PNC_V2
+ else:
+ self.comm_session.selected_auth_option = AuthEnum.EIM_V2

async def select_services(self, service_discovery_res: ServiceDiscoveryRes):
"""
Loading

0 comments on commit 714da6a

Please sign in to comment.