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

OCPP2.0.1: Device model access for EVSE and Connector specific variables #553

Merged
merged 3 commits into from
Apr 10, 2024
Merged
Show file tree
Hide file tree
Changes from 2 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
4 changes: 4 additions & 0 deletions config/v201/component_schemas/custom/EVSE_1.json
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,10 @@
{
"type": "Actual",
"mutability": "ReadOnly"
},
{
"type": "MaxSet",
"mutability": "ReadOnly"
}
],
"description": " kW,The variableCharacteristic maxLimit, that holds the maximum power that this EVSE can provide, is required. The Actual value of the instantaneous (real) power is desired, but not required.",
Expand Down
4 changes: 4 additions & 0 deletions config/v201/component_schemas/custom/EVSE_2.json
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,10 @@
{
"type": "Actual",
"mutability": "ReadOnly"
},
{
"type": "MaxSet",
"mutability": "ReadOnly"
}
],
"description": " kW,The variableCharacteristic maxLimit, that holds the maximum power that this EVSE can provide, is required. The Actual value of the instantaneous (real) power is desired, but not required.",
Expand Down
16 changes: 2 additions & 14 deletions config/v201/config.json
Original file line number Diff line number Diff line change
Expand Up @@ -46,12 +46,6 @@
"name": "EVSE",
"evse_id": 1,
"variables": {
"EVSEAvailabilityState": {
"variable_name": "AvailabilityState",
"attributes": {
"Actual": ""
}
},
"EVSEAvailable": {
"variable_name": "Available",
"attributes": {
Expand All @@ -61,7 +55,7 @@
"EVSEPower": {
"variable_name": "Power",
"attributes": {
"Actual": 42
"MaxSet": 22000
}
},
"EVSESupplyPhases": {
Expand Down Expand Up @@ -101,12 +95,6 @@
"name": "EVSE",
"evse_id": 2,
"variables": {
"EVSEAvailabilityState": {
"variable_name": "AvailabilityState",
"attributes": {
"Actual": ""
}
},
"EVSEAvailable": {
"variable_name": "Available",
"attributes": {
Expand All @@ -116,7 +104,7 @@
"EVSEPower": {
"variable_name": "Power",
"attributes": {
"Actual": 42
"MaxSet": 22000
}
},
"EVSESupplyPhases": {
Expand Down
3 changes: 3 additions & 0 deletions include/ocpp/v201/charge_point.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -264,6 +264,9 @@ class ChargePoint : ocpp::ChargingStationBase {
void init_certificate_expiration_check_timers();
void scheduled_check_client_certificate_expiration();
void scheduled_check_v2g_certificate_expiration();
void update_dm_availability_state(const int32_t evse_id, const int32_t connector_id,
const ConnectorStatusEnum status);
void update_dm_evse_power(const int32_t evse_id, const MeterValue& meter_value);

/// \brief Gets the configured NetworkConnectionProfile based on the given \p configuration_slot . The
/// central system uri ofthe connection options will not contain ws:// or wss:// because this method removes it if
Expand Down
26 changes: 18 additions & 8 deletions include/ocpp/v201/ctrlr_component_variables.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -106,9 +106,6 @@ extern const ComponentVariable& TimeOffset;
extern const ComponentVariable& TimeOffsetNextTransition;
extern const RequiredComponentVariable& TimeSource;
extern const ComponentVariable& TimeZone;
extern const RequiredComponentVariable& ConnectorAvailable;
extern const RequiredComponentVariable& ConnectorType;
extern const RequiredComponentVariable& ConnectorSupplyPhases;
extern const ComponentVariable& CustomImplementationEnabled;
extern const RequiredComponentVariable& BytesPerMessageGetReport;
extern const RequiredComponentVariable& BytesPerMessageGetVariables;
Expand All @@ -122,10 +119,6 @@ extern const ComponentVariable& DisplayMessageCtrlrAvailable;
extern const RequiredComponentVariable& NumberOfDisplayMessages;
extern const RequiredComponentVariable& DisplayMessageSupportedFormats;
extern const RequiredComponentVariable& DisplayMessageSupportedPriorities;
extern const ComponentVariable& EVSEAllowReset;
extern const RequiredComponentVariable& EVSEAvailable;
extern const RequiredComponentVariable& EVSEPower;
extern const RequiredComponentVariable& EVSESupplyPhases;
extern const ComponentVariable& CentralContractValidationAllowed;
extern const RequiredComponentVariable& ContractValidationOffline;
extern const ComponentVariable& RequestMeteringReceipt;
Expand Down Expand Up @@ -210,8 +203,25 @@ extern const RequiredComponentVariable& StopTxOnInvalidId;
extern const ComponentVariable& TxBeforeAcceptedEnabled;
extern const RequiredComponentVariable& TxStartPoint;
extern const RequiredComponentVariable& TxStopPoint;

} // namespace ControllerComponentVariables

namespace EvseComponentVariables {
extern const Variable& Available;
extern const Variable& AvailabilityState;
extern const Variable& SupplyPhases;
extern const Variable& AllowReset;
extern const Variable& Power;
ComponentVariable get_component_variable(const int32_t evse_id, const Variable& variable);
} // namespace EvseComponentVariables

namespace ConnectorComponentVariables {
extern const Variable& Available;
extern const Variable& AvailabilityState;
extern const Variable& Type;
extern const Variable& SupplyPhases;
ComponentVariable get_component_variable(const int32_t evse_id, const int32_t connector_id, const Variable& variable);
} // namespace ConnectorComponentVariables

} // namespace v201
} // namespace ocpp

Expand Down
2 changes: 1 addition & 1 deletion include/ocpp/v201/device_model.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -207,7 +207,7 @@ class DeviceModel {

/// \brief Check data integrity of the device model provided by the device model data storage:
/// For "required" variables, assert values exist. Checks might be extended in the future.
void check_integrity();
void check_integrity(const std::map<int32_t, int32_t>& evse_connector_structure);
};

} // namespace v201
Expand Down
3 changes: 3 additions & 0 deletions include/ocpp/v201/utils.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,9 @@ std::string generate_token_hash(const IdToken& token);
/// \return DateTime type timestamp
ocpp::DateTime align_timestamp(const DateTime timestamp, std::chrono::seconds align_interval);

/// \brief Returns the total Power_Active_Import value from the \p meter_value or 0 if it is not present
float get_total_power_active_import(const MeterValue& meter_value);
Copy link
Contributor

Choose a reason for hiding this comment

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

I would suggest to return an optional here if not found. A power of 0W is a very valid value when idle.


} // namespace utils
} // namespace v201
} // namespace ocpp
Expand Down
32 changes: 31 additions & 1 deletion lib/ocpp/v201/charge_point.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -79,14 +79,15 @@ ChargePoint::ChargePoint(const std::map<int32_t, int32_t>& evse_connector_struct
}

this->device_model = std::make_unique<DeviceModel>(std::move(device_model_storage));
this->device_model->check_integrity();
this->device_model->check_integrity(evse_connector_structure);

this->database_handler = std::make_shared<DatabaseHandler>(core_database_path, sql_init_path);
this->database_handler->open_connection();

// Set up the component state manager
this->component_state_manager = std::make_shared<ComponentStateManager>(
evse_connector_structure, database_handler, [this](auto evse_id, auto connector_id, auto status) {
this->update_dm_availability_state(evse_id, connector_id, status);
if (this->websocket == nullptr || !this->websocket->is_connected() ||
this->registration_status != RegistrationStatusEnum::Accepted) {
return false;
Expand Down Expand Up @@ -441,6 +442,7 @@ void ChargePoint::on_meter_value(const int32_t evse_id, const MeterValue& meter_
this->aligned_data_evse0.set_values(meter_value);
} else {
this->evses.at(evse_id)->on_meter_value(meter_value);
this->update_dm_evse_power(evse_id, meter_value);
}
}

Expand Down Expand Up @@ -3168,6 +3170,34 @@ void ChargePoint::scheduled_check_v2g_certificate_expiration() {
.value_or(12 * 60 * 60)));
}

void ChargePoint::update_dm_availability_state(const int32_t evse_id, const int32_t connector_id,
const ConnectorStatusEnum status) {
ComponentVariable evse_cv =
EvseComponentVariables::get_component_variable(evse_id, EvseComponentVariables::AvailabilityState);
ComponentVariable connector_cv = ConnectorComponentVariables::get_component_variable(
evse_id, connector_id, ConnectorComponentVariables::AvailabilityState);
if (evse_cv.variable.has_value()) {
this->device_model->set_read_only_value(evse_cv.component, evse_cv.variable.value(),
ocpp::v201::AttributeEnum::Actual,
conversions::connector_status_enum_to_string(status));
}
if (connector_cv.variable.has_value()) {
this->device_model->set_read_only_value(connector_cv.component, connector_cv.variable.value(),
ocpp::v201::AttributeEnum::Actual,
conversions::connector_status_enum_to_string(status));
}
}

void ChargePoint::update_dm_evse_power(const int32_t evse_id, const MeterValue& meter_value) {
ComponentVariable evse_power_cv =
EvseComponentVariables::get_component_variable(evse_id, EvseComponentVariables::Power);
if (evse_power_cv.variable.has_value()) {
this->device_model->set_read_only_value(evse_power_cv.component, evse_power_cv.variable.value(),
AttributeEnum::Actual,
std::to_string(utils::get_total_power_active_import(meter_value)));
}
}

void ChargePoint::set_cs_operative_status(OperationalStatusEnum new_status, bool persist) {
this->component_state_manager->set_cs_individual_operational_status(new_status, persist);
}
Expand Down
81 changes: 30 additions & 51 deletions lib/ocpp/v201/ctrlr_component_variables.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,9 @@ const Component& AuthCacheCtrlr = {"AuthCacheCtrlr"};
const Component& AuthCtrlr = {"AuthCtrlr"};
const Component& ChargingStation = {"ChargingStation"};
const Component& ClockCtrlr = {"ClockCtrlr"};
const Component& Connector = {"Connector"};
const Component& CustomizationCtrlr = {"CustomizationCtrlr"};
const Component& DeviceDataCtrlr = {"DeviceDataCtrlr"};
const Component& DisplayMessageCtrlr = {"DisplayMessageCtrlr"};
const Component& EVSE = {"EVSE"};
const Component& ISO15118Ctrlr = {"ISO15118Ctrlr"};
const Component& LocalAuthListCtrlr = {"LocalAuthListCtrlr"};
const Component& MonitoringCtrlr = {"MonitoringCtrlr"};
Expand Down Expand Up @@ -525,27 +523,6 @@ const ComponentVariable& TimeZone = {
"TimeZone",
}),
};
const RequiredComponentVariable& ConnectorAvailable = {
ControllerComponents::Connector,
std::nullopt,
std::optional<Variable>({
"Available",
}),
};
const RequiredComponentVariable& ConnectorType = {
ControllerComponents::Connector,
std::nullopt,
std::optional<Variable>({
"ConnectorType",
}),
};
const RequiredComponentVariable& ConnectorSupplyPhases = {
ControllerComponents::Connector,
std::nullopt,
std::optional<Variable>({
"SupplyPhases",
}),
};
const ComponentVariable& CustomImplementationEnabled = {
ControllerComponents::CustomizationCtrlr,
std::nullopt,
Expand Down Expand Up @@ -625,34 +602,6 @@ const RequiredComponentVariable& DisplayMessageSupportedPriorities = {
"SupportedPriorities",
}),
};
const ComponentVariable& EVSEAllowReset = {
ControllerComponents::EVSE,
std::nullopt,
std::optional<Variable>({
"AllowReset",
}),
};
const RequiredComponentVariable& EVSEAvailable = {
ControllerComponents::EVSE,
std::nullopt,
std::optional<Variable>({
"Available",
}),
};
const RequiredComponentVariable& EVSEPower = {
ControllerComponents::EVSE,
std::nullopt,
std::optional<Variable>({
"Power",
}),
};
const RequiredComponentVariable& EVSESupplyPhases = {
ControllerComponents::EVSE,
std::nullopt,
std::optional<Variable>({
"SupplyPhases",
}),
};
const ComponentVariable& CentralContractValidationAllowed = {
ControllerComponents::ISO15118Ctrlr,
std::nullopt,
Expand Down Expand Up @@ -1219,5 +1168,35 @@ const RequiredComponentVariable& TxStopPoint = {
};

} // namespace ControllerComponentVariables

namespace EvseComponentVariables {

const Variable& Available = {"Available"};
const Variable& AvailabilityState = {"AvailabilityState"};
const Variable& SupplyPhases = {"SupplyPhases"};
const Variable& AllowReset = {"AllowReset"};
const Variable& Power = {"Power"};

ComponentVariable get_component_variable(const int32_t evse_id, const Variable& variable) {
EVSE evse = {evse_id};
Component component = {"EVSE", std::nullopt, evse};
return {component, std::nullopt, variable};
}
} // namespace EvseComponentVariables

namespace ConnectorComponentVariables {

const Variable& Available = {"Available"};
const Variable& AvailabilityState = {"AvailabilityState"};
const Variable& Type = {"Type"};
const Variable& SupplyPhases = {"SupplyPhases"};

ComponentVariable get_component_variable(const int32_t evse_id, const int32_t connector_id, const Variable& variable) {
EVSE evse = {evse_id, std::nullopt, connector_id};
Component component = {"Connector", std::nullopt, evse};
return {component, std::nullopt, variable};
}
} // namespace ConnectorComponentVariables

} // namespace v201
} // namespace ocpp
Loading
Loading