2. Alarm状态模型:Alarm Set状态、Alarm Clear状态、Alarm状态转换图、状态机设计原则
2.1 Alarm状态模型概述
在SECS/GEM协议中,Alarm(报警)是设备向主机报告异常或故障的核心机制。Alarm状态模型定义了报警从产生到恢复的完整生命周期,是设备端实现可靠报警管理的基础。该模型基于有限状态机(FSM)理论,确保报警状态的确定性、可追溯性和一致性。
Alarm状态模型包含两个基本状态:Alarm Set(报警设置/激活)和Alarm Clear(报警清除/恢复)。设备端为每个定义的Alarm ID维护一个独立的状态机实例,主机通过SECS消息(如S5F1/S5F2、S5F3/S5F4)查询或修改报警状态。
2.2 Alarm Set状态
Alarm Set状态表示报警条件当前为真,设备检测到异常或故障。进入Set状态时,设备应执行以下动作:
- 记录报警发生的时间戳、报警ID、报警文本(ALCD/ALTX)。
- 向主机主动发送S5F1(Alarm Report Send)消息,通知报警已激活。
- 根据报警严重级别(ALCD),触发设备本地响应(如停止工艺、点亮指示灯、记录日志)。
- 将报警状态持久化到非易失性存储,防止断电丢失。
| 属性 | 说明 | 示例值 |
|---|---|---|
| ALID | 报警唯一标识符,1~65535 | 101 |
| ALCD | 报警代码,bit0=1表示Set,bit1=1表示需主机确认 | 0x03 (Set + 需确认) |
| ALTX | 报警文本描述,最多120字节 | "Chamber A Over Temperature" |
| Timestamp | 报警发生时间(设备本地时间) | 2025-03-21 14:30:00 |
2.3 Alarm Clear状态
Alarm Clear状态表示报警条件已消除,设备恢复正常。进入Clear状态时,设备应执行以下动作:
- 记录报警清除的时间戳。
- 向主机主动发送S5F1消息,ALCD的bit0=0表示Clear。
- 恢复因报警而暂停的工艺或操作(如适用)。
- 更新报警状态持久化记录。
Clear状态并不意味着报警历史被删除;设备应维护报警历史日志,供后续诊断和分析。主机可通过S5F3(Enable/Disable Alarm)命令控制报警的使能状态,但使能/禁用不影响Set/Clear状态机——禁用状态下的报警不会向主机发送S5F1,但设备内部仍可记录。
2.4 Alarm状态转换图
下图展示了Alarm状态机的完整转换关系,包含正常转换路径和边界条件:
状态转换图的关键路径说明:
- 上电/初始化 → Clear:设备启动后,默认所有报警处于Clear状态,除非非易失性存储中记录了未恢复的报警。
- Clear → Set:设备检测到报警条件成立(如温度超限、压力异常、通信超时),立即转换到Set状态并上报主机。
- Set → Clear:设备检测到报警条件消除(如温度回落、通信恢复),转换到Clear状态并上报主机。
- Set → Set(自环):同一报警在Set状态下再次触发(如间歇性故障),设备应忽略重复转换,避免重复上报。
2.5 状态机设计原则
在工程实施中,Alarm状态机设计需遵循以下原则,确保系统健壮性和协议合规性:
| 原则 | 描述 | 实施建议 |
|---|---|---|
| 确定性 | 每个状态和转换必须唯一确定,不存在歧义路径 | 使用枚举类型定义状态,避免布尔变量;转换条件使用互斥逻辑 |
| 原子性 | 状态转换过程不可中断,避免部分更新导致状态不一致 | 在临界区或互斥锁保护下执行转换;先更新状态再发送消息 |
| 持久化 | 报警状态在设备断电后必须恢复 | 使用NVRAM/EEPROM/Flash存储状态;上电时读取并恢复 |
| 幂等性 | 重复触发同一转换不应产生副作用 | Set状态下忽略重复Set事件;Clear状态下忽略重复Clear事件 |
| 可追溯性 | 每次状态转换都应记录日志 | 记录时间戳、旧状态、新状态、触发源(本地/主机) |
| 超时保护 | 防止状态机因外部条件卡死 | 为每个报警设置最大Set持续时间,超时自动上报或触发安全动作 |
2.6 状态机实现示例(伪代码)
以下是一个简化的Alarm状态机实现框架,展示核心转换逻辑:
// Alarm状态枚举
typedef enum {
ALARM_STATE_CLEAR = 0,
ALARM_STATE_SET
} AlarmState;
// Alarm状态机结构体
typedef struct {
uint16_t alid; // 报警ID
AlarmState state; // 当前状态
uint8_t alcd; // 报警代码
char altx[120]; // 报警文本
uint32_t timestamp; // 最后转换时间
bool enabled; // 使能标志
} AlarmFSM;
// 状态转换函数
AlarmError AlarmFSM_Transition(AlarmFSM *fsm, AlarmEvent event) {
if (fsm == NULL) return ALARM_ERR_NULL_PTR;
// 获取锁(原子操作)
Mutex_Lock(&fsm->lock);
AlarmState old_state = fsm->state;
AlarmError err = ALARM_OK;
switch (fsm->state) {
case ALARM_STATE_CLEAR:
if (event == ALARM_EVENT_SET) {
fsm->state = ALARM_STATE_SET;
fsm->timestamp = GetSystemTime();
// 发送S5F1到主机
err = SendS5F1(fsm->alid, fsm->alcd | 0x01, fsm->altx);
// 记录日志
LogAlarmTransition(fsm->alid, old_state, fsm->state);
}
// Clear状态下忽略Clear事件(幂等性)
break;
case ALARM_STATE_SET:
if (event == ALARM_EVENT_CLEAR) {
fsm->state = ALARM_STATE_CLEAR;
fsm->timestamp = GetSystemTime();
// 发送S5F1到主机(ALCD bit0=0)
err = SendS5F1(fsm->alid, fsm->alcd & 0xFE, fsm->altx);
LogAlarmTransition(fsm->alid, old_state, fsm->state);
}
// Set状态下忽略Set事件(幂等性)
break;
default:
err = ALARM_ERR_INVALID_STATE;
break;
}
// 释放锁
Mutex_Unlock(&fsm->lock);
return err;
}
2.7 状态机设计避坑指南
以下是实际项目中常见的Alarm状态机设计问题及解决方案:
- 状态丢失:设备断电后未持久化Set状态,上电后报警丢失。→ 使用NVRAM存储状态,上电时恢复。
- 重复上报:Set状态下再次触发Set事件,导致主机收到重复S5F1。→ 实现幂等性检查,状态不变时不发送消息。
- 状态不一致:设备内部状态与主机记录不同步。→ 主机定期发送S5F2查询所有报警状态,设备响应完整状态表。
- 死锁:状态机在转换过程中等待主机确认(如S5F1等待S5F2),但主机无响应。→ 设置超时定时器,超时后强制完成转换并记录异常。
- 资源泄漏:动态分配报警状态机实例但未释放。→ 使用静态数组预分配最大报警数,避免动态内存。
2.8 状态机与SECS/GEM消息交互
Alarm状态机与SECS/GEM消息的交互关系如下表所示:
| SECS消息 | 方向 | 触发时机 | 对状态机的影响 |
|---|---|---|---|
| S5F1 (Alarm Report Send) | 设备→主机 | 状态转换时主动上报 | 状态转换后立即发送,包含ALID和ALCD |
| S5F2 (Alarm Report Ack) | 主机→设备 | 响应S5F1 | 确认收到,设备可清除发送缓冲区 |
| S5F3 (Enable/Disable Alarm) | 主机→设备 | 主机控制报警使能 | 修改enabled标志,不影响Set/Clear状态 |
| S5F4 (Enable/Disable Alarm Ack) | 设备→主机 | 响应S5F3 | 确认使能/禁用操作 |
| S5F5 (List Alarm) | 主机→设备 | 主机查询所有报警状态 | 设备返回当前所有ALID的状态列表 |
| S5F6 (List Alarm Ack) | 设备→主机 | 响应S5F5 | 包含每个ALID的Set/Clear状态 |
状态机设计必须确保消息处理与状态转换同步:在发送S5F1之前完成状态更新,在收到S5F2之前不重复发送同一报警的S5F1。主机可通过S5F5/S5F6批量同步设备报警状态,作为状态机一致性的最终保障。