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

2024-05-15 12:06:51 发布

您现在位置:Python中文网/ 问答频道 /正文

我的最终目标是让我的树莓皮检测到我的iphone或pebble手表就在附近。我现在正在关注pebble,因为我相信iphone会随机化MAC地址。我有pebble手表的静态MAC地址。

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

我试过hcitool rssi[mac address]或l2ping[mac address],但是在任何响应之前,这两个都需要在监视上确认连接。我希望它是自动的。。。

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

编辑:我刚刚试过“hcitool name[Mac Address]”,它返回设备的名称,如果没有,它会返回一个“null”,所以这是我的想法。。。有没有类似的python?

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


Tags: addressmac地址静态可能性树莓经历iphone
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

也许这对某人有帮助。 干杯!

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

更新日期:2017年9月26日!

我对此进行了一些更新,并编写了一个Python脚本,该脚本通过DBus检测连接的蓝牙设备。因此,应首先对BT设备进行配对。 如果连接丢失,脚本还会尝试重新连接到设备。这是因为有些设备无法自行重新连接(就像我的手机一样)。 这个脚本没有读取RSSI的信号强度,因为系统上的dbu没有报告它(不知道为什么)。 因为我在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

检查PyBluez

为了检测附近的设备,PyBluez网站上有一个示例scrip。检查inquiry.py

另一个想法是使用您已经尝试过的hcitool,但是使用subprocess来拥有所有东西是Python。

Apple iDevices确实使用了蓝牙低能耗(BLE)专用可解析地址。他们每隔大约15分钟就换一个地址。只有具有所谓身份解析密钥的成对设备才能“破译”这些看似随机的地址,并将它们与成对设备关联起来。

所以要想用你的iPhone做这样的事情,你需要把它和你的覆盆子皮配对。 然后,你可以做一个简单的iOS应用程序,为一些数据做广告(没关系的是,当应用程序被备份时,只有iOS自己才能将数据放入广告包)。在覆盆子pi上,然后可以使用hcitool lescan扫描BLE广告。如果广告的地址可以用IRK来解析,那么你很肯定地知道那是iPhone。我不确定hcitool是否有现成的IRK计算,但是解析算法是由蓝牙规范很好地指定的

Pebble目前确实使用固定地址。然而,只有当它与本应连接的手机断开连接时,它才是广告。因此,对于您的用例,使用它的BLE广告不是很有用。目前,Pebble SDK中没有允许Pebble上的应用程序公布数据的API。


FWIW,你提到的命令只对蓝牙2.1(“经典”)有用,可能只有在其他设备可以被发现时才有用(基本上永远不会,除非它在设置/蓝牙菜单中)。

相关问题 更多 >