Skip to content

Commit c8d3f9a

Browse files
authored
Feature/notify ev charging needs (#93)
* Added base params for notify_ev_charging_needs * Added feedback with DC limits * Updated for ev/evse types and added a special context struct that holds all car-provided (EV) data * Added EV Control Mode * Updated for comments * Bump version --------- Signed-off-by: AssemblyJohn <ioan.bogdann@gmail.com>
1 parent 3f9cc0b commit c8d3f9a

File tree

8 files changed

+84
-15
lines changed

8 files changed

+84
-15
lines changed

CMakeLists.txt

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
cmake_minimum_required(VERSION 3.14)
22

33
project(iso15118
4-
VERSION 0.5.0
4+
VERSION 0.5.1
55
DESCRIPTION "iso15118 library suite"
66
LANGUAGES CXX C
77
)

include/iso15118/d20/config.hpp

+1
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ struct EvseSetupConfig {
2525
std::vector<ControlMobilityNeedsModes> control_mobility_modes;
2626
};
2727

28+
// This should only have EVSE information
2829
struct SessionConfig {
2930
explicit SessionConfig(EvseSetupConfig);
3031

include/iso15118/d20/context.hpp

+4
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414

1515
#include "config.hpp"
1616
#include "control_event.hpp"
17+
#include "ev_session_info.hpp"
1718
#include "session.hpp"
1819

1920
namespace iso15118::d20 {
@@ -96,6 +97,9 @@ class Context {
9697

9798
SessionConfig session_config;
9899

100+
// Contains the EV received data
101+
EVSessionInfo session_ev_info;
102+
99103
bool session_stopped{false};
100104

101105
private:
+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
// SPDX-License-Identifier: Apache-2.0
2+
// Copyright 2025 Pionix GmbH and Contributors to EVerest
3+
#pragma once
4+
5+
#include <iso15118/session/feedback.hpp>
6+
7+
namespace iso15118::d20 {
8+
9+
// Holds information reported by the EV
10+
struct EVSessionInfo {
11+
session::feedback::EvTransferLimits ev_transfer_limits;
12+
session::feedback::EvSEControlMode ev_control_mode;
13+
};
14+
15+
} // namespace iso15118::d20

include/iso15118/session/feedback.hpp

+25-6
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,16 @@
88
#include <string>
99
#include <variant>
1010

11+
#include <iso15118/d20/limits.hpp>
1112
#include <iso15118/message/dc_charge_loop.hpp>
13+
#include <iso15118/message/dc_charge_parameter_discovery.hpp>
14+
#include <iso15118/message/schedule_exchange.hpp>
1215
#include <iso15118/message/type.hpp>
1316

1417
namespace iso15118::session {
1518

19+
namespace dt = message_20::datatypes;
20+
1621
namespace feedback {
1722

1823
enum class Signal {
@@ -34,14 +39,18 @@ struct DcMaximumLimits {
3439
float power{NAN};
3540
};
3641

37-
using PresentVoltage = message_20::datatypes::RationalNumber;
42+
using PresentVoltage = dt::RationalNumber;
3843
using MeterInfoRequested = bool;
39-
using DcReqControlMode = std::variant<
40-
message_20::datatypes::Scheduled_DC_CLReqControlMode, message_20::datatypes::BPT_Scheduled_DC_CLReqControlMode,
41-
message_20::datatypes::Dynamic_DC_CLReqControlMode, message_20::datatypes::BPT_Dynamic_DC_CLReqControlMode>;
44+
using DcReqControlMode = std::variant<dt::Scheduled_DC_CLReqControlMode, dt::BPT_Scheduled_DC_CLReqControlMode,
45+
dt::Dynamic_DC_CLReqControlMode, dt::BPT_Dynamic_DC_CLReqControlMode>;
46+
47+
using DcChargeLoopReq = std::variant<DcReqControlMode, dt::DisplayParameters, PresentVoltage, MeterInfoRequested>;
48+
49+
// TODO(ioan): preparation for AC limits
50+
using EvseTransferLimits = std::variant<d20::DcTransferLimits>;
4251

43-
using DcChargeLoopReq =
44-
std::variant<DcReqControlMode, message_20::datatypes::DisplayParameters, PresentVoltage, MeterInfoRequested>;
52+
using EvTransferLimits = std::variant<dt::DC_CPDReqEnergyTransferMode, dt::BPT_DC_CPDReqEnergyTransferMode>;
53+
using EvSEControlMode = std::variant<dt::Dynamic_SEReqControlMode, dt::Scheduled_SEReqControlMode>;
4554

4655
struct Callbacks {
4756
std::function<void(Signal)> signal;
@@ -51,6 +60,11 @@ struct Callbacks {
5160
std::function<void(const message_20::Type&)> v2g_message;
5261
std::function<void(const std::string&)> evccid;
5362
std::function<void(const std::string&)> selected_protocol;
63+
64+
std::function<void(const dt::ServiceCategory&, const std::optional<dt::AcConnector>&, const dt::ControlMode&,
65+
const dt::MobilityNeedsMode&, const EvseTransferLimits&, const EvTransferLimits&,
66+
const EvSEControlMode&)>
67+
notify_ev_charging_needs;
5468
};
5569

5670
} // namespace feedback
@@ -67,6 +81,11 @@ class Feedback {
6781
void evcc_id(const std::string&) const;
6882
void selected_protocol(const std::string&) const;
6983

84+
void notify_ev_charging_needs(const dt::ServiceCategory&, const std::optional<dt::AcConnector>&,
85+
const dt::ControlMode&, const dt::MobilityNeedsMode&,
86+
const feedback::EvseTransferLimits&, const feedback::EvTransferLimits&,
87+
const feedback::EvSEControlMode&) const;
88+
7089
private:
7190
feedback::Callbacks callbacks;
7291
};

src/iso15118/d20/state/dc_charge_parameter_discovery.cpp

+7-7
Original file line numberDiff line numberDiff line change
@@ -31,13 +31,7 @@ template <> void convert(DC_ModeRes& out, const d20::DcTransferLimits& in) {
3131
}
3232

3333
template <> void convert(BPT_DC_ModeRes& out, const d20::DcTransferLimits& in) {
34-
out.max_charge_power = in.charge_limits.power.max;
35-
out.min_charge_power = in.charge_limits.power.min;
36-
out.max_charge_current = in.charge_limits.current.max;
37-
out.min_charge_current = in.charge_limits.current.min;
38-
out.max_voltage = in.voltage.max;
39-
out.min_voltage = in.voltage.min;
40-
out.power_ramp_limit = in.power_ramp_limit;
34+
convert(static_cast<DC_ModeRes&>(out), in);
4135

4236
if (in.discharge_limits.has_value()) {
4337
auto& discharge_limits = in.discharge_limits.value();
@@ -111,13 +105,19 @@ Result DC_ChargeParameterDiscovery::feed(Event ev) {
111105
dc_max_limits.power = dt::from_RationalNumber(mode->max_charge_power);
112106

113107
logf_info("Max charge current %fA", dt::from_RationalNumber(mode->max_charge_current));
108+
109+
// Set EV transfer limits
110+
m_ctx.session_ev_info.ev_transfer_limits.emplace<DC_ModeReq>(*mode);
114111
} else if (const auto* mode = std::get_if<BPT_DC_ModeReq>(&req->transfer_mode)) {
115112
dc_max_limits.current = dt::from_RationalNumber(mode->max_charge_current);
116113
dc_max_limits.voltage = dt::from_RationalNumber(mode->max_voltage);
117114
dc_max_limits.power = dt::from_RationalNumber(mode->max_charge_power);
118115

119116
logf_info("Max charge current %fA", dt::from_RationalNumber(mode->max_charge_current));
120117
logf_info("Max discharge current %fA", dt::from_RationalNumber(mode->max_discharge_current));
118+
119+
// Set EV transfer limits
120+
m_ctx.session_ev_info.ev_transfer_limits.emplace<BPT_DC_ModeReq>(*mode);
121121
}
122122

123123
const auto res = handle_request(*req, m_ctx.session, m_ctx.session_config.dc_limits);

src/iso15118/d20/state/schedule_exchange.cpp

+20-1
Original file line numberDiff line numberDiff line change
@@ -128,13 +128,32 @@ Result ScheduleExchange::feed(Event ev) {
128128

129129
dt::RationalNumber max_charge_power = {0, 0};
130130

131-
const auto selected_energy_service = m_ctx.session.get_selected_services().selected_energy_service;
131+
const auto& selected_services = m_ctx.session.get_selected_services();
132+
const auto selected_energy_service = selected_services.selected_energy_service;
132133

133134
if (selected_energy_service == dt::ServiceCategory::DC or
134135
selected_energy_service == dt::ServiceCategory::DC_BPT) {
135136
max_charge_power = m_ctx.session_config.dc_limits.charge_limits.power.max;
136137
}
137138

139+
// We will pass the raw data to the listener, the
140+
// listener will construct the full required type
141+
std::optional<dt::AcConnector> ac_connector{};
142+
if (std::holds_alternative<dt::AcConnector>(selected_services.selected_connector)) {
143+
ac_connector = std::get<dt::AcConnector>(selected_services.selected_connector);
144+
}
145+
146+
// TODO(ioan): prepare for AC transfer limits
147+
const session::feedback::EvseTransferLimits& evse_limits = m_ctx.session_config.dc_limits;
148+
const session::feedback::EvTransferLimits& ev_limits = m_ctx.session_ev_info.ev_transfer_limits;
149+
150+
const auto& control_mode = req->control_mode;
151+
152+
// Send the charging feedback
153+
m_ctx.feedback.notify_ev_charging_needs(
154+
selected_energy_service, ac_connector, selected_services.selected_control_mode,
155+
selected_services.selected_mobility_needs_mode, evse_limits, ev_limits, control_mode);
156+
138157
const auto res = handle_request(*req, m_ctx.session, max_charge_power, dynamic_parameters);
139158

140159
m_ctx.respond(res);

src/iso15118/session/feedback.cpp

+11
Original file line numberDiff line numberDiff line change
@@ -37,4 +37,15 @@ void Feedback::selected_protocol(const std::string& selected_protocol) const {
3737
call_if_available(callbacks.selected_protocol, selected_protocol);
3838
}
3939

40+
void Feedback::notify_ev_charging_needs(const dt::ServiceCategory& service_category,
41+
const std::optional<dt::AcConnector>& ac_connector,
42+
const dt::ControlMode& control_mode,
43+
const dt::MobilityNeedsMode& mobility_needs_mode,
44+
const feedback::EvseTransferLimits& evse_limits,
45+
const feedback::EvTransferLimits& ev_limits,
46+
const feedback::EvSEControlMode& ev_control_mode) const {
47+
call_if_available(callbacks.notify_ev_charging_needs, service_category, ac_connector, control_mode,
48+
mobility_needs_mode, evse_limits, ev_limits, ev_control_mode);
49+
}
50+
4051
} // namespace iso15118::session

0 commit comments

Comments
 (0)