Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
19 changes: 18 additions & 1 deletion lib/everest/iso15118/include/iso15118/d2/config.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,35 @@
#pragma once

#include <string>
#include <utility>

Check warning on line 6 in lib/everest/iso15118/include/iso15118/d2/config.hpp

View check run for this annotation

Codacy Production / Codacy Static Code Analysis

lib/everest/iso15118/include/iso15118/d2/config.hpp#L6

Include file: <utility> not found. Please note: Cppcheck does not need standard library headers to get proper results.
#include <vector>

Check warning on line 7 in lib/everest/iso15118/include/iso15118/d2/config.hpp

View check run for this annotation

Codacy Production / Codacy Static Code Analysis

lib/everest/iso15118/include/iso15118/d2/config.hpp#L7

Include file: <vector> not found. Please note: Cppcheck does not need standard library headers to get proper results.

#include <iso15118/message/d2/msg_data_types.hpp>

Check warning on line 9 in lib/everest/iso15118/include/iso15118/d2/config.hpp

View check run for this annotation

Codacy Production / Codacy Static Code Analysis

lib/everest/iso15118/include/iso15118/d2/config.hpp#L9

Include file: <iso15118/message/d2/msg_data_types.hpp> not found. Please note: Cppcheck does not need standard library headers to get proper results.

namespace iso15118::d2 {

namespace dt = msg::data_types;

struct EvseSetupConfig {
std::string evse_id;
dt::ChargeService charge_service;
std::vector<dt::PaymentOption> supported_payment_options;
dt::ServiceList offered_services;
};

// This should only have EVSE information
struct SessionConfig {
explicit SessionConfig(EvseSetupConfig config) : evse_id(std::move(config.evse_id)) {};
// TODO(kd) move the constructor to .cpp file
explicit SessionConfig(EvseSetupConfig config) :
evse_id(std::move(config.evse_id)),
charge_service(std::move(config.charge_service)),
supported_payment_options(std::move(config.supported_payment_options)),
offered_services(config.offered_services){};

std::string evse_id;
dt::ChargeService charge_service;
std::vector<dt::PaymentOption> supported_payment_options;
dt::ServiceList offered_services;
};

} // namespace iso15118::d2
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,6 @@
namespace iso15118::d2::msg {

namespace data_types {
enum class EnergyTransferMode {
AcSinglePhaseCore,
AcThreePhaseCore,
DcCore,
DcExtended,
DcComboCore,
DcUnique
};

enum class CostKind {
RelativePricePercentage,
RenewableGenerationPercentage,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,9 @@ using EVSEID = std::string; // Length: 7-37
using MeterReading = uint64_t; // Wh
using SigMeterReading = std::string; // base 64 binary, MaxLength: 64
using MeterStatus = int16_t;
using TMeter = int64_t; // Unix timestamp format
using TMeter = int64_t; // Unix timestamp format
using ServiceName = std::string; // MaxLength: 32
using ServiceScope = std::string; // MaxLength: 64

enum class ResponseCode {
OK,
Expand Down Expand Up @@ -72,6 +74,7 @@ enum class PaymentOption {
Contract,
ExternalPayment
};
using PaymentOptionList = std::vector<PaymentOption>; // [1 - 2]

enum class EvseProcessing {
Finished,
Expand Down Expand Up @@ -133,6 +136,38 @@ enum class IsolationLevel {
No_IMD
};

enum class ServiceCategory {
EvCharging,
Internet,
ContractCertificate,
OtherCustom
};

enum class EnergyTransferMode {
AC_single_phase_core,
AC_three_phase_core,
DC_core,
DC_extended,
DC_combo_core,
DC_unique
};
using SupportedEnergyTransferMode = std::vector<EnergyTransferMode>; // MaxLength: 6
constexpr auto SupportedEnergyTransferModeMaxLength = 6;

struct Service {
ServiceID service_id;
std::optional<ServiceName> service_name{std::nullopt};
ServiceCategory service_category;
std::optional<ServiceScope> service_scope{std::nullopt};
bool FreeService;
};
struct ChargeService : Service {
SupportedEnergyTransferMode supported_energy_transfer_mode;
};

using ServiceList = std::vector<Service>; // [1 - 8]
constexpr auto ServiceListMaxLength = 8;

struct MeterInfo {
MeterID meter_id;
std::optional<MeterReading> meter_reading{std::nullopt};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,44 +12,6 @@

namespace iso15118::d2::msg {

namespace data_types {
using ServiceName = std::string; // MaxLength: 32
using ServiceScope = std::string; // MaxLength: 64
using PaymentOptionList = std::vector<PaymentOption>; // [1 - 2]

enum class ServiceCategory {
EvCharging,
Internet,
ContractCertificate,
OtherCustom
};

enum class EnergyTransferMode {
AC_single_phase_core,
AC_three_phase_core,
DC_core,
DC_extended,
DC_combo_core,
DC_unique
};
using SupportedEnergyTransferMode = std::vector<EnergyTransferMode>; // MaxLength: 6
constexpr auto SupportedEnergyTransferModeMaxLength = 6;

struct Service {
ServiceID service_id;
std::optional<ServiceName> service_name{std::nullopt};
ServiceCategory service_category;
std::optional<ServiceScope> service_scope{std::nullopt};
bool FreeService;
};
using ServiceList = std::vector<Service>; // [1 - 8]
constexpr auto ServiceListMaxLength = 8;

struct ChargeService : Service {
SupportedEnergyTransferMode supported_energy_transfer_mode;
};
} // namespace data_types

struct ServiceDiscoveryRequest {
Header header;
std::optional<data_types::ServiceScope> service_scope{std::nullopt};
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,56 @@
// SPDX-License-Identifier: Apache-2.0
// Copyright 2026 Pionix GmbH and Contributors to EVerest
#include <iso15118/d2/state/service_discovery.hpp>
#include <iso15118/message/d2/service_discovery.hpp>

Check warning on line 4 in lib/everest/iso15118/src/iso15118/d2/state/service_discovery.cpp

View check run for this annotation

Codacy Production / Codacy Static Code Analysis

lib/everest/iso15118/src/iso15118/d2/state/service_discovery.cpp#L4

Include file: <iso15118/message/d2/service_discovery.hpp> not found. Please note: Cppcheck does not need standard library headers to get proper results.

#include <iso15118/detail/d2/context_helper.hpp>
#include <iso15118/detail/helper.hpp>
#include <optional>

Check warning on line 8 in lib/everest/iso15118/src/iso15118/d2/state/service_discovery.cpp

View check run for this annotation

Codacy Production / Codacy Static Code Analysis

lib/everest/iso15118/src/iso15118/d2/state/service_discovery.cpp#L8

Include file: <optional> not found. Please note: Cppcheck does not need standard library headers to get proper results.

namespace iso15118::d2::state {

namespace dt = d2::msg::data_types;

dt::ServiceList filter_services(const dt::ServiceList& offered_services, const std::optional<dt::ServiceScope>& scope,
const std::optional<dt::ServiceCategory>& category) {
dt::ServiceList filtered_services;

for (const auto& service : offered_services) {
if (scope.has_value() && service.service_scope != scope.value()) {
continue;
}
if (category.has_value() && service.service_category != category.value()) {
continue;
}
filtered_services.push_back(service);
}
return filtered_services;
}

d2::msg::ServiceDiscoveryResponse handle_request(const d2::msg::ServiceDiscoveryRequest& req, d2::Session& session,
const dt::ChargeService& charge_service,
const std::vector<dt::PaymentOption>& payment_options,
const dt::ServiceList& offered_services) {
d2::msg::ServiceDiscoveryResponse res;
setup_header(res.header, session);

res.charge_service = charge_service;
res.payment_option_list = payment_options;

if (!offered_services.empty()) {
dt::ServiceList services_to_offer;

if (req.service_category.has_value() || req.service_scope.has_value()) {
res.service_list = filter_services(offered_services, req.service_scope, req.service_category);
} else {
res.service_list = services_to_offer;
}
}

// [V2G2-545]
return response_with_code(res, dt::ResponseCode::OK);
}

void ServiceDiscovery::enter() {
// m_ctx.log.enter_state("ServiceDiscovery");
}
Expand All @@ -16,6 +60,34 @@
return {};
}

const auto variant = m_ctx.pull_request();

if (const auto req = variant->get_if<msg::ServiceDiscoveryRequest>()) {

const auto res =
handle_request(*req, m_ctx.session, m_ctx.session_config.charge_service,
m_ctx.session_config.supported_payment_options, m_ctx.session_config.offered_services);

m_ctx.respond(res);

if (res.response_code >= dt::ResponseCode::FAILED) {
// m_ctx.log("Error processing ServiceDiscoveryReq");
return {};
}

// TODO(kd): I wonder how to call the next state
// It waits either for ServiceDetailReq or ServicePaymentSelectionReq
// Perhaps PostServiceDiscovery?
return {};
}
// m_ctx.log("expected ServiceDiscoveryReq! But code type id: %d", variant->get_type());

// Sequence Error [V2G2-538]
const msg::Type req_type = variant->get_type();
send_sequence_error(req_type, m_ctx);

m_ctx.session_stopped = true;

return {};
}

Expand Down
Loading