smartpi 0.1.41__py3-none-any.whl → 0.1.43__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- smartpi/__init__.py +1 -1
- smartpi/ai_asr.py +18 -17
- smartpi/ai_vad.py +13 -129
- smartpi/base_driver.py +15 -265
- smartpi/onnx_pose_workflow.py +1 -1
- smartpi/rknn_pose_workflow.py +1 -1
- {smartpi-0.1.41.dist-info → smartpi-0.1.43.dist-info}/METADATA +1 -1
- {smartpi-0.1.41.dist-info → smartpi-0.1.43.dist-info}/RECORD +10 -10
- {smartpi-0.1.41.dist-info → smartpi-0.1.43.dist-info}/WHEEL +0 -0
- {smartpi-0.1.41.dist-info → smartpi-0.1.43.dist-info}/top_level.txt +0 -0
smartpi/__init__.py
CHANGED
|
@@ -4,5 +4,5 @@ from .base_driver import P1, P2, P3, P4, P5, P6, M1, M2, M3, M4, M5, M6
|
|
|
4
4
|
__all__ = ["base_driver","gui","ultrasonic","touch_sensor","temperature","humidity","light_sensor","color_sensor","motor","servo","led","flash",
|
|
5
5
|
"P1", "P2", "P3", "P4", "P5", "P6", "M1", "M2", "M3", "M4", "M5", "M6"]
|
|
6
6
|
|
|
7
|
-
__version__ = "0.1.
|
|
7
|
+
__version__ = "0.1.43"
|
|
8
8
|
|
smartpi/ai_asr.py
CHANGED
|
@@ -798,7 +798,7 @@ def init(appid: str, secret_id: str, secret_key: str, voice_format: int = 8, sam
|
|
|
798
798
|
hotword_id: str = "", result_type: int = 0, slice_size: int = 960,
|
|
799
799
|
vad_silence_timeout: int = 10000, vad_pause_timeout: int = 3000,
|
|
800
800
|
vad_mini_volume: int = 1000, vad_mini_length: int = 500, debug: bool = False,
|
|
801
|
-
|
|
801
|
+
vad_threshold: float = 0.7,
|
|
802
802
|
sentence_callback=None, engine_model_type: str = "16k_zh",
|
|
803
803
|
interruption_callback=None) -> bool:
|
|
804
804
|
"""初始化语音识别
|
|
@@ -817,7 +817,6 @@ def init(appid: str, secret_id: str, secret_key: str, voice_format: int = 8, sam
|
|
|
817
817
|
vad_mini_volume (int): 最小音量阈值,默认1000
|
|
818
818
|
vad_mini_length (int): 最小语音长度(毫秒),默认500
|
|
819
819
|
debug (bool): 是否开启调试模式,默认False
|
|
820
|
-
vad_type (str): VAD类型,默认"energy"(目前只支持energy silero不稳定慎用!)
|
|
821
820
|
vad_threshold (float): VAD阈值,默认0.7
|
|
822
821
|
sentence_callback (callable): 句子识别完成回调函数
|
|
823
822
|
engine_model_type (str): 引擎模型类型,默认"16k_zh"
|
|
@@ -839,28 +838,30 @@ def init(appid: str, secret_id: str, secret_key: str, voice_format: int = 8, sam
|
|
|
839
838
|
except ImportError:
|
|
840
839
|
print("警告: ai_vad模块未找到")
|
|
841
840
|
ai_vad = None
|
|
842
|
-
|
|
841
|
+
|
|
843
842
|
if ai_vad is not None:
|
|
844
843
|
try:
|
|
845
844
|
vad = ai_vad.VADProviderBase.create_vad_instance(
|
|
846
|
-
|
|
845
|
+
vad_mini_volume, vad_mini_length,
|
|
846
|
+
vad_pause_timeout, vad_silence_timeout,
|
|
847
|
+
vad_threshold
|
|
847
848
|
)
|
|
848
|
-
print(
|
|
849
|
+
print("VAD初始化成功,使用EnergyVADProvider")
|
|
849
850
|
except Exception as e:
|
|
850
851
|
print(f"VAD实例创建失败: {e}")
|
|
851
852
|
vad = None
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
853
|
+
|
|
854
|
+
_ai_asr_instance = TencentSpeechRecognizer(
|
|
855
|
+
appid=appid,
|
|
856
|
+
secret_id=secret_id,
|
|
857
|
+
secret_key=secret_key,
|
|
858
|
+
engine_model_type=engine_model_type,
|
|
859
|
+
sentence_callback=sentence_callback,
|
|
860
|
+
vad=vad,
|
|
861
|
+
interruption_callback=interruption_callback
|
|
862
|
+
)
|
|
863
|
+
print("语音识别初始化成功")
|
|
864
|
+
return True
|
|
864
865
|
except Exception as e:
|
|
865
866
|
print(f"语音识别初始化失败: {e}")
|
|
866
867
|
import traceback
|
smartpi/ai_vad.py
CHANGED
|
@@ -3,143 +3,27 @@ import sys
|
|
|
3
3
|
import os
|
|
4
4
|
import time
|
|
5
5
|
import numpy as np
|
|
6
|
-
import torch
|
|
7
|
-
|
|
8
|
-
# 设置环境变量以优化性能
|
|
9
|
-
os.environ['OMP_NUM_THREADS'] = '1'
|
|
10
|
-
os.environ['KMP_AFFINITY'] = 'disabled'
|
|
11
6
|
|
|
12
7
|
class VADProviderBase:
|
|
13
8
|
"""VAD provider base class"""
|
|
14
9
|
@staticmethod
|
|
15
10
|
def create_vad_instance(
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
11
|
+
vad_mini_volume=1000,
|
|
12
|
+
vad_mini_length=500,
|
|
13
|
+
vad_pause_timeout=3000,
|
|
14
|
+
vad_silence_timeout=10000,
|
|
15
|
+
threshold=0.02
|
|
21
16
|
):
|
|
22
|
-
"""Factory method to create VAD instance"""
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
)
|
|
30
|
-
except Exception as e:
|
|
31
|
-
print(f"Failed to create SileroVAD instance: {e}")
|
|
32
|
-
print("Falling back to EnergyVADProvider...")
|
|
33
|
-
return EnergyVADProvider(
|
|
34
|
-
threshold=energy_threshold,
|
|
35
|
-
min_silence_duration_ms=min_silence_duration_ms
|
|
36
|
-
)
|
|
37
|
-
elif class_name == "energy":
|
|
38
|
-
return EnergyVADProvider(
|
|
39
|
-
threshold=energy_threshold,
|
|
40
|
-
min_silence_duration_ms=min_silence_duration_ms
|
|
41
|
-
)
|
|
42
|
-
raise ValueError(f"Unsupported VAD type: {class_name}")
|
|
43
|
-
|
|
44
|
-
class SileroVADProvider(VADProviderBase):
|
|
45
|
-
"""Silero VAD provider"""
|
|
46
|
-
def __init__(self, model_dir=None, threshold=0.5, min_silence_duration_ms=800):
|
|
47
|
-
# 获取模型目录,默认为当前文件所在目录下的models/snakers4_silero-vad
|
|
48
|
-
if not model_dir:
|
|
49
|
-
model_dir = os.path.join(os.path.dirname(os.path.abspath(__file__)), "models/snakers4_silero-vad")
|
|
50
|
-
|
|
51
|
-
print(f"Initializing SileroVAD: model_dir={model_dir}, threshold={threshold}, min_silence_duration_ms={min_silence_duration_ms}")
|
|
52
|
-
|
|
53
|
-
# 加载模型
|
|
54
|
-
try:
|
|
55
|
-
# 尝试检查torchaudio是否安装
|
|
56
|
-
import importlib.util
|
|
57
|
-
torchaudio_available = importlib.util.find_spec('torchaudio') is not None
|
|
58
|
-
|
|
59
|
-
if torchaudio_available:
|
|
60
|
-
# 如果有torchaudio,使用默认的PyTorch模型
|
|
61
|
-
self.model, self.utils = torch.hub.load(
|
|
62
|
-
repo_or_dir=model_dir,
|
|
63
|
-
source="local",
|
|
64
|
-
model="silero_vad",
|
|
65
|
-
force_reload=False,
|
|
66
|
-
)
|
|
67
|
-
else:
|
|
68
|
-
# 如果没有torchaudio,尝试使用ONNX版本
|
|
69
|
-
print("torchaudio not found, trying ONNX version...")
|
|
70
|
-
self.model, self.utils = torch.hub.load(
|
|
71
|
-
repo_or_dir=model_dir,
|
|
72
|
-
source="local",
|
|
73
|
-
model="silero_vad",
|
|
74
|
-
onnx=True,
|
|
75
|
-
force_reload=False,
|
|
76
|
-
)
|
|
77
|
-
except Exception as e:
|
|
78
|
-
print(f"Failed to load Silero model (both PyTorch and ONNX versions): {e}")
|
|
79
|
-
# 降级到能量检测
|
|
80
|
-
raise Exception("Model loading failed, will use energy detection")
|
|
81
|
-
|
|
82
|
-
# 初始化VAD配置,使用默认值作为备选
|
|
83
|
-
self.vad_threshold = float(threshold) if threshold else 0.5
|
|
84
|
-
self.silence_threshold_ms = int(min_silence_duration_ms) if min_silence_duration_ms else 800
|
|
85
|
-
print("SileroVAD初始化成功")
|
|
86
|
-
|
|
87
|
-
def is_vad(self, conn, audio_data):
|
|
88
|
-
"""检测音频数据中的语音活动"""
|
|
89
|
-
try:
|
|
90
|
-
# 确保conn对象有必要的属性
|
|
91
|
-
if not hasattr(conn, 'client_audio_buffer'):
|
|
92
|
-
conn.client_audio_buffer = []
|
|
93
|
-
if not hasattr(conn, 'client_have_voice'):
|
|
94
|
-
conn.client_have_voice = False
|
|
95
|
-
if not hasattr(conn, 'client_have_voice_last_time'):
|
|
96
|
-
conn.client_have_voice_last_time = 0
|
|
97
|
-
if not hasattr(conn, 'client_voice_stop'):
|
|
98
|
-
conn.client_voice_stop = False
|
|
99
|
-
|
|
100
|
-
# 将新数据加入缓冲区
|
|
101
|
-
conn.client_audio_buffer.extend(audio_data)
|
|
102
|
-
|
|
103
|
-
# 处理缓冲区中的完整帧(每次处理512采样点,每个采样点2字节)
|
|
104
|
-
client_have_voice = False
|
|
105
|
-
while len(conn.client_audio_buffer) >= 512 * 2:
|
|
106
|
-
# 提取前512个采样点(1024字节)
|
|
107
|
-
chunk = bytes(conn.client_audio_buffer[:512 * 2])
|
|
108
|
-
conn.client_audio_buffer = conn.client_audio_buffer[512 * 2:]
|
|
109
|
-
|
|
110
|
-
# 转换为模型需要的格式
|
|
111
|
-
audio_int16 = np.frombuffer(chunk, dtype=np.int16)
|
|
112
|
-
audio_float32 = audio_int16.astype(np.float32) / 32768.0
|
|
113
|
-
|
|
114
|
-
# 检测语音活动
|
|
115
|
-
with torch.no_grad():
|
|
116
|
-
speech_prob = self.model(torch.from_numpy(audio_float32), 16000).item()
|
|
117
|
-
|
|
118
|
-
client_have_voice = speech_prob >= self.vad_threshold
|
|
119
|
-
|
|
120
|
-
# 更新VAD状态
|
|
121
|
-
if client_have_voice:
|
|
122
|
-
conn.client_have_voice = True
|
|
123
|
-
conn.client_have_voice_last_time = time.time() * 1000
|
|
124
|
-
conn.client_voice_stop = False
|
|
125
|
-
elif conn.client_have_voice:
|
|
126
|
-
# 检查静默时间
|
|
127
|
-
stop_duration = time.time() * 1000 - conn.client_have_voice_last_time
|
|
128
|
-
if stop_duration >= self.silence_threshold_ms:
|
|
129
|
-
conn.client_have_voice = False
|
|
130
|
-
conn.client_voice_stop = True
|
|
131
|
-
|
|
132
|
-
return client_have_voice
|
|
133
|
-
except Exception as e:
|
|
134
|
-
print(f"VAD detection error: {e}")
|
|
135
|
-
return False
|
|
136
|
-
|
|
137
|
-
def reset_states(self):
|
|
138
|
-
"""Reset VAD states"""
|
|
139
|
-
pass # States are now stored in conn object, no need to reset here
|
|
17
|
+
"""Factory method to create VAD instance - always returns EnergyVADProvider"""
|
|
18
|
+
# 忽略vad_mini_volume, vad_mini_length, vad_silence_timeout参数
|
|
19
|
+
# 将vad_pause_timeout作为min_silence_duration_ms传递
|
|
20
|
+
return EnergyVADProvider(
|
|
21
|
+
threshold=threshold,
|
|
22
|
+
min_silence_duration_ms=vad_pause_timeout
|
|
23
|
+
)
|
|
140
24
|
|
|
141
25
|
class EnergyVADProvider(VADProviderBase):
|
|
142
|
-
"""Audio energy-based VAD provider
|
|
26
|
+
"""Audio energy-based VAD provider"""
|
|
143
27
|
def __init__(self, threshold=0.02, min_silence_duration_ms=300):
|
|
144
28
|
print(f"Initializing EnergyVAD: threshold={threshold}, min_silence_duration_ms={min_silence_duration_ms}")
|
|
145
29
|
# 初始化VAD配置,使用默认值作为备选
|
smartpi/base_driver.py
CHANGED
|
@@ -109,7 +109,7 @@ def uart3_init() -> Optional[serial.Serial]:
|
|
|
109
109
|
def calculate_pro_check(command_h: int, command_l: int, data: List[bytes] = None) -> int:
|
|
110
110
|
if data:
|
|
111
111
|
len_data = len(data)
|
|
112
|
-
base_sum = 0x86 + 0xAB +
|
|
112
|
+
base_sum = 0x86 + 0xAB + (len_data+9)//256 + 0x09 + len_data + command_h + command_l + 0x01 + 0xCF
|
|
113
113
|
base_sum += sum(data)
|
|
114
114
|
else:
|
|
115
115
|
base_sum = 0x86 + 0xAB + 0x00 + 0x09 + command_h + command_l + 0x01 + 0xCF
|
|
@@ -130,10 +130,10 @@ def write_data(command_h: int, command_l: int, send_data: bytes= None, lock: byt
|
|
|
130
130
|
send_packet = [0x86, 0xAB, 0x00, 0x09, command_h, command_l, 0x01, pro_check, 0xCF]
|
|
131
131
|
send_bytes = bytes(send_packet)
|
|
132
132
|
|
|
133
|
-
print("send:")
|
|
134
|
-
for x in send_bytes:
|
|
135
|
-
print(f"{x:02X}", end=' ')
|
|
136
|
-
print("\n")
|
|
133
|
+
# print("send:")
|
|
134
|
+
# for x in send_bytes:
|
|
135
|
+
# print(f"{x:02X}", end=' ')
|
|
136
|
+
# print("\n")
|
|
137
137
|
buf_clear()
|
|
138
138
|
serial_lock.acquire() #获取线程锁
|
|
139
139
|
fcntl.flock(ser.fileno(), fcntl.LOCK_EX) #进程锁,阻塞其他进程
|
|
@@ -153,10 +153,10 @@ def write_data(command_h: int, command_l: int, send_data: bytes= None, lock: byt
|
|
|
153
153
|
send_packet = [0x86, 0xAB, 0x00, 0x09, command_h, command_l, 0x01, pro_check, 0xCF]
|
|
154
154
|
send_bytes = bytes(send_packet)
|
|
155
155
|
|
|
156
|
-
print("send:")
|
|
157
|
-
for x in send_bytes:
|
|
158
|
-
print(f"{x:02X}", end=' ')
|
|
159
|
-
print("\n")
|
|
156
|
+
# print("send:")
|
|
157
|
+
# for x in send_bytes:
|
|
158
|
+
# print(f"{x:02X}", end=' ')
|
|
159
|
+
# print("\n")
|
|
160
160
|
buf_clear()
|
|
161
161
|
ser.write(send_bytes)
|
|
162
162
|
|
|
@@ -197,6 +197,7 @@ def process_received_data():
|
|
|
197
197
|
# for x in buffer:
|
|
198
198
|
# print(f"{x:02X}", end=' ')
|
|
199
199
|
# print("\n")
|
|
200
|
+
|
|
200
201
|
# 1. 查找帧头
|
|
201
202
|
start_idx = buffer.find(HEADER)
|
|
202
203
|
if start_idx == -1:
|
|
@@ -230,6 +231,10 @@ def process_received_data():
|
|
|
230
231
|
# 处理所有完整帧
|
|
231
232
|
if len(frames_queue) > 0:
|
|
232
233
|
frame = frames_queue.popleft()
|
|
234
|
+
# for x in frame:
|
|
235
|
+
# print(f"{x:02X}", end=' ')
|
|
236
|
+
# print("\n")
|
|
237
|
+
|
|
233
238
|
if check_frame(frame):
|
|
234
239
|
return frame
|
|
235
240
|
else:
|
|
@@ -549,262 +554,7 @@ def buf_clear():
|
|
|
549
554
|
fcntl.ioctl(ser.fileno(), termios.TCIOFLUSH)
|
|
550
555
|
except:
|
|
551
556
|
pass
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
def enter_bootloader_mode():
|
|
555
|
-
"""进入Bootloader模式"""
|
|
556
|
-
serial_lock.acquire() #获取线程锁
|
|
557
|
-
fcntl.flock(ser.fileno(), fcntl.LOCK_EX) #进程锁,阻塞其他进程
|
|
558
|
-
write_data(BOOT_UPDATE_H, BOOT_UPDATE_L, None, False)
|
|
559
|
-
start_time = time.time()
|
|
560
|
-
while True:
|
|
561
|
-
response =process_received_data()
|
|
562
|
-
if response:
|
|
563
|
-
serial_lock.release() #释放线程锁
|
|
564
|
-
fcntl.flock(ser.fileno(), fcntl.LOCK_UN) # 释放进程锁
|
|
565
|
-
buf_clear()
|
|
566
|
-
print("get:")
|
|
567
|
-
for x in response:
|
|
568
|
-
print(f"{x:02X}", end=' ')
|
|
569
|
-
print("\n")
|
|
570
|
-
return True
|
|
571
|
-
else:
|
|
572
|
-
if time.time() - start_time > 2:
|
|
573
|
-
print("读取超时")
|
|
574
|
-
buf_clear()
|
|
575
|
-
serial_lock.release() #释放线程锁
|
|
576
|
-
fcntl.flock(ser.fileno(), fcntl.LOCK_UN) # 释放进程锁
|
|
577
|
-
return None
|
|
578
|
-
|
|
579
|
-
def send_update_request():
|
|
580
|
-
"""发送更新请求"""
|
|
581
|
-
serial_lock.acquire() #获取线程锁
|
|
582
|
-
fcntl.flock(ser.fileno(), fcntl.LOCK_EX) #进程锁,阻塞其他进程
|
|
583
|
-
write_data(UPDATE_REQUEST_H, UPDATE_REQUEST_L, None, False)
|
|
584
|
-
start_time = time.time()
|
|
585
|
-
while True:
|
|
586
|
-
response = process_received_data()
|
|
587
|
-
if response:
|
|
588
|
-
serial_lock.release() #释放线程锁
|
|
589
|
-
fcntl.flock(ser.fileno(), fcntl.LOCK_UN) # 释放进程锁
|
|
590
|
-
buf_clear()
|
|
591
|
-
print("get:")
|
|
592
|
-
for x in response:
|
|
593
|
-
print(f"{x:02X}", end=' ')
|
|
594
|
-
print("\n")
|
|
595
|
-
return True
|
|
596
|
-
else:
|
|
597
|
-
if time.time() - start_time > 2:
|
|
598
|
-
print("更新请求超时")
|
|
599
|
-
buf_clear()
|
|
600
|
-
serial_lock.release() #释放线程锁
|
|
601
|
-
fcntl.flock(ser.fileno(), fcntl.LOCK_UN) # 释放进程锁
|
|
602
|
-
return None
|
|
603
|
-
|
|
604
|
-
def send_file_size(file_size):
|
|
605
|
-
"""发送文件大小"""
|
|
606
|
-
serial_lock.acquire() #获取线程锁
|
|
607
|
-
fcntl.flock(ser.fileno(), fcntl.LOCK_EX) #进程锁,阻塞其他进程
|
|
608
|
-
|
|
609
|
-
try:
|
|
610
|
-
# 将文件大小转换为4字节小端序
|
|
611
|
-
size_data = struct.pack('<I', file_size)
|
|
612
|
-
write_data(MAX_COM_LEN_H, MAX_COM_LEN_L, size_data, False)
|
|
613
|
-
|
|
614
|
-
start_time = time.time()
|
|
615
|
-
while True:
|
|
616
|
-
response = process_received_data()
|
|
617
|
-
if response:
|
|
618
|
-
serial_lock.release() #释放线程锁
|
|
619
|
-
fcntl.flock(ser.fileno(), fcntl.LOCK_UN) # 释放进程锁
|
|
620
|
-
buf_clear()
|
|
621
|
-
for x in response:
|
|
622
|
-
print(f"{x:02X}", end=' ')
|
|
623
|
-
print("\n")
|
|
624
|
-
return True
|
|
625
|
-
else:
|
|
626
|
-
if time.time() - start_time > 2:
|
|
627
|
-
print("发送文件大小超时")
|
|
628
|
-
buf_clear()
|
|
629
|
-
serial_lock.release() #释放线程锁
|
|
630
|
-
fcntl.flock(ser.fileno(), fcntl.LOCK_UN) # 释放进程锁
|
|
631
|
-
return None
|
|
632
|
-
except Exception as e:
|
|
633
|
-
print(f"发送文件大小出错: {e}")
|
|
634
|
-
serial_lock.release() #释放线程锁
|
|
635
|
-
fcntl.flock(ser.fileno(), fcntl.LOCK_UN) # 释放进程锁
|
|
636
|
-
return None
|
|
637
|
-
|
|
638
|
-
def send_file_data_chunk(chunk_data, chunk_num, total_chunks):
|
|
639
|
-
"""发送文件数据块"""
|
|
640
|
-
serial_lock.acquire() #获取线程锁
|
|
641
|
-
fcntl.flock(ser.fileno(), fcntl.LOCK_EX) #进程锁,阻塞其他进程
|
|
642
|
-
|
|
643
|
-
try:
|
|
644
|
-
write_data(PAGE_SEND_H, PAGE_SEND_L, chunk_data, False)
|
|
645
|
-
|
|
646
|
-
start_time = time.time()
|
|
647
|
-
while True:
|
|
648
|
-
response = process_received_data()
|
|
649
|
-
if response:
|
|
650
|
-
serial_lock.release() #释放线程锁
|
|
651
|
-
fcntl.flock(ser.fileno(), fcntl.LOCK_UN) # 释放进程锁
|
|
652
|
-
buf_clear()
|
|
653
|
-
# 显示进度
|
|
654
|
-
progress = (chunk_num + 1) * 100 // total_chunks
|
|
655
|
-
if progress % 10 == 0 or chunk_num == total_chunks - 1:
|
|
656
|
-
print(f"传输进度: {progress}% ({chunk_num+1}/{total_chunks})")
|
|
657
|
-
return True
|
|
658
|
-
else:
|
|
659
|
-
if time.time() - start_time > 2:
|
|
660
|
-
print(f"第{chunk_num+1}块数据发送超时")
|
|
661
|
-
buf_clear()
|
|
662
|
-
serial_lock.release() #释放线程锁
|
|
663
|
-
fcntl.flock(ser.fileno(), fcntl.LOCK_UN) # 释放进程锁
|
|
664
|
-
return None
|
|
665
|
-
except Exception as e:
|
|
666
|
-
print(f"发送数据块出错: {e}")
|
|
667
|
-
serial_lock.release() #释放线程锁
|
|
668
|
-
fcntl.flock(ser.fileno(), fcntl.LOCK_UN) # 释放进程锁
|
|
669
|
-
return None
|
|
670
|
-
|
|
671
|
-
def send_restart_command():
|
|
672
|
-
"""发送重启命令"""
|
|
673
|
-
print("发送重启指令...")
|
|
674
|
-
serial_lock.acquire()
|
|
675
|
-
fcntl.flock(ser.fileno(), fcntl.LOCK_EX)
|
|
676
|
-
|
|
677
|
-
try:
|
|
678
|
-
# 发送重启命令 (0xFF 0xFF)
|
|
679
|
-
write_data(0xFF, 0xFF, None, False)
|
|
680
|
-
|
|
681
|
-
# 重启不需要等待响应,因为设备会立即重启
|
|
682
|
-
time.sleep(0.5)
|
|
683
|
-
print("重启指令已发送")
|
|
684
|
-
return True
|
|
685
|
-
except Exception as e:
|
|
686
|
-
print(f"发送重启指令出错: {e}")
|
|
687
|
-
return False
|
|
688
|
-
finally:
|
|
689
|
-
serial_lock.release()
|
|
690
|
-
fcntl.flock(ser.fileno(), fcntl.LOCK_UN)
|
|
691
|
-
|
|
692
|
-
def transmit_file_to_usb(file_path, chunk_size=512):
|
|
693
|
-
"""
|
|
694
|
-
传输文件到虚拟U盘的主函数
|
|
695
|
-
|
|
696
|
-
Args:
|
|
697
|
-
file_path: 要传输的文件路径
|
|
698
|
-
chunk_size: 每个数据块的大小(默认512字节)
|
|
699
|
-
|
|
700
|
-
Returns:
|
|
701
|
-
bool: 传输是否成功
|
|
702
|
-
"""
|
|
703
|
-
print("=" * 50)
|
|
704
|
-
print("开始文件传输到虚拟U盘")
|
|
705
|
-
print("=" * 50)
|
|
706
|
-
|
|
707
|
-
# 检查文件是否存在
|
|
708
|
-
if not os.path.exists(file_path):
|
|
709
|
-
print(f"错误: 文件不存在 - {file_path}")
|
|
710
|
-
return False
|
|
711
|
-
|
|
712
|
-
# 获取文件大小
|
|
713
|
-
try:
|
|
714
|
-
file_size = os.path.getsize(file_path)
|
|
715
|
-
print(f"文件: {os.path.basename(file_path)}")
|
|
716
|
-
print(f"大小: {file_size} 字节")
|
|
717
|
-
except Exception as e:
|
|
718
|
-
print(f"获取文件大小出错: {e}")
|
|
719
|
-
return False
|
|
720
|
-
|
|
721
|
-
# 确保串口已初始化
|
|
722
|
-
if not ser.is_open:
|
|
723
|
-
print("初始化串口...")
|
|
724
|
-
uart3_init()
|
|
725
|
-
if not ser.is_open:
|
|
726
|
-
print("串口初始化失败")
|
|
727
|
-
return False
|
|
728
|
-
|
|
729
|
-
# 1. 进入Bootloader模式
|
|
730
|
-
enter_bootloader_mode()
|
|
731
|
-
|
|
732
|
-
time.sleep(5)
|
|
733
|
-
|
|
734
|
-
# 2. 发送更新请求
|
|
735
|
-
if not send_update_request():
|
|
736
|
-
print("更新请求失败,传输中止")
|
|
737
|
-
return False
|
|
738
|
-
|
|
739
|
-
# # 3. 发送文件大小
|
|
740
|
-
# if not send_file_size(file_size):
|
|
741
|
-
# print("文件大小发送失败,传输中止")
|
|
742
|
-
# return False
|
|
743
|
-
#
|
|
744
|
-
# # 4. 读取并发送文件数据
|
|
745
|
-
# print("开始传输文件数据...")
|
|
746
|
-
# try:
|
|
747
|
-
# with open(file_path, 'rb') as f:
|
|
748
|
-
# total_chunks = (file_size + chunk_size - 1) // chunk_size
|
|
749
|
-
#
|
|
750
|
-
# for chunk_num in range(total_chunks):
|
|
751
|
-
# # 读取数据块
|
|
752
|
-
# chunk_data = f.read(chunk_size)
|
|
753
|
-
# if not chunk_data:
|
|
754
|
-
# print(f"错误: 第{chunk_num+1}块数据读取失败")
|
|
755
|
-
# return False
|
|
756
|
-
#
|
|
757
|
-
# # 如果数据块不足chunk_size,填充0(可选)
|
|
758
|
-
# if len(chunk_data) < chunk_size:
|
|
759
|
-
# chunk_data += b'\x00' * (chunk_size - len(chunk_data))
|
|
760
|
-
#
|
|
761
|
-
# # 发送数据块
|
|
762
|
-
# if not send_file_data_chunk(chunk_data, chunk_num, total_chunks):
|
|
763
|
-
# print(f"第{chunk_num+1}块数据发送失败,传输中止")
|
|
764
|
-
# return False
|
|
765
|
-
#
|
|
766
|
-
# print("文件数据传输完成!")
|
|
767
|
-
#
|
|
768
|
-
# except Exception as e:
|
|
769
|
-
# print(f"读取或发送文件数据出错: {e}")
|
|
770
|
-
# return False
|
|
771
|
-
#
|
|
772
|
-
# # 5. 发送重启命令
|
|
773
|
-
# if not send_restart_command():
|
|
774
|
-
# print("重启指令发送失败")
|
|
775
|
-
# return False
|
|
776
|
-
#
|
|
777
|
-
# print("=" * 50)
|
|
778
|
-
# print("文件传输成功完成!")
|
|
779
|
-
# print("文件已保存到虚拟U盘")
|
|
780
|
-
# print("设备将自动重启...")
|
|
781
|
-
# print("=" * 50)
|
|
782
|
-
|
|
783
|
-
# 等待设备重启
|
|
784
|
-
time.sleep(3)
|
|
785
|
-
return True
|
|
786
|
-
|
|
787
|
-
def example_file_transfer():
|
|
788
|
-
"""文件传输使用示例"""
|
|
789
|
-
print("文件传输示例")
|
|
790
|
-
print("-" * 30)
|
|
791
|
-
|
|
792
|
-
# 初始化串口
|
|
793
|
-
uart3_init()
|
|
794
|
-
|
|
795
|
-
# 指定要传输的文件路径
|
|
796
|
-
# 请根据实际情况修改
|
|
797
|
-
file_path = "/home/zmrobo/UPDATE.DAT"
|
|
798
|
-
|
|
799
|
-
# 执行文件传输
|
|
800
|
-
success = transmit_file_to_usb(file_path)
|
|
801
|
-
|
|
802
|
-
if success:
|
|
803
|
-
print("文件传输成功!")
|
|
804
|
-
return 0
|
|
805
|
-
else:
|
|
806
|
-
print("文件传输失败!")
|
|
807
|
-
return 1
|
|
557
|
+
|
|
808
558
|
|
|
809
559
|
"""H2-RCU初始化"""
|
|
810
560
|
def smartpi_init():
|
smartpi/onnx_pose_workflow.py
CHANGED
smartpi/rknn_pose_workflow.py
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
smartpi/__init__.py,sha256=
|
|
1
|
+
smartpi/__init__.py,sha256=YzlPmAHE6lnrGS7ChCmQYrfk9QZRPCNMlw46chQnWSY,356
|
|
2
2
|
smartpi/_gui.py,sha256=ij-6HZAEIwdy_hvU7f0NkyQjx_-eephijlKbGUhf8Uo,2177
|
|
3
|
-
smartpi/ai_asr.py,sha256=
|
|
3
|
+
smartpi/ai_asr.py,sha256=wxh_1Klh8vJottAt19jq3qpOmM_Cw4DHQEPKpsHGhmE,40063
|
|
4
4
|
smartpi/ai_llm.py,sha256=-khBK2PMwbYUDvbaCTRCktE4dFloqfai4mHI-V8GEXM,36751
|
|
5
5
|
smartpi/ai_tts.py,sha256=OjAJs3XOykiufXuEDiaD0coKsWjknPdhwRpRzGLDZKU,36061
|
|
6
|
-
smartpi/ai_vad.py,sha256=
|
|
7
|
-
smartpi/base_driver.py,sha256=
|
|
6
|
+
smartpi/ai_vad.py,sha256=9J1xxuKF8GvojkL_JuXv7_xE8bQAo5D49Xasi8piKK8,3630
|
|
7
|
+
smartpi/base_driver.py,sha256=BwqgcYbQ9Rg8KiBJV2xy--NMNsMIg_zL-nnsAilCHJk,22687
|
|
8
8
|
smartpi/camera.py,sha256=AVpZsMpW-24CP3BOfarjmRawMJdTOZY7Crq7FeLOqb4,3292
|
|
9
9
|
smartpi/color_sensor.py,sha256=ckIXD81YnqPo6nENAnipNp3gY12FJ235QKj0e8Cul9E,521
|
|
10
10
|
smartpi/cw2015.py,sha256=1lAF-pi_ye_ya1AZQS1sjbgsDf7MThO5IAskKsNGBzA,5695
|
|
@@ -20,13 +20,13 @@ smartpi/motor.py,sha256=DvFzREEzyRafGmSCagU6ASeoE8fnAsKYI4oYMrkXXJc,5351
|
|
|
20
20
|
smartpi/move.py,sha256=s1ZnkFtp6SCBnxhBxp6qQjGbifdsY5hjVCwlarTsZto,6688
|
|
21
21
|
smartpi/onnx_hand_workflow.py,sha256=ZCoaWC6GygZSrhM6jhsuB6qmQ6GiAFFrso6rKAGmue8,8157
|
|
22
22
|
smartpi/onnx_image_workflow.py,sha256=-saM_NxR6yDz06xlWZOvHf6cq3zmtOCFhCyZTGqvuOk,6188
|
|
23
|
-
smartpi/onnx_pose_workflow.py,sha256=
|
|
23
|
+
smartpi/onnx_pose_workflow.py,sha256=w0zGlXXBgIcxwjLF7eYHPEePqRw3KXvKQUqzVd_UrzQ,20966
|
|
24
24
|
smartpi/onnx_text_workflow.py,sha256=6l9MTT2T1-rNye3_dSHLI2U749Z94aoRdkSe6CNXfHw,7191
|
|
25
25
|
smartpi/onnx_voice_workflow.py,sha256=jkMFzy3RUnLo8LZAuCUfsS3YCJWSZzZuiE4RFoQ2HZw,17440
|
|
26
26
|
smartpi/posenet_utils.py,sha256=o3scK41Eqvftav4y4vp6_6HinQWNCLeLpArXAzqQ-7s,8983
|
|
27
27
|
smartpi/rknn_hand_workflow.py,sha256=wsVN_PYP9M-1AFaN4yqrGksUBoamYfujW0nQq4nv3kU,10160
|
|
28
28
|
smartpi/rknn_image_workflow.py,sha256=4lTtcdmQ9KN5WiEnHayvqAd-dA0tiap5YXIqAMn5SoI,18444
|
|
29
|
-
smartpi/rknn_pose_workflow.py,sha256=
|
|
29
|
+
smartpi/rknn_pose_workflow.py,sha256=T09F9vcQ6-QG3PlFRpCI4AuTPzEl_s0C38wfMD21Ujo,27836
|
|
30
30
|
smartpi/rknn_text_workflow.py,sha256=KNBSetj3tmlLxdZOm0yzbiDnjH8S5191fuxh5Mi-uCY,9632
|
|
31
31
|
smartpi/rknn_voice_workflow.py,sha256=T8iRQWPtJYXqoHIZH2FiT1WLxwN3HQg4D-mg-5KvYdA,16326
|
|
32
32
|
smartpi/servo.py,sha256=0p09Jk-IVk5nLXz2AqFvytiYSSe4sMxdy1FaNMQijoY,5770
|
|
@@ -70,7 +70,7 @@ smartpi/text_gte_model/config/tokenizer_config.json,sha256=w5RiDifbeIYy6vyGX5v94
|
|
|
70
70
|
smartpi/text_gte_model/config/vocab.txt,sha256=oi9hP3uz_8h8XoHNh6rgLnVdJbIEm75zKoSKM8HzsC8,84758
|
|
71
71
|
smartpi/text_gte_model/gte/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
72
72
|
smartpi/text_gte_model/gte/gte_model.onnx,sha256=XXYg6TUhzOx1SqAhp6ePDU0QgeK6DQEqHATMuQQJCNE,30468366
|
|
73
|
-
smartpi-0.1.
|
|
74
|
-
smartpi-0.1.
|
|
75
|
-
smartpi-0.1.
|
|
76
|
-
smartpi-0.1.
|
|
73
|
+
smartpi-0.1.43.dist-info/METADATA,sha256=Itx-zHFW2xLOdYkd5UgHu7EKImJObZdgVXD-yduwt7c,614
|
|
74
|
+
smartpi-0.1.43.dist-info/WHEEL,sha256=oiQVh_5PnQM0E3gPdiz09WCNmwiHDMaGer_elqB3coM,92
|
|
75
|
+
smartpi-0.1.43.dist-info/top_level.txt,sha256=PoLhUCmWAiQUg5UeN2fS-Y1iQyBbF2rdUlizXtpHGRQ,8
|
|
76
|
+
smartpi-0.1.43.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|