Need help reading temperature sensor data from a TI SensorTag 2650

I am able to read and print the values for the Luxometer; however, I need help figuring out what I am doing wrong when reading the values for the Ambient Temperature on a TI SensorTag 2650.


Code builds fine; however, I get NO values from temperature, ONLY luxometer values. I have downloaded the TI app for the SensorTag, and determined that the sensor is working as the app is able to obtain readings just fine...


I tried two different functions for the sensor read - tempConvert() and tempConvertion(). Both result in nothing read.


Thanks in advance...


Here's my code:


import UIKit
import CoreBluetooth

// Luxometer Service
let svcLight = CBUUID.init(string: "F000AA70-0451-4000-B000-000000000000")
let charLightData = CBUUID.init(string: "F000AA71-0451-4000-B000-000000000000")
let charLightConfig = CBUUID.init(string: "F000AA72-0451-4000-B000-000000000000")

// Humidity Service
let svcHumidity = CBUUID.init(string: "F000AA20-0451-4000-B000-000000000000")
let charHumidityData = CBUUID.init(string: "F000AA21-0451-4000-B000-000000000000")
let charHumidityConfig = CBUUID.init(string: "F000AA22-0451-4000-B000-000000000000")

// Temperature Service
let svcTemp = CBUUID.init(string: "F000AA00-0451-4000-B000-000000000000")
let charTempData = CBUUID.init(string: "F000AA01-0451-4000-B000-000000000000")
let charTempConfig = CBUUID.init(string: "F000AA02-0451-4000-B000-000000000000")

// IO Service
let svcIO = CBUUID.init(string: "F000AA64-0451-4000-B000-000000000000")
let charIOData = CBUUID.init(string: "F000AA65-0451-4000-B000-000000000000")
let charIOConfig = CBUUID.init(string: "F000AA66-0451-4000-B000-000000000000")

// Simple Keys Service
let svcKeys = CBUUID.init(string: "FFE0")
let charKeys = CBUUID.init(string: "FFE1")

class ViewController: UIViewController, CBCentralManagerDelegate, CBPeripheralDelegate {
   
    var centralManager : CBCentralManager!
    var myPeripheral : CBPeripheral?

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
        centralManager = CBCentralManager.init(delegate: self, queue: nil)
    }

    // 1. Scan for peripherals
    func centralManagerDidUpdateState(_ central: CBCentralManager) {
       
        // IF the Bluetooth device is powered on then do this...
        if central.state == CBManagerState.poweredOn {
            // ONLY Scan IF necessary, OTHERWISE
            // Check if we have connected with this peripheral before
            // Check if Data exists in UserDefaults array at key[PUUID]
            if let pUUIDString = UserDefaults.standard.object(forKey: "PUUID") as? String {
                // Check if UUID Data exists in pUUIDString
                if let pUUID = UUID.init(uuidString: pUUIDString) {
                    // CREATE a centralManager UUID from the UUID stored in UserDefaults Array
                    let peripherals = centralManager.retrievePeripherals(withIdentifiers: [pUUID])
                    // Check if Data exists in the first key of the peripherals Array
                    if let p = peripherals.first {
                        // Connect to peripheral found
                        connect(toPeripheral: p)
                        return
                    }
                }
            }
            // IF unable to connect to a stored peripheral then do this...
            let peripherals = centralManager.retrieveConnectedPeripherals(withServices: [CBUUID.init(string: "AA80")])
            if let p = peripherals.first {
                connect(toPeripheral: p)
                return
            }
            // IF still unable to connect to a stored peripheral then do this...
            // Scan for peripherals if Bluetooth is powered on
            central.scanForPeripherals(withServices: nil, options: nil)
            print ("scanning...")
        }
    }
   
    // 2. IF a peripheral is dicovered do this...
    func centralManager(_ central: CBCentralManager, didDiscover peripheral: CBPeripheral, advertisementData: [String : Any], rssi RSSI: NSNumber) {
        if peripheral.name?.contains("SensorTag") == true {
            print(advertisementData)
            connect(toPeripheral: peripheral)
        }
    }
    // 3. CONNECT to peripheral
    func connect(toPeripheral : CBPeripheral) {
        print(toPeripheral.name ?? "no name")
        centralManager.stopScan()
        // Conect to peripheral
        centralManager.connect(toPeripheral, options: nil)
        myPeripheral = toPeripheral // local copy of peripheral
    }
   
    // 3a. IF peripheral disconnects do this...
    func centralManager(_ central: CBCentralManager, didDisconnectPeripheral peripheral: CBPeripheral, error: Error?) {
        // Start scanning again
        central.scanForPeripherals(withServices: nil, options: nil)
    }
    // 4. Do this when we CONNECT to a Peripheral
    func centralManager(_ central: CBCentralManager, didConnect peripheral: CBPeripheral) {
       
        if let myPeripheral = peripheral.name {
            // Display the peripheral we connected to
            print("connected to: \(myPeripheral)")
        }
        // Discover the Available services
        peripheral.discoverServices(nil)
        peripheral.delegate = self
        // Store the peripheral UUID in the user's phone - This allows quicker reconnection in future
        UserDefaults.standard.set(peripheral.identifier.uuidString, forKey: "PUUID")
        UserDefaults.standard.synchronize()
       
    }
    // 5. When SERVICES are Discovered do this...
    func peripheral(_ peripheral: CBPeripheral, didDiscoverServices error: Error?) {
        // Check if services Data exists in the Peripheral
        if let services = peripheral.services {
            // IF Data exists then Iterate throught each service in the services Data array
            for svc in services {
                // IF the UUID matches the Luxometer Service then do this
                if svc.uuid == svcLight {
                    print(svc.uuid.uuidString)
                    // Discover characteristics for svcLight
                    peripheral.discoverCharacteristics(nil, for: svc)
                    // IF the UUID matches the
                } else if svc.uuid == svcKeys {
                    // Discover characteristics for svcKeys
                    peripheral.discoverCharacteristics(nil, for: svc)
                } else if svc.uuid == svcTemp {
                    // Discover characteristics for svcTemp
                    peripheral.discoverCharacteristics(nil, for: svc)
                } else if svc.uuid == svcHumidity {
                    // Discover characteristics for svcHumidity
                    peripheral.discoverCharacteristics(nil, for: svc)
                } else if svc.uuid == svcIO {
                    // Discover characteristics for svcIO
                    peripheral.discoverCharacteristics(nil, for: svc)                }
            }
        }
       
    }
    // 6. When characteristics are Discovered do this...
    func peripheral(_ peripheral: CBPeripheral, didDiscoverCharacteristicsFor service: CBService, error: Error?) {
       
        // Check if characteristics Data exists in the service Array
        if let characteristics = service.characteristics {
            // Loop through the characteristics Array
            for characteristic in characteristics {
                // Print the UUID for the characteristic
                print(characteristic.uuid.uuidString)
                // IF the characteristic uuid matches charLightConfig then do this...
                if characteristic.uuid == charLightConfig {
                    // Write a 01 to the characteristic to turn ON
                    if characteristic.properties.contains(CBCharacteristicProperties.writeWithoutResponse) {
                        peripheral.writeValue(Data.init(bytes: [01]), for: characteristic, type: CBCharacteristicWriteType.withoutResponse)
                    } else {
                        peripheral.writeValue(Data.init(bytes: [01]), for: characteristic, type: CBCharacteristicWriteType.withResponse)
                    }
                // IF the characteristic uuid matches charLightData then do this...
                } else if characteristic.uuid == charLightData {
                    // Read value from characteristic every 5 seconds
                    checkLight(curChar: characteristic)
                // IF the characteristic uuid matches the UUID stored for charKeys then do this...
                } else if characteristic.uuid == charKeys {
                    // Read value from characteristic ONLY when a button is pressed
                    peripheral.setNotifyValue(true, for: characteristic)
                // IF the characteristic matches charTempConfig then do this...
                } else if characteristic.uuid == charTempConfig {
                    // Write a 01 to the characteristic to turn ON
                    if characteristic.properties.contains(CBCharacteristicProperties.writeWithoutResponse) {
                        peripheral.writeValue(Data.init(bytes: [01]), for: characteristic, type: CBCharacteristicWriteType.withoutResponse)
                        peripheral.setNotifyValue(true, for: characteristic)
                    } else {
                        peripheral.writeValue(Data.init(bytes: [01]), for: characteristic, type: CBCharacteristicWriteType.withResponse)
                        peripheral.setNotifyValue(true, for: characteristic)
                    }
                    // IF the characteristic uuid matches charLightData then do this...
                } else if characteristic.uuid == charTempData {
                    peripheral.setNotifyValue(true, for: characteristic)
                    // Read value from characteristic every 5 seconds
                    checkTemp(curChar: characteristic)
                   
                }
            }
        }
    }
    // 7. When a value is written to a characteristic do this...
    func peripheral(_ peripheral: CBPeripheral, didWriteValueFor characteristic: CBCharacteristic, error: Error?) {
        print("wrote value for: \(characteristic)")
    }
    // 8. When Data is retrieved from a characteristic do this...
    func peripheral(_ peripheral: CBPeripheral, didUpdateValueFor characteristic: CBCharacteristic, error: Error?) {
        // Check if value Data exists in characteristic
        if let val = characteristic.value {
            // If the characteristic UUID matches charLightData UUID then do this...
            if characteristic.uuid == charLightData {
                // Convert the value from the characteristic
                let luxVal = luxConvert(value: val)
                // Display the converted value
                print("Luxometer: \(luxVal)")
            }
            // If the characteristic UUID matches charKeys UUID then do this...
            else if characteristic.uuid == charKeys {
                // Display which key was pressed
                print("keys: \([UInt8](val))")
            }
           
            else if characteristic.uuid == charTempData {
                let tempVal = tempConvertion(value: val as NSData)
                print("Temperature: \(tempVal)")
                let tempVal2 = tempConvert(value: val as NSData)
                print("Temperature: \(tempVal2)")
            }
        }
    }
   
    func dataToUnsignedBytes16(value : Data) -> [UInt16] {
        let count = value.count
        var array = [UInt16](repeating: 0, count: count)
        (value as NSData).getBytes(&array, length:count * MemoryLayout.size)
        return array
    }
   
    func dataToSignedBytes16(value : NSData) -> [Int16] {
        let count = value.length
        var array = [Int16](repeating: 0, count: count)
        value.getBytes(&array, length:count * MemoryLayout.size)
        return array
    }
   
    // Convert Data from Luxometer service
    func luxConvert(value : Data) -> Double {
        let rawData = dataToUnsignedBytes16(value: value)
        var e :UInt16 = 0
        var m :UInt16 = 0
        m = rawData[0] & 0x0FFF;
        e = (rawData[0] & 0xF000) >> 12;
        /** e on 4 bits stored in a 16 bit unsigned => it can store 2 << (e - 1) with e < 16 */
        e = (e == 0) ? 1 : 2 << (e - 1);
        return Double(m) * (0.01 * Double(e));
    }
   
    func tempConvert(value : NSData) -> Double {
        let rawData = dataToSignedBytes16(value: value)
        let SCALE_LSB = 0.03125
        // let a = rawData[0] >> 2
        // let Obj = Double(a) * SCALE_LSB
        let b = rawData[1] >> 2
        let AmbTemp = Double(b) * SCALE_LSB
        return AmbTemp
    }
    // Retrieve Data from a GIVEN characteristic every 5 seconds
    func checkLight(curChar : CBCharacteristic) {
        Timer.scheduledTimer(withTimeInterval: 5.0, repeats: true) { (timer) in
            self.myPeripheral?.readValue(for: curChar)
        }
    }
    // Retrieve Data from a GIVEN characteristic every 5 seconds
    func checkTemp(curChar : CBCharacteristic) {
        Timer.scheduledTimer(withTimeInterval: 5.0, repeats: true) { (timer) in
            self.myPeripheral?.readValue(for: curChar)
        }
    }
   
    func tempConvertion(value : NSData) -> Double {
        let dataLength = value.length
        var dataArray = [Int16](repeating: 0, count: dataLength)
        value.getBytes(&dataArray, length: dataLength * MemoryLayout.size)
       
        // Element 1 of the array will be ambient temperature raw value
        let ambientTemperature = Double(dataArray[1])/128
        return ambientTemperature
    }

}

Replies

Could you share the full log (results of print statements) ?


Have you contacted TI ?

What are the values from your current `tempConvert` and `tempConvertion`? Both are not Optional and you can read some outputs from them.