|
- #pragma once
-
- #include "project_limits.h"
- #include "register_address.h"
-
- #include <cstdint>
- #include <optional>
- #include <string>
- #include <variant>
- #include <vector>
-
- enum class ContactMode
- {
- NormallyOpen, // 常开触点,M 为 1 时条件成立
- NormallyClosed // 常闭触点,M 为 0 时条件成立
- };
-
- enum class CoilMode
- {
- Normal, // 普通线圈,直接写入条件结果
- Set, // 条件成立时置位 M
- Reset // 条件成立时复位 M
- };
-
- enum class EdgeMode
- {
- Rising, // 检测 M 从 0 变为 1
- Falling // 检测 M 从 1 变为 0
- };
-
- enum class ComparisonOperator
- {
- Equal, // 等于
- NotEqual, // 不等于
- LessThan, // 小于
- LessThanOrEqual, // 小于或等于
- GreaterThan, // 大于
- GreaterThanOrEqual // 大于或等于
- };
-
- enum class WordOperandKind
- {
- Constant, // 使用固定数值
- Register // 使用 D 区寄存器的值
- };
-
- struct WordOperand
- {
- WordOperandKind kind = WordOperandKind::Constant; // 操作数来源类型
- RegisterAddress address{RegisterArea::D, 0}; // 寄存器操作数使用的 D 地址
- std::int16_t constant = 0; // 常量操作数的数值
-
- // 校验操作数类型和寄存器地址是否有效
- bool validate(std::string *error = nullptr) const;
- };
-
- struct ContactNodeConfig
- {
- RegisterAddress address{RegisterArea::M, 0}; // 触点监控的 M 地址
- ContactMode mode = ContactMode::NormallyOpen; // 触点的常开或常闭模式
- };
-
- struct EdgeContactNodeConfig
- {
- RegisterAddress address{RegisterArea::M, 0}; // 边沿触点监控的 M 地址
- EdgeMode mode = EdgeMode::Rising; // 上升沿或下降沿模式
- };
-
- struct CoilNodeConfig
- {
- RegisterAddress address{RegisterArea::M, 0}; // 线圈写入的 M 地址
- CoilMode mode = CoilMode::Normal; // 普通、置位或复位模式
- };
-
- struct CompareNodeConfig
- {
- RegisterAddress address{RegisterArea::D, 0}; // 参与比较的 D 地址
- ComparisonOperator comparison = ComparisonOperator::Equal; // 比较方式
- std::int16_t value = 0; // 与 D 值比较的常量
- };
-
- struct MoveNodeConfig
- {
- WordOperand source; // MOVE 的源操作数
- RegisterAddress destination{RegisterArea::D, 0}; // MOVE 的目标 D 地址
- };
-
- enum class ArithmeticOperation
- {
- Add, // 加法
- Subtract // 减法
- };
-
- struct ArithmeticNodeConfig
- {
- ArithmeticOperation operation = ArithmeticOperation::Add; // 算术运算类型
- WordOperand left; // 左操作数
- WordOperand right; // 右操作数
- RegisterAddress destination{RegisterArea::D, 0}; // 运算结果写入的 D 地址
- };
-
- using LogicNodeConfig = std::variant<
- ContactNodeConfig,
- EdgeContactNodeConfig,
- CoilNodeConfig,
- CompareNodeConfig,
- MoveNodeConfig,
- ArithmeticNodeConfig>;
-
- // 返回逻辑节点主要使用的地址
- std::optional<RegisterAddress> registerAddressForLogicNode(
- const LogicNodeConfig &config);
- // 收集逻辑节点涉及的全部有效寄存器地址
- void collectRegisterAddressesForLogicNode(
- const LogicNodeConfig &config,
- std::vector<RegisterAddress> *addresses);
-
- struct LogicNode
- {
- std::string id; // 逻辑节点的唯一 ID
- LogicNodeConfig config; // 节点类型和具体参数
- bool configured = true; // 是否已完成运行所需的配置
-
- // 校验节点 ID 和节点参数
- bool validate(std::string *error = nullptr) const;
- // 返回节点是否已完成运行配置
- bool isConfigured() const;
- // 返回节点是否属于条件节点
- bool isCondition() const;
- // 返回节点是否属于输出节点
- bool isOutput() const;
- };
-
- enum class LadderCellKind
- {
- Gap, // 空白网格
- Wire, // 横向导线网格
- Node // 条件节点网格
- };
-
- // 条件区的一个固定网格,横线和空白与条件节点具有同等持久化地位
- struct LadderCell
- {
- std::string id; // 网格的唯一 ID
- LadderCellKind kind = LadderCellKind::Gap; // 网格类型
- std::optional<LogicNode> node; // 网格中的条件节点
-
- // 校验网格 ID、类型和节点内容是否匹配
- bool validate(std::string *error = nullptr) const;
- };
-
- // 两个相邻视觉行之间、指定列边界上的一段竖线
- struct VerticalConnection
- {
- std::string id; // 竖线的唯一 ID
- std::string upperRungId; // 竖线连接的上方行 ID
- std::string lowerRungId; // 竖线连接的下方行 ID
- int columnBoundary = 0; // 竖线所在的列边界
-
- // 校验竖线的关联行和列边界
- bool validate(std::string *error = nullptr) const;
- };
-
- // 连续梯形图的一条视觉行,不再是隔离的网络容器
- struct LadderRung
- {
- std::string id; // 梯形图行的唯一 ID
- std::string name; // 梯形图行名称
- std::string comment; // 网络首行上的注释
- std::optional<LogicNode> output; // 行末输出节点
- std::vector<LadderCell> cells; // 固定数量的条件网格
-
- // 校验梯形图行的完整结构
- bool validate(std::string *error = nullptr) const;
- // 校验保存时需要满足的结构规则
- bool validateStructure(std::string *error = nullptr) const;
- // 校验运行前的结构和节点配置
- bool validateForRunning(std::string *error = nullptr) const;
- };
-
- // 一张连续梯形图,网络由横竖连接关系自然形成
- struct ControlLogic
- {
- std::string id; // 控制逻辑的唯一 ID
- std::string name; // 控制逻辑名称
- std::vector<LadderRung> rungs; // 按视觉顺序保存的梯形图行
- bool enabled = true; // 是否参与运行扫描
- std::vector<VerticalConnection> verticalConnections; // 行之间的竖向连接
-
- // 返回指定行所在连续网络的首行下标
- std::size_t networkHeadIndex(std::size_t rung_index) const;
- // 使用指定工程限制校验控制逻辑
- bool validate(
- const ProjectLimitSettings &limits,
- std::string *error = nullptr) const;
- // 使用默认工程限制校验控制逻辑结构
- bool validateStructure(std::string *error = nullptr) const;
- // 使用指定工程限制校验控制逻辑结构
- bool validateStructure(
- const ProjectLimitSettings &limits,
- std::string *error = nullptr) const;
- // 使用默认工程限制校验运行前的控制逻辑
- bool validateForRunning(std::string *error = nullptr) const;
- // 使用指定工程限制校验运行前的控制逻辑
- bool validateForRunning(
- const ProjectLimitSettings &limits,
- std::string *error = nullptr) const;
- };
-
- // 在梯形图行中查找指定 ID 的只读网格
- const LadderCell *findLadderCell(
- const LadderRung &rung, const std::string &cell_id);
- // 在梯形图行中查找指定 ID 的可写网格
- LadderCell *findLadderCell(
- LadderRung &rung, const std::string &cell_id);
- // 在控制逻辑中查找指定 ID 的只读竖线
- const VerticalConnection *findVerticalConnection(
- const ControlLogic &logic, const std::string &connection_id);
- // 在控制逻辑中查找指定 ID 的可写竖线
- VerticalConnection *findVerticalConnection(
- ControlLogic &logic, const std::string &connection_id);
- // 收集一行中的全部条件节点
- void collectConditionNodes(
- const LadderRung &rung, std::vector<const LogicNode *> *nodes);
- // 收集控制逻辑中的全部条件节点和输出节点
- void collectLogicNodes(
- const ControlLogic &logic, std::vector<const LogicNode *> *nodes);
|