smartpi 1.1.4__py3-none-any.whl → 1.1.5__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 +8 -0
- smartpi/__init__.pyc +0 -0
- smartpi/_gui.py +66 -0
- smartpi/_gui.pyc +0 -0
- smartpi/ai_asr.py +1037 -0
- smartpi/ai_asr.pyc +0 -0
- smartpi/ai_llm.py +934 -0
- smartpi/ai_llm.pyc +0 -0
- smartpi/ai_tts.py +938 -0
- smartpi/ai_tts.pyc +0 -0
- smartpi/ai_vad.py +83 -0
- smartpi/ai_vad.pyc +0 -0
- smartpi/audio.py +125 -0
- smartpi/audio.pyc +0 -0
- smartpi/base_driver.py +618 -0
- smartpi/base_driver.pyc +0 -0
- smartpi/camera.py +84 -0
- smartpi/camera.pyc +0 -0
- smartpi/color_sensor.py +18 -0
- smartpi/color_sensor.pyc +0 -0
- smartpi/cw2015.py +179 -0
- smartpi/cw2015.pyc +0 -0
- smartpi/flash.py +130 -0
- smartpi/flash.pyc +0 -0
- smartpi/humidity.py +20 -0
- smartpi/humidity.pyc +0 -0
- smartpi/led.py +19 -0
- smartpi/led.pyc +0 -0
- smartpi/light_sensor.py +72 -0
- smartpi/light_sensor.pyc +0 -0
- smartpi/local_model.py +432 -0
- smartpi/local_model.pyc +0 -0
- smartpi/mcp_client.py +100 -0
- smartpi/mcp_client.pyc +0 -0
- smartpi/mcp_fastmcp.py +322 -0
- smartpi/mcp_fastmcp.pyc +0 -0
- smartpi/mcp_intent_recognizer.py +408 -0
- smartpi/mcp_intent_recognizer.pyc +0 -0
- smartpi/models/__init__.py +0 -0
- smartpi/models/__init__.pyc +0 -0
- smartpi/models/snakers4_silero-vad/__init__.py +0 -0
- smartpi/models/snakers4_silero-vad/__init__.pyc +0 -0
- smartpi/models/snakers4_silero-vad/hubconf.py +56 -0
- smartpi/models/snakers4_silero-vad/hubconf.pyc +0 -0
- smartpi/motor.py +177 -0
- smartpi/motor.pyc +0 -0
- smartpi/move.py +218 -0
- smartpi/move.pyc +0 -0
- smartpi/onnx_hand_workflow.py +201 -0
- smartpi/onnx_hand_workflow.pyc +0 -0
- smartpi/onnx_image_workflow.py +176 -0
- smartpi/onnx_image_workflow.pyc +0 -0
- smartpi/onnx_pose_workflow.py +482 -0
- smartpi/onnx_pose_workflow.pyc +0 -0
- smartpi/onnx_text_workflow.py +173 -0
- smartpi/onnx_text_workflow.pyc +0 -0
- smartpi/onnx_voice_workflow.py +437 -0
- smartpi/onnx_voice_workflow.pyc +0 -0
- smartpi/posemodel/__init__.py +0 -0
- smartpi/posemodel/__init__.pyc +0 -0
- smartpi/posenet_utils.py +222 -0
- smartpi/posenet_utils.pyc +0 -0
- smartpi/rknn_hand_workflow.py +245 -0
- smartpi/rknn_hand_workflow.pyc +0 -0
- smartpi/rknn_image_workflow.py +405 -0
- smartpi/rknn_image_workflow.pyc +0 -0
- smartpi/rknn_pose_workflow.py +592 -0
- smartpi/rknn_pose_workflow.pyc +0 -0
- smartpi/rknn_text_workflow.py +240 -0
- smartpi/rknn_text_workflow.pyc +0 -0
- smartpi/rknn_voice_workflow.py +394 -0
- smartpi/rknn_voice_workflow.pyc +0 -0
- smartpi/servo.py +178 -0
- smartpi/servo.pyc +0 -0
- smartpi/temperature.py +18 -0
- smartpi/temperature.pyc +0 -0
- smartpi/tencentcloud-speech-sdk-python/__init__.py +1 -0
- smartpi/tencentcloud-speech-sdk-python/__init__.pyc +0 -0
- smartpi/tencentcloud-speech-sdk-python/asr/__init__.py +0 -0
- smartpi/tencentcloud-speech-sdk-python/asr/__init__.pyc +0 -0
- smartpi/tencentcloud-speech-sdk-python/asr/flash_recognizer.py +178 -0
- smartpi/tencentcloud-speech-sdk-python/asr/flash_recognizer.pyc +0 -0
- smartpi/tencentcloud-speech-sdk-python/asr/speech_recognizer.py +311 -0
- smartpi/tencentcloud-speech-sdk-python/asr/speech_recognizer.pyc +0 -0
- smartpi/tencentcloud-speech-sdk-python/common/__init__.py +1 -0
- smartpi/tencentcloud-speech-sdk-python/common/__init__.pyc +0 -0
- smartpi/tencentcloud-speech-sdk-python/common/credential.py +6 -0
- smartpi/tencentcloud-speech-sdk-python/common/credential.pyc +0 -0
- smartpi/tencentcloud-speech-sdk-python/common/log.py +16 -0
- smartpi/tencentcloud-speech-sdk-python/common/log.pyc +0 -0
- smartpi/tencentcloud-speech-sdk-python/common/utils.py +7 -0
- smartpi/tencentcloud-speech-sdk-python/common/utils.pyc +0 -0
- smartpi/tencentcloud-speech-sdk-python/soe/__init__.py +0 -0
- smartpi/tencentcloud-speech-sdk-python/soe/__init__.pyc +0 -0
- smartpi/tencentcloud-speech-sdk-python/soe/speaking_assessment.py +276 -0
- smartpi/tencentcloud-speech-sdk-python/soe/speaking_assessment.pyc +0 -0
- smartpi/tencentcloud-speech-sdk-python/tts/__init__.py +0 -0
- smartpi/tencentcloud-speech-sdk-python/tts/__init__.pyc +0 -0
- smartpi/tencentcloud-speech-sdk-python/tts/flowing_speech_synthesizer.py +294 -0
- smartpi/tencentcloud-speech-sdk-python/tts/flowing_speech_synthesizer.pyc +0 -0
- smartpi/tencentcloud-speech-sdk-python/tts/speech_synthesizer.py +144 -0
- smartpi/tencentcloud-speech-sdk-python/tts/speech_synthesizer.pyc +0 -0
- smartpi/tencentcloud-speech-sdk-python/tts/speech_synthesizer_ws.py +234 -0
- smartpi/tencentcloud-speech-sdk-python/tts/speech_synthesizer_ws.pyc +0 -0
- smartpi/tencentcloud-speech-sdk-python/vc/__init__.py +0 -0
- smartpi/tencentcloud-speech-sdk-python/vc/__init__.pyc +0 -0
- smartpi/tencentcloud-speech-sdk-python/vc/speech_convertor_ws.py +237 -0
- smartpi/tencentcloud-speech-sdk-python/vc/speech_convertor_ws.pyc +0 -0
- smartpi/text_gte_model/__init__.py +0 -0
- smartpi/text_gte_model/__init__.pyc +0 -0
- smartpi/text_gte_model/config/__init__.py +0 -0
- smartpi/text_gte_model/config/__init__.pyc +0 -0
- smartpi/text_gte_model/gte/__init__.py +0 -0
- smartpi/text_gte_model/gte/__init__.pyc +0 -0
- smartpi/touch_sensor.py +16 -0
- smartpi/touch_sensor.pyc +0 -0
- smartpi/trace.py +120 -0
- smartpi/trace.pyc +0 -0
- smartpi/ultrasonic.py +20 -0
- smartpi/ultrasonic.pyc +0 -0
- {smartpi-1.1.4.dist-info → smartpi-1.1.5.dist-info}/METADATA +3 -2
- smartpi-1.1.5.dist-info/RECORD +137 -0
- smartpi-1.1.4.dist-info/RECORD +0 -77
- {smartpi-1.1.4.dist-info → smartpi-1.1.5.dist-info}/WHEEL +0 -0
- {smartpi-1.1.4.dist-info → smartpi-1.1.5.dist-info}/top_level.txt +0 -0
smartpi/base_driver.py
ADDED
|
@@ -0,0 +1,618 @@
|
|
|
1
|
+
# coding=utf-8
|
|
2
|
+
import serial,time,struct,threading,fcntl,os,termios
|
|
3
|
+
from typing import List, Optional
|
|
4
|
+
from collections import deque
|
|
5
|
+
from . import servo,motor,cw2015,led,light_sensor
|
|
6
|
+
|
|
7
|
+
# 创建全局线程锁
|
|
8
|
+
serial_lock = threading.RLock()
|
|
9
|
+
|
|
10
|
+
# 命令常量
|
|
11
|
+
BOOT_UPDATE_H = 0XFF
|
|
12
|
+
BOOT_UPDATE_L = 0XFF
|
|
13
|
+
READ_MODEL_H = 0XFF
|
|
14
|
+
READ_MODEL_L = 0X01
|
|
15
|
+
READ_VERSION_H = 0XFF
|
|
16
|
+
READ_VERSION_L = 0X02
|
|
17
|
+
READ_FACTORY_H = 0XFF
|
|
18
|
+
READ_FACTORY_L = 0X03
|
|
19
|
+
READ_HW_ID_H = 0XFF
|
|
20
|
+
READ_HW_ID_L = 0X04
|
|
21
|
+
READ_NAME_H = 0XFF
|
|
22
|
+
READ_NAME_L = 0X05
|
|
23
|
+
WRITE_NAME_H = 0XFF
|
|
24
|
+
WRITE_NAME_L = 0X06
|
|
25
|
+
READ_CONNECT_H = 0XFF
|
|
26
|
+
READ_CONNECT_L = 0X07
|
|
27
|
+
READ_BAT_H = 0XFF
|
|
28
|
+
READ_BAT_L = 0X0C
|
|
29
|
+
|
|
30
|
+
UPDATE_REQUEST_H = 0XFF
|
|
31
|
+
UPDATE_REQUEST_L = 0X10
|
|
32
|
+
MAX_COM_LEN_H = 0XFF
|
|
33
|
+
MAX_COM_LEN_L = 0X11
|
|
34
|
+
DL_MESSAGE_H = 0XFF
|
|
35
|
+
DL_MESSAGE_L = 0X12
|
|
36
|
+
READ_STATUS_H = 0XFF
|
|
37
|
+
READ_STATUS_L = 0X13
|
|
38
|
+
PAGE_CHECK_H = 0XFF
|
|
39
|
+
PAGE_CHECK_L = 0X14
|
|
40
|
+
PAGE_SEND_H = 0XFF
|
|
41
|
+
PAGE_SEND_L = 0X15
|
|
42
|
+
|
|
43
|
+
READ_PERIPH_H = 0X01
|
|
44
|
+
READ_PERIPH_L = 0X01
|
|
45
|
+
SINGLE_OP_H = 0X01
|
|
46
|
+
SINGLE_OP_L = 0X02
|
|
47
|
+
MODE_CHANGE_H = 0X01
|
|
48
|
+
MODE_CHANGE_L = 0X03
|
|
49
|
+
SEND_CYCLE_H = 0X01
|
|
50
|
+
SEND_CYCLE_L = 0X04
|
|
51
|
+
|
|
52
|
+
P1 = 1
|
|
53
|
+
P2 = 2
|
|
54
|
+
P3 = 3
|
|
55
|
+
P4 = 4
|
|
56
|
+
P5 = 5
|
|
57
|
+
P6 = 6
|
|
58
|
+
|
|
59
|
+
M1 = 1
|
|
60
|
+
M2 = 2
|
|
61
|
+
M3 = 3
|
|
62
|
+
M4 = 4
|
|
63
|
+
M5 = 5
|
|
64
|
+
M6 = 6
|
|
65
|
+
|
|
66
|
+
frames_queue = deque()
|
|
67
|
+
buffer = bytearray()
|
|
68
|
+
HEADER = bytes.fromhex('86 AB') # 帧头
|
|
69
|
+
FOOTER = bytes.fromhex('CF') # 帧尾
|
|
70
|
+
MIN_FRAME_LEN = 9 # 最小帧长度
|
|
71
|
+
|
|
72
|
+
# 串口配置参数
|
|
73
|
+
SERIAL_PORT = "/dev/ttyS3" # 串口设备路径
|
|
74
|
+
BAUD_RATE = 921600 # 波特率
|
|
75
|
+
TIMEOUT = 0.1 # 读取超时时间(秒)
|
|
76
|
+
|
|
77
|
+
ser = serial.Serial(
|
|
78
|
+
port=SERIAL_PORT,
|
|
79
|
+
baudrate=BAUD_RATE,
|
|
80
|
+
bytesize=serial.EIGHTBITS, # 8位数据位
|
|
81
|
+
parity=serial.PARITY_NONE, # 无校验位
|
|
82
|
+
stopbits=serial.STOPBITS_ONE, # 1位停止位
|
|
83
|
+
timeout=TIMEOUT,
|
|
84
|
+
xonxoff=False, # 关闭软件流控
|
|
85
|
+
rtscts=False, # 关闭硬件流控
|
|
86
|
+
)
|
|
87
|
+
|
|
88
|
+
def is_lock_locked(lock):
|
|
89
|
+
"""检查锁是否被占用"""
|
|
90
|
+
acquired = serial_lock.acquire(blocking=True)
|
|
91
|
+
if acquired:
|
|
92
|
+
serial_lock.release()
|
|
93
|
+
return False
|
|
94
|
+
return True
|
|
95
|
+
|
|
96
|
+
def uart3_init() -> Optional[serial.Serial]:
|
|
97
|
+
"""初始化串口"""
|
|
98
|
+
try:
|
|
99
|
+
if ser.is_open:
|
|
100
|
+
# print("UART3初始化成功")
|
|
101
|
+
return ser
|
|
102
|
+
else:
|
|
103
|
+
print("Error opening UART3")
|
|
104
|
+
return None
|
|
105
|
+
except Exception as e:
|
|
106
|
+
print(f"Error opening UART3: {e}")
|
|
107
|
+
return None
|
|
108
|
+
|
|
109
|
+
def calculate_pro_check(command_h: int, command_l: int, data: List[bytes] = None) -> int:
|
|
110
|
+
if data:
|
|
111
|
+
len_data = len(data)
|
|
112
|
+
base_sum = 0x86 + 0xAB + (len_data+9)//256 + 0x09 + len_data + command_h + command_l + 0x01 + 0xCF
|
|
113
|
+
base_sum += sum(data)
|
|
114
|
+
else:
|
|
115
|
+
base_sum = 0x86 + 0xAB + 0x00 + 0x09 + command_h + command_l + 0x01 + 0xCF
|
|
116
|
+
|
|
117
|
+
return base_sum % 256 # 确保结果为单字节(原C代码未取模,需根据实际协议调整)
|
|
118
|
+
|
|
119
|
+
def write_data(command_h: int, command_l: int, send_data: bytes= None, lock: bytes= True) -> Optional[bytes]:
|
|
120
|
+
if lock == True:
|
|
121
|
+
buffer = bytearray()
|
|
122
|
+
HEADER = bytes.fromhex('86 AB') # 帧头
|
|
123
|
+
FOOTER = bytes.fromhex('CF') # 帧尾
|
|
124
|
+
MIN_FRAME_LEN = 9 # 最小帧长度
|
|
125
|
+
if send_data:
|
|
126
|
+
pro_check = calculate_pro_check(command_h, command_l, list(send_data))
|
|
127
|
+
send_packet = [0x86, 0xAB, (0x09+len(send_data))//256, (0x09+len(send_data))%256, command_h, command_l, *send_data, 0x01, pro_check, 0xCF]
|
|
128
|
+
else:
|
|
129
|
+
pro_check = calculate_pro_check(command_h, command_l)
|
|
130
|
+
send_packet = [0x86, 0xAB, 0x00, 0x09, command_h, command_l, 0x01, pro_check, 0xCF]
|
|
131
|
+
send_bytes = bytes(send_packet)
|
|
132
|
+
|
|
133
|
+
# print("send:")
|
|
134
|
+
# for x in send_bytes:
|
|
135
|
+
# print(f"{x:02X}", end=' ')
|
|
136
|
+
# print("\n")
|
|
137
|
+
buf_clear()
|
|
138
|
+
serial_lock.acquire() #获取线程锁
|
|
139
|
+
fcntl.flock(ser.fileno(), fcntl.LOCK_EX) #进程锁,阻塞其他进程
|
|
140
|
+
ser.write(send_bytes)
|
|
141
|
+
serial_lock.release() #释放线程锁
|
|
142
|
+
fcntl.flock(ser.fileno(), fcntl.LOCK_UN) # 释放进程锁
|
|
143
|
+
elif lock == False:
|
|
144
|
+
buffer = bytearray()
|
|
145
|
+
HEADER = bytes.fromhex('86 AB') # 帧头
|
|
146
|
+
FOOTER = bytes.fromhex('CF') # 帧尾
|
|
147
|
+
MIN_FRAME_LEN = 9 # 最小帧长度
|
|
148
|
+
if send_data:
|
|
149
|
+
pro_check = calculate_pro_check(command_h, command_l, list(send_data))
|
|
150
|
+
send_packet = [0x86, 0xAB, (0x09+len(send_data))//256, (0x09+len(send_data))%256, command_h, command_l, *send_data, 0x01, pro_check, 0xCF]
|
|
151
|
+
else:
|
|
152
|
+
pro_check = calculate_pro_check(command_h, command_l)
|
|
153
|
+
send_packet = [0x86, 0xAB, 0x00, 0x09, command_h, command_l, 0x01, pro_check, 0xCF]
|
|
154
|
+
send_bytes = bytes(send_packet)
|
|
155
|
+
|
|
156
|
+
# print("send:")
|
|
157
|
+
# for x in send_bytes:
|
|
158
|
+
# print(f"{x:02X}", end=' ')
|
|
159
|
+
# print("\n")
|
|
160
|
+
buf_clear()
|
|
161
|
+
ser.write(send_bytes)
|
|
162
|
+
|
|
163
|
+
|
|
164
|
+
def check_frame(frame: bytes) -> bool:
|
|
165
|
+
# 简化版校验,实际应根据协议实现
|
|
166
|
+
if len(frame) < 9:
|
|
167
|
+
return False
|
|
168
|
+
|
|
169
|
+
# 计算校验和
|
|
170
|
+
calculated_checksum = (sum(frame[:-2])+frame[-1])%256
|
|
171
|
+
frame_checksum = frame[-2] # 倒数第二个字节是校验和
|
|
172
|
+
|
|
173
|
+
return calculated_checksum == frame_checksum
|
|
174
|
+
|
|
175
|
+
def process_received_data():
|
|
176
|
+
#with serial_lock:
|
|
177
|
+
global buffer
|
|
178
|
+
# 读取所有可用数据
|
|
179
|
+
data = ser.read(ser.in_waiting or 1)
|
|
180
|
+
|
|
181
|
+
# if data:
|
|
182
|
+
# buffer.extend(data)
|
|
183
|
+
#
|
|
184
|
+
# # 检查缓冲区中是否有0xCF
|
|
185
|
+
# if 0xCF in buffer:
|
|
186
|
+
# # 找到0xCF的位置
|
|
187
|
+
# cf_index = buffer.index(0xCF)
|
|
188
|
+
# # 提取从开始到0xCF的完整帧(包括0xCF)
|
|
189
|
+
# frame = buffer[:cf_index + 1]
|
|
190
|
+
# # 从缓冲区中移除已处理的数据
|
|
191
|
+
# buffer = buffer[cf_index + 1:]
|
|
192
|
+
# return bytes(frame)
|
|
193
|
+
|
|
194
|
+
if data:
|
|
195
|
+
buffer.extend(data)
|
|
196
|
+
while len(buffer)>=2:
|
|
197
|
+
# for x in buffer:
|
|
198
|
+
# print(f"{x:02X}", end=' ')
|
|
199
|
+
# print("\n")
|
|
200
|
+
|
|
201
|
+
# 1. 查找帧头
|
|
202
|
+
start_idx = buffer.find(HEADER)
|
|
203
|
+
if start_idx == -1:
|
|
204
|
+
# 没有找到帧头,清空无效数据(保留最后可能的部分帧头)
|
|
205
|
+
#print("Header no found")
|
|
206
|
+
if len(buffer) > len(HEADER) - 1:
|
|
207
|
+
buffer = buffer[-len(HEADER) + 1:]
|
|
208
|
+
return
|
|
209
|
+
# 2. 检查帧头后的长度字段是否足够
|
|
210
|
+
if start_idx + 4 > len(buffer):
|
|
211
|
+
# 长度字段不完整,等待更多数据
|
|
212
|
+
return
|
|
213
|
+
# 3. 解析帧长度
|
|
214
|
+
frame_length = (buffer[start_idx + 2] << 8) + buffer[start_idx + 3]
|
|
215
|
+
# 4. 检查完整帧是否已到达
|
|
216
|
+
end_idx = start_idx + frame_length - 1
|
|
217
|
+
if end_idx >= len(buffer):
|
|
218
|
+
# 完整帧尚未完全到达
|
|
219
|
+
return
|
|
220
|
+
# 5. 检查帧尾
|
|
221
|
+
if buffer[end_idx] != ord(FOOTER):
|
|
222
|
+
# 跳过当前帧头,继续查找
|
|
223
|
+
print("End no found")
|
|
224
|
+
buffer = buffer[start_idx + 1:]
|
|
225
|
+
continue
|
|
226
|
+
# 6. 提取完整帧
|
|
227
|
+
frame = buffer[start_idx:end_idx + 1]
|
|
228
|
+
frames_queue.append(frame)
|
|
229
|
+
# 7. 从缓冲区移除已处理帧
|
|
230
|
+
buffer = buffer[end_idx + 1:]
|
|
231
|
+
# 处理所有完整帧
|
|
232
|
+
if len(frames_queue) > 0:
|
|
233
|
+
frame = frames_queue.popleft()
|
|
234
|
+
# for x in frame:
|
|
235
|
+
# print(f"{x:02X}", end=' ')
|
|
236
|
+
# print("\n")
|
|
237
|
+
|
|
238
|
+
if check_frame(frame):
|
|
239
|
+
return frame
|
|
240
|
+
else:
|
|
241
|
+
print("Check byte error")
|
|
242
|
+
|
|
243
|
+
# 功能函数类
|
|
244
|
+
##############################################################################读取设备信息
|
|
245
|
+
"""读取设备型号"""
|
|
246
|
+
def read_device_model() -> Optional[bytes]:
|
|
247
|
+
serial_lock.acquire() #获取线程锁
|
|
248
|
+
fcntl.flock(ser.fileno(), fcntl.LOCK_EX) # 进程锁,阻塞其他进程
|
|
249
|
+
write_data(READ_MODEL_H, READ_MODEL_L, None, False)
|
|
250
|
+
start_time = time.time()
|
|
251
|
+
while True:
|
|
252
|
+
response =process_received_data()
|
|
253
|
+
if response:
|
|
254
|
+
serial_lock.release() #释放线程锁
|
|
255
|
+
fcntl.flock(ser.fileno(), fcntl.LOCK_UN) # 释放进程锁
|
|
256
|
+
display_data = response[6:-3].decode(errors="ignore")
|
|
257
|
+
buf_clear()
|
|
258
|
+
# print(f"设备型号: {display_data}")
|
|
259
|
+
return display_data
|
|
260
|
+
else:
|
|
261
|
+
if time.time() - start_time > 3:
|
|
262
|
+
print("读取超时")
|
|
263
|
+
buf_clear()
|
|
264
|
+
serial_lock.release() #释放线程锁
|
|
265
|
+
fcntl.flock(ser.fileno(), fcntl.LOCK_UN) # 释放进程锁
|
|
266
|
+
return None
|
|
267
|
+
|
|
268
|
+
"""读取版本号"""
|
|
269
|
+
def read_version() -> Optional[bytes]:
|
|
270
|
+
serial_lock.acquire() #获取线程锁
|
|
271
|
+
fcntl.flock(ser.fileno(), fcntl.LOCK_EX) # 进程锁,阻塞其他进程
|
|
272
|
+
write_data(READ_VERSION_H, READ_VERSION_L, None, False)
|
|
273
|
+
start_time = time.time()
|
|
274
|
+
while True:
|
|
275
|
+
response =process_received_data()
|
|
276
|
+
if response:
|
|
277
|
+
serial_lock.release() #释放线程锁
|
|
278
|
+
fcntl.flock(ser.fileno(), fcntl.LOCK_UN) # 释放进程锁
|
|
279
|
+
display_data = response[6:-3].decode(errors="ignore")
|
|
280
|
+
buf_clear()
|
|
281
|
+
# print(f"版本号: {display_data}")
|
|
282
|
+
return display_data
|
|
283
|
+
else:
|
|
284
|
+
if time.time() - start_time > 3:
|
|
285
|
+
print("读取超时")
|
|
286
|
+
buf_clear()
|
|
287
|
+
serial_lock.release() #释放线程锁
|
|
288
|
+
fcntl.flock(ser.fileno(), fcntl.LOCK_UN) # 释放进程锁
|
|
289
|
+
return None
|
|
290
|
+
|
|
291
|
+
"""读取工厂信息"""
|
|
292
|
+
def read_factory_data() -> Optional[bytes]:
|
|
293
|
+
serial_lock.acquire() #获取线程锁
|
|
294
|
+
fcntl.flock(ser.fileno(), fcntl.LOCK_EX) # 进程锁,阻塞其他进程
|
|
295
|
+
write_data(READ_FACTORY_H, READ_FACTORY_L, None, False)
|
|
296
|
+
start_time = time.time()
|
|
297
|
+
while True:
|
|
298
|
+
response =process_received_data()
|
|
299
|
+
if response:
|
|
300
|
+
serial_lock.release() #释放线程锁
|
|
301
|
+
fcntl.flock(ser.fileno(), fcntl.LOCK_UN) # 释放进程锁
|
|
302
|
+
display_data = response[6:-3].decode(errors="ignore")
|
|
303
|
+
buf_clear()
|
|
304
|
+
# print(f"厂家信息: {display_data}")
|
|
305
|
+
return display_data
|
|
306
|
+
else:
|
|
307
|
+
if time.time() - start_time > 3:
|
|
308
|
+
print("读取超时")
|
|
309
|
+
buf_clear()
|
|
310
|
+
serial_lock.release() #释放线程锁
|
|
311
|
+
fcntl.flock(ser.fileno(), fcntl.LOCK_UN) # 释放进程锁
|
|
312
|
+
return None
|
|
313
|
+
|
|
314
|
+
"""读取硬件ID"""
|
|
315
|
+
def read_hardware_ID() -> Optional[bytes]:
|
|
316
|
+
result = os.popen("cat /proc/cpuinfo | grep Serial").read().strip()
|
|
317
|
+
if ":" in result:
|
|
318
|
+
return result.split(":")[1].strip()
|
|
319
|
+
return None
|
|
320
|
+
|
|
321
|
+
"""读取设备名称"""
|
|
322
|
+
def read_device_name() -> Optional[bytes]:
|
|
323
|
+
serial_lock.acquire() #获取线程锁
|
|
324
|
+
fcntl.flock(ser.fileno(), fcntl.LOCK_EX) # 进程锁,阻塞其他进程
|
|
325
|
+
write_data(READ_NAME_H, READ_NAME_L, None, False)
|
|
326
|
+
start_time = time.time()
|
|
327
|
+
while True:
|
|
328
|
+
response =process_received_data()
|
|
329
|
+
if response:
|
|
330
|
+
serial_lock.release() #释放线程锁
|
|
331
|
+
fcntl.flock(ser.fileno(), fcntl.LOCK_UN) # 释放进程锁
|
|
332
|
+
display_data = response[6:-3].decode(errors="ignore")
|
|
333
|
+
buf_clear()
|
|
334
|
+
# print(f"设备名称: {display_data}")
|
|
335
|
+
return display_data
|
|
336
|
+
else:
|
|
337
|
+
if time.time() - start_time > 3:
|
|
338
|
+
print("读取超时")
|
|
339
|
+
buf_clear()
|
|
340
|
+
serial_lock.release() #释放线程锁
|
|
341
|
+
fcntl.flock(ser.fileno(), fcntl.LOCK_UN) # 释放进程锁
|
|
342
|
+
return None
|
|
343
|
+
|
|
344
|
+
"""设置设备名称"""
|
|
345
|
+
def write_device_name(send_data: str) -> Optional[bytes]:
|
|
346
|
+
serial_lock.acquire() #获取线程锁
|
|
347
|
+
fcntl.flock(ser.fileno(), fcntl.LOCK_EX) # 进程锁,阻塞其他进程
|
|
348
|
+
data_bytes = send_data.encode('utf-8')
|
|
349
|
+
write_data(WRITE_NAME_H, WRITE_NAME_L, data_bytes, False)
|
|
350
|
+
start_time = time.time()
|
|
351
|
+
while True:
|
|
352
|
+
response =process_received_data()
|
|
353
|
+
if response:
|
|
354
|
+
serial_lock.release() #释放线程锁
|
|
355
|
+
fcntl.flock(ser.fileno(), fcntl.LOCK_UN) # 释放进程锁
|
|
356
|
+
display_data = response[6:-3].decode(errors="ignore")
|
|
357
|
+
buf_clear()
|
|
358
|
+
# print(f"设置状态: {display_data}")
|
|
359
|
+
return 0
|
|
360
|
+
else:
|
|
361
|
+
if time.time() - start_time > 3:
|
|
362
|
+
print("读取超时")
|
|
363
|
+
buf_clear()
|
|
364
|
+
serial_lock.release() #释放线程锁
|
|
365
|
+
fcntl.flock(ser.fileno(), fcntl.LOCK_UN) # 释放进程锁
|
|
366
|
+
return None
|
|
367
|
+
|
|
368
|
+
"""读取连接方式"""
|
|
369
|
+
def read_connected() -> Optional[bytes]:
|
|
370
|
+
serial_lock.acquire() #获取线程锁
|
|
371
|
+
fcntl.flock(ser.fileno(), fcntl.LOCK_EX) # 进程锁,阻塞其他进程
|
|
372
|
+
write_data(READ_CONNECT_H, READ_CONNECT_L, None, False)
|
|
373
|
+
start_time = time.time()
|
|
374
|
+
while True:
|
|
375
|
+
response =process_received_data()
|
|
376
|
+
if response:
|
|
377
|
+
serial_lock.release() #释放线程锁
|
|
378
|
+
fcntl.flock(ser.fileno(), fcntl.LOCK_UN) # 释放进程锁
|
|
379
|
+
display_data = response[6:-3].decode(errors="ignore")
|
|
380
|
+
buf_clear()
|
|
381
|
+
# print(f"连接方式: {display_data}")
|
|
382
|
+
return display_data
|
|
383
|
+
else:
|
|
384
|
+
if time.time() - start_time > 3:
|
|
385
|
+
print("读取超时")
|
|
386
|
+
buf_clear()
|
|
387
|
+
serial_lock.release() #释放线程锁
|
|
388
|
+
fcntl.flock(ser.fileno(), fcntl.LOCK_UN) # 释放进程锁
|
|
389
|
+
return None
|
|
390
|
+
|
|
391
|
+
"""读取电池电量百分比"""
|
|
392
|
+
def read_battery() -> Optional[bytes]:
|
|
393
|
+
sensor = cw2015.CW2015()
|
|
394
|
+
if sensor.init():
|
|
395
|
+
return sensor.get_soc(0)
|
|
396
|
+
else:
|
|
397
|
+
return None
|
|
398
|
+
|
|
399
|
+
###############################################################################读取传感器信息
|
|
400
|
+
|
|
401
|
+
"""读取外设连接情况"""
|
|
402
|
+
def read_peripheral() -> Optional[bytes]:
|
|
403
|
+
serial_lock.acquire() #获取线程锁
|
|
404
|
+
fcntl.flock(ser.fileno(), fcntl.LOCK_EX) # 进程锁,阻塞其他进程
|
|
405
|
+
write_data(READ_PERIPH_H, READ_PERIPH_L, None, False)
|
|
406
|
+
start_time = time.time()
|
|
407
|
+
while True:
|
|
408
|
+
response =process_received_data()
|
|
409
|
+
if response:
|
|
410
|
+
serial_lock.release() #释放线程锁
|
|
411
|
+
fcntl.flock(ser.fileno(), fcntl.LOCK_UN) # 释放进程锁
|
|
412
|
+
display_data = response[6:-3]
|
|
413
|
+
buf_clear()
|
|
414
|
+
# for x in display_data:
|
|
415
|
+
# print(f"{x:02X}", end=' ')
|
|
416
|
+
# print("\n")
|
|
417
|
+
return display_data
|
|
418
|
+
else:
|
|
419
|
+
if time.time() - start_time > 3:
|
|
420
|
+
print("读取超时")
|
|
421
|
+
buf_clear()
|
|
422
|
+
serial_lock.release() #释放线程锁
|
|
423
|
+
fcntl.flock(ser.fileno(), fcntl.LOCK_UN) # 释放进程锁
|
|
424
|
+
return None
|
|
425
|
+
|
|
426
|
+
"""单次操作外设"""
|
|
427
|
+
def single_operate_sensor(op_struct: bytes, block_time: float) -> Optional[bytes]:
|
|
428
|
+
serial_lock.acquire() #获取线程锁
|
|
429
|
+
fcntl.flock(ser.fileno(), fcntl.LOCK_EX) #进程锁,阻塞其他进程
|
|
430
|
+
write_data(SINGLE_OP_H, SINGLE_OP_L, op_struct, False)
|
|
431
|
+
start_time = time.time()
|
|
432
|
+
while True:
|
|
433
|
+
response =process_received_data()
|
|
434
|
+
if response:
|
|
435
|
+
serial_lock.release() #释放线程锁
|
|
436
|
+
fcntl.flock(ser.fileno(), fcntl.LOCK_UN) # 释放进程锁
|
|
437
|
+
display_data = response[6:-3]
|
|
438
|
+
buf_clear()
|
|
439
|
+
# for x in display_data:
|
|
440
|
+
# print(f"{x:02X}", end=' ')
|
|
441
|
+
# print("\n")
|
|
442
|
+
return display_data
|
|
443
|
+
else:
|
|
444
|
+
if time.time() - start_time > 2+block_time:
|
|
445
|
+
print("读取超时")
|
|
446
|
+
buf_clear()
|
|
447
|
+
serial_lock.release() #释放线程锁
|
|
448
|
+
fcntl.flock(ser.fileno(), fcntl.LOCK_UN) # 释放进程锁
|
|
449
|
+
return None
|
|
450
|
+
|
|
451
|
+
#P端口初始化释放
|
|
452
|
+
def P_port_init(port:bytes) -> Optional[bytes]:
|
|
453
|
+
servo_str=[0xA0, 0x0F, 0x00, 0xBE]
|
|
454
|
+
servo_str[0]=0XA0+port
|
|
455
|
+
time.sleep(0.005)
|
|
456
|
+
# response = single_operate_sensor(servo_str,0)
|
|
457
|
+
write_data(0X01, 0X02, servo_str)
|
|
458
|
+
# if response == None:
|
|
459
|
+
# return None
|
|
460
|
+
# else:
|
|
461
|
+
return 0
|
|
462
|
+
|
|
463
|
+
"""从机模式转换"""
|
|
464
|
+
def mode_change(send_data: str) -> Optional[bytes]:
|
|
465
|
+
serial_lock.acquire() #获取线程锁
|
|
466
|
+
fcntl.flock(ser.fileno(), fcntl.LOCK_EX) # 进程锁,阻塞其他进程
|
|
467
|
+
write_data(MODE_CHANGE_H, MODE_CHANGE_L, send_data, False)
|
|
468
|
+
start_time = time.time()
|
|
469
|
+
while True:
|
|
470
|
+
response =process_received_data()
|
|
471
|
+
if response:
|
|
472
|
+
serial_lock.release() #释放线程锁
|
|
473
|
+
fcntl.flock(ser.fileno(), fcntl.LOCK_UN) # 释放进程锁
|
|
474
|
+
display_data = response[6:-3]
|
|
475
|
+
# for x in display_data:
|
|
476
|
+
# print(f"{x:02X}", end=' ')
|
|
477
|
+
# print("\n")
|
|
478
|
+
return display_data
|
|
479
|
+
else:
|
|
480
|
+
if time.time() - start_time > 3:
|
|
481
|
+
print("读取超时")
|
|
482
|
+
buffer.clear()
|
|
483
|
+
serial_lock.release() #释放线程锁
|
|
484
|
+
fcntl.flock(ser.fileno(), fcntl.LOCK_UN) # 释放进程锁
|
|
485
|
+
return None
|
|
486
|
+
|
|
487
|
+
"""智能模式发送周期"""
|
|
488
|
+
def mode_change(send_data: str) -> Optional[bytes]:
|
|
489
|
+
serial_lock.acquire() #获取线程锁
|
|
490
|
+
fcntl.flock(ser.fileno(), fcntl.LOCK_EX) # 进程锁,阻塞其他进程
|
|
491
|
+
write_data(SEND_CYCLE_H, SEND_CYCLE_L, send_data, False)
|
|
492
|
+
start_time = time.time()
|
|
493
|
+
while True:
|
|
494
|
+
response =process_received_data()
|
|
495
|
+
if response:
|
|
496
|
+
serial_lock.release() #释放线程锁
|
|
497
|
+
fcntl.flock(ser.fileno(), fcntl.LOCK_UN) # 释放进程锁
|
|
498
|
+
display_data = response[6:-3]
|
|
499
|
+
# for x in display_data:
|
|
500
|
+
# print(f"{x:02X}", end=' ')
|
|
501
|
+
# print("\n")
|
|
502
|
+
return display_data
|
|
503
|
+
else:
|
|
504
|
+
if time.time() - start_time > 3:
|
|
505
|
+
print("读取超时")
|
|
506
|
+
buffer.clear()
|
|
507
|
+
serial_lock.release() #释放线程锁
|
|
508
|
+
fcntl.flock(ser.fileno(), fcntl.LOCK_UN) # 释放进程锁
|
|
509
|
+
return None
|
|
510
|
+
|
|
511
|
+
def shut_down():
|
|
512
|
+
write_data(0XFF, 0XFE)
|
|
513
|
+
time.sleep(0.5)
|
|
514
|
+
|
|
515
|
+
def power_button_detec() -> bytes:
|
|
516
|
+
serial_lock.acquire() #获取线程锁
|
|
517
|
+
fcntl.flock(ser.fileno(), fcntl.LOCK_EX) # 进程锁,阻塞其他进程
|
|
518
|
+
response =process_received_data()
|
|
519
|
+
if response:
|
|
520
|
+
receive_data = response[4:-3]
|
|
521
|
+
if receive_data[0]==0XFF and receive_data[1]==0XFD:
|
|
522
|
+
serial_lock.release() #释放线程锁
|
|
523
|
+
fcntl.flock(ser.fileno(), fcntl.LOCK_UN) # 释放进程锁
|
|
524
|
+
return 1
|
|
525
|
+
elif receive_data[0]==0XFF and receive_data[1]==0XFE:
|
|
526
|
+
serial_lock.release() #释放线程锁
|
|
527
|
+
fcntl.flock(ser.fileno(), fcntl.LOCK_UN) # 释放进程锁
|
|
528
|
+
return 2
|
|
529
|
+
else:
|
|
530
|
+
buffer.clear()
|
|
531
|
+
serial_lock.release() #释放线程锁
|
|
532
|
+
fcntl.flock(ser.fileno(), fcntl.LOCK_UN) # 释放进程锁
|
|
533
|
+
return 0
|
|
534
|
+
else:
|
|
535
|
+
serial_lock.release() #释放线程锁
|
|
536
|
+
fcntl.flock(ser.fileno(), fcntl.LOCK_UN) # 释放进程锁
|
|
537
|
+
return 0
|
|
538
|
+
|
|
539
|
+
def buf_clear():
|
|
540
|
+
#清空Python层缓冲区
|
|
541
|
+
buffer.clear()
|
|
542
|
+
frames_queue.clear()
|
|
543
|
+
#清空pyserial缓冲区
|
|
544
|
+
try:
|
|
545
|
+
# 尝试先读取所有已到达的数据
|
|
546
|
+
while ser.in_waiting > 0:
|
|
547
|
+
ser.read(ser.in_waiting)
|
|
548
|
+
# 然后重置输入缓冲区
|
|
549
|
+
ser.reset_input_buffer()
|
|
550
|
+
except Exception as e:
|
|
551
|
+
print(f"清空串口缓冲区时出错: {e}")
|
|
552
|
+
|
|
553
|
+
try:
|
|
554
|
+
fcntl.ioctl(ser.fileno(), termios.TCIOFLUSH)
|
|
555
|
+
except:
|
|
556
|
+
pass
|
|
557
|
+
|
|
558
|
+
|
|
559
|
+
"""H2-RCU初始化"""
|
|
560
|
+
def smartpi_init():
|
|
561
|
+
|
|
562
|
+
if is_lock_locked(serial_lock):
|
|
563
|
+
serial_lock.release() #释放线程锁
|
|
564
|
+
|
|
565
|
+
fcntl.flock(ser.fileno(), fcntl.LOCK_UN) # 释放进程锁
|
|
566
|
+
serial_lock.acquire() #获取线程锁
|
|
567
|
+
fcntl.flock(ser.fileno(), fcntl.LOCK_EX) # 进程锁,阻塞其他进程
|
|
568
|
+
uart3_init()
|
|
569
|
+
serial_lock.release()
|
|
570
|
+
fcntl.flock(ser.fileno(), fcntl.LOCK_UN) # 释放进程锁
|
|
571
|
+
|
|
572
|
+
servo.set_init(1)
|
|
573
|
+
servo.set_init(2)
|
|
574
|
+
servo.set_init(3)
|
|
575
|
+
servo.set_init(4)
|
|
576
|
+
servo.set_init(5)
|
|
577
|
+
servo.set_init(6)
|
|
578
|
+
motor.set_motor(1,0)
|
|
579
|
+
motor.set_motor(2,0)
|
|
580
|
+
motor.set_motor(3,0)
|
|
581
|
+
motor.set_motor(4,0)
|
|
582
|
+
motor.set_motor(5,0)
|
|
583
|
+
motor.set_motor(6,0)
|
|
584
|
+
servo.reset_encode(1)
|
|
585
|
+
servo.reset_encode(2)
|
|
586
|
+
servo.reset_encode(3)
|
|
587
|
+
servo.reset_encode(4)
|
|
588
|
+
servo.reset_encode(5)
|
|
589
|
+
servo.reset_encode(6)
|
|
590
|
+
motor.reset_motor_encoder(1)
|
|
591
|
+
motor.reset_motor_encoder(2)
|
|
592
|
+
motor.reset_motor_encoder(3)
|
|
593
|
+
motor.reset_motor_encoder(4)
|
|
594
|
+
motor.reset_motor_encoder(5)
|
|
595
|
+
motor.reset_motor_encoder(6)
|
|
596
|
+
light_sensor.turn_off(1)
|
|
597
|
+
light_sensor.turn_off(2)
|
|
598
|
+
light_sensor.turn_off(3)
|
|
599
|
+
light_sensor.turn_off(4)
|
|
600
|
+
light_sensor.turn_off(5)
|
|
601
|
+
light_sensor.turn_off(6)
|
|
602
|
+
led.set_color(1,0)
|
|
603
|
+
led.set_color(2,0)
|
|
604
|
+
led.set_color(3,0)
|
|
605
|
+
led.set_color(4,0)
|
|
606
|
+
led.set_color(5,0)
|
|
607
|
+
led.set_color(6,0)
|
|
608
|
+
P_port_init(1)
|
|
609
|
+
P_port_init(2)
|
|
610
|
+
P_port_init(3)
|
|
611
|
+
P_port_init(4)
|
|
612
|
+
P_port_init(5)
|
|
613
|
+
P_port_init(6)
|
|
614
|
+
|
|
615
|
+
if is_lock_locked(serial_lock):
|
|
616
|
+
serial_lock.release() #释放线程锁
|
|
617
|
+
fcntl.flock(ser.fileno(), fcntl.LOCK_UN) # 释放进程锁
|
|
618
|
+
|
smartpi/base_driver.pyc
CHANGED
|
Binary file
|
smartpi/camera.py
ADDED
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
# coding: utf-8
|
|
2
|
+
import cv2
|
|
3
|
+
import os
|
|
4
|
+
import time
|
|
5
|
+
import platform
|
|
6
|
+
|
|
7
|
+
class Camera:
|
|
8
|
+
def __init__(self, indexes=[0, 1, 2, 3], target_width=640, target_height=480):
|
|
9
|
+
self.cap = None
|
|
10
|
+
self.indexes = indexes
|
|
11
|
+
self.target_width = target_width
|
|
12
|
+
self.target_height = target_height
|
|
13
|
+
self.open_camera()
|
|
14
|
+
|
|
15
|
+
def open_camera(self):
|
|
16
|
+
"""打开摄像头(硬件加速+参数优化)"""
|
|
17
|
+
for idx in self.indexes:
|
|
18
|
+
try:
|
|
19
|
+
# 适配linux/Android的V4L2硬件加速(RK芯片优先)
|
|
20
|
+
if platform.system() == "Linux":
|
|
21
|
+
cap = cv2.VideoCapture(idx, cv2.CAP_V4L2)
|
|
22
|
+
# 尝试启用硬件加速(兼容不同OpenCV版本)
|
|
23
|
+
try:
|
|
24
|
+
# 对于较新版本的OpenCV
|
|
25
|
+
if hasattr(cv2, 'CAP_PROP_HW_ACCELERATION') and hasattr(cv2, 'VIDEO_ACCELERATION_ANY'):
|
|
26
|
+
cap.set(cv2.CAP_PROP_HW_ACCELERATION, cv2.VIDEO_ACCELERATION_ANY)
|
|
27
|
+
except AttributeError as ae:
|
|
28
|
+
print(f"硬件加速设置不支持,使用默认配置: {ae}")
|
|
29
|
+
else:
|
|
30
|
+
cap = cv2.VideoCapture(idx)
|
|
31
|
+
|
|
32
|
+
if cap.isOpened():
|
|
33
|
+
# 尝试设置分辨率
|
|
34
|
+
cap.set(cv2.CAP_PROP_FRAME_WIDTH, self.target_width)
|
|
35
|
+
cap.set(cv2.CAP_PROP_FRAME_HEIGHT, self.target_height)
|
|
36
|
+
|
|
37
|
+
# 获取实际设置的分辨率
|
|
38
|
+
actual_width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
|
|
39
|
+
actual_height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
|
|
40
|
+
|
|
41
|
+
print(f"摄像头 {idx} 已打开, 分辨率: {actual_width}x{actual_height}")
|
|
42
|
+
self.cap = cap
|
|
43
|
+
return True
|
|
44
|
+
except Exception as e:
|
|
45
|
+
print(f"尝试打开摄像头 {idx} 失败: {e}")
|
|
46
|
+
continue
|
|
47
|
+
|
|
48
|
+
print("无法打开任何摄像头")
|
|
49
|
+
return False
|
|
50
|
+
|
|
51
|
+
def read_frame(self):
|
|
52
|
+
"""读取一帧并自动处理错误"""
|
|
53
|
+
if not self.cap or not self.cap.isOpened():
|
|
54
|
+
return False, None
|
|
55
|
+
|
|
56
|
+
ret, frame = self.cap.read()
|
|
57
|
+
if not ret:
|
|
58
|
+
print("读取帧失败,尝试重新打开摄像头...")
|
|
59
|
+
self.release()
|
|
60
|
+
time.sleep(1)
|
|
61
|
+
if self.open_camera():
|
|
62
|
+
return self.read_frame()
|
|
63
|
+
return False, None
|
|
64
|
+
|
|
65
|
+
# 调整到目标分辨率
|
|
66
|
+
if frame.shape[1] != self.target_width or frame.shape[0] != self.target_height:
|
|
67
|
+
frame = cv2.resize(frame, (self.target_width, self.target_height))
|
|
68
|
+
|
|
69
|
+
return True, frame
|
|
70
|
+
|
|
71
|
+
def get_resolution(self):
|
|
72
|
+
"""获取当前分辨率"""
|
|
73
|
+
if self.cap and self.cap.isOpened():
|
|
74
|
+
return (
|
|
75
|
+
int(self.cap.get(cv2.CAP_PROP_FRAME_WIDTH)),
|
|
76
|
+
int(self.cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
|
|
77
|
+
)
|
|
78
|
+
return self.target_width, self.target_height
|
|
79
|
+
|
|
80
|
+
def release(self):
|
|
81
|
+
"""释放摄像头资源"""
|
|
82
|
+
if self.cap and self.cap.isOpened():
|
|
83
|
+
self.cap.release()
|
|
84
|
+
self.cap = None
|
smartpi/camera.pyc
CHANGED
|
Binary file
|