我使用极地H10作为心率监测器,我想得到在iOS中使用Swift和核心蓝牙的心率测量特性中的值。
下面是CBPeripheralDelegate的适当回调方法中的代码:
func peripheral(_ peripheral: CBPeripheral, didUpdateValueFor characteristic: CBCharacteristic, error: Error?) {
print("didUpdateValueFor")
if let error = error {
print("error:", error)
}
guard let value = characteristic.value else {
return
}
print("value:", value)
guard let stringValue = String(data: value, encoding: .utf8) else {
return
}
print("string value:", stringValue)
}此心率测量的官方蓝牙网页显示了以下未格式化信息:
强制8位注:心率测量值字段的格式取决于“标志”字段的位0。C1 uint8 org.bluetooth.unit.period.beats_per_minute备注:心率测量值字段的格式取决于“标志”字段的位0。C2 uint16 org.bluetooth.unit.period.beats_per_minute能量消耗场的存在依赖于旗场的第3位。C3 uint16 org.bluetooth.unit.energy.joule C4 uint16 org.bluetooth.unit.time.second分辨率为1/1024秒,上表中的字段为LSO到MSO的顺序。其中LSO =最小的八进制,MSO =最重要的八位。
我搞不懂这些文件是什么意思。特别是我不明白C1、C2、C3和C4指的是什么。
characteristic.value是类型数据。我该如何处理那个数据对象?我如何获得我所需要的价值?我首先想要RR值。
也有类似的帖子,但他们不帮助我,因为他们使用的工具和语言不同,或者他们没有好的答案。
更新:
从那时起,我发现心率测量上的页面是一个xml文件。在我用一个可以显示它的应用程序打开它之后,我能够从这个文件中获得我需要的信息。我第一次看到它是在Safari。它不能很好地显示xml文件。以下是文件:
<?xml version="1.0" encoding="UTF-8"?>
<!-- Copyright 2011 Bluetooth SIG, Inc. All rights reserved. -->
<Characteristic xsi:noNamespaceSchemaLocation="http://schemas.bluetooth.org/Documents/characteristic.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" type="org.bluetooth.characteristic.heart_rate_measurement" uuid="2A37" name="Heart Rate Measurement">
<InformativeText>
</InformativeText>
<Value>
<Field name="Flags">
<Requirement>Mandatory</Requirement>
<Format>8bit</Format>
<BitField>
<Bit index="0" size="1" name="Heart Rate Value Format bit">
<Enumerations>
<Enumeration key="0" value="Heart Rate Value Format is set to UINT8. Units: beats per minute (bpm)" requires="C1" />
<Enumeration key="1" value="Heart Rate Value Format is set to UINT16. Units: beats per minute (bpm)" requires="C2" />
</Enumerations>
</Bit>
<Bit index="1" size="2" name="Sensor Contact Status bits">
<Enumerations>
<Enumeration key="0" value="Sensor Contact feature is not supported in the current connection" />
<Enumeration key="1" value="Sensor Contact feature is not supported in the current connection" />
<Enumeration key="2" value="Sensor Contact feature is supported, but contact is not detected" />
<Enumeration key="3" value="Sensor Contact feature is supported and contact is detected" />
</Enumerations>
</Bit>
<Bit index="3" size="1" name="Energy Expended Status bit">
<Enumerations>
<Enumeration key="0" value="Energy Expended field is not present" />
<Enumeration key="1" value="Energy Expended field is present. Units: kilo Joules" requires="C3"/>
</Enumerations>
</Bit>
<Bit index="4" size="1" name="RR-Interval bit">
<Enumerations>
<Enumeration key="0" value="RR-Interval values are not present." />
<Enumeration key="1" value="One or more RR-Interval values are present." requires="C4"/>
</Enumerations>
</Bit>
<ReservedForFutureUse index="5" size="3"></ReservedForFutureUse>
</BitField>
</Field>
<Field name="Heart Rate Measurement Value (uint8)">
<InformativeText>
Note: The format of the Heart Rate Measurement Value field is dependent upon bit 0 of the Flags field.
</InformativeText>
<Requirement>C1</Requirement>
<Format>uint8</Format>
<Unit>org.bluetooth.unit.period.beats_per_minute</Unit>
</Field>
<Field name="Heart Rate Measurement Value (uint16)">
<InformativeText>
Note: The format of the Heart Rate Measurement Value field is dependent upon bit 0 of the Flags field.
</InformativeText>
<Requirement>C2</Requirement>
<Format>uint16</Format>
<Unit>org.bluetooth.unit.period.beats_per_minute</Unit>
</Field>
<Field name="Energy Expended">
<InformativeText>The presence of the Energy Expended field is dependent upon bit 3 of the Flags field.</InformativeText>
<Requirement>C3</Requirement>
<Format>uint16</Format>
<Unit>org.bluetooth.unit.energy.joule</Unit>
</Field>
<Field name="RR-Interval">
<InformativeText>
<!-- The presence of the RR-Interval field is dependent upon bit 4 of the Flags field.
<p>The RR-Interval value represents the time between two R-Wave detections.</p>
<p>Because several RR-Intervals may be measured between transmissions of the HEART RATE MEASUREMENT characteristic,
multiple RR-Interval sub-fields may be present in the characteristic. The number of RR-Interval sub-fields present
is determined by a combination of the overall length of the characteristic and whether or not the characteristic contains
the Energy Expended field.</p>
<p>Where there are multiple RR-Interval values transmitted in the HEART RATE MEASUREMENT characteristic, the field uses the following format:</p>
<p>RR-Interval Value 0 (LSO...MSO), RR-Interval Value 1 (LSO...MSO), RR-Interval Value 2 (LSO...MSO), RR-Interval Value n (LSO...MSO).</p>
<p>Where the RR-Interval Value 0 is older than the RR-Interval Value 1.</p>
<p>RR-Interval Value 0 is transmitted first followed by the newer measurements.</p>-->
</InformativeText>
<Requirement>C4</Requirement>
<Format>uint16</Format>
<Unit>org.bluetooth.unit.time.second</Unit>
<Description>Resolution of 1/1024 second</Description>
</Field>
</Value>
<Note> <p>The fields in the above table are in the order of LSO to MSO. Where LSO = Least Significant Octet and MSO = Most Significant Octet.</p>
</Note>
</Characteristic>发布于 2020-07-02 08:23:12
下面是我的工作解决方案,以获得RR-区间:
guard let characteristicData = characteristic.value else { return nil }
let byteArray = [UInt8](characteristicData)
var rawRRinterval = 0
//if fifth bit (index 4) is set -> RR-Inteval present (00010000 = 16)
if (byteArray[0] & 16) != 0{
print("One or more RR-Interval values are present.")
//00000000 (0) = heart rate 8 bit in [1]
//00000001 (1) = heart rate 16 bit in [1] + [2]
//00000110 () = sensor contact flags - status decoded in flags no other field needed
//00001000 (8) = energy status 16 bit in [2] + [3]
//00001001 (9) = energy status 16 bit in [3] + [4]
//00010000 (16) = RR-value 16 bit in [2] + [3]
//00010010 (18) = RR-value 16 bit in [2] + [3]
//00010100 (20) = RR-value 16 bit in [2] + [3]
//00010110 (22) = RR-value 16 bit in [2] + [3]
//00010001 (17) = RR-value 16 bit in [3] + [4]
//00010011 (19) = RR-value 16 bit in [3] + [4]
//00010101 (21) = RR-value 16 bit in [3] + [4]
//00010111 (23) = RR-value 16 bit in [3] + [4]
//00011000 (24) = RR-value 16 bit in [4] + [5]
//00011010 (26) = RR-value 16 bit in [4] + [5]
//00011100 (28) = RR-value 16 bit in [4] + [5]
//00011110 (30) = RR-value 16 bit in [4] + [5]
//00011001 (25) = RR-value 16 bit in [5] + [6]
//00011011 (27) = RR-value 16 bit in [5] + [6]
//00011101 (29) = RR-value 16 bit in [5] + [6]
//00011111 (31) = RR-value 16 bit in [5] + [6]
switch byteArray[0] {
case 16,18,20,22:
//rr-value in [2] und [3]
rawRRinterval = Int(byteArray[2]) + (Int(byteArray[3]) << 8)
case 17,19,21,23:
//rr-value in [3] und [4]
rawRRinterval = Int(byteArray[3]) + (Int(byteArray[4]) << 8)
case 24,26,28,30:
//rr-value in [4] und [5]
rawRRinterval = Int(byteArray[4]) + (Int(byteArray[5]) << 8)
case 25,27,29,31:
//rr-value in [5] und [6]
rawRRinterval = Int(byteArray[4]) + (Int(byteArray[5]) << 8)
}else{
print("RR-Interval values are not present.")
}
//Resolution of 1/1024 second
let rrInSeconds: Double = Double(rawRRinterval)/1024
print(" rrInSeconds: \(rrInSeconds)")
let rrInMilSeconds: Double = Double(rrInSeconds) * 1000
print(" rrInMilSeconds: \(rrInMilSeconds)")
let value = (Double(rawRRinterval) / 1024.0 ) * 1000.0
print(" value: \(value)")
return rrInMilSeconds发布于 2022-01-05 14:02:43
这是我的功能,以获取HR以及HRV (RR-间隔)从BLE(蓝牙低能)连接到一个iOS应用程序。与来自@yedy的解决方案不同,我想在执行过程中“打开”我的数组。
private func heartRate2(from characteristic: CBCharacteristic) -> (Int, [Double]) {
guard let characteristicData = characteristic.value else { return (-1, []) }
var byteArray = [UInt8](characteristicData)
var rawRRinterval = 0
var rrInMilSeconds = [Double]()
var hrValue = 0
// https://www.bluetooth.com/wp-content/uploads/Sitecore-Media-Library/Gatt/Xml/Characteristics/org.bluetooth.characteristic.heart_rate_measurement.xml
// https://stackoverflow.com/a/62692067/14414215
// https://stackoverflow.com/a/65458794/14414215
// Refer section 3.103.2.1 Flags field of Bluetooth GATT Specification Supplement
// The heart rate mesurement is in the 2nd, or in the 2nd and 3rd bytes, i.e. one one or in two bytes
// The first byte of the first bit specifies the length of the heart rate data, 0 == 1 byte, 1 == 2 bytes
// the & 0x01 is the bitwise operation on the first value in the array. (the Flag)
// BIT0: 00000001 - 1 - 0x01 - HR Value 0 = UINT8, 1 = UINT16
// BIT1: 00000010 - 2 - 0x02 - Sensor Contact Status 1 = Sensor Contact Supported
// BIT2: 00000100 - 4 - 0x04 - Sensor Contact Status 1 = Good contact with the skin
// BIT3: 00001000 - 8 - 0x08 - Energy Expended 1 = Present
// BIT4: 00010000 - 16 - 0x10 - RR-Interval 1 = Present
let flags = byteArray[0]
// Pop 1st Bits (Flags)
byteArray.removeFirst(1)
// Check HR is UINT8(1bit) or UINT16(2bit)
if flags & 0x01 == 0 {
hrValue = Int(byteArray[0])
byteArray.removeFirst(1)
} else if flags & 0x01 == 1 {
hrValue = (Int(byteArray[0]) << 8) + Int(byteArray[1])
byteArray.removeFirst(2)
}
// Check Sensor Contact Detection support
if flags & 0x02 > 0 {
byteArray.removeFirst(1)
}
// Check Sensor Contact Support
if flags & 0x04 > 0 {
byteArray.removeFirst(1)
}
// Check Energy Expended Support
if flag & 0x08 > 0 {
byteArray.removeFirst(2)
}
// check for RR presence
if (flags & 0x10 ) != 0 {
while byteArray.count > 0 {
rawRRinterval = Int(byteArray[0]) + (Int(byteArray[1]) << 8)
//Resolution of 1/1024 second
rrInMilSeconds.append((Double(rawRRinterval) / 1024.0 ) * 1000.0)
byteArray.removeFirst(2)
}
}
return (hrValue, rrInMilSeconds)
}发布于 2020-02-22 07:23:59
首先,需要将特征值数据转换为UInt8数组,然后检查心率传感器是否提供指标值。我在我的项目中使用了下面的代码,它运行得很好。希望它也能帮到你。
var heartRate: Int = 0
guard let characteristicData = characteristic.value else { return }
let byteArray = [UInt8](characteristicData)
let firstBitValue = byteArray[0] & 0x01
if firstBitValue == 0 {
// Heart Rate Value Format is in the 2nd byte
heartRate = Int(byteArray[1])
} else {
// Heart Rate Value Format is in the 2nd and 3rd bytes
heartRate = (Int(byteArray[2]) << 8) + Int(byteArray[1])
}
print("heart rate", heartRate)将上述代码放入CBPeripheralDelegate的CBPeripheralDelegate方法中,并尝试从心率传感器中获取值。
https://stackoverflow.com/questions/60348615
复制相似问题