Blucon : up to pairing done
This commit is contained in:
parent
b320789a5b
commit
40c12b25ea
|
@ -87,6 +87,7 @@
|
|||
F8A54AFF22D9179100934E7A /* CRC.swift in Sources */ = {isa = PBXBuildFile; fileRef = F8A54AFC22D9179100934E7A /* CRC.swift */; };
|
||||
F8A54B0022D9179100934E7A /* ParseLibreData.swift in Sources */ = {isa = PBXBuildFile; fileRef = F8A54AFD22D9179100934E7A /* ParseLibreData.swift */; };
|
||||
F8A54B0122D9179100934E7A /* SensorState.swift in Sources */ = {isa = PBXBuildFile; fileRef = F8A54AFE22D9179100934E7A /* SensorState.swift */; };
|
||||
F8A7406E22D9C0E700967CFC /* CGMBluconTransmitter.swift in Sources */ = {isa = PBXBuildFile; fileRef = F8A7406D22D9C0E700967CFC /* CGMBluconTransmitter.swift */; };
|
||||
F8AC425E21ADEBD60078C348 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = F8AC425D21ADEBD60078C348 /* AppDelegate.swift */; };
|
||||
F8AC426021ADEBD60078C348 /* RootViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = F8AC425F21ADEBD60078C348 /* RootViewController.swift */; };
|
||||
F8AC426521ADEBD60078C348 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = F8AC426321ADEBD60078C348 /* Main.storyboard */; };
|
||||
|
@ -252,6 +253,7 @@
|
|||
F8A54AFD22D9179100934E7A /* ParseLibreData.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ParseLibreData.swift; sourceTree = "<group>"; };
|
||||
F8A54AFE22D9179100934E7A /* SensorState.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SensorState.swift; sourceTree = "<group>"; };
|
||||
F8A54B0A22D9215500934E7A /* xdrip-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "xdrip-Bridging-Header.h"; sourceTree = "<group>"; };
|
||||
F8A7406D22D9C0E700967CFC /* CGMBluconTransmitter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CGMBluconTransmitter.swift; sourceTree = "<group>"; };
|
||||
F8AC425A21ADEBD60078C348 /* xdrip.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = xdrip.app; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
F8AC425D21ADEBD60078C348 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
|
||||
F8AC425F21ADEBD60078C348 /* RootViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RootViewController.swift; sourceTree = "<group>"; };
|
||||
|
@ -798,6 +800,7 @@
|
|||
F8A54AF522D9156600934E7A /* Blucon */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
F8A7406D22D9C0E700967CFC /* CGMBluconTransmitter.swift */,
|
||||
);
|
||||
path = Blucon;
|
||||
sourceTree = "<group>";
|
||||
|
@ -1278,6 +1281,7 @@
|
|||
F8A54ADB22D911BA00934E7A /* AuthRequestTxMessage.swift in Sources */,
|
||||
F8EA6CA921BBE3010082976B /* UniqueId.swift in Sources */,
|
||||
F81D6D4822BD5F62005EFAE2 /* DexcomShareUploadManager.swift in Sources */,
|
||||
F8A7406E22D9C0E700967CFC /* CGMBluconTransmitter.swift in Sources */,
|
||||
F8B3A7B2226A0878004BA588 /* TextsAlerts.swift in Sources */,
|
||||
F8A54B0022D9179100934E7A /* ParseLibreData.swift in Sources */,
|
||||
F8025E5421EE8D2100ECF0C0 /* Libre1Calibrator.swift in Sources */,
|
||||
|
|
|
@ -39,6 +39,7 @@ struct Constants {
|
|||
static let defaultBatteryAlertLevelDexcomG4 = 210
|
||||
static let defaultBatteryAlertLevelMiaoMiao = 20
|
||||
static let defaultBatteryAlertLevelGNSEntry = 20
|
||||
static let defaultBatteryAlertLevelBlucon = 20
|
||||
|
||||
// blood glucose level alert values in mgdl
|
||||
static let veryHigh = 250
|
||||
|
@ -82,6 +83,8 @@ struct Constants {
|
|||
static let categoryCGMG5 = "categoryCGMG5"
|
||||
/// GNSEntry
|
||||
static let categoryCGMGNSEntry = "categoryCGMGNSEntry"
|
||||
/// Blucon
|
||||
static let categoryBlucon = "categoryBlucon"
|
||||
/// core data manager
|
||||
static let categoryCoreDataManager = "categoryCoreDataManager"
|
||||
/// application data bgreadings
|
||||
|
@ -379,4 +382,11 @@ struct Constants {
|
|||
|
||||
}
|
||||
|
||||
/// constants related to Bluetooth pairing
|
||||
enum BluetoothPairing {
|
||||
|
||||
/// minimum time in seconds between two pairing notifications
|
||||
static let minimumTimeBetweenTwoPairingNotificationsInSeconds = 30
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -61,6 +61,9 @@ enum CGMTransmitterType:String, CaseIterable {
|
|||
/// GNSentry
|
||||
case GNSentry = "GNSentry"
|
||||
|
||||
/// Blucon
|
||||
case Blucon = "Blucon"
|
||||
|
||||
/// does the transmitter need a transmitter id ?
|
||||
///
|
||||
/// can be used in UI stuff, if reset not possible then there's no need to show that option in the settings UI
|
||||
|
@ -79,6 +82,8 @@ enum CGMTransmitterType:String, CaseIterable {
|
|||
case .GNSentry:
|
||||
return false
|
||||
|
||||
case .Blucon:
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -101,6 +106,8 @@ enum CGMTransmitterType:String, CaseIterable {
|
|||
case .GNSentry:
|
||||
return false
|
||||
|
||||
case .Blucon:
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -133,6 +140,9 @@ enum CGMTransmitterType:String, CaseIterable {
|
|||
case .miaomiao, .GNSentry:
|
||||
return nil
|
||||
|
||||
case .Blucon:
|
||||
// todo: validate transmitter id for blucon
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -152,6 +162,9 @@ enum CGMTransmitterType:String, CaseIterable {
|
|||
case .GNSentry:
|
||||
return Constants.DefaultAlertLevels.defaultBatteryAlertLevelGNSEntry
|
||||
|
||||
case .Blucon:
|
||||
return Constants.DefaultAlertLevels.defaultBatteryAlertLevelBlucon
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -173,6 +186,8 @@ enum CGMTransmitterType:String, CaseIterable {
|
|||
case .GNSentry:
|
||||
return false
|
||||
|
||||
case .Blucon:
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -194,6 +209,8 @@ enum CGMTransmitterType:String, CaseIterable {
|
|||
case .GNSentry:
|
||||
return ""
|
||||
|
||||
case .Blucon:
|
||||
return "%"
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -215,6 +232,8 @@ enum CGMTransmitterType:String, CaseIterable {
|
|||
case .GNSentry:
|
||||
return false
|
||||
|
||||
case .Blucon:
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,9 +1,167 @@
|
|||
//
|
||||
// CGMBluconTransmitter.swift
|
||||
// xdrip
|
||||
//
|
||||
// Created by Johan Degraeve on 13/07/2019.
|
||||
// Copyright © 2019 Johan Degraeve. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import CoreBluetooth
|
||||
import os
|
||||
|
||||
class CGMBluconTransmitter: BluetoothTransmitter {
|
||||
|
||||
// MARK: - properties
|
||||
|
||||
/// will be used to pass back bluetooth and cgm related events
|
||||
private(set) weak var cgmTransmitterDelegate:CGMTransmitterDelegate?
|
||||
|
||||
/// Blucon Service
|
||||
let CBUUID_BluconService = "436A62C0-082E-4CE8-A08B-01D81F195B24"
|
||||
|
||||
/// receive characteristic
|
||||
let CBUUID_ReceiveCharacteristic_Blucon: String = "436A0C82-082E-4CE8-A08B-01D81F195B24"
|
||||
|
||||
/// write characteristic
|
||||
let CBUUID_WriteCharacteristic_Blucon: String = "436AA6E9-082E-4CE8-A08B-01D81F195B24"
|
||||
|
||||
/// for OS_log
|
||||
private let log = OSLog(subsystem: Constants.Log.subSystem, category: Constants.Log.categoryBlucon)
|
||||
|
||||
// actual device address
|
||||
private var actualDeviceAddress:String?
|
||||
|
||||
// used in parsing packet
|
||||
private var timeStampLastBgReading:Date
|
||||
|
||||
// waiting successful pairing yes or not
|
||||
private var waitingSuccessfulPairing:Bool = false
|
||||
|
||||
// MARK: - public functions
|
||||
|
||||
/// - parameters:
|
||||
/// - address: if already connected before, then give here the address that was received during previous connect, if not give nil
|
||||
/// - transmitterID: expected transmitterID
|
||||
init?(address:String?, transmitterID:String, delegate:CGMTransmitterDelegate, timeStampLastBgReading:Date) {
|
||||
|
||||
// assign addressname and name or expected devicename
|
||||
// start by using expected device name
|
||||
var newAddressAndName:BluetoothTransmitter.DeviceAddressAndName = BluetoothTransmitter.DeviceAddressAndName.notYetConnected(expectedName: CGMBluconTransmitter.createExpectedDeviceName(transmitterIdSetByUser: transmitterID))
|
||||
if let address = address {
|
||||
// address not nil, means it already connected before, use that address
|
||||
newAddressAndName = BluetoothTransmitter.DeviceAddressAndName.alreadyConnectedBefore(address: address)
|
||||
actualDeviceAddress = address
|
||||
}
|
||||
|
||||
//initialize timeStampLastBgReading
|
||||
self.timeStampLastBgReading = timeStampLastBgReading
|
||||
|
||||
// initialize
|
||||
super.init(addressAndName: newAddressAndName, CBUUID_Advertisement: nil, servicesCBUUIDs: [CBUUID(string: CBUUID_BluconService)], CBUUID_ReceiveCharacteristic: CBUUID_ReceiveCharacteristic_Blucon, CBUUID_WriteCharacteristic: CBUUID_WriteCharacteristic_Blucon, startScanningAfterInit: CGMTransmitterType.Blucon.startScanningAfterInit())
|
||||
|
||||
//assign CGMTransmitterDelegate
|
||||
cgmTransmitterDelegate = delegate
|
||||
|
||||
// set self as delegate for BluetoothTransmitterDelegate - this parameter is defined in the parent class BluetoothTransmitter
|
||||
bluetoothTransmitterDelegate = self
|
||||
|
||||
}
|
||||
|
||||
// MARK: - private helper functions
|
||||
|
||||
/// will check if the transmitter id as set by the user is complete, and if not complete it
|
||||
///
|
||||
/// user may just add the digits in which case this function will add BLU... with a number of 0's
|
||||
private static func createExpectedDeviceName(transmitterIdSetByUser: String) -> String {
|
||||
|
||||
var returnValue = transmitterIdSetByUser
|
||||
|
||||
if !returnValue.uppercased().startsWith("BLU") {
|
||||
while returnValue.count < 5 {
|
||||
returnValue = "0" + returnValue;
|
||||
}
|
||||
returnValue = "BLU" + returnValue;
|
||||
}
|
||||
|
||||
return returnValue
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
extension CGMBluconTransmitter: CGMTransmitter {
|
||||
|
||||
func initiatePairing() {
|
||||
// nothing to do, Blucon keeps on reconnecting, resulting in continous pairing request
|
||||
return
|
||||
}
|
||||
|
||||
func reset(requested: Bool) {
|
||||
// no reset supported for blucon
|
||||
return
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
extension CGMBluconTransmitter: BluetoothTransmitterDelegate {
|
||||
|
||||
func centralManagerDidConnect(address: String?, name: String?) {
|
||||
os_log("in centralManagerDidConnect", log: log, type: .info)
|
||||
cgmTransmitterDelegate?.cgmTransmitterDidConnect(address: address, name: name)
|
||||
}
|
||||
|
||||
func centralManagerDidFailToConnect(error: Error?) {
|
||||
os_log("in centralManagerDidFailToConnect", log: log, type: .error)
|
||||
}
|
||||
|
||||
func centralManagerDidUpdateState(state: CBManagerState) {
|
||||
cgmTransmitterDelegate?.deviceDidUpdateBluetoothState(state: state)
|
||||
}
|
||||
|
||||
func centralManagerDidDisconnectPeripheral(error: Error?) {
|
||||
os_log("in centralManagerDidDisconnectPeripheral", log: log, type: .info)
|
||||
cgmTransmitterDelegate?.cgmTransmitterDidDisconnect()
|
||||
}
|
||||
|
||||
func peripheralDidUpdateNotificationStateFor(characteristic: CBCharacteristic, error: Error?) {
|
||||
os_log("in peripheralDidUpdateNotificationStateFor", log: log, type: .info)
|
||||
|
||||
// check if error occurred
|
||||
if let error = error {
|
||||
|
||||
// no need to log the error, it's already logged in BluetoothTransmitter
|
||||
|
||||
// check if it's an encryption error, if so call delegate
|
||||
if error.localizedDescription.uppercased().contains(find: "ENCRYPTION IS INSUFFICIENT") {
|
||||
|
||||
cgmTransmitterDelegate?.cgmTransmitterNeedsPairing()
|
||||
|
||||
waitingSuccessfulPairing = true
|
||||
}
|
||||
} else {
|
||||
if waitingSuccessfulPairing {
|
||||
cgmTransmitterDelegate?.successfullyPaired()
|
||||
waitingSuccessfulPairing = false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func peripheralDidUpdateValueFor(characteristic: CBCharacteristic, error: Error?) {
|
||||
|
||||
// log the received characteristic value
|
||||
os_log("in peripheralDidUpdateValueFor with characteristic UUID = %{public}@", log: log, type: .info, characteristic.uuid.uuidString)
|
||||
|
||||
// this is only applicable the very first time that blucon connects and pairing is done
|
||||
if waitingSuccessfulPairing {
|
||||
cgmTransmitterDelegate?.successfullyPaired()
|
||||
waitingSuccessfulPairing = false
|
||||
}
|
||||
|
||||
// check if error occured
|
||||
if let error = error {
|
||||
os_log(" error: %{public}@", log: log, type: .error , error.localizedDescription)
|
||||
}
|
||||
|
||||
if let value = characteristic.value {
|
||||
let data = value.hexEncodedString()
|
||||
os_log("in peripheral didUpdateValueFor, data = %{public}@", log: log, type: .debug, data)
|
||||
|
||||
} else {
|
||||
os_log("in peripheral didUpdateValueFor, value is nil, no further processing", log: log, type: .error)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -138,7 +138,8 @@ class CGMGNSEntryTransmitter:BluetoothTransmitter, BluetoothTransmitterDelegate,
|
|||
}
|
||||
|
||||
func peripheralDidUpdateValueFor(characteristic: CBCharacteristic, error: Error?) {
|
||||
// log the receivec characteristic value
|
||||
|
||||
// log the received characteristic value
|
||||
os_log("in peripheralDidUpdateValueFor with characteristic UUID = %{public}@, matches characteristic name %{public}@", log: log, type: .info, characteristic.uuid.uuidString, receivedCharacteristicUUIDToCharacteristic(characteristicUUID: characteristic.uuid.uuidString)?.description ?? "not available")
|
||||
|
||||
if let error = error {
|
||||
|
@ -323,6 +324,7 @@ class CGMGNSEntryTransmitter:BluetoothTransmitter, BluetoothTransmitterDelegate,
|
|||
}
|
||||
}
|
||||
|
||||
/// creates readable representation of characteristicUUID, for logging only
|
||||
private func receivedCharacteristicUUIDToCharacteristic(characteristicUUID:String) -> CBUUID_Characteristic_UUID? {
|
||||
if CBUUID_Characteristic_UUID.CBUUID_BatteryLevel.rawValue.containsIgnoringCase(find: characteristicUUID) {
|
||||
return CBUUID_Characteristic_UUID.CBUUID_BatteryLevel
|
||||
|
|
|
@ -105,6 +105,9 @@ final class RootViewController: UIViewController {
|
|||
/// reference to bgReadingSpeaker
|
||||
private var bgReadingSpeaker:BGReadingSpeaker?
|
||||
|
||||
/// timestamp of last notification for pairing
|
||||
private var timeStampLastNotificationForPairing:Date?
|
||||
|
||||
// MARK: - View Life Cycle
|
||||
|
||||
override func viewWillAppear(_ animated: Bool) {
|
||||
|
@ -593,6 +596,12 @@ final class RootViewController: UIViewController {
|
|||
cgmTransmitter = CGMGNSEntryTransmitter(address: UserDefaults.standard.bluetoothDeviceAddress, delegate: self, timeStampLastBgReading: Date(timeIntervalSince1970: 0))
|
||||
calibrator = Libre1Calibrator()
|
||||
|
||||
case .Blucon:
|
||||
if let currentTransmitterId = UserDefaults.standard.transmitterId {
|
||||
cgmTransmitter = CGMBluconTransmitter(address: UserDefaults.standard.bluetoothDeviceAddress, transmitterID: currentTransmitterId, delegate: self, timeStampLastBgReading: Date(timeIntervalSince1970: 0))
|
||||
calibrator = Libre1Calibrator()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1001,6 +1010,9 @@ extension RootViewController:CGMTransmitterDelegate {
|
|||
|
||||
func successfullyPaired() {
|
||||
|
||||
// remove existing notification if any
|
||||
UNUserNotificationCenter.current().removeDeliveredNotifications(withIdentifiers: [Constants.Notifications.NotificationIdentifierForTransmitterNeedsPairing.transmitterNeedsPairing])
|
||||
|
||||
// invalidate transmitterPairingResponseTimer
|
||||
if let transmitterPairingResponseTimer = transmitterPairingResponseTimer {
|
||||
transmitterPairingResponseTimer.invalidate()
|
||||
|
@ -1063,6 +1075,20 @@ extension RootViewController:CGMTransmitterDelegate {
|
|||
|
||||
os_log("transmitter needs pairing", log: log, type: .info)
|
||||
|
||||
if let timeStampLastNotificationForPairing = timeStampLastNotificationForPairing {
|
||||
|
||||
// check timestamp of last notification, if too soon then return
|
||||
if Int(abs(timeStampLastNotificationForPairing.timeIntervalSinceNow)) < Constants.BluetoothPairing.minimumTimeBetweenTwoPairingNotificationsInSeconds {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// set timeStampLastNotificationForPairing
|
||||
timeStampLastNotificationForPairing = Date()
|
||||
|
||||
// remove existing notification if any
|
||||
UNUserNotificationCenter.current().removeDeliveredNotifications(withIdentifiers: [Constants.Notifications.NotificationIdentifierForTransmitterNeedsPairing.transmitterNeedsPairing])
|
||||
|
||||
// Create Notification Content
|
||||
let notificationContent = UNMutableNotificationContent()
|
||||
|
||||
|
|
|
@ -28,7 +28,7 @@ class SettingsViewDexcomSettingsViewModel:SettingsViewModelProtocol {
|
|||
if let transmitterType = UserDefaults.standard.transmitterType {
|
||||
switch transmitterType {
|
||||
|
||||
case .dexcomG4, .miaomiao, .GNSentry:
|
||||
case .dexcomG4, .miaomiao, .GNSentry, .Blucon:
|
||||
return true
|
||||
|
||||
case .dexcomG5, .dexcomG6:
|
||||
|
|
|
@ -170,11 +170,11 @@ struct SettingsViewTransmitterSettingsViewModel:SettingsViewModelProtocol {
|
|||
|
||||
switch transmitterType {
|
||||
|
||||
case .dexcomG4, .miaomiao, .GNSentry:
|
||||
break
|
||||
|
||||
case .dexcomG5, .dexcomG6:
|
||||
UserDefaults.standard.dexcomShareSerialNumber = UserDefaults.standard.transmitterId
|
||||
|
||||
default:
|
||||
break
|
||||
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue