#!/usr/bin/env python3
import json
import socket
import threading
import time
import traceback
from datetime import datetime
import argparse
from flask import Flask, render_template_string, jsonify, render_template
class CommaWebListener:
def __init__(self, port=8088):
"""初始化接收器"""
self.port = port
self.data = {}
self.last_update = 0
self.running = True
self.device_ip = None
def start_listening(self):
"""启动UDP监听"""
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
try:
sock.bind(('0.0.0.0', self.port))
print(f"正在监听端口 {self.port} 的广播数据...")
while self.running:
try:
data, addr = sock.recvfrom(4096)
self.device_ip = addr[0]
try:
self.data = json.loads(data.decode('utf-8'))
self.last_update = time.time()
except json.JSONDecodeError:
print(f"接收到无效的JSON数据: {data[:100]}...")
except Exception as e:
print(f"接收数据时出错: {e}")
except Exception as e:
print(f"无法绑定到端口 {self.port}: {e}")
finally:
sock.close()
# HTML模板
HTML_TEMPLATE = """
CommaAssist 数据监视器
"""
def create_app(listener):
app = Flask(__name__)
@app.route('/')
def index():
"""主页"""
return render_template_string(HTML_TEMPLATE)
@app.route('/api/data')
def get_data():
"""提供JSON数据API"""
return jsonify({
'data': listener.data,
'last_update': listener.last_update,
'device_ip': listener.device_ip
})
return app
def main():
"""主函数"""
parser = argparse.ArgumentParser(description='CommaAssist Web监视器')
parser.add_argument('-p', '--port', type=int, default=8088, help='监听comma设备的UDP端口(默认: 8088)')
parser.add_argument('-w', '--web-port', type=int, default=5000, help='Web服务器端口(默认: 5000)')
parser.add_argument('--host', default='0.0.0.0', help='Web服务器监听地址(默认: 0.0.0.0)')
args = parser.parse_args()
# 创建监听器
listener = CommaWebListener(port=args.port)
# 启动接收线程
receiver_thread = threading.Thread(target=listener.start_listening)
receiver_thread.daemon = True
receiver_thread.start()
# 创建Flask应用
app = create_app(listener)
# 启动Web服务器
try:
print(f"Web服务已启动,请访问 http://{args.host}:{args.web_port}/")
app.run(host=args.host, port=args.web_port)
except KeyboardInterrupt:
print("\n退出...")
finally:
listener.running = False
receiver_thread.join(timeout=1.0)
if __name__ == "__main__":
main()