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

OCPP1.6: Support for vendor errors #395

Merged
merged 1 commit into from
Jan 10, 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
17 changes: 14 additions & 3 deletions include/ocpp/v16/charge_point.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -225,12 +225,23 @@ class ChargePoint {
/// the state machine.
/// \param connector
/// \param error_code
void on_error(int32_t connector, const ChargePointErrorCode& error_code);
/// \param info Additional free format information related to the error
/// \param vendor_id This identifies the vendor-specific implementation
/// \param vendor_error_code This contains the vendor-specific error code
void on_error(int32_t connector, const ChargePointErrorCode& error_code,
const std::optional<CiString<50>>& info = std::nullopt,
const std::optional<CiString<255>>& vendor_id = std::nullopt,
const std::optional<CiString<50>>& vendor_error_code = std::nullopt);

/// \brief This function should be called if a fault is detected that prevents further charging operations. The \p
/// error_code indicates the reason for the fault.
/// \param error_code
void on_fault(int32_t connector, const ChargePointErrorCode& error_code);
/// \param info Additional free format information related to the error
/// \param vendor_id This identifies the vendor-specific implementation
/// \param vendor_error_code This contains the vendor-specific error code
void on_fault(int32_t connector, const ChargePointErrorCode& error_code,
const std::optional<CiString<50>>& info = std::nullopt,
const std::optional<CiString<255>>& vendor_id = std::nullopt,
const std::optional<CiString<50>>& vendor_error_code = std::nullopt);

/// \brief Chargepoint notifies about new log status \p log_status . This function should be called during a
/// Diagnostics / Log upload to indicate the current \p log_status .
Expand Down
18 changes: 14 additions & 4 deletions include/ocpp/v16/charge_point_impl.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -208,7 +208,10 @@ class ChargePointImpl : ocpp::ChargingStationBase {
const ocpp::DateTime& datetime);
void send_meter_value(int32_t connector, MeterValue meter_value);
void status_notification(const int32_t connector, const ChargePointErrorCode errorCode,
const ChargePointStatus status, const ocpp::DateTime& timestamp);
const ChargePointStatus status, const ocpp::DateTime& timestamp,
const std::optional<CiString<50>>& info = std::nullopt,
const std::optional<CiString<255>>& vendor_id = std::nullopt,
const std::optional<CiString<50>>& vendor_error_code = std::nullopt);
void diagnostic_status_notification(DiagnosticsStatus status);
void firmware_status_notification(FirmwareStatus status);
void log_status_notification(UploadLogStatusEnumType status, int requestId);
Expand Down Expand Up @@ -518,12 +521,19 @@ class ChargePointImpl : ocpp::ChargingStationBase {
/// the state machine.
/// \param connector
/// \param error_code
void on_error(int32_t connector, const ChargePointErrorCode& error);
/// \param info Additional free format information related to the error
/// \param vendor_id This identifies the vendor-specific implementation
/// \param vendor_error_code This contains the vendor-specific error code
void on_error(int32_t connector, const ChargePointErrorCode& error_code, const std::optional<CiString<50>>& info,
const std::optional<CiString<255>>& vendor_id, const std::optional<CiString<50>>& vendor_error_code);

/// \brief This function should be called if a fault is detected that prevents further charging operations. The \p
/// error_code indicates the reason for the fault.
/// \param error_code
void on_fault(int32_t connector, const ChargePointErrorCode& error_code);
/// \param info Additional free format information related to the error
/// \param vendor_id This identifies the vendor-specific implementation
/// \param vendor_error_code This contains the vendor-specific error code
void on_fault(int32_t connector, const ChargePointErrorCode& error_code, const std::optional<CiString<50>>& info,
const std::optional<CiString<255>>& vendor_id, const std::optional<CiString<50>>& vendor_error_code);

/// \brief Chargepoint notifies about new log status \p log_status . This function should be called during a
/// Diagnostics / Log upload to indicate the current \p log_status .
Expand Down
27 changes: 19 additions & 8 deletions include/ocpp/v16/charge_point_state_machine.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -45,12 +45,18 @@ using FSMDefinition = std::map<FSMState, FSMStateTransitions>;
class ChargePointFSM {
public:
using StatusNotificationCallback = std::function<void(
const ChargePointStatus status, const ChargePointErrorCode error_code, const ocpp::DateTime& timestamp)>;
const ChargePointStatus status, const ChargePointErrorCode error_code, const ocpp::DateTime& timestamp,
const std::optional<CiString<50>>& info, const std::optional<CiString<255>>& vendor_id,
const std::optional<CiString<50>>& vendor_error_code)>;
explicit ChargePointFSM(const StatusNotificationCallback& status_notification_callback, FSMState initial_state);

bool handle_event(FSMEvent event, const ocpp::DateTime timestamp);
bool handle_error(const ChargePointErrorCode& error_code, const ocpp::DateTime& timestamp);
bool handle_fault(const ChargePointErrorCode& error_code, const ocpp::DateTime& timestamp);
bool handle_error(const ChargePointErrorCode& error_code, const ocpp::DateTime& timestamp,
const std::optional<CiString<50>>& info, const std::optional<CiString<255>>& vendor_id,
const std::optional<CiString<50>>& vendor_error_code);
bool handle_fault(const ChargePointErrorCode& error_code, const ocpp::DateTime& timestamp,
const std::optional<CiString<50>>& info, const std::optional<CiString<255>>& vendor_id,
const std::optional<CiString<50>>& vendor_error_code);

FSMState get_state() const;

Expand All @@ -65,15 +71,20 @@ class ChargePointFSM {

class ChargePointStates {
public:
using ConnectorStatusCallback =
std::function<void(const int connector_id, const ChargePointErrorCode errorCode, const ChargePointStatus status,
const ocpp::DateTime& timestamp)>;
using ConnectorStatusCallback = std::function<void(
const int connector_id, const ChargePointErrorCode errorCode, const ChargePointStatus status,
const ocpp::DateTime& timestamp, const std::optional<CiString<50>>& info,
const std::optional<CiString<255>>& vendor_id, const std::optional<CiString<50>>& vendor_error_code)>;
ChargePointStates(const ConnectorStatusCallback& connector_status_callback);
void reset(std::map<int, ChargePointStatus> connector_status_map);

void submit_event(const int connector_id, FSMEvent event, const ocpp::DateTime& timestamp);
void submit_fault(const int connector_id, const ChargePointErrorCode& error_code, const ocpp::DateTime& timestamp);
void submit_error(const int connector_id, const ChargePointErrorCode& error_code, const ocpp::DateTime& timestamp);
void submit_fault(const int connector_id, const ChargePointErrorCode& error_code, const ocpp::DateTime& timestamp,
const std::optional<CiString<50>>& info, const std::optional<CiString<255>>& vendor_id,
const std::optional<CiString<50>>& vendor_error_code);
void submit_error(const int connector_id, const ChargePointErrorCode& error_code, const ocpp::DateTime& timestamp,
const std::optional<CiString<50>>& info, const std::optional<CiString<255>>& vendor_id,
const std::optional<CiString<50>>& vendor_error_code);

ChargePointStatus get_state(int connector_id);

Expand Down
12 changes: 8 additions & 4 deletions lib/ocpp/v16/charge_point.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -121,12 +121,16 @@ void ChargePoint::on_resume_charging(int32_t connector) {
this->charge_point->on_resume_charging(connector);
}

void ChargePoint::on_error(int32_t connector, const ChargePointErrorCode& error_code) {
this->charge_point->on_error(connector, error_code);
void ChargePoint::on_error(int32_t connector, const ChargePointErrorCode& error_code,
const std::optional<CiString<50>>& info, const std::optional<CiString<255>>& vendor_id,
const std::optional<CiString<50>>& vendor_error_code) {
this->charge_point->on_error(connector, error_code, info, vendor_id, vendor_error_code);
}

void ChargePoint::on_fault(int32_t connector, const ChargePointErrorCode& error_code) {
this->charge_point->on_fault(connector, error_code);
void ChargePoint::on_fault(int32_t connector, const ChargePointErrorCode& error_code,
const std::optional<CiString<50>>& info, const std::optional<CiString<255>>& vendor_id,
const std::optional<CiString<50>>& vendor_error_code) {
this->charge_point->on_fault(connector, error_code, info, vendor_id, vendor_error_code);
}

void ChargePoint::on_log_status_notification(int32_t request_id, std::string log_status) {
Expand Down
32 changes: 22 additions & 10 deletions lib/ocpp/v16/charge_point_impl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -94,13 +94,15 @@ ChargePointImpl::ChargePointImpl(const std::string& config, const fs::path& shar
this->v2g_certificate_timer->interval(V2G_CERTIFICATE_TIMER_INTERVAL);
});

this->status =
std::make_unique<ChargePointStates>([this](const int32_t connector, const ChargePointErrorCode errorCode,
const ChargePointStatus status, const ocpp::DateTime& timestamp) {
this->status = std::make_unique<ChargePointStates>(
[this](const int32_t connector, const ChargePointErrorCode errorCode, const ChargePointStatus status,
const ocpp::DateTime& timestamp, const std::optional<CiString<50>>& info,
const std::optional<CiString<255>>& vendor_id, const std::optional<CiString<50>>& vendor_error_code) {
this->status_notification_timers.at(connector)->stop();
this->status_notification_timers.at(connector)->timeout(
[this, connector, errorCode, status, timestamp]() {
this->status_notification(connector, errorCode, status, timestamp);
[this, connector, errorCode, status, timestamp, info, vendor_id, vendor_error_code]() {
this->status_notification(connector, errorCode, status, timestamp, info, vendor_id,
vendor_error_code);
},
std::chrono::seconds(this->configuration->getMinimumStatusDuration().value_or(0)));
});
Expand Down Expand Up @@ -2553,12 +2555,18 @@ bool ChargePointImpl::send(CallError call_error) {
}

void ChargePointImpl::status_notification(const int32_t connector, const ChargePointErrorCode errorCode,
const ChargePointStatus status, const ocpp::DateTime& timestamp) {
const ChargePointStatus status, const ocpp::DateTime& timestamp,
const std::optional<CiString<50>>& info,
const std::optional<CiString<255>>& vendor_id,
const std::optional<CiString<50>>& vendor_error_code) {
StatusNotificationRequest request;
request.connectorId = connector;
request.errorCode = errorCode;
request.status = status;
request.timestamp = timestamp;
request.info = info;
request.vendorId = vendor_id;
request.vendorErrorCode = vendor_error_code;
ocpp::Call<StatusNotificationRequest> call(request, this->message_queue->createMessageId());
this->send<StatusNotificationRequest>(call);
}
Expand Down Expand Up @@ -3365,12 +3373,16 @@ void ChargePointImpl::on_resume_charging(int32_t connector) {
this->status->submit_event(connector, FSMEvent::StartCharging, ocpp::DateTime());
}

void ChargePointImpl::on_error(int32_t connector, const ChargePointErrorCode& error_code) {
this->status->submit_error(connector, error_code, ocpp::DateTime());
void ChargePointImpl::on_error(int32_t connector, const ChargePointErrorCode& error_code,
const std::optional<CiString<50>>& info, const std::optional<CiString<255>>& vendor_id,
const std::optional<CiString<50>>& vendor_error_code) {
this->status->submit_error(connector, error_code, ocpp::DateTime(), info, vendor_id, vendor_error_code);
}

void ChargePointImpl::on_fault(int32_t connector, const ChargePointErrorCode& error_code) {
this->status->submit_fault(connector, error_code, ocpp::DateTime());
void ChargePointImpl::on_fault(int32_t connector, const ChargePointErrorCode& error_code,
const std::optional<CiString<50>>& info, const std::optional<CiString<255>>& vendor_id,
const std::optional<CiString<50>>& vendor_error_code) {
this->status->submit_fault(connector, error_code, ocpp::DateTime(), info, vendor_id, vendor_error_code);
}

void ChargePointImpl::on_log_status_notification(int32_t request_id, std::string log_status) {
Expand Down
50 changes: 33 additions & 17 deletions lib/ocpp/v16/charge_point_state_machine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -129,13 +129,16 @@ bool ChargePointFSM::handle_event(FSMEvent event, const ocpp::DateTime timestamp
state = dest_state_it->second;

if (!faulted) {
status_notification_callback(state, this->error_code, timestamp);
status_notification_callback(state, this->error_code, timestamp, std::nullopt, std::nullopt, std::nullopt);
}

return true;
}

bool ChargePointFSM::handle_fault(const ChargePointErrorCode& error_code, const ocpp::DateTime& timestamp) {
bool ChargePointFSM::handle_fault(const ChargePointErrorCode& error_code, const ocpp::DateTime& timestamp,
const std::optional<CiString<50>>& info,
const std::optional<CiString<255>>& vendor_id,
const std::optional<CiString<50>>& vendor_error_code) {
if (error_code == this->error_code) {
// has already been handled and reported
return false;
Expand All @@ -144,26 +147,29 @@ bool ChargePointFSM::handle_fault(const ChargePointErrorCode& error_code, const
this->error_code = error_code;
if (this->error_code == ChargePointErrorCode::NoError) {
faulted = false;
status_notification_callback(state, this->error_code, timestamp);
status_notification_callback(state, this->error_code, timestamp, info, vendor_id, vendor_error_code);
} else {
faulted = true;
status_notification_callback(FSMState::Faulted, error_code, timestamp);
status_notification_callback(FSMState::Faulted, error_code, timestamp, info, vendor_id, vendor_error_code);
}

return true;
}

bool ChargePointFSM::handle_error(const ChargePointErrorCode& error_code, const ocpp::DateTime& timestamp) {
bool ChargePointFSM::handle_error(const ChargePointErrorCode& error_code, const ocpp::DateTime& timestamp,
const std::optional<CiString<50>>& info,
const std::optional<CiString<255>>& vendor_id,
const std::optional<CiString<50>>& vendor_error_code) {
if (error_code == this->error_code) {
// has already been handled and reported
return false;
}

this->error_code = error_code;
if (!faulted) {
status_notification_callback(this->state, error_code, timestamp);
status_notification_callback(this->state, error_code, timestamp, info, vendor_id, vendor_error_code);
} else {
status_notification_callback(FSMState::Faulted, error_code, timestamp);
status_notification_callback(FSMState::Faulted, error_code, timestamp, info, vendor_id, vendor_error_code);
}
return true;
}
Expand All @@ -185,15 +191,21 @@ void ChargePointStates::reset(std::map<int, ChargePointStatus> connector_status_
} else if (connector_id == 0) {
state_machine_connector_zero = std::make_unique<ChargePointFSM>(
[this](const ChargePointStatus status, const ChargePointErrorCode error_code,
const ocpp::DateTime& timestamp) {
this->connector_status_callback(0, error_code, status, timestamp);
const ocpp::DateTime& timestamp, const std::optional<CiString<50>>& info,
const std::optional<CiString<255>>& vendor_id,
const std::optional<CiString<50>>& vendor_error_code) {
this->connector_status_callback(0, error_code, status, timestamp, info, vendor_id,
vendor_error_code);
},
initial_state);
} else {
state_machines.emplace_back(
[this, connector_id](ChargePointStatus status, ChargePointErrorCode error_code,
ocpp::DateTime timestamp) {
this->connector_status_callback(connector_id, error_code, status, timestamp);
ocpp::DateTime timestamp, std::optional<CiString<50>> info,
std::optional<CiString<255>> vendor_id,
std::optional<CiString<50>> vendor_error_code) {
this->connector_status_callback(connector_id, error_code, status, timestamp, info, vendor_id,
vendor_error_code);
},
initial_state);
}
Expand All @@ -211,22 +223,26 @@ void ChargePointStates::submit_event(const int connector_id, FSMEvent event, con
}

void ChargePointStates::submit_fault(const int connector_id, const ChargePointErrorCode& error_code,
const ocpp::DateTime& timestamp) {
const ocpp::DateTime& timestamp, const std::optional<CiString<50>>& info,
const std::optional<CiString<255>>& vendor_id,
const std::optional<CiString<50>>& vendor_error_code) {
const std::lock_guard<std::mutex> lck(state_machines_mutex);
if (connector_id == 0) {
this->state_machine_connector_zero->handle_fault(error_code, timestamp);
this->state_machine_connector_zero->handle_fault(error_code, timestamp, info, vendor_id, vendor_error_code);
} else if (connector_id > 0 && (size_t)connector_id <= state_machines.size()) {
state_machines.at(connector_id - 1).handle_fault(error_code, timestamp);
state_machines.at(connector_id - 1).handle_fault(error_code, timestamp, info, vendor_id, vendor_error_code);
}
}

void ChargePointStates::submit_error(const int connector_id, const ChargePointErrorCode& error_code,
const ocpp::DateTime& timestamp) {
const ocpp::DateTime& timestamp, const std::optional<CiString<50>>& info,
const std::optional<CiString<255>>& vendor_id,
const std::optional<CiString<50>>& vendor_error_code) {
const std::lock_guard<std::mutex> lck(state_machines_mutex);
if (connector_id == 0) {
this->state_machine_connector_zero->handle_error(error_code, timestamp);
this->state_machine_connector_zero->handle_error(error_code, timestamp, info, vendor_id, vendor_error_code);
} else if (connector_id > 0 && (size_t)connector_id <= state_machines.size()) {
state_machines.at(connector_id - 1).handle_error(error_code, timestamp);
state_machines.at(connector_id - 1).handle_error(error_code, timestamp, info, vendor_id, vendor_error_code);
}
}

Expand Down