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
}
}