@@ -301,6 +301,35 @@ void ChargePointEventsHandler::transactionDeAuthorized(unsigned int connector_id
301301 cout << " Transaction deauthorized on connector : " << connector_id << endl;
302302}
303303
304+ /* * @copydoc bool IChargePointEventsHandler::getLocalLimitationsSchedule(unsigned int, ocpp::types::ChargingSchedule&) */
305+ bool ChargePointEventsHandler::getLocalLimitationsSchedule (unsigned int connector_id,
306+ unsigned int duration,
307+ ocpp::types::ChargingSchedule& schedule)
308+ {
309+ cout << " Local limitations schedule requested : " << connector_id << " - " << duration << endl;
310+
311+ // Connector data
312+ ConnectorData& connector_data = m_connectors->at (connector_id - 1 );
313+
314+ // 1 period
315+ // local limitation = min of connector capacity and cable plugged
316+ ChargingSchedulePeriod period;
317+ if ((connector_data.status >= ChargePointStatus::Charging) && (connector_data.status < ChargePointStatus::Finishing))
318+ {
319+ period.limit = std::min (connector_data.max_setpoint , connector_data.car_cable_capacity );
320+ }
321+ else
322+ {
323+ period.limit = connector_data.max_setpoint ;
324+ }
325+ period.numberPhases = connector_data.meter ->getNumberOfPhases ();
326+ period.startPeriod = 0 ;
327+ schedule.chargingRateUnit = ChargingRateUnitType::A;
328+ schedule.chargingSchedulePeriod .push_back (period);
329+
330+ return true ;
331+ }
332+
304333/* * @copydoc bool IChargePointEventsHandler::resetRequested(ocpp::types::ResetType) */
305334bool ChargePointEventsHandler::resetRequested (ocpp::types::ResetType reset_type)
306335{
@@ -450,7 +479,7 @@ ocpp::types::CertificateStatusEnumType ChargePointEventsHandler::caCertificateRe
450479 << " - certificate subject = " << certificate.subjectString () << endl;
451480
452481 // Check number of installed certificates
453- if (getNumberOfCaCertificateInstalled (true , true ) < m_config.ocppConfig ().certificateStoreMaxLength ())
482+ if (getNumberOfCaCertificateInstalled (true , true , true ) < m_config.ocppConfig ().certificateStoreMaxLength ())
454483 {
455484 // Compute SHA256 to generate filename
456485 Sha2 sha256;
@@ -468,7 +497,7 @@ ocpp::types::CertificateStatusEnumType ChargePointEventsHandler::caCertificateRe
468497 {
469498 // Central System => Check AdditionalRootCertificateCheck configuration key
470499
471- if (m_config.ocppConfig ().additionalRootCertificateCheck () && (getNumberOfCaCertificateInstalled (false , true ) == 0 ))
500+ if (m_config.ocppConfig ().additionalRootCertificateCheck () && (getNumberOfCaCertificateInstalled (false , true , false ) == 0 ))
472501 {
473502 // Additionnal checks :
474503 // - only 1 CA certificate allowed
@@ -724,7 +753,7 @@ std::string ChargePointEventsHandler::getLog(ocpp::types::LogEnumType
724753bool ChargePointEventsHandler::hasCentralSystemCaCertificateInstalled ()
725754{
726755 // A better implementation would also check the validity dates of the certificates
727- return ((getNumberOfCaCertificateInstalled (false , true ) != 0 ) && (!m_config.stackConfig ().tlsServerCertificateCa ().empty ()));
756+ return ((getNumberOfCaCertificateInstalled (false , true , false ) != 0 ) && (!m_config.stackConfig ().tlsServerCertificateCa ().empty ()));
728757}
729758
730759/* * @copydoc bool IChargePointEventsHandler::hasChargePointCertificateInstalled() */
@@ -789,8 +818,206 @@ ocpp::types::UpdateFirmwareStatusEnumType ChargePointEventsHandler::checkFirmwar
789818 return ret;
790819}
791820
821+ // ISO 15118 PnC extensions
822+
823+ /* * @copydoc bool IChargePointEventsHandler::iso15118CheckEvCertificate(const ocpp::x509::Certificate&) */
824+ bool ChargePointEventsHandler::iso15118CheckEvCertificate (const ocpp::x509::Certificate& certificate)
825+ {
826+ bool ret = false ;
827+
828+ cout << " ISO15118 EV certificate verification requested : certificate subject = " << certificate.subjectString () << endl;
829+
830+ // Look for MO certificates
831+ for (auto const & dir_entry : std::filesystem::directory_iterator{m_working_dir})
832+ {
833+ if (!dir_entry.is_directory ())
834+ {
835+ std::string filename = dir_entry.path ().filename ();
836+ if (ocpp::helpers::startsWith (filename, " iso_mo_root_" ) && ocpp::helpers::endsWith (filename, " .pem" ))
837+ {
838+ Certificate mo_cert (dir_entry.path ());
839+ if (certificate.verify (mo_cert.certificateChain ()))
840+ {
841+ cout << " Validated against certificate : " << mo_cert.subjectString () << endl;
842+ ret = true ;
843+ break ;
844+ }
845+ }
846+ }
847+ }
848+
849+ cout << " EV certificate validated : " << (ret ? " yes" : " no" ) << endl;
850+
851+ return ret;
852+ }
853+
854+ /* * @copydoc bool IChargePointEventsHandler::iso15118ChargePointCertificateReceived(const ocpp::x509::Certificate&) */
855+ bool ChargePointEventsHandler::iso15118ChargePointCertificateReceived (const ocpp::x509::Certificate& certificate)
856+ {
857+ std::string ca_filename;
858+ bool ret = false ;
859+
860+ cout << " ISO15118 Charge point certificate installation requested : certificate subject = " << certificate.subjectString () << endl;
861+
862+ // Compute SHA256 to generate filename
863+ Sha2 sha256;
864+ sha256.compute (certificate.pem ().c_str (), certificate.pem ().size ());
865+
866+ std::stringstream name;
867+ name << " iso_cp_" << sha256.resultString () << " .pem" ;
868+ std::string cert_filename = m_working_dir / name.str ();
869+
870+ // Save certificate
871+ if (certificate.toFile (cert_filename))
872+ {
873+ // Retrieve and save the corresponding key/pair with the new certificate
874+ std::string cert_key_filename = cert_filename + " .key" ;
875+ std::filesystem::copy (" /tmp/charge_point_key.key" , cert_key_filename);
876+
877+ cout << " Certificate saved : " << cert_filename << endl;
878+ ret = true ;
879+ }
880+ else
881+ {
882+ cout << " Unable to save certificate : " << cert_filename << endl;
883+ }
884+
885+ return ret;
886+ }
887+
888+ /* * @copydoc ocpp::types::DeleteCertificateStatusEnumType IChargePointEventsHandler::iso15118DeleteCertificate(ocpp::types::HashAlgorithmEnumType,
889+ const std::string&,
890+ const std::string&,
891+ const std::string&) */
892+ ocpp::types::DeleteCertificateStatusEnumType ChargePointEventsHandler::iso15118DeleteCertificate (
893+ ocpp::types::HashAlgorithmEnumType hash_algorithm,
894+ const std::string& issuer_name_hash,
895+ const std::string& issuer_key_hash,
896+ const std::string& serial_number)
897+ {
898+ cout << " ISO15118 certificate deletion requested : hash = " << HashAlgorithmEnumTypeHelper.toString (hash_algorithm)
899+ << " - serial number = " << serial_number << endl;
900+ return deleteCertificate (hash_algorithm, issuer_name_hash, issuer_key_hash, serial_number);
901+ }
902+
903+ /* * @copydoc void IChargePointEventsHandler::iso15118GetInstalledCertificates(
904+ bool,
905+ bool,
906+ bool,
907+ std::vector<std::tuple<GetCertificateIdUseEnumType, Certificate, std::vector<Certificate>>>&) */
908+ void ChargePointEventsHandler::iso15118GetInstalledCertificates (
909+ bool v2g_root_certificate,
910+ bool mo_root_certificate,
911+ bool v2g_certificate_chain,
912+ std::vector<std::tuple<ocpp::types::GetCertificateIdUseEnumType, ocpp::x509::Certificate, std::vector<ocpp::x509::Certificate>>>&
913+ certificates)
914+ {
915+ cout << " ISO15118 get installed certificates requested : v2g_root_certificate = " << (v2g_root_certificate ? " yes" : " no" )
916+ << " - mo_root_certificate = " << (mo_root_certificate ? " yes" : " no" )
917+ << " - v2g_certificate_chain = " << (v2g_certificate_chain ? " yes" : " no" ) << endl;
918+
919+ for (auto const & dir_entry : std::filesystem::directory_iterator{m_working_dir})
920+ {
921+ if (!dir_entry.is_directory ())
922+ {
923+ std::string filename = dir_entry.path ().filename ();
924+ if (v2g_root_certificate)
925+ {
926+ if (ocpp::helpers::startsWith (filename, " iso_v2g_root_" ) && ocpp::helpers::endsWith (filename, " .pem" ))
927+ {
928+ auto tuple = std::make_tuple (GetCertificateIdUseEnumType::V2GRootCertificate,
929+ Certificate (dir_entry.path ()),
930+ std::vector<ocpp::x509::Certificate>());
931+ certificates.emplace_back (std::move (tuple));
932+ }
933+ }
934+ if (mo_root_certificate)
935+ {
936+ if (ocpp::helpers::startsWith (filename, " iso_mo_root_" ) && ocpp::helpers::endsWith (filename, " .pem" ))
937+ {
938+ auto tuple = std::make_tuple (GetCertificateIdUseEnumType::MORootCertificate,
939+ Certificate (dir_entry.path ()),
940+ std::vector<ocpp::x509::Certificate>());
941+ certificates.emplace_back (std::move (tuple));
942+ }
943+ }
944+ if (v2g_certificate_chain)
945+ {
946+ if (ocpp::helpers::startsWith (filename, " iso_v2g_chain_" ) && ocpp::helpers::endsWith (filename, " .pem" ))
947+ {
948+ auto tuple = std::make_tuple (GetCertificateIdUseEnumType::V2GCertificateChain,
949+ Certificate (dir_entry.path ()),
950+ std::vector<ocpp::x509::Certificate>());
951+ certificates.emplace_back (std::move (tuple));
952+ }
953+ }
954+ }
955+ }
956+ }
957+
958+ /* * @copydoc ocpp::types::InstallCertificateStatusEnumType IChargePointEventsHandler::iso15118CertificateReceived(
959+ ocpp::types::InstallCertificateUseEnumType type,
960+ const ocpp::x509::Certificate&) */
961+ ocpp::types::InstallCertificateStatusEnumType ChargePointEventsHandler::iso15118CertificateReceived (
962+ ocpp::types::InstallCertificateUseEnumType type, const ocpp::x509::Certificate& certificate)
963+ {
964+ std::string cert_filename;
965+ InstallCertificateStatusEnumType ret = InstallCertificateStatusEnumType::Rejected;
966+
967+ cout << " ISO15118 certificate installation requested : type = " << InstallCertificateUseEnumTypeHelper.toString (type)
968+ << " - certificate subject = " << certificate.subjectString () << endl;
969+
970+ // Check number of installed certificates
971+ if (getNumberOfCaCertificateInstalled (true , true , true ) < m_config.ocppConfig ().certificateStoreMaxLength ())
972+ {
973+ // Compute SHA256 to generate filename
974+ Sha2 sha256;
975+ sha256.compute (certificate.pem ().c_str (), certificate.pem ().size ());
976+
977+ if (type == InstallCertificateUseEnumType::V2GRootCertificate)
978+ {
979+ // V2 root certificate
980+ std::stringstream name;
981+ name << " iso_v2g_root_" << sha256.resultString () << " .pem" ;
982+ cert_filename = m_working_dir / name.str ();
983+ }
984+ else
985+ {
986+ // MO root certificate
987+ std::stringstream name;
988+ name << " iso_mo_root_" << sha256.resultString () << " .pem" ;
989+ cert_filename = m_working_dir / name.str ();
990+ }
991+
992+ // Save certificate
993+ if (certificate.toFile (cert_filename))
994+ {
995+ ret = InstallCertificateStatusEnumType::Accepted;
996+ cout << " Certificate saved : " << cert_filename << endl;
997+ }
998+ else
999+ {
1000+ ret = InstallCertificateStatusEnumType::Failed;
1001+ cout << " Unable to save certificate : " << cert_filename << endl;
1002+ }
1003+ }
1004+ else
1005+ {
1006+ cout << " Maximum number of certificates reached" << endl;
1007+ }
1008+
1009+ return ret;
1010+ }
1011+
1012+ /* * @copydoc void IChargePointEventsHandler::iso15118GenerateCsr(std::string&) */
1013+ void ChargePointEventsHandler::iso15118GenerateCsr (std::string& csr)
1014+ {
1015+ cout << " Generate ISO15118 CSR requested" << endl;
1016+ generateCsr (csr);
1017+ }
1018+
7921019/* * @brief Get the number of installed CA certificates */
793- unsigned int ChargePointEventsHandler::getNumberOfCaCertificateInstalled (bool manufacturer, bool central_system)
1020+ unsigned int ChargePointEventsHandler::getNumberOfCaCertificateInstalled (bool manufacturer, bool central_system, bool iso15118 )
7941021{
7951022 unsigned int count = 0 ;
7961023 for (auto const & dir_entry : std::filesystem::directory_iterator{m_working_dir})
@@ -806,6 +1033,10 @@ unsigned int ChargePointEventsHandler::getNumberOfCaCertificateInstalled(bool ma
8061033 {
8071034 count++;
8081035 }
1036+ if (iso15118 && ocpp::helpers::startsWith (filename, " iso_" ) && ocpp::helpers::endsWith (filename, " .pem" ))
1037+ {
1038+ count++;
1039+ }
8091040 }
8101041 }
8111042 return count;
0 commit comments