def _write_inquiry_tx_power(self, power): """ Returns 0 on success, error status code or -1 on failure. """ if not self._check_command_support(18, 0b10): return -1 # save current filter old_filter = self.sock.getsockopt(bluez.SOL_HCI, bluez.HCI_FILTER, 14) # Setup socket filter to receive only events related to the # read_inquiry_mode command flt = bluez.hci_filter_new() opcode = bluez.cmd_opcode_pack(bluez.OGF_HOST_CTL, 0x0059) bluez.hci_filter_set_ptype(flt, bluez.HCI_EVENT_PKT) bluez.hci_filter_set_event(flt, bluez.EVT_CMD_COMPLETE); bluez.hci_filter_set_opcode(flt, opcode) self.sock.setsockopt(bluez.SOL_HCI, bluez.HCI_FILTER, flt) # first read the current inquiry mode. bluez.hci_send_cmd(self.sock, bluez.OGF_HOST_CTL, 0x0059, struct.pack("b", power)) pkt = self.sock.recv(255) status = struct.unpack("xxxxxxB", pkt)[0] # restore old filter self.sock.setsockopt(bluez.SOL_HCI, bluez.HCI_FILTER, old_filter) return status
def device_inquiry_with_with_rssi(sock): global FOUND # save current filter old_filter = sock.getsockopt( bluez.SOL_HCI, bluez.HCI_FILTER, 14) # perform a device inquiry on bluetooth device #0 # The inquiry should last 8 * 1.28 = 10.24 seconds # before the inquiry is performed, bluez should flush its cache of # previously discovered devices flt = bluez.hci_filter_new() bluez.hci_filter_all_events(flt) bluez.hci_filter_set_ptype(flt, bluez.HCI_EVENT_PKT) sock.setsockopt( bluez.SOL_HCI, bluez.HCI_FILTER, flt ) duration = 4 max_responses = 255 cmd_pkt = struct.pack("BBBBB", 0x33, 0x8b, 0x9e, duration, max_responses) bluez.hci_send_cmd(sock, bluez.OGF_LINK_CTL, bluez.OCF_INQUIRY, cmd_pkt) results = [] done = False while not done: pkt = sock.recv(255) ptype, event, plen = struct.unpack("BBB", pkt[:3]) if event == bluez.EVT_INQUIRY_RESULT_WITH_RSSI: pkt = pkt[3:] nrsp = struct.unpack("B", pkt[0])[0] for i in range(nrsp): addr = bluez.ba2str( pkt[1+6*i:1+6*i+6] ) rssi = struct.unpack("b", pkt[1+13*nrsp+i])[0] results.append( ( addr, rssi ) ) print("[%s] RSSI: [%d]" % (addr, rssi)) if addr == ADDR: FOUND = True return elif event == bluez.EVT_INQUIRY_COMPLETE: done = True elif event == bluez.EVT_CMD_STATUS: status, ncmd, opcode = struct.unpack("BBH", pkt[3:7]) if status != 0: print("uh oh...") printpacket(pkt[3:7]) done = True elif event == bluez.EVT_INQUIRY_RESULT: pkt = pkt[3:] nrsp = struct.unpack("B", pkt[0])[0] for i in range(nrsp): addr = bluez.ba2str( pkt[1+6*i:1+6*i+6] ) results.append( ( addr, -1 ) ) print("[%s] (no RRSI)" % addr) else: print("unrecognized packet type 0x%02x" % ptype) print("event ", event) # restore old filter sock.setsockopt( bluez.SOL_HCI, bluez.HCI_FILTER, old_filter ) return results
def read_inquiry_scan_activity(sock): """returns the current inquiry scan interval and window, or -1 on failure""" # save current filter old_filter = sock.getsockopt( bluez.SOL_HCI, bluez.HCI_FILTER, 14) # Setup socket filter to receive only events related to the # read_inquiry_mode command flt = bluez.hci_filter_new() opcode = bluez.cmd_opcode_pack(bluez.OGF_HOST_CTL, bluez.OCF_READ_INQ_ACTIVITY) bluez.hci_filter_set_ptype(flt, bluez.HCI_EVENT_PKT) bluez.hci_filter_set_event(flt, bluez.EVT_CMD_COMPLETE); bluez.hci_filter_set_opcode(flt, opcode) sock.setsockopt( bluez.SOL_HCI, bluez.HCI_FILTER, flt ) # first read the current inquiry mode. bluez.hci_send_cmd(sock, bluez.OGF_HOST_CTL, bluez.OCF_READ_INQ_ACTIVITY ) pkt = sock.recv(255) status,interval,window = struct.unpack("!xxxxxxBHH", pkt) interval = bluez.btohs(interval) interval = (interval >> 8) | ( (interval & 0xFF) << 8 ) window = (window >> 8) | ( (window & 0xFF) << 8 ) if status != 0: mode = -1 # restore old filter sock.setsockopt( bluez.SOL_HCI, bluez.HCI_FILTER, old_filter ) return interval, window
def _check_command_support(self, octet, mask): """ Checks if a certain command is supported by the Bluetooth sensor. @param octet The octet of the command. @param mask The bitmask of the command. Both as defined in the Bluetooth specification v4.0 pp. 447 (pdf 693). """ # save current filter old_filter = self.sock.getsockopt(bluez.SOL_HCI, bluez.HCI_FILTER, 14) # Setup socket filter to receive only events related to the # read_inquiry_mode command flt = bluez.hci_filter_new() opcode = bluez.cmd_opcode_pack(0x04, 0x0002) bluez.hci_filter_set_ptype(flt, bluez.HCI_EVENT_PKT) bluez.hci_filter_set_event(flt, bluez.EVT_CMD_COMPLETE); bluez.hci_filter_set_opcode(flt, opcode) self.sock.setsockopt(bluez.SOL_HCI, bluez.HCI_FILTER, flt) # Send the Read Local Supported Commands command bluez.hci_send_cmd(self.sock, 0x04, 0x0002) pkt = self.sock.recv(65) status = struct.unpack("65B", pkt) status = status[6:] # restore old filter self.sock.setsockopt(bluez.SOL_HCI, bluez.HCI_FILTER, old_filter) # Check if the requested bit is set. if len(status) >= octet+1: return status[octet+1] & mask == mask return False
def authenticate(sock, handle): old_filter = save_filter(sock) cmd_pkt = struct.pack("H", handle) bluez.hci_send_cmd(sock, bluez.OGF_LINK_CTL, bluez.OCF_AUTH_REQUESTED, cmd_pkt) done = False while not done: pkt = sock.recv(255) #printpacket(pkt) ptype, event, plen = struct.unpack("BBB", pkt[:3]) if event == bluez.EVT_CMD_STATUS: status, ncmd, opcode = struct.unpack("BBH", pkt[3:7]) if status != 0: print "-" * 10 printpacket(pkt) print "auth command failed" done = True raise CommandNotCompletedError("command failed") elif event == bluez.EVT_AUTH_COMPLETE: status, returned_handle = struct.unpack("xBH",pkt[2:]) if status == 0 and handle == returned_handle: done = True elif status != 0 and handle == returned_handle: print "authenticatin failed! is device paired?" done = True raise CommandNotCompletedError("Authentication did not succeed!") restore_filter(old_filter, sock)
def read_inquiry_mode(sock): """returns the current mode, or -1 on failure""" # save current filter old_filter = sock.getsockopt( bluez.SOL_HCI, bluez.HCI_FILTER, 14) # Setup socket filter to receive only events related to the # read_inquiry_mode command flt = bluez.hci_filter_new() opcode = bluez.cmd_opcode_pack(bluez.OGF_HOST_CTL, bluez.OCF_READ_INQUIRY_MODE) bluez.hci_filter_set_ptype(flt, bluez.HCI_EVENT_PKT) bluez.hci_filter_set_event(flt, bluez.EVT_CMD_COMPLETE); bluez.hci_filter_set_opcode(flt, opcode) sock.setsockopt( bluez.SOL_HCI, bluez.HCI_FILTER, flt ) # first read the current inquiry mode. bluez.hci_send_cmd(sock, bluez.OGF_HOST_CTL, bluez.OCF_READ_INQUIRY_MODE ) pkt = sock.recv(255) status,mode = struct.unpack("xxxxxxBB", pkt) if status != 0: mode = -1 # restore old filter sock.setsockopt( bluez.SOL_HCI, bluez.HCI_FILTER, old_filter ) return mode
def find_devices (s, lookup_names=True, duration=8, flush_cache=True): if s.is_inquiring: raise BluetoothError ("Already inquiring!") s.lookup_names = lookup_names s.sock = _gethcisock () flt = _bt.hci_filter_new () _bt.hci_filter_all_events (flt) _bt.hci_filter_set_ptype (flt, _bt.HCI_EVENT_PKT) try: s.sock.setsockopt (_bt.SOL_HCI, _bt.HCI_FILTER, flt) except: raise BluetoothError ("problem with local bluetooth device.") # send the inquiry command max_responses = 255 cmd_pkt = struct.pack ("BBBBB", 0x33, 0x8b, 0x9e, \ duration, max_responses) s.pre_inquiry () try: _bt.hci_send_cmd (s.sock, _bt.OGF_LINK_CTL, \ _bt.OCF_INQUIRY, cmd_pkt) except: raise BluetoothError ("problem with local bluetooth device.") s.is_inquiring = True s.names_to_find = {}
def write_inquiry_mode(sock, mode): """returns 0 on success, -1 on failure""" # save current filter old_filter = sock.getsockopt( bluez.SOL_HCI, bluez.HCI_FILTER, 14) # Setup socket filter to receive only events related to the # write_inquiry_mode command flt = bluez.hci_filter_new() opcode = bluez.cmd_opcode_pack(bluez.OGF_HOST_CTL, bluez.OCF_WRITE_INQUIRY_MODE) bluez.hci_filter_set_ptype(flt, bluez.HCI_EVENT_PKT) bluez.hci_filter_set_event(flt, bluez.EVT_CMD_COMPLETE); bluez.hci_filter_set_opcode(flt, opcode) sock.setsockopt( bluez.SOL_HCI, bluez.HCI_FILTER, flt ) # send the command! bluez.hci_send_cmd(sock, bluez.OGF_HOST_CTL, bluez.OCF_WRITE_INQUIRY_MODE, struct.pack("B", mode) ) pkt = sock.recv(255) status = struct.unpack("xxxxxxB", pkt)[0] # restore old filter sock.setsockopt( bluez.SOL_HCI, bluez.HCI_FILTER, old_filter ) if status != 0: return -1 return 0
def hci_le_set_scan_parameters(sock, scan_type=LE_SCAN_ACTIVE, interval=0x10, window=0x10, own_bdaddr_type=LE_RANDOM_ADDRESS, filter_type=LE_FILTER_ALLOW_ALL): # setting up scan # interval and window are uint_16, so we pad them with 0x0 cmd_pkt = struct.pack("<BBBBBBB", scan_type, 0x0, interval, 0x0, window, own_bdaddr_type, filter_type) bluez.hci_send_cmd(sock, OGF_LE_CTL, OCF_LE_SET_SCAN_PARAMETERS, cmd_pkt)
def device_inquiry_with_with_rssi(sock): # save current filter old_filter = sock.getsockopt(bluez.SOL_HCI, bluez.HCI_FILTER, 14) # perform a device inquiry on bluetooth device #0 # The inquiry should last 8 * 1.28 = 10.24 seconds # before the inquiry is performed, bluez should flush its cache of # previously discovered devices flt = bluez.hci_filter_new() bluez.hci_filter_all_events(flt) bluez.hci_filter_set_ptype(flt, bluez.HCI_EVENT_PKT) sock.setsockopt(bluez.SOL_HCI, bluez.HCI_FILTER, flt) duration = 4 max_responses = 255 cmd_pkt = struct.pack("BBBBB", 0x33, 0x8b, 0x9e, duration, max_responses) bluez.hci_send_cmd(sock, bluez.OGF_LINK_CTL, bluez.OCF_INQUIRY, cmd_pkt) results = [] done = False while not done: pkt = sock.recv(255) ptype, event, plen = struct.unpack("BBB", pkt[:3]) if event == bluez.EVT_INQUIRY_RESULT_WITH_RSSI: pkt = pkt[3:] nrsp = bluetooth.get_byte(pkt[0]) for i in range(nrsp): addr = bluez.ba2str(pkt[1 + 6 * i:1 + 6 * i + 6]) rssi = bluetooth.byte_to_signed_int( bluetooth.get_byte(pkt[1 + 13 * nrsp + i])) results.append((addr, rssi)) elif event == bluez.EVT_INQUIRY_COMPLETE: done = True elif event == bluez.EVT_CMD_STATUS: status, ncmd, opcode = struct.unpack("BBH", pkt[3:7]) if status != 0: print("uh oh...") printpacket(pkt[3:7]) done = True elif event == bluez.EVT_INQUIRY_RESULT: pkt = pkt[3:] nrsp = bluetooth.get_byte(pkt[0]) for i in range(nrsp): addr = bluez.ba2str(pkt[1 + 6 * i:1 + 6 * i + 6]) results.append((addr, -1)) print("[%s] (no RRSI)" % addr) else: print("unrecognized packet type 0x%02x" % ptype) # restore old filter sock.setsockopt(bluez.SOL_HCI, bluez.HCI_FILTER, old_filter) return results
def hci_le_set_scan_parameters(sock): SCAN_RANDOM = 0x01 OWN_TYPE = SCAN_RANDOM SCAN_TYPE = 0x01 INTERVAL = 0x10 WINDOW = 0x10 FILTER = 0x00 # all advertisements, not just whitelisted devices # interval and window are uint_16, so we pad them with 0x0 cmd_pkt = struct.pack("<BBBBBBB", SCAN_TYPE, 0x0, INTERVAL, 0x0, WINDOW, OWN_TYPE, FILTER) # print "packed up: \"", str( cmd_pkt ) , "\"" bluez.hci_send_cmd(sock, OGF_LE_CTL, OCF_LE_SET_SCAN_PARAMETERS, cmd_pkt)
def enable_custom_ac_pdu(self, enable, wait_status=True): if enable: enable = b"\x01\x00\x00" else: enable = b"\x00" _bt.hci_send_cmd(self.hci_sock, _bt.OGF_VENDOR_CMD, OCF_VS_ENABLE_CUSTOM_AC_PDU, enable) if wait_status: is_cmd_status_ok( self.hci_sock, to_opcode(_bt.OGF_VENDOR_CMD, OCF_VS_ENABLE_CUSTOM_AC_PDU))
def device_inquiry_with_with_rssi(sock, wanted_addr): global results # save current filter old_filter = sock.getsockopt(bluez.SOL_HCI, bluez.HCI_FILTER, 14) # perform a device inquiry on bluetooth device #0 # The inquiry should last 8 * 1.28 = 10.24 seconds # before the inquiry is performed, bluez should flush its cache of # previously discovered devices flt = bluez.hci_filter_new() bluez.hci_filter_all_events(flt) bluez.hci_filter_set_ptype(flt, bluez.HCI_EVENT_PKT) sock.setsockopt(bluez.SOL_HCI, bluez.HCI_FILTER, flt) duration = 4 max_responses = 255 # 0x9e8b33 is the reserved code for general inquiry of Bluetooth devices cmd_pkt = struct.pack("BBBBB", 0x33, 0x8b, 0x9e, duration, max_responses) bluez.hci_send_cmd(sock, bluez.OGF_LINK_CTL, bluez.OCF_INQUIRY, cmd_pkt) done = False while not done: pkt = sock.recv(255) ptype, event, plen = struct.unpack("BBB", pkt[:3]) if event == bluez.EVT_INQUIRY_RESULT_WITH_RSSI: pkt = pkt[3:] nrsp = struct.unpack("B", pkt[0])[0] for i in range(nrsp): addr = bluez.ba2str(pkt[1 + 6 * i:1 + 6 * i + 6]) rssi = struct.unpack("b", pkt[1 + 13 * nrsp + i])[0] if addr == wanted_addr: results.append(rssi) # print "*** ", # print "[%s] RSSI: [%d]" % (addr, rssi) elif event == bluez.EVT_INQUIRY_COMPLETE: done = True elif event == bluez.EVT_CMD_STATUS: status, ncmd, opcode = struct.unpack("BBH", pkt[3:7]) if status != 0: print "uh oh..." done = True else: # print "unrecognized packet type 0x%02x" % ptype continue # restore old filter sock.setsockopt(bluez.SOL_HCI, bluez.HCI_FILTER, old_filter) if len(results) > 10: results = results[-10:] return results
def set_receive(socket): """Setup to receive contact tracing packets.""" # Enable scanning enable_scanning = struct.pack("<BB", 0x01, 0x00) bluez.hci_send_cmd(socket, OGF_LE_CTL, OCF_LE_SET_SCAN_ENABLE, enable_scanning) # Obtain Bluetooth advertisement packets socket.getsockopt(bluez.SOL_HCI, bluez.HCI_FILTER, 14) listen_filter = bluez.hci_filter_new() bluez.hci_filter_all_events(listen_filter) bluez.hci_filter_set_ptype(listen_filter, bluez.HCI_EVENT_PKT) socket.setsockopt(bluez.SOL_HCI, bluez.HCI_FILTER, listen_filter)
def __init__(self): try: self.sock = bluez.hci_open_dev(self.dev_id) old_filter = self.sock.getsockopt(bluez.SOL_HCI, bluez.HCI_FILTER, 14) enable = 1 cmd_pkt = struct.pack("<BB", enable, 0x00) bluez.hci_send_cmd(self.sock, OGF_LE_CTL, OCF_LE_SET_SCAN_ENABLE, cmd_pkt) except: print "error accessing blue tooth device..." sys.exit(1)
def hci_le_set_scan_parameters(sock): SCAN_RANDOM = 0x01 OWN_TYPE = SCAN_RANDOM SCAN_TYPE = 0x01 WINDOW = 0x10 INTERVAL = 0x10 FILTER = 0x00 # all advertisements, not just whitelisted devices # interval and window are uint_16, so we pad them with 0x0 cmd_pkt = struct.pack('<BBBBBBB', SCAN_TYPE, 0x0, INTERVAL, 0x0, WINDOW, OWN_TYPE, FILTER) bluez.hci_send_cmd(sock, OGF_LE_CTL, OCF_LE_SET_SCAN_PARAMETERS, cmd_pkt) __logger.info('Sent scan parameters command.')
def set_scan_options(self): # 1. Should scanning be active? # 2. Set scan interval to 100ms # 3. Set scan window to 100ms # 4. Do not use a random bluetooth address # 5. Do not filter cmd = struct.pack( ">BHHBB", False, int(100 / 0.625), int(100 / 0.625), False, False) bluez.hci_send_cmd(self.sock, OGF_LE_CTL, OCF_LE_SET_SCAN_PARAMETERS, cmd)
def hci_le_set_scan_parameters(sock, scan_type=LE_SCAN_ACTIVE, interval=0x10, window=0x10, own_bdaddr_type=LE_RANDOM_ADDRESS, filter_type=LE_FILTER_ALLOW_ALL): if (DEBUG == True): print "---- setting up scan" old_filter = sock.getsockopt( bluez.SOL_HCI, bluez.HCI_FILTER, 14) if (DEBUG == True): print "---- got old filter" # interval and window are uint_16, so we pad them with 0x0 cmd_pkt = struct.pack("<BBBBBBB", scan_type, 0x0, interval, 0x0, window, own_bdaddr_type, filter_type) bluez.hci_send_cmd(sock, OGF_LE_CTL, OCF_LE_SET_SCAN_PARAMETERS, cmd_pkt) if (DEBUG == True): print "---- sent scan parameters command"
def create_connection(self, cmd_params: dict): ''' cmd_params -- { 'BD_ADDR': str, 'Packet_Type': int, 'Page_Scan_Repetition_Mode': , 'Reserved': , 'Clock_Offset': , 'Allow_Role_Switch': } ''' dd = hci_open_dev(self.devid) bin_cmd_params = bytes.fromhex( cmd_params['BD_ADDR'].replace(':', ''))[::-1] + \ cmd_params['Packet_Type'].to_bytes(2, 'little') + \ cmd_params['Page_Scan_Repetition_Mode'].to_bytes(1, 'little') + \ cmd_params['Reserved'].to_bytes(1, 'little') + \ cmd_params['Clock_Offset'].to_bytes(2, 'little') + \ cmd_params['Allow_Role_Switch'].to_bytes(1, 'little') flt = hci_filter_new() hci_filter_set_ptype(flt, HCI_EVENT_PKT) hci_filter_set_event(flt, EVT_CONN_COMPLETE) dd.setsockopt(SOL_HCI, HCI_FILTER, flt) hci_send_cmd(dd, OGF_LINK_CTL, OCF_CREATE_CONN, bin_cmd_params) while True: event_params = dd.recv(3 + EVT_CONN_COMPLETE_SIZE)[3:] status, conn_handle, bd_addr, link_type, encrypt_enabled = \ struct.unpack('<BH6sBB', event_params) event_params = { 'Status': status, 'Connection_Handle': conn_handle, 'BD_ADDR': ':'.join(['%02x' % b for b in bd_addr[::-1]]), 'Link_Type': link_type, 'Encryption_Enabled': encrypt_enabled, } if event_params['BD_ADDR'].lower() == cmd_params['BD_ADDR'].lower( ): break else: print(WARNING, 'Another HCI_Connection_Complete event detected', event_params) hci_close_dev(dd.fileno()) return event_params
def enable_adv(self, enable, wait_status=True): OCF_LE_SET_ADV_ENABLE = 0x0a if enable: enable = b"\x01" else: enable = b"\x00" self.called_adv_func = self.enable_adv _bt.hci_send_cmd(self.hci_sock, OGF_LE_CTL, OCF_LE_SET_ADV_ENABLE, enable) if wait_status: is_cmd_status_ok(self.hci_sock, to_opcode(OGF_LE_CTL, OCF_LE_SET_ADV_ENABLE))
def hci_le_connect(sock, peer_bdaddr, interval=0x0004, window=0x004, initiator_filter=LE_FILTER_ALLOW_ALL, peer_bdaddr_type=LE_RANDOM_ADDRESS, own_bdaddr_type=LE_PUBLIC_ADDRESS, min_interval=0x000F, max_interval=0x000F, latency=0x0000, supervision_timeout=0x0C80, min_ce_length=0x0001, max_ce_length=0x0001): package_bdaddr = get_packed_bdaddr(peer_bdaddr) cmd_pkt = struct.pack("<HHBB", interval, window, initiator_filter, peer_bdaddr_type) cmd_pkt += package_bdaddr cmd_pkt += struct.pack("<BHHHHHH", own_bdaddr_type, min_interval, max_interval, latency, supervision_timeout, min_ce_length, max_ce_length) bluez.hci_send_cmd(sock, OGF_LE_CTL, OCF_LE_CREATE_CONN, cmd_pkt)
def set_adv_params(self): params = b"\x20\x00" # Advertising_Interval_Min params += b"\x20\x00" # Advertising_Interval_Max params += b"\x03" # Advertising_Type params += b"\x00" # Own_Address_Type params += b"\x00" # Peer_Address_Type params += b"\x00\x00\x00\x00\x00\x00" # Peer_Address params += b"\x07" # Advertising_Channel_Map params += b"\x00" # Advertising_Filter_Policy # TODO: improve error handling _bt.hci_send_cmd(self.hci_sock, OGF_LE_CTL, OCF_LE_SET_ADV_PARAMS, params) is_cmd_status_ok(self.hci_sock, to_opcode(OGF_LE_CTL, OCF_LE_SET_ADV_PARAMS))
def _send_next_name_req(self): assert len(self.names_to_find) > 0 address = list(self.names_to_find.keys())[0] device_class, rssi, psrm, pspm, clockoff = self.names_to_find[address] bdaddr = _bt.str2ba(address) #TODO not supported in python3 cmd_pkt = "{}{}\0{}".format(bdaddr, psrm, clockoff) try: _bt.hci_send_cmd (self.sock, _bt.OGF_LINK_CTL, \ _bt.OCF_REMOTE_NAME_REQ, cmd_pkt) except _bt.error as e: raise BluetoothError( e.args[0], "error request name of %s - %s:" % (address, e.args[1]))
def bt_start_discovery(sock): """ void """ # The inquiry should last 8 * 1.28 = 10.24 seconds # before the inquiry is performed, bluez will flush its cache of # previously discovered devices flt = bluez.hci_filter_new() bluez.hci_filter_all_events(flt) bluez.hci_filter_set_ptype(flt, bluez.HCI_EVENT_PKT) sock.setsockopt(bluez.SOL_HCI, bluez.HCI_FILTER, flt) duration = 16 max_responses = 255 cmd_pkt = struct.pack("BBBBB", 0x33, 0x8b, 0x9e, duration, max_responses) bluez.hci_send_cmd(sock, bluez.OGF_LINK_CTL, bluez.OCF_INQUIRY, cmd_pkt) return
def turn_off(call): """Turn Bluetooth tracker off.""" _LOGGER.info("Turning off Bluetooth") try: sock = bluez.hci_open_dev(0) bluez.hci_send_cmd(sock, bluez.OGF_LINK_CTL, bluez.OCF_INQUIRY_CANCEL) sock.close() _LOGGER.info("Turned off Bluetooth") hass.states.set(DOMAIN + '.' + ENTITY_ID, STATE_OFF) except Exception as err: _LOGGER.error("Error turning off Bluetooth: %s", err) sock.close()
def bt_print_device_inquiry_list(sock): """ void """ # save current filter old_filter = sock.getsockopt(bluez.SOL_HCI, bluez.HCI_FILTER, 14) # perform a device inquiry on bluetooth device #0 # The inquiry should last 8 * 1.28 = 10.24 seconds # before the inquiry is performed, bluez should flush its cache of # previously discovered devices flt = bluez.hci_filter_new() bluez.hci_filter_all_events(flt) bluez.hci_filter_set_ptype(flt, bluez.HCI_EVENT_PKT) sock.setsockopt(bluez.SOL_HCI, bluez.HCI_FILTER, flt) duration = 16 max_responses = 255 cmd_pkt = struct.pack("BBBBB", 0x33, 0x8b, 0x9e, duration, max_responses) bluez.hci_send_cmd(sock, bluez.OGF_LINK_CTL, bluez.OCF_INQUIRY, cmd_pkt) results = [] done = False while not done: pkt = sock.recv(255) ptype, event, plen = struct.unpack("BBB", pkt[:3]) if event == bluez.EVT_INQUIRY_RESULT_WITH_RSSI: pkt = pkt[3:] nrsp = struct.unpack("B", pkt[0])[0] for i in range(nrsp): addr = bluez.ba2str(pkt[1 + 6 * i:1 + 6 * i + 6]) rssi = struct.unpack("b", pkt[1 + 13 * nrsp + i])[0] results.append(addr) elif event == bluez.EVT_INQUIRY_COMPLETE: done = True elif event == bluez.EVT_CMD_STATUS: status, ncmd, opcode = struct.unpack("BBH", pkt[3:7]) if status != 0: done = True else: print "unrecognized packet type 0x%02x" % ptype # restore old filter sock.setsockopt(bluez.SOL_HCI, bluez.HCI_FILTER, old_filter) # Results become unique set = {} map(set.__setitem__, results, []) print set.keys()
def hci_connect_le(sock, peer_bdaddr, interval=0x0004, window=0x004, initiator_filter=0x0, peer_bdaddr_type=LE_RANDOM_ADDRESS, own_bdaddr_type=0x00, min_interval=0x000F, max_interval=0x000F, latency=0x0000, supervision_timeout=0x0C80, min_ce_length=0x0001, max_ce_length=0x0001): # interval = htobs(0x0004); # window = htobs(0x0004); # own_bdaddr_type = 0x00; # min_interval = htobs(0x000F); # max_interval = htobs(0x000F); # latency = htobs(0x0000); # supervision_timeout = htobs(0x0C80); # min_ce_length = htobs(0x0001); # max_ce_length = htobs(0x0001); # # err = hci_le_create_conn(dd, interval, window, initiator_filter, # peer_bdaddr_type, bdaddr, own_bdaddr_type, min_interval, # max_interval, latency, supervision_timeout, # min_ce_length, max_ce_length, &handle, 25000); # uint16_t interval; # uint16_t window; # uint8_t initiator_filter; # uint8_t peer_bdaddr_type; # bdaddr_t peer_bdaddr; # uint8_t own_bdaddr_type; # uint16_t min_interval; # uint16_t max_interval; # uint16_t latency; # uint16_t supervision_timeout; # uint16_t min_ce_length; # uint16_t max_ce_length; package_bdaddr = get_packed_bdaddr(peer_bdaddr) cmd_pkt = struct.pack("<HHBB", interval, window, initiator_filter, peer_bdaddr_type) cmd_pkt = cmd_pkt + package_bdaddr cmd_pkt = cmd_pkt + struct.pack("<BHHHHHH", own_bdaddr_type, min_interval, max_interval, latency, supervision_timeout, min_ce_length, max_ce_length) bluez.hci_send_cmd(sock, OGF_LE_CTL, OCF_LE_CREATE_CONN, cmd_pkt)
def read_rssi(sock, handle): # save current filter old_filter = save_filter(sock) cmd_pkt = struct.pack("H", handle) result = bluez.hci_send_cmd(sock, bluez.OGF_STATUS_PARAM, bluez.OCF_READ_RSSI, cmd_pkt) done = False while not done: pkt = sock.recv(255) ptype, event, plen = struct.unpack("BBB", pkt[:3]) if event == bluez.EVT_CMD_STATUS: status, ncmd, opcode = struct.unpack("BBH", pkt[3:7]) if status != 0: print "RSSI command failed" done = True raise CommandNotCompletedError("RSSI could not be read") elif event == bluez.EVT_CMD_COMPLETE: status, returned_handle, rssi = struct.unpack("xBHb", pkt[5:]) if status == 0 and returned_handle == handle: done = True elif status != 0 and returned_handle == handle: rssi = -255 # some error while reading the RSSI done = True # restore old filter restore_filter(old_filter, sock) return rssi
def main(time_value): if int(time_value) > 0: pid_check() beacon() timer(time_value) else: f = open("/var/swgedbr.pid") g = f.read() f.close() os.kill(int(g), signal.SIGTERM)#Script fails if previous swgebr.py process was not shut down properly. Manually remove /var/swgedbr.pid and try again "sudo rm -f /var/swgebr.pid" os.remove("/var/swgedbr.pid") OGF_LE_CTL=0x08 OCF_HCI_LE_Set_Advertising_Enable=0x000A dis_adv=struct.pack("<B", 0x00) sock = bluez.hci_open_dev(0) bluez.hci_send_cmd(sock, OGF_LE_CTL, OCF_HCI_LE_Set_Advertising_Enable, dis_adv)
def read_local_bdaddr(sock): flt = bluez.hci_filter_new() opcode = bluez.cmd_opcode_pack(bluez.OGF_INFO_PARAM, bluez.OCF_READ_BD_ADDR) bluez.hci_filter_set_ptype(flt, bluez.HCI_EVENT_PKT) bluez.hci_filter_set_event(flt, bluez.EVT_CMD_COMPLETE) bluez.hci_filter_set_opcode(flt, opcode) sock.setsockopt(bluez.SOL_HCI, bluez.HCI_FILTER, flt) bluez.hci_send_cmd(sock, bluez.OGF_INFO_PARAM, bluez.OCF_READ_BD_ADDR) pkt = sock.recv(255) status, raw_bdaddr = struct.unpack("xxxxxxB6s", pkt) assert status == 0 t = ["%02X" % ord(b) for b in raw_bdaddr] t.reverse() bdaddr = "".join(t) return bdaddr.lower()
def hci_le_set_scan_parameters(sock): print "setting up scan" old_filter = sock.getsockopt(bluez.SOL_HCI, bluez.HCI_FILTER, 14) print "got old filter" SCAN_RANDOM = 0x01 OWN_TYPE = SCAN_RANDOM SCAN_TYPE = 0x01 # pack all these # uint8_t type; # uint16_t interval; # uint16_t window; # uint8_t own_bdaddr_type; # uint8_t filter; # memset(¶m_cp, 0, sizeof(param_cp)); # param_cp.type = type; # param_cp.interval = interval; # param_cp.window = window; # param_cp.own_bdaddr_type = own_type; # param_cp.filter = filter; # # memset(&rq, 0, sizeof(rq)); # #define OGF_LE_CTL 0x08 # rq.ogf = OGF_LE_CTL; # #define OCF_LE_SET_SCAN_PARAMETERS 0x000B # rq.ocf = OCF_LE_SET_SCAN_PARAMETERS; # rq.cparam = ¶m_cp; # #define LE_SET_SCAN_PARAMETERS_CP_SIZE 7 # rq.clen = LE_SET_SCAN_PARAMETERS_CP_SIZE; # rq.rparam = &status; # rq.rlen = 1; # if (hci_send_req(dd, &rq, to) < 0) INTERVAL = 0x10 WINDOW = 0x10 FILTER = 0x00 # all advertisements, not just whitelisted devices # interval and window are uint_16, so we pad them with 0x0 cmd_pkt = struct.pack("<BBBBBBB", SCAN_TYPE, 0x0, INTERVAL, 0x0, WINDOW, OWN_TYPE, FILTER) print "packed up: ", cmd_pkt bluez.hci_send_cmd(sock, OGF_LE_CTL, OCF_LE_SET_SCAN_PARAMETERS, cmd_pkt) print "sent scan parameters command"
def inquiry(self, lap=0x9e8b33, inquiry_len=0x08, num_rsp=0x00): print(INFO, "BR scanning on " + blue("hci%d"%self.devid) + \ " with timeout " + blue("%.2f sec\n"%(inquiry_len*1.28))+'\n') self.scanned_dev = [] cmd_params = lap.to_bytes(3, 'little') + \ inquiry_len.to_bytes(1, 'little') + num_rsp.to_bytes(1, 'little') # If no filter is set, we can't receive any inquiry result. flt = hci_filter_new() hci_filter_set_ptype(flt, HCI_EVENT_PKT) hci_filter_all_events(flt) dd = hci_open_dev(self.devid) dd.setsockopt(SOL_HCI, HCI_FILTER, flt) hci_send_cmd(dd, OGF_LINK_CTL, OCF_INQUIRY, cmd_params) try: while True: data = dd.recv(300) if len(data) >= 4: event_code = data[1] if event_code == EVT_CMD_STATUS: # print(DEBUG, 'HCI_Command_Status') pass elif event_code == EVT_INQUIRY_RESULT: print(DEBUG, 'HCI_Inquiry_Result') self.pp_inquiry_result(data[3:]) elif event_code == EVT_INQUIRY_RESULT_WITH_RSSI: # print(DEBUG, 'HCI_Inquiry_Result_with_RSSI') self.pp_inquiry_result_with_rssi(data[3:]) elif event_code == EVT_EXTENDED_INQUIRY_RESULT: # print(DEBUG, 'HCI_Extended_Inquiry_Result') self.pp_extended_inquiry_result(data[3:]) elif event_code == EVT_INQUIRY_COMPLETE: # print(DEBUG, 'HCI_Inquiry_Complete') print(INFO, 'Inquiry completed') break else: print(DEBUG, "Unknow:", data) except KeyboardInterrupt as e: print(INFO, "BR/EDR devices scan canceled\n") HCI(self.iface).inquiry_cancel() hci_close_dev(dd.fileno())
def hci_le_set_scan_parameters(sock): print "setting up scan" old_filter = sock.getsockopt(bluez.SOL_HCI, bluez.HCI_FILTER, 14) print "got old filter" SCAN_RANDOM = 0x01 OWN_TYPE = SCAN_RANDOM SCAN_TYPE = 0x01 INTERVAL = 0x10 WINDOW = 0x10 FILTER = 0x00 # all advertisements, not just whitelisted devices # interval and window are uint_16, so we pad them with 0x0 cmd_pkt = struct.pack("<BBBBBBB", SCAN_TYPE, 0x0, INTERVAL, 0x0, WINDOW, OWN_TYPE, FILTER) print "packed up: ", cmd_pkt bluez.hci_send_cmd(sock, OGF_LE_CTL, OCF_LE_SET_SCAN_PARAMETERS, cmd_pkt) print "sent scan parameters command"
def cancel_inquiry(self): """ Call this method to cancel an inquiry in process. inquiry_complete will still be called. """ self.names_to_find = {} if self.is_inquiring: try: _bt.hci_send_cmd (self.sock, _bt.OGF_LINK_CTL, \ _bt.OCF_INQUIRY_CANCEL) except _bt.error as e: self.sock.close() self.sock = None raise BluetoothError(e.args[0], "error canceling inquiry: " + e.args[1]) self.is_inquiring = False
def le_set_advertising_parameters( self, cmd_params={ 'Advertising_Interval_Min': 0x0800, 'Advertising_Interval_Max': 0x0800, 'Advertising_Type': 0x00, # ADV_IND 'Own_Address_Type': 0x00, # Public Device Address 'Peer_Address_Type': 0x00, # Public Device Address 'Peer_Address': bytes(6), 'Advertising_Channel_Map': 0x07, # 37, 38, 39 'Advertising_Filter_Policy': 0x00 # Process scan and connection requests from all devices } ) -> dict: dd = hci_open_dev(self.devid) bin_cmd_params = cmd_params['Advertising_Interval_Min'].to_bytes(2, 'little') + \ cmd_params['Advertising_Interval_Max'].to_bytes(2, 'little') + \ cmd_params['Advertising_Type'].to_bytes(1, 'little') + \ cmd_params['Own_Address_Type'].to_bytes(1, 'little') + \ cmd_params['Peer_Address_Type'].to_bytes(1, 'little') + \ cmd_params['Peer_Address'][::-1] + \ cmd_params['Advertising_Channel_Map'].to_bytes(1, 'little') + \ cmd_params['Advertising_Filter_Policy'].to_bytes(1, 'little') flt = hci_filter_new() hci_filter_set_ptype(flt, HCI_EVENT_PKT) hci_filter_set_event(flt, EVT_CMD_COMPLETE) hci_filter_set_opcode( flt, cmd_opcode_pack(OGF_LE_CTL, OCF_LE_SET_ADVERTISING_PARAMETERS)) dd.setsockopt(SOL_HCI, HCI_FILTER, flt) hci_send_cmd(dd, OGF_LE_CTL, OCF_LE_SET_ADVERTISING_PARAMETERS, bin_cmd_params) event_params = dd.recv(3 + EVT_CMD_COMPLETE_SIZE + 1)[3:] num_hci_cmd_pkts, cmd_opcode, status = struct.unpack( '<BHB', event_params) event_params = { 'Num_HCI_Command_Packets': num_hci_cmd_pkts, 'Command_Opcode': cmd_opcode, 'Status': status } hci_close_dev(dd.fileno()) return event_params
def scan(devices): try: # Open the bluetooth device sock = bluez.hci_open_dev(0) except: # Failed to open sock = None if sock: # We have device access, start BLE scan cmd_pkt = struct.pack("<BB", 0x01, 0x00) bluez.hci_send_cmd(sock, OGF_LE_CTL, OCF_LE_SET_SCAN_ENABLE, cmd_pkt) time_pre = datetime.datetime.now() while True: # Save the current filter setting old_filter = sock.getsockopt(bluez.SOL_HCI, bluez.HCI_FILTER, 14) # Set filter for getting HCI events flt = bluez.hci_filter_new() bluez.hci_filter_all_events(flt) bluez.hci_filter_set_ptype(flt, bluez.HCI_EVENT_PKT) sock.setsockopt(bluez.SOL_HCI, bluez.HCI_FILTER, flt) # Get and decode data buffers = sock.recv(255) mac_address, rssi, tx_power = process_input(buffers) if mac_address != None: devices.append(mac_address, rssi, tx_power) time_now = datetime.datetime.now() if (time_now - time_pre).total_seconds() > env.TIME_INTERVAL: break #Restore the filter setting sock.setsockopt(bluez.SOL_HCI, bluez.HCI_FILTER, old_filter) clients = devices.get_device() if DEBUG: print(clients) send(clients)
def get_localAdapter(self, deviceNr): "Return name and address of a local adapter" name = None address = None sock = bt.hci_open_dev(deviceNr) if sock.getsockid() >= 0: sock.settimeout(3) # Save original filter orig_filter = sock.getsockopt(bt.SOL_HCI, bt.HCI_FILTER, 14) # Create new filter new_filter = orig_filter new_filter = bt.hci_filter_new() bt.hci_filter_set_ptype(new_filter, bt.HCI_EVENT_PKT) bt.hci_filter_set_event(new_filter, bt.EVT_CMD_COMPLETE) # CMD Read local name opcode = bt.cmd_opcode_pack(bt.OGF_HOST_CTL, bt.OCF_READ_LOCAL_NAME) bt.hci_filter_set_opcode(new_filter, opcode) sock.setsockopt(bt.SOL_HCI, bt.HCI_FILTER, new_filter) bt.hci_send_cmd(sock, bt.OGF_HOST_CTL, bt.OCF_READ_LOCAL_NAME) try: data = sock.recv(255) name = data[7:] name = name[:name.find('\0')] except bluetooth._bluetooth.timeout: print 'bluetooth timeout during local device scan for name' # CMD Read local address opcode = bt.cmd_opcode_pack(bt.OGF_INFO_PARAM, bt.OCF_READ_BD_ADDR) bt.hci_filter_set_opcode(new_filter, opcode) sock.setsockopt(bt.SOL_HCI, bt.HCI_FILTER, new_filter) bt.hci_send_cmd(sock, bt.OGF_INFO_PARAM, bt.OCF_READ_BD_ADDR) try: data = sock.recv(255) status, raw_bdaddr = struct.unpack('xxxxxxB6s', data) address = ['%02X' % ord(b) for b in raw_bdaddr] address.reverse() address = ':'.join(address) except bluetooth._bluetooth.timeout: print 'bluetooth timeout during local device scan for address' # Restore original filter sock.setsockopt(bt.SOL_HCI, bt.HCI_FILTER, orig_filter) sock.close() return name, address
def hci_toggle_le_scan(self, sock, enable): # hci_le_set_scan_enable(dd, 0x01, filter_dup, 1000); # memset(&scan_cp, 0, sizeof(scan_cp)); #uint8_t enable; # uint8_t filter_dup; # scan_cp.enable = enable; # scan_cp.filter_dup = filter_dup; # # memset(&rq, 0, sizeof(rq)); # rq.ogf = OGF_LE_CTL; # rq.ocf = OCF_LE_SET_SCAN_ENABLE; # rq.cparam = &scan_cp; # rq.clen = LE_SET_SCAN_ENABLE_CP_SIZE; # rq.rparam = &status; # rq.rlen = 1; # if (hci_send_req(dd, &rq, to) < 0) # return -1; cmd_pkt = struct.pack("<BB", enable, 0x00) bluez.hci_send_cmd(sock, OGF_LE_CTL, OCF_LE_SET_SCAN_ENABLE, cmd_pkt)