1

I am having a hard time getting the correct value that I need. I get from my characteristic vales from:

func peripheral(_ peripheral: CBPeripheral, didUpdateValueFor ...

I can read and print off the values with:

let values = characteristic.value
for val in values! {
    print("Value", num)
}

This gets me:

"Value 0" // probe state not important
"Value 46" // temp 
"Value 2" // see below

The problem is that the temp is not 46. Below is a snippet of instructions on how I need to convert the byte to get the actual temp. The actual temp was around 558 ºF. Here are a part of the instructions:

Description: temperature data that is valid only if the temperature stat is normal
byte[1] = (unsigned char)temp;
byte[2] = (unsigned char)(temp>>8);
byte[3] = (unsigned char)(temp>>16);
byte[4] = (unsigned char)(temp>>24);

I can't seem to get the correct temp? Please let me know what I am doing wrong.

Rob Napier
  • 286,113
  • 34
  • 456
  • 610
temp_
  • 1,238
  • 2
  • 12
  • 24
  • Others have answered your question, but I will pipe in to say to get rid of the `!` after `values`. If the `peripheral()` function returns `nil`, and your program uses the `!` operator on it, your entire program will crash. Instead, use `if let` or `guard let` to unwrap it, or use `?? []` to replace `nil` with an empty array. – Charles Srstka Apr 25 '18 at 17:31
  • @CharlesSrstka I just wanted to make my question short. Probably bad practice, but you are right, it's too risky to just add ! – temp_ Apr 25 '18 at 17:35
  • What I do when I want to use a for loop like this is just to say `for val in values ?? []`. Almost as short, and won't crash. – Charles Srstka Apr 25 '18 at 17:38
  • @CharlesSrstka I will have to try that if I don't check with an "if let". – temp_ Apr 25 '18 at 17:50

2 Answers2

2

The instructions tell you the answer. You are getting 46 in byte 1, then 2 in byte 2. The instructions say to leave byte 1 alone, but for byte 2 we are to shift the results as temp>>8 — which means "multiply by 256" (because 2^8 is 256). Well, what is

46+256×2

It is 558, just the result we're looking for.

matt
  • 515,959
  • 87
  • 875
  • 1,141
2

According to the description, value[1] ... value[4] are the least significant to most significant bytes of the (32-bit integer) temperature, so this is how you would recreate that value from the bytes:

if let value = characteristic.value, value.count >= 5 {
    let tmp = UInt32(value[1]) + UInt32(value[2]) << 8 + UInt32(value[3]) << 16 + UInt32(value[4]) << 24
    let temperature = Int32(bitPattern: tmp)
}

The bit-fiddling is done in unsigned integer arithmetic to avoid an overflow. Assuming that the temperature is a signed value, this value is then converted to a signed integer with the same bit representation.

Martin R
  • 529,903
  • 94
  • 1,240
  • 1,382
  • 1
    `UInt32(value[1]) + UInt32(value[2]) << 8 + UInt32(value[3]) << 16 + UInt32(value[4]) << 24` sounds like a job for its own `UInt32` extension. – Alexander Apr 25 '18 at 18:06
  • 1
    @Alexander: Something like this: [round trip Swift number types to/from Data](https://stackoverflow.com/questions/38023838/round-trip-swift-number-types-to-from-data) ? – Martin R Apr 25 '18 at 18:11
  • @MartinR Yep :D Don't have time to look into that in detail right now, but is it ABI dependent? – Alexander Apr 25 '18 at 19:22
  • @Alexander: If you think of byte order: No, my answer does not handle that, but it would not be difficult to add, using the bigEndian/littleEndian methods/initializers. It is partially handled in https://stackoverflow.com/a/41067342/1187415. – Martin R Apr 25 '18 at 19:27