Skip to content
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
2 changes: 1 addition & 1 deletion src/chargepoint/authent/AuthentLocalList.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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())
Expand Down
72 changes: 51 additions & 21 deletions src/chargepoint/maintenance/MaintenanceManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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";
}
}
}

Expand Down Expand Up @@ -635,10 +642,12 @@ void MaintenanceManager::processUpdateFirmware(std::string
ocpp::types::Optional<unsigned int> 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()));
}

Expand Down Expand Up @@ -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";
}
}
}

Expand Down Expand Up @@ -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";
}
}
}

Expand Down Expand Up @@ -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";
}
}
}

Expand Down
30 changes: 26 additions & 4 deletions src/chargepoint/metervalues/MeterValuesManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -188,9 +188,20 @@ void MeterValuesManager::getTxStopMeterValues(unsigned int connector_id, std::ve
bool MeterValuesManager::onTriggerMessage(ocpp::types::MessageTrigger message, const ocpp::types::Optional<unsigned int>& 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;
Expand All @@ -201,9 +212,20 @@ bool MeterValuesManager::onTriggerMessage(ocpp::types::MessageTriggerEnumType
const ocpp::types::Optional<unsigned int>& 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;
Expand Down
30 changes: 16 additions & 14 deletions src/chargepoint/trigger/TriggerMessageManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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))
Expand All @@ -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;
Expand Down Expand Up @@ -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))
Expand All @@ -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;
Expand Down
134 changes: 128 additions & 6 deletions tests/chargepoint/metervalues/test_metervalues.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,120 @@ static void checkClockAligned(const std::vector<std::pair<std::string, std::uniq
CHECK_EQ(meter_value_req.meterValue[0].sampledValue[2].value, "16");
}

/** @brief Check all the sampled meter values */
static void checkAllSampled(const std::vector<std::pair<std::string, std::unique_ptr<rapidjson::Document>>>& 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<std::pair<std::string, std::unique_ptr<rapidjson::Document>>>& messages)
{
Expand Down Expand Up @@ -825,18 +939,26 @@ TEST_SUITE("Metervalues component")
rpc.clearCalls();

// Trigger meter values without connector id
CHECK_FALSE(meter_mgr.onTriggerMessage(MessageTrigger::MeterValues, Optional<unsigned int>()));
CHECK_FALSE(event_handler.methodCalled("getMeterValue", params));
CHECK(meter_mgr.onTriggerMessage(MessageTrigger::MeterValues, Optional<unsigned int>()));
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<unsigned int>()));
CHECK_FALSE(event_handler.methodCalled("getMeterValue", params));
CHECK(meter_mgr.onTriggerMessage(MessageTriggerEnumType::MeterValues, Optional<unsigned int>()));
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")
Expand Down
2 changes: 1 addition & 1 deletion tests/stubs/ChargePointEventsHandlerStub.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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");
}

Expand Down