0

I am retrieving a BLE characteristic value and I want to understand how am I supposed to read the advertised value on an iOS App using Swift?

I am using a c++ Library from nkolban to advertise a value over Bluetooth from an ESP32. I have a u32int value voltage1 and convert it into a string:

std::string Voltage1AsString((char*)&voltage1, 4);

Then set the value for the characteristic:

Signal1_Characteristic->setValue(Voltage1AsString);

What I found till now is this function for reading in the value which, nearly works perfectly, but I want to understand the complete implementation to gain the knowledge for another use case.

private func getByteArray(from characteristic: CBCharacteristic ) -> Int{
        guard let characteristicData = characteristic.value else {return -1}
        let byteArray = [UInt8](characteristicData)

        return (Int(byteArray[1]) << 8) + Int(byteArray[2] << 8) + Int(byteArray[3] << 8) + Int(byteArray[2] << 8)

    }
  • 1
    more like shift left bitwise – user7860670 Sep 03 '19 at 10:47
  • @VTT I've corrected that, we used to learn MIPS in the university so I stucked with this one – Panagiotis D. Sep 03 '19 at 10:58
  • 2
    The Swift bitwise shift operators are excellently documented (with illustrations) in [Advanced Operators](https://docs.swift.org/swift-book/LanguageGuide/AdvancedOperators.html). – Martin R Sep 03 '19 at 11:02
  • This is not an array operation! Anyway this code smells in many ways: missing zero index, https://repl.it/repls/TidyUnevenDistributionsoftware – Marek R Sep 03 '19 at 11:10
  • Possible duplicate of [Convert bytes/UInt8 array to Int in Swift](https://stackoverflow.com/questions/32769929/convert-bytes-uint8-array-to-int-in-swift) – Marek R Sep 03 '19 at 11:25
  • The decoding function as @MarekR says is pretty odd - funny placed brackets, non-zero, all the shifting. But I suppose it comes does to what your Voltage1AsString function is doing. Does the library not accept uint32s, or a simple cast to uint8[4]? – N. Smith Sep 03 '19 at 11:32
  • @N.Smith note `byteArray[2] << 8` always produces zero! So in fact only `byteArray[1]` has impact on result. I'm pretty sure I've linked proper answer. – Marek R Sep 03 '19 at 11:33
  • Possible duplicate of [What are bitwise shift (bit-shift) operators and how do they work?](https://stackoverflow.com/questions/141525/what-are-bitwise-shift-bit-shift-operators-and-how-do-they-work) – phuclv Sep 03 '19 at 12:57

1 Answers1

2

The way you converted the voltage value to a string is fundamentally broken. And most of all: it's not needed. There are several setValue functions and one of them takes an uint32_t. So it's simply:

Signal1_Characteristic->setValue(voltage1);

The voltage value will then be transmitted as a binary values (four bytes, starting with the least significant byte).

On the receiving end, you can reconstruct the value like so:

private func getByteArray(from characteristic: CBCharacteristic ) -> Int{
    guard let characteristicData = characteristic.value else { return -1 }
    let byteArray = [UInt8](characteristicData)
    return (Int(byteArray[0]) << 0)
         + (Int(byteArray[1]) << 8)
         + (Int(byteArray[2]) << 16)
         + (Int(byteArray[3]) << 24)
}

Each byte is 8 bit long. So in order to combined the four bytes into a single 32-bit value, they need to be offset by 0, 8, 16 and 24.

BTW: In C++, it is a convention to use a names starting with a lowercase letter for variables and functions. It's helpful to stick to these conventions as you are reading other people's code and other people are reading your code.

Codo
  • 75,595
  • 17
  • 168
  • 206