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

Extended Use of SecurityEventNotification.req in OCPP1.6 #425

Merged
merged 4 commits into from
Jan 31, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
8 changes: 6 additions & 2 deletions include/ocpp/v16/charge_point.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -73,15 +73,19 @@ class ChargePoint {
/// \param connector_status_map initial state of connectors including connector 0 with reduced set of states
/// (Available, Unavailable, Faulted). connector_status_map is empty, last availability states from the persistant
/// storage will be used
/// \param bootreason reason for calling the start function
/// \return
bool start(const std::map<int, ChargePointStatus>& connector_status_map = {});
bool start(const std::map<int, ChargePointStatus>& connector_status_map = {},
BootReasonEnum bootreason = BootReasonEnum::PowerUp);

/// \brief Restarts the ChargePoint if it has been stopped before. The ChargePoint is reinitialized, connects to the
/// websocket and starts to communicate OCPP messages again
/// \param connector_status_map initial state of connectors including connector 0 with reduced set of states
/// (Available, Unavailable, Faulted). connector_status_map is empty, last availability states from the persistant
/// storage will be used
bool restart(const std::map<int, ChargePointStatus>& connector_status_map = {});
/// \param bootreason reason for calling the start function
bool restart(const std::map<int, ChargePointStatus>& connector_status_map = {},
BootReasonEnum bootreason = BootReasonEnum::ApplicationReset);

// \brief Resets the internal state machine for the connectors using the given \p connector_status_map
/// \param connector_status_map state of connectors including connector 0 with reduced set of states (Available,
Expand Down
10 changes: 7 additions & 3 deletions include/ocpp/v16/charge_point_impl.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@ namespace v16 {
class ChargePointImpl : ocpp::ChargingStationBase {
private:
bool initialized;
BootReasonEnum bootreason;
ChargePointConnectionState connection_state;
bool boot_notification_callerror;
RegistrationStatus registration_status;
Expand Down Expand Up @@ -373,15 +374,18 @@ class ChargePointImpl : ocpp::ChargingStationBase {
/// \brief Starts the ChargePoint, initializes and connects to the Websocket endpoint and initializes a
/// BootNotification.req
/// \param connector_status_map initial state of connectors including connector 0 with reduced set of states
/// (Available, Unavailable, Faulted) \return
bool start(const std::map<int, ChargePointStatus>& connector_status_map);
/// (Available, Unavailable, Faulted)
/// \param bootreason reason for calling the start function
/// \return
bool start(const std::map<int, ChargePointStatus>& connector_status_map, BootReasonEnum bootreason);

/// \brief Restarts the ChargePoint if it has been stopped before. The ChargePoint is reinitialized, connects to the
/// websocket and starts to communicate OCPP messages again
/// \param connector_status_map initial state of connectors including connector 0 with reduced set of states
/// (Available, Unavailable, Faulted). connector_status_map is empty, last availability states from the persistant
/// storage will be used
bool restart(const std::map<int, ChargePointStatus>& connector_status_map);
/// \param bootreason reason for calling the restart function
bool restart(const std::map<int, ChargePointStatus>& connector_status_map, BootReasonEnum bootreason);

/// \brief Resets the internal state machine for the connectors using the given \p connector_status_map
/// \param connector_status_map state of connectors including connector 0 with reduced set of states (Available,
Expand Down
13 changes: 13 additions & 0 deletions include/ocpp/v16/types.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,19 @@ struct AvailabilityChange {
bool persist;
};

/// \brief BootReasonEnum contains the different boot reasons of the charge point (copied from OCPP2.0.1 definition)
enum BootReasonEnum {
ApplicationReset,
FirmwareUpdate,
LocalReset,
PowerUp,
RemoteReset,
ScheduledReset,
Triggered,
Unknown,
Watchdog
};

} // namespace v16
} // namespace ocpp

Expand Down
8 changes: 4 additions & 4 deletions lib/ocpp/v16/charge_point.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,12 @@ ChargePoint::ChargePoint(const std::string& config, const fs::path& share_path,

ChargePoint::~ChargePoint() = default;

bool ChargePoint::start(const std::map<int, ChargePointStatus>& connector_status_map) {
return this->charge_point->start(connector_status_map);
bool ChargePoint::start(const std::map<int, ChargePointStatus>& connector_status_map, BootReasonEnum bootreason) {
return this->charge_point->start(connector_status_map, bootreason);
}

bool ChargePoint::restart(const std::map<int, ChargePointStatus>& connector_status_map) {
return this->charge_point->restart(connector_status_map);
bool ChargePoint::restart(const std::map<int, ChargePointStatus>& connector_status_map, BootReasonEnum bootreason) {
return this->charge_point->restart(connector_status_map, bootreason);
}

bool ChargePoint::stop() {
Expand Down
35 changes: 27 additions & 8 deletions lib/ocpp/v16/charge_point_impl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ ChargePointImpl::ChargePointImpl(const std::string& config, const fs::path& shar
ocpp::ChargingStationBase(evse_security, security_configuration),
boot_notification_callerror(false),
initialized(false),
bootreason(BootReasonEnum::PowerUp),
connection_state(ChargePointConnectionState::Disconnected),
registration_status(RegistrationStatus::Pending),
diagnostics_status(DiagnosticsStatus::Idle),
Expand Down Expand Up @@ -789,7 +790,8 @@ void ChargePointImpl::send_meter_value(int32_t connector, MeterValue meter_value
this->send<MeterValuesRequest>(call, initiated_by_trigger_message);
}

bool ChargePointImpl::start(const std::map<int, ChargePointStatus>& connector_status_map) {
bool ChargePointImpl::start(const std::map<int, ChargePointStatus>& connector_status_map, BootReasonEnum bootreason) {
this->bootreason = bootreason;
this->init_state_machine(connector_status_map);
this->init_websocket();
this->websocket->connect();
Expand All @@ -800,15 +802,15 @@ bool ChargePointImpl::start(const std::map<int, ChargePointStatus>& connector_st
return true;
}

bool ChargePointImpl::restart(const std::map<int, ChargePointStatus>& connector_status_map) {
bool ChargePointImpl::restart(const std::map<int, ChargePointStatus>& connector_status_map, BootReasonEnum bootreason) {
if (this->stopped) {
EVLOG_info << "Restarting OCPP Chargepoint";
this->database_handler->open_db_connection(this->configuration->getNumberOfConnectors());
// instantiating new message queue on restart
this->message_queue = this->create_message_queue();
this->initialized = true;

return this->start(connector_status_map);
return this->start(connector_status_map, bootreason);
} else {
EVLOG_warning << "Attempting to restart Chargepoint while it has not been stopped before";
return false;
Expand Down Expand Up @@ -1013,6 +1015,7 @@ void ChargePointImpl::message_callback(const std::string& message) {
auto call_error = CallError(MessageId(json_message.at(MESSAGE_ID).get<std::string>()), "FormationViolation",
e.what(), json({}, true));
this->send(call_error);
this->securityEventNotification(ocpp::security_events::INVALIDMESSAGES, message, true);
}
}
}
Expand Down Expand Up @@ -1198,6 +1201,17 @@ void ChargePointImpl::handleBootNotificationResponse(ocpp::CallResult<BootNotifi
this->ocsp_request_timer->timeout(INITIAL_CERTIFICATE_REQUESTS_DELAY);
}

if (this->bootreason == BootReasonEnum::RemoteReset) {
this->securityEventNotification(CiString<50>(ocpp::security_events::RESET_OR_REBOOT),
"Charging Station rebooted due to requested remote reset!", true);
} else if (this->bootreason == BootReasonEnum::ScheduledReset) {
this->securityEventNotification(CiString<50>(ocpp::security_events::RESET_OR_REBOOT),
"Charging Station rebooted due to a scheduled reset!", true);
} else if (this->bootreason == BootReasonEnum::PowerUp) {
this->securityEventNotification(CiString<50>(ocpp::security_events::STARTUP_OF_THE_DEVICE),
"The Charge Point has booted", true);
}

this->stop_pending_transactions();

break;
Expand Down Expand Up @@ -2229,7 +2243,7 @@ void ChargePointImpl::handleCertificateSignedRequest(ocpp::Call<CertificateSigne
this->send<CertificateSignedResponse>(call_result);

if (response.status == CertificateSignedStatusEnumType::Rejected) {
this->securityEventNotification("InvalidChargePointCertificate",
this->securityEventNotification(ocpp::security_events::INVALIDCHARGINGSTATIONCERTIFICATE,
ocpp::conversions::install_certificate_result_to_string(result), true);
}

Expand Down Expand Up @@ -2312,7 +2326,7 @@ void ChargePointImpl::handleInstallCertificateRequest(ocpp::Call<InstallCertific
this->send<InstallCertificateResponse>(call_result);

if (response.status == InstallCertificateStatusEnumType::Rejected) {
this->securityEventNotification("InvalidCentralSystemCertificate",
this->securityEventNotification(ocpp::security_events::INVALIDCSMSCERTIFICATE,
ocpp::conversions::install_certificate_result_to_string(result), true);
}
}
Expand Down Expand Up @@ -2348,7 +2362,8 @@ void ChargePointImpl::handleSignedUpdateFirmware(ocpp::Call<SignedUpdateFirmware
}

if (response.status == UpdateFirmwareStatusEnumType::InvalidCertificate) {
this->securityEventNotification("InvalidFirmwareSigningCertificate", "Certificate is invalid.", true);
this->securityEventNotification(ocpp::security_events::INVALIDFIRMWARESIGNINGCERTIFICATE,
"Certificate is invalid.", true);
}
}

Expand Down Expand Up @@ -2413,7 +2428,7 @@ void ChargePointImpl::signed_firmware_update_status_notification(FirmwareStatusE
this->send<SignedFirmwareStatusNotificationRequest>(call, initiated_by_trigger_message);

if (status == FirmwareStatusEnumType::InvalidSignature) {
this->securityEventNotification("InvalidFirmwareSignature", "", true);
this->securityEventNotification(ocpp::security_events::INVALIDFIRMWARESIGNATURE, "", true);
}

if (this->firmware_update_is_pending) {
Expand Down Expand Up @@ -2957,7 +2972,7 @@ void ChargePointImpl::handle_data_transfer_pnc_certificate_signed(Call<DataTrans
this->send<DataTransferResponse>(call_result);

if (certificate_response.status == CertificateSignedStatusEnumType::Rejected) {
this->securityEventNotification("InvalidChargePointCertificate", tech_info, true);
this->securityEventNotification(ocpp::security_events::INVALIDCHARGINGSTATIONCERTIFICATE, tech_info, true);
}
} catch (const json::exception& e) {
EVLOG_warning << "Could not parse data of DataTransfer message CertificateSigned.req: " << e.what();
Expand Down Expand Up @@ -3424,6 +3439,10 @@ void ChargePointImpl::on_firmware_update_status_notification(int32_t request_id,
} catch (const std::out_of_range& e) {
EVLOG_debug << "Could not convert incoming FirmwareStatusNotification to OCPP type";
}

if (firmware_update_status == FirmwareStatusNotification::Installed) {
this->securityEventNotification(ocpp::security_events::FIRMWARE_UPDATED, "Firmware update was installed", true);
}
}

void ChargePointImpl::diagnostic_status_notification(DiagnosticsStatus status) {
Expand Down
Loading