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

OCPP 2.0.1: Refactor Smart Charging Persistence #790

Merged
merged 15 commits into from
Oct 4, 2024
Merged
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
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
ALTER TABLE CHARGING_PROFILES DROP COLUMN CHARGING_LIMIT_SOURCE;
ALTER TABLE CHARGING_PROFILES DROP COLUMN TRANSACTION_ID;
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
ALTER TABLE CHARGING_PROFILES ADD COLUMN CHARGING_LIMIT_SOURCE TEXT NOT NULL DEFAULT 'CSO';

Check failure on line 1 in config/v201/core_migrations/6_up-charging_profiles_source_tx_id.sql

View check run for this annotation

Codacy Production / Codacy Static Code Analysis

config/v201/core_migrations/6_up-charging_profiles_source_tx_id.sql#L1

Expected SET ANSI_NULLS ON near top of file

Check failure on line 1 in config/v201/core_migrations/6_up-charging_profiles_source_tx_id.sql

View check run for this annotation

Codacy Production / Codacy Static Code Analysis

config/v201/core_migrations/6_up-charging_profiles_source_tx_id.sql#L1

Expected SET NOCOUNT ON near top of file

Check failure on line 1 in config/v201/core_migrations/6_up-charging_profiles_source_tx_id.sql

View check run for this annotation

Codacy Production / Codacy Static Code Analysis

config/v201/core_migrations/6_up-charging_profiles_source_tx_id.sql#L1

Expected SET QUOTED_IDENTIFIER ON near top of file

Check failure on line 1 in config/v201/core_migrations/6_up-charging_profiles_source_tx_id.sql

View check run for this annotation

Codacy Production / Codacy Static Code Analysis

config/v201/core_migrations/6_up-charging_profiles_source_tx_id.sql#L1

Expected SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED near top of file
ALTER TABLE CHARGING_PROFILES ADD COLUMN TRANSACTION_ID TEXT;
2 changes: 1 addition & 1 deletion dependencies.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ nlohmann_json:
git: https://github.com/nlohmann/json
git_tag: v3.11.2
options: ["JSON_BuildTests OFF", "JSON_MultipleHeaders ON"]
nlohmann_json_schema_validator:
pboettch_json_schema_validator:
christopher-davis-afs marked this conversation as resolved.
Show resolved Hide resolved
git: https://github.com/pboettch/json-schema-validator
git_tag: 2.3.0
options:
Expand Down
2 changes: 1 addition & 1 deletion include/ocpp/v201/charge_point.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -735,7 +735,7 @@ class ChargePoint : public ChargePointInterface, private ocpp::ChargingStationBa
std::shared_ptr<SmartChargingHandlerInterface> smart_charging_handler;

void handle_message(const EnhancedMessage<v201::MessageType>& message);
void load_charging_profiles();
void clear_invalid_charging_profiles();

public:
/// \brief Construct a new ChargePoint object
Expand Down
31 changes: 28 additions & 3 deletions include/ocpp/v201/database_handler.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
#ifndef OCPP_V201_DATABASE_HANDLER_HPP
#define OCPP_V201_DATABASE_HANDLER_HPP

#include "ocpp/v201/types.hpp"
#include "sqlite3.h"
#include <deque>
#include <fstream>
Expand Down Expand Up @@ -178,16 +179,40 @@ class DatabaseHandler : public common::DatabaseHandlerCommon {
/// charging profiles

/// \brief Inserts or updates the given \p profile to CHARGING_PROFILES table
void insert_or_update_charging_profile(const int evse_id, const v201::ChargingProfile& profile);
void insert_or_update_charging_profile(
const int evse_id, const v201::ChargingProfile& profile,
const ChargingLimitSourceEnum charging_limit_source = ChargingLimitSourceEnum::CSO);
christopher-davis-afs marked this conversation as resolved.
Show resolved Hide resolved

/// \brief Deletes the profile with the given \p profile_id
void delete_charging_profile(const int profile_id);
bool delete_charging_profile(const int profile_id);

/// \brief Deletes the profiles with the given \p transaction_id
void delete_charging_profile_by_transaction_id(const std::string& transaction_id);

/// \brief Deletes all profiles from table CHARGING_PROFILES
void clear_charging_profiles();
bool clear_charging_profiles();

/// \brief Deletes all profiles from table CHARGING_PROFILES matching \p profile_id or \p criteria
bool clear_charging_profiles_matching_criteria(const std::optional<int32_t> profile_id,
const std::optional<ClearChargingProfile>& criteria);

/// \brief Get all profiles from table CHARGING_PROFILES matching \p profile_id or \p criteria
std::vector<ReportedChargingProfile>
get_charging_profiles_matching_criteria(const std::optional<int32_t> evse_id,
const ChargingProfileCriterion& criteria);

/// \brief Retrieves the charging profiles stored on \p evse_id
std::vector<v201::ChargingProfile> get_charging_profiles_for_evse(const int evse_id);

/// \brief Retrieves all ChargingProfiles
std::vector<v201::ChargingProfile> get_all_charging_profiles();

/// \brief Retrieves all ChargingProfiles grouped by EVSE ID
virtual std::map<int32_t, std::vector<v201::ChargingProfile>> get_all_charging_profiles_group_by_evse();

ChargingLimitSourceEnum get_charging_limit_source_for_profile(const int profile_id);
christopher-davis-afs marked this conversation as resolved.
Show resolved Hide resolved

std::unique_ptr<common::SQLiteStatementInterface> new_statement(const std::string& sql);
};

} // namespace v201
Expand Down
37 changes: 9 additions & 28 deletions include/ocpp/v201/smart_charging.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
#include <ocpp/v201/ocpp_enums.hpp>
#include <ocpp/v201/ocpp_types.hpp>
#include <ocpp/v201/transaction.hpp>
#include <ocpp/v201/types.hpp>

namespace ocpp::v201 {

Expand Down Expand Up @@ -48,19 +49,6 @@ enum class ProfileValidationResultEnum {
RequestStartTransactionNonTxProfile
};

/// \brief This enhances the ChargingProfile type by additional paramaters that are required in the
/// ReportChargingProfilesRequest (EvseId, ChargingLimitSourceEnum)
struct ReportedChargingProfile {
ChargingProfile profile;
int32_t evse_id;
ChargingLimitSourceEnum source;

ReportedChargingProfile(const ChargingProfile& profile, const int32_t evse_id,
const ChargingLimitSourceEnum source) :
profile(profile), evse_id(evse_id), source(source) {
}
};

/// \brief This is used to associate charging profiles with a source.
/// Based on the source a different validation path can be taken.
enum class AddChargingProfileSource {
Expand All @@ -86,6 +74,7 @@ class SmartChargingHandlerInterface {

virtual SetChargingProfileResponse validate_and_add_profile(
ChargingProfile& profile, int32_t evse_id,
ChargingLimitSourceEnum charging_limit_source = ChargingLimitSourceEnum::CSO,
AddChargingProfileSource source_of_request = AddChargingProfileSource::SetChargingProfile) = 0;

virtual void delete_transaction_tx_profiles(const std::string& transaction_id) = 0;
Expand All @@ -94,7 +83,9 @@ class SmartChargingHandlerInterface {
validate_profile(ChargingProfile& profile, int32_t evse_id,
AddChargingProfileSource source_of_request = AddChargingProfileSource::SetChargingProfile) = 0;

virtual SetChargingProfileResponse add_profile(ChargingProfile& profile, int32_t evse_id) = 0;
virtual SetChargingProfileResponse
add_profile(ChargingProfile& profile, int32_t evse_id,
ChargingLimitSourceEnum charging_limit_source = ChargingLimitSourceEnum::CSO) = 0;

virtual ClearChargingProfileResponse clear_profiles(const ClearChargingProfileRequest& request) = 0;

Expand All @@ -116,8 +107,6 @@ class SmartChargingHandler : public SmartChargingHandlerInterface {
std::shared_ptr<DeviceModel>& device_model;

std::shared_ptr<ocpp::v201::DatabaseHandler> database_handler;
// cppcheck-suppress unusedStructMember
std::map<int32_t, std::vector<ChargingProfile>> charging_profiles;

public:
SmartChargingHandler(EvseManagerInterface& evse_manager, std::shared_ptr<DeviceModel>& device_model,
Expand All @@ -134,6 +123,7 @@ class SmartChargingHandler : public SmartChargingHandlerInterface {
///
SetChargingProfileResponse validate_and_add_profile(
ChargingProfile& profile, int32_t evse_id,
ChargingLimitSourceEnum charging_limit_source = ChargingLimitSourceEnum::CSO,
AddChargingProfileSource source_of_request = AddChargingProfileSource::SetChargingProfile) override;

///
Expand All @@ -148,12 +138,9 @@ class SmartChargingHandler : public SmartChargingHandlerInterface {
///
/// \brief Adds a given \p profile and associated \p evse_id to our stored list of profiles
///
SetChargingProfileResponse add_profile(ChargingProfile& profile, int32_t evse_id) override;

///
/// \brief Retrieves existing profiles on system.
///
std::vector<ChargingProfile> get_profiles() const;
SetChargingProfileResponse
add_profile(ChargingProfile& profile, int32_t evse_id,
ChargingLimitSourceEnum charging_limit_source = ChargingLimitSourceEnum::CSO) override;

///
/// \brief Clears profiles from the system using the given \p request
Expand Down Expand Up @@ -225,13 +212,7 @@ class SmartChargingHandler : public SmartChargingHandlerInterface {
///
ProfileValidationResultEnum verify_no_conflicting_external_constraints_id(const ChargingProfile& profile) const;

///
/// \brief Retrieves existing profiles on the EVSE \p evse_id
///
std::vector<ChargingProfile> get_profiles_on_evse(int32_t evse_id) const;

private:
std::vector<ChargingProfile> get_station_wide_profiles() const;
std::vector<ChargingProfile> get_evse_specific_tx_default_profiles() const;
std::vector<ChargingProfile> get_station_wide_tx_default_profiles() const;
std::vector<ChargingProfile> get_valid_profiles_for_evse(int32_t evse_id);
Expand Down
15 changes: 15 additions & 0 deletions include/ocpp/v201/types.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
#ifndef V201_TYPES_HPP
#define V201_TYPES_HPP

#include <ocpp/v201/ocpp_types.hpp>

#include <ostream>
#include <string>

Expand Down Expand Up @@ -142,6 +144,19 @@ enum class MessageType {
InternalError, // not in spec, for internal use
};

/// \brief This enhances the ChargingProfile type by additional paramaters that are required in the
/// ReportChargingProfilesRequest (EvseId, ChargingLimitSourceEnum)
struct ReportedChargingProfile {
ChargingProfile profile;
int32_t evse_id;
ChargingLimitSourceEnum source;

ReportedChargingProfile(const ChargingProfile& profile, const int32_t evse_id,
const ChargingLimitSourceEnum source) :
profile(profile), evse_id(evse_id), source(source) {
}
};

namespace conversions {
/// \brief Converts the given MessageType \p m to std::string
/// \returns a string representation of the MessageType
Expand Down
15 changes: 6 additions & 9 deletions lib/ocpp/v201/charge_point.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -183,8 +183,8 @@ void ChargePoint::start(BootReasonEnum bootreason) {
// get transaction messages from db (if there are any) so they can be sent again.
this->message_queue->get_persisted_messages_from_db();
this->boot_notification_req(bootreason);
// K01.27 - call load_charging_profiles when system boots
this->load_charging_profiles();
// call clear_invalid_charging_profiles when system boots
christopher-davis-afs marked this conversation as resolved.
Show resolved Hide resolved
this->clear_invalid_charging_profiles();
this->connectivity_manager->start();

const std::string firmware_version =
Expand Down Expand Up @@ -3144,7 +3144,8 @@ void ChargePoint::handle_remote_start_transaction_request(Call<RequestStartTrans
if (charging_profile.chargingProfilePurpose == ChargingProfilePurposeEnum::TxProfile) {

const auto add_profile_response = this->smart_charging_handler->validate_and_add_profile(
msg.chargingProfile.value(), evse_id, AddChargingProfileSource::RequestStartTransactionRequest);
msg.chargingProfile.value(), evse_id, ChargingLimitSourceEnum::CSO,
AddChargingProfileSource::RequestStartTransactionRequest);
if (add_profile_response.status == ChargingProfileStatusEnum::Accepted) {
EVLOG_debug << "Accepting SetChargingProfileRequest";
} else {
Expand Down Expand Up @@ -4431,19 +4432,15 @@ void ChargePoint::execute_change_availability_request(ChangeAvailabilityRequest
}
}

// K01.27 - load profiles from database
void ChargePoint::load_charging_profiles() {
void ChargePoint::clear_invalid_charging_profiles() {
try {
auto evses = this->database_handler->get_all_charging_profiles_group_by_evse();
EVLOG_info << "Found " << evses.size() << " evse in the database";
for (const auto& [evse_id, profiles] : evses) {
for (auto profile : profiles) {
try {
if (this->smart_charging_handler->validate_profile(profile, evse_id) ==
if (this->smart_charging_handler->validate_profile(profile, evse_id) !=
ProfileValidationResultEnum::Valid) {
this->smart_charging_handler->add_profile(profile, evse_id);
} else {
// delete if not valid anymore
this->database_handler->delete_charging_profile(profile.id);
}
} catch (const QueryExecutionException& e) {
Expand Down
Loading
Loading