Genymotion添加devices时出现Connection timeout occurred的解决办法

Genymotion添加devices时如图的错误:这里写图片描述
解决办法:
打开C:\Users[你的名字]\AppData\Local\Genymobile\genymotion.log日志文件(AppData文件夹是隐藏的,要显示隐藏才能看到哦)。在日志的最后面找到类似
Downloading file "http://files2.genymotion.com/dists/4.1.1/ova/genymotion_vbox86p_4.1.1_151117_133208.ova
其中http://files2.genymotion.com/dists......就是下载地址,复制到浏览器或用第三方下载工具下载该文件。
下载好后copy 到C:\Users[你的字]\AppData\Local\Genymobile\Genymotion\ova文件夹下。重复之前的操作就ok了。
如果没有找到http://files2.genymotion.com/dists......的解决办法:
其实办法和上面的一样,只是下载地址需要自己拼接。下载地址的格式如下:

http://files2.genymotion.com/dists/版本号/ova/文件名

把版本号和文件名替换掉就可以了。
这里写图片描述
版本号替换成你所选的。如5.0.0
文件名:找到

# -------------------------------------- # Created by Milo on 2025/3/18 # Project: app_maintain # Desc: 纯蓝牙连接 # -------------------------------------- import traceback from asyncio import Event from threading import Thread from typing import Union from PyQt6.QtCore import QThread from bleak import BleakClient, BleakScanner, BLEDevice from bleak.exc import BleakError import asyncio import logging from customer_blue.include.basealgorithm import decimal_to_hex, get_high_low from customer_blue.include.protobuf_msg import MessagePB from customer_blue.include.seting import logger from customer_blue.include.signalmanage import MainSignal BLUE_SERVICE_UUID = "0000ffff-0000-1000-8000-00805f9b34fb" BLUE_WRITE_CHAR_UUID = "0000ff01-0000-1000-8000-00805f9b34fb" BLUE_NOTIF_CHAR_UUID = "0000ff02-0000-1000-8000-00805f9b34fb" BLUE_NOTIF_DESC_UUID = "00002902-0000-1000-8000-00805f9b34fb" class StableBleakClient: def __init__(self, device_name=None, device_address=None, timeout=20.0, retries=3, heartbeat_interval=10.0): """ 稳定的BLE客户端封装类 参数: device_name: 目标设备名称 (优先使用) device_address: 目标设备MAC地址 timeout: 连接超间(秒) retries: 最大重连次数 heartbeat_interval: 心跳检测间隔(秒) """ self.device_name = device_name self.device_address = device_address self.timeout = timeout self.max_retries = retries self.heartbeat_interval = heartbeat_interval self.client = None self.heartbeat_task = None self.connected = False self.alive_callbacks = None self.main_disconnected_callbacks = None self.notification_callbacks = {} # 存储通知回调 async def connect(self): """建立稳定连接,包含重试机制和信号强度筛选""" if not self.device_name and not self.device_address: raise ValueError("必须提供device_name或device_address") device = None attempts = 0 while attempts < self.max_retries and not self.connected: attempts += 1 try: # 通过扫描查找设备 if self.device_name: device = await self._find_device_by_name() elif self.device_address: device = await self._find_device_by_address() if not device: print(f"未找到设备,重试 {attempts}/{self.max_retries}") await asyncio.sleep(2) continue # 创建客户端并连接 self.client = BleakClient(device.address, timeout=self.timeout, disconnected_callback=self._handle_disconnect) await self.client.connect() # 设置断开回调 # 启动心跳检测 self.heartbeat_task = asyncio.create_task(self._heartbeat_check()) self.connected = True print(f"成功连接到设备: {device.name} ({device.address})") return True except (BleakError, asyncio.TimeoutError) as e: print(f"连接失败 (尝试 {attempts}/{self.max_retries}): {str(e)}") await self._cleanup_resources() await asyncio.sleep(1 + attempts) # 指数退避重试 return False async def _find_device_by_name(self): """通过设备名称查找信号最强的设备""" devices = await BleakScanner.discover(timeout=5.0) target_devices = [d for d in devices if d.name and d.name == self.device_name] if not target_devices: return None # 选择RSSI信号最强的设备 strongest_device = max(target_devices, key=lambda d: d.rssi) print(f"找到设备: {strongest_device.name}, RSSI: {strongest_device.rssi}") return strongest_device async def _find_device_by_address(self): """通过MAC地址查找设备""" device = await BleakScanner.find_device_by_address( self.device_address, timeout=5.0 ) if device: print(f"找到设备: {device.address}") return device def regst_disconnect_callback(self, callback): self.main_disconnected_callbacks = callback async def _heartbeat_check(self): """心跳检测维持连接""" while self.connected: try: # 读取设备信息作为心跳检测 if self.client and self.client.is_connected: await self.client.read_gatt_char(BLUE_NOTIF_CHAR_UUID) # 设备名称特征 print("心跳检测成功") else: print("心跳检测失败,连接已断开") self.connected = False except BleakError as e: print(f"心跳检测错误: {str(e)}") self.connected = False await self.alive_callbacks( self.connected # 内部状态标志 and self.client is not None # 客户端对象存在 and self.client.is_connected ) await asyncio.sleep(self.heartbeat_interval) async def enable_notifications(self, char_uuid, callback): """启用通知并注册回调""" if not self.connected or not self.client: raise ConnectionError("未连接") await self.client.start_notify(char_uuid, callback) self.notification_callbacks[char_uuid] = callback async def disable_notifications(self, char_uuid): """禁用通知并移除回调""" if not self.connected or not self.client: return if char_uuid in self.notification_callbacks: await self.client.stop_notify(char_uuid) del self.notification_callbacks[char_uuid] def _handle_disconnect(self, client): """处理断开连接事件""" print("设备断开连接") self.connected = False self.main_disconnected_callbacks("disconnected") asyncio.create_task(self._cleanup_resources()) async def disconnect(self): """安全断开连接并清理资源""" if not self.connected or not self.client: return print("正在断开连接...") self.connected = False await self.alive_callbacks(False) # 取消心跳任务 if self.heartbeat_task: self.heartbeat_task.cancel() try: await self.heartbeat_task except asyncio.CancelledError: pass await self._cleanup_resources() async def _cleanup_resources(self): """清理所有资源""" try: if self.client: # 停止所有通知 for char_uuid in list(self.notification_callbacks.keys()): try: await self.client.stop_notify(char_uuid) except BleakError: pass self.notification_callbacks.clear() # 断开连接 if self.client.is_connected: await self.client.disconnect() # 强制清理(平台特定) if hasattr(self.client, '_backend') and hasattr(self.client._backend, 'cleanup'): self.client._backend.cleanup() # print("资源清理完成") except Exception as e: print(f"清理资源出错: {str(e)}") finally: self.client = None async def read_characteristic(self, char_uuid): """读取特征值""" if not self.connected or not self.client: raise ConnectionError("未连接") return await self.client.read_gatt_char(char_uuid) async def write_characteristic(self, char_uuid, data, response=True): """写入特征值""" if not self.connected or not self.client: raise ConnectionError("未连接") await self.client.write_gatt_char(char_uuid, data) async def __aenter__(self): await self.connect() return self async def __aexit__(self, exc_type, exc_value, traceback): await self.disconnect() def is_alive_callbacks(self, callback): """是否连接""" self.alive_callbacks = callback class BleakClientThread(QThread): FLAG = 'BleakClientThread' def __init__(self, address_or_ble_device: Union[BLEDevice, str], parent, disconnect_callback=None): super().__init__() self.send_sequence = 0 self.manage = parent self.ble_device = address_or_ble_device self.loop = asyncio.new_event_loop() self.stop_event = asyncio.Event() self.write_queue = asyncio.Queue() # 当前已经存的长度 self.already_len = None # 当前的片计数 self.cont = None # 需要拼包的总长的,第一次进入赋值 self.total_length = None # 拼包数据 self.pack_data = [] self.pack_flag = False self.last_seq = None self.notice_callback = None self.recv_callback = None self.is_connected = False self.disconnect_callback = disconnect_callback def register_connect(self, parm): """ 注册连接成功、失败、断开的回调通知函数 :param parm: 函数指针名 :return: """ self.notice_callback = parm def unregister_connect(self): """ 注销回调函数 :return: """ self.notice_callback = None def register_recv(self, parm): """ 注册收数 :param parm: :return: """ self.recv_callback = parm def unregister_recv(self): """ 注销收数 :return: """ self.recv_callback = None def run(self): try: asyncio.set_event_loop(self.loop) self.loop.run_until_complete(self.main()) except Exception as e: logger.error(f"{self.FLAG}, run error: {str(e)}") finally: # Clean up loop resources self.loop.run_until_complete(self.loop.shutdown_asyncgens()) # self.loop.close() async def main(self): # 使用设备名称连接 async with StableBleakClient(device_address=self.ble_device) as client: # 启用通知 await client.enable_notifications( BLUE_NOTIF_CHAR_UUID, self.notification_handler ) client.is_alive_callbacks(self.is_connect) client.regst_disconnect_callback(self.disconnect_callback) # 读取设备信息 # device_name = await client.read_characteristic(BLUE_NOTIF_DESC_UUID) # print(f"设备名称: {device_name.decode('utf-8')}") while True: try: data = await asyncio.wait_for(self.write_queue.get(), timeout=1.0) if data is None: break print("send to ",data) # 写入数据 await client.write_characteristic( BLUE_WRITE_CHAR_UUID, data, response=True ) except asyncio.TimeoutError: continue # Timeout is expected, continue the loop # async def main(self): # try: # await self.client.connect() # for service in self.client.services: # logger.error( # '-----------------service uuid: {} [{}]---------------------'.format(service.uuid, # service.description)) # for c in service.characteristics: # logger.error('characteristic uuid: {} [{}] [{}]'.format(c.uuid, c.description, c.properties)) # await self.client.start_notify(BLUE_NOTIF_CHAR_UUID, self.notification_handler) # MainSignal.get_instance().manage_client_connected.emit(True) # if self.notice_callback: # self.notice_callback(True) # while not self.stop_event.is_set(): # try: # data = await asyncio.wait_for(self.write_queue.get(), timeout=1.0) # if data is None: # break # await self.client.write_gatt_char(BLUE_WRITE_CHAR_UUID, data) # except asyncio.TimeoutError: # continue # Timeout is expected, continue the loop # except Exception as e: # logger.error(f"{self.FLAG}, connection or notification error: {str(e)}") # finally: # try: # await self.client.disconnect() # logger.error(f"{self.FLAG}, Bluetooth disconnected") # except Exception as e: # logger.error(f"{self.FLAG}, disconnect error: {str(e)}") # # MainSignal.get_instance().manage_client_connected.emit(False) # if self.notice_callback: # self.notice_callback(True) # 第一次收到14帧序号,进行初始拼包操作 def inti_merge_data(self, data): self.pack_data.clear() high = data[0:2] low = data[2:4] self.total_length = int(low + high, 16) * 2 self.pack_data.append(data[4:]) self.already_len = len(data[4:]) self.pack_flag = True # 拼包0x14 def dispose_0x14(self, msg_type, fc, data): if not self.pack_flag and fc == '14': self.inti_merge_data(data) elif fc == '14': # 第二次来的还是14 就进行检查是否为上一帧的后续,如果不是,就当第一次14帧处理 temp_height = data[0:2] temp_low = data[2:4] temp_len = int(temp_low + temp_height, 16) * 2 if self.total_length != temp_len + self.already_len: self.inti_merge_data(data) else: self.pack_data.append(data[4:]) self.already_len += len(data[4:]) else: temp_len = len(data) if self.total_length == self.already_len + temp_len: real_data = '' for str_data in self.pack_data: real_data += str_data real_data += data self.pack_flag = False MainSignal.get_instance().manage_data_received.emit(msg_type, real_data) if self.recv_callback: self.recv_callback(msg_type, data) self.pack_data.clear() else: self.dispose_0x04(msg_type, data) # 直接丢出0x04 def dispose_0x04(self, msg_type, data): MainSignal.get_instance().manage_data_received.emit(msg_type, data) if self.recv_callback: self.recv_callback(msg_type, data) def notification_handler(self, sender, data): try: print("", data) data_t = bytes(data).hex() lo = ' '.join([data_t[i:i + 2] for i in range(0, len(data_t), 2)]) # print(lo) msg_type = data_t[0:2] fc = data_t[2:4] seq = data_t[4:6] data_len = data_t[6:8] data_protobuf = data_t[8:] if msg_type == '3d': return # if msg_type != '4d': # print(lo) if fc == '14' or self.pack_flag: self.dispose_0x14(msg_type, fc, data_protobuf) else: self.dispose_0x04(msg_type, data_protobuf) except Exception: traceback.print_exc() # 获取计数 def get_send_num(self): self.send_sequence += 1 self.send_sequence = self.send_sequence & 0xFF return self.send_sequence def send_data(self, obj: object): seqs = self.get_send_num() data = None # TODO if isinstance(obj, MessagePB): obj.setseqs(seqs) data = obj.create_msg() else: # data = obj return while True: data_len = len(data) if data_len == 0: break if data_len > 100: head = [77, 20, seqs, 102] hex_st = decimal_to_hex(data_len) high_byte, low_byte = get_high_low(hex_st) low_byte = int(low_byte, 16) head.append(low_byte) high_byte = int(high_byte, 16) head.append(high_byte) head.extend(data[0:100]) data = data[100:] send_data = bytearray(head) seqs = self.get_send_num() else: len_data = len(data) head = [77, 4, seqs, len_data] head.extend(data) send_data = bytearray(head) data = '' hx = send_data.hex() # logger.debug(f" send data: {' '.join([hx[i:i + 2] for i in range(0, len(hx), 2)])}") if not self.loop.is_closed(): self.loop.call_soon_threadsafe(self.write_queue.put_nowait, send_data) def send_wifi_cntrl(self, msg_type, msg_data): seqs = self.get_send_num() if msg_data is None: head = [msg_type, 0, seqs, 0] else: head = [msg_type, 0, seqs, len(msg_data)] head.extend(msg_data) send_data = bytearray(head) hx = send_data.hex() # logger.debug(f"send data: {' '.join([hx[i:i + 2] for i in range(0, len(hx), 2)])}") if not self.loop.is_closed(): self.loop.call_soon_threadsafe(self.write_queue.put_nowait, send_data) async def is_connect(self, parm): self.is_connected = parm def is_alive(self): return self.is_connected def stop(self): try: self.loop.call_soon_threadsafe(self.write_queue.put_nowait, None) # self.loop.call_soon_threadsafe(self.stop_event.set) except Exception as e: logger.error(f'{self.FLAG} stop error: {str(e)}') 整理成一个可复用的
最新发布
07-03
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值