Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Modify cable check contactor status check #404

Merged
merged 10 commits into from
May 20, 2024
20 changes: 10 additions & 10 deletions iso15118/evcc/controller/simulator.py
Original file line number Diff line number Diff line change
Expand Up @@ -679,21 +679,21 @@ async def get_scheduled_dc_charge_loop_params(
) -> ScheduledDCChargeLoopReqParams:
"""Overrides EVControllerInterface.get_scheduled_dc_charge_loop_params()."""
return ScheduledDCChargeLoopReqParams(
ev_target_current=RationalNumber(exponent=3, value=40),
ev_target_voltage=RationalNumber(exponent=3, value=60),
ev_target_current=RationalNumber(exponent=1, value=20),
ev_target_voltage=RationalNumber(exponent=1, value=20),
)

async def get_dynamic_dc_charge_loop_params(self) -> DynamicDCChargeLoopReqParams:
"""Overrides EVControllerInterface.get_dynamic_dc_charge_loop_params()."""
return DynamicDCChargeLoopReqParams(
ev_target_energy_request=RationalNumber(exponent=3, value=40),
ev_max_energy_request=RationalNumber(exponent=3, value=60),
ev_min_energy_request=RationalNumber(exponent=-2, value=20),
ev_max_charge_power=RationalNumber(exponent=3, value=40),
ev_min_charge_power=RationalNumber(exponent=3, value=300),
ev_max_charge_current=RationalNumber(exponent=3, value=40),
ev_max_voltage=RationalNumber(exponent=3, value=300),
ev_min_voltage=RationalNumber(exponent=3, value=300),
ev_target_energy_request=RationalNumber(exponent=1, value=20),
ev_max_energy_request=RationalNumber(exponent=1, value=20),
ev_min_energy_request=RationalNumber(exponent=0, value=20),
ev_max_charge_power=RationalNumber(exponent=2, value=40),
ev_min_charge_power=RationalNumber(exponent=1, value=40),
ev_max_charge_current=RationalNumber(exponent=0, value=40),
ev_max_voltage=RationalNumber(exponent=1, value=40),
ev_min_voltage=RationalNumber(exponent=0, value=40),
)

async def get_bpt_scheduled_dc_charge_loop_params(
Expand Down
84 changes: 41 additions & 43 deletions iso15118/secc/states/din_spec_states.py
Original file line number Diff line number Diff line change
Expand Up @@ -438,9 +438,8 @@ class CableCheck(StateSECC):

def __init__(self, comm_session: SECCCommunicationSession):
super().__init__(comm_session, Timeouts.V2G_SECC_SEQUENCE_TIMEOUT)
self.cable_check_req_was_received: bool = False
self.contactors_closed: bool = False
self.cable_check_started: bool = False
self.contactors_closed_for_cable_check: Optional[bool] = None

async def process_message(
self,
Expand Down Expand Up @@ -472,63 +471,62 @@ async def process_message(
evse_processing: EVSEProcessing = EVSEProcessing.ONGOING
response_code: ResponseCode = ResponseCode.OK
next_state = None
if not self.cable_check_req_was_received:
# Requirement in 6.4.3.106 of the IEC 61851-23
# Any relays in the DC output circuit of the DC station shall
# be closed during the insulation test
self.contactors_closed_for_cable_check = (
await self.comm_session.evse_controller.is_contactor_closed()
)
self.cable_check_req_was_received = True

if self.contactors_closed_for_cable_check is not None:
if not self.contactors_closed_for_cable_check:
if not self.cable_check_started:
await self.comm_session.evse_controller.start_cable_check()
self.cable_check_started = True

if self.contactors_closed:
isolation_level = (
await self.comm_session.evse_controller.get_cable_check_status()
) # noqa

evse_processing = EVSEProcessing.ONGOING
next_state = None
if isolation_level in [
IsolationLevel.VALID,
IsolationLevel.WARNING,
]:
if isolation_level == IsolationLevel.WARNING:
logger.warning(
"Isolation resistance measured by EVSE is in Warning-Range"
)
evse_processing = EVSEProcessing.FINISHED
next_state = PreCharge
elif isolation_level in [
IsolationLevel.FAULT,
IsolationLevel.INVALID,
]:
self.stop_state_machine(
"Contactor didnt close for Cable Check",
f"Isolation Failure: {isolation_level}",
message,
ResponseCode.FAILED,
)
return

if self.cable_check_started:
isolation_level = (
await self.comm_session.evse_controller.get_cable_check_status()
) # noqa

evse_processing = EVSEProcessing.ONGOING
next_state = None
if isolation_level in [
IsolationLevel.VALID,
IsolationLevel.WARNING,
]:
if isolation_level == IsolationLevel.WARNING:
logger.warning(
"Isolation resistance measured by EVSE is in Warning-Range"
)
evse_processing = EVSEProcessing.FINISHED
next_state = PreCharge
elif isolation_level in [
IsolationLevel.FAULT,
IsolationLevel.INVALID,
]:
else:
# Requirement in 6.4.3.106 of the IEC 61851-23
# Any relays in the DC output circuit of the DC station shall
# be closed during the insulation test
# If None is returned, then contactor close operation is ongoing.
contactors_closed_for_cable_check: Optional[
bool
] = await self.comm_session.evse_controller.is_contactor_closed()

if contactors_closed_for_cable_check is not None:
if contactors_closed_for_cable_check:
self.contactors_closed = True
else:
self.stop_state_machine(
f"Isolation Failure: {isolation_level}",
"Contactor didnt close for Cable Check",
message,
ResponseCode.FAILED,
)
return
else:
await self.comm_session.evse_controller.start_cable_check()
self.cable_check_started = True

self.comm_session.evse_controller.ev_data_context.present_soc = (
cable_check_req.dc_ev_status.ev_ress_soc
)

isolation_level = (
await self.comm_session.evse_controller.get_cable_check_status()
) # noqa

# [V2G-DC-418] Stay in CableCheck state until EVSEProcessing is complete.
# Until EVSEProcessing is completed, EV will send identical
# CableCheckReq message.
Expand Down
71 changes: 37 additions & 34 deletions iso15118/secc/states/iso15118_20_states.py
Original file line number Diff line number Diff line change
Expand Up @@ -1585,9 +1585,8 @@ class DCCableCheck(StateSECC):

def __init__(self, comm_session: SECCCommunicationSession):
super().__init__(comm_session, Timeouts.V2G_EVCC_COMMUNICATION_SETUP_TIMEOUT)
self.cable_check_req_was_received = False
self.contactors_closed = False
self.cable_check_started = False
self.contactors_closed_for_cable_check: Optional[bool] = None

async def process_message(
self,
Expand All @@ -1613,46 +1612,50 @@ async def process_message(
next_state = None
processing = EVSEProcessing.ONGOING

if not self.cable_check_req_was_received:
# Requirement in 6.4.3.106 of the IEC 61851-23
# Any relays in the DC output circuit of the DC station shall
# be closed during the insulation test
self.contactors_closed_for_cable_check = (
await self.comm_session.evse_controller.is_contactor_closed()
if not self.cable_check_started:
# Start cable check as contactors are now closed.
await self.comm_session.evse_controller.start_cable_check()
self.cable_check_started = True

if self.contactors_closed:
isolation_level = (
await self.comm_session.evse_controller.get_cable_check_status()
)
self.cable_check_req_was_received = True

if self.contactors_closed_for_cable_check is not None:
if not self.contactors_closed_for_cable_check:
if isolation_level in [IsolationLevel.VALID, IsolationLevel.WARNING]:
if isolation_level == IsolationLevel.WARNING:
logger.warning(
"Isolation resistance measured by EVSE is in Warning range"
)
next_state = DCPreCharge
processing = EVSEProcessing.FINISHED
elif isolation_level in [IsolationLevel.INVALID, IsolationLevel.FAULT]:
self.stop_state_machine(
"Contactor didnt close for Cable Check",
f"Isolation Failure: {isolation_level}",
message,
ResponseCode.FAILED,
)
return

if self.cable_check_started:
isolation_level = (
await self.comm_session.evse_controller.get_cable_check_status()
)

if isolation_level in [IsolationLevel.VALID, IsolationLevel.WARNING]:
if isolation_level == IsolationLevel.WARNING:
logger.warning(
"Isolation resistance measured by EVSE is in Warning range"
else:
if not self.contactors_closed:
# Requirement in 6.4.3.106 of the IEC 61851-23
# Any relays in the DC output circuit of the DC station shall
# be closed during the insulation test
# If None is returned, then contactor close operation is ongoing.
contactors_closed_for_cable_check: Optional[
bool
] = await self.comm_session.evse_controller.is_contactor_closed()

if contactors_closed_for_cable_check is not None:
if contactors_closed_for_cable_check:
self.contactors_closed = True
else:
self.stop_state_machine(
"Contactor didnt close for Cable Check",
message,
ResponseCode.FAILED,
)
next_state = DCPreCharge
processing = EVSEProcessing.FINISHED
elif isolation_level in [IsolationLevel.INVALID, IsolationLevel.FAULT]:
self.stop_state_machine(
f"Isolation Failure: {isolation_level}",
message,
ResponseCode.FAILED,
)
return
else:
await self.comm_session.evse_controller.start_cable_check()
self.cable_check_started = True
return

dc_cable_check_res = DCCableCheckRes(
header=MessageHeader(
Expand Down
79 changes: 40 additions & 39 deletions iso15118/secc/states/iso15118_2_states.py
Original file line number Diff line number Diff line change
Expand Up @@ -2186,9 +2186,8 @@ class CableCheck(StateSECC):

def __init__(self, comm_session: SECCCommunicationSession):
super().__init__(comm_session, Timeouts.V2G_SECC_SEQUENCE_TIMEOUT)
self.cable_check_req_was_received = False
self.cable_check_started = False
self.contactors_closed_for_cable_check: Optional[bool] = None
self.contactors_closed = False

async def process_message(
self,
Expand Down Expand Up @@ -2219,55 +2218,57 @@ async def process_message(
next_state = None
evse_processing = EVSEProcessing.ONGOING

if not self.cable_check_req_was_received:
# Requirement in 6.4.3.106 of the IEC 61851-23
# Any relays in the DC output circuit of the DC station shall
# be closed during the insulation test
self.contactors_closed_for_cable_check = (
await self.comm_session.evse_controller.is_contactor_closed()
)
self.cable_check_req_was_received = True
if not self.cable_check_started:
await self.comm_session.evse_controller.start_cable_check()
self.cable_check_started = True

if self.contactors_closed_for_cable_check is not None:
if not self.contactors_closed_for_cable_check:
if self.contactors_closed:
isolation_level = (
await self.comm_session.evse_controller.get_cable_check_status()
) # noqa

evse_processing = EVSEProcessing.ONGOING
next_state = None
if isolation_level in [
IsolationLevel.VALID,
IsolationLevel.WARNING,
]:
if isolation_level == IsolationLevel.WARNING:
logger.warning(
"Isolation resistance measured by EVSE is in Warning-Range"
)
evse_processing = EVSEProcessing.FINISHED
next_state = PreCharge
elif isolation_level in [
IsolationLevel.FAULT,
IsolationLevel.NO_IMD,
IsolationLevel.INVALID,
]:
self.stop_state_machine(
"Contactor didnt close for Cable Check",
f"Isolation Failure: {isolation_level}",
message,
ResponseCode.FAILED,
)
return
else:
# Requirement in 6.4.3.106 of the IEC 61851-23
# Any relays in the DC output circuit of the DC station shall
# be closed during the insulation test
# If None is returned, then contactor close operation is ongoing.
contactors_closed_for_cable_check = (
await self.comm_session.evse_controller.is_contactor_closed()
)

if self.cable_check_started:
isolation_level = (
await self.comm_session.evse_controller.get_cable_check_status()
) # noqa

evse_processing = EVSEProcessing.ONGOING
next_state = None
if isolation_level in [
IsolationLevel.VALID,
IsolationLevel.WARNING,
]:
if isolation_level == IsolationLevel.WARNING:
logger.warning(
"Isolation resistance measured by EVSE is in Warning-Range"
)
evse_processing = EVSEProcessing.FINISHED
next_state = PreCharge
elif isolation_level in [
IsolationLevel.FAULT,
IsolationLevel.NO_IMD,
IsolationLevel.INVALID,
]:
if contactors_closed_for_cable_check is not None:
if contactors_closed_for_cable_check:
self.contactors_closed = True
else:
self.stop_state_machine(
f"Isolation Failure: {isolation_level}",
"Contactor didnt close for Cable Check",
message,
ResponseCode.FAILED,
)
return
else:
await self.comm_session.evse_controller.start_cable_check()
self.cable_check_started = True

self.comm_session.evse_controller.ev_data_context.present_soc = (
cable_check_req.dc_ev_status.ev_ress_soc
Expand Down
Loading