PySide6.QtBluetooth.QLowEnergyService¶
- class QLowEnergyService¶
QLowEnergyService
类表示蓝牙低功耗设备上的单个服务。更多…概要¶
方法¶
def
characteristic()
def
contains()
def
error()
def
readDescriptor()
def
serviceName()
def
serviceUuid()
def
state()
def
type()
信号¶
def
descriptorRead()
def
errorOccurred()
def
stateChanged()
注意
本文档可能包含从C++自动翻译到Python的代码片段。我们始终欢迎对代码片段翻译的贡献。如果您发现翻译问题,您也可以通过在我们的https:/bugreports.qt.io/projects/PYSIDE上创建工单来告知我们。
详细描述¶
警告
本节包含从C++自动翻译到Python的代码片段,可能包含错误。
QLowEnergyService
提供了对蓝牙低功耗服务细节的访问。该类促进了服务细节的发现和发布,允许读取和写入包含的数据,并通知数据更改。服务结构¶
一个蓝牙低功耗外围设备可以包含多个服务。反过来,每个服务可能包括更多的服务。这个类代表外围设备的单个服务,并通过
createServiceObject()
创建。type()
指示此服务是主要(顶级)服务还是另一个服务的一部分。每个服务可能包含一个或多个特征,每个特征可能包含描述符。生成的结构可能如下图所示:特征是主要的信息载体。它具有一个
value()
和一个properties()
,用于描述对值的访问权限。包含的描述符的总体目的是进一步定义特征的性质。例如,它可能指定如何解释值,或者是否可以通知值消费者有关值的变化。服务交互¶
首次创建服务对象时,其详细信息尚未被发现。这由其当前的
state()
为DiscoveryRequired
表示。此时只能检索serviceUuid()
和serviceName()
。当调用
discoverDetails()
时,会触发其包含的服务、特性和描述符的发现。在发现过程中,state()
从DiscoveryRequired
经过DiscoveringService
过渡到最终的ServiceDiscovered
状态。这个过渡通过stateChanged()
信号进行通知。一旦细节已知,所有包含的特性、描述符和包含的服务都已知,并且可以读取或写入。特性和描述符的值可以通过
QLowEnergyCharacteristic
和QLowEnergyDescriptor
分别获取。然而,直接读取或写入这些属性需要服务对象。readCharacteristic()
函数尝试重新读取特性的值。尽管初始服务发现可能已经获取了一个值,但在特性值不断变化且未提供任何通知的情况下,可能需要此调用。一个例子可能是提供连续值的时间特性。如果读取尝试成功,则会发出characteristicRead()
信号。读取值失败会触发CharacteristicReadError
。writeCharacteristic()
函数尝试将新值写入给定的特性。如果写入尝试成功,则会发出characteristicWritten()
信号。写入失败会触发CharacteristicWriteError
。描述符的读取和写入遵循相同的模式。每次尝试读取或写入硬件上的描述符或特征值。这意味着在读取和写入时,通常会忽略诸如
properties()
之类的元信息。例如,尽管特征根据其元数据描述是只读的,但仍可以调用writeCharacteristic()
。生成的写入请求会转发到连接的设备,由设备决定如何响应可能无效的请求。在这种情况下,结果是发出CharacteristicWriteError
以响应返回的设备错误。这种行为简化了与报告错误元信息的设备的交互。如果无法将请求转发到远程设备,则会设置OperationError
。可能的原因是要写入的特征对象甚至不属于当前服务。总之,这两种类型的错误允许快速区分本地和远程错误情况。所有请求都基于先进先出原则进行序列化。例如,在前一个写请求完成之前发出第二个写请求,将延迟到第一个写请求完成后执行。
注意
目前,无法发送签名的写入或可靠的写入请求。
在某些情况下,外围设备会生成中央设备感兴趣接收的值更新。为了使特性支持此类通知,它必须具有
Notify
或Indicate
属性以及类型为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
在最小发现过程中,所有特性都会被发现。特性值和描述符不会被读取。
另请参阅
- 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:
uuid –
QBluetoothUuid
- Return type:
返回与
uuid
匹配的特征;否则返回无效特征。如果此服务实例的
discoverDetails()
尚未调用或没有匹配uuid
的特征,则返回的特征无效。另请参阅
- characteristicChanged(info, value)¶
- Parameters:
value –
QByteArray
如果关联的控制器对象处于
central
角色,当外围设备/设备端的事件改变了characteristic
的值时,会发出此信号。在这种情况下,信号的发出意味着在外围设备上的更改事件之前,必须通过特征的ClientCharacteristicConfiguration
描述符激活更改通知。关于如何实现这一点的更多详细信息可以在above
找到。如果控制器处于
peripheral
角色,即服务对象是通过addService
创建的,当GATT客户端使用写请求或命令写入特征值时,信号将被发出。newValue
参数包含characteristic
的更新值。- characteristicRead(info, value)¶
- Parameters:
value –
QByteArray
当
characteristic
的读取请求成功返回其value
时,会发出此信号。该信号可能通过调用characteristicRead()触发。如果读取操作不成功,则会使用CharacteristicReadError
标志发出errorOccurred()
信号。- characteristicWritten(info, value)¶
- Parameters:
value –
QByteArray
当
characteristic
的值成功更改为newValue
时,会发出此信号。此更改必须是通过调用writeCharacteristic()
触发的。如果写入操作不成功,则会使用CharacteristicWriteError
标志发出errorOccurred()
信号。书面信号的接收可以被视为目标设备接收到待写入值并报告写入请求状态的标志。
注意
如果使用
WriteWithoutResponse
模式调用writeCharacteristic()
,则永远不会发出此信号和errorOccurred()
。- characteristics()¶
- Return type:
返回与此
QLowEnergyService
实例关联的所有特性。如果此服务实例的
discoverDetails()
尚未调用或没有已知特征,则返回的列表为空。- contains(characteristic)¶
- Parameters:
- Return type:
布尔
如果
characteristic
属于此服务,则返回true
;否则返回false
。如果一个特征属于一个服务,那么
characteristics()
包含characteristic
。- contains(descriptor)
- Parameters:
描述符 –
QLowEnergyDescriptor
- Return type:
布尔
如果
descriptor
属于此服务,则返回true
;否则返回false
。- descriptorRead(info, value)¶
- Parameters:
信息 –
QLowEnergyDescriptor
value –
QByteArray
当
descriptor
的读取请求成功返回其value
时,会发出此信号。该信号可能通过调用descriptorRead()触发。如果读取操作不成功,则会使用DescriptorReadError
标志发出errorOccurred()
信号。- descriptorWritten(info, value)¶
- Parameters:
信息 –
QLowEnergyDescriptor
value –
QByteArray
当
descriptor
的值成功更改为newValue
时,会发出此信号。如果关联的控制器对象处于central
角色,则更改必须是通过调用writeDescriptor()
引起的。否则,该信号是GATT客户端向相应描述符发出写入请求或命令的结果。另请参阅
- discoverDetails([mode=QLowEnergyService.DiscoveryMode.FullDiscovery])¶
- Parameters:
mode –
DiscoveryMode
启动服务发现,包括服务、特性及其相关的描述符。
发现过程通过
stateChanged()
信号指示。创建后,服务处于DiscoveryRequired
状态。当调用discoverDetails()时,它会过渡到DiscoveringService
状态。在详细信息发现完成后,它会过渡到ServiceDiscovered
状态。每次过渡时,都会发出stateChanged()
信号。根据参数mode
,执行FullDiscovery
或SkipValueDiscovery
。无论如何,所有服务和特性都会被发现。FullDiscovery
会继续并读取所有特性值和描述符。SkipValueDiscovery
不会读取特性值和描述符。SkipValueDiscovery
有两个优点。首先,它更快。其次,它绕过了某些设备中的错误,这些设备错误地将特性或描述符宣传为可读,但不允许读取它们。这可能会引发不可预测的行为。在SkipValueDiscovery
之后,有必要调用readCharacteristic()
/readDescriptor()
并等待它们成功完成,然后才能访问特性或描述符的值。参数
mode
是在 Qt 6.2 中引入的。另请参阅
- error()¶
- Return type:
返回最后发生的错误或
NoError
。- errorOccurred(error)¶
- Parameters:
错误 –
ServiceError
当发生错误时,会发出此信号。
newError
参数描述了发生的错误。- includedServices()¶
- Return type:
返回当前服务包含的所有服务的UUID。
如果此服务实例的
discoverDetails()
尚未调用或没有已知特征,则返回的列表为空。可能包含的服务中还包含另一个服务。这样的第二级包含必须通过它们相关的第一级
QLowEnergyService
实例来获取。从技术上讲,这可能会产生循环依赖。createServiceObject()
应该用于获取每个UUID的服务实例。- readCharacteristic(characteristic)¶
- Parameters:
读取
characteristic
的值。如果操作成功,会发出characteristicRead()
信号;否则会设置CharacteristicReadError
。通常,如果characteristic
的Read
属性被设置,那么它是可读的。所有对同一远程设备的描述符和特征请求都是串行化的。当同时发出多个请求时,会使用一个队列。该队列不会消除对同一特征的重复读取请求。
只有在服务处于
ServiceDiscovered
状态并且属于该服务时,才能读取特征。如果这些条件中的任何一个不成立,则设置OperationError
。注意
尽管
properties()
报告了一个不可读的属性,调用此函数总是尝试读取硬件上的特征值。如果硬件返回错误,则设置CharacteristicReadError
。- readDescriptor(descriptor)¶
- Parameters:
描述符 –
QLowEnergyDescriptor
读取
descriptor
的值。如果操作成功,则会发出descriptorRead()
信号;否则会设置DescriptorReadError
。所有对同一远程设备的描述符和特征请求都是序列化的。当同时发出多个请求时,会使用一个队列。该队列不会消除对同一描述符的重复读取请求。
只有在服务处于
ServiceDiscovered
状态且描述符属于该服务时,才能读取描述符。如果这些条件中的任何一个不成立,则设置OperationError
。- serviceName()¶
- Return type:
字符串
返回服务的名称;否则返回空字符串。
返回的名称只有在
serviceUuid()
是已知的UUID时才能检索到。- serviceUuid()¶
- Return type:
返回服务的UUID;否则返回一个空的UUID。
- state()¶
- Return type:
返回服务的当前状态。
如果设备的服务是首次实例化,对象的状态是
DiscoveryRequired
。所有指向外围设备上同一服务的服务对象的状态始终相同。这是由于内部对象数据的共享性质所致。因此,在第一个实例之后创建的任何服务对象实例的状态都与已存在的实例相同。如果
QLowEnergyController
与远程设备断开连接,服务将变为无效。无效的服务在断开连接事件时保留其内部状态。这意味着一旦发现服务详细信息,甚至可以从无效的服务中检索它们。这允许设备连接建立、检索服务详细信息并立即断开设备连接,以允许下一个设备连接到外围设备的场景。然而,在正常情况下,应保持连接以避免重复发现服务及其详细信息。发现过程可能需要一些时间,客户端可以订阅持续的变化通知。
另请参阅
- stateChanged(newState)¶
- Parameters:
newState –
ServiceState
当服务的状态发生变化时,会发出此信号。
newState
也可以通过state()
获取。另请参阅
- type()¶
- Return type:
ServiceType
的组合
返回服务的类型。
注意
在服务达到
ServiceDiscovered
状态之前,不能依赖type属性。此字段初始化为PrimaryService
。注意
在Android上,无法确定服务是主要服务还是次要服务。因此,所有服务都设置了
PrimaryService
标志。- writeCharacteristic(characteristic, newValue[, mode=QLowEnergyService.WriteMode.WriteWithResponse])¶
- Parameters:
newValue –
QByteArray
mode –
WriteMode
将
newValue
作为characteristic
的值写入。确切的语义取决于关联控制器对象的角色。核心角色
调用结果会导致向远程外设发出写请求或命令。如果操作成功,则会发出
characteristicWritten()
信号;否则会设置CharacteristicWriteError
。调用此函数不会触发characteristicChanged()
信号,除非外设在当前写请求之后再次更改值。mode
参数决定远程设备是否应发送写入确认。要写入的characteristic
必须支持相关的写入模式。特征的受支持写入模式由其Write
和WriteNoResponse
属性指示。所有针对同一远程设备的描述符和特性写请求都是串行化的。当同时发出多个写请求时,会使用一个队列。该队列不会消除对同一特性的重复写请求。例如,如果同一描述符被设置为值A,然后立即设置为B,这两个写请求将按给定的顺序执行。
注意
目前,无法使用蓝牙规范定义的签名或可靠写入。
只有在服务处于
ServiceDiscovered
状态并且属于该服务时,才能写入特征。如果这些条件中的任何一个不成立,则设置OperationError
。注意
尽管
properties()
报告了一个不可写的属性,调用此函数总是尝试写入硬件。同样,即使特性可能只支持WriteWithResponse
,也会向硬件发送WriteWithoutResponse
。如果硬件返回错误,则设置CharacteristicWriteError
。外围角色
调用结果导致特征值在本地数据库中得到更新。
如果客户端当前已连接并且已为该特性启用了通知或指示,则将发送相应的信息。如果设备已为该特性启用了通知或指示,并且该设备当前未连接,但与该本地设备之间存在绑定,则通知或指示将在下次重新连接时发送。
如果对特征值的长度有约束,并且
newValue
不符合该约束,则行为未指定。- writeDescriptor(descriptor, newValue)¶
- Parameters:
描述符 –
QLowEnergyDescriptor
newValue –
QByteArray
将
newValue
作为descriptor
的值写入。确切的语义取决于关联控制器对象的角色。核心角色
调用此函数会导致向远程设备发出写请求。如果操作成功,则会发出
descriptorWritten()
信号;否则会发出DescriptorWriteError
。对同一远程设备的所有描述符和特征请求都是序列化的。当同时发出多个写入请求时,会使用一个队列。该队列不会消除对同一描述符的重复写入请求。例如,如果同一描述符被设置为值A,然后立即设置为B,这两个写入请求将按给定的顺序执行。
只有当此服务处于
ServiceDiscovered
状态时,描述符才能被写入,且属于该服务。如果这些条件中的任何一个不成立,则设置OperationError
。外围角色
该值被写入本地服务数据库。如果
newValue
的内容对于descriptor
无效,则行为未指定。