From 8292d0c218fad581725b6b85a192ef9cb5fd5b93 Mon Sep 17 00:00:00 2001 From: SNSubramanya <139965468+SNSubramanya@users.noreply.github.com> Date: Tue, 17 Oct 2023 13:08:41 +0200 Subject: [PATCH] J01- Non transaction meter values - evseId =0 values * Send IdleMeasurements * Add phase rotation varaible --- .../standardized/ChargingStation.json | 15 +++++++++ config/v201/config.json | 14 ++++++++- include/ocpp/v201/charge_point.hpp | 8 +++++ lib/ocpp/v201/charge_point.cpp | 31 ++++++++++++++++++- lib/ocpp/v201/ctrlr_component_variables.cpp | 8 +++++ 5 files changed, 74 insertions(+), 2 deletions(-) diff --git a/config/v201/component_schemas/standardized/ChargingStation.json b/config/v201/component_schemas/standardized/ChargingStation.json index ba7eb654a..f98c4689b 100644 --- a/config/v201/component_schemas/standardized/ChargingStation.json +++ b/config/v201/component_schemas/standardized/ChargingStation.json @@ -35,6 +35,21 @@ "description": "This variable reports current availability state for the ChargingStation", "type": "string" }, + "ChargingStationPhaseRotation": { + "variable_name": "PhaseRotation", + "characteristics": { + "supportsMonitoring": true, + "dataType": "string" + }, + "attributes": [ + { + "type": "Actual", + "mutability": "ReadWrite" + } + ], + "description": "This variable describes the phase rotation of a Component relative to its parent Component, using a three letter string consisting of the letters: R, S, T and x.", + "type": "string" + }, "ChargingStationAvailable": { "variable_name": "Available", "characteristics": { diff --git a/config/v201/config.json b/config/v201/config.json index ac5b50359..134d4a0e8 100644 --- a/config/v201/config.json +++ b/config/v201/config.json @@ -428,6 +428,12 @@ "attributes": { "Actual": "Energy.Active.Import.Register" } + }, + "AlignedDataSendDuringIdle": { + "variable_name": "SendDuringIdle", + "attributes": { + "Actual": false + } } } }, @@ -497,6 +503,12 @@ "attributes": { "Actual": 42 } + }, + "ChargingStationPhaseRotation": { + "variable_name": "PhaseRotation", + "attributes": { + "Actual": "RST" + } } } }, @@ -658,4 +670,4 @@ } } } -] +] \ No newline at end of file diff --git a/include/ocpp/v201/charge_point.hpp b/include/ocpp/v201/charge_point.hpp index 7bd77a900..1e8755fda 100644 --- a/include/ocpp/v201/charge_point.hpp +++ b/include/ocpp/v201/charge_point.hpp @@ -165,6 +165,9 @@ class ChargePoint : ocpp::ChargingStationBase { std::map conn_state_per_evse; std::chrono::time_point time_disconnected; + MeterValue meter_value; // represents evseId = 0 meter value + std::mutex meter_value_mutex; + /// \brief Used when an 'OnIdle' reset is requested, to perform the reset after the charging has stopped. bool reset_scheduled; /// \brief If `reset_scheduled` is true and the reset is for a specific evse id, it will be stored in this member. @@ -262,6 +265,11 @@ class ChargePoint : ocpp::ChargingStationBase { /// @brief Get the value optional offline flag /// @return true if the charge point is offline. std::nullopt if it is online; bool is_offline(); + + /// \brief Returns the last present meter value for evseId 0 + /// \return MeterValue + MeterValue get_meter_value(); + /* OCPP message requests */ // Functional Block A: Security diff --git a/lib/ocpp/v201/charge_point.cpp b/lib/ocpp/v201/charge_point.cpp index fb9eef6b9..e78d61e48 100644 --- a/lib/ocpp/v201/charge_point.cpp +++ b/lib/ocpp/v201/charge_point.cpp @@ -320,7 +320,18 @@ void ChargePoint::on_session_finished(const int32_t evse_id, const int32_t conne } void ChargePoint::on_meter_value(const int32_t evse_id, const MeterValue& meter_value) { - this->evses.at(evse_id)->on_meter_value(meter_value); + if (evse_id == 0) { + std::lock_guard lk(this->meter_value_mutex); + // if evseId = 0 then store in the chargepoint metervalues + this->meter_value = meter_value; + } else { + this->evses.at(evse_id)->on_meter_value(meter_value); + } +} + +MeterValue ChargePoint::get_meter_value() { + std::lock_guard lk(this->meter_value_mutex); + return this->meter_value; } void ChargePoint::on_unavailable(const int32_t evse_id, const int32_t connector_id) { @@ -897,6 +908,7 @@ void ChargePoint::update_aligned_data_interval() { EVLOG_debug << "Next meter value will be sent at: " << next_timestamp.value().to_rfc3339(); this->aligned_meter_values_timer.at( [this]() { + bool transaction_active = false; for (auto const& [evse_id, evse] : this->evses) { auto _meter_value = evse->get_meter_value(); // this will apply configured measurands and possibly reduce the entries of sampledValue @@ -906,6 +918,7 @@ void ChargePoint::update_aligned_data_interval() { ControllerComponentVariables::AlignedDataMeasurands); if (evse->has_active_transaction()) { + transaction_active = true; // because we do not actively read meter values at clock aligned timepoint, we switch the // ReadingContext here for (auto& sampled_value : _meter_value.sampledValue) { @@ -926,12 +939,28 @@ void ChargePoint::update_aligned_data_interval() { this->device_model ->get_optional_value(ControllerComponentVariables::AlignedDataSendDuringIdle) .value_or(false)) { + transaction_active = false; if (!meter_value.sampledValue.empty()) { // J01.FR.14 this is the only case where we send a MeterValue.req this->meter_values_req(evse_id, std::vector(1, meter_value)); } } } + // also send meter values for evseId 0 if no transactions are on going + if (!transaction_active) { + auto _meter_value = this->get_meter_value(); + + // this will apply configured measurands and possibly reduce the entries of sampledValue + // according to the configuration + const auto meter_value = + get_latest_meter_value_filtered(_meter_value, ReadingContextEnum::Sample_Clock, + ControllerComponentVariables::AlignedDataMeasurands); + + if (!meter_value.sampledValue.empty()) { + this->meter_values_req(0, std::vector(1, meter_value)); + } + } + this->update_aligned_data_interval(); }, next_timestamp.value().to_time_point()); diff --git a/lib/ocpp/v201/ctrlr_component_variables.cpp b/lib/ocpp/v201/ctrlr_component_variables.cpp index 3e3aa5b77..eb1a1c7fe 100644 --- a/lib/ocpp/v201/ctrlr_component_variables.cpp +++ b/lib/ocpp/v201/ctrlr_component_variables.cpp @@ -352,6 +352,14 @@ const ComponentVariable& ChargingStationAvailabilityState = { "AvailabilityState", }), }; +const ComponentVariable& ChargingStationPhaseRotation = { + ControllerComponents::ChargingStation, + std::nullopt, + std::optional({ + "PhaseRotation", + }), +}; + const ComponentVariable& ChargingStationAvailable = { ControllerComponents::ChargingStation, std::nullopt,