def inquiry(self, inquiry_len=0x08): logger.info('BR scanning on ' + blue("hci%d"%self.devid) + \ ' with timeout ' + blue("%.2f sec\n"%(inquiry_len*1.28))+'\n') self.scanned_dev = [] self.remote_name_req_flag = True hci = HCI(self.iface) def inquiry_result_handler(result: bytes): event_code = result[0] logger.debug("Entered inquiry(), inquiry_result_handler()\n" "{}".format(HciEventCodes[event_code].name)) if event_code == HCI_Inquiry_Result.evt_code: self.pp_inquiry_result(result[2:]) elif event_code == HCI_Inquiry_Result_with_RSSI.evt_code: self.pp_inquiry_result_with_rssi(result[2:]) elif event_code == HCI_Extended_Inquiry_Result.evt_code: self.pp_extended_inquiry_result(result[2:]) else: logger.warning('Unknow inquiry result: {}'.format(result)) try: hci.inquiry(inquiry_len=inquiry_len, inquiry_result_handler=inquiry_result_handler) logger.info('Inquiry completed\n') if self.remote_name_req_flag and len(self.scanned_dev) != 0: logger.info('Requesting the name of the scanned devices...') for bd_addr in self.scanned_dev: try: name = hci.remote_name_request({ 'BD_ADDR': bytes.fromhex(bd_addr.replace(':', '')), 'Page_Scan_Repetition_Mode': 0x01, 'Reserved': 0x00, 'Clock_Offset': 0x0000 })['Remote_Name'].decode().strip() except Exception as e: print(e) name = '' print(bd_addr + ':', blue(name)) except HciRuntimeError as e: logger.error("{}".format(e)) except KeyboardInterrupt as e: logger.info('BR/EDR devices scan canceled\n') hci.inquiry_cancel() hci.close()
def init_hci(iface: str = 'hci0'): # hciconfig <hci> up 的前提是 rfkill 先 unblock subprocess.check_output('rfkill unblock %d' % find_rfkill_devid(iface), stderr=STDOUT, timeout=5, shell=True) subprocess.check_output('hciconfig {} up'.format(iface), stderr=STDOUT, timeout=5, shell=True) subprocess.check_output('systemctl restart bluetooth.service', stderr=STDOUT, timeout=5, shell=True) hci = HCI(iface) # 下面在发送各种 HCI command 时,如果出现如下异常: # BlockingIOError: [Errno 11] Resource temporarily unavailable # 那么可能是 hci socket 被设为了 non-blocking mode。 hci.inquiry_cancel() hci.exit_periodic_inquiry_mode() hci.write_scan_enable() # No scan enabled event_params = hci.le_set_advertising_enable() # Advertising is disabled if event_params['Status'] != 0x00: #print(WARNING, 'Status of HCI_LE_Set_Advertising_Enable command: 0x%02x'%event_params['Status']) pass try: hci.le_set_scan_enable({ 'LE_Scan_Enable': 0x00, # Scanning disabled 'Filter_Duplicates': 0x01 # Ignored }) except RuntimeError as e: #print(WARNING, e) pass hci.set_event_filter({'Filter_Type': 0x00}) # Clear All Filters event_params = hci.read_bdaddr() if event_params['Status'] != 0: raise RuntimeError else: local_bd_addr = event_params['BD_ADDR'].upper() # Clear bluetoothd cache cache_path = PosixPath('/var/lib/bluetooth/') / local_bd_addr / 'cache' if cache_path.exists(): for file in cache_path.iterdir(): os.remove(file) hci.close()