ocpp 0.24.1
A C++ implementation of the Open Charge Point Protocol
device_model.hpp
1// SPDX-License-Identifier: Apache-2.0
2// Copyright 2020 - 2023 Pionix GmbH and Contributors to EVerest
3
4#ifndef DEVICE_MODEL_HPP
5#define DEVICE_MODEL_HPP
6
7#include <type_traits>
8
9#include <everest/logging.hpp>
10
11#include <ocpp/v2/device_model_storage_interface.hpp>
12
13namespace ocpp {
14namespace v2 {
15
18template <typename T> struct RequestDeviceModelResponse {
19 GetVariableStatusEnum status;
20 std::optional<T> value;
21};
22
27template <typename T> T to_specific_type(const std::string& value) {
28 static_assert(std::is_same<T, std::string>::value || std::is_same<T, int>::value ||
29 std::is_same<T, double>::value || std::is_same<T, size_t>::value ||
30 std::is_same<T, DateTime>::value || std::is_same<T, bool>::value ||
31 std::is_same<T, uint64_t>::value,
32 "Requested unknown datatype");
33
34 if constexpr (std::is_same<T, std::string>::value) {
35 return value;
36 } else if constexpr (std::is_same<T, int>::value) {
37 return std::stoi(value);
38 } else if constexpr (std::is_same<T, double>::value) {
39 return std::stod(value);
40 } else if constexpr (std::is_same<T, size_t>::value) {
41 size_t res = std::stoul(value);
42 return res;
43 } else if constexpr (std::is_same<T, DateTime>::value) {
44 return DateTime(value);
45 } else if constexpr (std::is_same<T, bool>::value) {
46 return ocpp::conversions::string_to_bool(value);
47 } else if constexpr (std::is_same<T, uint64_t>::value) {
48 return std::stoull(value);
49 }
50}
51
52template <DataEnum T> auto to_specific_type_auto(const std::string& value) {
53 static_assert(T == DataEnum::string || T == DataEnum::integer || T == DataEnum::decimal ||
54 T == DataEnum::dateTime || T == DataEnum::boolean,
55 "Requested unknown datatype");
56
57 if constexpr (T == DataEnum::string) {
58 return to_specific_type<std::string>(value);
59 } else if constexpr (T == DataEnum::integer) {
60 return to_specific_type<int>(value);
61 } else if constexpr (T == DataEnum::decimal) {
62 return to_specific_type<double>(value);
63 } else if constexpr (T == DataEnum::dateTime) {
64 return to_specific_type<DateTime>(value);
65 } else if constexpr (T == DataEnum::boolean) {
66 return to_specific_type<bool>(value);
67 }
68}
69
70template <DataEnum T> bool is_type_numeric() {
71 static_assert(T == DataEnum::string || T == DataEnum::integer || T == DataEnum::decimal ||
72 T == DataEnum::dateTime || T == DataEnum::boolean || T == DataEnum::OptionList ||
73 T == DataEnum::SequenceList || T == DataEnum::MemberList,
74 "Requested unknown datatype");
75
76 if constexpr (T == DataEnum::integer || T == DataEnum::decimal) {
77 return true;
78 } else {
79 return false;
80 }
81}
82
83typedef std::function<void(const std::unordered_map<int64_t, VariableMonitoringMeta>& monitors,
84 const Component& component, const Variable& variable,
85 const VariableCharacteristics& characteristics, const VariableAttribute& attribute,
86 const std::string& value_previous, const std::string& value_current)>
87 on_variable_changed;
88
89typedef std::function<void(const VariableMonitoringMeta& updated_monitor, const Component& component,
90 const Variable& variable, const VariableCharacteristics& characteristics,
91 const VariableAttribute& attribute, const std::string& current_value)>
92 on_monitor_updated;
93
97
98private:
99 DeviceModelMap device_model_map;
100 std::unique_ptr<DeviceModelStorageInterface> device_model;
101
103 on_variable_changed variable_listener;
105 on_monitor_updated monitor_update_listener;
106
116 GetVariableStatusEnum request_value_internal(const Component& component_id, const Variable& variable_id,
117 const AttributeEnum& attribute_enum, std::string& value,
118 bool allow_write_only) const;
119
127 bool component_criteria_match(const Component& component_id,
128 const std::vector<ComponentCriterionEnum>& component_criteria);
129
135 bool component_variables_match(const std::vector<ComponentVariable>& component_variables,
136 const ocpp::v2::Component& component_, const struct ocpp::v2::Variable& variable_);
137
138public:
141 explicit DeviceModel(std::unique_ptr<DeviceModelStorageInterface> device_model_storage_interface);
142
149 template <typename T>
150 T get_value(const RequiredComponentVariable& component_variable,
151 const AttributeEnum& attribute_enum = AttributeEnum::Actual) const {
152 std::string value;
153 auto response = GetVariableStatusEnum::UnknownVariable;
154 if (component_variable.variable.has_value()) {
155 response = this->request_value_internal(component_variable.component, component_variable.variable.value(),
156 attribute_enum, value, true);
157 }
158 if (response == GetVariableStatusEnum::Accepted) {
159 return to_specific_type<T>(value);
160 } else {
161 EVLOG_critical << "Directly requested value for ComponentVariable that doesn't exist in the device model: "
162 << component_variable;
163 EVLOG_AND_THROW(std::runtime_error(
164 "Directly requested value for ComponentVariable that doesn't exist in the device model."));
165 }
166 }
167
174 template <typename T>
175 std::optional<T> get_optional_value(const ComponentVariable& component_variable,
176 const AttributeEnum& attribute_enum = AttributeEnum::Actual) const {
177 std::string value;
178 auto response = GetVariableStatusEnum::UnknownVariable;
179 if (component_variable.variable.has_value()) {
180 response = this->request_value_internal(component_variable.component, component_variable.variable.value(),
181 attribute_enum, value, true);
182 }
183 if (response == GetVariableStatusEnum::Accepted) {
184 return to_specific_type<T>(value);
185 } else {
186 return std::nullopt;
187 }
188 }
189
198 template <typename T>
199 RequestDeviceModelResponse<T> request_value(const Component& component_id, const Variable& variable_id,
200 const AttributeEnum& attribute_enum) {
201 std::string value;
202 const auto req_status = this->request_value_internal(component_id, variable_id, attribute_enum, value, false);
203
204 if (req_status == GetVariableStatusEnum::Accepted) {
205 return {GetVariableStatusEnum::Accepted, to_specific_type<T>(value)};
206 } else {
207 return {req_status};
208 }
209 }
210
216 std::optional<MutabilityEnum> get_mutability(const Component& component_id, const Variable& variable,
217 const AttributeEnum& attribute_enum);
218
229 SetVariableStatusEnum set_value(const Component& component_id, const Variable& variable_id,
230 const AttributeEnum& attribute_enum, const std::string& value,
231 const std::string& source, const bool allow_read_only = false);
240 SetVariableStatusEnum set_read_only_value(const Component& component_id, const Variable& variable_id,
241 const AttributeEnum& attribute_enum, const std::string& value,
242 const std::string& source);
243
248 std::optional<VariableMetaData> get_variable_meta_data(const Component& component_id, const Variable& variable_id);
249
256 std::vector<ReportData> get_base_report_data(const ReportBaseEnum& report_base);
257
264 std::vector<ReportData>
265 get_custom_report_data(const std::optional<std::vector<ComponentVariable>>& component_variables = std::nullopt,
266 const std::optional<std::vector<ComponentCriterionEnum>>& component_criteria = std::nullopt);
267
268 void register_variable_listener(on_variable_changed&& listener) {
269 variable_listener = std::move(listener);
270 }
271
272 void register_monitor_listener(on_monitor_updated&& listener) {
273 monitor_update_listener = std::move(listener);
274 }
275
282 std::vector<SetMonitoringResult> set_monitors(const std::vector<SetMonitoringData>& requests,
283 const VariableMonitorType type = VariableMonitorType::CustomMonitor);
284
285 bool update_monitor_reference(int32_t monitor_id, const std::string& reference_value);
286
287 std::vector<VariableMonitoringPeriodic> get_periodic_monitors();
288
293 std::vector<MonitoringData> get_monitors(const std::vector<MonitoringCriterionEnum>& criteria,
294 const std::vector<ComponentVariable>& component_variables);
295
301 std::vector<ClearMonitoringResult> clear_monitors(const std::vector<int>& request_ids,
302 bool allow_protected = false);
303
306 int32_t clear_custom_monitors();
307
310 void check_integrity(const std::map<int32_t, int32_t>& evse_connector_structure);
311};
312
313} // namespace v2
314} // namespace ocpp
315
316#endif // DEVICE_MODEL_HPP
This class manages access to the device model representation and to the device model interface and pr...
Definition: device_model.hpp:96
std::vector< ReportData > get_custom_report_data(const std::optional< std::vector< ComponentVariable > > &component_variables=std::nullopt, const std::optional< std::vector< ComponentCriterionEnum > > &component_criteria=std::nullopt)
Gets the ReportData for the specifed filter component_variables and component_criteria.
Definition: device_model.cpp:391
std::optional< MutabilityEnum > get_mutability(const Component &component_id, const Variable &variable, const AttributeEnum &attribute_enum)
Get the mutability for the given component, variable and attribute_enum.
Definition: device_model.cpp:253
std::vector< ReportData > get_base_report_data(const ReportBaseEnum &report_base)
Gets the ReportData for the specifed filter report_base component_variables and component_criteria.
Definition: device_model.cpp:349
SetVariableStatusEnum set_read_only_value(const Component &component_id, const Variable &variable_id, const AttributeEnum &attribute_enum, const std::string &value, const std::string &source)
Sets the variable_id attribute value specified by component_id , variable_id and attribute_enum for r...
Definition: device_model.cpp:329
void check_integrity(const std::map< int32_t, int32_t > &evse_connector_structure)
Check data integrity of the device model provided by the device model data storage: For "required" va...
Definition: device_model.cpp:423
std::optional< VariableMetaData > get_variable_meta_data(const Component &component_id, const Variable &variable_id)
Gets the VariableMetaData for the given component_id and variable_id.
Definition: device_model.cpp:340
RequestDeviceModelResponse< T > request_value(const Component &component_id, const Variable &variable_id, const AttributeEnum &attribute_enum)
Requests a value of a VariableAttribute specified by combination of component_id and variable_id from...
Definition: device_model.hpp:199
std::optional< T > get_optional_value(const ComponentVariable &component_variable, const AttributeEnum &attribute_enum=AttributeEnum::Actual) const
Access to std::optional of a VariableAttribute for the given component, variable and attribute_enum.
Definition: device_model.hpp:175
std::vector< MonitoringData > get_monitors(const std::vector< MonitoringCriterionEnum > &criteria, const std::vector< ComponentVariable > &component_variables)
Gets the Monitoring data for the request criteria and component_variables.
Definition: device_model.cpp:731
T get_value(const RequiredComponentVariable &component_variable, const AttributeEnum &attribute_enum=AttributeEnum::Actual) const
Direct access to value of a VariableAttribute for the given component, variable and attribute_enum....
Definition: device_model.hpp:150
std::vector< ClearMonitoringResult > clear_monitors(const std::vector< int > &request_ids, bool allow_protected=false)
Clears the given request_ids from the registered monitors if request_id is present.
Definition: device_model.cpp:811
SetVariableStatusEnum set_value(const Component &component_id, const Variable &variable_id, const AttributeEnum &attribute_enum, const std::string &value, const std::string &source, const bool allow_read_only=false)
Sets the variable_id attribute value specified by component_id , variable_id and attribute_enum.
Definition: device_model.cpp:263
DeviceModel(std::unique_ptr< DeviceModelStorageInterface > device_model_storage_interface)
Constructor for the device model.
Definition: device_model.cpp:324
int32_t clear_custom_monitors()
Clears all the custom monitors (set by the CSMS) present in the database.
Definition: device_model.cpp:846
std::vector< SetMonitoringResult > set_monitors(const std::vector< SetMonitoringData > &requests, const VariableMonitorType type=VariableMonitorType::CustomMonitor)
Sets the given monitor requests in the device model.
Definition: device_model.cpp:533
Definition: ocpp_types.hpp:334
Definition: ocpp_types.hpp:303
Response to requesting a value from the device model.
Definition: device_model.hpp:18
Definition: ocpp_types.hpp:969
Definition: ocpp_types.hpp:319