smart-home/verify_cloud_alarm_reporting.py
2026-02-26 09:16:34 +08:00

187 lines
7.4 KiB
Python
Raw Permalink 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.

#!/usr/bin/env python3
"""
验证ESP32云端报警上报功能
通过模拟云端服务器来测试ESP32的上报功能
"""
import socket
import threading
import json
import time
from datetime import datetime
from http.server import HTTPServer, BaseHTTPRequestHandler
import urllib.parse
class CloudAlarmHandler(BaseHTTPRequestHandler):
"""模拟云端报警接收服务器"""
received_alarms = []
def do_POST(self):
"""处理POST请求"""
if self.path == '/device-alarms':
try:
# 读取请求体
content_length = int(self.headers.get('Content-Length', 0))
post_data = self.rfile.read(content_length)
# 解析JSON数据
alarm_data = json.loads(post_data.decode('utf-8'))
# 检查设备密钥
device_key = self.headers.get('X-Device-Key')
expected_key = "39dc753bd0cb19da5050a2f0edf932f851f5b21b90a6d06ecf9a28d81079a0a6"
print(f"\n📨 收到ESP32报警上报:")
print(f"时间: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}")
print(f"设备密钥: {device_key}")
print(f"报警数据: {json.dumps(alarm_data, indent=2, ensure_ascii=False)}")
if device_key == expected_key:
# 保存报警数据
alarm_data['received_at'] = datetime.now().isoformat()
CloudAlarmHandler.received_alarms.append(alarm_data)
# 返回成功响应
response = {
"code": 200,
"message": "报警上报成功",
"data": {
"alarmId": len(CloudAlarmHandler.received_alarms),
"receivedAt": alarm_data['received_at']
}
}
self.send_response(200)
self.send_header('Content-Type', 'application/json')
self.end_headers()
self.wfile.write(json.dumps(response).encode('utf-8'))
print(f"✅ 报警接收成功! 总计收到 {len(CloudAlarmHandler.received_alarms)} 个报警")
else:
# 设备密钥错误
self.send_response(401)
self.send_header('Content-Type', 'application/json')
self.end_headers()
error_response = {"code": 401, "message": "设备密钥验证失败"}
self.wfile.write(json.dumps(error_response).encode('utf-8'))
print(f"❌ 设备密钥验证失败")
except Exception as e:
print(f"❌ 处理报警数据时出错: {e}")
self.send_response(500)
self.send_header('Content-Type', 'application/json')
self.end_headers()
error_response = {"code": 500, "message": f"服务器内部错误: {str(e)}"}
self.wfile.write(json.dumps(error_response).encode('utf-8'))
else:
# 其他路径返回404
self.send_response(404)
self.end_headers()
def do_GET(self):
"""处理GET请求"""
if self.path == '/health':
self.send_response(200)
self.send_header('Content-Type', 'application/json')
self.end_headers()
response = {"status": "ok", "message": "模拟云端服务器运行正常"}
self.wfile.write(json.dumps(response).encode('utf-8'))
else:
self.send_response(404)
self.end_headers()
def log_message(self, format, *args):
"""禁用默认日志输出"""
pass
def start_mock_cloud_server(port=36988):
"""启动模拟云端服务器"""
try:
server = HTTPServer(('0.0.0.0', port), CloudAlarmHandler)
print(f"🌐 模拟云端服务器启动成功")
print(f"监听地址: http://0.0.0.0:{port}")
print(f"报警接收端点: http://0.0.0.0:{port}/device-alarms")
print("=" * 50)
server.serve_forever()
except Exception as e:
print(f"❌ 启动模拟云端服务器失败: {e}")
def trigger_esp32_alarm():
"""尝试触发ESP32报警通过接触传感器"""
print("\n🔥 触发ESP32报警指导:")
print("=" * 40)
print("请执行以下操作之一来触发报警:")
print("1. 用手指接触热成像传感器表面")
print("2. 用打火机或热源靠近传感器")
print("3. 快速移动热源触发异常升温")
print("4. 等待系统自动检测")
print("=" * 40)
print("触发报警后ESP32应该会自动上报到模拟云端服务器")
def monitor_received_alarms():
"""监控接收到的报警"""
print("\n📊 报警监控中...")
last_count = 0
while True:
current_count = len(CloudAlarmHandler.received_alarms)
if current_count > last_count:
print(f"\n🚨 新报警通知! 总计: {current_count}")
for i in range(last_count, current_count):
alarm = CloudAlarmHandler.received_alarms[i]
print(f"报警 #{i+1}:")
print(f" 设备ID: {alarm.get('physicalUid')}")
print(f" 标题: {alarm.get('title')}")
print(f" 级别: {alarm.get('level')}")
print(f" 温度: {alarm.get('temp')}°C")
print(f" 消息: {alarm.get('message')}")
print(f" 发生时间: {datetime.fromtimestamp(alarm.get('occurredAtMs', 0)/1000)}")
print(f" 接收时间: {alarm.get('received_at')}")
last_count = current_count
time.sleep(2) # 每2秒检查一次
def main():
"""主函数"""
print("🧪 ESP32云端报警上报功能验证")
print("=" * 50)
print(f"测试时间: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}")
print("=" * 50)
# 启动模拟云端服务器(在后台线程中)
server_thread = threading.Thread(target=start_mock_cloud_server, daemon=True)
server_thread.start()
# 等待服务器启动
time.sleep(2)
# 显示触发指导
trigger_esp32_alarm()
# 开始监控报警
try:
monitor_received_alarms()
except KeyboardInterrupt:
print(f"\n\n🎯 测试结果总结:")
print("=" * 30)
print(f"总共接收到报警: {len(CloudAlarmHandler.received_alarms)}")
if CloudAlarmHandler.received_alarms:
print("✅ ESP32云端报警上报功能正常!")
print("\n📋 接收到的报警列表:")
for i, alarm in enumerate(CloudAlarmHandler.received_alarms):
print(f"{i+1}. {alarm.get('title')} - {alarm.get('level')} - {alarm.get('temp')}°C")
else:
print("⚠️ 未接收到任何报警")
print("可能的原因:")
print("1. ESP32未连接到网络")
print("2. CloudAlarmReporter模块未正确初始化")
print("3. 报警未被触发")
print("4. 网络配置问题")
print(f"\n💡 如果测试成功说明ESP32能够正确上报报警到云端!")
if __name__ == "__main__":
main()