Add READMEs for RICS, eqpm, dsm and update eqpalg README with corrections
- RICS_readme.md: Rule information centralized display service - eqpm_readme.md: Equipment predictive maintenance & status monitoring - dsm_readme.md: Data save manager for historical data archiving - eqpalg_readme.md: Corrected architecture, data flow, variable system, thread model, and inter-process relationships
This commit is contained in:
parent
92a23222f7
commit
bd7e93ae68
120
RICS/RICS_readme.md
Normal file
120
RICS/RICS_readme.md
Normal file
@ -0,0 +1,120 @@
|
|||||||
|
# RICS — 规则信息集中服务
|
||||||
|
|
||||||
|
## 概述
|
||||||
|
|
||||||
|
RICS(**R**ule **I**nfo **C**entralized **S**ervice)是 EIS 系统中的规则配置信息集中展示服务。它**不执行算法**,而是将 DB2 中配置的所有规则解析、格式化为结构化 JSON,然后推送到 Memcached 供前端页面和仪表盘使用。
|
||||||
|
|
||||||
|
与 eqpalg 不同,RICS 不做实时数据监控和报警,它专职负责**规则的配置信息的读取和格式化输出**。
|
||||||
|
|
||||||
|
## 进程架构
|
||||||
|
|
||||||
|
RICS 作为单个 PACE 平台组件运行,注册 ICE 端点 `"baosight/RICS"`,通过定时器周期性刷新全量规则信息。
|
||||||
|
|
||||||
|
```
|
||||||
|
┌─────────────────────────────────────────────┐
|
||||||
|
│ RICS 进程 │
|
||||||
|
│ │
|
||||||
|
│ TimeNotify() ──→ RICSAlg::timed_task() │
|
||||||
|
│ │ │
|
||||||
|
│ ├→ alg_handle(algId) │
|
||||||
|
│ │ ├─ 读 T_RULE_CFG │
|
||||||
|
│ │ ├─ 解析 ruleParam │
|
||||||
|
│ │ └─ exp_handle() │
|
||||||
|
│ │ │
|
||||||
|
│ ├→ get_json_by_algid() │
|
||||||
|
│ │ └─ 格式化为JSON │
|
||||||
|
│ │ │
|
||||||
|
│ └→ write_memcaced() │
|
||||||
|
│ └─ Memcached 写入 │
|
||||||
|
└─────────────────────────────────────────────┘
|
||||||
|
```
|
||||||
|
|
||||||
|
## ICE 接口
|
||||||
|
|
||||||
|
| 方法 | 说明 |
|
||||||
|
|------|------|
|
||||||
|
| `SendDataShort(99999, seq)` | 调试/测试入口,调用 `RICS_alg_->dispose()` |
|
||||||
|
| `SendDataLong(...)` | 复杂数据接口(未实现) |
|
||||||
|
| `TimeNotify(...)` | 定时触发,调用 `timed_task()` 全量刷新 |
|
||||||
|
|
||||||
|
## 核心工作流
|
||||||
|
|
||||||
|
### `timed_task()` — 定时刷新
|
||||||
|
|
||||||
|
定时触发后,遍历 **15 种算法 ID**(`{1,2,3,4,5,6,7,8,12,13,14,15,16,17,18}`),对每种算法:
|
||||||
|
|
||||||
|
1. **`alg_handle(algId)`** — 从 DB2 `T_RULE_CFG` 读取该算法类型下的所有规则配置
|
||||||
|
2. **`exp_handle()`** — 按算法 ID 解析 `ruleParam` JSON,提取表达式字符串、参数、阈值等
|
||||||
|
3. **`get_json_by_algid()`** — 将所有规则组装为 `{columns: [...], data: [[...]]}` 的表格 JSON
|
||||||
|
4. **`write_memcaced()`** — 以 `"{unitNo}_Alg_{algId}"` 为 key 写入 Memcached
|
||||||
|
|
||||||
|
### 算法参数解析 (`exp_handle()`)
|
||||||
|
|
||||||
|
针对不同算法 ID 提取不同的参数字段:
|
||||||
|
|
||||||
|
| algId | 算法类型 | 表达式数 | 关键参数 |
|
||||||
|
|-------|----------|---------|----------|
|
||||||
|
| 1 | 简单报警 | 1 | — |
|
||||||
|
| 2 | 阈值监控 | 2 | limit_down, limit_up, unit |
|
||||||
|
| 3 | 动作-反馈(逻辑) | 3 | hold, timeout |
|
||||||
|
| 4 | 动作-反馈(阈值) | 3 | hold, timeout, limit_down, limit_up |
|
||||||
|
| 5 | 持续限值 | 2 | hold_time, limit_down, limit_up |
|
||||||
|
| 6 | 保持时间 | 1 | limit_time(小时) |
|
||||||
|
| 7 | 出现次数 | 1 | limit_times |
|
||||||
|
| 8 | 斜率/趋势 | 1 | interval_time, deltaX, diff, CS_AVG_SIZE |
|
||||||
|
| 12 | 相关性 | 3 | scale, min_len |
|
||||||
|
| 13 | 相关性+最小长度 | 3 | scale, min_len |
|
||||||
|
| 14 | 变化率 | 1 | interval_time, deltaX, diff(%), CS_AVG_SIZE |
|
||||||
|
| 15 | 数据窗口 | 1 | length(100-1000) |
|
||||||
|
| 16 | 多变量离群 | 2 | detect_mode, limit_warn, limit_error, hold_time |
|
||||||
|
| 17 | 限幅检查 | 2 | limit_warn, limit_error |
|
||||||
|
| 18 | 多变量离群v2 | 2 | 同 algId 16 |
|
||||||
|
|
||||||
|
### Memcached 输出
|
||||||
|
|
||||||
|
- **Key 格式**: `"{unitNo}_Alg_{algId}"`(如 `C308_Alg_1`)
|
||||||
|
- **Value 格式**: `{"columns": [...], "data": [[...]]}`
|
||||||
|
- 列包含:规则ID、规则名称、机组、标签名及中文翻译、表达式、参数等
|
||||||
|
|
||||||
|
## 关键技术细节
|
||||||
|
|
||||||
|
- **规则配置来源**: DB2 `T_RULE_CFG` 表,其中 `ruleParam` 是 JSON 字符串,包含 tags、before_exec(前提条件表达式)、function(算法参数)三大部分
|
||||||
|
- **中文翻译**: 通过 `BinaryTele` 从共享内存读取 `T_LOV_FDAAITEM` 表,构建 item 名→中文翻译的映射
|
||||||
|
- **算法 ID 缺失**: 算法 9、10、11 从未在 RICS 中实现展示
|
||||||
|
|
||||||
|
## 与 eqpalg 的关系
|
||||||
|
|
||||||
|
| 方面 | RICS | eqpalg |
|
||||||
|
|------|------|--------|
|
||||||
|
| 职责 | 规则配置展示 | 规则执行与报警 |
|
||||||
|
| 数据方向 | DB2 → Memcached(只读) | 共享内存 → 算法 → 报警 |
|
||||||
|
| 触发方式 | 定时全量刷新 | mon 持续/cron 定时/task 按需 |
|
||||||
|
| 输出 | Memcached 中的 JSON | 报警、DB2 统计结果 |
|
||||||
|
|
||||||
|
**RICS 是 eqpalg 的"配置展示面"** — 它将 eqpalg 所用到的同一批规则配置(来自 `T_RULE_CFG`)格式化后提供给前端,使得操作人员能看到当前正在运行哪些规则、每个规则的参数和表达式是什么。
|
||||||
|
|
||||||
|
## 目录结构
|
||||||
|
|
||||||
|
```
|
||||||
|
RICS/
|
||||||
|
├── RICS.cc/h # 进程入口,启动 ICE 服务
|
||||||
|
├── RICS_icei.cc/h # ICE 接口,处理电文和定时触发
|
||||||
|
├── RICS_alg.cc/h # 核心逻辑:规则读取、解析、JSON 输出
|
||||||
|
├── utility.cc/h # 时间工具函数
|
||||||
|
├── item2chinese.hpp # 标签名→中文翻译映射
|
||||||
|
├── public.h # RuleInfo / CfgRuleInfo 数据结构
|
||||||
|
├── table_struct/ # DB2 表结构映射
|
||||||
|
│ ├── t_rule_cfg.h # 规则配置表
|
||||||
|
│ ├── t_eqp_data.h # 设备数据表
|
||||||
|
│ ├── t_eqp_repair.h # 设备检修表
|
||||||
|
│ └── fv_pdi.h # 卷材生产数据视图
|
||||||
|
├── json/ # JSON 模板文件
|
||||||
|
│ ├── eqp_status.json
|
||||||
|
│ └── norm_info.json
|
||||||
|
└── CMakeLists.txt
|
||||||
|
```
|
||||||
|
|
||||||
|
## 作者
|
||||||
|
|
||||||
|
- Cat (null.null.null@qq.com)
|
||||||
|
- 宝信软件(Baosight Co. Ltd.)
|
||||||
160
dsm/dsm_readme.md
Normal file
160
dsm/dsm_readme.md
Normal file
@ -0,0 +1,160 @@
|
|||||||
|
# dsm — 数据存储管理
|
||||||
|
|
||||||
|
## 概述
|
||||||
|
|
||||||
|
dsm(**D**ata **S**ave **M**anager / 数据存储管理)是 EIS 系统中的历史数据归档服务。它的核心职责是:
|
||||||
|
|
||||||
|
- **周期性**从 iHyperDB 工业历史数据库查询指定规则的历史数据
|
||||||
|
- 将查询到的数据(标签值 + 时间戳)保存为 **JSON 文件**在磁盘上
|
||||||
|
- 按规则 ID 和日期组织文件,区分正常数据和报警数据
|
||||||
|
|
||||||
|
## 进程架构
|
||||||
|
|
||||||
|
dsm 作为单个 PACE 平台组件运行,注册 ICE 端点 `"baosight/dsm"`。它**被动接收**其他进程推送的规则 ID 列表,然后定时从 iHyperDB 拉取数据归档。
|
||||||
|
|
||||||
|
```
|
||||||
|
eqpalg / 其它进程
|
||||||
|
│
|
||||||
|
│ ICE SendDataShort(99999, {"ruleid": [...]})
|
||||||
|
▼
|
||||||
|
┌──────────────────────────────────────────┐
|
||||||
|
│ dsm 进程 │
|
||||||
|
│ │
|
||||||
|
│ dsmICEI::SendDataShort(99999) │
|
||||||
|
│ │ │
|
||||||
|
│ ▼ │
|
||||||
|
│ DsmAlg::dispose() → need_ruleid_ │
|
||||||
|
│ │
|
||||||
|
│ dsmICEI::TimeNotify() │
|
||||||
|
│ │ │
|
||||||
|
│ ▼ │
|
||||||
|
│ DsmAlg::timed_task() │
|
||||||
|
│ │ │
|
||||||
|
│ ├→ dsm_handle(ruleid) │
|
||||||
|
│ │ ├─ 读共享内存 ZONE10 获取配置 │
|
||||||
|
│ │ ├─ DataQuery → iHyperDB 查询 │
|
||||||
|
│ │ └─ save_json_file() → 写磁盘 │
|
||||||
|
│ │ │
|
||||||
|
└───────┼───────────────────────────────────┘
|
||||||
|
│
|
||||||
|
▼
|
||||||
|
/dscdata/RuleNormData/<ruleid>/<yyyy-mm-dd>.json (正常数据)
|
||||||
|
/dscdata/RuleAlertData/<ruleid>/<yyyy-mm-dd>.json (报警数据)
|
||||||
|
```
|
||||||
|
|
||||||
|
## ICE 接口
|
||||||
|
|
||||||
|
| 方法 | 事件号 | 说明 |
|
||||||
|
|------|--------|------|
|
||||||
|
| `SendDataShort` | 99999 | 接收规则 ID 列表,解析 JSON `{"ruleid": [...]}` 存入 `need_ruleid_` |
|
||||||
|
| `SendDataLong` | — | 未实现 |
|
||||||
|
| `TimeNotify` | — | 定时触发 `timed_task()`,处理所有待处理的规则 |
|
||||||
|
|
||||||
|
定时器根据 `config/config.json` 中的 CronTab 配置触发(默认每分钟第 18、19 秒各执行一次)。
|
||||||
|
|
||||||
|
## 核心模块
|
||||||
|
|
||||||
|
### 1. DsmAlg — 数据归档调度
|
||||||
|
|
||||||
|
| 方法 | 说明 |
|
||||||
|
|------|------|
|
||||||
|
| `dispose(event_no, seq)` | 解析 ICE 消息中的 JSON,提取 `ruleid` 数组存入 `need_ruleid_` |
|
||||||
|
| `timed_task()` | 遍历 `need_ruleid_`,调用 `dsm_handle()` 处理每个规则 |
|
||||||
|
| `dsm_handle(ruleid)` | 核心归档逻辑(见下) |
|
||||||
|
|
||||||
|
**`dsm_handle()` 工作流程**:
|
||||||
|
|
||||||
|
1. 从共享内存 `ZONE10` 读取该 `ruleid` 的 `DataInfo`(含 start/end/tags/data_type)
|
||||||
|
2. 根据 `data_type` 确定输出目录:
|
||||||
|
- `flag=0` → `/dscdata/RuleNormData/`(正常数据)
|
||||||
|
- `flag=1` → `/dscdata/RuleAlertData/`(报警数据)
|
||||||
|
3. 构建文件路径:`<root>/<ruleid>/<yyyy-mm-dd>.json`
|
||||||
|
4. 如果文件已存在则跳过(防止重复写入)
|
||||||
|
5. 调用 `DataQuery` 从 iHyperDB 拉取数据
|
||||||
|
6. 调用 `UtilityTools::save_json_file()` 写入磁盘
|
||||||
|
|
||||||
|
### 2. DataQuery — iHyperDB 查询
|
||||||
|
|
||||||
|
通过 `mix_cc::ihd` API 查询工业历史数据库:
|
||||||
|
|
||||||
|
- **输入**: 标签名称列表 + 时间范围
|
||||||
|
- **输出**: JSON 对象,每个标签对应一个 `vector<double>` 值数组,外加 `"time"` 时间戳数组(毫秒 epoch)
|
||||||
|
- **连接**: `config.json` 中配置的 `10.3.226.3:5673`
|
||||||
|
|
||||||
|
### 3. 共享内存 ZONE10
|
||||||
|
|
||||||
|
- **区名**: `"ZONE10"`
|
||||||
|
- **结构**: `CMemMap<string, DataInfo>`
|
||||||
|
- **容量**: 最多 5000 条规则
|
||||||
|
- **DataInfo 字段**:
|
||||||
|
- `start` / `end`: 时间范围(epoch 毫秒)
|
||||||
|
- `tags`: 最多 30 个标签名,每个 50 字符
|
||||||
|
- `flag`: 0=正常数据,1=报警数据
|
||||||
|
|
||||||
|
### 4. 定时调度
|
||||||
|
|
||||||
|
根据 `config/config.json`,ICE CronTab 每整分钟的第 **18 秒**和**第 19 秒**触发 `TimeNotify`。ICE 代理列表包含 `"baosight/ProxyTest"` 和 `"baosight/pyml"`。
|
||||||
|
|
||||||
|
## 数据流
|
||||||
|
|
||||||
|
```
|
||||||
|
其他进程推送 ruleId
|
||||||
|
│
|
||||||
|
▼
|
||||||
|
dsm.process 维护 need_ruleid_ 列表
|
||||||
|
│
|
||||||
|
│ (每分钟两次)
|
||||||
|
▼
|
||||||
|
共享内存 ZONE10 → 读取 DataInfo (start/end/tags/flag)
|
||||||
|
│
|
||||||
|
▼
|
||||||
|
iHyperDB 查询 → Eigen Matrix → JSON 转换
|
||||||
|
│
|
||||||
|
▼
|
||||||
|
/dscdata/
|
||||||
|
├── RuleNormData/<ruleid>/YYYY-MM-DD.json
|
||||||
|
└── RuleAlertData/<ruleid>/YYYY-MM-DD.json
|
||||||
|
```
|
||||||
|
|
||||||
|
## 与其它进程的关系
|
||||||
|
|
||||||
|
| 进程 | 关系 |
|
||||||
|
|------|------|
|
||||||
|
| **eqpalg** | eqpalg 产生报警和规则统计,写入共享内存 ZONE10,dsm 据此归档历史数据;eqpalg-mon 的 TimeNotify(5) 定期向 dsm 发送 ruleId JSON |
|
||||||
|
| **RICS** | 独立模块,RICS 做规则配置展示,不直接交互 |
|
||||||
|
| **eqpm** | 独立模块,eqpm 做设备点检管理,不直接交互 |
|
||||||
|
|
||||||
|
dsm 本质上是 eqpalg 的**数据归档下游** — eqpalg 负责检测和报警,dsm 负责将相关规则的原始数据拉取保存到磁盘,供后续离线分析和问题追溯使用。
|
||||||
|
|
||||||
|
## 目录结构
|
||||||
|
|
||||||
|
```
|
||||||
|
dsm/
|
||||||
|
├── dsm.cc/h # 进程入口
|
||||||
|
├── dsm_icei.cc/h # ICE 接口
|
||||||
|
├── dsm_alg.cc/h # 数据归档调度
|
||||||
|
├── data_query.cc/h # iHyperDB 数据查询
|
||||||
|
├── utility.cc/h # 时间/文件系统工具
|
||||||
|
├── public.h # DataInfo / DsmMapConfig 数据结构
|
||||||
|
├── table_struct/ # DB2 表结构(当前未直接使用)
|
||||||
|
│ ├── fv_pdi.h
|
||||||
|
│ ├── t_eqp_data.h
|
||||||
|
│ └── t_eqp_repair.h
|
||||||
|
├── json/ # 测试/模板数据
|
||||||
|
│ ├── norm_info.json
|
||||||
|
│ └── eqp_status.json
|
||||||
|
└── CMakeLists.txt
|
||||||
|
```
|
||||||
|
|
||||||
|
## 配置文件(项目级)
|
||||||
|
|
||||||
|
| 文件 | 用途 |
|
||||||
|
|------|------|
|
||||||
|
| `config/config.json` | DB2 凭据、IHDB 连接参数、共享内存路径、样本目录、CronTab 调度 |
|
||||||
|
| `config/dsfconfig.json` | DSF 数据源订阅配置(服务器 `10.64.3.20:1234`) |
|
||||||
|
| `config/zone.cfg` | 共享内存区域定义(含 ZONE10) |
|
||||||
|
|
||||||
|
## 作者
|
||||||
|
|
||||||
|
- Cat (null.null.null@qq.com)
|
||||||
|
- 宝信软件(Baosight Co. Ltd.)
|
||||||
@ -1,160 +1,332 @@
|
|||||||
# eqpalg — 设备算法监控进程
|
# eqpalg — 设备算法监控引擎
|
||||||
|
|
||||||
## 概述
|
## 概述
|
||||||
|
|
||||||
eqpalg(**Eq**uipment **P**rocess **Alg**orithm)是 EIS 系统中的核心设备监控与报警引擎。它基于宝信 PACE 平台构建,通过 ICE 中间件与系统内其他进程通信,从 iHyperDB 实时数据库和共享内存获取工业现场数据,根据数据库中配置的规则对设备运行状态进行实时监控、统计分析和报警。
|
eqpalg(**Eq**uipment **P**rocess **Alg**orithm)是 EIS 系统中的核心设备监控与报警引擎。它基于宝信 PACE 平台构建,通过 ICE 中间件与系统内其他进程通信,从共享内存实时读取 PLC 数据,根据 DB2 中配置的规则,以数学表达式引擎对设备运行状态进行实时监控、统计分析和报警。
|
||||||
|
|
||||||
## 进程架构
|
## 进程架构
|
||||||
|
|
||||||
eqpalg 以 **3 个子进程** 的形式运行,通过 ICE 通信协作:
|
eqpalg 以 **3 个进程实例** 的形式运行,部署为不同的 PACE 组件名,各行其责:
|
||||||
|
|
||||||
| 进程名 | ProcessType | 功能 |
|
| 进程名 | ProcessType | 功能 |
|
||||||
|--------|-------------|------|
|
|--------|-------------|------|
|
||||||
| `eqpalg-mon` | kMon | **监控进程** — 实时读取共享内存数据,周期性执行所有启用的规则,产出实时报警;同时维护共享内存缓存和数据库时间戳 |
|
| `eqpalg-mon` | kMon | **实时监控进程** — 从共享内存双缓冲区读取实时 PLC 数据(~19ms 刷新一次),周期性执行所有启用的规则(执行间隔可配置,最小 20ms),产出实时报警 |
|
||||||
| `eqpalg-cron` | kCron | **定时任务进程** — 按固定周期(默认24小时)查询 iHyperDB 历史数据,执行统计分析(如置信区间更新、样本累积) |
|
| `eqpalg-cron` | kCron | **定时学习进程** — 每 1 秒轮询一次,从 `RuleStatShm`(由 mon 累积的统计值)中取出统计数据,通过 `DAA::STA` 分布分析类计算置信区间,将学习结果写回 DB2(`T_SAMPLE_STAT`、`T_SAMPLE_MAG`)。默认每 24 小时更新一次 |
|
||||||
| `eqpalg-task` | kTask | **单次执行进程** — 响应用户在页面上发起的一次性分析任务,从 iHyperDB 拉取指定时间范围的历史数据,运行算法并返回结果 |
|
| `eqpalg-task` | kTask | **单次执行进程** — 响应用户发起的按需分析任务,从 iHyperDB 拉取指定时间范围的历史数据,执行算法并返回结果(含报警回测、多项式拟合、相关性计算等) |
|
||||||
|
|
||||||
|
**三者协作**:eqpalg-mon 收到 99999 电文(规则 CRUD)时,通过 ICE 代理转发给 eqpalg-cron,确保 cron 的配置与 mon 保持同步。三个进程各自实例化独立的 `AlgorithmManager`,从 DB2 独立加载规则,但 mon 的执行频率最高(毫秒级),cron 次之(秒级),task 按需触发。
|
||||||
|
|
||||||
### 关键依赖
|
### 关键依赖
|
||||||
|
|
||||||
- **ICE** — 进程间通信(接收电文、转发请求)
|
- **ICE** — 进程间通信,注册端点 `"baosight/eqpalg-{mon|cron|task}"`
|
||||||
- **DB2** — 存储规则配置、报警记录、样本数据和统计结果
|
- **DB2** — 存储规则配置(`T_RULE_CFG`)、报警记录(`T_RULE_RESULT`)、样本统计(`T_RULE_SAMPLE_1D`、`T_SAMPLE_STAT`、`T_SAMPLE_FIT`、`T_SAMPLE_MAG`)、时间戳(`T_RULE_RECORD_TIME`)
|
||||||
- **iHyperDB** — 工业实时/历史数据库,存储设备 tag 点数据
|
- **共享内存(SHM)** — 实时 PLC 数据的低延迟访问通道,基于 `MemFix<PLC_DATA>` 双缓冲区设计
|
||||||
- **共享内存(SHM)** — 实时数据的低延迟访问通道
|
- **iHyperDB** — 工业历史数据库,供 cron/task 查询历史趋势
|
||||||
- **Boost** — 通用工具库(filesystem, serialization, stacktrace 等)
|
- **Boost** — 通用工具库(filesystem, serialization, stacktrace, container 等)
|
||||||
- **dlib / mlpack / Armadillo / Eigen3** — 机器学习与数值计算库
|
- **dlib / mlpack / Armadillo / Eigen3** — 数值计算库(`DAA::STA` 统计分布分析、`DAA::LSM` 最小二乘拟合、矩阵运算)
|
||||||
- **nlohmann/json** — JSON 解析
|
- **nlohmann/json** — JSON 解析
|
||||||
|
|
||||||
## 核心工作流
|
## 核心工作流
|
||||||
|
|
||||||
```
|
```
|
||||||
┌─────────────┐
|
现场PLC/传感器
|
||||||
│ DB2 (配置) │
|
|
||||||
└──────┬──────┘
|
|
||||||
│ 读取规则配置
|
|
||||||
▼
|
|
||||||
┌────────────────────────┐
|
|
||||||
│ AlgorithmManager │
|
|
||||||
│ (构建所有规则实例) │
|
|
||||||
└───────────┬────────────┘
|
|
||||||
│
|
|
||||||
┌─────────────┼─────────────┐
|
|
||||||
▼ ▼ ▼
|
|
||||||
┌──────────┐ ┌──────────┐ ┌──────────┐
|
|
||||||
│eqpalg-mon│ │eqpalg-cron│ │eqpalg-task│
|
|
||||||
└────┬─────┘ └────┬─────┘ └────┬─────┘
|
|
||||||
│ │ │
|
|
||||||
共享内存(实时) iHyperDB(历史) iHyperDB
|
|
||||||
│ │ │
|
|
||||||
▼ ▼ ▼
|
|
||||||
┌─────────────────────────────────────┐
|
|
||||||
│ threads::Manager │
|
|
||||||
│ (多线程调度,每个 TaskSeq 一个线程) │
|
|
||||||
└──────────────┬──────────────────────┘
|
|
||||||
│
|
│
|
||||||
▼
|
▼
|
||||||
┌─────────────────────────────────────┐
|
DSF 数据采集 ──→ 共享内存 MemFix<PLC_DATA>
|
||||||
│ HandlerExec │
|
|
||||||
│ (单个线程的执行句柄,管理规则集) │
|
|
||||||
└──────────────┬──────────────────────┘
|
|
||||||
│
|
│
|
||||||
▼
|
▼
|
||||||
┌─────────────────────────────────────┐
|
GlobaltemSharedMemory (双缓冲区, ~19ms刷新)
|
||||||
│ AlgBase │
|
|
||||||
│ (具体算法实例的执行) │
|
|
||||||
└──────────────┬──────────────────────┘
|
|
||||||
│
|
│
|
||||||
▼
|
├──→ eqpalg-mon: mm_vars → matheval 表达式引擎 → mon_proc()
|
||||||
┌──────────────┐
|
│ │
|
||||||
│ 报警 / 统计结果 │
|
│ ├──→ 报警 → AlarmPoster → CMemQueue / ICE MQ / DB2
|
||||||
└──────────────┘
|
│ ├──→ 正常数据 → ExpModule → DB2 T_RULE_SAMPLE_*
|
||||||
|
│ ├──→ 统计累积 → RuleStatShm (供 cron 学习)
|
||||||
|
│ └──→ 页面数据 → EqpStat → Memcached
|
||||||
|
│
|
||||||
|
├──→ eqpalg-cron: RuleStatShm → DAA::STA → 置信区间 → DB2
|
||||||
|
│
|
||||||
|
└──→ eqpalg-task: iHyperDB(指定时间范围) → 拟合/统计/回测
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### 数据源模式
|
||||||
|
|
||||||
|
每个规则可以配置两种数据源(`DataSource`枚举):
|
||||||
|
|
||||||
|
| 模式 | 值 | 说明 |
|
||||||
|
|------|---|------|
|
||||||
|
| MEMORY | 1 | mon 进程默认:从 `GlobaltemSharedMemory` 双缓冲区实时读取,延迟低至 20ms |
|
||||||
|
| IHDB | 0 | cron/task 进程使用:通过 `mix_cc::ihd` API 从 iHyperDB 查询历史数据 |
|
||||||
|
|
||||||
|
### 共享内存双缓冲区
|
||||||
|
|
||||||
|
`GlobaltemSharedMemory` 是 eqpalg 的数据中枢:
|
||||||
|
|
||||||
|
- **写侧**:`mem_cached_thread_`(仅在 mon 中)以 ~19ms 为周期,使用 `CLOCK_MONOTONIC` 单调时钟计时,从 `MemFix<PLC_DATA>` 顺序读取所有 tag 值,写入 write 缓冲区后执行 swap(通过 `std::shared_mutex` 保护)
|
||||||
|
- **读侧**:监控线程无锁读取 read 缓冲区,不会与写操作竞争
|
||||||
|
- **超时处理**:若一次刷新超过 19ms,记录 Error 日志并立即开始下一次循环,不再 sleep
|
||||||
|
- **索引构建**:构造函数中遍历 `BinaryTele` 电文定义,将 tag 名→缓冲区索引的映射一次性构建
|
||||||
|
|
||||||
### ICE 电文接口
|
### ICE 电文接口
|
||||||
|
|
||||||
进程通过 `EqpAlgICEI` 接收三类 ICE 调用:
|
`EqpAlgICEI` 继承自 `MessageICE`,处理三类调用:
|
||||||
|
|
||||||
1. **SendDataShort(eventNo, seq)** — 处理控制指令:
|
**SendDataShort(eventNo, seq)** — 同步消息分发:
|
||||||
- `eventNo=99999`:规则增删改查/执行指令(mon 进程转发给 cron)
|
|
||||||
- `eventNo=11111`:收到外部报警信息,转发报警
|
|
||||||
- `eventNo=22222`:更新规则的上下限阈值
|
|
||||||
|
|
||||||
2. **SendDataLong** — 复杂数据接口(当前未实现具体逻辑)
|
| eventNo | 用途 | 处理逻辑 |
|
||||||
|
|---------|------|----------|
|
||||||
|
| 99999 | 规则 CRUD + 单次执行 | JSON `{"eventNo":N, "ruleId":"...", "algId":N, ...}` → `AlgorithmManager::dispose()`。mon 收到后通过 ICE 代理转发给 cron |
|
||||||
|
| 11111 | 外部原始报警 | 直接调用 `AlarmPoster::alarm(str)` |
|
||||||
|
| 22222 | 规则上下限更新 | JSON `{"ruleid":"...", "lb":N, "ub":N, "va":N, ...}` → `update_limit_alarm()` |
|
||||||
|
|
||||||
3. **TimeNotify(eventNo)** — 定时任务触发:
|
**SendDataLong** — 复杂数据接口(未实现)
|
||||||
- `eventNo=1`:更新设备运行状态
|
|
||||||
- `eventNo=2`:更新规则统计的共享内存数据
|
|
||||||
- `eventNo=5`:定期向 dsm 进程推送最新 ruleId 列表和共享内存统计
|
|
||||||
|
|
||||||
### 规则生命周期
|
**TimeNotify(eventNo)** — 定时器回调:
|
||||||
|
|
||||||
|
| eventNo | 用途 | 触发周期 |
|
||||||
|
|---------|------|----------|
|
||||||
|
| 1 | 更新设备运行状态到 Memcached | ~1秒 |
|
||||||
|
| 2 | 更新规则统计共享内存数据 | ~1秒 |
|
||||||
|
| 5 | 向 dsm 发送 ruleId 列表和共享内存统计 | 定期 |
|
||||||
|
|
||||||
|
### 规则生命周期(eventNo=99999)
|
||||||
|
|
||||||
```
|
```
|
||||||
页面/外部发起 → ICE电文(JSON) → AlgorithmManager.dispose()
|
页面/外部 → ICE 电文(JSON) → AlgorithmManager::dispose()
|
||||||
│
|
│
|
||||||
┌────────┬────────┬─────────┼──────────┬────────┐
|
┌───────┬────────┬──────────┼──────────┬────────┐
|
||||||
▼ ▼ ▼ ▼ ▼ ▼
|
▼ ▼ ▼ ▼ ▼ ▼
|
||||||
kCreate kDelete kUpdate kEnable kReset kExec
|
kCreate kDelete kUpdate kEnable kReset kExec
|
||||||
(创建) (删除) (更新) (启/停用) (重置) (单次执行)
|
(1) (0) (2) (3) (4) (10)
|
||||||
```
|
```
|
||||||
|
|
||||||
- 所有规则操作均通过 JSON 电文驱动
|
- **kCreate(1)**: `thread_manager_.storage()` → `attach()` → 启动线程执行 → 更新 DB2 `T_RULE_RECORD_TIME`
|
||||||
- 创建/更新时同步维护 DB2 表 `T_RULE_CFG` 和 `T_RULE_RECORD_TIME`
|
- **kDelete(0)**: `delete_instance()` → 停止线程 → 删除 DB2 记录
|
||||||
|
- **kUpdate(2)**: `detach()` → `storage()` → `attach()` → 更新修改时间
|
||||||
|
- **kEnable(3)**: `thread_manager_.enable(ruleId, usable)` → 更新 DB2 时间
|
||||||
|
- **kReset(4)**: 重置算法 6(累计时间)和 7(出现次数)的统计值
|
||||||
|
- **kExec(10)**: 单次执行,从 DB2 重新读取最新配置,创建独立线程运行 `exec_task(time_range)`
|
||||||
|
|
||||||
|
## 线程模型
|
||||||
|
|
||||||
|
### 三层调度
|
||||||
|
|
||||||
|
```
|
||||||
|
threads::Manager ← 顶层:按 TaskSeq 分配线程,维护 handles_ map
|
||||||
|
│
|
||||||
|
▼
|
||||||
|
HandlerExec ← 中层:单个线程的执行句柄,管理队列和规则集
|
||||||
|
│
|
||||||
|
▼
|
||||||
|
AlgBase (子类实例) ← 底层:具体算法执行
|
||||||
|
```
|
||||||
|
|
||||||
|
### HandlerExec 执行循环
|
||||||
|
|
||||||
|
每个 `HandlerExec` 运行在独立线程中,线程名格式为 `alg_{algId}_{dataSource}_{taskSeq}`(cron 加后缀 `_cron`,task 加后缀 `_task`):
|
||||||
|
|
||||||
|
- **mon 模式**:遍历规则,对每条调用 `exec_mon_call()`。每条规则执行间隔由配置的 `delay_time_` 控制。若单次执行超过 20ms,跳过 sleep 立即下一轮
|
||||||
|
- **cron 模式**:每秒轮询一次,对每条规则调用 `exec_cron_call()`
|
||||||
|
- **task 模式**:每秒轮询一次,每条规则执行一次后从活动集中移除
|
||||||
|
|
||||||
|
### 线程安全
|
||||||
|
|
||||||
|
通过多级队列实现无锁化动态增删:
|
||||||
|
|
||||||
|
| 队列 | 用途 |
|
||||||
|
|------|------|
|
||||||
|
| `attach_queue_` | 新增算法排队加入 |
|
||||||
|
| `detach_queue_` | 待删除的规则 ID 列表 |
|
||||||
|
| `reset_queue_` | 待重置统计的规则 ID |
|
||||||
|
| `usable_queue_` | 待设置启/停用的 `(ruleId, bool)` |
|
||||||
|
| `once_exec_queue_` | task 单次执行请求 `(algo_ptr, time_range)` |
|
||||||
|
|
||||||
|
每轮 `event_handler()` 清空所有队列,修改活动规则集。
|
||||||
|
|
||||||
|
### 随机偏移(防惊群)
|
||||||
|
|
||||||
|
`AlgBase::init()` 使用 `XorShift128Plus` 随机数生成器为 `save_interval_ms_` 和 `rule_state_update_interval_ms_` 添加随机毫秒偏移,避免大量规则同时写 DB2。
|
||||||
|
|
||||||
## 算法体系
|
## 算法体系
|
||||||
|
|
||||||
所有算法类继承自 `AlgBase`,`AlgBase` 提供:
|
所有算法继承自 `AlgBase`,基类提供:
|
||||||
- 表达式解析引擎(基于 `mix_cc::matheval`)
|
- 表达式解析引擎(`mix_cc::matheval::Expression`)
|
||||||
- iHyperDB/共享内存双数据源
|
- 双数据源(共享内存 / iHyperDB)
|
||||||
- 执行间隔控制、心跳日志、前提条件判断
|
- 执行间隔控制、心跳日志、前提条件判断
|
||||||
- 报警/正常数据保存、共享内存统计更新
|
- 报警保存、统计累积
|
||||||
|
|
||||||
### 当前使用的算法(18种)
|
### 表达式变量系统
|
||||||
|
|
||||||
| algId | 类名 | 名称 | 说明 |
|
表达式引擎中可用以下特殊变量(通过宏替换注入实际值):
|
||||||
|-------|------|------|------|
|
|
||||||
| 1 | `ExpBase` | 实时逻辑判断 | 对监控变量做布尔逻辑判断,触发报警 |
|
|
||||||
| 2 | `ExpBase` | 监控变量-上下限 | 检测变量是否超出上下限区间(含在线自学习) |
|
|
||||||
| 3 | `ExpBase` | 动作反馈-逻辑判断 | 当触发动作条件后,监测反馈是否在规定时间内到位 |
|
|
||||||
| 4 | `ExpBase` | 动作反馈-上下限 | 触发动作后,监测反馈变量是否回到合理区间 |
|
|
||||||
| 5 | `ExpBase` | 上下限-保持时间 | 变量超出区间并持续超过设定时间才报警 |
|
|
||||||
| 6 | `ExpTimes` | 运行时间累计 | 累计设备/部件运行时长,超阈值报警 |
|
|
||||||
| 7 | `ExpTimes` | 出现次数累计 | 累计事件发生次数,超阈值报警 |
|
|
||||||
| 8 | `TrendSlope2` | 斜率监控 | 监测变量变化趋势(斜率),检测过快变化 |
|
|
||||||
| 9 | `Roller2` | 离群检测(百分比) | 同组多变量中检测某个值偏离群体百分比 |
|
|
||||||
| 10 | `FaultCode` | 故障代码解析(整体) | 将数字故障码与 DB2 字典表比对,解析为可读故障信息 |
|
|
||||||
| 11 | `FaultCode` | 故障代码解析(按位) | 按位解析数字故障码,适用于组合故障信号 |
|
|
||||||
| 12 | `ExpSample2D` | 多项式拟合 | Cron 累积 XY 样本,Mon 用拟合多项式做预测与偏差检测 |
|
|
||||||
| 13 | `ExpSample2D` | 皮尔逊相关性 | Cron 累积样本计算相关系数,Mon 检测相关性偏离 |
|
|
||||||
| 14 | `TrendSlope3` | 趋势检测增强版 | 斜率监控的改进版本 |
|
|
||||||
| 15 | `GlitchDetection` | 毛刺检测 | 检测数据中突发的尖峰/毛刺信号,可联动 Python 算法 |
|
|
||||||
| 16 | `Roller3` | 离群检测(百分比v3) | 离群检测的改进版本 |
|
|
||||||
| 17 | `ExpBound` | 数据超限幅值 | 检测变量是否超出设定的误差限和警告限 |
|
|
||||||
| 18 | `Roller3` | 离群检测(实际值v3) | 基于实际值阈值的离群检测 |
|
|
||||||
|
|
||||||
### 已弃用的算法(位于 `.do_not_use/`)
|
| 变量 | 含义 |
|
||||||
|
|------|------|
|
||||||
|
| `m{tagN}` | tagN 的当前值(如 `m{tag1}`) |
|
||||||
|
| `p{tagN}` | tagN 上一次执行时的值 |
|
||||||
|
| `s{tagN}` | 动作开始时的快照值 |
|
||||||
|
| `mx_tagN` | tagN 的历史最大值 |
|
||||||
|
| `mi_tagN` | tagN 的历史最小值 |
|
||||||
|
| `mv2_tagN` | tagN 的累积变化量 |
|
||||||
|
| `up_tagN` | tagN 的上限 |
|
||||||
|
| `dw_tagN` | tagN 的下限 |
|
||||||
|
| `time` | 当前运行时间 |
|
||||||
|
| `stime` | 动作开始时间 |
|
||||||
|
| `etime` | 动作结束时间 |
|
||||||
|
| `now` | 当前时间点 |
|
||||||
|
|
||||||
包括但不限于:样板曲线检测、CPC 检测、区间分布统计、波形监控、DTW 动态时间规整、一类 SVM 异常检测、KRR 核岭回归、FFT 频谱统计等实验性算法。这些代码保留供参考但不再参与编译。
|
### 自定义带状态函数
|
||||||
|
|
||||||
## 表达式系统
|
| 函数 | 含义 |
|
||||||
|
|------|------|
|
||||||
|
| `KeepT(N, T)` | tagN 为真后保持 T 分钟 |
|
||||||
|
| `KeepC(N)` | tagN 为真后累计次数 |
|
||||||
|
| `RiseEdge(N)` | tagN 的上升沿检测 |
|
||||||
|
| `Detect(N, T)` | T 分钟内检测 tagN 是否为真 |
|
||||||
|
| `hold(N, T)` | 将 tagN 保持 T 分钟不变(hold 变量有独立的状态管理) |
|
||||||
|
|
||||||
基于 `mix_cc::matheval` 数学表达式解析引擎,规则配置中可书写数学表达式来引用 tag 变量和内置函数:
|
### 算法详细说明
|
||||||
|
|
||||||
- **变量语法**: `m{tagN}` — 引用第 N 个监控 tag 点(如 `m{tag1}`),`s{tagN}` — 动作开始时的快照值
|
#### 1-5: ExpBase — 表达式类算法
|
||||||
- **自定义带状态函数**(`StatExp::FunVars`):
|
|
||||||
- `KeepT(N, T)` — tagN 为真后保持 T 分钟
|
所有基于表达式的算法共享 `ExpBase`,通过 `exp_type_` 区分行为:
|
||||||
- `KeepC(N)` — tagN 为真后累计次数
|
|
||||||
- `RiseEdge(N)` — tagN 的上升沿检测
|
| exp_type_ | algId | 名称 | 核心逻辑 |
|
||||||
- `Detect(N, T)` — T 分钟内检测 tagN 是否为真
|
|-----------|-------|------|----------|
|
||||||
- **hold 函数**: `hold(N, T)` — 将 tagN 保持 T 分钟不变
|
| Logic (1) | 1 | 实时逻辑判断 | 评估 `exp_act_` 表达式,结果为真即报警 |
|
||||||
- **数学函数**: 标准四则运算、三角函数、log、绝对值等
|
| Bound (2) | 2 | 变量上下限 | 计算 `exp_result_` 值,与下限/上限比较。支持在线自学习:`is_learning_=true` 时累积统计值到 `EqpStat`,cron 定期用 `DAA::STA` 计算新置信区间写回 DB2 |
|
||||||
|
| ActionFeedBack (3) | 3 | 动作反馈-逻辑 | 跟踪状态机:`act_start_done()` → 超时/保持检测 → `act_done()` → 反馈表达式评估 |
|
||||||
|
| CondBound (4) | 4 | 动作反馈-上下限 | 与 3 相同流程,反馈后用上下限判断 |
|
||||||
|
| BoundHoldTime (5) | 5 | 上下限-保持时间 | 仅在超限持续超过 `hold_time_` 毫秒后才触发报警 |
|
||||||
|
|
||||||
|
**动作反馈状态机**(algId 3/4):
|
||||||
|
|
||||||
|
```
|
||||||
|
act_start_done() ──→ act_not_hold() ──→ 停止
|
||||||
|
│ (未保持)
|
||||||
|
│ act_timeout() ──→ 超时报警
|
||||||
|
│
|
||||||
|
▼
|
||||||
|
act_done() → 反馈评价 → 正常/报警
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 6-7: ExpTimes — 累计统计
|
||||||
|
|
||||||
|
| algId | 名称 | 逻辑 |
|
||||||
|
|-------|------|------|
|
||||||
|
| 6 | 运行时间累计 | 跟踪条件满足的持续时间,累积到 `running_time`(小时),超过 `max_time_` 阈值报警。结果持久化到 DB2 `T_RULE_SAMPLE_1D` |
|
||||||
|
| 7 | 出现次数累计 | 跟踪条件满足的次数,累积到 `shear_times`,超过 `max_times_` 阈值报警 |
|
||||||
|
|
||||||
|
两种累计均支持通过 kReset 事件重置。
|
||||||
|
|
||||||
|
#### 8, 14: TrendSlope2 / TrendSlope3 — 趋势检测
|
||||||
|
|
||||||
|
| 类 | algId | 检测方式 |
|
||||||
|
|----|-------|----------|
|
||||||
|
| `TrendSlope2` | 8 | **原始值斜率**:在 `deltaX_` 间隔内查询 iHyperDB,计算连续间隔均值之间的斜率 `deltaY / deltaX`,若在连续 `CS_AVG_SIZE_` 个间隔中斜率超过 `limit_slope_` 则报警 |
|
||||||
|
| `TrendSlope3` | 14 | **百分比变化**: 斜率为 `100 * deltaY / avg[i-1]`,适用于量级不同的变量,实现归一化 |
|
||||||
|
|
||||||
|
#### 9, 16, 18: Roller2 / Roller3 — 离群检测
|
||||||
|
|
||||||
|
| 类 | algId | 检测方式 |
|
||||||
|
|----|-------|----------|
|
||||||
|
| `Roller2` | 9 | **基于均值**:计算所有变量的算术平均,任一个体偏离均值超过 `limit_over_%` 即报警 |
|
||||||
|
| `Roller3` | 16 | **基于中位数(百分比)**:计算所有变量的中位数,偏离超过 `limit_warn_%`(警告)或 `limit_error_%`(错误)即报警,支持 `hold_time_` 持续判断 |
|
||||||
|
| `Roller3` | 18 | **基于中位数(实际值)**:使用实际值阈值代替百分比 |
|
||||||
|
|
||||||
|
Roller2/3 的典型应用场景是"轧辊组监控"——同组多个传感器(如多个轧辊温度计),检测其中某个是否明显偏离群体。
|
||||||
|
|
||||||
|
#### 10-11: FaultCode — 故障代码解析
|
||||||
|
|
||||||
|
维护一个 DB2 `T_LOV_FCODE` 查询缓存(`map2fcode_`),将整数值映射为故障名称和内容:
|
||||||
|
|
||||||
|
| algId | code_type_ | 解析方式 |
|
||||||
|
|-------|------------|----------|
|
||||||
|
| 10 | 0 | **整体解析**:将故障码整数值在字典中查找对应描述 |
|
||||||
|
| 11 | 1 | **按位解析**:检查 0-15 每一位,对每个置位位查找对应故障描述 |
|
||||||
|
|
||||||
|
#### 12-13: ExpSample2D — 二维拟合与相关性
|
||||||
|
|
||||||
|
| algId | 名称 | mon 执行 | task 执行 |
|
||||||
|
|-------|------|----------|-----------|
|
||||||
|
| 12 | 多项式拟合 | 评估 X/Y 表达式,用 DB2 中存储的拟合系数计算 Y_fit,偏差超 `scale_ × |Y_fit|` 即报警 | 收集 (X,Y) 数据点,用 `DAA::LSM` 做最小二乘拟合,系数存入 `T_SAMPLE_FIT` |
|
||||||
|
| 13 | 皮尔逊相关系数 | 累积到 `min_len_` 个数据点后计算皮尔逊 r,与存储值偏差超 `scale_` 报警 | 收集数据→计算皮尔逊系数→存入 `T_SAMPLE_FIT` |
|
||||||
|
|
||||||
|
#### 15: GlitchDetection — 毛刺检测
|
||||||
|
|
||||||
|
将监控变量累积到固定大小数组(最大 2000 点),数据满后通过 `ProxPy` 将数据传递给外部 Python 进程("glitch" 模块)执行毛刺分析。是唯一与 Python 联动的算法。
|
||||||
|
|
||||||
|
#### 17: ExpBound — 双阈值限幅
|
||||||
|
|
||||||
|
单独配置一个值表达式,设置两层阈值:
|
||||||
|
|
||||||
|
- `limit_warn_` — 警告阈值,触发 **WARN** 级别
|
||||||
|
- `limit_error_` — 错误阈值,触发 **ERROR** 级别
|
||||||
|
|
||||||
|
### 已弃用算法(`.do_not_use/`)
|
||||||
|
|
||||||
|
样板曲线、CPC 检测、FFT 频谱统计、DTW 动态时间规整、一类 SVM 异常检测、KRR 核岭回归、区间分布统计、波形监控等实验性算法。保留代码供参考但不参与编译。
|
||||||
|
|
||||||
|
## 报警机制
|
||||||
|
|
||||||
|
### 报警通道
|
||||||
|
|
||||||
|
`AlarmPoster` 多渠道推送报警:
|
||||||
|
|
||||||
|
```
|
||||||
|
mon_proc() 返回 AlarmInfo
|
||||||
|
│
|
||||||
|
▼
|
||||||
|
AlarmPoster::alarm()
|
||||||
|
│
|
||||||
|
├──→ CMemQueue (内存队列) → AlarmHandler 线程 (500ms轮询) → 统一处理
|
||||||
|
├──→ ICE MQ (baosight/zmqp) — 可选,用于消息队列服务
|
||||||
|
└──→ DB2 T_RULE_RESULT — 可选,persist 到数据库
|
||||||
|
```
|
||||||
|
|
||||||
|
### 去抖
|
||||||
|
|
||||||
|
`AlarmPoster` 强制每规则最小报警间隔(默认 5 分钟 × `AlarmIntervalHours`),防止信号振荡导致报警风暴。
|
||||||
|
|
||||||
|
### 报警信息结构
|
||||||
|
|
||||||
|
```
|
||||||
|
AlarmInfo {
|
||||||
|
bool alarmed;
|
||||||
|
json content; // 报警内容(含规则ID、名称、组、值、上下限等)
|
||||||
|
time_point alarm_start_time;
|
||||||
|
time_point alarm_end_time;
|
||||||
|
ConfigInfo cfg_info; // rule ID / name / group / remark
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## 表达式配置示例
|
||||||
|
|
||||||
|
DB2 `T_RULE_CFG.ruleParam` JSON 格式:
|
||||||
|
|
||||||
配置格式示例(JSON):
|
|
||||||
```json
|
```json
|
||||||
{
|
{
|
||||||
"exp_str": "m{tag1} > (limit_up_ + 0.251) or m{tag1} < (limit_down_ - 0.251)",
|
"datasource": 1,
|
||||||
|
"delay_time": 1000,
|
||||||
|
"before_exec": "m{tag1} > 0",
|
||||||
|
"function": {
|
||||||
|
"exp_str": "m{tag1} > limit_up_ or m{tag1} < limit_down_",
|
||||||
|
"exp_feedback": "m{tag10} > 0",
|
||||||
|
"exp_result": "m{tag1} + m{tag2}",
|
||||||
"limit_up_": 800,
|
"limit_up_": 800,
|
||||||
"limit_down_": 200,
|
"limit_down_": 200,
|
||||||
"hold_time": 5000,
|
"hold_time": 5000,
|
||||||
"delay_time": 1000
|
"is_learning_": true,
|
||||||
|
"dist_mode_": 1,
|
||||||
|
"time_out": 30000,
|
||||||
|
"keep_mode": true,
|
||||||
|
"max_times_": 100,
|
||||||
|
"max_time_": 720,
|
||||||
|
"unit": "℃"
|
||||||
|
},
|
||||||
|
"tags": {
|
||||||
|
"tag1": ["C308_TEMP_01", "1号温度"],
|
||||||
|
"tag2": ["C308_TEMP_02", "2号温度"]
|
||||||
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
@ -162,87 +334,93 @@ eqpalg 以 **3 个子进程** 的形式运行,通过 ICE 通信协作:
|
|||||||
|
|
||||||
```
|
```
|
||||||
eqpalg/
|
eqpalg/
|
||||||
├── eqpalg.cpp/h # 进程入口,start() 中启动 ICE 服务
|
├── eqpalg.cpp/h # 进程入口,根据进程名确定类型
|
||||||
├── eqpalg_icei.cpp/h # ICE 接口实现,处理电文分发
|
├── eqpalg_icei.cpp/h # ICE 接口,含共享内存缓存线程
|
||||||
├── algorithm_manager.cpp/h # 算法管理器:从 DB2 加载规则,协调生命周期
|
├── algorithm_manager.cpp/h # 算法管理器:DB2 加载 + 规则 CRUD
|
||||||
├── build_algorithm.cpp/h # 算法工厂:algId → 具体算法类实例
|
├── build_algorithm.cpp/h # 算法工厂:algId → 具体类
|
||||||
├── alg_base.cpp/h # 所有算法的基类,提供表达式引擎、数据获取等
|
├── alg_base.cpp/h # 所有算法的基类
|
||||||
├── gb_logger.cpp/h # 全局日志模块
|
├── gb_logger.cpp/h # 全局日志
|
||||||
├── gb_item_memory.cpp/h # 全局内存数据管理
|
├── gb_item_memory.cpp/h # GlobaltemSharedMemory 双缓冲区
|
||||||
├── algs/ # 算法实现
|
├── algs/ # 18 种算法实现
|
||||||
│ ├── exp_base.* # 表达式类算法 (algId 1-5)
|
│ ├── exp_base.* # algId 1-5: 表达式/上下限/动作反馈
|
||||||
│ ├── exp_times.* # 时间/次数累计 (algId 6-7)
|
│ ├── exp_times.* # algId 6-7: 累计时间/次数
|
||||||
│ ├── exp_bound.* # 限幅值检测 (algId 17)
|
│ ├── exp_bound.* # algId 17: 双阈值限幅
|
||||||
│ ├── exp_sample2D.* # 二维拟合/相关性 (algId 12-13)
|
│ ├── exp_sample2D.* # algId 12-13: 拟合/皮尔逊相关性
|
||||||
│ ├── trend_slope2.* # 斜率监控 (algId 8)
|
│ ├── trend_slope2.* # algId 8: 原始斜率
|
||||||
│ ├── trend_slope3.* # 斜率监控增强版 (algId 14)
|
│ ├── trend_slope3.* # algId 14: 百分比变化率
|
||||||
│ ├── roller2.* # 离群检测 (algId 9)
|
│ ├── roller2.* # algId 9: 均值离群
|
||||||
│ ├── roller3.* # 离群检测 v3 (algId 16,18)
|
│ ├── roller3.* # algId 16,18: 中位数离群
|
||||||
│ ├── fault_code.* # 故障代码解析 (algId 10-11)
|
│ ├── fault_code.* # algId 10-11: 故障码解析
|
||||||
│ ├── glitch_detection.* # 毛刺检测 (algId 15)
|
│ ├── glitch_detection.* # algId 15: 毛刺检测 → Python
|
||||||
│ └── null.h # 空算法(未匹配时使用)
|
│ └── null.h # 未匹配的空算法
|
||||||
├── threads/ # 多线程调度
|
├── threads/ # 多线程调度
|
||||||
│ ├── manager.* # 线程管理器:按 TaskSeq 分配线程
|
│ ├── manager.* # 按 TaskSeq 分组,维护 HandlerExec
|
||||||
│ └── handler_exec.* # 单线程执行句柄:管理队列,调度规则
|
│ └── handler_exec.* # 单线程执行句柄 + 5 种队列
|
||||||
├── exp_macro/ # 表达式宏(delta/max/min/hold/persist 等)
|
├── exp_macro/ # 表达式宏替换(delta/persist/hold/max/min)
|
||||||
├── feature_extraction/ # 特征提取(LSM 拟合 / STA 统计 / 分布分析)
|
├── feature_extraction/ # DAA::STA(统计) / DAA::LSM(拟合) / 分布分析
|
||||||
├── utility/ # 工具类
|
├── utility/ # 工具类
|
||||||
│ ├── alarm_poster.* # 报警推送
|
│ ├── alarm_poster.* # 报警多渠道推送 + 去抖
|
||||||
│ ├── alarm_handler.hpp # 报警处理器
|
│ ├── alarm_handler.hpp # CMemQueue 消费线程
|
||||||
│ ├── build_alarm_info.* # 报警信息构造
|
│ ├── build_alarm_info.* # 报警 JSON 构造
|
||||||
│ ├── condition_monitor.hpp # 条件监控
|
│ ├── condition_monitor.hpp# 正常数据保存条件判断
|
||||||
│ ├── eqp_stat.* # 设备统计
|
│ ├── eqp_stat.* # RuleStatShm 统计管理
|
||||||
│ ├── eqp_status.* # 设备运行状态
|
│ ├── eqp_status.* # 设备运行状态读取
|
||||||
│ ├── ExpModule.* # 表达式模块
|
│ ├── ExpModule.* # 表达式加载与变量管理
|
||||||
│ ├── HoldTime.* # 保持时间处理
|
│ ├── HoldTime.* # hold(N,T) 状态保持
|
||||||
│ ├── update_data.* # 共享内存数据更新
|
│ ├── update_data.* # 规则数据写入 Memcached
|
||||||
│ ├── proxy_py.* # Python 算法代理
|
│ ├── proxy_py.* # C++→Python 通信(共享内存 + ICE)
|
||||||
│ ├── StatExp.hpp # 带状态表达式函数
|
│ ├── StatExp.hpp # 带状态自定义函数
|
||||||
│ ├── VarsCache.hpp # 变量缓存
|
│ ├── VarsCache.hpp # mm_vars 预分配缓存
|
||||||
│ └── XorShift128Plus.hpp # 随机数生成器
|
│ └── XorShift128Plus.hpp # 随机数(防惊群)
|
||||||
├── table_struct/ # DB2 表结构映射(ORM)
|
├── table_struct/ # DB2 ORM: T_RULE_CFG / T_RULE_RESULT 等
|
||||||
├── define/ # 全局定义(枚举、常量、结构体)
|
├── define/ # 枚举常量:ProcessType / ExpType / EventCase 等
|
||||||
├── doc/ # Doxygen 文档
|
├── doc/ # Doxygen 文档
|
||||||
├── .do_not_use/ # 弃用的算法代码(不参与编译)
|
├── .do_not_use/ # 弃用算法(不参与编译)
|
||||||
└── CMakeLists.txt # 构建配置
|
└── CMakeLists.txt
|
||||||
```
|
```
|
||||||
|
|
||||||
## 数据流
|
## 数据流全景
|
||||||
|
|
||||||
```
|
```
|
||||||
现场PLC/传感器
|
PLC/传感器
|
||||||
│
|
│
|
||||||
▼
|
▼
|
||||||
iHyperDB (实时/历史数据库) ──← cron/task 查询历史
|
DSF/OPC ──→ 共享内存 MemFix<PLC_DATA>
|
||||||
│
|
│
|
||||||
▼
|
├──→ GlobaltemSharedMemory (双缓冲, ~19ms)
|
||||||
共享内存 (实时 tag 数据) ──← mon 实时读取
|
│ │
|
||||||
|
│ ├──→ eqpalg-mon: mm_vars → 表达式引擎 → 报警/统计
|
||||||
|
│ │ │
|
||||||
|
│ │ ├──→ AlarmPoster → DB2 T_RULE_RESULT / ICE MQ
|
||||||
|
│ │ ├──→ 正常数据 → DB2 T_RULE_SAMPLE_*
|
||||||
|
│ │ ├──→ 统计累积 → RuleStatShm → cron 学习
|
||||||
|
│ │ └──→ 页面数据 → EqpStat → Memcached
|
||||||
|
│ │
|
||||||
|
│ ├──→ eqpalg-cron: RuleStatShm → DAA::STA → CI → DB2
|
||||||
|
│ │
|
||||||
|
│ └──→ eqpalg-task: iHyperDB → 拟合/统计 → DB2
|
||||||
│
|
│
|
||||||
▼
|
└──→ dsm: ZONE10 → DataQuery → /dscdata/Rule*Data/*.json
|
||||||
eqpalg 进程
|
|
||||||
│
|
|
||||||
├──→ 报警 → ICE电文 → 其他系统 / 页面展示
|
|
||||||
├──→ 统计结果 → DB2 (T_RULE_RESULT, T_RULE_SAMPLE_*)
|
|
||||||
└──→ 运行状态 → DB2 (T_RULE_RECORD_TIME, T_EQP_*)
|
|
||||||
```
|
```
|
||||||
|
|
||||||
## 启动流程
|
## 启动流程
|
||||||
|
|
||||||
1. `eqpalg::start()` — 根据模块名确定进程类型(mon/cron/task)
|
1. `eqpalg::start()` — 根据模块名确定 `glob_process_type`
|
||||||
2. 创建 `EqpAlgICEI` 实例 — 注册 ICE 接口
|
2. 创建 `EqpAlgICEI` — 注册 ICE + 初始化共享内存缓存线程(仅 mon)
|
||||||
3. `AlgorithmManager` 构造 — 从 DB2 `T_RULE_CFG` 表读取所有规则配置
|
3. `AlgorithmManager` — 从 DB2 `T_RULE_CFG` 加载所有规则配置
|
||||||
4. `threads::Manager::start()` — 按 `TaskSeq` 分组创建线程
|
4. `threads::Manager::start()` — 按 `TaskSeq` 分组创建 `HandlerExec` 线程
|
||||||
5. 每个线程创建 `HandlerExec`,根据规则 algId 调用 `build_algorithm()` 创建算法实例
|
5. mon: 额外启动 alarm handler 线程(500ms 轮询 CMemQueue)
|
||||||
6. mon 进程额外启动 `mem_cached_thread_` — 以约 19ms 间隔刷新共享内存缓存
|
6. mon: `mem_cached_thread_` 开始以 ~19ms 间隔刷新 `GlobaltemSharedMemory`
|
||||||
|
|
||||||
## 相关进程
|
## 相关进程
|
||||||
|
|
||||||
| 进程 | 关系 |
|
| 进程 | 关系 |
|
||||||
|------|------|
|
|------|------|
|
||||||
| **dsm** | eqpalg-mon 定期向 dsm 推送统计数据 |
|
| **dsm** | eqpalg-mon 的 `TimeNotify(5)` 向 dsm 推送 ruleId 列表;eqpalg 将规则配置写入共享内存 ZONE10 供 dsm 读取归档 |
|
||||||
| **eqpalg-cron** | eqpalg-mon 收到 99999 电文时转发给 cron |
|
| **eqpalg-cron** | eqpalg-mon 收到 99999 电文时通过 ICE 代理转发给 cron,保持配置同步 |
|
||||||
| **RICS** | 同系统内其他设备算法进程 |
|
| **RICS** | RICS 读取同一条 `T_RULE_CFG` 配置,格式化为 JSON 推送到 Memcached 供前端展示,与 eqpalg 是"展示面"与"执行面"的关系 |
|
||||||
| **页面服务** | 通过 ICE 发送规则增删改查指令 |
|
| **eqpm** | eqpalg 产生报警写入 `T_RULE_RESULT` → eqpm 查询 `FV_RESULT_JOIN_EQPID` 获取报警统计用于设备状态面板 |
|
||||||
|
| **前端/页面服务** | 通过 ICE 发送规则 CRUD 指令;通过 Memcached 读取规则状态和设备数据 |
|
||||||
|
|
||||||
## 作者
|
## 作者
|
||||||
|
|
||||||
|
|||||||
154
eqpm/eqpm_readme.md
Normal file
154
eqpm/eqpm_readme.md
Normal file
@ -0,0 +1,154 @@
|
|||||||
|
# eqpm — 设备点检与状态管理
|
||||||
|
|
||||||
|
## 概述
|
||||||
|
|
||||||
|
eqpm(**Eq**uipment **P**oint-inspection **M**anagement / 设备点检管理)是 EIS 系统中的设备预测性维护和实时状态监控服务。它做两件事:
|
||||||
|
|
||||||
|
1. **预测性维护** — 根据生产累计指标(处理重量、长度或经过天数),计算设备何时需要检修,预测下次检修日期
|
||||||
|
2. **实时状态监控** — 解码遥测二进制数据,跟踪报警信息,将设备状态推送到 Memcached 供仪表盘使用
|
||||||
|
|
||||||
|
## 进程架构
|
||||||
|
|
||||||
|
eqpm 作为单个 PACE 平台组件运行,注册 ICE 端点 `"baosight/eqpm"`。
|
||||||
|
|
||||||
|
```
|
||||||
|
┌──────────────────────────┐
|
||||||
|
│ eqpm 进程 │
|
||||||
|
│ │
|
||||||
|
ICE TimeNotify ──→│ 事件0 → update_repair() │──→ DB2 T_EQP_REPAIR
|
||||||
|
ICE SendData ────→│ 事件1 → 状态写入 │──→ Memcached
|
||||||
|
(1002/99999) │ 事件2 → update_alarm() │──→ DB2
|
||||||
|
│ 事件3 → update_coil() │
|
||||||
|
│ │
|
||||||
|
共享内存 ────────→│ EqpmAlg::update_data() │──→ 产量环形缓冲区
|
||||||
|
(FV_PDI) │ │
|
||||||
|
└──────────────────────────┘
|
||||||
|
```
|
||||||
|
|
||||||
|
## ICE 接口
|
||||||
|
|
||||||
|
| 方法 | 事件号 | 说明 |
|
||||||
|
|------|--------|------|
|
||||||
|
| `SendDataShort` | 99999 | 触发 `update_repair()` 刷新检修计划 |
|
||||||
|
| `SendDataShort` | 1002 | 解码机组状态二进制遥测数据 |
|
||||||
|
| `SendDataLong` | — | 未实现 |
|
||||||
|
| `TimeNotify` | 0 | 更新检修计划 |
|
||||||
|
| `TimeNotify` | 1 | 获取状态 JSON 写入 Memcached(key: `"unit_status"`) |
|
||||||
|
| `TimeNotify` | 2 | 更新报警信息 |
|
||||||
|
| `TimeNotify` | 3 | 更新钢卷信息 |
|
||||||
|
|
||||||
|
## 核心模块
|
||||||
|
|
||||||
|
### 1. EqpmAlg — 预测性维护引擎
|
||||||
|
|
||||||
|
负责设备点检计划的计算。核心数据结构:
|
||||||
|
|
||||||
|
```
|
||||||
|
EqpRule {
|
||||||
|
int rule_type; // 0=无 1=重量(吨) 2=长度(千米) 3=时间(天)
|
||||||
|
double data; // 自上次检修后的累计值
|
||||||
|
TimePoint repair_date; // 上次检修日期
|
||||||
|
TimePoint repair_plan; // 预测下次检修日期
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**三种检修规则类型**:
|
||||||
|
|
||||||
|
| rule_type | 名称 | 计算方式 |
|
||||||
|
|-----------|------|----------|
|
||||||
|
| 1 | 基于重量 | 从 FV_PDI 累计每日重量(吨),超阈值触发检修,按日均重量外推未来日期 |
|
||||||
|
| 2 | 基于长度 | 从 FV_PDI 累计每日长度(千米),超阈值触发检修,按日均长度外推未来日期 |
|
||||||
|
| 3 | 基于时间 | 按日历天数计算,距上次检修超过 interval 天后预测在 interval 天满的那天 |
|
||||||
|
|
||||||
|
**工作流程**:
|
||||||
|
|
||||||
|
1. **`update_data()`** — 从 FV_PDI 视图读取每日钢卷产量(长度、重量),写入共享内存环形缓冲区(10年,3650天)
|
||||||
|
2. **`update_slope()`** — 计算 3 日滑动平均的日产量(`length_slope_`、`weight_slope_`),用于外推预测
|
||||||
|
3. **`update_repair()`** — 从 DB2 加载设备规则配置,针对每条有规则类型的设备计算累计值和下次检修日期
|
||||||
|
4. **`update_db2()`** — 将计算结果写回 DB2 `T_EQP_REPAIR` 表
|
||||||
|
|
||||||
|
**产量数据流**:
|
||||||
|
|
||||||
|
```
|
||||||
|
FV_PDI (钢卷视图) → EqpmAlg::update_data()
|
||||||
|
│
|
||||||
|
▼
|
||||||
|
EqpmRecord 共享内存 (环形缓冲区)
|
||||||
|
/users/dsc/shm/EqpmRecord_boost.mmap
|
||||||
|
│
|
||||||
|
▼
|
||||||
|
update_slope() → 日均产量
|
||||||
|
│
|
||||||
|
▼
|
||||||
|
update_rule_data() → 预测检修日期
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. EqpStatus — 实时状态监控
|
||||||
|
|
||||||
|
解析来自 PLC 的二进制遥测数据,转换为结构化 JSON。
|
||||||
|
|
||||||
|
**解码的数据组**:
|
||||||
|
|
||||||
|
| 数据组 | 内容 |
|
||||||
|
|--------|------|
|
||||||
|
| `status_data` | 泵状态、液位、温度、速度等 25 个数值测点 |
|
||||||
|
| `tension` | 张力数据(2组 × 12个值) |
|
||||||
|
| `cpc` | CPC 对中数据(3组 × 10个值,含位掩码处理) |
|
||||||
|
| `TR` | 运输辊道数据(钢卷ID + 5个数值,含时间格式转换) |
|
||||||
|
| `POR` | 卷取机数据(入口/出口共2组,钢卷ID + 4个数值) |
|
||||||
|
|
||||||
|
**报警跟踪**(`update_alarm_info()`):
|
||||||
|
|
||||||
|
- 查询 DB2 视图 `FV_RESULT_JOIN_EQPID`,统计最近 3 天的报警
|
||||||
|
- `isAlarm = 0`: 无报警;`isAlarm = 1`: 有新报警(statuscode=100);`isAlarm = 2`: 仅跟踪报警(statuscode=200)
|
||||||
|
|
||||||
|
**钢卷信息**(`update_coil_info()`):
|
||||||
|
|
||||||
|
- 从 DB2 `FV_DSC_PDI_DATA` 读取当前生产中的钢卷数据(最多4条)
|
||||||
|
- 每条包含:入口外径、出口外径、厚度、宽度、重量、长度、钢种等9个字段
|
||||||
|
|
||||||
|
### 3. 共享内存环形缓冲区(EqpmRecord)
|
||||||
|
|
||||||
|
- **路径**: `/users/dsc/shm/EqpmRecord_boost.mmap`(500MB)
|
||||||
|
- **结构**: `Map<int, EqpmRecord>`,天偏移量为 key,存储每日重量和长度
|
||||||
|
- **容量**: 3650天(10年)
|
||||||
|
- **元数据**: `TimeRecord` 记录有效时间范围和日均产量
|
||||||
|
|
||||||
|
## 目录结构
|
||||||
|
|
||||||
|
```
|
||||||
|
eqpm/
|
||||||
|
├── eqpm.cc/h # 进程入口
|
||||||
|
├── eqpm_icei.cc/h # ICE 接口(处理事件和定时回调)
|
||||||
|
├── eqpm_alg.cc/h # 预测性维护算法
|
||||||
|
├── eqp_status.cc/h # 实时状态监控、遥测解码
|
||||||
|
├── EqpmRecord.h # 共享内存环形缓冲区定义
|
||||||
|
├── utility.cc/h # 时间工具(时区感知、UTC+8)
|
||||||
|
├── jsonReader.hpp # JSON 文件读取工具
|
||||||
|
├── rule_info.h # 规则信息结构体(暂未使用)
|
||||||
|
├── table_struct/ # DB2 表结构
|
||||||
|
│ ├── fv_pdi.h # 卷材产量视图
|
||||||
|
│ ├── t_eqp_data.h # 设备规则配置
|
||||||
|
│ ├── t_eqp_repair.h # 检修记录(输出)
|
||||||
|
│ ├── FV_RESULT_JOIN_EQPID.h # 报警信息视图
|
||||||
|
│ └── FV_DSC_PDI_DATA.h # 钢卷信息视图
|
||||||
|
├── json/ # JSON 模板与配置
|
||||||
|
│ ├── eqp_status.json # 输出模板
|
||||||
|
│ ├── eqp_status_config.json # 遥测解码映射
|
||||||
|
│ └── eqpm.json # 测试用 MQ 消息
|
||||||
|
└── CMakeLists.txt
|
||||||
|
```
|
||||||
|
|
||||||
|
## 与其它进程的关系
|
||||||
|
|
||||||
|
| 进程 | 关系 |
|
||||||
|
|------|------|
|
||||||
|
| **eqpalg** | eqpalg 产生设备报警 → eqpm 查询 FV_RESULT_JOIN_EQPID 获取报警统计 |
|
||||||
|
| **RICS** | 同系统内独立模块,RICS 做规则配置展示 |
|
||||||
|
| **dsm** | 同系统内独立模块,dsm 做规则数据归档 |
|
||||||
|
| **前端页面** | eqpm 将实时状态和检修计划写入 Memcached 供前端读取 |
|
||||||
|
|
||||||
|
## 作者
|
||||||
|
|
||||||
|
- Cat (null.null.null@qq.com)
|
||||||
|
- 宝信软件(Baosight Co. Ltd.)
|
||||||
Loading…
Reference in New Issue
Block a user