|
- #include "data_point_service.h"
-
- #include "project_service.h"
-
- #include <algorithm>
-
- namespace {
-
- bool nodeUsesAddress(const LogicNode &node, const RegisterAddress &address)
- {
- return std::visit(
- [&address](const auto &config) { return config.address == address; },
- node.config);
- }
-
- } // namespace
-
- DataPointService::DataPointService(ProjectService &project_service)
- : project_service_(project_service)
- {
- }
-
- const std::vector<DataPoint> &DataPointService::dataPoints() const
- {
- return project_service_.project().dataPoints;
- }
-
- const DataPoint *DataPointService::find(const RegisterAddress &address) const
- {
- const auto &points = dataPoints();
- const auto found = std::find_if(
- points.cbegin(), points.cend(),
- [&address](const DataPoint &point) { return point.address == address; });
- return found == points.cend() ? nullptr : &*found;
- }
-
- DataPointResult DataPointService::add(const DataPoint &data_point)
- {
- const DataPointResult validation = validateUnique(data_point, nullptr);
- if (!validation.succeeded)
- {
- return validation;
- }
- project_service_.editProject().dataPoints.push_back(data_point);
- return {true, DataPointError::None, {}};
- }
-
- DataPointResult DataPointService::update(
- const RegisterAddress &old_address, const DataPoint &data_point)
- {
- const auto existing = std::find_if(
- dataPoints().cbegin(), dataPoints().cend(),
- [&old_address](const DataPoint &candidate)
- {
- return candidate.address == old_address;
- });
- if (existing == dataPoints().cend())
- {
- return {false, DataPointError::NotFound, "data point was not found"};
- }
- const DataPointResult validation = validateUnique(data_point, &old_address);
- if (!validation.succeeded)
- {
- return validation;
- }
- if (data_point.address != old_address && !references(old_address).empty())
- {
- return {false, DataPointError::AddressInUse,
- "referenced data point address cannot be changed"};
- }
- Project &project = project_service_.editProject();
- const auto point = std::find_if(
- project.dataPoints.begin(), project.dataPoints.end(),
- [&old_address](const DataPoint &candidate)
- {
- return candidate.address == old_address;
- });
- *point = data_point;
- return {true, DataPointError::None, {}};
- }
-
- DataPointResult DataPointService::remove(const RegisterAddress &address)
- {
- if (find(address) == nullptr)
- {
- return {false, DataPointError::NotFound, "data point was not found"};
- }
- if (!references(address).empty())
- {
- return {false, DataPointError::AddressInUse,
- "data point is still referenced by HMI or ladder logic"};
- }
- Project &project = project_service_.editProject();
- project.dataPoints.erase(
- std::remove_if(
- project.dataPoints.begin(), project.dataPoints.end(),
- [&address](const DataPoint &point) { return point.address == address; }),
- project.dataPoints.end());
- return {true, DataPointError::None, {}};
- }
-
- std::vector<DataPointReference> DataPointService::references(
- const RegisterAddress &address) const
- {
- std::vector<DataPointReference> result;
- const Project &project = project_service_.project();
- for (const HmiPage &page : project.hmiPages)
- {
- for (const HmiControl &control : page.controls)
- {
- if (control.binding.has_value() && *control.binding == address)
- {
- result.push_back({"HMI/" + page.name + '/' + control.id});
- }
- }
- }
- for (const ControlLogic &logic : project.controlLogics)
- {
- for (const LadderRung &rung : logic.rungs)
- {
- if (rung.condition.has_value())
- {
- std::vector<const LogicNode *> nodes;
- collectConditionNodes(*rung.condition, &nodes);
- for (const LogicNode *node : nodes)
- {
- if (nodeUsesAddress(*node, address))
- {
- result.push_back({"LAD/" + logic.name + '/' + rung.name + '/' + node->id});
- }
- }
- }
- if (rung.output.has_value() && nodeUsesAddress(*rung.output, address))
- {
- result.push_back({"LAD/" + logic.name + '/' + rung.name + '/'
- + rung.output->id});
- }
- }
- }
- return result;
- }
-
- DataPointResult DataPointService::validateUnique(
- const DataPoint &data_point,
- const RegisterAddress *ignored_address) const
- {
- std::string error;
- if (!data_point.validate(&error))
- {
- return {false, DataPointError::InvalidDataPoint, error};
- }
- for (const DataPoint &existing : dataPoints())
- {
- if (ignored_address != nullptr && existing.address == *ignored_address)
- {
- continue;
- }
- if (existing.address == data_point.address)
- {
- return {false, DataPointError::DuplicateAddress,
- "data point address already exists"};
- }
- if (existing.name == data_point.name)
- {
- return {false, DataPointError::DuplicateName,
- "data point name already exists"};
- }
- }
- return {true, DataPointError::None, {}};
- }
|