iosswiftbluetooth-lowenergynsdata

Get a string from BLE


Hello I am beginner in swift, and I am trying to make an application that communicate one BLE with a polar heart rate, I have a problem to get the correct information from data structure generated by characteristic.value, I really have a problem to transform that from uint8 to something more simple like int or strings.

her is my code:

func peripheral(_ peripheral: CBPeripheral, didUpdateValueForCharacteristic characteristic: CBCharacteristic, error: NSError?) {

    if characteristic.uuid == POLARH7_HRM_MEASUREMENT_CHARACTERISTIC_UUID {
        print("Get the new heart BPM : ", terminator:"")

        var wavelength: UInt16?
        if let data = characteristic.value {
            var bytes = Array(repeating: 0 as UInt8, count:(characteristic.value?.count)!/MemoryLayout<UInt8>.size)

            data.copyBytes(to: &bytes, count:data.count)
            let data16 = bytes.map { UInt16($0) }
            wavelength = 256 * data16[1] + data16[0]

        }
        print("W : ")
        print(wavelength)
    }

    if characteristic.uuid == POLARH7_HRM_BODY_LOCATION_CHARACTERISTIC_UUID {
        print("Get the new sensor location", terminator:"")
        print(characteristic.value)
        //let data = NSData(data: characteristic.value as! Data)

    }

    if characteristic.uuid == POLARH7_HRM_MANUFACTURER_NAME_CHARACTERISTIC_UUID {
        print("Get the new name", terminator:"")
        print(characteristic.value)
    }

}

I trie a lot of ways, but I am new to swift and swift 3 is not easy because every year there is an update in this language so the most tips a found were in objective-c or swift 2. like in this exemples :

    // Instance method to get the manufacturer name of the device
- (void) getManufacturerName:(CBCharacteristic *)characteristic
{
    NSString *manufacturerName = [[NSString alloc] initWithData:characteristic.value encoding:NSUTF8StringEncoding];  // 1
    self.manufacturer = [NSString stringWithFormat:@"Manufacturer: %@", manufacturerName];    // 2
    return;
}

or

    - (void) getHeartBPMData:(CBCharacteristic *)characteristic error:(NSError *)error
{
    // Get the Heart Rate Monitor BPM
    NSData *data = [characteristic value];      // 1
    const uint8_t *reportData = [data bytes];
    uint16_t bpm = 0;

    if ((reportData[0] & 0x01) == 0) {          // 2
        // Retrieve the BPM value for the Heart Rate Monitor
        bpm = reportData[1];
    }
    else {
        bpm = CFSwapInt16LittleToHost(*(uint16_t *)(&reportData[1]));  // 3
    }
    // Display the heart rate value to the UI if no error occurred
    if( (characteristic.value)  || !error ) {   // 4
        self.heartRate = bpm;
        self.heartRateBPM.text = [NSString stringWithFormat:@"%i bpm", bpm];
        self.heartRateBPM.font = [UIFont fontWithName:@"Futura-CondensedMedium" size:28];
        [self doHeartBeat];
        self.pulseTimer = [NSTimer scheduledTimerWithTimeInterval:(60. / self.heartRate) target:self selector:@selector(doHeartBeat) userInfo:nil repeats:NO];
    }
    return;
}

thanks in advance


Solution

  • The data sent from BLE devices is usually in unicode, so you will need to convert these unicode values to whatever you need it to be.

    Here is an example for converting it to strings:

    // Convert byte to unicode string
    let unicodeString = String(data: characteristic.value!, encoding: String.Encoding.utf8)
    
    // Initialize value
    var value: String? = nil
    
    // Convert unicode to actual value
    for element in unicodeString!.unicodeScalars {
        value = "\(element.value)"
    }
    
    // If value exists
    if let value = value {
        // Do something with the value
    }