如何使用 Python 将 SDP 记录添加到 MacOS?

How to add an SDP Record to MacOS with Python?

我目前的目标是在 MacBook Pro 上向蓝牙服务 运行 添加 SDP 记录,这样我就可以将此服务宣传给其他蓝牙设备。理想情况下,我想在 Python.

内完成此任务

此时,我已经在 BlueZ 蓝牙堆栈下的 Linux 上成功创建、添加和通告了一条 SDP 记录,但是,我在获得类似过程时遇到了一些麻烦在 MacOS 上工作。

经过一些研究,我的理解是在 MacOS 上与蓝牙 API 交互涉及使用 IOBluetooth Objective-C framework, which can be accomplished in Python through pyobjc。附带一提,我也知道存在 CoreBluetooth 框架,但是,该框架的功能并不合适,因为它缺少 SDP 记录 add/remove 功能。

我目前正在处理两个问题:

1。创建适用于 MacOS 的 SDP 记录

MacOS 对 loading/specifying SDP 记录使用 PLIST 格式。我有一个 XML 格式的现有记录,可由 BlueZ 加载。是否可以将此记录转换为 PLIST 格式,或者我应该考虑从头开始重写记录?

2。通过pyobjc

添加SDP记录

我可以通过 pyobjc/IOBluetooth interact/query 基本的蓝牙功能。当我尝试使用 IOBluetoothSDPServiceRecord class 时出现问题。从我在其他地方看到的一些示例(一个示例 )来看,这个 class 似乎是您用来添加新记录的那个?当我尝试 load/use 这个 class 时,我无法访问它的任何功能。

如果对于熟悉 Objective-C 的人来说这似乎是一个 trivial/or 业余问题,我提前道歉! Python 是我的专长所在,因此与这种语言交互有点超出我的驾驶室。

我还将在下面提供一个我一直在做的工作的最小工作示例:

IOBluetooth.py

import objc as _objc

_objc.loadBundle('IOBluetooth', globals(),\
  bundle_path=u'/System/Library/Frameworks/IOBluetooth.framework')

bluetooth_test.py

from IOBluetooth import *


sdp = None
with open("record.plist", "r") as f:
    sdp = f.read()

# This functions correctly
devs = IOBluetoothDevice.recentDevices_(0)
print(devs[0].getNameOrAddress())

# This does not
sdp_sr = IOBluetoothSDPServiceRecord.alloc().init()
sdp_sr.publishedServiceRecord(sdp)

bluetooth_test.py

的输出
Apple Watch
Traceback (most recent call last):
  File "bluetooth_test.py", line 12, in <module>
    sdp_sr.publishedServiceRecord(sdp)
AttributeError: 'IOBluetoothSDPServiceRecord' object has no attribute 'publishedServiceRecord'

如有任何意见,我们将不胜感激!

在进一步研究之后,我得出了一个答案。对于那些碰巧在做类似事情的人,我会 post 我是如何解决这个问题的:

问题 1 的答案

经过一番搜索,我认为最好手动重写现有的 XML SDP 记录。我找不到任何实用程序可以处理 16 位蓝牙 UUID 从 XML 到 PLIST 格式的转换。

问题 2 的答案

上面的 IOBluetooth.py 文件与我的问题没有变化。

bluetooth_test.py

from IOBluetooth import *
from Cocoa import NSDictionary
import time


plist = NSDictionary.dictionaryWithContentsOfFile_("service.plist")
sdp_sr = IOBluetoothSDPServiceRecord.publishedServiceRecordWithDictionary_(plist)

time.sleep(10)

sdp_sr.removeServiceRecord()
print("Removed Service Record")

真正有助于探索 IOBluetooth API 的是使用 Python 中的 dir() 函数。您实际上可以向它扔一个 pyobjc 实例或 Class,您将收到所有可用方法的列表。

希望这对以后的人有所帮助!