diff --git a/src/chargepoint/authent/AuthentLocalList.cpp b/src/chargepoint/authent/AuthentLocalList.cpp index 0e8769e7..fd19b740 100644 --- a/src/chargepoint/authent/AuthentLocalList.cpp +++ b/src/chargepoint/authent/AuthentLocalList.cpp @@ -124,7 +124,7 @@ bool AuthentLocalList::handleMessage(const ocpp::messages::SendLocalListReq& req // Check local list activation if (m_ocpp_config.localAuthListEnabled()) { - if (request.listVersion > 0) + if (request.listVersion >= 0) { // Check update list size if (request.localAuthorizationList.size() <= m_ocpp_config.sendLocalListMaxLength()) diff --git a/src/chargepoint/maintenance/MaintenanceManager.cpp b/src/chargepoint/maintenance/MaintenanceManager.cpp index bde7442f..205d5443 100644 --- a/src/chargepoint/maintenance/MaintenanceManager.cpp +++ b/src/chargepoint/maintenance/MaintenanceManager.cpp @@ -586,12 +586,19 @@ void MaintenanceManager::processGetDiagnostics(std::string if (!success) { // Next retry - nb_retries--; - if (nb_retries != 0) + if (nb_retries > 0) { - LOG_WARNING << "GetDiagnostics : upload failed (" << nb_retries << " retrie(s) left - next retry in " - << retry_interval_s.count() << "s)"; - std::this_thread::sleep_for(retry_interval_s); + nb_retries--; + if (nb_retries != 0) + { + LOG_WARNING << "GetDiagnostics : upload failed (" << nb_retries << " retrie(s) left - next retry in " + << retry_interval_s.count() << "s)"; + std::this_thread::sleep_for(retry_interval_s); + } + else + { + LOG_WARNING << "GetDiagnostics : upload failed no retries left"; + } } } @@ -635,10 +642,12 @@ void MaintenanceManager::processUpdateFirmware(std::string ocpp::types::Optional retry_interval, ocpp::types::DateTime retrieve_date) { + + LOG_INFO << "UpdateFirmware : Waiting until retrieve date (" << retrieve_date.timestamp() << ") from now (" << DateTime::now() << ")"; + // Check retrieve date if (retrieve_date > DateTime::now()) { - LOG_INFO << "UpdateFirmware : Waiting until retrieve date"; std::this_thread::sleep_until(std::chrono::system_clock::from_time_t(retrieve_date.timestamp())); } @@ -667,12 +676,19 @@ void MaintenanceManager::processUpdateFirmware(std::string if (!success) { // Next retry - nb_retries--; - if (nb_retries != 0) + if (nb_retries > 0) { - LOG_WARNING << "FirmwareUpdate : download failed (" << nb_retries << " retrie(s) left - next retry in " - << retry_interval_s.count() << "s)"; - std::this_thread::sleep_for(retry_interval_s); + nb_retries--; + if (nb_retries != 0) + { + LOG_WARNING << "FirmwareUpdate : download failed (" << nb_retries << " retrie(s) left - next retry in " + << retry_interval_s.count() << "s)"; + std::this_thread::sleep_for(retry_interval_s); + } + else + { + LOG_WARNING << "FirmwareUpdate : download failed no retries left"; + } } } @@ -767,12 +783,19 @@ void MaintenanceManager::processGetLog(ocpp::types::LogEnumType type, if (!success) { // Next retry - nb_retries--; - if (nb_retries != 0) + if (nb_retries > 0) { - LOG_WARNING << "GetLog : upload failed (" << nb_retries << " retrie(s) left - next retry in " << retry_interval_s.count() - << "s)"; - std::this_thread::sleep_for(retry_interval_s); + nb_retries--; + if (nb_retries != 0) + { + LOG_WARNING << "GetLog : upload failed (" << nb_retries << " retrie(s) left - next retry in " + << retry_interval_s.count() << "s)"; + std::this_thread::sleep_for(retry_interval_s); + } + else + { + LOG_WARNING << "GetLog : upload failed retries left"; + } } } @@ -855,12 +878,19 @@ void MaintenanceManager::processSignedUpdateFirmware(std::string if (!success) { // Next retry - nb_retries--; - if (nb_retries != 0) + if (nb_retries > 0) { - LOG_WARNING << "SignedUpdateFirmware : download failed (" << nb_retries << " retrie(s) left - next retry in " - << retry_interval_s.count() << "s)"; - std::this_thread::sleep_for(retry_interval_s); + nb_retries--; + if (nb_retries != 0) + { + LOG_WARNING << "SignedUpdateFirmware : download failed (" << nb_retries << " retrie(s) left - next retry in " + << retry_interval_s.count() << "s)"; + std::this_thread::sleep_for(retry_interval_s); + } + else + { + LOG_WARNING << "SignedUpdateFirmware : download failed no retries left"; + } } } diff --git a/src/chargepoint/metervalues/MeterValuesManager.cpp b/src/chargepoint/metervalues/MeterValuesManager.cpp index 8eea0996..be9157cb 100644 --- a/src/chargepoint/metervalues/MeterValuesManager.cpp +++ b/src/chargepoint/metervalues/MeterValuesManager.cpp @@ -188,9 +188,20 @@ void MeterValuesManager::getTxStopMeterValues(unsigned int connector_id, std::ve bool MeterValuesManager::onTriggerMessage(ocpp::types::MessageTrigger message, const ocpp::types::Optional& connector_id) { bool ret = false; - if (connector_id.isSet() && (message == MessageTrigger::MeterValues)) + if (message == MessageTrigger::MeterValues) { - processTriggered(connector_id); + if (connector_id.isSet()) + { + processTriggered(connector_id); + } + else + { + for (const Connector* connector : m_connectors.getConnectors()) + { + unsigned int id = connector->id; + processTriggered(id); + } + } ret = true; } return ret; @@ -201,9 +212,20 @@ bool MeterValuesManager::onTriggerMessage(ocpp::types::MessageTriggerEnumType const ocpp::types::Optional& connector_id) { bool ret = false; - if (connector_id.isSet() && (message == MessageTriggerEnumType::MeterValues)) + if (message == MessageTriggerEnumType::MeterValues) { - processTriggered(connector_id); + if (connector_id.isSet()) + { + processTriggered(connector_id); + } + else + { + for (const Connector* connector : m_connectors.getConnectors()) + { + unsigned int id = connector->id; + processTriggered(id); + } + } ret = true; } return ret; diff --git a/src/chargepoint/trigger/TriggerMessageManager.cpp b/src/chargepoint/trigger/TriggerMessageManager.cpp index e97b7c1b..172b6e30 100644 --- a/src/chargepoint/trigger/TriggerMessageManager.cpp +++ b/src/chargepoint/trigger/TriggerMessageManager.cpp @@ -85,8 +85,14 @@ bool TriggerMessageManager::handleMessage(const ocpp::messages::TriggerMessageRe } else { - // Check connector id - if (!request.connectorId.isSet() || m_connectors.isValid(request.connectorId)) + // Check invalid connector id + if (request.connectorId.isSet() && !m_connectors.isValid(request.connectorId)) + { + error_code = ocpp::rpc::IRpc::RPC_ERROR_PROPERTY_CONSTRAINT_VIOLATION; + error_message = "Invalid connector id"; + response.status = TriggerMessageStatus::Rejected; + } + else { // Call handler if (it->second->onTriggerMessage(request.requestedMessage, request.connectorId)) @@ -100,11 +106,6 @@ bool TriggerMessageManager::handleMessage(const ocpp::messages::TriggerMessageRe LOG_WARNING << "Trigger message rejected : " << trigger_message; } } - else - { - error_code = ocpp::rpc::IRpc::RPC_ERROR_PROPERTY_CONSTRAINT_VIOLATION; - error_message = "Invalid connector id"; - } } return ret; @@ -136,8 +137,14 @@ bool TriggerMessageManager::handleMessage(const ocpp::messages::ExtendedTriggerM } else { - // Check connector id - if (!request.connectorId.isSet() || m_connectors.isValid(request.connectorId)) + // Check invalid connector id + if (request.connectorId.isSet() && !m_connectors.isValid(request.connectorId)) + { + error_code = ocpp::rpc::IRpc::RPC_ERROR_PROPERTY_CONSTRAINT_VIOLATION; + error_message = "Invalid connector id"; + response.status = TriggerMessageStatusEnumType::Rejected; + } + else { // Call handler if (it->second->onTriggerMessage(request.requestedMessage, request.connectorId)) @@ -151,11 +158,6 @@ bool TriggerMessageManager::handleMessage(const ocpp::messages::ExtendedTriggerM LOG_WARNING << "Extended trigger message rejected : " << trigger_message; } } - else - { - error_code = ocpp::rpc::IRpc::RPC_ERROR_PROPERTY_CONSTRAINT_VIOLATION; - error_message = "Invalid connector id"; - } } return ret; diff --git a/tests/chargepoint/metervalues/test_metervalues.cpp b/tests/chargepoint/metervalues/test_metervalues.cpp index a001d861..7102a08c 100644 --- a/tests/chargepoint/metervalues/test_metervalues.cpp +++ b/tests/chargepoint/metervalues/test_metervalues.cpp @@ -162,6 +162,120 @@ static void checkClockAligned(const std::vector>>& messages, + ReadingContext context) +{ + MeterValuesReq meter_value_req; + + CHECK_EQ(messages.size(), 3u); + CHECK_EQ(messages[0].first, METER_VALUES_ACTION); + CHECK_EQ(messages[1].first, METER_VALUES_ACTION); + CHECK_EQ(messages[2].first, METER_VALUES_ACTION); + + CHECK(deserializeMeterValue((*messages[0].second), meter_value_req)); + CHECK_EQ(meter_value_req.connectorId, 0); + CHECK_FALSE(meter_value_req.transactionId.isSet()); + CHECK_EQ(meter_value_req.meterValue.size(), 1u); + CHECK_EQ(meter_value_req.meterValue[0].sampledValue.size(), 4); + CHECK_EQ(meter_value_req.meterValue[0].sampledValue[0].measurand, Measurand::CurrentImport); + CHECK_EQ(meter_value_req.meterValue[0].sampledValue[0].phase, Phase::L1); + CHECK_EQ(meter_value_req.meterValue[0].sampledValue[0].location, Location::Inlet); + CHECK_EQ(meter_value_req.meterValue[0].sampledValue[0].format, ValueFormat::Raw); + CHECK_EQ(meter_value_req.meterValue[0].sampledValue[0].unit, UnitOfMeasure::A); + CHECK_EQ(meter_value_req.meterValue[0].sampledValue[0].context, context); + CHECK_EQ(meter_value_req.meterValue[0].sampledValue[0].value, "10"); + CHECK_EQ(meter_value_req.meterValue[0].sampledValue[1].measurand, Measurand::CurrentImport); + CHECK_EQ(meter_value_req.meterValue[0].sampledValue[1].phase, Phase::L2); + CHECK_EQ(meter_value_req.meterValue[0].sampledValue[1].location, Location::Inlet); + CHECK_EQ(meter_value_req.meterValue[0].sampledValue[1].format, ValueFormat::Raw); + CHECK_EQ(meter_value_req.meterValue[0].sampledValue[1].unit, UnitOfMeasure::A); + CHECK_EQ(meter_value_req.meterValue[0].sampledValue[1].context, context); + CHECK_EQ(meter_value_req.meterValue[0].sampledValue[1].value, "20"); + CHECK_EQ(meter_value_req.meterValue[0].sampledValue[2].measurand, Measurand::CurrentImport); + CHECK_EQ(meter_value_req.meterValue[0].sampledValue[2].phase, Phase::L3); + CHECK_EQ(meter_value_req.meterValue[0].sampledValue[2].location, Location::Inlet); + CHECK_EQ(meter_value_req.meterValue[0].sampledValue[2].format, ValueFormat::Raw); + CHECK_EQ(meter_value_req.meterValue[0].sampledValue[2].unit, UnitOfMeasure::A); + CHECK_EQ(meter_value_req.meterValue[0].sampledValue[2].context, context); + CHECK_EQ(meter_value_req.meterValue[0].sampledValue[2].value, "30"); + CHECK_EQ(meter_value_req.meterValue[0].sampledValue[3].measurand, Measurand::EnergyActiveImportRegister); + CHECK_FALSE(meter_value_req.meterValue[0].sampledValue[3].phase.isSet()); + CHECK_EQ(meter_value_req.meterValue[0].sampledValue[3].location, Location::Inlet); + CHECK_EQ(meter_value_req.meterValue[0].sampledValue[3].format, ValueFormat::Raw); + CHECK_EQ(meter_value_req.meterValue[0].sampledValue[3].unit, UnitOfMeasure::kWh); + CHECK_EQ(meter_value_req.meterValue[0].sampledValue[3].context, context); + CHECK_EQ(meter_value_req.meterValue[0].sampledValue[3].value, "123"); + + CHECK(deserializeMeterValue((*messages[1].second), meter_value_req)); + CHECK_EQ(meter_value_req.connectorId, 1); + CHECK_FALSE(meter_value_req.transactionId.isSet()); + CHECK_EQ(meter_value_req.meterValue.size(), 1u); + CHECK_EQ(meter_value_req.meterValue[0].sampledValue.size(), 4); + CHECK_EQ(meter_value_req.meterValue[0].sampledValue[0].measurand, Measurand::CurrentImport); + CHECK_EQ(meter_value_req.meterValue[0].sampledValue[0].phase, Phase::L1); + CHECK_EQ(meter_value_req.meterValue[0].sampledValue[0].location, Location::Outlet); + CHECK_EQ(meter_value_req.meterValue[0].sampledValue[0].format, ValueFormat::Raw); + CHECK_EQ(meter_value_req.meterValue[0].sampledValue[0].unit, UnitOfMeasure::A); + CHECK_EQ(meter_value_req.meterValue[0].sampledValue[0].context, context); + CHECK_EQ(meter_value_req.meterValue[0].sampledValue[0].value, "40"); + CHECK_EQ(meter_value_req.meterValue[0].sampledValue[1].measurand, Measurand::CurrentImport); + CHECK_EQ(meter_value_req.meterValue[0].sampledValue[1].phase, Phase::L2); + CHECK_EQ(meter_value_req.meterValue[0].sampledValue[1].location, Location::Outlet); + CHECK_EQ(meter_value_req.meterValue[0].sampledValue[1].format, ValueFormat::Raw); + CHECK_EQ(meter_value_req.meterValue[0].sampledValue[1].unit, UnitOfMeasure::A); + CHECK_EQ(meter_value_req.meterValue[0].sampledValue[1].context, context); + CHECK_EQ(meter_value_req.meterValue[0].sampledValue[1].value, "50"); + CHECK_EQ(meter_value_req.meterValue[0].sampledValue[2].measurand, Measurand::CurrentImport); + CHECK_EQ(meter_value_req.meterValue[0].sampledValue[2].phase, Phase::L3); + CHECK_EQ(meter_value_req.meterValue[0].sampledValue[2].location, Location::Outlet); + CHECK_EQ(meter_value_req.meterValue[0].sampledValue[2].format, ValueFormat::Raw); + CHECK_EQ(meter_value_req.meterValue[0].sampledValue[2].unit, UnitOfMeasure::A); + CHECK_EQ(meter_value_req.meterValue[0].sampledValue[2].context, context); + CHECK_EQ(meter_value_req.meterValue[0].sampledValue[2].value, "60"); + CHECK_EQ(meter_value_req.meterValue[0].sampledValue[3].measurand, Measurand::EnergyActiveImportRegister); + CHECK_FALSE(meter_value_req.meterValue[0].sampledValue[3].phase.isSet()); + CHECK_EQ(meter_value_req.meterValue[0].sampledValue[3].location, Location::Outlet); + CHECK_EQ(meter_value_req.meterValue[0].sampledValue[3].format, ValueFormat::Raw); + CHECK_EQ(meter_value_req.meterValue[0].sampledValue[3].unit, UnitOfMeasure::kWh); + CHECK_EQ(meter_value_req.meterValue[0].sampledValue[3].context, context); + CHECK_EQ(meter_value_req.meterValue[0].sampledValue[3].value, "100"); + + CHECK(deserializeMeterValue((*messages[2].second), meter_value_req)); + CHECK_EQ(meter_value_req.connectorId, 2); + CHECK_FALSE(meter_value_req.transactionId.isSet()); + CHECK_EQ(meter_value_req.meterValue.size(), 1u); + CHECK_EQ(meter_value_req.meterValue[0].sampledValue.size(), 4); + CHECK_EQ(meter_value_req.meterValue[0].sampledValue[0].measurand, Measurand::CurrentImport); + CHECK_EQ(meter_value_req.meterValue[0].sampledValue[0].phase, Phase::L1); + CHECK_EQ(meter_value_req.meterValue[0].sampledValue[0].location, Location::Outlet); + CHECK_EQ(meter_value_req.meterValue[0].sampledValue[0].format, ValueFormat::Raw); + CHECK_EQ(meter_value_req.meterValue[0].sampledValue[0].unit, UnitOfMeasure::A); + CHECK_EQ(meter_value_req.meterValue[0].sampledValue[0].context, context); + CHECK_EQ(meter_value_req.meterValue[0].sampledValue[0].value, "70"); + CHECK_EQ(meter_value_req.meterValue[0].sampledValue[1].measurand, Measurand::CurrentImport); + CHECK_EQ(meter_value_req.meterValue[0].sampledValue[1].phase, Phase::L2); + CHECK_EQ(meter_value_req.meterValue[0].sampledValue[1].location, Location::Outlet); + CHECK_EQ(meter_value_req.meterValue[0].sampledValue[1].format, ValueFormat::Raw); + CHECK_EQ(meter_value_req.meterValue[0].sampledValue[1].unit, UnitOfMeasure::A); + CHECK_EQ(meter_value_req.meterValue[0].sampledValue[1].context, context); + CHECK_EQ(meter_value_req.meterValue[0].sampledValue[1].value, "80"); + CHECK_EQ(meter_value_req.meterValue[0].sampledValue[2].measurand, Measurand::CurrentImport); + CHECK_EQ(meter_value_req.meterValue[0].sampledValue[2].phase, Phase::L3); + CHECK_EQ(meter_value_req.meterValue[0].sampledValue[2].location, Location::Outlet); + CHECK_EQ(meter_value_req.meterValue[0].sampledValue[2].format, ValueFormat::Raw); + CHECK_EQ(meter_value_req.meterValue[0].sampledValue[2].unit, UnitOfMeasure::A); + CHECK_EQ(meter_value_req.meterValue[0].sampledValue[2].context, context); + CHECK_EQ(meter_value_req.meterValue[0].sampledValue[2].value, "90"); + CHECK_EQ(meter_value_req.meterValue[0].sampledValue[3].measurand, Measurand::EnergyActiveImportRegister); + CHECK_FALSE(meter_value_req.meterValue[0].sampledValue[3].phase.isSet()); + CHECK_EQ(meter_value_req.meterValue[0].sampledValue[3].location, Location::Outlet); + CHECK_EQ(meter_value_req.meterValue[0].sampledValue[3].format, ValueFormat::Raw); + CHECK_EQ(meter_value_req.meterValue[0].sampledValue[3].unit, UnitOfMeasure::kWh); + CHECK_EQ(meter_value_req.meterValue[0].sampledValue[3].context, context); + CHECK_EQ(meter_value_req.meterValue[0].sampledValue[3].value, "23"); +} + /** @brief Check the sampled meter values */ static void checkSampled(const std::vector>>& messages) { @@ -825,18 +939,26 @@ TEST_SUITE("Metervalues component") rpc.clearCalls(); // Trigger meter values without connector id - CHECK_FALSE(meter_mgr.onTriggerMessage(MessageTrigger::MeterValues, Optional())); - CHECK_FALSE(event_handler.methodCalled("getMeterValue", params)); + CHECK(meter_mgr.onTriggerMessage(MessageTrigger::MeterValues, Optional())); + CHECK(event_handler.methodCalled("getMeterValue", params)); // Check messages - CHECK(rpc.getCalls().empty()); + checkAllSampled(rpc.getCalls(), ReadingContext::Trigger); + + // Clear stubs + event_handler.clearCalls(); + rpc.clearCalls(); // Extended trigger meter values without connector id - CHECK_FALSE(meter_mgr.onTriggerMessage(MessageTriggerEnumType::MeterValues, Optional())); - CHECK_FALSE(event_handler.methodCalled("getMeterValue", params)); + CHECK(meter_mgr.onTriggerMessage(MessageTriggerEnumType::MeterValues, Optional())); + CHECK(event_handler.methodCalled("getMeterValue", params)); // Check messages - CHECK(rpc.getCalls().empty()); + checkAllSampled(rpc.getCalls(), ReadingContext::Trigger); + + // Clear stubs + event_handler.clearCalls(); + rpc.clearCalls(); } TEST_CASE("Custom meter values") diff --git a/tests/stubs/ChargePointEventsHandlerStub.cpp b/tests/stubs/ChargePointEventsHandlerStub.cpp index 806ba68f..ce30bedf 100755 --- a/tests/stubs/ChargePointEventsHandlerStub.cpp +++ b/tests/stubs/ChargePointEventsHandlerStub.cpp @@ -170,7 +170,7 @@ bool ChargePointEventsHandlerStub::getLocalLimitationsSchedule(unsigned int /** @copydoc bool IChargePointEventsHandler::resetRequested(ocpp::types::ResetType) */ bool ChargePointEventsHandlerStub::resetRequested(ocpp::types::ResetType reset_type) { - m_calls["transactionDeAuthorized"] = {{"reset_type", ResetTypeHelper.toString(reset_type)}}; + m_calls["resetRequested"] = {{"reset_type", ResetTypeHelper.toString(reset_type)}}; return callResult("resetRequested"); }