我用python中的Bluez(5.49版)编写了一个程序.目标是发送广告包(IBeacon),并使用嗅探器将其解包并保存主要、次要和RSSI(如果UUID是正确的).主要值和次要值是用于发送数据的广告频道.
首先,我使用两个模块Sena Parani-UD100.一个人发送信息,另一个人接收信息.接收器工作得非常好,我用手机上的一个应用程序测试了它,该应用程序可以发送广告包裹,它可以让它们非常迅速地完成我预期的接收包裹的操作.
所以当我用另一个模块发送信息时,问题来了,它每秒只发送一次广告包(实际上,大约1.3-1.4秒),我不知道问题出在哪里,为什么要花那么多时间.
以下是我的代码:
import sys
import argparse
import os
import signal
import time
import struct
import bluetooth._bluetooth as bluez
import blescan
import random
import re
# Configurable parameters
intervalm = 1000
intervalM = 1000
tx = -55
# HCI BLE CORE COMMANDS
LE_META_EVENT = 0x3e
LE_PUBLIC_ADDRESS=0x00
LE_RANDOM_ADDRESS=0x01
LE_SET_SCAN_PARAMETERS_CP_SIZE=7
OGF_LE_CTL=0x08
OCF_LE_SET_SCAN_PARAMETERS=0x000B
OCF_LE_SET_SCAN_ENABLE=0x000C
OCF_LE_CREATE_CONN=0x000D
OCF_LE_SET_ADVERTISING_PARAMETERS=0x0006
OCF_LE_SET_ADVERTISING_DATA=0x0008
OCF_LE_SET_ADVERTISE_ENABLE=0x000A
OCF_LE_SET_RANDOM_MAC=0x0005
LE_ROLE_MASTER = 0x00
LE_ROLE_SLAVE = 0x01
# these are actually subevents of LE_META_EVENT
EVT_LE_CONN_COMPLETE=0x01
EVT_LE_ADVERTISING_REPORT=0x02
EVT_LE_CONN_UPDATE_COMPLETE=0x03
EVT_LE_READ_REMOTE_USED_FEATURES_COMPLETE=0x04
# Advertisment event types
ADV_IND=0x00
ADV_DIRECT_IND=0x01
ADV_SCAN_IND=0x02
ADV_NONCONN_IND=0x03
ADV_SCAN_RSP=0x04
def randomMAC():
return [ 0x1A, 0x3A, 0x3e,
random.randint(0x00, 0x7f),
random.randint(0x00, 0xff),
random.randint(0x00, 0xff)]
def macCanal():
return [0x11,0x11,0x11,0x11,0x11,0x11]
def printpacket(pkt):
for c in pkt:
sys.stdout.write("%02x " % struct.unpack("B",c)[0])
def hci_le_set_advertising_parameters(sock, interval_min, interval_max, canal):
min1 = interval_min/0.625
max1 = interval_max/0.625
if canal == 37:
advertising_channel_map = 0x01 # 0b00000001
elif canal == 38:
advertising_channel_map = 0x02 # 0b00000010
elif canal == 39:
advertising_channel_map = 0x04 # 0b00000100
else:
advertising_channel_map = 0x07 # Other channels
cmd_pkt = struct.pack("<HHBBBBBB", int(min1), int(max1), ADV_NONCONN_IND, 0x00, 0x00, 0x00, advertising_channel_map, 0x00)
bluez.hci_send_cmd(sock, OGF_LE_CTL, OCF_LE_SET_ADVERTISING_PARAMETERS, cmd_pkt)
def hci_le_set_advertising_data(sock, minor, major, txpower):
min = minor
print("Minor:", min)
maj = major
print("major: ", maj)
tx = txpower
print("tx power: ", tx)
#uu = uuid.uuid4().hex
uu="11111111111111111111111111111002"
print ("UUID: ", uu)
uui = re.findall('.{1,2}', uu)
txp = struct.pack(">h", int(tx))
txup = struct.unpack("<h", txp)
cmd_pkt = struct.pack(">BBBBBBBBBBBBBBBBBBBBBBBBBBHHh", 0x1E, 0x02, 0x01, 0x1A, 0x1A, 0xFF, 0x4C, 0x00, 0x02, 0x15, int(uui[0], 16), int(uui[1], 16), int(uui[2], 16), int(uui[3], 16), int(uui[4], 16), int(uui[5], 16), int(uui[6], 16), int(uui[7], 16), int(uui[8], 16), int(uui[9], 16), int(uui[10], 16), int(uui[11], 16), int(uui[12], 16), int(uui[13], 16), int(uui[14], 16), int(uui[15], 16), int(min), int(maj), int(txup[0]))
bluez.hci_send_cmd(sock, OGF_LE_CTL, OCF_LE_SET_ADVERTISING_DATA, cmd_pkt)
def hci_enable_le_advertise(sock):
hci_toggle_le_advertise(sock, 0x01)
def hci_disable_le_advertise(sock):
hci_toggle_le_advertise(sock, 0x00)
def hci_toggle_le_advertise(sock, enable):
cmd_pkt = struct.pack("<B", enable)
bluez.hci_send_cmd(sock, OGF_LE_CTL, OCF_LE_SET_ADVERTISE_ENABLE, cmd_pkt)
def hci_set_random_mac(sock, canal):
mac = macCanal() #BREAKPOINT#################
if canal == 37:
print(canal)
cmd_pkt = struct.pack("<BBBBBB", 55, mac[4], mac[3], mac[2], mac[1], mac[0])
bluez.hci_send_cmd(sock, OGF_LE_CTL, OCF_LE_SET_RANDOM_MAC, cmd_pkt)
elif canal == 38:
print(canal)
cmd_pkt = struct.pack("<BBBBBB", 56, mac[4], mac[3], mac[2], mac[1], mac[0])
bluez.hci_send_cmd(sock, OGF_LE_CTL, OCF_LE_SET_RANDOM_MAC, cmd_pkt)
elif canal == 39:
print(canal)
cmd_pkt = struct.pack("<BBBBBB", 57, mac[4], mac[3], mac[2], mac[1], mac[0])
bluez.hci_send_cmd(sock, OGF_LE_CTL, OCF_LE_SET_RANDOM_MAC, cmd_pkt)
else:
print("Tres canales")
cmd_pkt = struct.pack("<BBBBBB", mac[5], mac[4], mac[3], mac[2], mac[1], mac[0])
bluez.hci_send_cmd(sock, OGF_LE_CTL, OCF_LE_SET_RANDOM_MAC, cmd_pkt)
########################################################################################################################
def showAdapters():
os.system("sudo hcitool dev")
def signal_handler(signal, frame):
print("You pressed Ctrl+C")
blescan.hci_disable_le_advertise(sock)
sys.exit(0)
signal.signal(signal.SIGINT, signal_handler)
parser = argparse.ArgumentParser()
parser.add_argument("-i","--id", type=int, help="device id")
parser.add_argument("-d", "--devices", action="store_true", help="Show devices")
parser.add_argument("-t","--tx", type=int, help="Tx power")
parser.add_argument("-u","--intervalm", type=int, help="Interval min")
parser.add_argument("-U","--intervalM", type=int, help="Interval max")
parser.add_argument("-s","--sleep", type=int, help="Sleep time")
args = parser.parse_args()
if args.sleep == None:
sleep = 1
else:
sleep = args.sleep
if args.intervalm == None:
intervalm = intervalm
else:
intervalm = args.intervalm
if args.intervalM == None:
intervalM = intervalM
else:
intervalM = args.intervalM
if intervalM < intervalm:
print("Max interval is smaller than min interval.")
sys.exit(2)
if args.tx == None:
tx = tx
else:
tx = args.tx
if args.id == None:
args.id = 1
if args.devices:
showAdapters()
sys.exit(2)
try:
sock = bluez.hci_open_dev(args.id)
print("ble thread started")
except:
print("error accessing bluetooth device")
sys.exit(1)
channel = 37 # First advertisement channel
while True:
blescan.hci_set_random_mac(sock, channel)
blescan.hci_le_set_advertising_parameters(sock, int(intervalm), int(intervalM), channel)
blescan.hci_le_set_advertising_data(sock, channel, channel, int(tx))
blescan.hci_enable_le_advertise(sock)
time.sleep(1)
if channel == 39:
channel = 37
blescan.hci_disable_le_advertise(sock)
else:
channel = channel + 1
blescan.hci_disable_le_advertise(sock)
请注意,当我在启用广告后将程序置于Hibernate 状态时,在这段时间内必须发送许多包,但它只发送一个.
在BLE中,我try 每秒发送多个包裹,这是BLE中常见的广告流程,但它每秒只发送一个,所以我试图优化代码,并try 修改包裹和接收器中的过滤器,认为问题出在接收器中,但这些都不起作用.经过多次商议,我最终得出结论,问题出在emits 器上,对我来说,代码是正确的.还有人机界面命令的功能,所以我不知道问题出在哪里.