1515from floating_window import FloatingWindow
1616from vrc_osc import VrcOscClient
1717from api_server import ApiServer
18+ from websocket_server import WebSocketServer # [新增] 导入WebSocket服务器
1819from webhook_manager import WebhookManager
1920from webhook_ui import WebhookWindow
2021
@@ -30,6 +31,7 @@ def __init__(self):
3031 self .should_stop = False
3132
3233 self .api_server = None
34+ self .websocket_server = None # [新增] WebSocket服务器实例
3335
3436 self .floating_window = FloatingWindow (self )
3537
@@ -56,6 +58,10 @@ def setup_ui(self):
5658 self .root .minsize (800 , 500 )
5759 self .root .resizable (True , True )
5860
61+ # [新增] WebSocket UI变量
62+ self .websocket_server_enabled = tk .BooleanVar (value = False )
63+ self .websocket_port_var = tk .StringVar (value = "8001" )
64+
5965 self .api_server_enabled = tk .BooleanVar (value = False )
6066 self .api_port_var = tk .StringVar (value = "8000" )
6167 self .vrc_ip_var = tk .StringVar (value = "127.0.0.1" )
@@ -120,6 +126,17 @@ def setup_ui(self):
120126 self .vrc_status_label = ttk .Label (vrc_frame , text = "状态: 未连接" , font = ("Arial" , 10 ), foreground = "gray" )
121127 self .vrc_status_label .grid (row = 3 , column = 0 , columnspan = 2 , sticky = "w" , pady = (5 ,0 ))
122128
129+ # [新增] WebSocket 服务器 UI
130+ websocket_frame = ttk .LabelFrame (middle_column_frame , text = "WebSocket服务器 (实时推送)" , padding = "10" )
131+ websocket_frame .pack (fill = "x" , pady = PAD_Y )
132+ websocket_frame .columnconfigure (1 , weight = 1 )
133+ self .websocket_server_enabled .trace_add ("write" , self .toggle_websocket_server )
134+ ttk .Checkbutton (websocket_frame , text = "启用WebSocket服务器" , variable = self .websocket_server_enabled ).grid (row = 0 , column = 0 , sticky = tk .W , columnspan = 2 )
135+ ttk .Label (websocket_frame , text = "端口:" ).grid (row = 1 , column = 0 , sticky = tk .W , pady = (5 ,0 ))
136+ ttk .Entry (websocket_frame , textvariable = self .websocket_port_var , width = 10 ).grid (row = 1 , column = 1 , sticky = "ew" , padx = 5 , pady = (5 ,0 ))
137+ self .websocket_status_label = ttk .Label (websocket_frame , text = "状态: 已禁用" , font = ("Arial" , 10 ), foreground = "gray" )
138+ self .websocket_status_label .grid (row = 2 , column = 0 , columnspan = 2 , sticky = "w" , pady = (5 ,0 ))
139+
123140 api_frame = ttk .LabelFrame (middle_column_frame , text = "心率API服务器 (被动获取)" , padding = "10" )
124141 api_frame .pack (fill = "x" , pady = PAD_Y )
125142 api_frame .columnconfigure (1 , weight = 1 )
@@ -249,9 +266,12 @@ def update_heart_rate_display(self):
249266 self .heart_rate_label .config (text = f"心率: { heart_rate } " )
250267
251268 if heart_rate > 0 :
252- # [修改] 使用新的事件触发方法
253269 self .webhook_manager .trigger_event ("heart_rate_updated" , heart_rate )
254270
271+ # [修改] 增加WebSocket广播
272+ if self .websocket_server :
273+ self .websocket_server .broadcast ()
274+
255275 if heart_rate > 0 :
256276 self .heart_rate_label .config (fg = "green" )
257277 if self .vrc_connected :
@@ -267,6 +287,29 @@ def update_heart_rate_display(self):
267287 def clear_logs (self ):
268288 self .log_text .delete (1.0 , tk .END )
269289
290+ # [新增] 启动/停止 WebSocket 服务器
291+ def toggle_websocket_server (self , * args ):
292+ if self .websocket_server_enabled .get ():
293+ try :
294+ port = int (self .websocket_port_var .get ())
295+ self .websocket_server = WebSocketServer (self , port , self .log_message )
296+ self .websocket_server .start ()
297+ self .websocket_status_label .config (text = f"状态: 运行于 ws://127.0.0.1:{ port } " , foreground = "green" )
298+ except ValueError :
299+ self .log_message ("WebSocket服务器启动失败:端口号必须是有效的数字。" )
300+ self .websocket_status_label .config (text = "状态: 端口号无效" , foreground = "red" )
301+ self .websocket_server_enabled .set (False )
302+ except Exception as e :
303+ self .log_message (f"WebSocket服务器启动失败: { e } " )
304+ self .websocket_status_label .config (text = f"状态: 启动失败" , foreground = "red" )
305+ self .websocket_server_enabled .set (False )
306+
307+ else :
308+ if self .websocket_server :
309+ self .websocket_server .stop ()
310+ self .websocket_server = None
311+ self .websocket_status_label .config (text = "状态: 已禁用" , foreground = "gray" )
312+
270313 def toggle_api_server (self , * args ):
271314 if self .api_server_enabled .get ():
272315 try :
@@ -313,6 +356,11 @@ def save_settings(self):
313356 "api_server" : {
314357 "enabled" : self .api_server_enabled .get (),
315358 "port" : self .api_port_var .get ()
359+ },
360+ # [新增] 保存 WebSocket 设置
361+ "websocket_server" : {
362+ "enabled" : self .websocket_server_enabled .get (),
363+ "port" : self .websocket_port_var .get ()
316364 }
317365 }
318366 save_config (config )
@@ -367,10 +415,19 @@ def load_settings(self):
367415
368416 api_settings = config .get ("api_server" )
369417 if api_settings :
370- self .api_port_var .set (api_settings .get ("port" , "8080 " ))
418+ self .api_port_var .set (api_settings .get ("port" , "8000 " ))
371419 if api_settings .get ("enabled" , False ):
372420 self .root .after (100 , lambda : self .api_server_enabled .set (True ))
373421 self .log_message ("已加载 API 服务器设置" )
422+
423+ # [新增] 加载 WebSocket 设置
424+ websocket_settings = config .get ("websocket_server" )
425+ if websocket_settings :
426+ self .websocket_port_var .set (websocket_settings .get ("port" , "8001" ))
427+ if websocket_settings .get ("enabled" , False ):
428+ # 延迟执行,确保UI完全加载
429+ self .root .after (200 , lambda : self .websocket_server_enabled .set (True ))
430+ self .log_message ("已加载 WebSocket 服务器设置" )
374431
375432 def toggle_vrc_connection (self ):
376433 if self .vrc_connected :
@@ -433,8 +490,11 @@ def on_closing(self):
433490 self .disconnect_device ()
434491 if self .vrc_connected :
435492 self .vrc_osc_client .disconnect ()
436- if self .api_server and self .api_server .httpd :
493+ # [修改] 增加停止服务器的逻辑
494+ if self .api_server :
437495 self .api_server .stop ()
496+ if self .websocket_server :
497+ self .websocket_server .stop ()
438498 if self .floating_window .is_open ():
439499 self .floating_window .close_window ()
440500 self .root .destroy ()
@@ -588,13 +648,14 @@ def _on_connect(self):
588648 self .connected = True
589649 self .status_label .config (text = "状态: 已连接" , fg = "green" )
590650 self .log_message ("设备连接成功,开始监控心率" )
591- # [修改] 触发 "connected" 事件
592651 self .webhook_manager .trigger_event ("connected" , self .heart_rate )
652+ # [新增] 连接时广播状态
653+ if self .websocket_server :
654+ self .websocket_server .broadcast ()
593655
594656
595657 def _on_disconnect (self ):
596- # [修改] 先触发事件,再更新状态
597- if self .connected : # 只有在之前是连接状态时才触发
658+ if self .connected :
598659 self .webhook_manager .trigger_event ("disconnected" , self .heart_rate )
599660
600661 self .connected = False
@@ -605,13 +666,13 @@ def _on_disconnect(self):
605666 self .heart_rate_label .config (text = "心率: --" , fg = "red" )
606667 self .heart_rate_queue .put (0 )
607668 self .log_message ("设备已断开连接" )
669+ # [新增] 断开时广播状态
670+ if self .websocket_server :
671+ self .websocket_server .broadcast ()
608672
609673 def disconnect_device (self ):
610674 self .should_stop = True
611675 if self .ble_loop and not self .ble_loop .is_closed () and self .ble_loop .is_running ():
612- # 停止事件循环可能会导致正在运行的异步任务突然中断,
613- # 这里改为在循环内通过 should_stop 标志来优雅退出
614- # self.ble_loop.call_soon_threadsafe(self.ble_loop.stop)
615676 pass
616677 self ._on_disconnect ()
617678 self .log_message ("手动断开连接" )
0 commit comments