smart-home/smart-home-app/报警解除状态-isActive字段说明.md
2026-02-26 09:16:34 +08:00

285 lines
8.7 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 报警解除状态 - 基于ESP32的isActive字段
## 🎯 核心逻辑
利用ESP32已有的 `isActive` 字段来判断报警是否已解除:
- **`isActive: true`** = 报警正在持续中
- **`isActive: false`** = 报警已自动解除
## 📊 ESP32数据格式
ESP32的报警历史API (`/api/alarm/history`) 已经包含 `isActive` 字段:
```json
{
"alarms": [
{
"id": 1,
"title": "燃烧报警报警",
"desc": "热源持续升温,温度超过阈值",
"temp": 65.5,
"time": "14:26:10",
"date": "01-22",
"location": "厨房区域",
"isActive": false, // ✅ 关键字段false表示已解除
"timestamp_ms": 1737548770000
},
{
"id": 2,
"title": "无人值守风险",
"desc": "热源持续升温厨房无人5分钟",
"temp": 45.2,
"time": "21:30:00",
"date": "01-22",
"location": "厨房区域",
"isActive": true, // ⚠️ 仍在持续
"timestamp_ms": 1737548400000
}
],
"anyAlarmActive": true
}
```
## 🔧 前端实现逻辑
### 1. 解除状态判断
`pages/kitchen/history.vue``parseAlarmHistory` 方法中:
```javascript
// 1. 优先使用ESP32的isActive字段判断isActive=false表示已解除
if (alarm.hasOwnProperty('isActive') && alarm.isActive === false) {
resolved = true
resolvedType = 'auto' // ESP32自动检测解除
// 如果ESP32提供了解除时间使用它
if (alarm.resolvedAt || alarm.resolved_at || alarm.resolvedTimestamp) {
const resolvedTimestamp = alarm.resolvedAt || alarm.resolved_at || alarm.resolvedTimestamp
const resolvedDate = new Date(typeof resolvedTimestamp === 'number' ? resolvedTimestamp : Date.parse(resolvedTimestamp))
resolvedTime = resolvedDate.getHours() + ':' + String(resolvedDate.getMinutes()).padStart(2, '0')
} else {
// 如果没有解除时间,显示为"已解除"(不显示具体时间)
resolvedTime = ''
}
}
```
### 2. UI显示
在报警卡片中:
```vue
<view class="alarm-resolved" v-if="alarm.resolved">
<text class="resolved-icon"></text>
<!-- 有解除时间时 -->
<text class="resolved-text" v-if="alarm.resolvedTime">
已于 {{alarm.resolvedTime}} {{alarm.resolvedType === 'auto' ? '自动解除' : '用户处理'}}
</text>
<!-- 没有解除时间时 -->
<text class="resolved-text" v-else>
{{alarm.resolvedType === 'auto' ? '已自动解除' : '已处理'}}
</text>
</view>
```
### 3. 显示效果
**有解除时间**
```
无人值守风险
热源持续升温厨房无人5分钟
热点区域: 厨房区域
✅ 已于 21:38 自动解除
```
**没有解除时间**
```
燃烧报警报警
热源持续升温,温度超过阈值
热点区域: 厨房区域
✅ 已自动解除
```
## 🚀 ESP32端建议优化
### 当前实现
ESP32已经在报警数据中提供了 `isActive` 字段,这很好!
### 建议增强
为了提供更完整的解除信息建议ESP32在报警解除时记录解除时间
```cpp
// AlarmManager.cpp
struct AlarmRecord {
int id;
String title;
String desc;
float temp;
unsigned long timestamp;
String location;
bool isActive; // ✅ 已有
// 建议新增
unsigned long resolvedAt; // 解除时间戳(毫秒)
};
// 当检测到报警解除时
void checkAndResolveAlarms() {
for (auto& alarm : alarmHistory) {
if (alarm.isActive && currentTemp < SAFE_TEMP) {
alarm.isActive = false;
alarm.resolvedAt = millis(); // 记录解除时间
ESP_LOGI(TAG, "报警已解除: %s, 解除时间: %lu",
alarm.title.c_str(), alarm.resolvedAt);
}
}
}
```
### 增强后的API响应
```json
{
"alarms": [
{
"id": 1,
"title": "燃烧报警报警",
"desc": "热源持续升温,温度超过阈值",
"temp": 65.5,
"time": "14:26:10",
"date": "01-22",
"location": "厨房区域",
"isActive": false,
"timestamp_ms": 1737548770000,
"resolvedAt": 1737548880000 // ✨ 新增:解除时间戳
}
]
}
```
## 📋 数据流程
### 1. 报警触发
```
ESP32检测到高温
→ 创建报警记录 (isActive=true)
→ 推送到云端
→ APP显示报警无解除状态
```
### 2. 报警解除
```
ESP32检测到温度恢复
→ 更新报警记录 (isActive=false, resolvedAt=当前时间)
→ 同步到云端
→ APP显示解除状态 ✅
```
### 3. APP查询
```
APP请求报警历史
→ ESP32返回所有报警包含isActive字段
→ APP根据isActive判断是否显示解除状态
→ 如果有resolvedAt显示具体解除时间
→ 如果没有resolvedAt只显示"已自动解除"
```
## 🎨 UI效果对比
### 未解除的报警
```
┌─────────────────────────────┐
│ 🔥 高温危险 65.5°C │
│ 14:26 │
│ │
│ 热源持续升温,温度超过阈值 │
│ 热点区域: 厨房区域 │
│ │
│ [标记已读] [删除] │
└─────────────────────────────┘
```
### 已解除的报警(有时间)
```
┌─────────────────────────────┐
│ 👤 无人值守风险 45.2°C │
│ 21:30 │
│ │
│ 热源持续升温厨房无人5分钟 │
│ 热点区域: 厨房区域 │
│ ┌─────────────────────────┐ │
│ │ ✅ 已于 21:38 自动解除 │ │
│ └─────────────────────────┘ │
│ │
│ [标记已读] [删除] │
└─────────────────────────────┘
```
### 已解除的报警(无时间)
```
┌─────────────────────────────┐
│ 🔥 燃烧报警报警 65.5°C │
│ 14:26 │
│ │
│ 热源持续升温,温度超过阈值 │
│ 热点区域: 厨房区域 │
│ ┌─────────────────────────┐ │
│ │ ✅ 已自动解除 │ │
│ └─────────────────────────┘ │
│ │
│ [标记已读] [删除] │
└─────────────────────────────┘
```
## 🔍 调试信息
在首页 (`pages/index/index.vue`) 中已经有详细的调试日志:
```javascript
console.log('📊 最新报警状态:', {
id: this.recentAlarms[0].id,
title: this.recentAlarms[0].title,
isActive: this.recentAlarms[0].isActive,
anyAlarmActive: response.data.anyAlarmActive,
shouldShowResetBtn: this.isAlarmActive(this.recentAlarms[0])
})
console.log('🔍 Alarm Reset按钮显示检查:', {
totalAlarms: this.recentAlarms.length,
firstAlarmActive: this.recentAlarms.length > 0 ? this.isAlarmActive(this.recentAlarms[0]) : false,
firstAlarmData: this.recentAlarms.length > 0 ? {
hasIsActive: this.recentAlarms[0].hasOwnProperty('isActive'),
isActiveValue: this.recentAlarms[0].isActive,
timestamp_ms: this.recentAlarms[0].timestamp_ms,
timeDiff: this.recentAlarms[0].timestamp_ms ? (Date.now() - this.recentAlarms[0].timestamp_ms) : null
} : null
})
```
这些日志可以帮助验证 `isActive` 字段是否正确传递。
## ✅ 优势
使用 `isActive` 字段的优势:
1. **无需额外开发** - ESP32已经提供了这个字段
2. **实时准确** - ESP32实时检测温度能准确判断报警是否解除
3. **向后兼容** - 即使ESP32不提供 `resolvedAt`,也能显示解除状态
4. **逻辑清晰** - `isActive=false` 直观表示报警已解除
## 📝 总结
现在报警历史页面已经支持:
1. ✅ 读取ESP32的 `isActive` 字段
2.`isActive=false` 时显示"已自动解除"
3. ✅ 如果有 `resolvedAt` 时间,显示具体解除时间
4. ✅ 没有时间时,显示简化文案
5. ✅ 绿色背景样式,清晰易识别
**无需修改ESP32代码即可立即使用** 如果ESP32后续添加 `resolvedAt` 字段APP会自动显示具体解除时间。