Skip to content

Commit

Permalink
Updated for spec request: N07.FR.11
Browse files Browse the repository at this point in the history
Signed-off-by: AssemblyJohn <[email protected]>
  • Loading branch information
AssemblyJohn committed Aug 9, 2024
1 parent f7ace37 commit aaccfd3
Show file tree
Hide file tree
Showing 5 changed files with 213 additions and 106 deletions.
11 changes: 11 additions & 0 deletions include/ocpp/v201/device_model.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,11 @@ typedef std::function<void(const std::unordered_map<int64_t, VariableMonitoringM
const std::string& value_previous, const std::string& value_current)>
on_variable_changed;

typedef std::function<void(const VariableMonitoringMeta& updated_monitor, const Component& component,
const Variable& variable, const VariableCharacteristics& characteristics,
const VariableAttribute& attribute, const std::string& current_value)>
on_monitor_updated;

/// \brief This class manages access to the device model representation and to the device model storage and provides
/// functionality to support the use cases defined in the functional block Provisioning
class DeviceModel {
Expand All @@ -93,6 +98,8 @@ class DeviceModel {

/// \brief Listener for the internal change of a variable
on_variable_changed variable_listener;
/// \brief Listener for the internal update of a monitor
on_monitor_updated monitor_update_listener;

/// \brief Private helper method that does some checks with the device model representation in memory to evaluate if
/// a value for the given parameters can be requested. If it can be requested it will be retrieved from the device
Expand Down Expand Up @@ -253,6 +260,10 @@ class DeviceModel {
variable_listener = std::move(listener);
}

void register_monitor_listener(on_monitor_updated&& listener) {
monitor_update_listener = std::move(listener);
}

/// \brief Sets the given monitor \p requests in the device model
/// \param request
/// \param type The type of the set monitors. HardWiredMonitor - used for OEM specific monitors,
Expand Down
14 changes: 14 additions & 0 deletions include/ocpp/v201/init_device_model_db.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -344,15 +344,29 @@ class InitDeviceModelDb : public common::DatabaseHandlerCommon {
///
void delete_attribute(const DbVariableAttribute& attribute);

///
/// \brief Inserts a single monitor in the database
/// \param monitor Monitor data
/// \param variable_id Variable ID for which we insert this monitor
void insert_variable_monitor(const VariableMonitoringMeta& monitor, const int64_t& variable_id);

///
/// \brief same as \ref insert_variable_monitor but will simply iterate the monitors and call the function
void insert_variable_monitors(const std::vector<VariableMonitoringMeta>& monitors, const int64_t& variable_id);

///
/// \brief Updates the monitor in the database, using the information from the new monitor
void update_variable_monitor(const VariableMonitoringMeta& new_monitor, const VariableMonitoringMeta& db_monitor,
const int64_t& variable_id);

///
/// \brief Updates the monitors in the database, removing the monitors that do not exist
/// in the configuration file, and inserting the new ones that were newly added
void update_variable_monitors(const std::vector<VariableMonitoringMeta>& new_monitors,
const std::vector<VariableMonitoringMeta>& db_monitors, const int64_t& variable_id);

///
/// \brief Deletes a single monitor related to the provided variable_id from the database
void delete_variable_monitor(const VariableMonitoringMeta& monitor, const int64_t& variable_id);

///
Expand Down
14 changes: 14 additions & 0 deletions include/ocpp/v201/monitoring_updater.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,20 @@ class MonitoringUpdater {
const VariableCharacteristics& characteristics, const VariableAttribute& attribute,
const std::string& value_old, const std::string& value_current);

/// \brief Callback that is registered to the 'device_model' that determines if any of
/// the already existing monitors were updated. It is required for some spec requirements
/// that must refresh monitor data in the case of a monitor update
void on_monitor_updated(const VariableMonitoringMeta& updated_monitor, const Component& component,
const Variable& variable, const VariableCharacteristics& characteristics,
const VariableAttribute& attribute, const std::string& current_value);

/// \brief Evaluates if an monitor was triggered, and if it is triggered
/// it adds it to our internal list
void evaluate_monitor(const VariableMonitoringMeta& monitor_meta, const Component& component,
const Variable& variable, const VariableCharacteristics& characteristics,
const VariableAttribute& attribute, const std::string& value_previous,
const std::string& value_current);

/// \brief Processes the periodic monitors. Since this can be somewhat of a costly
/// operation (DB query of each triggered monitor's actual value) the processing time
/// can be configured using the 'VariableMonitoringProcessTime' internal variable. If
Expand Down
22 changes: 21 additions & 1 deletion lib/ocpp/v201/device_model.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -566,7 +566,9 @@ std::vector<SetMonitoringResult> DeviceModel::set_monitors(const std::vector<Set
}
}

if (this->device_model.find(request.component) == this->device_model.end()) {
auto component_it = this->device_model.find(request.component);

if (component_it == this->device_model.end()) {
// N04.FR.16
if (request_has_id && id_found) {
result.status = SetMonitoringStatusEnum::Rejected;
Expand Down Expand Up @@ -656,6 +658,24 @@ std::vector<SetMonitoringResult> DeviceModel::set_monitors(const std::vector<Set
auto monitor_meta = this->storage->set_monitoring_data(request, type);

if (monitor_meta.has_value()) {
// N07.FR.11
// In case of an existing monitor update
if (request_has_id && monitor_update_listener) {
auto attribute = this->storage->get_variable_attribute(component_it->first, variable_it->first,
AttributeEnum::Actual);

if (attribute.has_value()) {
static std::string empty_value{};
const auto& current_value = attribute.value().value.value_or(empty_value);

monitor_update_listener(monitor_meta.value(), component_it->first, variable_it->first,
characteristics, attribute.value(), current_value);
} else {
EVLOG_warning << "Could not notify monitor update listener, missing variable attribute: "
<< variable_it->first;
}
}

// If we had a successful insert, add/replace it to the variable monitor map
variable_it->second.monitors[monitor_meta.value().monitor.id] = std::move(monitor_meta.value());

Expand Down
Loading

0 comments on commit aaccfd3

Please sign in to comment.