Skip to content

Commit

Permalink
B04:[wip] send status notification for changed connectors when back o…
Browse files Browse the repository at this point in the history
…nline

Signed-off-by: Soumya Subramanya <s.subramanya@alfen.com>
  • Loading branch information
SNSubramanya committed Sep 15, 2023
1 parent 6b70020 commit 33cb132
Show file tree
Hide file tree
Showing 2 changed files with 66 additions and 89 deletions.
18 changes: 4 additions & 14 deletions include/ocpp/v201/charge_point.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -116,13 +116,11 @@ class ChargePoint : ocpp::ChargingStationBase {
std::mutex data_transfer_callbacks_mutex;

std::map<int32_t, std::pair<IdToken, int32_t>> remote_start_id_per_evse;
bool is_offline_threshold_expired;

// timers
Everest::SteadyTimer heartbeat_timer;
Everest::SteadyTimer boot_notification_timer;
Everest::SteadyTimer aligned_meter_values_timer;
Everest::SteadyTimer offline_threshold_timer;

// states
RegistrationStatusEnum registration_status;
Expand All @@ -136,29 +134,22 @@ class ChargePoint : ocpp::ChargingStationBase {
bool disable_automatic_websocket_reconnects;

// store the connector status
struct conn_states_per_evse_id_key
{
struct evse_connector_pair {
int32_t evse_id;
int32_t connectior_id;

// Define a comparison operator for the struct
bool operator<(const conn_states_per_evse_id_key& other) const {
bool operator<(const evse_connector_pair& other) const {
// Compare based on name, then age
if (evse_id != other.evse_id) {
return evse_id < other.evse_id;
}
return connectior_id < other.connectior_id;
}
};
struct conn_states_per_evse_id_value
{
ConnectorStatusEnum connector_status;
bool is_status_changed_when_offline;
};


std::map<conn_states_per_evse_id_key,conn_states_per_evse_id_value> conn_state_per_evse;

std::map<evse_connector_pair, ConnectorStatusEnum> conn_state_per_evse;

Check notice on line 151 in include/ocpp/v201/charge_point.hpp

View check run for this annotation

Codacy Production / Codacy Static Code Analysis

include/ocpp/v201/charge_point.hpp#L151

class member 'ChargePoint::conn_state_per_evse' is never used.
std::chrono::time_point<std::chrono::steady_clock> time_disconnected;

/// \brief Used when an 'OnIdle' reset is requested, to perform the reset after the charging has stopped.
bool reset_scheduled;
Expand Down Expand Up @@ -240,7 +231,6 @@ class ChargePoint : ocpp::ChargingStationBase {
///
void set_evse_connectors_unavailable(const std::unique_ptr<Evse>& evse, bool persist);

bool is_offline_threshold_passed();
/* OCPP message requests */

// Functional Block B: Provisioning
Expand Down
137 changes: 62 additions & 75 deletions lib/ocpp/v201/charge_point.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -468,79 +468,80 @@ void ChargePoint::init_websocket() {

this->websocket = std::make_unique<Websocket>(connection_options, this->pki_handler, this->logging);
this->websocket->register_connected_callback([this](const int security_profile) {
//stop the offline threshold timer
offline_threshold_timer.stop();

if(!is_offline_threshold_expired){
EVLOG_info << "LIBOCPP: Offline < threshold";
// get the status of all the connectors
for (auto const& [evse_id, evse] : this->evses) {
int number_of_connectors = evse->get_number_of_connectors();
conn_states_per_evse_id_key conn_states_struct_key;
conn_states_per_evse_id_value conn_states_struct_value;
EVLOG_info << "LIBOCPP: evseId: " << evse_id << " numConn: " << number_of_connectors;
for (int connector_id = 1; connector_id <=number_of_connectors; connector_id++){
conn_states_struct_key.evse_id = evse_id;
conn_states_struct_key.connectior_id = connector_id;

if(!(conn_state_per_evse[conn_states_struct_key].connector_status == evse->get_state(connector_id))){
// if the state varied when offline
EVLOG_info << "conn_id: " << conn_states_struct_key.connectior_id << " State: " << evse->get_state(connector_id);
conn_state_per_evse[conn_states_struct_key].is_status_changed_when_offline = true;
// conn_state_per_evse[conn_states_struct_key].connector_status = evse->get_state(connector_id);
}
}
}
}

this->message_queue->resume();
this->websocket_connection_status = WebsocketConnectionStatusEnum::Connected;
});

this->websocket->register_closed_callback(
[this, connection_options, configuration_slot](const websocketpp::close::status::value reason) {
EVLOG_warning << "Failed to connect to NetworkConfigurationPriority: "
<< this->network_configuration_priority + 1
<< " which is configurationSlot: " << configuration_slot;
this->websocket_connection_status = WebsocketConnectionStatusEnum::Disconnected;
this->message_queue->pause();
// B04.FR.01
// If offline period exceeds Offline threshold, send status notification for all all connectors.
int offline_threshold = this->device_model->get_value<int>(ControllerComponentVariables::OfflineThreshold);
if (offline_threshold > 0) {
if (this->registration_status == RegistrationStatusEnum::Accepted) {
// handle offline threshold
// Get the current time point using steady_clock
std::chrono::steady_clock::duration offline_duration = std::chrono::steady_clock::now() - time_disconnected;

// get the status of all the connectors
// B04.FR.01
// If offline period exceeds offline threshold then send the status notification for all connectors
if (offline_duration > (std::chrono::seconds)this->device_model->get_value<int>(
ControllerComponentVariables::OfflineThreshold)) {
EVLOG_debug << "offline for more than offline threshold ";
for (auto const& [evse_id, evse] : this->evses) {
evse->trigger_status_notification_callbacks();
}
} else {
// B04.FR.02
// If offline period doesn't exceed offline threshold then send the status notification for all
// connectors that changed state
EVLOG_debug << "offline for less than offline threshold ";
for (auto const& [evse_id, evse] : this->evses) {
int number_of_connectors = evse->get_number_of_connectors();
conn_states_per_evse_id_key conn_states_struct_key;
conn_states_per_evse_id_value conn_states_struct_value;
EVLOG_info << "LIBOCPP: evseId: " << evse_id << " numConn: " << number_of_connectors;
for (int connector_id = 1; connector_id <=number_of_connectors; connector_id++){
conn_states_struct_key.evse_id = evse_id;
conn_states_struct_key.connectior_id = connector_id;
conn_state_per_evse[conn_states_struct_key].connector_status = evse->get_state(connector_id);
EVLOG_info << "conn_id: " << conn_states_struct_key.connectior_id << " State: " << conn_state_per_evse[conn_states_struct_key].connector_status;
for (int connector_id = 1; connector_id <= number_of_connectors; connector_id++) {
if (conn_state_per_evse[{evse_id, connector_id}] != evse->get_state(connector_id)) {
evse->trigger_status_notification_callback(connector_id);
}
}
}

this->offline_threshold_timer.interval(
[this]() {
EVLOG_debug << "offline threshold exceeded";
is_offline_threshold_expired = true;
},
std::chrono::seconds(offline_threshold));
}
if (!this->disable_automatic_websocket_reconnects) {
this->websocket_timer.timeout(
[this, reason]() {
if (reason != websocketpp::close::status::service_restart) {
this->next_network_configuration_priority();
}
this->start_websocket();
},
WEBSOCKET_INIT_DELAY);
}
});

this->websocket->register_closed_callback([this, connection_options,
configuration_slot](const websocketpp::close::status::value reason) {
EVLOG_warning << "Failed to connect to NetworkConfigurationPriority: "
<< this->network_configuration_priority + 1
<< " which is configurationSlot: " << configuration_slot;
this->websocket_connection_status = WebsocketConnectionStatusEnum::Disconnected;
this->message_queue->pause();

// check if offline threshold has been defined
if ((std::chrono::seconds)this->device_model->get_value<int>(ControllerComponentVariables::OfflineThreshold) !=
std::chrono::seconds(0)) {
// get the status of all the connectors
for (auto const& [evse_id, evse] : this->evses) {
int number_of_connectors = evse->get_number_of_connectors();
evse_connector_pair conn_states_struct_key;
EVLOG_debug << "evseId: " << evse_id << " numConn: " << number_of_connectors;
for (int connector_id = 1; connector_id <= number_of_connectors; connector_id++) {
conn_states_struct_key.evse_id = evse_id;
conn_states_struct_key.connectior_id = connector_id;
conn_state_per_evse[conn_states_struct_key] = evse->get_state(connector_id);
EVLOG_debug << "conn_id: " << conn_states_struct_key.connectior_id
<< " State: " << conn_state_per_evse[conn_states_struct_key];
}
}
});
// Get the current time point using steady_clock
time_disconnected = std::chrono::steady_clock::now();
}

if (!this->disable_automatic_websocket_reconnects) {
this->websocket_timer.timeout(
[this, reason]() {
if (reason != websocketpp::close::status::service_restart) {
this->next_network_configuration_priority();
}
this->start_websocket();
},
WEBSOCKET_INIT_DELAY);
}
});

this->websocket->register_message_callback([this](const std::string& message) { this->message_callback(message); });
}
Expand Down Expand Up @@ -675,20 +676,6 @@ void ChargePoint::message_callback(const std::string& message) {
this->logging->central_system(conversions::messagetype_to_string(enhanced_message.messageType), message);

if (this->registration_status == RegistrationStatusEnum::Accepted) {
// B04.FR.01
// If offline period exceeds offline threshold then send the status notification for all connectors
if(is_offline_threshold_expired)
{
is_offline_threshold_expired = false;
for (auto const& [evse_id, evse] : this->evses) {
evse->trigger_status_notification_callbacks();
}
}
else
{

}

this->handle_message(json_message, enhanced_message.messageType);
} else if (this->registration_status == RegistrationStatusEnum::Pending) {
if (enhanced_message.messageType == MessageType::BootNotificationResponse) {
Expand Down

0 comments on commit 33cb132

Please sign in to comment.