这是 BeaconScanner.py 文件用来查找和列出 ble 信标的 ScanUtility.py 文件。
#This is a working prototype. DO NOT USE IT IN LIVE PROJECTS
import sys
import struct
import bluetooth._bluetooth as bluez
OGF_LE_CTL=0x08
OCF_LE_SET_SCAN_ENABLE=0x000C
def hci_enable_le_scan(sock):
hci_toggle_le_scan(sock, 0x01)
def hci_disable_le_scan(sock):
hci_toggle_le_scan(sock, 0x00)
def hci_toggle_le_scan(sock, enable):
cmd_pkt = struct.pack("<BB", enable, 0x00)
bluez.hci_send_cmd(sock, OGF_LE_CTL, OCF_LE_SET_SCAN_ENABLE, cmd_pkt)
def packetToString(packet):
"""
Returns the string representation of a raw HCI packet.
"""
if sys.version_info > (3, 0):
return ''.join('%02x' % struct.unpack("B", bytes([x]))[0] for x in packet)
else:
return ''.join('%02x' % struct.unpack("B", x)[0] for x in packet)
def parse_events(sock, loop_count=100):
old_filter = sock.getsockopt( bluez.SOL_HCI, bluez.HCI_FILTER, 14)
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 )
results = []
for i in range(0, loop_count):
packet = sock.recv(255)
ptype, event, plen = struct.unpack("BBB", packet[:3])
packetOffset = 0
dataString = packetToString(packet)
"""
If the bluetooth device is an beacon then show the beacon.
"""
#print (dataString)
if dataString[34:50] == '0303aafe1516aafe' or '0303AAFE1116AAFE':
"""
Selects parts of the bluetooth packets.
"""
broadcastType = dataString[50:52]
if broadcastType == '00' :
type = "Eddystone UID"
namespace = dataString[54:74].upper()
instance = dataString[74:86].upper()
resultsArray = [
{"type": type, "namespace": namespace, "instance": instance}]
return resultsArray
elif broadcastType == '10':
type = "Eddystone URL"
urlprefix = dataString[54:56]
if urlprefix == '00':
prefix = 'http://www.'
elif urlprefix == '01':
prefix = 'https://www.'
elif urlprefix == '02':
prefix = 'http://'
elif urlprefix == '03':
prefix = 'https://'
hexUrl = dataString[56:][:-2]
url = prefix + hexUrl.decode("hex")
rssi, = struct.unpack("b", packet[packetOffset -1])
resultsArray = [{"type": type, "url": url}]
return resultsArray
elif broadcastType == '20':
type = "Eddystone TLM"
resultsArray = [{"type": type}]
return resultsArray
elif broadcastType == '30':
type = "Eddystone EID"
resultsArray = [{"type": type}]
return resultsArray
elif broadcastType == '40':
type = "Eddystone RESERVED"
resultsArray = [{"type": type}]
return resultsArray
if dataString[38:46] == '4c000215':
"""
Selects parts of the bluetooth packets.
"""
type = "iBeacon"
uuid = dataString[46:54] + "-" + dataString[54:58] + "-" + dataString[58:62] + "-" + dataString[62:66] + "-" + dataString[66:78]
major = dataString[78:82]
minor = dataString[82:86]
majorVal = int("".join(major.split()[::-1]), 16)
minorVal = int("".join(minor.split()[::-1]), 16)
"""
Organises Mac Address to display properly
"""
scrambledAddress = dataString[14:26]
fixStructure = iter("".join(reversed([scrambledAddress[i:i+2] for i in range(0, len(scrambledAddress), 2)])))
macAddress = ':'.join(a+b for a,b in zip(fixStructure, fixStructure))
rssi, = struct.unpack("b", packet[packetOffset -1])
resultsArray = [{"type": type, "uuid": uuid, "major": majorVal, "minor": minorVal, "rssi": rssi, "macAddress": macAddress}]
return resultsArray
return results
原始的 Beaconscanner.py 文件通过列出信标来正常工作。
import ScanUtility
import bluetooth._bluetooth as bluez
#Set bluetooth device. Default 0.
dev_id = 0
try:
sock = bluez.hci_open_dev(dev_id)
print ("\n *** Looking for BLE Beacons ***\n")
print ("\n *** CTRL-C to Cancel ***\n")
except:
print ("Error accessing bluetooth")
ScanUtility.hci_enable_le_scan(sock)
#Scans for iBeacons
try:
while True:
returnedList = ScanUtility.parse_events(sock, 10)
for item in returnedList:
print(item)
print("")
except KeyboardInterrupt:
pass
这是修改后的 BeaconScanner.py 文件,如果扫描仪通过其 MAC 地址找到所需的信标,该文件应打印“Works”。
import ScanUtility
import bluetooth._bluetooth as bluez
#Set bluetooth device. Default 0.
dev_id = 0
try:
sock = bluez.hci_open_dev(dev_id)
print ("\n *** Looking for BLE Beacons ***\n")
print ("\n *** CTRL-C to Cancel ***\n")
except:
print ("Error accessing bluetooth")
ScanUtility.hci_enable_le_scan(sock)
#Scans for iBeacons
try:
while True:
returnedList = ScanUtility.parse_events(sock, 10)
for macAddress in returnedList:
if macAddress == "e2:e3:23:d1:b0:54":
print("Works")
else:
print("Nope")
except KeyboardInterrupt:
pass
然而,修改后的文件总是打印“Nope”。我认为 if 语句中的“macAddress”部分不能用于识别信标。必须在代码中更改哪些内容才能通过 if 语句中的 MAC 地址来识别信标?