使用MAC地址检测特定蓝牙设备的存在

时间:2014-12-10 13:12:04

标签: python bluetooth pebble-watch

我的最终目标是当我的iphone或卵石手表在附近时,让我的覆盆子pi检测到。我现在专注于鹅卵石,因为我相信iphone随机化MAC地址。我有鹅卵石手表的静态MAC地址。

我的问题是如何通过蓝牙检测MAC地址的存在?

我已尝试hcitool rssi [mac地址]或l2ping [mac地址]但是在响应之前,两者都需要在手表上确认连接。我希望它是自动的...

我也尝试过hcitool扫描,但这需要一段时间,大概是它正在经历所有可能性。我只是想搜索一个特定的Mac地址。

编辑:我刚试过" hcitool名称[Mac地址]"返回设备的名称,如果没有,则返回" null"所以这就是这个想法......有没有相当于它的python?

我是python的新手,所以希望有人可以指出我如何简单地ping mac地址并看看RSSI值有多强?

5 个答案:

答案 0 :(得分:3)

Apple iDevices确实使用具有蓝牙低功耗(BLE)的私有可解析地址。它们每隔约15分钟循环到一个不同的地址。只有具有所谓的身份解析密钥的配对设备才能解密"这些看似随机的地址并将它们关联回配对设备。

所以要用你的iPhone做这样的事情,你需要将它与你的覆盆子pi配对。 然后你可以做的是制作一个简单的iOS应用程序,宣传一些数据(无关紧要,因为当应用程序背景时,只有iOS本身才能将数据放入广告数据包中)。在树莓派上,您可以使用hcitool lescan来扫描BLE广告。如果可以使用IRK解析广告的地址,则可以肯定地知道它是iPhone。我不确定hcitool是否可以开箱即用任何IRK数学,但蓝牙规范明确规定了解析算法。

Pebble目前确实使用固定地址。但是,只有当它与应该连接的手机断开连接时才会进行广告宣传。因此,对于您的用例,使用其BLE广告并不是非常有用。目前,Pebble SDK中没有API允许Pebble上的应用程序公布数据。


FWIW,你提到的命令仅对蓝牙2.1(" Classic")有用,并且可能仅在其他设备可被发现时才有用(基本上没有,除非它在设置/蓝牙中)菜单)。

答案 1 :(得分:3)

感谢Chris,我建立了自己的脚本,检测我的手机是否在范围内并锁定/解锁屏幕,如果设备在超时5秒后仍然离开。 它有点快速和肮脏,但对我有用:)

#!/bin/bash
#################################################################
# Check if Bluetooth device is in range and lock/unlock screen. #
#################################################################

MAC=AA:BB:CC:DD:EE:FF
TIMEOUT=5
DEBUG=0

LASTSEEN=0
STATUS=0
PREVSTATUS=0
while true; do
    DT="[$(date '+%F %T')]"
    pgrep xscreensaver >/dev/null || xscreensaver -no-splash >/dev/null     2>&1 &
    if [ -z "$RSSI" ]; then
        sudo hcitool cc $MAC 2>/dev/null
    fi
    RSSI=$(sudo hcitool rssi $MAC 2>/dev/null | cut -d ' ' -f4)

    [ $DEBUG -gt 0 ] && echo "$DT RSSI: $RSSI"

    if [[ -n "$RSSI" && $RSSI -gt 0  ]]; then
        LASTSEEN=$(date '+%s')
    fi

    if [[ $RSSI -eq 0 && $((`date '+%s'`-$LASTSEEN)) -gt $TIMEOUT ]]; then
        STATUS=0
        [ $DEBUG -gt 0 ] && echo "$DT Status: $STATUS Lastseen: $LASTSEEN     Timeout: $((`date '+%s'`-$LASTSEEN))"
    else
        STATUS=1
        [ $DEBUG -gt 0 ] && echo "$DT Status: $STATUS Lastseen: $LASTSEEN     Timeout: $((`date '+%s'`-$LASTSEEN))"
    fi

    if [ $STATUS -ne $PREVSTATUS ]; then
        PREVSTATUS=$STATUS
        if [ $STATUS -gt 0 ]; then
            [ $DEBUG -gt 0 ] && echo "$DT UnLock"
            pgrep xscreensaver >/dev/null && xscreensaver-command     -deactivate
            xset dpms force on
            pgrep xscreensaver >/dev/null && pkill xscreensaver
        else    
            [ $DEBUG -gt 0 ] && echo "$DT Lock"
            pgrep xscreensaver >/dev/null && xscreensaver-command -lock
        fi
    fi

    [ $DEBUG -gt 0 ] && sleep 1
done

可能需要在/ etc / sudoers中添加一行:

username ALL = NOPASSWD: /usr/bin/hcitool

也许这有助于某人。 干杯!

=========================

更新26.09.2017!

我对此进行了更新,并编写了一个Python脚本,通过 DBus 检测连接的蓝牙设备。因此,BT设备应首先配对。 如果连接丢失,该脚本还会尝试重新连接到设备。这是因为有些设备不能自行重新连接(就像我的手机一样)。 这个脚本没有读取RSSI 信号强度,因为我系统上的DBus没有报告它(不知道为什么)。 因为我在Gnome下,我使用 org.gnome.ScreenSaver 作为DBus接口来锁定屏幕。如果您使用的是KDE或者您希望在代码中更改此内容的任何内容。

#!/usr/local/bin/python3
# encoding: utf-8
'''
bluescreen -- Locks your screen
bluescreen is a little python script which locks your screen as long as a bluetooth device is disconnected.
It also unlocks the screen when you return.
It uses the DBus to check if the device is connected and it locks the screen through DBus message calls.
The script uses the first BT adapter found in the system, mainly "hci0". This might be incorrect on some systems.
If so, check the source code below and do the necessary changes.

@author:     Evil2000
@copyright:  2017 Evil2000
@license:    LGPL
@contact:    evil.2000@web.de
@deffield    updated: 26.09.2017
'''

import time
import dbus
from dbus.mainloop.glib import DBusGMainLoop
from gi.repository import GObject as gobject
from pprint import pprint

'''
Debug flag should be clear
1 = Verbose
2 = Debug
'''
DEBUG = 0

'''
The BT MAC address of the device to monitor
'''
MAC = "11:22:33:AA:BB:CC"

''' =================================================================================================================== '''

# Replace : with _ in device MAC address
DEV_ID = MAC.replace(":", "_")
# Access the DBus main loop
dbus_loop = DBusGMainLoop()
# Connect to the system bus
sysbus = dbus.SystemBus(mainloop=dbus_loop)
# Retrieve the device BlueZ object
device = sysbus.get_object('org.bluez', "/org/bluez/hci0/dev_" + DEV_ID)

# Read the property if the device is connected
deviceConnected = device.Get("org.bluez.Device1", "Connected", dbus_interface='org.freedesktop.DBus.Properties')

if DEBUG > 1:
    pprint(deviceConnected)

# Connect to the session bus
sesbus = dbus.SessionBus(mainloop=dbus_loop)
# Get the screen saver object
sSaver = sesbus.get_object('org.gnome.ScreenSaver', "/org/gnome/ScreenSaver")

# Lock the screen and start the screen saver (i.e. turn off the screen) if it isn't already
def lockScreen():
    if not sSaver.GetActive(dbus_interface='org.gnome.ScreenSaver'):
        if DEBUG:
            print("["+time.strftime('%Y-%m-%d %H:%M:%S')+"] Locking Screen")
        sSaver.Lock(dbus_interface='org.gnome.ScreenSaver')

# Try to connect to the device if it got disconnected. This is called from gobject.timeout_add_seconds() below
def tryConnect():
    if not deviceConnected:
        if DEBUG:
            print("["+time.strftime('%Y-%m-%d %H:%M:%S')+"] Trying device reconnect")
        device.Connect(dbus_interface='org.bluez.Device1')
    return True

# The callback function from connect_to_signal. This handles the events sent by the DBus.
def cb(*args, **kwargs):
    iface = args[0]
    chgprop = args[1]
    #extra = args[2]
    if DEBUG > 1:
        pprint(iface)
        pprint(chgprop)

    # chgprop contains a dictionary with the "Connected" key
    # If it is present and the interface in which the event triggered is Device1, then...
    if iface == "org.bluez.Device1" and "Connected" in chgprop:
        # ... lock screen if device is NOT connected, otherwise disable the screen saver
        if chgprop['Connected'] == True:
            print("["+time.strftime('%Y-%m-%d %H:%M:%S')+"] connected")
            deviceConnected = True
            sSaver.SetActive(False, dbus_interface='org.gnome.ScreenSaver')
        else:
            print("["+time.strftime('%Y-%m-%d %H:%M:%S')+"] disconnected")
            deviceConnected = False
            lockScreen()

# Register a callback function which is triggered if the properties of the bluetooth device changes.
device.connect_to_signal("PropertiesChanged", cb, dbus_interface=None, interface_keyword='iface', member_keyword='member', path_keyword='path', sender_keyword="sender", destination_keyword="dest", message_keyword="message")

# Every 3 seconds, call the tryConnect function
gobject.timeout_add_seconds(3, tryConnect)

# Now, start the main loop.
loop = gobject.MainLoop()
loop.run()

# EOF

答案 2 :(得分:0)

检查PyBluez

要检测附近的设备,PyBluez网站上有一个示例脚本。查看inquiry.py

另一个想法是使用你已经尝试过的hcitool,但使用subprocess让一切都是Python。

答案 3 :(得分:0)

我在iPhone 7和Raspberry Pi上使用此代码,效果很好。 iPhone蓝牙MAC地址是静态的。

#!/bin/bash

sudo hcitool cc AA:BB:CC:DD:EE:FF 2> /dev/null

while true
do
    bt=$(hcitool rssi AA:BB:CC:DD:EE:FF 2> /dev/null)
    if [ "$bt" == "" ]; then
        sudo hcitool cc AA:BB:CC:DD:EE:FF  2> /dev/null
        bt=$(hcitool rssi AA:BB:CC:DD:EE:FF 2> /dev/null)
    fi

    echo "$bt"
done

答案 4 :(得分:0)

谢谢大家,感谢你的答案,来自我的树莓派:

1)避免sudo

sudo setcap cap_net_raw+ep /usr/bin/hcitool 

2)找到设备

hcitool cc "$mac" 2>/dev/null && hcitool rssi "$mac" 2>/dev/null && echo "found $mac"