First off if anybody knows of a good tutorial for coding bluetooth on my raspberry pi zero w with python to turn on discovery, listen for a pair request, connect and save the paired device, and more, that would be awesome. My code for testing bluetooth discovery is below.
import bluetooth
print("performing inquiry...")
nearby_devices = bluetooth.discover_devices(
duration=8, lookup_names=True, flush_cache=True)
print("found %d devices" % len(nearby_devices))
for addr, name in nearby_devices:
try:
print(" %s - %s" % (addr, name))
except UnicodeEncodeError:
print(" %s - %s" % (addr, name.encode('utf-8', 'replace')))
The TraceBack is below
Traceback (most recent call last):
File "bluetoothConnect.py", line 6, in <module>
duration=8, lookup_names=True, flush_cache=True)
File "/usr/lib/python2.7/dist-packages/bluetooth/bluez.py", line 17, in discover_devices
sock = _gethcisock ()
File "/usr/lib/python2.7/dist-packages/bluetooth/bluez.py", line 226, in _gethcisock
raise BluetoothError ("error accessing bluetooth device")
bluetooth.btcommon.BluetoothError: error accessing bluetooth device
("error accessing bluetooth device") is the clue.
Yes - as earlier mentioned you need elevated privileges.
Simply run the script with sudo...
eg - sudo python myscript.py
enter your password
It should now work..for testing purposes.
Though going forward I would create a privileged user and add that user to the root group with the setting /bin/false.
Then use that user to run all your scripts..
Had the same issue and then I wrote this simple script to wrap Bluetoothctl using python3. Tested on Raspberry pi 4.
import subprocess
import time
def scan(scan_timeout=20):
""" scan
Scan for devices
Parameters
----------
scan_timeout : int
Timeout to run the scan
Returns
----------
devices : dict
set of discovered devices as MAC:Name pairs
"""
p = subprocess.Popen(["bluetoothctl", "scan", "on"])
time.sleep(scan_timeout)
p.terminate()
return __devices()
def __devices():
""" devices
List discovered devices
Returns
----------
devices : dict
set of discovered devices as MAC:Name pairs
"""
devices_s = subprocess.check_output("bluetoothctl devices", shell=True).decode().split("\n")[:-1]
devices = {}
for each in devices_s:
devices[each[7:24]] = each[25:]
return devices
def info():
""" Info
Returns
----------
info : str
information about the device connected currently if any
"""
return subprocess.check_output("bluetoothctl info", shell=True).decode()
def pair(mac_address):
""" pair
Pair with a device
Parameters
----------
mac_address : str
mac address of the device tha you need to pair
"""
subprocess.check_output("bluetoothctl pair {}".format(mac_address), shell=True)
def remove(mac_address):
""" remove
Remove a connected(paired) device
Parameters
----------
mac_address : str
mac address of the device tha you need to remove
"""
subprocess.check_output("bluetoothctl remove {}".format(mac_address), shell=True)
def connect(mac_address):
""" connect
Connect to a device
Parameters
----------
mac_address : str
mac address of the device tha you need to connect
"""
subprocess.check_output("bluetoothctl connect {}".format(mac_address), shell=True)
def disconnect():
""" disconnect
Disconnects for currently connected device
"""
subprocess.check_output("bluetoothctl disconnect", shell=True)
def paired_devices():
""" paired_devices
Return a list of paired devices
"""
return subprocess.check_output("bluetoothctl paired-devices", shell=True).decode()
Related
A little bit of background, I want to use my Pi to emulate a bluetooth keyboard for my phone.
I have actually managed to get it to work with my phone but I'm having a hard time with automatic connection.
I want the pi to scan nearby devices and initiate connection with already paired devices but for some reason it doesn't work.
If my pi is connected to a screen (my screen has a built in speaker) than for some reason automatic connection only connects to audio profiles and I have to manually connect to the HID profile, if my pi is not connected to a screen it just can't connect at all and I'm getting
org.bluez.Error.Failed: Protocol not available
when I'm trying to view the bluetooth status using sudo systemctl status bluetooth I get a hint about what protocol is missing.. this is the output:
● bluetooth.service - Bluetooth service
Loaded: loaded (/lib/systemd/system/bluetooth.service; enabled; vendor preset: enabled)
Active: active (running) since Wed 2021-08-11 11:43:46 IDT; 52min ago
Docs: man:bluetoothd(8)
Main PID: 627 (bluetoothd)
Status: "Running"
Tasks: 1 (limit: 4915)
CGroup: /system.slice/bluetooth.service
└─627 /usr/lib/bluetooth/bluetoothd -P input
Aug 11 11:57:37 raspberrypi bluetoothd[627]: a2dp-source profile connect failed for {DEVICE MAC}: Protocol not available
Aug 11 12:00:53 raspberrypi bluetoothd[627]: Endpoint registered: sender=:1.96 path=/MediaEndpoint/A2DPSource
Aug 11 12:00:53 raspberrypi bluetoothd[627]: Endpoint registered: sender=:1.96 path=/MediaEndpoint/A2DPSink
Aug 11 12:01:10 raspberrypi bluetoothd[627]: Endpoint unregistered: sender=:1.96 path=/MediaEndpoint/A2DPSource
Aug 11 12:01:10 raspberrypi bluetoothd[627]: Endpoint unregistered: sender=:1.96 path=/MediaEndpoint/A2DPSink
Aug 11 12:04:43 raspberrypi bluetoothd[627]: a2dp-source profile connect failed for {DEVICE MAC}: Protocol not available
Aug 11 12:05:02 raspberrypi bluetoothd[627]: a2dp-source profile connect failed for {DEVICE MAC}: Protocol not available
Aug 11 12:28:12 raspberrypi bluetoothd[627]: a2dp-source profile connect failed for {DEVICE MAC}: Protocol not available
Aug 11 12:28:27 raspberrypi bluetoothd[627]: a2dp-source profile connect failed for {DEVICE MAC}: Protocol not available
Aug 11 12:28:40 raspberrypi bluetoothd[627]: a2dp-source profile connect failed for {DEVICE MAC}: Protocol not available
I feel like I've tried everything at this point, the lack of online documentation/information is really frustrating.
I have even purged pulseaudio completely from my device in hopes that it would stop trying to connect to audio profiles but it didn't work.
Here is some of the code that I think is relevant:
The device class
class BTKbDevice:
"""This class is used to define the bluetooth controller properties and capabilities"""
def __init__(self):
# Set up device
system_helper.init_device()
# log periodical scan results
ScanLogHelper().run()
# Declare class fields
self.server_control_port = None
self.server_interrupt_port = None
self.client_control_port = None
self.client_interrupt_port = None
# define some constants
self.__CONTROL_PORT = 17 # Service port - must match port configured in SDP record
self.__INTERRUPTION_PORT = 19 # Interrupt port - must match port configured in SDP record
self.__CURRENTLY_CONNECTED_DEVICE = "" # Used for logging connection/disconnection events
print("device started")
# listen for incoming client connections
def listen(self):
# We are not using BluetoothSocket constructor to have access to setsockopt method later
# instead we use the native socket equivalent
self.server_control_port = socket.socket(
socket.AF_BLUETOOTH, socket.SOCK_SEQPACKET, socket.BTPROTO_L2CAP) # BluetoothSocket(L2CAP)
self.server_interrupt_port = socket.socket(
socket.AF_BLUETOOTH, socket.SOCK_SEQPACKET, socket.BTPROTO_L2CAP) # BluetoothSocket(L2CAP)
# This allows the system to reuse the same port for different connections
# this is useful for situations where for some reason the port wasn't closed properly
# i.e. crashes, keyboard interrupts etc.
self.server_control_port.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
self.server_interrupt_port.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
# bind these sockets to a port
# use BDADDR_ANY because we are only really interested in defining a constant port
self.server_control_port.bind((socket.BDADDR_ANY, self.__CONTROL_PORT))
self.server_interrupt_port.bind((socket.BDADDR_ANY, self.__INTERRUPTION_PORT))
# Start listening on the server sockets
self.server_control_port.listen(1)
self.server_interrupt_port.listen(1)
# Wait for connections
# the accept() method will block code execution until a connection was established
self.client_control_port, client_information = self.server_control_port.accept()
self.client_interrupt_port, client_information = self.server_interrupt_port.accept()
# We need to remember the connected device for disconnection logging
# client_information[0] is device's mac address
self.__CURRENTLY_CONNECTED_DEVICE = client_information[0]
def device_disconnected(self):
self.__CURRENTLY_CONNECTED_DEVICE = ""
def is_currently_connected_exists(self):
return self.__CURRENTLY_CONNECTED_DEVICE != ""
def get_currently_connected_device(self):
return self.__CURRENTLY_CONNECTED_DEVICE
# Cleanup
def close_connections(self):
self.server_control_port.close()
self.server_interrupt_port.close()
self.client_control_port.close()
self.client_interrupt_port.close()
The service class
class BTKbService(dbus.service.Object):
def __init__(self):
# set up as a dbus service
bus_name = dbus.service.BusName(
"org.thanhle.btkbservice", bus=dbus.SystemBus())
dbus.service.Object.__init__(
self, bus_name, "/org/thanhle/btkbservice")
print("service started. starting device")
# create and setup our device
self.device = BTKbDevice()
# start listening for connections
self.device.listen()
system_helper.py
"""A utility for handling system related operations and events"""
UUID = "00001124-0000-1000-8000-00805f9b34fb"
# Get available bluetooth devices list from system
def get_controllers_info():
return subprocess.getoutput("hcitool dev")
# Check if our device is available
def is_controller_available():
device_data = get_controllers_info()
return const.MY_ADDRESS in device_data.split()
# Handle device initialization
def init_device():
__init_hardware()
__init_bluez_profile()
# Configure the bluetooth hardware device
def __init_hardware():
# Reset everything to make sure there are no problems
os.system("hciconfig hci0 down")
os.system("systemctl daemon-reload")
os.system("/etc/init.d/bluetooth start")
# Activate device and set device name
os.system("hciconfig hci0 up")
os.system("hciconfig hci0 name " + const.MY_DEV_NAME)
# make the device discoverable
os.system("hciconfig hci0 piscan")
# set up a bluez profile to advertise device capabilities from a loaded service record
def __init_bluez_profile():
# read and return an sdp record from a file
service_record = __read_sdp_service_record()
# setup profile options
opts = {
"AutoConnect": True,
"RequireAuthorization": False,
"ServiceRecord": service_record
}
# retrieve a proxy for the bluez profile interface
bus = dbus.SystemBus()
manager = dbus.Interface(bus.get_object(
"org.bluez", "/org/bluez"), "org.bluez.ProfileManager1")
manager.RegisterProfile("/org/bluez/hci0", UUID, opts)
# Set device class
os.system("hciconfig hci0 class 0x0025C0")
def __read_sdp_service_record():
try:
fh = open(const.SDP_RECORD_PATH, "r")
except OSError:
sys.exit("Could not open the sdp record. Exiting...")
return fh.read()
def get_connected_devices_data():
return subprocess.getoutput("hcitool con")
def get_paired_devices_data():
return subprocess.getoutput("bluetoothctl paired-devices")
connection_helper.py
The method initiate_connection_with_devices_in_range get's called every 10 seconds or so by another file that isn't relevant to this problem.
""" Responsible for finding paired devices in range and attempting connection with them """
def initiate_connection_with_devices_in_range(nearby_devices):
print("init connection started")
# Get paired devices from system
paired_devices = system_helper.get_paired_devices_data()
print("Paired device:\n" + paired_devices)
# Check nearby devices for a match
# no need to request data from bus if no paired device is available
for device in nearby_devices:
mac, name = device
print("checking for device " + name + " " + mac)
if mac in paired_devices.split():
print(name + " is paired, let's attempt connection")
# Paired device found, try to connect
__attempt_connection()
def __attempt_connection():
print("attempting connection")
# Get reference for the bus object, and for the objects it manages
bus = dbus.SystemBus()
manager = dbus.Interface(bus.get_object("org.bluez", "/"),
"org.freedesktop.DBus.ObjectManager")
objects = manager.GetManagedObjects()
# Extract device objects from bus
all_devices = (str(path) for path, interfaces in objects.items() if
"org.bluez.Device1" in interfaces.keys())
# Extract only devices managed by our adapter
device_list = None
for path, interfaces in objects.items():
if "org.bluez.Adapter1" not in interfaces.keys():
continue
device_list = [d for d in all_devices if d.startswith(path + "/")]
if device_list is not None:
print(device_list)
# Devices found, attempt connection
for dev_path in device_list:
print("trying to connect keyboard profile with " + dev_path)
dev_obj = bus.get_object('org.bluez', dev_path)
methods = dbus.Interface(dev_obj, 'org.bluez.Device1')
props = dbus.Interface(dev_obj, dbus.PROPERTIES_IFACE)
try:
methods.Connect()
except Exception as e:
print("Exception caught in connect method! {}".format(e))
# this actually print Exception caught in connect method! org.bluez.Error.Failed: Protocol not available
If I manually connect from my phone it works just fine, only automatic connection is problematic at the moment.
ANY help would be appreciated, most of what I did so far is the result of trial and error so it's possible that I made a mistake somewhere
I think that at the moment the pi "wants" to connect as an audio device but lacks ability to do so as it is not connected to any hardware that will allow it.. So somehow I need to make it "forget" about the audio profiles.
I would gladly provide more information if needed.
This does seem a little back to front as you have the peripheral trying to connect to the phone. Have you looked at using ConnectProfile rather than Connect?
If you want to have the HID device initiating connection (or reconnection) to HID host (RPi reconnects to your phone), then that is a change in the SDP record. More information at the following gist
I am working on a project that connects an Android device with a Raspberry Pi. The RPi needs to be treated like a deployable device that the user never needs to touch. For this reason, I am trying to write a startup batch script on the RPi that will allow the user to pair their Android with the PI.
My idea is that when you startup, this script will run, the user on their phone will try and connect to the RPi, and the RPi will automatically accept this connection.
Here is what I have so far
#!/bin/bash
bluetoothctl -- discoverable on
bluetoothctl -- pairable on
bluetoothctl -- agent on
bluetoothctl -- default-agent
The issue is, when I do it this way I don't get into the [bluetoothctl] prompt that I need to communicate with the Android.
When I run these commands (Without batch script) and try and pair with my Android I get
Request confirmation
[agent] Confirm passkey 861797 (yes/no): yes
And from here I simply need to input yes to instantiate the connection. The issue I'm seeing is 1: I don't know how to stay in the [bluetoothctl] prompt within the command line to communicate with the device and 2: I don't know how to send "Yes" to the prompt.
Again, the important thing for me is that the user never needs to do anything more to the RPi than start it up for deployment purposes. Is there a fix for my problem or perhaps a better way to do it all together?
For those interested, the bluetooth startup connection is in place so that I can send network information to the RPi and it can automatically connect itself to the network so that the main application communication will take place that way.
Here is the desired result of the script which I was able to do manually.
Using bluetoothctl in that manner can be problematic as it is not designed to be interactive in that way. As you have put Python as one of the tags, the intended way of accessing this functionality from Python (and other languages) is through the D-Bus API.
These are documented at: https://git.kernel.org/pub/scm/bluetooth/bluez.git/tree/doc
And there are examples at: https://git.kernel.org/pub/scm/bluetooth/bluez.git/tree/test
The confirmation is the RequestConfirmation in the agent API. You can also set discoverable and pairable with the adapter API. Using the API will also allow you to stop discoverable from timing out.
Once the phone has connected, you typically want to mark it as trusted so that it doesn't need to pair again. This is done with the device API.
Below is an example of setting these properties on the adapter with Python. I have left all of the Agent functions in although it is only the RequestConfirmation that is used. I have set it to always agree to whatever code it is sent which is what you asked for in your question.
This example Python script would replace your batch script
import dbus
import dbus.service
import dbus.mainloop.glib
from gi.repository import GLib
BUS_NAME = 'org.bluez'
ADAPTER_IFACE = 'org.bluez.Adapter1'
ADAPTER_ROOT = '/org/bluez/hci'
AGENT_IFACE = 'org.bluez.Agent1'
AGNT_MNGR_IFACE = 'org.bluez.AgentManager1'
AGENT_PATH = '/my/app/agent'
AGNT_MNGR_PATH = '/org/bluez'
CAPABILITY = 'KeyboardDisplay'
DEVICE_IFACE = 'org.bluez.Device1'
dbus.mainloop.glib.DBusGMainLoop(set_as_default=True)
bus = dbus.SystemBus()
def set_trusted(path):
props = dbus.Interface(bus.get_object(BUS_NAME, path), dbus.PROPERTIES_IFACE)
props.Set(DEVICE_IFACE, "Trusted", True)
class Agent(dbus.service.Object):
#dbus.service.method(AGENT_IFACE,
in_signature="", out_signature="")
def Release(self):
print("Release")
#dbus.service.method(AGENT_IFACE,
in_signature='o', out_signature='s')
def RequestPinCode(self, device):
print(f'RequestPinCode {device}')
return '0000'
#dbus.service.method(AGENT_IFACE,
in_signature="ou", out_signature="")
def RequestConfirmation(self, device, passkey):
print("RequestConfirmation (%s, %06d)" % (device, passkey))
set_trusted(device)
return
#dbus.service.method(AGENT_IFACE,
in_signature="o", out_signature="")
def RequestAuthorization(self, device):
print("RequestAuthorization (%s)" % (device))
auth = input("Authorize? (yes/no): ")
if (auth == "yes"):
return
raise Rejected("Pairing rejected")
#dbus.service.method(AGENT_IFACE,
in_signature="o", out_signature="u")
def RequestPasskey(self, device):
print("RequestPasskey (%s)" % (device))
set_trusted(device)
passkey = input("Enter passkey: ")
return dbus.UInt32(passkey)
#dbus.service.method(AGENT_IFACE,
in_signature="ouq", out_signature="")
def DisplayPasskey(self, device, passkey, entered):
print("DisplayPasskey (%s, %06u entered %u)" %
(device, passkey, entered))
#dbus.service.method(AGENT_IFACE,
in_signature="os", out_signature="")
def DisplayPinCode(self, device, pincode):
print("DisplayPinCode (%s, %s)" % (device, pincode))
class Adapter:
def __init__(self, idx=0):
bus = dbus.SystemBus()
self.path = f'{ADAPTER_ROOT}{idx}'
self.adapter_object = bus.get_object(BUS_NAME, self.path)
self.adapter_props = dbus.Interface(self.adapter_object,
dbus.PROPERTIES_IFACE)
self.adapter_props.Set(ADAPTER_IFACE,
'DiscoverableTimeout', dbus.UInt32(0))
self.adapter_props.Set(ADAPTER_IFACE,
'Discoverable', True)
self.adapter_props.Set(ADAPTER_IFACE,
'PairableTimeout', dbus.UInt32(0))
self.adapter_props.Set(ADAPTER_IFACE,
'Pairable', True)
if __name__ == '__main__':
agent = Agent(bus, AGENT_PATH)
agnt_mngr = dbus.Interface(bus.get_object(BUS_NAME, AGNT_MNGR_PATH),
AGNT_MNGR_IFACE)
agnt_mngr.RegisterAgent(AGENT_PATH, CAPABILITY)
agnt_mngr.RequestDefaultAgent(AGENT_PATH)
adapter = Adapter()
mainloop = GLib.MainLoop()
try:
mainloop.run()
except KeyboardInterrupt:
agnt_mngr.UnregisterAgent(AGENT_PATH)
mainloop.quit()
On my raspberry pi 4 with bluez the following will accept my android phones pairing without the need to type anything on the raspberry.
sudo apt install bluez-tools
sudo bt-agent -c DisplayOnly -p ~/pins.txt &
pins.txt:
00:00:00:00:00:00 *
* *
Note that adding -d to bt-agent did not work for, no matter the -c arguments. Hence the ampersand at the end.
I need all connected bluetooth devices to my computer.
I found library, but i can't get connected devices
Simple inquiry example:
import bluetooth
nearby_devices = bluetooth.discover_devices(lookup_names=True)
print("Found {} devices.".format(len(nearby_devices)))
for addr, name in nearby_devices:
print(" {} - {}".format(addr, name))
The snippet of code in the question is doing a scan for new devices rather than reporting on connected devices.
The PyBluez library is not under active development so I tend to avoid it.
BlueZ (the Bluetooth stack on Linux) offers a set of API's through D-Bus that are accessible with Python using D-Bus bindings. I prefer pydbus for most situations.
The BlueZ API is documented at:
https://git.kernel.org/pub/scm/bluetooth/bluez.git/tree/doc/adapter-api.txt
https://git.kernel.org/pub/scm/bluetooth/bluez.git/tree/doc/device-api.txt
As an example of how to implement this in Python3:
import pydbus
bus = pydbus.SystemBus()
adapter = bus.get('org.bluez', '/org/bluez/hci0')
mngr = bus.get('org.bluez', '/')
def list_connected_devices():
mngd_objs = mngr.GetManagedObjects()
for path in mngd_objs:
con_state = mngd_objs[path].get('org.bluez.Device1', {}).get('Connected', False)
if con_state:
addr = mngd_objs[path].get('org.bluez.Device1', {}).get('Address')
name = mngd_objs[path].get('org.bluez.Device1', {}).get('Name')
print(f'Device {name} [{addr}] is connected')
if __name__ == '__main__':
list_connected_devices()
I found a solution, but it uses terminal.
Before using you need to install dependencies
Bluez
Code
def get_connected_devices():
bounded_devices = check_output(['bt-device', '-l']).decode().split("\n")[1:-1]
connected_devices = list()
for device in bounded_devices:
name = device[:device.rfind(' ')]
#mac_address regex
regex = '([0-9A-Fa-f]{2}[:-]){5}([0-9A-Fa-f]{2})|([0-9a-fA-F]{4}\\.[0-9a-fA-F]{4}\\.[0-9a-fA-F]{4})$'
mac_address = re.search(regex, device).group(0)
device_info = check_output(['bt-device', '-i', mac_address]).decode()
connection_state = device_info[device_info.find('Connected: ') + len('Connected: ')]
if connection_state == '1':
connected_devices.append({"name": name, "address": mac_address})
return connected_devices
For test purposes, I want to connect a USB device and want to check what is the speed (HS/FS/LS).
I am able to access to Device Descriptor, Endpoint descriptor, interface descriptor but I would like to know the device address which has been allocated by the OS (windows 7)
My code so far :
import usb
busses = usb.busses()
for bus in busses:
for dev in bus.devices:
if dev.idVendor == vendor_id and dev.idProduct == product_id:
print ("Test vehicle %s device FOUND!" %protocol)
print ("iManufacturer : %s" %usb.util.get_string(dev.dev, 256, 1))
print ("iProduct : %s" %usb.util.get_string(dev.dev, 256, 2))
print ("iSerialNumber : %s" %usb.util.get_string(dev.dev, 256, 3))
return dev
print ("Test vehicle %s device NOT FOUND!" %protocol)
Returns :
C:\Python27\Lib\site-packages>python example.py
Test vehicle HS device FOUND!
iManufacturer : Kingston
iProduct : DataTraveler 2.0
iSerialNumber : 5B720A82364A
In the very useful USBview software, there is a section :
ConnectionStatus: DeviceConnected
Current Config Value: 0x01
Device Bus Speed: High
Device Address: 0x09
Open Pipes: 2
How do I get these informations ? is it a query to the USB device using pyUSB ? or is it a query to sys ?
Thanks for any help.
There are several more fields available in the device objects (in your code these are named dev).
A quick and dirty way to look at them
def print_internals(dev):
for attrib in dir(dev):
if not attrib.startswith('_') and not attrib == 'configurations':
x=getattr(dev, attrib)
print " ", attrib, x
for config in dev.configurations:
for attrib in dir(config):
if not attrib.startswith('_'):
x=getattr(config, attrib)
print " ", attrib, x
And call it within your "for dev in bus.devices" loop. It looks like the filename might correspond to 'device address', though bus speed is a bit deeper in (dev.configurations[i].interfaces[j][k].interfaceProtocol), and this only has an integer. usb.util might be able to provide you more information based on those integers, but I don't have that module available to me.
Documentation for pyUSB doesn't seem to be very extensive, but this SO question points at the libusb docs which it wraps up.
You can get usb device speed information by pyUSB with this patch https://github.com/DeliangFan/pyusb/commit/a882829859cd6ef3c91ca11870937dfff93fea9d.
Because libusb1.0 has already support to get usb speed information.
These attributes are (nowadays) easily accessible. At least it works for me. https://github.com/pyusb/pyusb/blob/master/usb/core.py
import usb.core
devices = usb.core.find(find_all=True)
dev = next(devices)
print("device bus:", dev.bus)
print("device address:", dev.address)
print("device port:", dev.port_number)
print("device speed:", dev.speed)
Im trying to make a algorithm in python to detect if my phone is in the area. Im using this to find my device:
bluetooth.discover_devices()
But it only detects my phone if I set my Bluetooth on my phone to "visible".
Is there a function or command to detect my phone when it's set to hidden?
Im fairly new to python so any form of help is very welcome!
Thanks in advance!
You could attempt to connect to your phone. If it's nearby, the connection will succeed. Devices can be connectable when they are not discoverable. You would have to already know the device address of your phone (via discovery when your phone was visible) in order to initiate the connection.
Not sure if a solution is still needed (I think this is right, just haven't been succesful with it). A book entitled "Violent Python" gives a solution for this in chapter 5, but I haven't been successful in implementing it. Supposedly you just need to increment the MAC address of the devices wifi adapter by one to calculate the Bluetooth MAC.
def retBtAddr(addr):
btAddr=str(hex(int(addr.replace(':', ''), 16) + 1))[2:]
btAddr=btAddr[0:2]+":"+btAddr[2:4]+":"+btAddr[4:6]+":"+\
btAddr[6:8]+":"+btAddr[8:10]+":"+btAddr[10:12]
return btAddr
and then something like the following (where OUI is the first 24 bytes of BT MAC)
def checkBluetooth(btAddr):
btName = lookup_name(btAddr)
if btName:
print '[+] Detected Bluetooth Device: ' + btName
else:
print '[-] Failed to Detect Bluetooth Device.'
def wifiPrint(pkt):
iPhone_OUI = 'd0:23:db'
if pkt.haslayer(Dot11):
wifiMAC = pkt.getlayer(Dot11).addr2
if wifiMAC != None and iPhone_OUI == wifiMAC[:8]:
print '[*] Detected iPhone MAC: ' + wifiMAC
btAddr = retBtAddr(wifiMAC)
print '[+] Testing Bluetooth MAC: ' + btAddr
checkBluetooth(btAddr)