DeviceControl.py 35 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886
  1. import asyncio
  2. import serial.tools.list_ports
  3. import time, json
  4. from .SerialIns import SerialIns
  5. from utils.SingletonType import SingletonType
  6. from .BaseClass import BaseClass
  7. from sockets import ConnectionManager
  8. from collections import defaultdict
  9. import threading
  10. # mcu命令
  11. class DeviceControl(BaseClass,metaclass=SingletonType):
  12. lock = threading.Lock()
  13. def __init__(self, websocket_manager: ConnectionManager):
  14. super().__init__(websocket_manager)
  15. self.msg_type = "mcu"
  16. self.m_t = 1
  17. self._mcu_move_state = 0
  18. self.state_camera_motor = 3
  19. self.state_camera_steering = 3
  20. self.state_turntable_steering = 3
  21. self.state_overturn_steering = 3
  22. self.state_move_turntable_steering = 3
  23. self.last_from_mcu_move_respond_data = None
  24. self.camera_motor_speed = 0
  25. self.camera_motor_value = 0
  26. self.port_name = ""
  27. self.t_n = 0
  28. self.serial_ins = None
  29. self.connected_ports_dict = {} # 已连接的ports
  30. self.p_list = []
  31. self.temp_ports_dict = {}
  32. self.is_running = False
  33. self.connect_state = False
  34. self.device_name_dict = {
  35. "camera_steering": 0,
  36. "camera_high_motor": 1,
  37. "turntable_steering": 2,
  38. "overturn_steering": 3,
  39. "laser_position": 4,
  40. "buzzer": 5,
  41. "split": 6,
  42. "turntable_position_motor": 7,
  43. "mp3_player": 8,
  44. "mcu": 99,
  45. }
  46. # 最近的mcu基础信息,用于获取数据状态检查
  47. self.last_mcu_info_data = {
  48. "num": 0,
  49. "time": time.time(),
  50. "data": None,
  51. }
  52. # 最近的mcu的其他配置
  53. self.last_mcu_other_info_data = {
  54. "num": 0,
  55. "time": time.time(),
  56. "data": {},
  57. }
  58. self.command = {
  59. "to_device_move": 1, # 设备运动
  60. "to_init_device": 2, # 初始化设备
  61. "to_deal_other_device": 3, # 处理其他设备
  62. "get_all_info": 29, # 获取所有信息
  63. "set_deviation": 40, # 设置偏移量
  64. "get_deviation": 41, # 读取偏移量
  65. "signal_forwarding": 91, # 信号转发处理
  66. "signal_forwarding_return": 92, # 信号转发返回
  67. "get_other_info": 44, # 获取其他信息
  68. "open_rgb_led": 43, ## RGB灯的处理与通讯
  69. "set_other_info": 45, # 设置其他信息
  70. "query_remote_control_battery": 47, # 查询遥控器电量
  71. "set_turntable_mode": 48, # 设置转盘通讯方式 1、串口、2、无线、3 混合
  72. "stop_mcu": 93, # 停止运行mcu
  73. }
  74. # self.window = window
  75. self.last_push_time = defaultdict(float)
  76. self.is_running = False
  77. self.is_wait_connect = False # 等待链接
  78. self.send_data_queue = [] # 发送队列
  79. # self.lock = Lock()
  80. # 是否是刚进行完初始化;首次初始化,需要运动到指定第一个指定位置
  81. self.is_just_init_time = False
  82. # self.init()
  83. # ===========注册命令函数============
  84. self.deal_code_func_dict = {
  85. 29: self.get_from_mcu_base_info, # 获取基本情况
  86. 32: self.get_from_mcu_button, # 获取按键信息
  87. 42: self.get_from_mcu_deviation_info, # 获取偏移量信息
  88. 44: self.get_from_mcu_other_info, # 获取其他配置参数
  89. 90: self.get_from_mcu_connect_info, # 获取链接电脑信号
  90. 92: self.get_from_mcu_move_respond_data, # 获取MCU响应
  91. 100: self.print_mcu_error_data, # 打印下位机的错误内容
  92. }
  93. async def initDevice(self):
  94. if not self.is_running:
  95. self.sendSocketMessage(code=1,msg="mcu设备未连接,请先连接设备")
  96. return False
  97. self.serial_ins.clearn_flush()
  98. self.to_init_device_origin_point(device_name="mcu")
  99. print("MCU 开始循环~")
  100. while 1:
  101. await asyncio.sleep(0.01)
  102. if not self.serial_ins or not self.connect_state:
  103. break
  104. try:
  105. # print("mcu send_cmd")
  106. self.send_cmd()
  107. # time.sleep(0.01)
  108. self.get_basic_info_mcu()
  109. except BaseException as e:
  110. print("121231298908", e)
  111. break
  112. self.is_running = False
  113. self.connect_state = False
  114. print("MCU 循环退出~")
  115. # self.sign_data.emit(
  116. # {"_type": "show_info", "plugins_mode": "mcu", "data": "MCU 连接失败"}
  117. # )
  118. message = {"_type": "show_info", "plugins_mode": "mcu", "data": "MCU 连接失败"}
  119. self.sendSocketMessage(code=1, msg="MCU 连接失败", data=message)
  120. self.close_connect()
  121. def stop_mcu(self):
  122. buf = [self.command["stop_mcu"]]
  123. buf.extend(self.encapsulation_data(data=1, len_data=1))
  124. self.add_send_data_queue(buf)
  125. # 设置转盘通讯方式 1、串口、2、无线、3 混合
  126. def to_set_turntable_mode(self, mode=1):
  127. buf = [self.command["set_turntable_mode"]]
  128. buf.extend(self.encapsulation_data(data=mode, len_data=1))
  129. self.add_send_data_queue(buf)
  130. def query_remote_control_battery(self):
  131. '''查询遥控器电量'''
  132. buf = [self.command["query_remote_control_battery"]]
  133. buf.extend(self.encapsulation_data(data=1, len_data=1))
  134. buf.extend(self.encapsulation_data(data=1, len_data=1))
  135. buf.extend(self.encapsulation_data(data=1, len_data=1))
  136. self.add_send_data_queue(buf)
  137. def encapsulation_data(self, data, len_data, data_magnification=1):
  138. # data_magnification 数据放大倍数,或缩小倍数,默认为1
  139. data = int(data * data_magnification)
  140. if len_data == 1:
  141. return [0xFF & data]
  142. elif len_data == 2:
  143. return [0xFF & data >> 8, 0xFF & data]
  144. elif len_data == 4:
  145. return [0xFF & data >> 24, 0xFF & data >> 16, 0xFF & data >> 8, 0xFF & data]
  146. def open_rgb_led(
  147. self,
  148. color_name,
  149. led_command=1,
  150. brightness=80,
  151. enable=True,
  152. mode="loop",
  153. times=2,
  154. interval=0.1,
  155. ):
  156. color_name_value = {
  157. "红色": (156, 6, 3),
  158. "黄色": (255, 206, 25),
  159. "绿色": (0, 128, 0),
  160. "蓝色": (0, 25, 255),
  161. "白色": (255, 250, 227),
  162. }
  163. if color_name in color_name_value:
  164. buf = [self.command["open_rgb_led"]]
  165. buf.append(1 if enable else 0)
  166. buf.append(led_command)
  167. buf.extend(color_name_value[color_name])
  168. buf.extend(
  169. [
  170. brightness,
  171. 1 if mode == "loop" else 2,
  172. times,
  173. int(interval * 10),
  174. ]
  175. )
  176. self.add_send_data_queue(buf)
  177. def get_deviation(self):
  178. # 发送获取偏移量
  179. data = [self.command["get_deviation"], 1]
  180. self.add_send_data_queue(data)
  181. # if self.serial_ins:
  182. # self.serial_ins.write_cmd(data)
  183. print("发送获取偏移量")
  184. def get_other_info(self):
  185. # 发送获取偏移量
  186. data = [self.command["get_other_info"], 1]
  187. self.add_send_data_queue(data)
  188. print("发送获取其他信息")
  189. def add_send_data_queue(self, data):
  190. self.lock.acquire()
  191. if self.serial_ins:
  192. # print("send_data_queue append :{}".format(data))
  193. self.send_data_queue.append(data)
  194. self.lock.release()
  195. def send_cmd(self):
  196. self.lock.acquire()
  197. if self.send_data_queue:
  198. data = self.send_data_queue.pop(0)
  199. self.serial_ins.write_cmd(data)
  200. else:
  201. self.t_n += 1
  202. # 加大发送获取基础数据的时间间隔
  203. # 默认为0.01秒一个循环,每隔1.5秒发送数据
  204. if self.t_n > 150:
  205. self.t_n = 0
  206. data = [self.command["get_all_info"], 1]
  207. self.serial_ins.write_cmd(data)
  208. self.lock.release()
  209. def print_mcu_error_data(self, receive_data):
  210. # 扫码数据
  211. try:
  212. data = receive_data[1:].decode()
  213. print("115 print_mcu_error_data:", data)
  214. except BaseException as e:
  215. print("117 error {}".format(e))
  216. return
  217. def get_from_mcu_move_respond_data(self, receive_data):
  218. self.last_from_mcu_move_respond_data = receive_data
  219. def get_from_mcu_connect_info(self, receive_data):
  220. connect_flag = receive_data[1]
  221. device_id = receive_data[2]
  222. try:
  223. mcu_has_been_set = receive_data[6] # 设备是否有初始化 ,1 表示已初始化
  224. except:
  225. mcu_has_been_set = 99 # 未知状态
  226. # self.self_sign.emit({"type": "connect_sign", "data": connect_flag})
  227. message = {"type": "connect_sign", "data": connect_flag}
  228. self.sendSocketMessage(msg="接收链接信息", data=message)
  229. print("接收链接信息")
  230. return
  231. def to_init_device_origin_point(self, device_name, is_force=True):
  232. device_id = self.device_name_dict[device_name]
  233. cmd = 2
  234. data = [cmd, device_id, 0 if is_force is False else 1]
  235. self.open_rgb_led(color_name="红色")
  236. self.add_send_data_queue(data)
  237. if device_name == "mcu":
  238. # 重置初始化标记为 从未初始化
  239. self.is_just_init_time = False
  240. return True
  241. def get_basic_info_mcu(self):
  242. receive_data = self.serial_ins.read_cmd(out_time=1)
  243. if receive_data is False:
  244. print("------------------------------------------------4657564654")
  245. self.connect_state = False
  246. return False
  247. if not receive_data:
  248. return
  249. # print("receive_data")
  250. # 数据 结构 command,按命令解析
  251. # command 0(9) 相机高度1-2 相机角度3-4 转盘角度5-6 灯光状态7 激光指示器状态8,运行状态9
  252. command = receive_data[0]
  253. if command in self.deal_code_func_dict:
  254. self.deal_code_func_dict[command](receive_data)
  255. def get_from_mcu_button(self, receive_data):
  256. button_name = receive_data[1]
  257. self.deal_mcu_button(button_name)
  258. def deal_mcu_button(self, button_name):
  259. # 防止重复点击
  260. s = time.time()
  261. if s - self.last_push_time[button_name] > 0.1:
  262. self.last_push_time[button_name] = s
  263. # print("button_name", button_name)
  264. else:
  265. self.last_push_time[button_name] = s
  266. return
  267. if button_name == 1:
  268. # 自动执行全部
  269. # self.sign_data.emit(
  270. # {"_type": "mcu_button", "plugins_mode": "mcu", "data": "todo_1"}
  271. # )
  272. message = {"_type": "mcu_button", "plugins_mode": "mcu", "data": "todo_1"}
  273. self.sendSocketMessage(code=0, msg="", data=message)
  274. if button_name == 2:
  275. # self.sign_data.emit(
  276. # {"_type": "mcu_button", "plugins_mode": "mcu", "data": "todo_2"}
  277. # )
  278. message = {"_type": "mcu_button", "plugins_mode": "mcu", "data": "todo_2"}
  279. self.sendSocketMessage(code=0, msg="", data=message)
  280. if button_name == 3:
  281. # self.sign_data.emit(
  282. # {"_type": "mcu_button", "plugins_mode": "mcu", "data": "todo_3"}
  283. # )
  284. message = {"_type": "mcu_button", "plugins_mode": "mcu", "data": "todo_3"}
  285. self.sendSocketMessage(code=0, msg="", data=message)
  286. # 获取偏移量信息
  287. def get_from_mcu_deviation_info(self, receive_data):
  288. if len(receive_data) == 18:
  289. camera_high_motor_deviation_dir = receive_data[1]
  290. camera_high_motor_deviation = receive_data[2] << 8 | receive_data[3]
  291. camera_high_motor_deviation = (
  292. camera_high_motor_deviation * -1
  293. if camera_high_motor_deviation_dir == 0
  294. else camera_high_motor_deviation
  295. )
  296. camera_steering_deviation_dir = receive_data[4]
  297. camera_steering_deviation = (receive_data[5] << 8 | receive_data[6]) * 0.1
  298. camera_steering_deviation = (
  299. camera_steering_deviation * -1
  300. if camera_steering_deviation_dir == 0
  301. else camera_steering_deviation
  302. )
  303. turntable_steering_deviation_dir = receive_data[7]
  304. turntable_steering_deviation = (
  305. receive_data[8] << 8 | receive_data[9]
  306. ) * 0.1
  307. turntable_steering_deviation = (
  308. turntable_steering_deviation * -1
  309. if turntable_steering_deviation_dir == 0
  310. else turntable_steering_deviation
  311. )
  312. overturn_steering_middle_dir = receive_data[10]
  313. overturn_steering_middle = (receive_data[11] << 8 | receive_data[12]) * 0.1
  314. overturn_steering_middle = (
  315. overturn_steering_middle * -1
  316. if overturn_steering_middle_dir == 0
  317. else overturn_steering_middle
  318. )
  319. overturn_steering_high_dir = receive_data[13]
  320. overturn_steering_high = (receive_data[14] << 8 | receive_data[15]) * 0.1
  321. overturn_steering_high = (
  322. overturn_steering_middle * -1
  323. if overturn_steering_high_dir == 0
  324. else overturn_steering_high
  325. )
  326. overturn_steering_up_speed = receive_data[16]
  327. overturn_steering_down_speed = receive_data[17]
  328. # self.sign_data.emit(
  329. # {
  330. # "_type": "get_deviation_data",
  331. # "plugins_mode": "mcu",
  332. # "data": {
  333. # "camera_high_motor_deviation": camera_high_motor_deviation,
  334. # "camera_steering_deviation": camera_steering_deviation,
  335. # "turntable_steering_deviation": turntable_steering_deviation,
  336. # "overturn_steering_middle": overturn_steering_middle,
  337. # "overturn_steering_high": overturn_steering_high,
  338. # "overturn_steering_up_speed": overturn_steering_up_speed,
  339. # "overturn_steering_down_speed": overturn_steering_down_speed,
  340. # },
  341. # }
  342. # )
  343. message = {
  344. "_type": "get_deviation_data",
  345. "plugins_mode": "mcu",
  346. "data": {
  347. "camera_high_motor_deviation": camera_high_motor_deviation,
  348. "camera_steering_deviation": camera_steering_deviation,
  349. "turntable_steering_deviation": turntable_steering_deviation,
  350. "overturn_steering_middle": overturn_steering_middle,
  351. "overturn_steering_high": overturn_steering_high,
  352. "overturn_steering_up_speed": overturn_steering_up_speed,
  353. "overturn_steering_down_speed": overturn_steering_down_speed,
  354. },
  355. }
  356. self.sendSocketMessage(msg="接收偏移量信息", data=message)
  357. print("接收偏移量信息")
  358. return
  359. # 获取其他信息
  360. def get_from_mcu_other_info(self, receive_data):
  361. is_auto_send_base_info = self.get_data_from_receive_data(
  362. receive_data=receive_data, start=1, len_data=1
  363. )
  364. is_move_retry = self.get_data_from_receive_data(
  365. receive_data=receive_data, start=2, len_data=1
  366. )
  367. is_data_response = self.get_data_from_receive_data(
  368. receive_data=receive_data, start=3, len_data=1
  369. )
  370. low_speed = self.get_data_from_receive_data(
  371. receive_data=receive_data, start=4, len_data=2
  372. )
  373. is_test = self.get_data_from_receive_data(
  374. receive_data=receive_data, start=6, len_data=1
  375. )
  376. to_init_mode = self.get_data_from_receive_data(
  377. receive_data=receive_data, start=7, len_data=1
  378. )
  379. turntable_move_to_init_mode = self.get_data_from_receive_data(
  380. receive_data=receive_data, start=8, len_data=1
  381. )
  382. led_count = self.get_data_from_receive_data(
  383. receive_data=receive_data, start=9, len_data=2
  384. )
  385. turntable_steering_angle_ratio = self.get_data_from_receive_data(
  386. receive_data=receive_data, start=11, len_data=2
  387. )
  388. is_manual_check = self.get_data_from_receive_data(
  389. receive_data=receive_data, start=13, len_data=1
  390. )
  391. camera_steering_angle_ratio = self.get_data_from_receive_data(
  392. receive_data=receive_data, start=14, len_data=4
  393. )
  394. is_auto_motor_to_disable = self.get_data_from_receive_data(
  395. receive_data=receive_data, start=18, len_data=1
  396. )
  397. diff_dir = self.get_data_from_receive_data(
  398. receive_data=receive_data, start=19, len_data=1
  399. )
  400. is_auto_send_pos_info = self.get_data_from_receive_data(
  401. receive_data=receive_data, start=20, len_data=1
  402. )
  403. is_dog = self.get_data_from_receive_data(
  404. receive_data=receive_data, start=21, len_data=1
  405. )
  406. has_been_set_motor_config = self.get_data_from_receive_data(
  407. receive_data=receive_data, start=22, len_data=1
  408. )
  409. self.last_mcu_other_info_data["data"] = {
  410. "is_auto_send_base_info": is_auto_send_base_info,
  411. "is_move_retry": is_move_retry,
  412. "is_data_response": is_data_response,
  413. "low_speed": low_speed,
  414. "is_test": is_test,
  415. "to_init_mode": to_init_mode,
  416. "turntable_move_to_init_mode": turntable_move_to_init_mode,
  417. "led_count": led_count,
  418. "turntable_steering_angle_ratio": turntable_steering_angle_ratio,
  419. "is_manual_check": is_manual_check,
  420. "camera_steering_angle_ratio": camera_steering_angle_ratio,
  421. "is_auto_motor_to_disable": is_auto_motor_to_disable,
  422. "diff_dir": diff_dir,
  423. "is_auto_send_pos_info": is_auto_send_pos_info,
  424. "is_dog": is_dog,
  425. "has_been_set_motor_config": has_been_set_motor_config,
  426. }
  427. self.last_mcu_other_info_data["time"] = time.time()
  428. self.last_mcu_other_info_data["num"] += 1
  429. for k, v in self.last_mcu_other_info_data["data"].items():
  430. print("k:{},v:{}".format(k, v))
  431. def get_data_from_receive_data(
  432. self, receive_data, start, len_data, data_magnification=1
  433. ):
  434. # data_magnification 数据放大倍数,或缩小倍数,默认为1
  435. try:
  436. if len_data == 1:
  437. data = receive_data[start]
  438. return data * data_magnification
  439. elif len_data == 2:
  440. data = receive_data[start] << 8 | receive_data[start + 1]
  441. return data * data_magnification
  442. elif len_data == 4:
  443. data = (
  444. receive_data[start] << 24
  445. | receive_data[start + 1] << 16
  446. | receive_data[start + 2] << 8
  447. | receive_data[start + 3]
  448. )
  449. return data * data_magnification
  450. return None
  451. except:
  452. return None
  453. def get_from_mcu_base_info(self, receive_data):
  454. # 数据缓存
  455. self.last_mcu_info_data["time"] = time.time()
  456. self.last_mcu_info_data["num"] += 1
  457. # print("last_mcu_info_data:{}".format(self.last_mcu_info_data["time"]))
  458. self.state_camera_motor = 3
  459. self.state_camera_steering = 3
  460. self.state_turntable_steering = 3
  461. self.state_overturn_steering = 3
  462. self.state_move_turntable_steering = 3
  463. if len(receive_data) == 7:
  464. self.m_t = 1
  465. laser_state = receive_data[1]
  466. self.state_camera_motor = receive_data[2]
  467. self.state_camera_steering = receive_data[3]
  468. self.state_turntable_steering = receive_data[4]
  469. self.state_overturn_steering = receive_data[5]
  470. flag = receive_data[6]
  471. message = {
  472. "_type": "show_mcu_info",
  473. "plugins_mode": "mcu",
  474. "data": "激光状态;{laser_state},相机高度状态:{state_camera_motor},相机角度状态:{state_camera_steering},转盘状态:{state_turntable_steering},翻板状态:{state_overturn_steering},flag:{flag}".format(
  475. laser_state=laser_state,
  476. state_camera_motor=self.state_camera_motor,
  477. state_camera_steering=self.state_camera_steering,
  478. state_turntable_steering=self.state_turntable_steering,
  479. state_overturn_steering=self.state_overturn_steering,
  480. flag=flag,
  481. ),
  482. "data_state": {
  483. "state_camera_motor": self.state_camera_motor,
  484. "state_camera_steering": self.state_camera_steering,
  485. "state_turntable_steering": self.state_turntable_steering,
  486. "state_overturn_steering": self.state_overturn_steering,
  487. },
  488. }
  489. self.sendSocketMessage(msg="获取mcu设备运行状态信息", data=message)
  490. # print("转盘:{},时间:{}".format(self.state_turntable_steering, time.time()))
  491. if len(receive_data) == 8:
  492. self.m_t = 2
  493. laser_state = receive_data[1]
  494. self.state_camera_motor = receive_data[2]
  495. self.state_camera_steering = receive_data[3]
  496. self.state_turntable_steering = receive_data[4]
  497. self.state_overturn_steering = receive_data[5]
  498. self.state_move_turntable_steering = receive_data[6]
  499. flag = receive_data[7]
  500. message = {
  501. "_type": "show_mcu_info",
  502. "plugins_mode": "mcu",
  503. "data": "激光状态;{laser_state},相机高度状态:{state_camera_motor},相机角度状态:{state_camera_steering},转盘状态:{state_turntable_steering},转盘前后移动状态:{state_move_turntable_steering},翻板状态:{state_overturn_steering},flag:{flag}".format(
  504. laser_state=laser_state,
  505. state_camera_motor=self.state_camera_motor,
  506. state_camera_steering=self.state_camera_steering,
  507. state_turntable_steering=self.state_turntable_steering,
  508. state_overturn_steering=self.state_overturn_steering,
  509. state_move_turntable_steering=self.state_move_turntable_steering,
  510. flag=flag,
  511. ),
  512. "data_state": {
  513. "state_camera_motor": self.state_camera_motor,
  514. "state_camera_steering": self.state_camera_steering,
  515. "state_turntable_steering": self.state_turntable_steering,
  516. "state_overturn_steering": self.state_overturn_steering,
  517. "state_move_turntable_steering": self.state_move_turntable_steering,
  518. },
  519. }
  520. self.sendSocketMessage(msg="获取mcu设备运行状态信息", data=message)
  521. # 检查是否成功初始化
  522. if self.is_just_init_time is False:
  523. if self.mcu_move_state == 2:
  524. self.is_just_init_time = True
  525. print("is_just_init_time")
  526. message = {
  527. "_type": "is_just_init_time",
  528. "plugins_mode": "mcu",
  529. "data": "",
  530. }
  531. self.sendSocketMessage(msg="检查设备初始化", data=message)
  532. return
  533. # def init(self, sign_data):
  534. # if sign_data["type"] == "connect_sign":
  535. # if sign_data["data"] == 0:
  536. # self.is_running = False
  537. # else:
  538. # self.is_running = True
  539. def scan_serial_port(self) -> dict:
  540. # 获取所有可用串口列表
  541. ports_dict = {}
  542. ports = serial.tools.list_ports.comports()
  543. # 遍历所有端口并打印信息
  544. for port in ports:
  545. if "CH340" in port.description:
  546. ports_dict[port.name] = {
  547. "name": port.name,
  548. "device": port.device,
  549. "description": port.description,
  550. "hwid": port.hwid,
  551. "manufacturer": port.manufacturer,
  552. "product": port.product,
  553. "serial_number": port.serial_number,
  554. }
  555. if len(ports_dict) <= 0:
  556. return {}
  557. return ports_dict
  558. def remove_port(self, port_name):
  559. """移除串口"""
  560. print("remove", port_name)
  561. data = {
  562. "_type": "remove_port",
  563. "plugins_mode": "auto_select_com",
  564. "data": {"port_name": port_name},
  565. }
  566. self.sendSocketMessage(1, "串口被移除", data)
  567. def add_port_by_linkage(self, port_name):
  568. # port_value :串口基础信息
  569. # todo 根据prot_value 信息自动进行连接
  570. print("add", port_name)
  571. # 对没有连接的设备进行尝试连接
  572. message_data = {
  573. "_type": "show_info",
  574. "plugins_mode": "auto_select_com",
  575. "data": {"text": "开始识别接口:{}".format(port_name)},
  576. }
  577. self.sendSocketMessage(msg="开始识别接口:{}".format(port_name), data=message_data)
  578. time.sleep(1)
  579. """
  580. 步骤:
  581. 1、进行临时连接,并发送命令,成功后,自动连接对应设备
  582. """
  583. try:
  584. # 尝试使用115200波特率链接
  585. serial_handle = serial.Serial(port=port_name, baudrate=115200, timeout=0.5)
  586. except:
  587. message_data = {
  588. "_type": "show_info",
  589. "plugins_mode": "auto_select_com",
  590. "data": {"text": "串口:{} 被占用,或无法识别".format(port_name)},
  591. }
  592. self.sendSocketMessage(
  593. 1,
  594. msg="串口:{} 被占用,或无法识别".format(port_name).format(port_name),
  595. data=message_data,
  596. )
  597. print("串口:{} 被占用".format(port_name))
  598. return
  599. time.sleep(2)
  600. print("开始发送命令")
  601. data = [90, 1]
  602. try:
  603. serial_handle.flushInput() # 尝试重置输入缓冲区
  604. except serial.SerialTimeoutException:
  605. print("超时错误:无法在规定时间内重置输入缓冲区。")
  606. self.sendSocketMessage(
  607. 1,
  608. msg="超时错误:无法在规定时间内重置输入缓冲区。",
  609. data=None,
  610. )
  611. serial_handle.close()
  612. return
  613. print("尝试写入数据")
  614. buf = bytearray(b"")
  615. buf.extend([0x55, 0x55, (0xFF & len(data))])
  616. buf.extend(data)
  617. buf.extend([0xFF & ~sum(data)])
  618. try:
  619. self.receive_data = b""
  620. serial_handle.write(buf)
  621. except serial.SerialTimeoutException:
  622. print("写入数据错误")
  623. serial_handle.close()
  624. return
  625. time.sleep(0.3)
  626. print("尝试接收命令")
  627. receive_data = self.read_cmd(serial_handle)
  628. device_id = 0
  629. if receive_data:
  630. print("receive_data", receive_data)
  631. if receive_data[0] == 90:
  632. connect_flag = receive_data[1]
  633. device_id = receive_data[2]
  634. print("关闭串口:{}".format(port_name))
  635. serial_handle.close()
  636. if device_id > 0:
  637. if device_id == 1:
  638. self.to_connect_com(port_name)
  639. message_data = {
  640. "_type": "show_info",
  641. "plugins_mode": "auto_select_com",
  642. "data": {"text": "MCU开始连接"},
  643. }
  644. self.sendSocketMessage(
  645. msg="MCU开始连接",
  646. data=message_data,
  647. )
  648. self.connected_ports_dict[port_name] = "MCU"
  649. message_data = {
  650. "_type": "select_port_name",
  651. "plugins_mode": "auto_select_com",
  652. "data": {
  653. "device_name": "mcu" if device_id == 1 else "remote_control",
  654. "port_name": port_name,
  655. },
  656. }
  657. self.sendSocketMessage(
  658. msg="MCU连接成功",
  659. data=message_data,
  660. )
  661. else:
  662. print("串口无法识别")
  663. # 走其他途径处理
  664. # 检查当前MCU链接是否正常
  665. # 正常跳过;记录为其他列表
  666. # 不正常进行尝试连接
  667. # 连接不上,记录为其他列表
  668. def to_connect_com(self, port_name):
  669. # 关闭串口
  670. print("to_connect_com", port_name)
  671. self.close_connect()
  672. time.sleep(0.3)
  673. self.connect_state = False
  674. try:
  675. self.serial_ins = SerialIns(port_name=port_name, baud=115200, timeout=0.1)
  676. if not self.serial_ins.serial_handle:
  677. message_data= {
  678. "_type": "show_info",
  679. "plugins_mode": "mcu",
  680. "data": "MCU 打开串口失败",
  681. }
  682. self.sendSocketMessage(
  683. msg="MCU 打开串口失败",
  684. data=message_data,
  685. )
  686. self.serial_ins = None
  687. self.connect_state = False
  688. return False
  689. except:
  690. message_data={
  691. "_type": "show_info",
  692. "plugins_mode": "mcu",
  693. "data": "MCU 打开串口失败",
  694. }
  695. self.sendSocketMessage(
  696. msg="MCU 打开串口失败",
  697. data=message_data,
  698. )
  699. self.serial_ins = None
  700. self.connect_state = False
  701. return False
  702. message_data={"_type": "show_info", "plugins_mode": "mcu", "data": "MCU 开始连接"}
  703. self.sendSocketMessage(
  704. msg="MCU 开始连接",
  705. data=message_data,
  706. )
  707. # =======================发送连接请求=================================
  708. cmd = 90
  709. data = [cmd, 1]
  710. print("405 发送 连接请求 -----------------------------------------")
  711. print(self.serial_ins)
  712. # self.serial_ins.clearn_flush()
  713. self.serial_ins.write_cmd(data)
  714. # 延迟接收数据
  715. time.sleep(0.3)
  716. receive_data = self.serial_ins.read_cmd(out_time=1)
  717. if receive_data:
  718. print(
  719. "409 receive_data--90:{}".format(self.change_hex_to_int(receive_data))
  720. )
  721. if receive_data:
  722. # receive_data[2]=1 表示为MCU设备编号
  723. if receive_data[0] == 90 and receive_data[2] == 1:
  724. connect_flag = receive_data[1]
  725. # 是否有初始化
  726. try:
  727. mcu_has_been_set = receive_data[
  728. 6
  729. ] # 设备是否有初始化 ,1 表示已初始化
  730. except:
  731. mcu_has_been_set = 99 # 未知状态
  732. print("MCU初始化信息{}".format(mcu_has_been_set))
  733. message_data = {
  734. "_type": "show_info",
  735. "plugins_mode": "mcu",
  736. "data": "MCU 已连接",
  737. }
  738. self.sendSocketMessage(
  739. msg="MCU 已连接",
  740. data=message_data,
  741. )
  742. self.connect_state = True
  743. self.is_running = True
  744. print("MCU 已连接")
  745. self.port_name = port_name
  746. return
  747. print("MCU 连接失败")
  748. message_data = {
  749. "_type": "show_info",
  750. "plugins_mode": "mcu",
  751. "data": "MCU 连接失败",
  752. }
  753. self.sendSocketMessage(
  754. msg="MCU 连接失败",
  755. data=message_data,
  756. )
  757. self.close_connect()
  758. def close_connect(self):
  759. self.port_name = ""
  760. if self.serial_ins:
  761. self.serial_ins.close_serial_port()
  762. self.is_running = False
  763. self.connect_state = False
  764. self.connected_ports_dict = {} # 已连接的ports
  765. self.p_list = []
  766. self.temp_ports_dict = {}
  767. print("关闭MCU")
  768. @property
  769. def mcu_move_state(self):
  770. if self.m_t == 1:
  771. if (
  772. self.state_camera_motor == 2
  773. and self.state_camera_steering == 2
  774. and self.state_turntable_steering == 2
  775. and self.state_overturn_steering == 2
  776. ):
  777. self._mcu_move_state = 2
  778. else:
  779. self._mcu_move_state = 1
  780. else:
  781. if (
  782. self.state_camera_motor == 2
  783. and self.state_camera_steering == 2
  784. and self.state_turntable_steering == 2
  785. and self.state_overturn_steering == 2
  786. and self.state_move_turntable_steering == 2
  787. ):
  788. self._mcu_move_state = 2
  789. else:
  790. self._mcu_move_state = 1
  791. # self._mcu_move_state = 2
  792. return self._mcu_move_state
  793. async def checkMcuConnection(device_ctrl: DeviceControl):
  794. if device_ctrl.is_running == True:
  795. message = {
  796. "_type": "select_port_name",
  797. "plugins_mode": "auto_select_com",
  798. "data": device_ctrl.temp_ports_dict,
  799. }
  800. device_ctrl.sendSocketMessage(code=0, msg="MCU连接成功", data=message)
  801. return
  802. """实时检测串口是否连接"""
  803. while True:
  804. await asyncio.sleep(0.5)
  805. ports_dict = device_ctrl.scan_serial_port()
  806. device_ctrl.temp_ports_dict = ports_dict
  807. if not ports_dict:
  808. # 全部清空 移除所有串口
  809. if device_ctrl.p_list:
  810. _p = device_ctrl.p_list.pop()
  811. device_ctrl.remove_port(_p)
  812. print("串口未连接,请检查")
  813. device_ctrl.sendSocketMessage(code=1, msg="串口未连接,请检查")
  814. continue
  815. if ports_dict:
  816. for index, _i in enumerate(device_ctrl.p_list):
  817. if _i not in ports_dict:
  818. _p = device_ctrl.p_list.pop(index)
  819. device_ctrl.remove_port(_p)
  820. for _port_name, _port_value in ports_dict.items():
  821. if _port_name not in device_ctrl.p_list:
  822. try:
  823. device_ctrl.p_list.append(_port_name)
  824. device_ctrl.add_port_by_linkage(_port_name)
  825. except BaseException as e:
  826. print("串口不存在{} {}".format(_port_name, e))