PySide6.QtBluetooth.QLowEnergyService

class QLowEnergyService

QLowEnergyService 类表示蓝牙低功耗设备上的单个服务。更多

PySide6.QtBluetooth.QLowEnergyService 的继承图

概要

方法

信号

注意

本文档可能包含从C++自动翻译到Python的代码片段。我们始终欢迎对代码片段翻译的贡献。如果您发现翻译问题,您也可以通过在我们的https:/bugreports.qt.io/projects/PYSIDE上创建工单来告知我们。

详细描述

警告

本节包含从C++自动翻译到Python的代码片段,可能包含错误。

QLowEnergyService 提供了对蓝牙低功耗服务细节的访问。该类促进了服务细节的发现和发布,允许读取和写入包含的数据,并通知数据更改。

服务结构

一个蓝牙低功耗外围设备可以包含多个服务。反过来,每个服务可能包括更多的服务。这个类代表外围设备的单个服务,并通过createServiceObject()创建。type()指示此服务是主要(顶级)服务还是另一个服务的一部分。每个服务可能包含一个或多个特征,每个特征可能包含描述符。生成的结构可能如下图所示:

../../_images/peripheral-structure.png

特征是主要的信息载体。它具有一个value()和一个properties(),用于描述对值的访问权限。包含的描述符的总体目的是进一步定义特征的性质。例如,它可能指定如何解释值,或者是否可以通知值消费者有关值的变化。

服务交互

首次创建服务对象时,其详细信息尚未被发现。这由其当前的state()DiscoveryRequired表示。此时只能检索serviceUuid()serviceName()

当调用discoverDetails()时,会触发其包含的服务、特性和描述符的发现。在发现过程中,state()DiscoveryRequired经过DiscoveringService过渡到最终的ServiceDiscovered状态。这个过渡通过stateChanged()信号进行通知。一旦细节已知,所有包含的特性、描述符和包含的服务都已知,并且可以读取或写入。

特性和描述符的值可以通过QLowEnergyCharacteristicQLowEnergyDescriptor分别获取。然而,直接读取或写入这些属性需要服务对象。readCharacteristic()函数尝试重新读取特性的值。尽管初始服务发现可能已经获取了一个值,但在特性值不断变化且未提供任何通知的情况下,可能需要此调用。一个例子可能是提供连续值的时间特性。如果读取尝试成功,则会发出characteristicRead()信号。读取值失败会触发CharacteristicReadErrorwriteCharacteristic()函数尝试将新值写入给定的特性。如果写入尝试成功,则会发出characteristicWritten()信号。写入失败会触发CharacteristicWriteError。描述符的读取和写入遵循相同的模式。

每次尝试读取或写入硬件上的描述符或特征值。这意味着在读取和写入时,通常会忽略诸如properties()之类的元信息。例如,尽管特征根据其元数据描述是只读的,但仍可以调用writeCharacteristic()。生成的写入请求会转发到连接的设备,由设备决定如何响应可能无效的请求。在这种情况下,结果是发出CharacteristicWriteError以响应返回的设备错误。这种行为简化了与报告错误元信息的设备的交互。如果无法将请求转发到远程设备,则会设置OperationError。可能的原因是要写入的特征对象甚至不属于当前服务。总之,这两种类型的错误允许快速区分本地和远程错误情况。

所有请求都基于先进先出原则进行序列化。例如,在前一个写请求完成之前发出第二个写请求,将延迟到第一个写请求完成后执行。

注意

目前,无法发送签名的写入或可靠的写入请求。

在某些情况下,外围设备会生成中央设备感兴趣接收的值更新。为了使特性支持此类通知,它必须具有NotifyIndicate属性以及类型为ClientCharacteristicConfiguration的描述符。如果满足这些条件,则可以启用通知,如下面的代码段所示:

#PreCondition: service details already discovered
batteryLevel = service.characteristic(
            QBluetoothUuid.CharacteristicType.BatteryLevel)
if not batteryLevel.isValid():
    return
notification = batteryLevel.descriptor(
            QBluetoothUuid.DescriptorType.ClientCharacteristicConfiguration)
if not notification.isValid():
    return
# establish hook into notifications
connect(service, SIGNAL(characteristicChanged(QLowEnergyCharacteristic,QByteArray)),
        self, SLOT(characteristicChanged(QLowEnergyCharacteristic,QByteArray)))
# enable notification
service.writeDescriptor(notification, QByteArray.fromHex("0100"))
# disable notification
#service->writeDescriptor(notification, QByteArray::fromHex("0000"))
# wait until descriptorWritten() signal is emitted
# to confirm successful write

该示例展示了一个电池电量特性,它在每次值变化时更新中央设备。通知通过characteristicChanged()信号提供。有关此机制的更多详细信息由Bluetooth Specification提供。

服务数据共享

每个 QLowEnergyService 实例与其他相同服务的 QLowEnergyService 实例共享其内部状态和信息。如果一个实例启动了服务细节的发现,所有其他实例会自动跟随。因此以下代码片段总是有效的:

first, = QLowEnergyService()
control = QLowEnergyController(remoteDevice)
control.connectToDevice()
# waiting for connection
first = control.createServiceObject(QBluetoothUuid.ServiceClassUuid.BatteryService)
second = control.createServiceObject(QBluetoothUuid.ServiceClassUuid.BatteryService)
Q_ASSERT(first.state() == QLowEnergyService.RemoteService)
Q_ASSERT(first.state() == second.state())
first.discoverDetails()
Q_ASSERT(first.state() == QLowEnergyService.RemoteServiceDiscovering)
Q_ASSERT(first.state() == second.state())

其他操作,如调用readCharacteristic()readDescriptor()writeCharacteristic()writeDescriptor(),或由于相关的QLowEnergyController与设备断开连接而导致服务失效,都以相同的方式共享。

class ServiceType

(继承 enum.Flag) 此枚举描述了服务的类型。

常量

描述

QLowEnergyService.PrimaryService

该服务是顶级/主要服务。如果未设置此类型标志,则该服务被视为次要服务。每个服务可能被另一个服务包含,这由IncludedService指示。

QLowEnergyService.IncludedService

该服务被另一个服务包含。在某些平台上,直到发现包含当前服务的服务后,才能确定此标志。

class ServiceError

此枚举描述了服务存在期间所有可能的错误情况。error() 函数返回最后发生的错误。

常量

描述

QLowEnergyService.NoError

没有发生错误。

QLowEnergyService.OperationError

尝试在服务未准备好时执行操作。例如,在服务尚未处于ServiceDiscovered state()状态或由于与外围设备的连接丢失而导致服务无效时,尝试写入服务。

QLowEnergyService.CharacteristicReadError

尝试读取特征值失败。例如,它可能是在调用 readCharacteristic() 时触发的。

QLowEnergyService.CharacteristicWriteError

尝试向特征写入新值失败。例如,当尝试向只读特征写入时可能会触发此错误。

QLowEnergyService.DescriptorReadError

尝试读取描述符值失败。例如,它可能是在调用 readDescriptor() 时触发的。

QLowEnergyService.DescriptorWriteError

尝试向描述符写入新值失败。例如,当尝试向只读描述符写入时可能会触发此错误。

QLowEnergyService.UnknownError

与服务交互时发生未知错误。

class ServiceState

此枚举描述了服务对象的state()状态。

常量

描述

QLowEnergyService.InvalidService

当服务失去与底层设备的连接时,它可能会变得无效。即使连接可能丢失,它仍保留其最后的信息。即使重新建立与设备的连接,无效的服务也无法再次变为有效。

QLowEnergyService.RemoteService

服务详细信息尚未通过调用discoverDetails()发现。唯一可靠的信息是其serviceUuid()serviceName()

QLowEnergyService.RemoteServiceDiscovering

正在发现服务详细信息。

QLowEnergyService.RemoteServiceDiscovered

服务详情已被发现。

QLowEnergyService.LocalService

该服务与peripheral role中的控制器对象相关联。此类服务对象不会改变其状态。

QLowEnergyService.DiscoveryRequired

已弃用。已重命名为RemoteService。

QLowEnergyService.DiscoveringService

已弃用。已重命名为 RemoteServiceDiscovering。

QLowEnergyService.ServiceDiscovered

已弃用。已重命名为RemoteServiceDiscovered。

class DiscoveryMode

此枚举列出了服务发现模式。所有模式都会发现服务的特征和特征的描述符。这些模式的区别在于是否读取特征值和描述符。

常量

描述

QLowEnergyService.FullDiscovery

在完全发现过程中,所有特性都会被发现。所有特性值和描述符都会被读取。

QLowEnergyService.SkipValueDiscovery

在最小发现过程中,所有特性都会被发现。特性值和描述符不会被读取。

另请参阅

discoverDetails()

class WriteMode

此枚举描述了在写入特征值时要使用的模式。特征通过其properties广告其支持的写入模式。

常量

描述

QLowEnergyService.WriteWithResponse

如果使用此模式写入特征,外围设备应发送写入确认。如果操作成功,确认将通过characteristicWritten()信号发出。否则,将发出CharacteristicWriteError。特征必须设置Write属性以支持此写入模式。

QLowEnergyService.WriteWithoutResponse

如果使用此模式写入特征,远程外设不应发送写入确认。无法确定操作的成功与否,且有效载荷不得超过20字节。特征必须设置WriteNoResponse属性以支持此写入模式。其优点是写入操作更快,因为它可能在其他设备交互之间发生。

QLowEnergyService.WriteSigned

如果使用此模式写入特征,远程外设将不会发送写入确认。无法确定操作是否成功,且有效载荷不得超过8字节。两台设备之间必须存在绑定,且链接不得加密。特征必须设置WriteSigned属性以支持此写入模式。此值目前仅在Android和Linux上支持,且需要BlueZ 5和内核版本3.7或更高版本。

characteristic(uuid)
Parameters:

uuidQBluetoothUuid

Return type:

QLowEnergyCharacteristic

返回与uuid匹配的特征;否则返回无效特征。

如果此服务实例的discoverDetails()尚未调用或没有匹配uuid的特征,则返回的特征无效。

另请参阅

characteristics()

characteristicChanged(info, value)
Parameters:

如果关联的控制器对象处于central角色,当外围设备/设备端的事件改变了characteristic的值时,会发出此信号。在这种情况下,信号的发出意味着在外围设备上的更改事件之前,必须通过特征的ClientCharacteristicConfiguration描述符激活更改通知。关于如何实现这一点的更多详细信息可以在above找到。

如果控制器处于peripheral角色,即服务对象是通过addService创建的,当GATT客户端使用写请求或命令写入特征值时,信号将被发出。

newValue 参数包含 characteristic 的更新值。

characteristicRead(info, value)
Parameters:

characteristic的读取请求成功返回其value时,会发出此信号。该信号可能通过调用characteristicRead()触发。如果读取操作不成功,则会使用CharacteristicReadError标志发出errorOccurred()信号。

注意

此信号仅针对中央角色相关的用例发出。

另请参阅

readCharacteristic()

characteristicWritten(info, value)
Parameters:

characteristic的值成功更改为newValue时,会发出此信号。此更改必须是通过调用writeCharacteristic()触发的。如果写入操作不成功,则会使用CharacteristicWriteError标志发出errorOccurred()信号。

书面信号的接收可以被视为目标设备接收到待写入值并报告写入请求状态的标志。

注意

如果使用WriteWithoutResponse模式调用writeCharacteristic(),则永远不会发出此信号和errorOccurred()

注意

此信号仅针对中央角色相关的用例发出。

另请参阅

writeCharacteristic()

characteristics()
Return type:

QLowEnergyCharacteristic的列表

返回与此QLowEnergyService实例关联的所有特性。

如果此服务实例的discoverDetails()尚未调用或没有已知特征,则返回的列表为空。

contains(characteristic)
Parameters:

特性QLowEnergyCharacteristic

Return type:

布尔

如果 characteristic 属于此服务,则返回 true;否则返回 false

如果一个特征属于一个服务,那么characteristics()包含characteristic

contains(descriptor)
Parameters:

描述符QLowEnergyDescriptor

Return type:

布尔

如果 descriptor 属于此服务,则返回 true;否则返回 false

descriptorRead(info, value)
Parameters:

descriptor的读取请求成功返回其value时,会发出此信号。该信号可能通过调用descriptorRead()触发。如果读取操作不成功,则会使用DescriptorReadError标志发出errorOccurred()信号。

注意

此信号仅针对中央角色相关的用例发出。

另请参阅

readDescriptor()

descriptorWritten(info, value)
Parameters:

descriptor的值成功更改为newValue时,会发出此信号。如果关联的控制器对象处于central角色,则更改必须是通过调用writeDescriptor()引起的。否则,该信号是GATT客户端向相应描述符发出写入请求或命令的结果。

另请参阅

writeDescriptor()

discoverDetails([mode=QLowEnergyService.DiscoveryMode.FullDiscovery])
Parameters:

modeDiscoveryMode

启动服务发现,包括服务、特性及其相关的描述符。

发现过程通过stateChanged()信号指示。创建后,服务处于DiscoveryRequired状态。当调用discoverDetails()时,它会过渡到DiscoveringService状态。在详细信息发现完成后,它会过渡到ServiceDiscovered状态。每次过渡时,都会发出stateChanged()信号。根据参数mode,执行FullDiscoverySkipValueDiscovery。无论如何,所有服务和特性都会被发现。FullDiscovery会继续并读取所有特性值和描述符。SkipValueDiscovery不会读取特性值和描述符。SkipValueDiscovery有两个优点。首先,它更快。其次,它绕过了某些设备中的错误,这些设备错误地将特性或描述符宣传为可读,但不允许读取它们。这可能会引发不可预测的行为。在SkipValueDiscovery之后,有必要调用readCharacteristic() / readDescriptor()并等待它们成功完成,然后才能访问特性或描述符的值。

参数 mode 是在 Qt 6.2 中引入的。

另请参阅

state()

error()
Return type:

ServiceError

返回最后发生的错误或NoError

errorOccurred(error)
Parameters:

错误ServiceError

当发生错误时,会发出此信号。newError 参数描述了发生的错误。

includedServices()
Return type:

QBluetoothUuid的列表

返回当前服务包含的所有服务的UUID。

如果此服务实例的discoverDetails()尚未调用或没有已知特征,则返回的列表为空。

可能包含的服务中还包含另一个服务。这样的第二级包含必须通过它们相关的第一级QLowEnergyService实例来获取。从技术上讲,这可能会产生循环依赖。

createServiceObject() 应该用于获取每个UUID的服务实例。

另请参阅

createServiceObject()

readCharacteristic(characteristic)
Parameters:

特性QLowEnergyCharacteristic

读取characteristic的值。如果操作成功,会发出characteristicRead()信号;否则会设置CharacteristicReadError。通常,如果characteristicRead属性被设置,那么它是可读的。

所有对同一远程设备的描述符和特征请求都是串行化的。当同时发出多个请求时,会使用一个队列。该队列不会消除对同一特征的重复读取请求。

只有在服务处于ServiceDiscovered状态并且属于该服务时,才能读取特征。如果这些条件中的任何一个不成立,则设置OperationError

注意

尽管properties()报告了一个不可读的属性,调用此函数总是尝试读取硬件上的特征值。如果硬件返回错误,则设置CharacteristicReadError

readDescriptor(descriptor)
Parameters:

描述符QLowEnergyDescriptor

读取descriptor的值。如果操作成功,则会发出descriptorRead()信号;否则会设置DescriptorReadError

所有对同一远程设备的描述符和特征请求都是序列化的。当同时发出多个请求时,会使用一个队列。该队列不会消除对同一描述符的重复读取请求。

只有在服务处于ServiceDiscovered状态且描述符属于该服务时,才能读取描述符。如果这些条件中的任何一个不成立,则设置OperationError

serviceName()
Return type:

字符串

返回服务的名称;否则返回空字符串。

返回的名称只有在serviceUuid()已知的UUID时才能检索到。

serviceUuid()
Return type:

QBluetoothUuid

返回服务的UUID;否则返回一个空的UUID。

state()
Return type:

ServiceState

返回服务的当前状态。

如果设备的服务是首次实例化,对象的状态是DiscoveryRequired。所有指向外围设备上同一服务的服务对象的状态始终相同。这是由于内部对象数据的共享性质所致。因此,在第一个实例之后创建的任何服务对象实例的状态都与已存在的实例相同。

如果QLowEnergyController与远程设备断开连接,服务将变为无效。无效的服务在断开连接事件时保留其内部状态。这意味着一旦发现服务详细信息,甚至可以从无效的服务中检索它们。这允许设备连接建立、检索服务详细信息并立即断开设备连接,以允许下一个设备连接到外围设备的场景。

然而,在正常情况下,应保持连接以避免重复发现服务及其详细信息。发现过程可能需要一些时间,客户端可以订阅持续的变化通知。

另请参阅

stateChanged()

stateChanged(newState)
Parameters:

newStateServiceState

当服务的状态发生变化时,会发出此信号。newState 也可以通过 state() 获取。

另请参阅

state()

type()
Return type:

ServiceType 的组合

返回服务的类型。

注意

在服务达到ServiceDiscovered状态之前,不能依赖type属性。此字段初始化为PrimaryService

注意

在Android上,无法确定服务是主要服务还是次要服务。因此,所有服务都设置了PrimaryService标志。

writeCharacteristic(characteristic, newValue[, mode=QLowEnergyService.WriteMode.WriteWithResponse])
Parameters:

newValue 作为 characteristic 的值写入。确切的语义取决于关联控制器对象的角色。

核心角色

调用结果会导致向远程外设发出写请求或命令。如果操作成功,则会发出characteristicWritten()信号;否则会设置CharacteristicWriteError。调用此函数不会触发characteristicChanged()信号,除非外设在当前写请求之后再次更改值。

mode 参数决定远程设备是否应发送写入确认。要写入的 characteristic 必须支持相关的写入模式。特征的受支持写入模式由其 WriteWriteNoResponse 属性指示。

所有针对同一远程设备的描述符和特性写请求都是串行化的。当同时发出多个写请求时,会使用一个队列。该队列不会消除对同一特性的重复写请求。例如,如果同一描述符被设置为值A,然后立即设置为B,这两个写请求将按给定的顺序执行。

注意

目前,无法使用蓝牙规范定义的签名或可靠写入。

只有在服务处于ServiceDiscovered状态并且属于该服务时,才能写入特征。如果这些条件中的任何一个不成立,则设置OperationError

注意

尽管properties()报告了一个不可写的属性,调用此函数总是尝试写入硬件。同样,即使特性可能只支持WriteWithResponse,也会向硬件发送WriteWithoutResponse。如果硬件返回错误,则设置CharacteristicWriteError

外围角色

调用结果导致特征值在本地数据库中得到更新。

如果客户端当前已连接并且已为该特性启用了通知或指示,则将发送相应的信息。如果设备已为该特性启用了通知或指示,并且该设备当前未连接,但与该本地设备之间存在绑定,则通知或指示将在下次重新连接时发送。

如果对特征值的长度有约束,并且newValue不符合该约束,则行为未指定。

注意

mode 参数在外设模式下被忽略。

writeDescriptor(descriptor, newValue)
Parameters:

newValue 作为 descriptor 的值写入。确切的语义取决于关联控制器对象的角色。

核心角色

调用此函数会导致向远程设备发出写请求。如果操作成功,则会发出descriptorWritten()信号;否则会发出DescriptorWriteError

对同一远程设备的所有描述符和特征请求都是序列化的。当同时发出多个写入请求时,会使用一个队列。该队列不会消除对同一描述符的重复写入请求。例如,如果同一描述符被设置为值A,然后立即设置为B,这两个写入请求将按给定的顺序执行。

只有当此服务处于ServiceDiscovered状态时,描述符才能被写入,且属于该服务。如果这些条件中的任何一个不成立,则设置OperationError

外围角色

该值被写入本地服务数据库。如果newValue的内容对于descriptor无效,则行为未指定。