从字节中获取字符串(Corebluetooth,Swift)

Posted

技术标签:

【中文标题】从字节中获取字符串(Corebluetooth,Swift)【英文标题】:Getting a String from a byte (Corebluetooth, Swift) 【发布时间】:2020-05-13 09:13:31 【问题描述】:

只是为了看看是否有人可以帮助我解决一些 BLE 问题。我正在尝试制作一个从划船机中获取内容的应用程序,但我不知道如何将字节转换为字符串?很难解释,但这是我的 VC:

import UIKit
import CoreBluetooth


let rowerServiceCBUUID = CBUUID(string: "CE060000-43E5-11E4-916C-0800200C9A66")
let characteristic1CBUUID = CBUUID(string: "CE060031-43E5-11E4-916C-0800200C9A66")
let characteristic2CBUUID = CBUUID(string: "2AD1")
class HRMViewController: UIViewController 
  @IBOutlet weak var heartRateLabel: UILabel!
  @IBOutlet weak var bodySensorLocationLabel: UILabel!
  var centralManager: CBCentralManager!
  var pmPeripheral: CBPeripheral!
  var wattValue: Int!
  override func viewDidLoad() 
    super.viewDidLoad()
    centralManager = CBCentralManager(delegate: self, queue: nil)
    // Make the digits monospaces to avoid shifting when the numbers change
    heartRateLabel.font = UIFont.monospacedDigitSystemFont(ofSize: heartRateLabel.font!.pointSize, weight: .regular)
  

  func onHeartRateReceived(_ heartRate: Int) 
    heartRateLabel.text = String(heartRate)
    print("BPM: \(heartRate)")
  

extension HRMViewController: CBCentralManagerDelegate 
  func centralManagerDidUpdateState(_ central: CBCentralManager) 
      print("Central state update")
      if central.state != .poweredOn 
          print("Central is not powered on")
       else 
          print("Central scanning for", rowerServiceCBUUID);
          centralManager.scanForPeripherals(withServices: [rowerServiceCBUUID],
                                            options: [CBCentralManagerScanOptionAllowDuplicatesKey : true])
      
  

  func centralManager(_ central: CBCentralManager, didDiscover peripheral: CBPeripheral, advertisementData: [String : Any], rssi RSSI: NSNumber) 
    print(peripheral)
    peripheral.delegate = self
    pmPeripheral = peripheral
    pmPeripheral.delegate = self
    centralManager.stopScan()
    centralManager.connect(pmPeripheral!)
  
  func centralManager(_ central: CBCentralManager, didConnect peripheral: CBPeripheral) 
    print("Connected!")
    pmPeripheral.discoverServices(nil)
  


extension HRMViewController: CBPeripheralDelegate 
  func peripheral(_ peripheral: CBPeripheral, didDiscoverServices error: Error?) 
    guard let services = peripheral.services else  return 
    for service in services 
      print(service)
      print(service.characteristics ?? "characteristics are nil")
      peripheral.discoverCharacteristics(nil, for: service)
    
  
  func peripheral(_ peripheral: CBPeripheral, didDiscoverCharacteristicsFor service: CBService, error: Error?)
    guard let characteristics = service.characteristics else  return 
    for characteristic in characteristics 
      print(characteristic)
      if characteristic.properties.contains(.read) 
        print("\(characteristic.uuid): properties contains .read")
      
      if characteristic.properties.contains(.notify) 
        print("\(characteristic.uuid): properties contains .notify")
      
      peripheral.readValue(for: characteristic)
    
  
  func peripheral(_ peripheral: CBPeripheral, didUpdateValueFor characteristic: CBCharacteristic,
                  error: Error?) 
    switch characteristic.uuid 
      case characteristic1CBUUID:
        let bodySensorLocation = bodyLocation(from: characteristic)
        bodySensorLocationLabel.text = bodySensorLocation
      default:
        print("Unhandled Characteristic UUID: \(characteristic.uuid)")
    
  
  private func bodyLocation(from characteristic: CBCharacteristic) -> String 
    guard let characteristicData = characteristic.value,
      let byte = characteristicData.first else  return "Error" 
    switch byte 
      case 0: return "0"
      case 1: return "1"
      case 2: return "2"
      case 3: return "3"
      case 4: return "4"
      case 5: return "5"
      case 6: return "6"
      case 7: return "7"
      case 8: return "8"
      default:
        return "Reserved for future use"
    
  

特别是最底部的文本是我卡住的地方,每个 Corebluetooth 指南都将数字交换为文本,但我的是一个字符串数组(如下所示:https://youtu.be/rXDCBVQXdbg)

我被困住了,不知道从这里去哪里。对此的任何帮助将不胜感激!

【问题讨论】:

您需要查看您正在使用的特征的定义。如果是字符串数据,则可以使用String(data: data, encoding .utf8) 【参考方案1】:

从您使用的 UUID 来看,您目前关注的是Concept2 Performance Monitor Bluetooth Smart Communications Interface Definition 第 11 页上记录的C2 划船一般状态特征

文档说该消息将由 19 个字节组成:

字节 0:经过时间 Lo(0.01 秒 lsb) 字节 1:中间经过的时间 字节 2:经过时间高 字节 3:距离 Lo (0.1 m lsb) 字节 4:中距离 字节 5:距离高 字节 6:锻炼类型(枚举) ...

经过的时间存储在 3 个字节中:字节 0 是最低有效字节 (LSB),然后是中字节和高字节。单位为0.01s。所以要获得秒数,必须除以 100。

距离的存储方式类似。单位是0.1m。

锻炼类型在字节 6 中作为枚举给出。所以不包含文本。只是一个数字代码。

要对其进行解码,请使用如下代码。函数onRowingGeneralStatusUpdate(for:) 替换了你容易混淆的函数bodyLocation(from:)

func onRowingGeneralStatusUpdate(characteristic: CBCharacteristic) 
    guard let data = characteristic.value else  return 

    // elapsed time in sec
    let elapsedTime: Double = Double(Int(data[0]) + 256 * Int(data[1]) + 65536 * Int(data[2])) / 100.0
    // distance in m
    let distance: Double = Double(Int(data[3]) + 256 * Int(data[4]) + 65536 * Int(data[5])) / 10.0
    let workout: String =  workoutType(for: data[6])


func workoutType(for code: UInt8) -> String 
    switch code 
    case 0:
        return "Just row, no splits"
    case 1:
        return "Just row, splits"
    case 2:
        return "Fixed dist, no splits"
    case 3:
        return "Fixed dist, splits"
    case 4:
        return "Fixed time, no splits"
    case 5:
        return "Fixed time, splits"
    case 6:
        return "Fixed time, interval"
    case 7:
        return "Fixed dist, interval"
    case 8:
        return "Variable, interval"
    case 9:
        return "Variable, undef rest, interval"
    case 10:
        return "Fixed, calorie"
    case 11:
        return "Fixed, watt-minutes"
    case 12:
        return "Fixed cals, interval"
    default:
        return ""
    

【讨论】:

我得说,谢谢!没有你的回答,我仍然会困惑地坐在这里。 (它被称为 bodylocation,因为我正在关注人力资源指南) 嘿,呃,你能帮我做点什么吗?每当我打印出锻炼、距离和经过的时间时,每次打印时它都会打印出 Error, 120856.02, 1083899.8。你知道我需要做什么来修复它吗? 听起来好像接收到的数据根本不符合预期的描述。可能是错误的特征或其他一些混淆?

以上是关于从字节中获取字符串(Corebluetooth,Swift)的主要内容,如果未能解决你的问题,请参考以下文章

iPhone 5C/5S 上的 CoreBluetooth:收到的数据损坏

如何获取/查找 CoreBluetooth.Framework?

按照字符和字节截取内容的区别

字符串数据进入内存的位置

如何在 CoreBluetooth Swift 中获取 kCBAdvDataManufacturerData?

汇编 x86 从任何文件读取并转义所有特殊字符并以字节为单位获取文件大小