|
- /**
- * @file hmi_model.h
- * @brief 定义可保存的 HMI 页面、控件和寄存器绑定模型
- * @author suyu
- * @date 2026-08-10
- */
-
- #pragma once
-
- #include "register_address.h"
- #include "register_value_type.h"
- #include "project_limits.h"
-
- #include <map>
- #include <optional>
- #include <string>
- #include <variant>
- #include <vector>
-
- namespace HmiAppearanceProperty
- {
-
- inline constexpr const char kTextColor[] = "textColor";
- inline constexpr const char kFontSize[] = "fontSize";
- inline constexpr const char kFontBold[] = "fontBold";
- inline constexpr const char kFontItalic[] = "fontItalic";
-
- } // namespace HmiAppearanceProperty
-
- /**
- * @brief 描述 HMI 控件在页面坐标系中的位置和尺寸
- *
- * 页面校验要求矩形的左上角非负且完整位于页面范围内
- */
- struct HmiRect
- {
- static constexpr int kDefaultWidth = 80;
- static constexpr int kDefaultHeight = 32;
-
- int x = 0;
- int y = 0;
- int width = kDefaultWidth;
- int height = kDefaultHeight;
- };
-
- /**
- * @brief HMI 控件的基础类型
- *
- * 按钮和指示灯只能绑定 M 位,数值控件只能绑定 D 字
- */
- enum class HmiControlType
- {
- Button, // 按钮
- Indicator, // 指示灯
- NumericDisplay, // 数值显示
- NumericInput, // 数值输入
- Label, // 标签
- StatusText, // 状态文本
- PageJump, // 页面跳转
- AlarmList, // 报警列表
- Count // 已注册控件类型数量,不作为实际控件使用
- };
-
- /**
- * @brief 按钮对绑定 M 位执行的操作
- */
- enum class HmiButtonOperation
- {
- SetOn, // 按下时写入 1
- SetOff, // 按下时写入 0
- Toggle, // 按下时写入当前读回值的反值
- MomentaryOn // 按下时写入 1,释放时写入 0
- };
-
- /** @brief HMI 按钮 D 数值启用条件的比较方式 */
- enum class HmiButtonConditionOperator
- {
- Equal,
- NotEqual,
- LessThan,
- LessThanOrEqual,
- GreaterThan,
- GreaterThanOrEqual
- };
-
- struct HmiButtonBitEnableCondition
- {
- RegisterAddress address{RegisterArea::M, 0};
- bool expected = false;
-
- bool operator==(const HmiButtonBitEnableCondition &other) const
- {
- return address == other.address && expected == other.expected;
- }
- };
-
- struct HmiButtonWordEnableCondition
- {
- RegisterAddress address{RegisterArea::D, 0};
- RegisterDataType dataType = RegisterDataType::Int16;
- HmiButtonConditionOperator operation = HmiButtonConditionOperator::Equal;
- double value = 0.0;
-
- bool operator==(const HmiButtonWordEnableCondition &other) const
- {
- return address == other.address
- && dataType == other.dataType
- && operation == other.operation
- && value == other.value;
- }
- };
-
- using HmiButtonEnableCondition = std::variant<
- HmiButtonBitEnableCondition,
- HmiButtonWordEnableCondition>;
-
- struct HmiPageJumpConfig
- {
- std::string targetPageId;
- };
-
- struct HmiStatusBitTextConfig
- {
- std::string offText;
- std::string onText;
-
- bool operator==(const HmiStatusBitTextConfig &other) const
- {
- return offText == other.offText && onText == other.onText;
- }
- };
-
- struct HmiStatusValueRange
- {
- std::optional<double> lowerBound;
- std::optional<double> upperBound;
- std::string text;
-
- bool operator==(const HmiStatusValueRange &other) const
- {
- return lowerBound == other.lowerBound
- && upperBound == other.upperBound
- && text == other.text;
- }
- };
-
- struct HmiStatusWordTextConfig
- {
- std::vector<HmiStatusValueRange> ranges;
-
- bool operator==(const HmiStatusWordTextConfig &other) const
- {
- return ranges == other.ranges;
- }
- };
-
- using HmiStatusTextConfig = std::variant<
- HmiStatusBitTextConfig,
- HmiStatusWordTextConfig>;
-
- /**
- * @brief 描述一个可保存的 HMI 控件及其显示和寄存器配置
- *
- * `properties` 保存未纳入公共字段的字符串扩展属性
- */
- struct HmiControl
- {
- std::string id;
- HmiControlType type = HmiControlType::Label;
- HmiRect bounds;
- std::string text;
- std::optional<RegisterAddress> binding;
- RegisterDataType dataType = RegisterDataType::Int16;
- std::map<std::string, std::string> properties;
- HmiButtonOperation buttonOperation = HmiButtonOperation::MomentaryOn;
- std::optional<HmiButtonEnableCondition> buttonEnableCondition;
- std::optional<HmiPageJumpConfig> pageJump;
- std::optional<HmiStatusTextConfig> statusText;
-
- /**
- * @brief 校验控件的标识、尺寸、扩展属性和寄存器绑定
- * @param error 可选错误输出,失败时写入首个校验原因
- * @return 配置完整且满足控件类型绑定规则时返回 true
- *
- * 位控件必须绑定有效 M 地址,字控件必须绑定有效 D 地址
- */
- bool validate(std::string *error = nullptr) const;
- bool isConfigured() const;
- };
-
- /**
- * @brief 描述一个 HMI 页面及其控件集合
- *
- * 控件标识在同一页面内必须唯一,所有控件必须完整位于页面边界内
- */
- struct HmiPage
- {
- std::string id;
- std::string name;
- int width = ProjectLimits::kDefaultHmiPageWidth;
- int height = ProjectLimits::kDefaultHmiPageHeight;
- std::vector<HmiControl> controls;
-
- /**
- * @brief 校验页面尺寸、控件标识唯一性和全部控件配置
- * @param error 可选错误输出,失败时写入首个校验原因
- * @return 页面及其全部控件有效时返回 true
- */
- bool validate(
- const ProjectLimitSettings &limits,
- std::string *error = nullptr) const;
- bool validateForRunning(
- const ProjectLimitSettings &limits,
- std::string *error = nullptr) const;
- };
|