树莓派Pico W基于aioble的BLE连接立即失败问题求助
树莓派Pico W BLE HID键盘连接失败问题
我尝试用树莓派Pico W制作一款带按键的小型蓝牙键盘,但尚未实现按键功能就卡在了BLE连接环节——设备可被BLE调试APP搜索到,但尝试连接时蓝牙会立即断开。
我使用aioble模块(简写为ble)定义了三类服务:设备信息服务(DIS)、电池电量服务(BAS)和HID服务(仅HID服务被设置为广播)。曾尝试执行await connection.exchange_mtu()进行MTU交换,但问题反而恶化。
相关代码如下:
import struct from bluetooth import UUID import asyncio _ADV_INTERVAL_MS = 250_000 dis_service = ble.Service(UUID(0x180A)) dis_model_char = ble.Characteristic(dis_service, UUID(0x2A24), read = True) dis_serial_char = ble.Characteristic(dis_service, UUID(0x2A25), read = True) dis_firm_char = ble.Characteristic(dis_service, UUID(0x2A26), read = True) dis_hard_char = ble.Characteristic(dis_service, UUID(0x2A27), read = True) dis_soft_char = ble.Characteristic(dis_service, UUID(0x2A28), read = True) dis_manu_char = ble.Characteristic(dis_service, UUID(0x2A29), read = True) dis_pnp_char = ble.Characteristic(dis_service, UUID(0x2A50), read = True) bas_service = ble.Service(UUID(0x180F)) bas_levl_char = ble.Characteristic(bas_service, UUID(0x2A19), notify = True) hid_service = ble.Service(UUID(0x1812)) hid_info_char = ble.Characteristic(hid_service, UUID(0x2A4A), read = True) hid_irmap_char = ble.Characteristic(hid_service, UUID(0x2A4B), read = True) hid_control_char = ble.Characteristic(hid_service, UUID(0x2A4C), write = True) hid_report_char = ble.Characteristic(hid_service, UUID(0x2A4D), notify = True, read = True) hid_protocol_char = ble.Characteristic(hid_service, UUID(0x2A4E), write = True) hid_report_desc = ble.Descriptor(hid_report_char, UUID(0x2908), read = True) ble.register_services(dis_service, bas_service, hid_service) print("Services registered") HID_INPUT_REPORT = bytes([ # Report Description: describes what we communicate 0x05, 0x01, # USAGE_PAGE (Generic Desktop) 0x09, 0x06, # USAGE (Keyboard) 0xa1, 0x01, # COLLECTION (Application) 0x85, 0x01, # REPORT_ID (1) 0x75, 0x01, # Report Size (1) 0x95, 0x08, # Report Count (8) 0x05, 0x07, # Usage Page (Key Codes) 0x19, 0xE0, # Usage Minimum (224) 0x29, 0xE7, # Usage Maximum (231) 0x15, 0x00, # Logical Minimum (0) 0x25, 0x01, # Logical Maximum (1) 0x81, 0x02, # Input (Data, Variable, Absolute); Modifier byte 0x95, 0x01, # Report Count (1) 0x75, 0x08, # Report Size (8) 0x81, 0x01, # Input (Constant); Reserved byte 0x95, 0x05, # Report Count (5) 0x75, 0x01, # Report Size (1) 0x05, 0x08, # Usage Page (LEDs) 0x19, 0x01, # Usage Minimum (1) 0x29, 0x05, # Usage Maximum (5) 0x91, 0x02, # Output (Data, Variable, Absolute); LED report 0x95, 0x01, # Report Count (1) 0x75, 0x03, # Report Size (3) 0x91, 0x01, # Output (Constant); LED report padding 0x95, 0x06, # Report Count (6) 0x75, 0x08, # Report Size (8) 0x15, 0x00, # Logical Minimum (0) 0x25, 0x65, # Logical Maximum (101) 0x05, 0x07, # Usage Page (Key Codes) 0x19, 0x00, # Usage Minimum (0) 0x29, 0x65, # Usage Maximum (101) 0x81, 0x00, # Input (Data, Array); Key array (6 bytes) 0xc0 # END_COLLECTION ]) def pack_str(in_str): return struct.pack(str(len(in_str))+"s", in_str.encode('UTF-8')) pnp_manufacturer_source = 0x01 # Bluetooth uuid list pnp_manufacturer_uuid = 0xaf73 # 0xFEB2 for Microsoft, 0xFE61 for Logitech, 0xFD65 for Razer pnp_product_id = 0x01 # ID 1 pnp_product_version = 0x0123 # Version 1.2.3 battery_level = 100 appearance = 961 name = "Pi Pico Keyboard" dis_model_char.write(pack_str("1")) dis_serial_char.write(pack_str("1")) dis_firm_char.write(pack_str("1")) dis_hard_char.write(pack_str("1")) dis_soft_char.write(pack_str("1")) dis_manu_char.write(pack_str("Homebrew")) dis_pnp_char.write(struct.pack("<BHHH", pnp_manufacturer_source, pnp_manufacturer_uuid, pnp_product_id, pnp_product_version)) bas_levl_char.write(struct.pack("<B", battery_level)) hid_info_char.write(b"\x01\x01\x00\x02") hid_irmap_char.write(HID_INPUT_REPORT) hid_report_desc.write(struct.pack("<BB", 1, 1)) #hid_report_desc.write(struct.pack("<BB", 1, 2)) hid_protocol_char.write(b"\x01") print("Characteristics written") async def advertise(): while True: print("Advertising") async with await ble.advertise( _ADV_INTERVAL_MS, name=name, services=[UUID(0x1812)], appearance=appearance, ) as connection: print("Connection from", connection.device) await connection.disconnected(timeout_ms=None) # Run both tasks. async def main(): t1 = asyncio.create_task(advertise()) await asyncio.gather(t1) asyncio.run(main())
内容的提问来源于stack exchange,提问作者Tyrannicodin16
相关产品推荐
相关产品推荐

