Skip to content

Commit

Permalink
Merge branch 'main' into tm-adding-yeti-simulator
Browse files Browse the repository at this point in the history
  • Loading branch information
MarzellT authored Sep 11, 2024
2 parents e9de9bc + cd1f60a commit b1b9863
Show file tree
Hide file tree
Showing 11 changed files with 180 additions and 12 deletions.
5 changes: 5 additions & 0 deletions config/config-sil-ocpp.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ active_modules:
ac_hlc_use_5percent: false
ac_enforce_hlc: false
external_ready_to_start_charging: true
request_zero_power_in_idle: true
connections:
bsp:
- module_id: yeti_driver_1
Expand Down Expand Up @@ -57,6 +58,7 @@ active_modules:
ac_hlc_use_5percent: false
ac_enforce_hlc: false
external_ready_to_start_charging: true
request_zero_power_in_idle: true
connections:
bsp:
- module_id: yeti_driver_2
Expand Down Expand Up @@ -159,6 +161,9 @@ active_modules:
display_message:
- module_id: display_message
implementation_id: display_message
connector_zero_sink:
- module_id: grid_connection_point
implementation_id: external_limits
display_message:
module: TerminalCostAndPriceMessage
connections:
Expand Down
5 changes: 5 additions & 0 deletions config/config-sil-ocpp201.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ active_modules:
ac_hlc_enabled: false
ac_hlc_use_5percent: false
ac_enforce_hlc: false
request_zero_power_in_idle: true
connections:
bsp:
- module_id: yeti_driver_1
Expand All @@ -50,6 +51,7 @@ active_modules:
ac_hlc_enabled: false
ac_hlc_use_5percent: false
ac_enforce_hlc: false
request_zero_power_in_idle: true
connections:
bsp:
- module_id: yeti_driver_2
Expand Down Expand Up @@ -125,6 +127,9 @@ active_modules:
security:
- module_id: evse_security
implementation_id: main
connector_zero_sink:
- module_id: grid_connection_point
implementation_id: external_limits
persistent_store:
module: PersistentStore
evse_security:
Expand Down
2 changes: 1 addition & 1 deletion dependencies.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ libevse-security:
# OCPP
libocpp:
git: https://github.com/EVerest/libocpp.git
git_tag: 3fef09231f0033a4af5d0af97d35851ecc00d399
git_tag: 4a62b490fb89efd9c2f36d21d7949ee273d2c8b9
cmake_condition: "EVEREST_DEPENDENCY_ENABLED_LIBOCPP"
# Josev
Josev:
Expand Down
2 changes: 1 addition & 1 deletion modules/OCPP/OCPP.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ void OCPP::publish_charging_schedules(
types::ocpp::ChargingSchedules schedules;
for (const auto& charging_schedule : charging_schedules) {
types::ocpp::ChargingSchedule sch = conversions::to_charging_schedule(charging_schedule.second);
sch.connector = charging_schedule.first;
sch.evse = charging_schedule.first;
schedules.schedules.emplace_back(std::move(sch));
}
this->p_ocpp_generic->publish_charging_schedules(schedules);
Expand Down
1 change: 0 additions & 1 deletion modules/OCPP/conversions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -418,7 +418,6 @@ types::ocpp::ChargingSchedule to_charging_schedule(const ocpp::v16::EnhancedChar
0,
ocpp::v16::conversions::charging_rate_unit_to_string(schedule.chargingRateUnit),
{},
std::nullopt,
schedule.duration,
std::nullopt,
schedule.minChargingRate};
Expand Down
81 changes: 78 additions & 3 deletions modules/OCPP201/OCPP201.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -235,6 +235,16 @@ std::optional<ocpp::v201::IdToken> get_authorized_id_token(const types::evse_man
return std::nullopt;
}

ocpp::v201::ChargingRateUnitEnum get_unit_or_default(const std::string& unit_string) {
try {
return ocpp::v201::conversions::string_to_charging_rate_unit_enum(unit_string);
} catch (const std::out_of_range& e) {
EVLOG_warning << "RequestCompositeScheduleUnit configured incorrectly with: " << unit_string
<< ". Defaulting to using Amps.";
return ocpp::v201::ChargingRateUnitEnum::A;
}
}

bool OCPP201::all_evse_ready() {
for (auto const& [evse, ready] : this->evse_ready_map) {
if (!ready) {
Expand Down Expand Up @@ -522,11 +532,19 @@ void OCPP201::ready() {
this->p_ocpp_generic->publish_security_event(event);
};

callbacks.set_charging_profiles_callback = [this]() {
// TODO: implement once charging profiles are available in libocpp
return;
const auto composite_schedule_unit = get_unit_or_default(this->config.RequestCompositeScheduleUnit);

// this callback publishes the schedules within EVerest and applies the schedules for the individual evse_manager(s)
// and the connector_zero_sink
const auto charging_schedules_callback = [this, composite_schedule_unit]() {
const auto composite_schedules = this->charge_point->get_all_composite_schedules(
this->config.RequestCompositeScheduleDurationS, composite_schedule_unit);
this->publish_charging_schedules(composite_schedules);
this->set_external_limits(composite_schedules);
};

callbacks.set_charging_profiles_callback = charging_schedules_callback;

const auto sql_init_path = this->ocpp_share_path / SQL_CORE_MIGRATIONS;

std::map<int32_t, int32_t> evse_connector_structure = this->get_connector_structure();
Expand All @@ -535,6 +553,14 @@ void OCPP201::ready() {
device_model_config_path, this->ocpp_share_path.string(), this->config.CoreDatabasePath, sql_init_path.string(),
this->config.MessageLogPath, std::make_shared<EvseSecurity>(*this->r_security), callbacks);

// publish charging schedules at least once on startup
charging_schedules_callback();

if (this->config.CompositeScheduleIntervalS > 0) {
this->charging_schedules_timer.interval(charging_schedules_callback,
std::chrono::seconds(this->config.CompositeScheduleIntervalS));
}

const auto ev_connection_timeout_request_value_response = this->charge_point->request_value<int32_t>(
ocpp::v201::Component{"TxCtrlr"}, ocpp::v201::Variable{"EVConnectionTimeOut"},
ocpp::v201::AttributeEnum::Actual);
Expand Down Expand Up @@ -1018,4 +1044,53 @@ void OCPP201::process_deauthorized(const int32_t evse_id, const int32_t connecto
this->process_tx_event_effect(evse_id, tx_event_effect, session_event);
}

void OCPP201::publish_charging_schedules(const std::vector<ocpp::v201::CompositeSchedule>& composite_schedules) {
const auto everest_schedules = conversions::to_everest_charging_schedules(composite_schedules);
this->p_ocpp_generic->publish_charging_schedules(everest_schedules);
}

void OCPP201::set_external_limits(const std::vector<ocpp::v201::CompositeSchedule>& composite_schedules) {
const auto start_time = ocpp::DateTime();

// iterate over all schedules reported by the libocpp to create ExternalLimits
// for each connector

for (const auto& composite_schedule : composite_schedules) {
types::energy::ExternalLimits limits;
std::vector<types::energy::ScheduleReqEntry> schedule_import;

for (const auto& period : composite_schedule.chargingSchedulePeriod) {
types::energy::ScheduleReqEntry schedule_req_entry;
types::energy::LimitsReq limits_req;
const auto timestamp = start_time.to_time_point() + std::chrono::seconds(period.startPeriod);
schedule_req_entry.timestamp = ocpp::DateTime(timestamp).to_rfc3339();
if (composite_schedule.chargingRateUnit == ocpp::v201::ChargingRateUnitEnum::A) {
limits_req.ac_max_current_A = period.limit;
if (period.numberPhases.has_value()) {
limits_req.ac_max_phase_count = period.numberPhases.value();
}
} else {
limits_req.total_power_W = period.limit;
}
schedule_req_entry.limits_to_leaves = limits_req;
schedule_import.push_back(schedule_req_entry);
}
limits.schedule_import = schedule_import;

if (composite_schedule.evseId == 0) {
if (!this->r_connector_zero_sink.empty()) {
EVLOG_debug << "OCPP sets the following external limits for evse 0: \n" << limits;
this->r_connector_zero_sink.at(0)->call_set_external_limits(limits);
} else {
EVLOG_debug << "OCPP cannot set external limits for evse 0. No "
"sink is configured.";
}
} else {
EVLOG_debug << "OCPP sets the following external limits for evse " << composite_schedule.evseId << ": \n"
<< limits;
this->r_evse_manager.at(composite_schedule.evseId - 1)->call_set_external_limits(limits);
}
}
}

} // namespace module
15 changes: 14 additions & 1 deletion modules/OCPP201/OCPP201.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
#include <generated/interfaces/auth/Interface.hpp>
#include <generated/interfaces/evse_manager/Interface.hpp>
#include <generated/interfaces/evse_security/Interface.hpp>
#include <generated/interfaces/external_energy_limits/Interface.hpp>
#include <generated/interfaces/ocpp_data_transfer/Interface.hpp>
#include <generated/interfaces/system/Interface.hpp>

Expand All @@ -42,6 +43,9 @@ struct Conf {
std::string DeviceModelConfigPath;
bool EnableExternalWebsocketControl;
int MessageQueueResumeDelay;
int CompositeScheduleIntervalS;
int RequestCompositeScheduleDurationS;
std::string RequestCompositeScheduleUnit;
};

class OCPP201 : public Everest::ModuleBase {
Expand All @@ -54,7 +58,7 @@ class OCPP201 : public Everest::ModuleBase {
std::vector<std::unique_ptr<evse_managerIntf>> r_evse_manager, std::unique_ptr<systemIntf> r_system,
std::unique_ptr<evse_securityIntf> r_security,
std::vector<std::unique_ptr<ocpp_data_transferIntf>> r_data_transfer, std::unique_ptr<authIntf> r_auth,
Conf& config) :
std::vector<std::unique_ptr<external_energy_limitsIntf>> r_connector_zero_sink, Conf& config) :
ModuleBase(info),
mqtt(mqtt_provider),
p_main(std::move(p_main)),
Expand All @@ -67,6 +71,7 @@ class OCPP201 : public Everest::ModuleBase {
r_security(std::move(r_security)),
r_data_transfer(std::move(r_data_transfer)),
r_auth(std::move(r_auth)),
r_connector_zero_sink(std::move(r_connector_zero_sink)),
config(config){};

Everest::MqttProvider& mqtt;
Expand All @@ -80,6 +85,7 @@ class OCPP201 : public Everest::ModuleBase {
const std::unique_ptr<evse_securityIntf> r_security;
const std::vector<std::unique_ptr<ocpp_data_transferIntf>> r_data_transfer;
const std::unique_ptr<authIntf> r_auth;
const std::vector<std::unique_ptr<external_energy_limitsIntf>> r_connector_zero_sink;
const Conf& config;

// ev@1fce4c5e-0ab8-41bb-90f7-14277703d2ac:v1
Expand All @@ -100,6 +106,7 @@ class OCPP201 : public Everest::ModuleBase {
// ev@211cfdbe-f69a-4cd6-a4ec-f8aaa3d1b6c8:v1
// insert your private definitions here
std::unique_ptr<TransactionHandler> transaction_handler;
Everest::SteadyTimer charging_schedules_timer;

std::filesystem::path ocpp_share_path;

Expand Down Expand Up @@ -139,6 +146,12 @@ class OCPP201 : public Everest::ModuleBase {
const types::evse_manager::SessionEvent& session_event);
void process_deauthorized(const int32_t evse_id, const int32_t connector_id,
const types::evse_manager::SessionEvent& session_event);

/// \brief This function publishes the given \p composite_schedules via the ocpp interface
void publish_charging_schedules(const std::vector<ocpp::v201::CompositeSchedule>& composite_schedules);

/// \brief This function applies given \p composite_schedules for each evse_manager and the connector_zero_sink
void set_external_limits(const std::vector<ocpp::v201::CompositeSchedule>& composite_schedules);
// ev@211cfdbe-f69a-4cd6-a4ec-f8aaa3d1b6c8:v1
};

Expand Down
35 changes: 35 additions & 0 deletions modules/OCPP201/conversions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1252,5 +1252,40 @@ to_everest_set_variable_status_enum_type(const ocpp::v201::SetVariableStatusEnum
}
}

types::ocpp::ChargingSchedules
to_everest_charging_schedules(const std::vector<ocpp::v201::CompositeSchedule>& composite_schedules) {
types::ocpp::ChargingSchedules charging_schedules;
for (const auto& composite_schedule : composite_schedules) {
charging_schedules.schedules.push_back(conversions::to_everest_charging_schedule(composite_schedule));
}
return charging_schedules;
}

types::ocpp::ChargingSchedule to_everest_charging_schedule(const ocpp::v201::CompositeSchedule& composite_schedule) {
types::ocpp::ChargingSchedule charging_schedule;
charging_schedule.evse = composite_schedule.evseId;
charging_schedule.charging_rate_unit =
ocpp::v201::conversions::charging_rate_unit_enum_to_string(composite_schedule.chargingRateUnit);
charging_schedule.evse = composite_schedule.evseId;
charging_schedule.duration = composite_schedule.duration;
charging_schedule.start_schedule = composite_schedule.scheduleStart.to_rfc3339();
// min_charging_rate is not given as part of a OCPP2.0.1 composite schedule
for (const auto& charging_schedule_period : composite_schedule.chargingSchedulePeriod) {
charging_schedule.charging_schedule_period.push_back(
to_everest_charging_schedule_period(charging_schedule_period));
}
return charging_schedule;
}

types::ocpp::ChargingSchedulePeriod
to_everest_charging_schedule_period(const ocpp::v201::ChargingSchedulePeriod& period) {
types::ocpp::ChargingSchedulePeriod _period;
_period.start_period = period.startPeriod;
_period.limit = period.limit;
_period.number_phases = period.numberPhases;
_period.phase_to_use = period.phaseToUse;
return _period;
}

} // namespace conversions
} // namespace module
12 changes: 12 additions & 0 deletions modules/OCPP201/conversions.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -226,6 +226,18 @@ to_everest_get_variable_status_enum_type(const ocpp::v201::GetVariableStatusEnum
types::ocpp::SetVariableStatusEnumType
to_everest_set_variable_status_enum_type(const ocpp::v201::SetVariableStatusEnum set_variable_status);

/// \brief Converts a given vector of ocpp::v201::CompositeSchedule \p composite_schedules to a
/// types::ocpp::ChargingSchedules
types::ocpp::ChargingSchedules
to_everest_charging_schedules(const std::vector<ocpp::v201::CompositeSchedule>& composite_schedules);

/// \brief Converts a given ocpp::v201::CompositeSchedule \p composite_schedule to a types::ocpp::ChargingSchedule
types::ocpp::ChargingSchedule to_everest_charging_schedule(const ocpp::v201::CompositeSchedule& composite_schedule);

/// \brief Converst a given ocpp::v201::ChargingSchedulePeriod \p period to a types::ocpp::ChargingSchedulePeriod
types::ocpp::ChargingSchedulePeriod
to_everest_charging_schedule_period(const ocpp::v201::ChargingSchedulePeriod& period);

} // namespace conversions
} // namespace module

Expand Down
26 changes: 26 additions & 0 deletions modules/OCPP201/manifest.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,28 @@ config:
description: Time (seconds) to delay resuming the message queue after reconnecting
type: integer
default: 0
CompositeScheduleIntervalS:
description:
Interval in seconds in which composite schedules are received from libocpp
are be published over MQTT and signalled to connected modules. If the value
is set to 0, composite schedules are only published when changed by CSMS
type: integer
default: 30
RequestCompositeScheduleDurationS:
description: >-
Time (seconds) for which composite schedules are requested.
Schedules are requested from now until now + RequestCompositeScheduleDurationS
type: integer
default: 600
RequestCompositeScheduleUnit:
description: >-
Unit in which composite schedules are requested and shared within EVerest. It is recommended to use
Amps for AC and Watts for DC charging stations.
Allowed values:
- 'A' for Amps
. 'W' for Watts
type: string
default: 'A'
provides:
main:
description: This is a OCPP 2.0.1 charge point
Expand Down Expand Up @@ -65,6 +87,10 @@ requires:
interface: auth
min_connections: 1
max_connections: 1
connector_zero_sink:
interface: external_energy_limits
min_connections: 0
max_connections: 1
enable_external_mqtt: true
enable_global_errors: true
metadata:
Expand Down
8 changes: 3 additions & 5 deletions types/ocpp.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ types:
required:
- start_period
- limit
- stack_level
properties:
start_period:
type: integer
Expand All @@ -32,22 +31,21 @@ types:
type: integer
stack_level:
type: integer
phase_to_use:
type: integer
ChargingSchedule:
description: >-
Element providing information on an OCPP charging schedule.
type: object
required:
- connector
- evse
- charging_rate_unit
- charging_schedule_period
properties:
evse:
description: The OCPP 2.0.1 EVSE ID (not used in OCPP 1.6).
type: integer
minimum: 0
connector:
type: integer
minimum: 0
charging_rate_unit:
type: string
charging_schedule_period:
Expand Down

0 comments on commit b1b9863

Please sign in to comment.