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

Updates to store EV and EVSE limits shared in CPD and CL (-20 AC and DC). #279

Merged
merged 54 commits into from
Nov 5, 2023
Merged
Show file tree
Hide file tree
Changes from 53 commits
Commits
Show all changes
54 commits
Select commit Hold shift + click to select a range
1d7ac27
Store cpd params from EV.
shalinnijel2 Jul 21, 2023
947071d
Fixed flake8 errors.
shalinnijel2 Jul 21, 2023
1e314d9
Merge branch 'master' into dc_bpt_change
shalinnijel2 Jul 25, 2023
d84cfeb
Store ev limits shared during cl
shalinnijel2 Jul 26, 2023
478a02f
Added EVSEDataContext dataclass. Refactor.
shalinnijel2 Jul 27, 2023
00779c2
Added missed file
shalinnijel2 Jul 27, 2023
e92b3f0
Added tests for reading from evse_context during CPD.
shalinnijel2 Jul 27, 2023
c01213d
Fixed flake8 errors.
shalinnijel2 Jul 27, 2023
2040c63
Added tests for evse_context read.
shalinnijel2 Jul 28, 2023
f0f25a7
Fixed reading from wrong field
shalinnijel2 Jul 31, 2023
838b25e
Merge branch 'master' into dc_bpt_change
shalinnijel2 Jul 31, 2023
9e2efac
Fixed black errors
shalinnijel2 Jul 31, 2023
5d6ab9d
Undo changes to ev simulator
shalinnijel2 Jul 31, 2023
3914831
Merge branch 'master' into dc_bpt_change
shalinnijel2 Aug 1, 2023
d0350c5
Updated send_charging_command to accept RationalNumber
shalinnijel2 Aug 2, 2023
1a788ef
Updated send_charging_command signature to include discharge
shalinnijel2 Aug 3, 2023
6a4dcab
Updated description
shalinnijel2 Aug 3, 2023
f8691f9
Fixed failed tests
shalinnijel2 Aug 3, 2023
ae7950d
Removed duplicates in ev_data context
shalinnijel2 Aug 3, 2023
f9eeb05
Merge branch 'master' into dc_bpt_change
shalinnijel2 Aug 4, 2023
39e5297
Added comment to clarify
shalinnijel2 Aug 4, 2023
b6cfe16
Merge branch 'master' into dc_bpt_change
shalinnijel2 Aug 22, 2023
378ba02
Merge branch 'master' into dc_bpt_change
shalinnijel2 Aug 23, 2023
f60d01b
Merge branch 'master' into dc_bpt_change
shalinnijel2 Sep 12, 2023
afc9737
Fixed failing test
shalinnijel2 Sep 12, 2023
b3a0351
Fixed mypy tests
shalinnijel2 Sep 12, 2023
0b18e41
Fix mypy tests
shalinnijel2 Sep 12, 2023
7809356
store current voltage and current in evse_data_context
shalinnijel2 Sep 14, 2023
b83261e
Fixed flake8 error
shalinnijel2 Sep 14, 2023
49b2c7f
Merge branch 'master' into dc_bpt_change
shalinnijel2 Sep 14, 2023
6ae4604
Refactored evse_data to split cl and cpd params
shalinnijel2 Sep 29, 2023
1f8adfe
Fixed flake8 errors
shalinnijel2 Sep 29, 2023
9a20a13
Merge branch 'master' into dc_bpt_change
shalinnijel2 Sep 29, 2023
a454f43
Refactored evse_data further to bpt and non-bpt types
shalinnijel2 Oct 2, 2023
095c1b4
Merge branch 'dc_bpt_change' of https://github.com/SwitchEV/iso15118 …
shalinnijel2 Oct 2, 2023
0cc6419
Fixed flake8 errors
shalinnijel2 Oct 2, 2023
b1dcc5e
Moved simulated context to simulator
shalinnijel2 Oct 3, 2023
cfb2d61
Removed cl related fields from evse rated limits
shalinnijel2 Oct 3, 2023
a86ccef
Updated comment
shalinnijel2 Oct 12, 2023
2384f8d
Updated ev_data_context to inherit from a common Limits base class
shalinnijel2 Oct 19, 2023
dee882a
Fixed flake8 issue
shalinnijel2 Oct 19, 2023
64952dd
Changes based on review
shalinnijel2 Oct 20, 2023
d0b4653
Merge branch 'master' into dc_bpt_change
shalinnijel2 Oct 20, 2023
182aaef
Merge branch 'master' into dc_bpt_change
shalinnijel2 Oct 22, 2023
8786010
Merge branch 'master' into dc_bpt_change
shalinnijel2 Oct 25, 2023
be4e0bf
Fixed conflicts
shalinnijel2 Oct 25, 2023
3818928
Refactored EV context data
shalinnijel2 Oct 27, 2023
1072362
Merge branch 'master' into dc_bpt_change
shalinnijel2 Oct 27, 2023
91c5b56
Merge branch 'master' into dc_bpt_change
shalinnijel2 Oct 27, 2023
926b57b
Merge branch 'master' into dc_bpt_change
shalinnijel2 Nov 2, 2023
9903de3
Updated dataclasses to include CPD where required and added descriptions
shalinnijel2 Nov 2, 2023
6a2a591
Addressed comments on PR.
shalinnijel2 Nov 2, 2023
f1a0cb8
Merge branch 'master' into dc_bpt_change
shalinnijel2 Nov 2, 2023
7fb4857
Wrap sending_power_limits in a try catch
shalinnijel2 Nov 4, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 2 additions & 5 deletions iso15118/secc/comm_session_handler.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,8 @@
from asyncio.streams import StreamReader, StreamWriter
from typing import Any, Coroutine, Dict, List, Optional, Tuple, Union

from iso15118.secc.controller.interface import (
EVSEControllerInterface,
EVSessionContext15118,
ServiceStatus,
)
from iso15118.secc.controller.ev_data import EVSessionContext15118
from iso15118.secc.controller.interface import EVSEControllerInterface, ServiceStatus
from iso15118.secc.failed_responses import (
init_failed_responses_din_spec_70121,
init_failed_responses_iso_v2,
Expand Down
19 changes: 19 additions & 0 deletions iso15118/secc/controller/common.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
from abc import ABC


class Limits(ABC):
def update(
self,
params: dict,
):
updated_params = {}
for k, v in params.items():
if type(v) is dict:
updated_params.update({k: v["value"] * 10 ** v["exponent"]})
elif type(v) in [int, float]:
updated_params.update({k: v})

self.__dict__.update(updated_params)

def as_dict(self):
return self.__dict__
187 changes: 187 additions & 0 deletions iso15118/secc/controller/ev_data.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,187 @@
from dataclasses import dataclass
from typing import List, Optional, Union

from iso15118.secc.controller.common import Limits
from iso15118.shared.messages.datatypes import (
PVEAmount,
PVEVEnergyRequest,
PVEVMaxCurrent,
PVEVMaxCurrentLimit,
PVEVMaxPowerLimit,
PVEVMaxVoltage,
PVEVMaxVoltageLimit,
)
from iso15118.shared.messages.enums import AuthEnum
from iso15118.shared.messages.iso15118_2.datatypes import ChargeService


@dataclass
class EVACCPDLimits(Limits):
"""Holds the AC limits shared by the EV during ChargeParameterDiscovery"""

ev_max_charge_power: Optional[float] = 0.0
ev_max_charge_power_l2: Optional[float] = None
ev_max_charge_power_l3: Optional[float] = None

ev_min_charge_power: Optional[float] = 0.0
ev_min_charge_power_l2: Optional[float] = None
ev_min_charge_power_l3: Optional[float] = None

ev_max_discharge_power: Optional[float] = None
ev_max_discharge_power_l2: Optional[float] = None
ev_max_discharge_power_l3: Optional[float] = None
ev_min_discharge_power: Optional[float] = None
ev_min_discharge_power_l2: Optional[float] = None
ev_min_discharge_power_l3: Optional[float] = None


@dataclass
class EVDCCPDLimits(Limits):
"""Holds the DC limits shared by the EV during ChargeParameterDiscovery"""

ev_max_charge_power: Optional[float] = 0.0
ev_min_charge_power: Optional[float] = 0.0
ev_max_charge_current: Optional[float] = None
ev_min_charge_current: Optional[float] = None
ev_max_voltage: Optional[float] = None
ev_min_voltage: Optional[float] = None
target_soc: Optional[int] = None

ev_max_discharge_power: Optional[float] = None
ev_min_discharge_power: Optional[float] = None
ev_max_discharge_current: Optional[float] = None
ev_min_discharge_current: Optional[float] = None
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes, sorry, I meant to add in a review and not as single comment and I deleted my comment when I realized I was wrong



@dataclass
class EVRatedLimits(Limits):
def __init__(
self,
ac_limits: Optional[EVACCPDLimits] = None,
dc_limits: Optional[EVDCCPDLimits] = None,
):
self.ac_limits = ac_limits or EVACCPDLimits()
self.dc_limits = dc_limits or EVDCCPDLimits()


@dataclass
class EVACCLLimits(Limits):
"""Holds the AC limits shared by the EV during ChargingLoop.
Unlike the CPD values, these could potentially change during charing loop"""

departure_time: Optional[int] = None
ev_target_energy_request: Optional[float] = None
ev_max_energy_request: Optional[float] = None
ev_min_energy_request: Optional[float] = None

ev_max_charge_power: Optional[float] = None
ev_max_charge_power_l2: Optional[float] = None
ev_max_charge_power_l3: Optional[float] = None

ev_min_charge_power: Optional[float] = None
ev_min_charge_power_l2: Optional[float] = None
ev_min_charge_power_l3: Optional[float] = None

ev_present_active_power: Optional[float] = None
ev_present_active_power_l2: Optional[float] = None
ev_present_active_power_l3: Optional[float] = None

ev_present_reactive_power: Optional[float] = None
ev_present_reactive_power_l2: Optional[float] = None
ev_present_reactive_power_l3: Optional[float] = None

ev_max_discharge_power: Optional[float] = None
ev_max_discharge_power_l2: Optional[float] = None
ev_max_discharge_power_l3: Optional[float] = None

ev_min_discharge_power: Optional[float] = None
ev_min_discharge_power_l2: Optional[float] = None
ev_min_discharge_power_l3: Optional[float] = None

ev_max_v2x_energy_request: Optional[float] = None
ev_min_v2x_energy_request: Optional[float] = None


@dataclass
class EVDCCLLimits(Limits):
"""Holds the DC limits shared by the EV during ChargingLoop.
Unlike the CPD values, these could potentially change during charging loop"""

departure_time: Optional[int] = None
ev_target_energy_request: Optional[float] = None

ev_target_current: float = 0.0
ev_target_voltage: float = 0.0
ev_max_charge_power: Optional[float] = None
tropxy marked this conversation as resolved.
Show resolved Hide resolved
ev_min_charge_power: Optional[float] = None
tropxy marked this conversation as resolved.
Show resolved Hide resolved
ev_max_charge_current: Optional[float] = None
tropxy marked this conversation as resolved.
Show resolved Hide resolved
ev_max_voltage: Optional[float] = None
ev_min_voltage: Optional[float] = None

ev_max_discharge_power: Optional[float] = None
ev_min_discharge_power: Optional[float] = None
ev_max_discharge_current: Optional[float] = None

ev_max_energy_request: Optional[float] = None
ev_min_energy_request: Optional[float] = None

ev_max_v2x_energy_request: Optional[float] = None
ev_min_v2x_energy_request: Optional[float] = None


@dataclass
class EVSessionContext(Limits):
def __init__(
self,
ac_limits: Optional[EVACCLLimits] = None,
dc_limits: Optional[EVDCCLLimits] = None,
):
self.ac_limits = ac_limits or EVACCLLimits()
self.dc_limits = dc_limits or EVDCCLLimits()

dc_current_request: Optional[int] = None
dc_voltage_request: Optional[int] = None
ac_current: Optional[dict] = None # {"l1": 10, "l2": 10, "l3": 10}
ac_voltage: Optional[dict] = None # {"l1": 230, "l2": 230, "l3": 230}
soc: Optional[int] = None # 0-100

remaining_time_to_full_soc_s: Optional[float] = None
remaining_time_to_bulk_soc_s: Optional[float] = None


@dataclass
class EVDataContext:
def __init__(
self,
evcc_id: Optional[str] = None,
ev_rated_limits: Optional[EVRatedLimits] = None,
ev_session_context: Optional[EVSessionContext] = None,
):
self.evcc_id = evcc_id or None
self.ev_rated_limits = ev_rated_limits or EVRatedLimits()
self.ev_session_context = ev_session_context or EVSessionContext()


@dataclass
class EVChargeParamsLimits:
ev_max_voltage: Optional[Union[PVEVMaxVoltageLimit, PVEVMaxVoltage]] = None
ev_max_current: Optional[Union[PVEVMaxCurrentLimit, PVEVMaxCurrent]] = None
ev_max_power: Optional[PVEVMaxPowerLimit] = None
e_amount: Optional[PVEAmount] = None
ev_energy_request: Optional[PVEVEnergyRequest] = None
tropxy marked this conversation as resolved.
Show resolved Hide resolved


@dataclass
class EVSessionContext15118:
# EVSessionContext15118 holds information required to resume a paused session.
# [V2G2-741] - In a resumed session, the following are reused:
# 1. SessionID (SessionSetup)
# 2. PaymentOption that was previously selected (ServiceDiscoveryRes)
# 3. ChargeService (ServiceDiscoveryRes)
# 4. SAScheduleTuple (ChargeParameterDiscoveryRes) -
# Previously selected id must remain the same.
# However, the entries could reflect the elapsed time
session_id: Optional[str] = None
auth_options: Optional[List[AuthEnum]] = None
charge_service: Optional[ChargeService] = None
sa_schedule_tuple_id: Optional[int] = None
138 changes: 138 additions & 0 deletions iso15118/secc/controller/evse_data.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
from dataclasses import dataclass
from typing import Optional, Union

from iso15118.secc.controller.common import Limits


@dataclass
class EVSEACCPDLimits(Limits):
"""Holds the EVSE's rated AC limits to be returned during
Charge Parameter Discovery state."""

# 15118-2 AC CPD
evse_nominal_voltage: Optional[float] = None # Also required for 15118-20 CPD
evse_max_current: Optional[float] = None # Required

# 15118-20 AC CPD (Required)
evse_max_charge_power: Optional[float] = None
evse_min_charge_power: Optional[float] = None

# 15118-20 AC CPD (Optional)
evse_max_charge_power_l2: Optional[float] = None
evse_max_charge_power_l3: Optional[float] = None
evse_min_charge_power_l2: Optional[float] = None
evse_min_charge_power_l3: Optional[float] = None
evse_nominal_frequency: Optional[float] = None
max_power_asymmetry: Optional[float] = None
evse_power_ramp_limit: Optional[float] = None

evse_present_active_power: Optional[float] = None # Optional in AC Scheduled CL
evse_present_active_power_l2: Optional[float] = None # Optional in AC Scheduled CL
evse_present_active_power_l3: Optional[float] = None # Optional in AC Scheduled CL


@dataclass
class EVSEACBPTCPDLimits(EVSEACCPDLimits):
"""Holds the EVSE's rated AC BPT limits to be returned during
Charge Parameter Discovery state."""

evse_max_discharge_power: Optional[float] = None # Required
evse_max_discharge_power_l2: Optional[float] = None # Optional
evse_max_discharge_power_l3: Optional[float] = None # Optional

evse_min_discharge_power: Optional[float] = None # Required
evse_min_discharge_power_l2: Optional[float] = None # Optional
evse_min_discharge_power_l3: Optional[float] = None # Optional


@dataclass
class EVSEDCBPTCPDLimits(Limits):
"""Holds the EVSE's rated DC BPT limits to be returned during
Charge Parameter Discovery state."""

# Required in 15118-20 DC BPT CPD
evse_max_discharge_power: Optional[float] = None
evse_min_discharge_power: Optional[float] = None
evse_max_discharge_current: Optional[float] = None
evse_min_discharge_current: Optional[float] = None


@dataclass
class EVSEDCCPDLimits(EVSEDCBPTCPDLimits):
"""Holds the EVSE's rated DC limits to be returned during
Charge Parameter Discovery state."""

# Required in 15118-20 DC CPD
evse_max_charge_power: Optional[float] = None # Required for -2 DC, DIN CPD
evse_min_charge_power: Optional[float] = None # Not Required for -2 DC, DIN CPD
evse_max_charge_current: Optional[float] = None # Required for -2 DC, DIN CPD
evse_min_charge_current: Optional[float] = None # Required for -2 DC, DIN CPD
evse_max_voltage: Optional[float] = None # Required for -2 DC, DIN CPD
evse_min_voltage: Optional[float] = None # Required for -2 DC, DIN CPD

# Optional in 15118-20 DC CPD
evse_power_ramp_limit: Optional[float] = None

# Optional in 15118-2 CPD
evse_current_regulation_tolerance: Optional[float] = None
evse_peak_current_ripple: Optional[float] = None
evse_energy_to_be_delivered: Optional[float] = None


@dataclass
class EVSERatedLimits:
ac_limits: Optional[EVSEACCPDLimits] = None
ac_bpt_limits: Optional[EVSEACBPTCPDLimits] = None
dc_limits: Optional[EVSEDCCPDLimits] = None
dc_bpt_limits: Optional[EVSEDCBPTCPDLimits] = None


@dataclass
class EVSEACCLLimits(Limits):
# Optional in both Scheduled and Dynamic CL (both AC CL and BPT AC CL)
evse_target_active_power: Optional[float] = None # Required in Dynamic AC CL
evse_target_active_power_l2: Optional[float] = None
evse_target_active_power_l3: Optional[float] = None
evse_target_reactive_power: Optional[float] = None
evse_target_reactive_power_l2: Optional[float] = None
evse_target_reactive_power_l3: Optional[float] = None
evse_present_active_power: Optional[float] = None # Optional in AC CPD
evse_present_active_power_l2: Optional[float] = None # Optional in AC CPD
evse_present_active_power_l3: Optional[float] = None # Optional in AC CPD


@dataclass
class EVSEDCCLLimits(Limits):
# Optional in 15118-20 DC Scheduled CL
evse_max_charge_power: Optional[float] = None # Required in 15118-20 Dynamic CL
evse_min_charge_power: Optional[float] = None # Required in 15118-20 Dynamic CL
evse_max_charge_current: Optional[float] = None # Required in 15118-20 Dynamic CL
evse_max_voltage: Optional[float] = None # Required in 15118-20 Dynamic CL

# Optional and present in 15118-20 DC BPT CL (Scheduled)
evse_max_discharge_power: Optional[float] = None # Req in 15118-20 Dynamic BPT CL
evse_min_discharge_power: Optional[float] = None # Req in 15118-20 Dynamic BPT CL
evse_max_discharge_current: Optional[float] = None # Req in 15118-20 Dynamic BPT CL
evse_min_voltage: Optional[float] = None # Required in 15118-20 Dynamic BPT CL


@dataclass
class EVSESessionContext:
# Optional in -20 Dynamic CL Res
ev_departure_time: Optional[int] = None
ev_min_soc: Optional[int] = None
ev_target_soc: Optional[int] = None
ack_max_delay: Optional[int] = None

# Required for -2 DC CurrentDemand, -20 DC CL
evse_present_current: Union[float, int] = 0
evse_present_voltage: Union[float, int] = 0

ac_limits: Optional[EVSEACCLLimits] = None
dc_limits: Optional[EVSEDCCLLimits] = None


@dataclass
class EVSEDataContext:
rated_limits: Optional[EVSERatedLimits] = None
session_context: Optional[EVSESessionContext] = None
Loading