G5 improvements
This commit is contained in:
parent
21d608f17b
commit
51fe942fa5
|
@ -20,7 +20,7 @@
|
|||
F8025E4E21ED450300ECF0C0 /* Double.swift in Sources */ = {isa = PBXBuildFile; fileRef = F8025E4D21ED450300ECF0C0 /* Double.swift */; };
|
||||
F8025E5021EE746400ECF0C0 /* CalibratorProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = F8025E4F21EE746400ECF0C0 /* CalibratorProtocol.swift */; };
|
||||
F8025E5421EE8D2100ECF0C0 /* Libre1Calibrator.swift in Sources */ = {isa = PBXBuildFile; fileRef = F8025E5321EE8D2100ECF0C0 /* Libre1Calibrator.swift */; };
|
||||
F8025E5721F4A60900ECF0C0 /* CGMTransmitterProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = F8025E5621F4A60900ECF0C0 /* CGMTransmitterProtocol.swift */; };
|
||||
F8025E5721F4A60900ECF0C0 /* CGMTransmitter.swift in Sources */ = {isa = PBXBuildFile; fileRef = F8025E5621F4A60900ECF0C0 /* CGMTransmitter.swift */; };
|
||||
F8025E6421F7BF3300ECF0C0 /* UserDefaults.swift in Sources */ = {isa = PBXBuildFile; fileRef = F8025E6321F7BF3300ECF0C0 /* UserDefaults.swift */; };
|
||||
F8025E6B21F7CD7600ECF0C0 /* UIStoryboard.swift in Sources */ = {isa = PBXBuildFile; fileRef = F8025E6A21F7CD7600ECF0C0 /* UIStoryboard.swift */; };
|
||||
F8025E6D21F7CD7C00ECF0C0 /* UIViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = F8025E6C21F7CD7C00ECF0C0 /* UIViewController.swift */; };
|
||||
|
@ -84,7 +84,7 @@
|
|||
F8025E4D21ED450300ECF0C0 /* Double.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Double.swift; sourceTree = "<group>"; };
|
||||
F8025E4F21EE746400ECF0C0 /* CalibratorProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CalibratorProtocol.swift; sourceTree = "<group>"; };
|
||||
F8025E5321EE8D2100ECF0C0 /* Libre1Calibrator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Libre1Calibrator.swift; sourceTree = "<group>"; };
|
||||
F8025E5621F4A60900ECF0C0 /* CGMTransmitterProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CGMTransmitterProtocol.swift; sourceTree = "<group>"; };
|
||||
F8025E5621F4A60900ECF0C0 /* CGMTransmitter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CGMTransmitter.swift; sourceTree = "<group>"; };
|
||||
F8025E6321F7BF3300ECF0C0 /* UserDefaults.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserDefaults.swift; sourceTree = "<group>"; };
|
||||
F8025E6A21F7CD7600ECF0C0 /* UIStoryboard.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UIStoryboard.swift; sourceTree = "<group>"; };
|
||||
F8025E6C21F7CD7C00ECF0C0 /* UIViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UIViewController.swift; sourceTree = "<group>"; };
|
||||
|
@ -196,7 +196,7 @@
|
|||
isa = PBXGroup;
|
||||
children = (
|
||||
F8025C0E21D95EC200ECF0C0 /* CGMTransmitterDelegate.swift */,
|
||||
F8025E5621F4A60900ECF0C0 /* CGMTransmitterProtocol.swift */,
|
||||
F8025E5621F4A60900ECF0C0 /* CGMTransmitter.swift */,
|
||||
F85DC2FE21D3E83100B9F74A /* G4 */,
|
||||
F897AAFC2202575600CDDD10 /* G5 */,
|
||||
F8025C0621D8DCE700ECF0C0 /* MiaoMiao */,
|
||||
|
@ -557,7 +557,7 @@
|
|||
F897AB2622073C4B00CDDD10 /* AuthChallengeTxMessage.swift in Sources */,
|
||||
F8AC425E21ADEBD60078C348 /* AppDelegate.swift in Sources */,
|
||||
F897AB1D22059EA000CDDD10 /* TransmitterMessage.swift in Sources */,
|
||||
F8025E5721F4A60900ECF0C0 /* CGMTransmitterProtocol.swift in Sources */,
|
||||
F8025E5721F4A60900ECF0C0 /* CGMTransmitter.swift in Sources */,
|
||||
F897AB3D220A243300CDDD10 /* ResetMessage.swift in Sources */,
|
||||
F85DC30121D3F5CC00B9F74A /* CGMG4xDripTransmitter.swift in Sources */,
|
||||
F8025C0A21D94FD700ECF0C0 /* CBManagerState.swift in Sources */,
|
||||
|
|
|
@ -47,27 +47,6 @@ extension Data {
|
|||
}))
|
||||
}
|
||||
|
||||
/*var hexadecimalString: String {
|
||||
return map { String(format: "%02hhx", $0) }.joined()
|
||||
}*/
|
||||
|
||||
|
||||
/*var uint8: UInt8 {
|
||||
get {
|
||||
var number: UInt8 = 0
|
||||
self.getBytes(&number, length: MemoryLayout.size(ofValue: number))
|
||||
return number
|
||||
}
|
||||
}
|
||||
|
||||
var uint16: UInt16 {
|
||||
get {
|
||||
var number: UInt16 = 0
|
||||
self.getBytes(&number, length: MemoryLayout.size(ofValue: number))
|
||||
return number
|
||||
}
|
||||
}*/
|
||||
|
||||
///takes 4 bytes starting at position and converts to Uint32
|
||||
func uint32 (position:Int)-> UInt32 {
|
||||
let start = position
|
||||
|
@ -84,6 +63,14 @@ extension Data {
|
|||
return number
|
||||
}
|
||||
|
||||
///takes 1 byte starting at position and converts to Uint8
|
||||
func uint8 (position:Int)-> UInt8 {
|
||||
let start = position
|
||||
let end = start.advanced(by: 1)
|
||||
let number: UInt8 = self.subdata(in: start..<end).toInt()
|
||||
return number
|
||||
}
|
||||
|
||||
//source Data.Swift CGMBLEKit
|
||||
func to<T: FixedWidthInteger>(_: T.Type) -> T {
|
||||
return self.withUnsafeBytes { (bytes: UnsafePointer<T>) in
|
||||
|
|
|
@ -0,0 +1,17 @@
|
|||
import Foundation
|
||||
|
||||
protocol CGMTransmitter {
|
||||
/// example MiaoMiao can detect new sensor, implementation should return true, Dexcom transmitter's can't
|
||||
func canDetectNewSensor() -> Bool
|
||||
|
||||
/// get device address, cgmtransmitters should also derive from BlueToothTransmitter, hence no need to implement this function
|
||||
func address() -> String?
|
||||
|
||||
/// get device name, cgmtransmitters should also derive from BlueToothTransmitter, hence no need to implement this function
|
||||
func name() -> String?
|
||||
|
||||
/// start scanning, cgmtransmitters should also derive from BlueToothTransmitter, hence no need to implement this function
|
||||
/// - returns:
|
||||
/// the scanning result
|
||||
func startScanning() -> BluetoothTransmitter.startScanningResult
|
||||
}
|
|
@ -1,6 +0,0 @@
|
|||
import Foundation
|
||||
|
||||
protocol CGMTransmitterProtocol {
|
||||
/// example MiaoMiao can detect new sensor, implementation should return true, Dexcom transmitter's can't
|
||||
func canDetectNewSensor() -> Bool
|
||||
}
|
|
@ -2,7 +2,7 @@ import Foundation
|
|||
import CoreBluetooth
|
||||
import os
|
||||
|
||||
final class CGMG4xDripTransmitter: BluetoothTransmitter, BluetoothTransmitterDelegate, CGMTransmitterProtocol {
|
||||
final class CGMG4xDripTransmitter: BluetoothTransmitter, BluetoothTransmitterDelegate, CGMTransmitter {
|
||||
// MARK: - properties
|
||||
|
||||
/// uuid used for scanning, can be empty string, if empty string then scan all devices - only possible if app is in foreground
|
||||
|
|
|
@ -2,7 +2,7 @@ import Foundation
|
|||
import CoreBluetooth
|
||||
import os
|
||||
|
||||
class CGMG5Transmitter:BluetoothTransmitter, BluetoothTransmitterDelegate, CGMTransmitterProtocol {
|
||||
class CGMG5Transmitter:BluetoothTransmitter, BluetoothTransmitterDelegate, CGMTransmitter {
|
||||
// MARK: - properties
|
||||
|
||||
/// UUID's
|
||||
|
@ -56,8 +56,11 @@ class CGMG5Transmitter:BluetoothTransmitter, BluetoothTransmitterDelegate, CGMTr
|
|||
/// is G5 reset necessary or not
|
||||
private var G5ResetRequested:Bool
|
||||
|
||||
// G5 transmitter firmware version
|
||||
// G5 transmitter firmware version - only used internally, if nil then it was never received
|
||||
private var transmitterVersion:String?
|
||||
|
||||
// actual device address
|
||||
private var actualDeviceAddress:String?
|
||||
|
||||
// MARK: - functions
|
||||
|
||||
|
@ -82,6 +85,7 @@ class CGMG5Transmitter:BluetoothTransmitter, BluetoothTransmitterDelegate, CGMTr
|
|||
var newAddressAndName:BluetoothTransmitter.DeviceAddressAndName = BluetoothTransmitter.DeviceAddressAndName.notYetConnected(expectedName: "DEXCOM" + transmitterID[transmitterID.index(transmitterID.startIndex, offsetBy: 4)..<transmitterID.endIndex])
|
||||
if let address = address {
|
||||
newAddressAndName = BluetoothTransmitter.DeviceAddressAndName.alreadyConnectedBefore(address: address)
|
||||
actualDeviceAddress = address
|
||||
}
|
||||
|
||||
// set timestampoflastg5reading to 0
|
||||
|
@ -119,11 +123,19 @@ class CGMG5Transmitter:BluetoothTransmitter, BluetoothTransmitterDelegate, CGMTr
|
|||
|
||||
// MARK: CBCentralManager overriden functions
|
||||
|
||||
override func centralManager(_ central: CBCentralManager, didDiscover peripheral: CBPeripheral, advertisementData: [String : Any], rssi RSSI: NSNumber) {
|
||||
if Date() < Date(timeInterval: 60, since: timeStampOfLastG5Reading) {
|
||||
// will probably never come here because reconnect doesn't happen with scanning, hence diddiscover will never be called excep the very first time that an app tries to connect to a G5
|
||||
os_log("diddiscover peripheral, but last reading was less than 1 minute ago, will ignore", log: log, type: .info)
|
||||
} else {
|
||||
super.centralManager(central, didDiscover: peripheral, advertisementData: advertisementData, rssi: RSSI)
|
||||
}
|
||||
}
|
||||
|
||||
override func centralManager(_ central: CBCentralManager, didConnect peripheral: CBPeripheral) {
|
||||
//Date(timeInterval: (5*60), since: firstCalibrationTimeStamp)
|
||||
if Date() < Date(timeInterval: 60, since: timeStampOfLastG5Reading) {
|
||||
os_log("connected, but last reading was less than 1 minute ago, disconnecting", log: log, type: .info)
|
||||
//TODO : isn't it better to just do nothing ? wait for dexcom to timeout ?
|
||||
//TODO: is it not better to keep connection open till it times out ? should be tested with new device, see if battery drains, if it does, try with removing the disconnect - Spike also disconnects
|
||||
disconnect()
|
||||
} else {
|
||||
super.centralManager(central, didConnect: peripheral)
|
||||
|
@ -135,7 +147,7 @@ class CGMG5Transmitter:BluetoothTransmitter, BluetoothTransmitterDelegate, CGMTr
|
|||
|
||||
// log error if any
|
||||
if let error = error {
|
||||
os_log("error: %{public}@", log: log, type: .error , error.localizedDescription)
|
||||
os_log(" error: %{public}@", log: log, type: .error , error.localizedDescription)
|
||||
}
|
||||
|
||||
if let characteristics = service.characteristics {
|
||||
|
@ -152,11 +164,11 @@ class CGMG5Transmitter:BluetoothTransmitter, BluetoothTransmitterDelegate, CGMTr
|
|||
communicationCharacteristic = characteristic
|
||||
case .CBUUID_Receive_Authentication:
|
||||
receiveAuthenticationCharacteristic = characteristic
|
||||
os_log("calling setNotifyValue true", log: log, type: .info)
|
||||
os_log(" calling setNotifyValue true", log: log, type: .info)
|
||||
peripheral.setNotifyValue(true, for: characteristic)
|
||||
}
|
||||
} else {
|
||||
os_log("characteristic UUID unknown", log: log, type: .error)
|
||||
os_log(" characteristic UUID unknown", log: log, type: .error)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
@ -177,7 +189,7 @@ class CGMG5Transmitter:BluetoothTransmitter, BluetoothTransmitterDelegate, CGMTr
|
|||
// if status changed to poweredon, and if address = nil then superclass will not start the scanning
|
||||
// but for DexcomG5 we can start scanning
|
||||
if state == .poweredOn {
|
||||
if (address == nil) {
|
||||
if (actualDeviceAddress == nil) {
|
||||
_ = startScanning()
|
||||
}
|
||||
}
|
||||
|
@ -192,10 +204,10 @@ class CGMG5Transmitter:BluetoothTransmitter, BluetoothTransmitterDelegate, CGMTr
|
|||
func peripheralDidUpdateNotificationStateFor(characteristic: CBCharacteristic, error: Error?) {
|
||||
os_log("in peripheralDidUpdateNotificationStateFor", log: log, type: .info)
|
||||
if let error = error {
|
||||
os_log("error: %{public}@", log: log, type: .error , error.localizedDescription)
|
||||
os_log(" error: %{public}@", log: log, type: .error , error.localizedDescription)
|
||||
}
|
||||
let ASCIIstring = characteristic.uuid.uuidString
|
||||
os_log("characteristic uuid: %{public}@", log: log, type: .info, ASCIIstring)
|
||||
os_log(" characteristic uuid: %{public}@", log: log, type: .info, ASCIIstring)
|
||||
if let characteristicValue = CBUUID_Characteristic_UUID(rawValue: ASCIIstring) {
|
||||
switch characteristicValue {
|
||||
case .CBUUID_Write_Control:
|
||||
|
@ -213,7 +225,7 @@ class CGMG5Transmitter:BluetoothTransmitter, BluetoothTransmitterDelegate, CGMTr
|
|||
break
|
||||
}
|
||||
} else {
|
||||
os_log("characteristicValue is nil", log: log, type: .error)
|
||||
os_log(" characteristicValue is nil", log: log, type: .error)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -226,45 +238,50 @@ class CGMG5Transmitter:BluetoothTransmitter, BluetoothTransmitterDelegate, CGMTr
|
|||
if let value = characteristic.value {
|
||||
//only for logging
|
||||
let data = value.hexEncodedString()
|
||||
os_log(" data = %{public}@", log: log, type: .debug, data)
|
||||
os_log(" data = %{public}@", log: log, type: .debug, data)
|
||||
|
||||
//check type of message and process according to type
|
||||
if let firstByte = value.first {
|
||||
if let opCode = Opcode(rawValue: firstByte) {
|
||||
os_log("opcode = %{public}@", log: log, type: .info, opCode.description)
|
||||
os_log(" opcode = %{public}@", log: log, type: .info, opCode.description)
|
||||
switch opCode {
|
||||
case .authChallengeRx:
|
||||
if let authChallengeRxMessage = AuthChallengeRxMessage(data: value) {
|
||||
if !authChallengeRxMessage.bonded {
|
||||
cgmTransmitterDelegate?.cgmTransmitterNeedsPairing()
|
||||
os_log("transmitter needs paring", log: log, type: .info)
|
||||
os_log(" transmitter needs paring", log: log, type: .info)
|
||||
} else {
|
||||
if let writeControlCharacteristic = writeControlCharacteristic {
|
||||
setNotifyValue(true, for: writeControlCharacteristic)
|
||||
} else {
|
||||
os_log(" writeControlCharacteristic is nil, can not set notifyValue", log: log, type: .error)
|
||||
}
|
||||
}
|
||||
}
|
||||
if let writeControlCharacteristic = writeControlCharacteristic {
|
||||
setNotifyValue(true, for: writeControlCharacteristic)
|
||||
} else {
|
||||
os_log("writeControlCharacteristic is nil, can not set notifyValue", log: log, type: .error)
|
||||
os_log(" failed to create authChallengeRxMessage", log: log, type: .info)
|
||||
}
|
||||
case .authRequestRx:
|
||||
if let authRequestRxMessage = AuthRequestRxMessage(data: value), let receiveAuthenticationCharacteristic = receiveAuthenticationCharacteristic {
|
||||
guard let challengeHash = CGMG5Transmitter.computeHash(transmitterId, of: authRequestRxMessage.challenge) else {
|
||||
os_log("failed to calculate challengeHash, no further processing", log: log, type: .error)
|
||||
os_log(" failed to calculate challengeHash, no further processing", log: log, type: .error)
|
||||
return
|
||||
}
|
||||
let authChallengeTxMessage = AuthChallengeTxMessage(challengeHash: challengeHash)
|
||||
_ = writeDataToPeripheral(data: authChallengeTxMessage.data, characteristicToWriteTo: receiveAuthenticationCharacteristic, type: .withResponse)
|
||||
} else {
|
||||
os_log("writeControlCharacteristic is nil or authRequestRxMessage is nil", log: log, type: .error)
|
||||
os_log(" writeControlCharacteristic is nil or authRequestRxMessage is nil", log: log, type: .error)
|
||||
}
|
||||
case .sensorDataRx:
|
||||
if let sensorDataRxMessage = SensorDataRxMessage(data: value) {
|
||||
if transmitterVersion != nil {
|
||||
if Date() < Date(timeInterval: Constants.DexcomG5.batteryReadPeriodInHours * 60 * 60, since: timeStampOfLastBatteryReading) {
|
||||
os_log("last battery reading was long time, ago requesting now", log: log, type: .info)
|
||||
// transmitterversion was already recceived, let's see if we need to get the batterystatus
|
||||
if Date() > Date(timeInterval: Constants.DexcomG5.batteryReadPeriodInHours * 60 * 60, since: timeStampOfLastBatteryReading) {
|
||||
os_log(" last battery reading was long time, ago requesting now", log: log, type: .info)
|
||||
if let writeControlCharacteristic = writeControlCharacteristic {
|
||||
_ = writeDataToPeripheral(data: BatteryStatusTxMessage().data, characteristicToWriteTo: writeControlCharacteristic, type: .withResponse)
|
||||
timeStampOfLastBatteryReading = Date()
|
||||
} else {
|
||||
os_log("writeControlCharacteristic is nil, can not send BatteryStatusTxMessage", log: log, type: .error)
|
||||
os_log(" writeControlCharacteristic is nil, can not send BatteryStatusTxMessage", log: log, type: .error)
|
||||
}
|
||||
//TODO: strictly speaking a disconnect should be done after having written the data
|
||||
} else {
|
||||
|
@ -274,16 +291,16 @@ class CGMG5Transmitter:BluetoothTransmitter, BluetoothTransmitterDelegate, CGMTr
|
|||
if let writeControlCharacteristic = writeControlCharacteristic {
|
||||
_ = writeDataToPeripheral(data: TransmitterVersionTxMessage().data, characteristicToWriteTo: writeControlCharacteristic, type: .withResponse)
|
||||
} else {
|
||||
os_log("writeControlCharacteristic is nil, can not send TransmitterVersionTxMessage", log: log, type: .error)
|
||||
os_log(" writeControlCharacteristic is nil, can not send TransmitterVersionTxMessage", log: log, type: .error)
|
||||
}
|
||||
//TODO: strictly speaking a disconnect should be done after having written the data
|
||||
}
|
||||
//if reset was done recently, less than 5 minutes ago, then ignore the reading
|
||||
if Date() < Date(timeInterval: 5 * 60, since: timeStampTransmitterReset) {
|
||||
os_log("last transmitterreset was less than 5 minutes ago, ignoring this reading", log: log, type: .info)
|
||||
os_log(" last transmitterreset was less than 5 minutes ago, ignoring this reading", log: log, type: .info)
|
||||
} else {
|
||||
if Date() < Date(timeInterval: 60, since: timeStampOfLastG5Reading) {
|
||||
os_log("last reading was less than 1 minute ago, disconnecting", log: log, type: .info)
|
||||
os_log(" last reading was less than 1 minute ago, disconnecting", log: log, type: .info)
|
||||
} else {
|
||||
timeStampOfLastG5Reading = Date()
|
||||
let glucoseData = RawGlucoseData(timeStamp: sensorDataRxMessage.timestamp, glucoseLevelRaw: sensorDataRxMessage.unfiltered, glucoseLevelFiltered: sensorDataRxMessage.filtered)
|
||||
|
@ -294,7 +311,7 @@ class CGMG5Transmitter:BluetoothTransmitter, BluetoothTransmitterDelegate, CGMTr
|
|||
//start processing now the sensorDataRxMessage
|
||||
|
||||
} else {
|
||||
os_log("sensorDataRxMessagee is nil", log: log, type: .error)
|
||||
os_log(" sensorDataRxMessagee is nil", log: log, type: .error)
|
||||
}
|
||||
case .resetRx:
|
||||
processResetRxMessage(value: value)
|
||||
|
@ -303,14 +320,14 @@ class CGMG5Transmitter:BluetoothTransmitter, BluetoothTransmitterDelegate, CGMTr
|
|||
case .transmitterVersionRx:
|
||||
processTransmitterVersionRxMessage(value: value)
|
||||
default:
|
||||
os_log("unknown opcode received ", log: log, type: .error)
|
||||
os_log(" unknown opcode received ", log: log, type: .error)
|
||||
break
|
||||
}
|
||||
} else {
|
||||
os_log("value doesn't start with a known opcode = %{public}d", log: log, type: .error, firstByte)
|
||||
os_log(" value doesn't start with a known opcode = %{public}d", log: log, type: .error, firstByte)
|
||||
}
|
||||
} else {
|
||||
os_log("characteristic.value is nil", log: log, type: .error)
|
||||
os_log(" characteristic.value is nil", log: log, type: .error)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -329,7 +346,7 @@ class CGMG5Transmitter:BluetoothTransmitter, BluetoothTransmitterDelegate, CGMTr
|
|||
if let writeControlCharacteristic = writeControlCharacteristic {
|
||||
_ = writeDataToPeripheral(data: SensorDataTxMessage().data, characteristicToWriteTo: writeControlCharacteristic, type: .withResponse)
|
||||
} else {
|
||||
os_log("writeControlCharacteristic is nil, not getsensordata", log: log, type: .error)
|
||||
os_log(" writeControlCharacteristic is nil, not getsensordata", log: log, type: .error)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -340,7 +357,7 @@ class CGMG5Transmitter:BluetoothTransmitter, BluetoothTransmitterDelegate, CGMTr
|
|||
_ = writeDataToPeripheral(data: ResetTxMessage().data, characteristicToWriteTo: writeControlCharacteristic, type: .withResponse)
|
||||
G5ResetRequested = false
|
||||
} else {
|
||||
os_log("writeControlCharacteristic is nil, not sending G5 reset", log: log, type: .error)
|
||||
os_log(" writeControlCharacteristic is nil, not sending G5 reset", log: log, type: .error)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -367,7 +384,7 @@ class CGMG5Transmitter:BluetoothTransmitter, BluetoothTransmitterDelegate, CGMTr
|
|||
private func processBatteryStatusRxMessage(value:Data) {
|
||||
if let batteryStatusRxMessage = BatteryStatusRxMessage(data: value) {
|
||||
var emptyArray: [RawGlucoseData] = []
|
||||
cgmTransmitterDelegate?.cgmTransmitterInfoReceived(glucoseData: &emptyArray, transmitterBatteryInfo: TransmitterBatteryInfo.DexcomG5(voltageA: batteryStatusRxMessage.voltageA, voltageB: batteryStatusRxMessage.voltageB, resist: batteryStatusRxMessage.resist), sensorState: nil, sensorTimeInMinutes: nil, firmware: nil, hardware: nil)
|
||||
cgmTransmitterDelegate?.cgmTransmitterInfoReceived(glucoseData: &emptyArray, transmitterBatteryInfo: TransmitterBatteryInfo.DexcomG5(voltageA: batteryStatusRxMessage.voltageA, voltageB: batteryStatusRxMessage.voltageB, resist: batteryStatusRxMessage.resist, runtime: batteryStatusRxMessage.runtime, temperature: batteryStatusRxMessage.temperature), sensorState: nil, sensorTimeInMinutes: nil, firmware: nil, hardware: nil)
|
||||
} else {
|
||||
os_log("batteryStatusRxMessage is nil", log: log, type: .error)
|
||||
}
|
||||
|
@ -377,6 +394,8 @@ class CGMG5Transmitter:BluetoothTransmitter, BluetoothTransmitterDelegate, CGMTr
|
|||
if let transmitterVersionRxMessage = TransmitterVersionRxMessage(data: value) {
|
||||
var emptyArray: [RawGlucoseData] = []
|
||||
cgmTransmitterDelegate?.cgmTransmitterInfoReceived(glucoseData: &emptyArray, transmitterBatteryInfo: nil, sensorState: nil, sensorTimeInMinutes: nil, firmware: transmitterVersionRxMessage.firmwareVersion.hexEncodedString(), hardware: nil)
|
||||
// assign transmitterVersion
|
||||
transmitterVersion = transmitterVersionRxMessage.firmwareVersion.hexEncodedString()
|
||||
} else {
|
||||
os_log("transmitterVersionRxMessage is nil", log: log, type: .error)
|
||||
}
|
||||
|
|
|
@ -6,6 +6,8 @@ struct BatteryStatusRxMessage: TransmitterRxMessage {
|
|||
let voltageA: Int
|
||||
let voltageB: Int
|
||||
let resist: Int
|
||||
let runtime: Int
|
||||
let temperature:Int
|
||||
|
||||
init?(data: Data) {
|
||||
guard data.count >= 12 && data.isCRCValid else {
|
||||
|
@ -17,9 +19,11 @@ struct BatteryStatusRxMessage: TransmitterRxMessage {
|
|||
}
|
||||
|
||||
status = data[1]
|
||||
voltageA = data[2..<4].toInt()
|
||||
voltageB = data[4..<6].toInt()
|
||||
resist = data[6..<8].toInt()
|
||||
voltageA = Int(data.uint16(position: 2))
|
||||
voltageB = Int(data.uint16(position: 4))
|
||||
resist = Int(data.uint16(position: 6))
|
||||
runtime = Int(data.uint16(position: 8))
|
||||
temperature = Int(data.uint8(position: 10))
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -2,7 +2,7 @@ import Foundation
|
|||
import CoreBluetooth
|
||||
import os
|
||||
|
||||
class CGMMiaoMiaoTransmitter:BluetoothTransmitter, BluetoothTransmitterDelegate, CGMTransmitterProtocol {
|
||||
class CGMMiaoMiaoTransmitter:BluetoothTransmitter, BluetoothTransmitterDelegate, CGMTransmitter {
|
||||
// MARK: - properties
|
||||
|
||||
/// service to be discovered
|
||||
|
|
|
@ -5,7 +5,7 @@ enum TransmitterBatteryInfo {
|
|||
case percentage (percentage:Int)
|
||||
|
||||
/// Dexcom G5 (and also G6 ?) voltageA, voltageB and resist
|
||||
case DexcomG5 (voltageA:Int, voltageB:Int, resist:Int)
|
||||
case DexcomG5 (voltageA:Int, voltageB:Int, resist:Int, runtime:Int, temperature:Int)
|
||||
|
||||
/// Dexcom G4, batteryinfo (215 or something like that)
|
||||
case DexcomG4 (level:Int)
|
||||
|
@ -14,8 +14,8 @@ enum TransmitterBatteryInfo {
|
|||
switch (self) {
|
||||
case .DexcomG4(let level):
|
||||
return "Battery Level = " + level.description
|
||||
case .DexcomG5(let voltA, let voltB, let res):
|
||||
return "VoltageA = " + voltA.description + " Voltage B = " + voltB.description + " resistance = " + res.description
|
||||
case .DexcomG5(let voltA, let voltB, let res, let runt, let temp):
|
||||
return "VoltageA = " + voltA.description + ", Voltage B = " + voltB.description + ", resistance = " + res.description + ", runtime = " + runt.description + ", temperature = " + temp.description
|
||||
case .percentage(let perc):
|
||||
return "Battery Percentage = " + perc.description
|
||||
}
|
||||
|
|
|
@ -12,9 +12,9 @@ class BluetoothTransmitter: NSObject, CBCentralManagerDelegate, CBPeripheralDele
|
|||
public weak var bluetoothTransmitterDelegate:BluetoothTransmitterDelegate?
|
||||
|
||||
/// the address of the transmitter. If nil then transmitter never connected, so we don't know the name.
|
||||
public private(set) var address:String?
|
||||
private var deviceAddress:String?
|
||||
/// the name of the transmitter. If nil then transmitter never connected, so we don't know the name
|
||||
public private(set) var name:String?
|
||||
private var deviceName:String?
|
||||
|
||||
/// uuid used for scanning, can be empty string, if empty string then scan all devices - only possible if app is in foreground
|
||||
private let CBUUID_Advertisement:String?
|
||||
|
@ -58,7 +58,7 @@ class BluetoothTransmitter: NSObject, CBCentralManagerDelegate, CBPeripheralDele
|
|||
init(addressAndName:BluetoothTransmitter.DeviceAddressAndName, CBUUID_Advertisement:String?, CBUUID_Service:String, CBUUID_ReceiveCharacteristic:String, CBUUID_WriteCharacteristic:String) {
|
||||
switch addressAndName {
|
||||
case .alreadyConnectedBefore(let newAddress):
|
||||
address = newAddress
|
||||
deviceAddress = newAddress
|
||||
case .notYetConnected(let newexpectedName):
|
||||
expectedName = newexpectedName
|
||||
}
|
||||
|
@ -177,8 +177,8 @@ class BluetoothTransmitter: NSObject, CBCentralManagerDelegate, CBPeripheralDele
|
|||
fileprivate func stopScanAndconnect(to peripheral: CBPeripheral) {
|
||||
|
||||
self.centralManager?.stopScan()
|
||||
self.address = peripheral.identifier.uuidString
|
||||
self.name = peripheral.name
|
||||
self.deviceAddress = peripheral.identifier.uuidString
|
||||
self.deviceName = peripheral.name
|
||||
peripheral.delegate = self
|
||||
self.peripheral = peripheral
|
||||
|
||||
|
@ -196,8 +196,8 @@ class BluetoothTransmitter: NSObject, CBCentralManagerDelegate, CBPeripheralDele
|
|||
}
|
||||
|
||||
fileprivate func retrievePeripherals(_ central:CBCentralManager) -> Bool {
|
||||
if let address = address {
|
||||
if let uuid = UUID(uuidString: address) {
|
||||
if let deviceAddress = deviceAddress {
|
||||
if let uuid = UUID(uuidString: deviceAddress) {
|
||||
var peripheralArr = central.retrievePeripherals(withIdentifiers: [uuid])
|
||||
if peripheralArr.count > 0 {
|
||||
peripheral = peripheralArr[0]
|
||||
|
@ -225,8 +225,8 @@ class BluetoothTransmitter: NSObject, CBCentralManagerDelegate, CBPeripheralDele
|
|||
os_log("Did discover peripheral with name: %{public}@", log: log, type: .info, String(describing: deviceName))
|
||||
|
||||
// check if stored address not nil, in which case we already connected before and we expect a full match with the already known device name
|
||||
if let address = address {
|
||||
if peripheral.identifier.uuidString == address {
|
||||
if let deviceAddress = deviceAddress {
|
||||
if peripheral.identifier.uuidString == deviceAddress {
|
||||
os_log("stored address matches peripheral address, will try to connect", log: log, type: .info)
|
||||
stopScanAndconnect(to: peripheral)
|
||||
}
|
||||
|
@ -370,6 +370,15 @@ class BluetoothTransmitter: NSObject, CBCentralManagerDelegate, CBPeripheralDele
|
|||
}
|
||||
}
|
||||
|
||||
// MARK: methods to get address and name
|
||||
func address() -> String? {
|
||||
return deviceAddress
|
||||
}
|
||||
|
||||
func name() -> String? {
|
||||
return deviceName
|
||||
}
|
||||
|
||||
// MARK: - helpers
|
||||
|
||||
private func initialize() {
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
<li><a href="#peripheraldidupdatenotificationstatefor">peripheralDidUpdateNotificationStateFor</a></li>
|
||||
<li><a href="#peripheraldidupatevaluefor">peripheralDidUpdateValueFor</a></li>
|
||||
</ul></li>
|
||||
<li><a href="#protocolCGMTransmitterProtocol">conform to protocol CGMTransmitterProtocol</a>
|
||||
<li><a href="#protocolCGMTransmitter">conform to protocol CGMTransmitter</a>
|
||||
<ul>
|
||||
<li><a href="#canDetectNewSensorprotocol">canDetectNewSensor</a></li>
|
||||
</ul></li>
|
||||
|
@ -40,6 +40,7 @@
|
|||
<li><a href="#newSensorDetected">newSensorDetected</a></li>
|
||||
<li><a href="#sensorNotDetected">sensorNotDetected</a></li>
|
||||
<li><a href="#newReadingsReceived">newReadingsReceived</a></li>
|
||||
<li><a href="#transmitterNeedsPairing">transmitterNeedsPairing</a></li>
|
||||
</ul></li>
|
||||
</ul></li>
|
||||
<li><a href="#functionsandpropertiesavailableintransmitterclasses">Functions and properties available in transmitter classes</a>
|
||||
|
@ -84,7 +85,7 @@ BluetoothTransmitter class to a specific transmitter class. Example when a disco
|
|||
handles the reconnect but the delegate class can for instance show the connection status to the user. It will be informed about
|
||||
the connection status via the function centralManagerDidConnect in the BluetoothTransmitterDelegate</p>
|
||||
|
||||
<p><strong>CGMTransmitterProtocol</strong> defines functions that CGM transmitter classes need to implement.</p>
|
||||
<p><strong>CGMTransmitter</strong> defines functions that CGM transmitter classes need to implement.</p>
|
||||
|
||||
<p>The CGM transmitter communicates back to the caller via the <strong>CGMTransmitterDelegate</strong> protocol.<br>
|
||||
Needs to be conformed to, for instance by a view controller, or manager, .. whatever<br>
|
||||
|
@ -106,7 +107,7 @@ This protocol allows passing information like new readings, sensor detected, and
|
|||
<p>If it's a CGM transmitter (it could also be a bloodglucose meter that transmits data over bluetooth)</p>
|
||||
|
||||
<ul>
|
||||
<li>conform to the protocol CGMTransmitterProtocol</li>
|
||||
<li>conform to the protocol CGMTransmitter</li>
|
||||
</ul>
|
||||
|
||||
<h2><a name="protocolbluetoothtransmitterdelegate"></a>conform to protocol BluetoothTransmitterDelegate</h2>
|
||||
|
@ -145,7 +146,7 @@ For other types of transmitters there may be nothing to do.<br></p>
|
|||
|
||||
<p>This will be the most important function, because it contains the data that needs to be processed by the specific transmitter class.</p>
|
||||
|
||||
<h2><a name="protocolCGMTransmitterProtocol"></a>conform to protocol CGMTransmitterProtocol</h2>
|
||||
<h2><a name="protocolCGMTransmitter"></a>conform to protocol CGMTransmitter</h2>
|
||||
|
||||
<h3><a name="canDetectNewSensorprotocol"></a>canDetectNewSensor</h3>
|
||||
|
||||
|
@ -237,6 +238,10 @@ This will typically be called in centralManagerDidUpdateState</p>
|
|||
|
||||
<p>This is the most important function, it passes new readings to the delegate</p>
|
||||
|
||||
<h3><a name="transmitterNeedsPairing"></a>transmitterNeedsPairing</h3>
|
||||
|
||||
<p>The transmitter needs pairing, app should give warning to user to keep the app in the foreground</p>
|
||||
|
||||
<h1><a name="functionsandpropertiesavailableintransmitterclasses"></a>Functions and properties available in transmitter classes</h1>
|
||||
|
||||
<h2><a name="functionsinbluetoothtransmitterclasses"></a>Functions in BluetoothTransmitter classes</h2>
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
- [centralManagerDidUpdateState](#centralManagerDidUpdateState)
|
||||
- [peripheralDidUpdateNotificationStateFor](#peripheraldidupdatenotificationstatefor)
|
||||
- [peripheralDidUpdateValueFor](#peripheraldidupatevaluefor)
|
||||
- [conform to protocol CGMTransmitterProtocol](#protocolCGMTransmitterProtocol)
|
||||
- [conform to protocol CGMTransmitter](#protocolCGMTransmitter)
|
||||
- [canDetectNewSensor](#canDetectNewSensorprotocol)
|
||||
- [extend class BluetoothTransmitter](#extendclassbuetoothtransmitter)
|
||||
- [initialize the super class BluetoothTransmitter](#initializebluetoothtransmitter)
|
||||
|
@ -62,7 +62,7 @@ BluetoothTransmitter class to a specific transmitter class. Example when a disco
|
|||
handles the reconnect but the delegate class can for instance show the connection status to the user. It will be informed about
|
||||
the connection status via the function centralManagerDidConnect in the BluetoothTransmitterDelegate
|
||||
|
||||
**CGMTransmitterProtocol** defines functions that CGM transmitter classes need to implement.
|
||||
**CGMTransmitter** defines functions that CGM transmitter classes need to implement.
|
||||
|
||||
The CGM transmitter communicates back to the caller via the **CGMTransmitterDelegate** protocol.<br>
|
||||
Needs to be conformed to, for instance by a view controller, or manager, .. whatever<br>
|
||||
|
@ -81,7 +81,7 @@ Every new type of bluetoothtransmitter needs to
|
|||
|
||||
If it's a CGM transmitter (it could also be a bloodglucose meter that transmits data over bluetooth)
|
||||
|
||||
* conform to the protocol CGMTransmitterProtocol
|
||||
* conform to the protocol CGMTransmitter
|
||||
|
||||
## <a name="protocolbluetoothtransmitterdelegate"></a>conform to protocol BluetoothTransmitterDelegate
|
||||
|
||||
|
@ -119,7 +119,7 @@ For other types of transmitters there may be nothing to do.<br>
|
|||
|
||||
This will be the most important function, because it contains the data that needs to be processed by the specific transmitter class.
|
||||
|
||||
## <a name="protocolCGMTransmitterProtocol"></a>conform to protocol CGMTransmitterProtocol
|
||||
## <a name="protocolCGMTransmitter"></a>conform to protocol CGMTransmitter
|
||||
|
||||
### <a name="canDetectNewSensorprotocol"></a>canDetectNewSensor
|
||||
|
||||
|
|
|
@ -6,7 +6,7 @@ import UserNotifications
|
|||
|
||||
final class RootHomeViewController: UIViewController, CGMTransmitterDelegate {
|
||||
// MARK: - Properties
|
||||
var test:CGMG5Transmitter?//TODO: should be possible to define as cgmtransmitterprotocol ? that protocol should support a few more functions
|
||||
var test:CGMTransmitter?
|
||||
|
||||
var address:String?
|
||||
var name:String?
|
||||
|
@ -75,13 +75,6 @@ final class RootHomeViewController: UIViewController, CGMTransmitterDelegate {
|
|||
|
||||
}
|
||||
|
||||
// called when transmitter considered to be connected
|
||||
func cgmTransmitterdidConnect() {
|
||||
address = test?.address
|
||||
name = test?.name
|
||||
os_log("didconnect to device with address %{public}@ and name %{public}@", log: log!, type: .info, address!,name!)
|
||||
}
|
||||
|
||||
// Only MioaMiao will call this
|
||||
func newSensorDetected() {
|
||||
os_log("new sensor detected", log: log!, type: .info)
|
||||
|
@ -98,7 +91,7 @@ final class RootHomeViewController: UIViewController, CGMTransmitterDelegate {
|
|||
os_log("sensorstate %{public}@", log: log!, type: .debug, sensorState?.description ?? "no sensor state found")
|
||||
os_log("firmware %{public}@", log: log!, type: .debug, firmware ?? "no firmware version found")
|
||||
os_log("hardware %{public}@", log: log!, type: .debug, hardware ?? "no hardware version found")
|
||||
os_log("transmitterBatteryInfo %{public}d", log: log!, type: .debug, transmitterBatteryInfo?.description ?? 0)
|
||||
os_log("transmitterBatteryInfo %{public}@", log: log!, type: .debug, transmitterBatteryInfo?.description ?? 0)
|
||||
os_log("sensor time in minutes %{public}d", log: log!, type: .debug, sensorTimeInMinutes ?? 0)
|
||||
for (index, reading) in glucoseData.enumerated() {
|
||||
os_log("Reading %{public}d, raw level = %{public}f, realDate = %{public}s", log: log!, type: .debug, index, reading.glucoseLevelRaw, reading.timeStamp.description)
|
||||
|
@ -362,10 +355,10 @@ extension RootHomeViewController: UNUserNotificationCenterDelegate {
|
|||
}
|
||||
}
|
||||
|
||||
// MARK: - CGMTransmitterDelegate functions
|
||||
// MARK: - CGMTransmitter protocol functions
|
||||
|
||||
func cgmTransmitterDidConnect() {
|
||||
if let address = test?.address, let name = test?.name {
|
||||
if let address = test?.address(), let name = test?.name() {
|
||||
self.address = address
|
||||
self.name = name
|
||||
UserDefaults.standard.bluetoothDeviceAddress = address
|
||||
|
|
Loading…
Reference in New Issue