Skip to content

Commit 203e2a9

Browse files
committed
[ocpp20] Add device model implementation + GetBaseReport implementation example in quick_start_chargepoint20
1 parent 1440c49 commit 203e2a9

16 files changed

+2135
-563
lines changed

examples/ocpp20/common/DefaultChargePointEventsHandler.cpp

Lines changed: 96 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,11 @@ SOFTWARE.
2424

2525
#include "DefaultChargePointEventsHandler.h"
2626
#include "ChargePointDemoConfig.h"
27+
#include "NotifyReport20.h"
2728

2829
#include <fstream>
2930
#include <iostream>
31+
#include <thread>
3032

3133
// With MSVC compiler, the system() call returns directly the command's return value
3234
#ifdef _MSC_VER
@@ -36,11 +38,16 @@ SOFTWARE.
3638
using namespace std;
3739
using namespace ocpp::types;
3840
using namespace ocpp::types::ocpp20;
41+
using namespace ocpp::messages;
42+
using namespace ocpp::messages::ocpp20;
3943

4044
/** @brief Constructor */
41-
DefaultChargePointEventsHandler::DefaultChargePointEventsHandler(ChargePointDemoConfig& config, const std::filesystem::path& working_dir)
42-
: m_config(config), m_chargepoint(nullptr), m_working_dir(working_dir), m_is_connected(false)
45+
DefaultChargePointEventsHandler::DefaultChargePointEventsHandler(ChargePointDemoConfig& config,
46+
ocpp::chargepoint::ocpp20::IDeviceModel20& device_model,
47+
const std::filesystem::path& working_dir)
48+
: m_config(config), m_device_model(device_model), m_chargepoint(nullptr), m_working_dir(working_dir), m_is_connected(false)
4349
{
50+
m_device_model.registerListener(*this);
4451
}
4552

4653
/** @brief Destructor */
@@ -59,6 +66,24 @@ void DefaultChargePointEventsHandler::connectionStateChanged(bool isConnected)
5966
m_is_connected = isConnected;
6067
}
6168

69+
// IDeviceModel20 interface
70+
71+
/** @brief Called to retrieve the value of a variable */
72+
void DefaultChargePointEventsHandler::getVariable(ocpp::types::ocpp20::GetVariableResultType& var)
73+
{
74+
std::string value;
75+
m_config.getDeviceModelValue(var.component, var.variable, value);
76+
var.attributeValue.value().assign(std::move(value));
77+
}
78+
79+
/** @brief Called to set the value of a variable */
80+
ocpp::types::ocpp20::SetVariableStatusEnumType DefaultChargePointEventsHandler::setVariable(
81+
const ocpp::types::ocpp20::SetVariableDataType& var)
82+
{
83+
m_config.setDeviceModelValue(var.component, var.variable, var.attributeValue.str());
84+
return SetVariableStatusEnumType::Accepted;
85+
}
86+
6287
// OCPP operations
6388

6489
/** @brief Called on reception of a CancelReservation message from the central */
@@ -284,13 +309,78 @@ bool DefaultChargePointEventsHandler::onGetBaseReport(const ocpp::messages::ocpp
284309
{
285310
bool ret = true;
286311

287-
(void)request;
288312
(void)error;
289313
(void)message;
290314

291315
cout << "GetBaseReport" << endl;
292316

293-
response.status = GenericDeviceModelStatusEnumType::NotSupported;
317+
if (request.reportBase == ReportBaseEnumType::SummaryInventory)
318+
{
319+
response.status = GenericDeviceModelStatusEnumType::NotSupported;
320+
}
321+
else
322+
{
323+
std::thread report_thread(
324+
[this, type = request.reportBase, req_id = request.requestId]
325+
{
326+
NotifyReportReq notif_req;
327+
notif_req.requestId = req_id;
328+
notif_req.generatedAt = DateTime::now();
329+
notif_req.seqNo = 0;
330+
notif_req.tbc = false;
331+
332+
const auto& device_model = m_device_model.getModel();
333+
for (const auto& [_, comps] : device_model.components)
334+
{
335+
for (const auto& component : comps)
336+
{
337+
for (const auto& [_, vars] : component.variables)
338+
{
339+
for (const auto& [_, var] : vars)
340+
{
341+
if ((type == ReportBaseEnumType::FullInventory) || !var.attributes.type.isSet() ||
342+
(var.attributes.mutability.value() == MutabilityEnumType::ReadWrite))
343+
{
344+
ReportDataType report_data;
345+
report_data.component.name.assign(component.name);
346+
if (component.instance.isSet())
347+
{
348+
report_data.component.instance.value().assign(component.instance.value());
349+
}
350+
if (component.evse.isSet())
351+
{
352+
report_data.component.evse.value().id = component.evse.value();
353+
}
354+
if (component.connector.isSet())
355+
{
356+
report_data.component.evse.value().connectorId.value() = component.connector.value();
357+
}
358+
report_data.variable.name.assign(var.name);
359+
if (var.instance.isSet())
360+
{
361+
report_data.variable.instance.value().assign(var.instance.value());
362+
}
363+
report_data.variableAttribute.push_back(var.attributes);
364+
report_data.variableCharacteristics = var.characteristics;
365+
366+
notif_req.reportData.push_back(std::move(report_data));
367+
}
368+
}
369+
}
370+
}
371+
}
372+
373+
(void)device_model;
374+
375+
std::this_thread::sleep_for(std::chrono::seconds(1));
376+
377+
NotifyReportConf notif_conf;
378+
std::string error;
379+
std::string error_msg;
380+
m_chargepoint->call(notif_req, notif_conf, error, error_msg);
381+
});
382+
report_thread.detach();
383+
}
294384

295385
return ret;
296386
}
@@ -500,10 +590,7 @@ bool DefaultChargePointEventsHandler::onGetVariables(const ocpp::messages::ocpp2
500590

501591
for (const auto& var_data : request.getVariableData)
502592
{
503-
(void)var_data;
504-
505-
GetVariableResultType result;
506-
result.attributeStatus = GetVariableStatusEnumType::UnknownVariable;
593+
GetVariableResultType result = m_device_model.getVariable(var_data);
507594
response.getVariableResult.push_back(result);
508595
}
509596

@@ -783,10 +870,7 @@ bool DefaultChargePointEventsHandler::onSetVariables(const ocpp::messages::ocpp2
783870

784871
for (const auto& var_data : request.setVariableData)
785872
{
786-
SetVariableResultType result;
787-
result.attributeStatus = SetVariableStatusEnumType::Rejected;
788-
result.component = var_data.component;
789-
result.variable = var_data.variable;
873+
SetVariableResultType result = m_device_model.setVariable(var_data);
790874
response.setVariableResult.push_back(result);
791875
}
792876

examples/ocpp20/common/DefaultChargePointEventsHandler.h

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,18 +27,22 @@ SOFTWARE.
2727

2828
#include "IChargePoint20.h"
2929
#include "IChargePointEventsHandler20.h"
30+
#include "IDeviceModel20.h"
3031

3132
#include <filesystem>
3233
#include <vector>
3334

3435
class ChargePointDemoConfig;
3536

3637
/** @brief Default charge point event handlers implementation for the examples */
37-
class DefaultChargePointEventsHandler : public ocpp::chargepoint::ocpp20::IChargePointEventsHandler20
38+
class DefaultChargePointEventsHandler : public ocpp::chargepoint::ocpp20::IChargePointEventsHandler20,
39+
public ocpp::chargepoint::ocpp20::IDeviceModel20::IListener
3840
{
3941
public:
4042
/** @brief Constructor */
41-
DefaultChargePointEventsHandler(ChargePointDemoConfig& config, const std::filesystem::path& working_dir);
43+
DefaultChargePointEventsHandler(ChargePointDemoConfig& config,
44+
ocpp::chargepoint::ocpp20::IDeviceModel20& device_model,
45+
const std::filesystem::path& working_dir);
4246

4347
/** @brief Destructor */
4448
virtual ~DefaultChargePointEventsHandler();
@@ -49,6 +53,14 @@ class DefaultChargePointEventsHandler : public ocpp::chargepoint::ocpp20::ICharg
4953
/** @brief Indicate if the Charge Point is connected */
5054
bool isConnected() const { return m_is_connected; }
5155

56+
// IDeviceModel20 interface
57+
58+
/** @brief Called to retrieve the value of a variable */
59+
void getVariable(ocpp::types::ocpp20::GetVariableResultType& var) override;
60+
61+
/** @brief Called to set the value of a variable */
62+
ocpp::types::ocpp20::SetVariableStatusEnumType setVariable(const ocpp::types::ocpp20::SetVariableDataType& var) override;
63+
5264
// IChargePointEventsHandler20 interface
5365

5466
/** @copydoc void IChargePointEventsHandler20::connectionStateChanged() */
@@ -312,6 +324,8 @@ class DefaultChargePointEventsHandler : public ocpp::chargepoint::ocpp20::ICharg
312324
private:
313325
/** @brief Configuration */
314326
ChargePointDemoConfig& m_config;
327+
/** @brief Device model */
328+
ocpp::chargepoint::ocpp20::IDeviceModel20& m_device_model;
315329
/** @brief Associated Charge Point instance */
316330
ocpp::chargepoint::ocpp20::IChargePoint20* m_chargepoint;
317331
/** @brief Working directory */

examples/ocpp20/common/config/ChargePointDemoConfig.h

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ SOFTWARE.
2626
#define CHARGEPOINTDEMOCONFIG_H
2727

2828
#include "ChargePointConfig.h"
29+
#include "IDeviceModel20.h"
2930
#include "IniFile.h"
3031

3132
/** @brief Configuration of the Charge Point demo */
@@ -41,12 +42,62 @@ class ChargePointDemoConfig
4142
/** @brief Set the value of a stack internal configuration key */
4243
void setStackConfigValue(const std::string& key, const std::string& value) { m_stack_config.setConfigValue(key, value); }
4344

45+
/** @brief Get the value of a variable of the device model */
46+
bool getDeviceModelValue(const ocpp::types::ocpp20::ComponentType& component,
47+
const ocpp::types::ocpp20::VariableType& variable,
48+
std::string& value)
49+
{
50+
auto ini_value = m_config.get(buildComponentName(component), buildVariableName(variable));
51+
value = ini_value.toString();
52+
return true;
53+
}
54+
55+
/** @brief Set the value of a variable of the device model */
56+
bool setDeviceModelValue(const ocpp::types::ocpp20::ComponentType& component,
57+
const ocpp::types::ocpp20::VariableType& variable,
58+
const std::string& value)
59+
{
60+
m_config.set(buildComponentName(component), buildVariableName(variable), value);
61+
m_config.store();
62+
return true;
63+
}
64+
4465
private:
4566
/** @brief Configuration file */
4667
ocpp::helpers::IniFile m_config;
4768

4869
/** @brief Stack internal configuration */
4970
ChargePointConfig m_stack_config;
71+
72+
/** @brief Build the device model component unique name */
73+
std::string buildComponentName(const ocpp::types::ocpp20::ComponentType& component)
74+
{
75+
std::string name = component.name;
76+
if (component.instance.isSet())
77+
{
78+
name += "." + component.instance.value().str();
79+
}
80+
if (component.evse.isSet())
81+
{
82+
name += "." + std::to_string(component.evse.value().id);
83+
if (component.evse.value().connectorId.isSet())
84+
{
85+
name += "." + std::to_string(component.evse.value().connectorId.value());
86+
}
87+
}
88+
return name;
89+
}
90+
91+
/** @brief Build the device model variable unique name */
92+
std::string buildVariableName(const ocpp::types::ocpp20::VariableType& variable)
93+
{
94+
std::string name = variable.name;
95+
if (variable.instance.isSet())
96+
{
97+
name += "." + variable.instance.value().str();
98+
}
99+
return name;
100+
}
50101
};
51102

52103
#endif // CHARGEPOINTDEMOCONFIG_H

0 commit comments

Comments
 (0)