|
- #pragma once
-
- #include "domain/register_monitor_model.h"
- #include "domain/register_repository.h"
-
- #include <cstdint>
- #include <functional>
- #include <string>
- #include <vector>
-
- class VirtualRegisterRepository;
-
- // 自由监控列表编辑的失败分类
- enum class RegisterMonitorError
- {
- None, // 操作成功
- InvalidAddress, // 起始地址格式或区域不支持
- RangeOverflow, // 连续范围超出 M/D 地址上限
- LimitExceeded, // 监控地址数量超过会话上限
- NoChange // 操作没有产生任何列表变化
- };
-
- // 监控列表编辑结果;affectedCount 表示本次受影响的地址数量
- struct RegisterMonitorResult
- {
- bool succeeded = false; // 列表编辑是否成功
- RegisterMonitorError error = RegisterMonitorError::None; // 失败时的分类
- std::string message; // 面向用户的 UTF-8 成功说明或失败原因
- int affectedCount = 0; // 本次新增或删除的地址数量
- };
-
- // 自由监控写入结果;底层 RegisterError 会原样保留
- struct RegisterMonitorWriteResult
- {
- bool succeeded = false; // 写入请求是否成功提交
- RegisterError error = RegisterError::Unavailable; // 底层仓库错误分类
- std::string message; // 面向用户的 UTF-8 错误说明
- };
-
- /**
- * @brief 编排自由监控地址列表和寄存器仓库读写
- *
- * 地址列表和离线初始值只属于当前运行会话,不写入工程文件;仓库由当前运行模式注入
- */
- class RegisterMonitorService
- {
- public:
- /**
- * @brief 创建自由监控服务
- * @param repository 当前运行模式使用的寄存器仓库,不由服务拥有
- */
- explicit RegisterMonitorService(RegisterRepository &repository);
-
- // 配置编辑态离线初始值仓库;该仓库只保存在当前进程内
- void setOfflineInitialRepository(VirtualRegisterRepository &repository);
- // 编辑态开启时,监控写入同时更新离线初始值
- void setOfflineInitialCaptureEnabled(bool enabled);
-
- /**
- * @brief 从起始地址连续添加同一区域的多个地址
- * @param start_address 文本地址,例如 M0 或 D100
- * @param count 连续地址数量,必须为正且不能越过 4000
- * @return 去重后实际新增数量;格式、范围、容量或无变化时返回失败
- */
- RegisterMonitorResult addRange(const std::string &start_address, int count);
- RegisterMonitorResult addRange(
- const std::string &start_address, int count, RegisterDataType data_type);
- /**
- * @brief 删除一批监控地址
- * @param addresses 待删除地址;不存在的地址会被忽略
- * @return 实际删除数量,并在发生变化时通知轮询集合更新
- */
- RegisterMonitorResult remove(const std::vector<RegisterAddress> &addresses);
- RegisterMonitorResult remove(const std::vector<MonitorPoint> &points);
- /**
- * @brief 清空当前会话的监控地址列表
- * @return 实际清除数量;列表本来为空时返回 NoChange
- */
- RegisterMonitorResult clear();
- /**
- * @brief 对单个 M 地址提交位写入
- * @param address 必须是有效的 M 区地址
- * @param value 要写入的位值
- * @return 成功或包含底层 RegisterError 和用户可读文本的失败结果
- */
- RegisterMonitorWriteResult writeBit(const RegisterAddress &address, bool value);
- /**
- * @brief 对单个 D 地址提交有符号 16 位字写入
- * @param address 必须是有效的 D 区地址
- * @param value 要写入的 D 字值
- * @return 成功或包含底层 RegisterError 和用户可读文本的失败结果
- */
- RegisterMonitorWriteResult writeWord(
- const RegisterAddress &address, std::int16_t value);
- RegisterMonitorWriteResult writeFloat(
- const RegisterAddress &address, float value);
- /**
- * @brief 返回当前会话的监控地址列表
- * @return 按服务内部顺序保存的只读地址列表
- */
- const std::vector<RegisterAddress> &addresses() const;
- const std::vector<MonitorPoint> &points() const;
- std::vector<RegisterAddress> pollAddresses() const;
- std::vector<RegisterAddress> float32Starts() const;
- /**
- * @brief 读取监控列表的当前值并生成 UI 展示模型
- * @param communication_fault 通信处于故障态时,将成功读回值标记为通信故障
- * @return 每个监控地址对应一个值和可用性状态
- */
- std::vector<MonitorValue> values(bool communication_fault) const;
- /**
- * @brief 设置监控地址变化通知回调
- * @param callback 地址列表新增、删除或清空后调用;可传空函数取消通知
- */
- void setAddressesChangedCallback(std::function<void()> callback);
-
- private:
- RegisterMonitorWriteResult captureInitialBit(
- const RegisterAddress &address, bool value,
- const RegisterMonitorWriteResult &active_result);
- RegisterMonitorWriteResult captureInitialWord(
- const RegisterAddress &address, std::int16_t value,
- const RegisterMonitorWriteResult &active_result);
- RegisterMonitorWriteResult captureInitialFloat(
- const RegisterAddress &address, float value,
- const RegisterMonitorWriteResult &active_result);
-
- RegisterRepository &repository_; // 当前运行模式的寄存器仓库,不由服务拥有
- VirtualRegisterRepository *offline_initial_repository_ = nullptr;
- bool capture_offline_initial_values_ = false;
- RegisterMonitorModel model_; // 当前会话的去重监控地址列表
- std::function<void()> addresses_changed_callback_; // 地址变化后的轮询刷新通知
- };
|