1

I'm trying to read the current time from a Bluetooth device.

I currently get a 10 byte array but I'm unsure how to convert that to something readable.

Here is the code I'm reading it from.

private func printTime(from characteristic: CBCharacteristic) {
        guard let timeData = characteristic.value else { return }
        let byteArray = [UInt8](timeData)


        print("Time ",byteArray, "timeData ", timeData)
    }

Here is the output.

Time  [224, 7, 1, 3, 4, 36, 5, 0, 0, 1] timeData  10 bytes

Here is the specs I got for the device on this characteristic.

3.2.1.  Current Time        
3.2.1.1.    UUID:       2A2B
3.2.1.2.    Read:       Yes
3.2.1.3.    Write:      Yes
3.2.1.4.    Notify:     Yes
3.2.1.5.    Value:      byte[10]    
3.2.1.6.    Description:        0 – 1:  Year
                                2:  Month
                                3:  Day
                                4:  Hour
                                5:  Minute
                                6:  Seconds
                                7:  Day of Week
                                8:  256 Fractions of a Seconds
                                9:  Adjust Reason

So I know the year is 224, 7. Which I assume is 2016 but I'm not sure how to convert this in code.

rmaddy
  • 314,917
  • 42
  • 532
  • 579
Matt C
  • 548
  • 3
  • 9
  • The year is a little-endian 16 bit integer 7*256+224 = 2016. You just need to get the bytes from the data and perform the math. – Paulw11 Oct 16 '19 at 19:00
  • Thanks, Paul. That makes sense now. – Matt C Oct 16 '19 at 19:30
  • @rmaddy - where did you find the spec for Current Time? - I've searched and cannot find the same definition as clean as you have here. I'm actually looking the same format of "Local Time". – David Wilson Jan 26 '21 at 07:45

1 Answers1

2

To convert from data/bytes to numeric types you can check this post

extension Numeric {
    init<D: DataProtocol>(_ data: D) {
        var value: Self = .zero
        let size = withUnsafeMutableBytes(of: &value, { data.copyBytes(to: $0)} )
        assert(size == MemoryLayout.size(ofValue: value))
        self = value
    }
}

extension DataProtocol {
    func value<N: Numeric>() -> N { .init(self) }
    var uint16: UInt16 { value() }
}

Now you can easily convert from bytes to any numeric type:

let timeData: [UInt8] = [224, 7, 1, 3, 4, 36, 5, 0, 0, 1]
let timeDate = DateComponents(calendar: .current,
                               timeZone: .current,
                               year: Int(timeData[0..<2].uint16),
                               month: Int(timeData[2]),
                               day: Int(timeData[3]),
                               hour: Int(timeData[4]),
                               minute: Int(timeData[5]),
                               second: Int(timeData[6])).date!
timeDate // "Jan 3, 2016 at 4:36 AM"
Leo Dabus
  • 229,809
  • 59
  • 489
  • 571