137 lines
5.5 KiB
Python
137 lines
5.5 KiB
Python
#!/usr/bin/env python3
|
||
# -*- coding: utf-8 -*-
|
||
"""
|
||
TCP接收程序 - 替换UDP接收,用于测试ESP32的TCP发送功能
|
||
完全保留原有数据解析逻辑,仅替换传输层接口
|
||
"""
|
||
|
||
import socket
|
||
import json
|
||
import time
|
||
from datetime import datetime
|
||
|
||
def log_message(message):
|
||
"""打印带时间戳的日志"""
|
||
timestamp = datetime.now().strftime("%H:%M:%S.%f")[:-3]
|
||
print(f"[{timestamp}] {message}")
|
||
|
||
def start_tcp_server():
|
||
"""启动TCP服务器,接收ESP32发送的数据"""
|
||
# 配置(和ESP32端一致)
|
||
TCP_HOST = '0.0.0.0' # 监听所有网卡
|
||
TCP_PORT = 8888
|
||
BUFFER_SIZE = 1024
|
||
|
||
# 创建TCP服务器套接字
|
||
tcp_server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||
tcp_server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) # 允许端口重用
|
||
|
||
try:
|
||
tcp_server.bind((TCP_HOST, TCP_PORT))
|
||
tcp_server.listen(5) # 监听最多5个连接
|
||
log_message(f"✅ TCP接收服务器已启动,监听端口 {TCP_PORT}")
|
||
log_message(f"📡 等待ESP32连接...")
|
||
|
||
while True:
|
||
try:
|
||
# 等待ESP32客户端连接
|
||
client_conn, client_addr = tcp_server.accept()
|
||
log_message(f"🔗 来自 {client_addr} 的连接已建立")
|
||
|
||
# 处理客户端连接
|
||
handle_client(client_conn, client_addr)
|
||
|
||
except KeyboardInterrupt:
|
||
log_message("⏹️ 收到中断信号,正在关闭服务器...")
|
||
break
|
||
except Exception as e:
|
||
log_message(f"⚠️ 接受连接时发生异常:{e}")
|
||
time.sleep(1)
|
||
|
||
except Exception as e:
|
||
log_message(f"❌ 启动TCP服务器失败:{e}")
|
||
finally:
|
||
tcp_server.close()
|
||
log_message("🔌 TCP服务器已关闭")
|
||
|
||
def handle_client(client_conn, client_addr):
|
||
"""处理单个客户端连接"""
|
||
log_message(f"📡 开始处理来自 {client_addr} 的数据...")
|
||
|
||
try:
|
||
while True:
|
||
# 接收数据
|
||
data = client_conn.recv(1024)
|
||
if not data:
|
||
log_message(f"❌ 客户端 {client_addr} 连接已断开")
|
||
break
|
||
|
||
# 解析数据(复用原有UDP的解析逻辑,无需修改)
|
||
try:
|
||
# 尝试解析为JSON(热成像状态数据)
|
||
json_str = data.decode('utf-8')
|
||
json_data = json.loads(json_str)
|
||
|
||
# 提取设备ID
|
||
device_id = json_data.get('device_id', '未知设备')
|
||
|
||
# 提取PIR和Radar状态
|
||
pir_status = "有人" if json_data.get('pir', 0) == 1 else "无人"
|
||
radar_status = "有人" if json_data.get('radar', 0) == 1 else "无人"
|
||
|
||
# 提取温度数据(16宫格)
|
||
grid_temps = json_data.get('grid', [])
|
||
if len(grid_temps) >= 16:
|
||
avg_temp = sum(grid_temps) / len(grid_temps)
|
||
log_message(f"📊 [{device_id}] 热成像数据: PIR={pir_status}, Radar={radar_status}, 平均温度={avg_temp:.1f}°C")
|
||
log_message(f"🌡️ [{device_id}] 16宫格温度: {[f'{t:.1f}' for t in grid_temps[:4]]}")
|
||
else:
|
||
log_message(f"📊 [{device_id}] 传感器状态: PIR={pir_status}, Radar={radar_status}")
|
||
|
||
except json.JSONDecodeError:
|
||
# 不是JSON数据,可能是二进制热成像数据或AI检测结果
|
||
if len(data) == 513: # 热成像分包数据
|
||
packet_num = data[0]
|
||
log_message(f"🖼️ 热成像数据包 #{packet_num}: {len(data)}字节")
|
||
elif len(data) == 17: # AI检测结果数据
|
||
packet_num = data[0]
|
||
score = data[1]
|
||
x, y, w, h = data[2], data[3], data[4], data[5]
|
||
cx, cy = data[6], data[7]
|
||
heater_on = bool(data[8])
|
||
heater_burst = bool(data[9])
|
||
danger_temp = bool(data[10])
|
||
burning = bool(data[11])
|
||
|
||
log_message(f"🤖 AI检测结果 #{packet_num}: 人员({score}%@{x},{y},{w}x{h}), 热源({cx},{cy})")
|
||
log_message(f"🔥 火灾状态: 加热器={heater_on}, 异常升温={heater_burst}, 危险温度={danger_temp}, 燃烧={burning}")
|
||
else:
|
||
log_message(f"📦 未知数据格式: {len(data)}字节 - {data.hex()[:32]}...")
|
||
|
||
except Exception as parse_error:
|
||
log_message(f"⚠️ 数据解析异常: {parse_error}")
|
||
log_message(f"📦 原始数据: {data.hex()[:64]}...")
|
||
|
||
except Exception as e:
|
||
log_message(f"❌ 处理客户端 {client_addr} 时发生异常:{e}")
|
||
finally:
|
||
client_conn.close()
|
||
log_message(f"🔌 与 {client_addr} 的连接已关闭")
|
||
|
||
def main():
|
||
"""主函数"""
|
||
print("=" * 70)
|
||
print("🔬 TCP接收程序 - 替换UDP接收,测试ESP32 TCP发送功能")
|
||
print("📡 完全保留原有数据解析逻辑,仅替换传输层接口")
|
||
print("=" * 70)
|
||
|
||
try:
|
||
start_tcp_server()
|
||
except KeyboardInterrupt:
|
||
log_message("⏹️ 程序被用户中断")
|
||
except Exception as e:
|
||
log_message(f"💥 程序异常: {str(e)}")
|
||
|
||
if __name__ == "__main__":
|
||
main()
|