99import websockets
1010from websockets .asyncio .client import connect as ws_connect
1111
12- from dglabv3 .dtype import (Button , Channel , ChannelStrength , MessageType ,
13- Strength , StrengthMode , StrengthType )
12+ from dglabv3 .dtype import Button , Channel , ChannelStrength , MessageType , Strength , StrengthMode , StrengthType
1413from dglabv3 .event import EventEmitter
1514from dglabv3 .music_to_wave import convert_audio_to_v3_protocol
1615from dglabv3 .wsmessage import WSMessage , WStype
@@ -41,37 +40,56 @@ def __init__(self) -> None:
4140 self .bot = None
4241
4342 async def _dispatch_button (self , button : Button ) -> None :
43+ """
44+ 按鈕事件
45+
46+ :param button: 按鈕物件
47+ """
4448 self .emit ("button" , button )
4549 if self .bot :
4650 await self .bot .dispatch ("dglab_button" , button )
4751
4852 async def _dispatch_strength (self , strength : Strength ) -> None :
53+ """
54+ 強度事件
55+
56+ :param strength: 強度物件
57+ """
4958 logger .debug (f"Dispatch strength: { strength } " )
5059 self .emit ("strength" , strength )
5160 if self .bot :
5261 await self .bot .dispatch ("dglab_strength" , strength )
5362
5463 def set_bot (self , bot ):
5564 """
56- 設置discord bot
65+ 設置Discord Bot
66+
67+ :param bot: Discord Bot
5768 """
5869 self .bot = bot
5970
6071 def is_connected (self ) -> bool :
6172 """
62- 是否連接到WebSocket
73+ 檢查是否已連接到WebSocket伺服器
74+
75+ :return: 連接狀態
6376 """
6477 return self .client is not None
6578
6679 def is_linked_to_app (self ) -> bool :
6780 """
68- 是否連接到app
81+ 檢查是否已連接到App
82+
83+ :return: App連接狀態
6984 """
7085 return self .client_id is not None
7186
7287 async def connect_and_wait (self , timeout : int = 30 ) -> None :
7388 """
74- 連接並等待bind完成
89+ 連接WebSocket並等待綁定完成
90+
91+ :param timeout: 超時時間(秒)
92+ :raises TimeoutError: 當綁定超時
7593 """
7694 await self .connect ()
7795 try :
@@ -86,7 +104,10 @@ async def connect_and_wait(self, timeout: int = 30) -> None:
86104
87105 async def wait_for_app_connect (self , timeout : int = 30 ) -> None :
88106 """
89- 等待app連結
107+ 等待App連接
108+
109+ :param timeout: 超時時間(秒)
110+ :raises TimeoutError: 當App連接超時
90111 """
91112 try :
92113 await asyncio .wait_for (
@@ -100,7 +121,9 @@ async def wait_for_app_connect(self, timeout: int = 30) -> None:
100121
101122 async def connect (self ) -> None :
102123 """
103- 連接WebSocket
124+ 連接到WebSocket伺服器
125+
126+ :raises ConnectionError: 當連接失敗時
104127 """
105128 try :
106129 self .client = await ws_connect (self .clienturl )
@@ -112,6 +135,9 @@ async def connect(self) -> None:
112135 raise ConnectionError ("WebSocket connection error" )
113136
114137 async def _listen (self ):
138+ """
139+ 監聽WebSocket訊息
140+ """
115141 try :
116142 if self .client is None :
117143 logger .error ("WebSocket client is None" )
@@ -127,6 +153,8 @@ async def _listen(self):
127153 def generate_qrcode (self ) -> Optional [io .BytesIO ]:
128154 """
129155 生成QR code圖片
156+
157+ :return: QR code圖片的BytesIO物件,如果client_id為空則返回None
130158 """
131159 if self .client_id is None :
132160 logger .error ("Client ID is empty, please connect to the server first" )
@@ -143,6 +171,8 @@ def generate_qrcode(self) -> Optional[io.BytesIO]:
143171 def generate_qrcode_text (self ) -> Optional [str ]:
144172 """
145173 生成QR code文字
174+
175+ :return: ASCII格式的QR code文字,如果client_id為空則返回None
146176 """
147177 if self .client_id is None :
148178 logger .error ("Client ID is empty, please connect to the server first" )
@@ -154,13 +184,21 @@ def generate_qrcode_text(self) -> Optional[str]:
154184 return f .getvalue ()
155185
156186 async def _update_connects (self , message : WSMessage ):
187+ """
188+ 更新連接狀態並同步強度設定
189+
190+ :param message: WebSocket訊息物件
191+ """
157192 if message .targetID :
158193 self .target_id = message .targetID
159194 await self .set_strength (Channel .A , StrengthType .SPECIFIC , self .strength .A )
160195 await self .set_strength (Channel .B , StrengthType .SPECIFIC , self .strength .B )
161196 self ._app_connect_event .set ()
162197
163198 async def _heartbeat (self ):
199+ """
200+ 心跳檢測任務,維持連接並檢測App連接狀態
201+ """
164202 try :
165203 while not self ._closing :
166204 await self ._send_message (
@@ -185,12 +223,19 @@ async def _heartbeat(self):
185223 logger .error (f"Heartbeat error: { e } " )
186224
187225 def _start_heartbeat (self ):
188- """啟動心跳檢測"""
226+ """
227+ 啟動心跳檢測任務
228+ """
189229 if self ._heartbeat_task :
190230 self ._heartbeat_task .cancel ()
191231 self ._heartbeat_task = asyncio .create_task (self ._heartbeat ())
192232
193233 async def _handle_message (self , data : websockets .Data ):
234+ """
235+ 處理接收到的WebSocket訊息
236+
237+ :param data: WebSocket訊息資料
238+ """
194239 try :
195240 message = json .loads (data )
196241 WSmsg = WSMessage (message )
@@ -219,6 +264,12 @@ async def _handle_message(self, data: websockets.Data):
219264 logger .debug (f"Received raw message: { data } " )
220265
221266 async def _send_message (self , message : dict , update : bool = True ) -> None :
267+ """
268+ 發送WebSocket訊息
269+
270+ :param message: 要發送的訊息字典
271+ :param update: 是否自動添加clientId和targetId
272+ """
222273 try :
223274 if self .client :
224275 if update :
@@ -234,7 +285,7 @@ async def _send_message(self, message: dict, update: bool = True) -> None:
234285
235286 async def close (self ):
236287 """
237- 斷開連結
288+ 關閉WebSocket連接並清理資源
238289 """
239290 self ._closing = True
240291 try :
@@ -256,21 +307,40 @@ async def close(self):
256307
257308 @staticmethod
258309 def _wave2hex (data ):
310+ """
311+ 將波形資料轉換為16進制字串
312+
313+ :param data: 波形資料
314+ :return: 16進制字串列表
315+ """
259316 return ["" .join (format (num , "02X" ) for num in sum (item , [])) for item in data ]
260317
261318 async def music_2_wave (self , mp3_file_path : str , channel : Channel = Channel .BOTH ):
262319 """
263- 將音樂轉換為波形
320+ 將音樂檔案轉換為波形並發送
321+
322+ :param mp3_file_path: 音樂檔案路徑
323+ :param channel: 目標通道,預設為雙通道
324+
325+ Example:
326+
327+ >>> await client.music_2_wave("music.mp3", Channel.A)
264328 """
265329 data = convert_audio_to_v3_protocol (mp3_file_path )
266330 await self .send_wave_message (data , channel = channel )
267331
268332 async def send_wave_message (self , wave : list [list [list [int ]]], time : int = 10 , channel : Channel = Channel .BOTH ):
269333 """
270334 發送波形\n
271- wave: Pulse().breath\n
272- time: 30\n
273- channel: Channel.A
335+
336+ :param wave: 波形數據
337+ :param time: 波形持續時間(秒)
338+ :param channel: Channel.A or Channel.B or Channel.BOTH
339+
340+ Example:
341+
342+ >>> await client.send_wave_message(PULSES["呼吸"], 30, Channel.A)
343+
274344 """
275345 channel_str = ""
276346 if channel == Channel .A :
@@ -304,6 +374,15 @@ def _create_wave_message(ch_str: str, wave: list[list[list[int]]], time: int) ->
304374 await self ._send_message (message )
305375
306376 async def clear_wave (self , channel : Channel ):
377+ """
378+ 清除指定通道的波形
379+
380+ :param channel: 要清除的通道
381+
382+ Example:
383+
384+ >>> await client.clear_wave(Channel.A)
385+ """
307386 if channel == Channel .A :
308387 await self ._send_message (
309388 {
@@ -335,6 +414,15 @@ async def clear_wave(self, channel: Channel):
335414 logger .error (f"Invalid channel: { channel } " )
336415
337416 async def clear_all_wave (self ):
417+ """
418+ 清除所有通道的波形
419+
420+ :return: 操作成功返回True
421+
422+ Example:
423+
424+ >>> await client.clear_all_wave()
425+ """
338426 # type : msg 固定不变
339427 # message: clear-1 -> 清除A通道波形队列; clear-2 -> 清除B通道波形队列
340428 await self ._send_message (
@@ -354,13 +442,27 @@ async def clear_all_wave(self):
354442
355443 async def set_strength_value (self , channel : Channel , strength : int ) -> None :
356444 """
357- 设置通道强度
445+ 設定通道強度值
446+
447+ :param channel: 目標通道
448+ :param strength: 強度值[0-200]
449+
450+ Example:
451+
452+ >>> await client.set_strength_value(Channel.A, 50)
358453 """
359454 await self .set_strength (channel , StrengthType .SPECIFIC , strength )
360455
361456 async def add_strength_value (self , channel : Channel , strength : int ) -> None :
362457 """
363458 增加通道強度
459+
460+ :param channel: 目標通道
461+ :param strength: 要增加的強度值
462+
463+ Example:
464+
465+ >>> await client.add_strength_value(Channel.A, 10)
364466 """
365467 if channel == Channel .BOTH :
366468 await self .add_strength_value (Channel .A , strength )
@@ -372,6 +474,13 @@ async def add_strength_value(self, channel: Channel, strength: int) -> None:
372474 async def decrease_strength_value (self , channel : Channel , strength : int ) -> None :
373475 """
374476 減少通道強度
477+
478+ :param channel: 目標通道
479+ :param strength: 要減少的強度值
480+
481+ Example:
482+
483+ >>> await client.decrease_strength_value(Channel.A, 5)
375484 """
376485 if channel == Channel .BOTH :
377486 await self .decrease_strength_value (Channel .A , strength )
@@ -382,15 +491,27 @@ async def decrease_strength_value(self, channel: Channel, strength: int) -> None
382491
383492 async def reset_strength_value (self , channel : Channel ) -> None :
384493 """
385- 通道強度重置為0
494+ 重置通道強度為0
495+
496+ :param channel: 目標通道
497+
498+ Example:
499+
500+ >>> await client.reset_strength_value(Channel.A)
386501 """
387502 await self .set_strength (channel , StrengthType .ZERO , 0 )
388503
389504 async def set_strength (self , channel : Channel , type_id : StrengthType , strength : int ) -> None :
390505 """
391- channel: 通道
392- type_id: StrengthType
393- strength: 強度值[0-200]
506+ 設定通道強度
507+
508+ :param channel: 目標通道
509+ :param type_id: 強度類型
510+ :param strength: 強度值[0-200]
511+
512+ Example:
513+
514+ >>> await client.set_strength(Channel.A, StrengthType.SPECIFIC, 80)
394515 """
395516 # type : 1 -> 通道强度减少; 2 -> 通道强度增加; 3 -> 通道强度归零 ;4 -> 通道强度指定为某个值
396517 # strength: 强度值变化量/指定强度值(当type为1或2时,该值会被强制设置为1)
@@ -472,6 +593,13 @@ async def set_strength(self, channel: Channel, type_id: StrengthType, strength:
472593 def get_strength_value (self , channel : Channel ) -> int :
473594 """
474595 獲取通道強度
596+
597+ :param channel: 目標通道
598+ :return: 強度值
599+
600+ Example:
601+
602+ >>> strength = client.get_strength_value(Channel.A)
475603 """
476604 match channel :
477605 case Channel .A :
@@ -484,6 +612,13 @@ def get_strength_value(self, channel: Channel) -> int:
484612 def get_max_strength_value (self , channel : Channel ) -> int :
485613 """
486614 獲取通道最大強度
615+
616+ :param channel: 目標通道
617+ :return: 最大強度值
618+
619+ Example:
620+
621+ >>> max_strength = client.get_max_strength_value(Channel.A)
487622 """
488623 match channel :
489624 case Channel .A :
0 commit comments