bluetoothPeripheralViewController, add line with last connection or disconnection timestamp

This commit is contained in:
Johan Degraeve 2020-03-24 20:35:34 +01:00
parent e5b677f8ae
commit 1dedd35156
15 changed files with 214 additions and 86 deletions

View File

@ -199,6 +199,15 @@
F8BECB05235CE5D80060DAE1 /* GlucoseChartManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = F8BECB04235CE5D80060DAE1 /* GlucoseChartManager.swift */; };
F8BECB12235CEA9B0060DAE1 /* TimeInterval.swift in Sources */ = {isa = PBXBuildFile; fileRef = F8BECB11235CEA9B0060DAE1 /* TimeInterval.swift */; };
F8C5EBE722F38F0E00563B5F /* Trace.swift in Sources */ = {isa = PBXBuildFile; fileRef = F8C5EBE622F38F0E00563B5F /* Trace.swift */; };
F8C9784D2428052E00A09483 /* CGMSensorType.swift in Sources */ = {isa = PBXBuildFile; fileRef = F8C9784C2428052D00A09483 /* CGMSensorType.swift */; };
F8DF765323E34F4500063910 /* DexcomG5+CoreDataClass.swift in Sources */ = {isa = PBXBuildFile; fileRef = F8DF765223E34F4500063910 /* DexcomG5+CoreDataClass.swift */; };
F8DF765523E34FD500063910 /* DexcomG5+CoreDataProperties.swift in Sources */ = {isa = PBXBuildFile; fileRef = F8DF765423E34FD500063910 /* DexcomG5+CoreDataProperties.swift */; };
F8DF765C23E350B100063910 /* DexcomG5+BluetoothPeripheral.swift in Sources */ = {isa = PBXBuildFile; fileRef = F8DF765B23E350B100063910 /* DexcomG5+BluetoothPeripheral.swift */; };
F8DF766023E38FC100063910 /* BLEPeripheral+CoreDataClass.swift in Sources */ = {isa = PBXBuildFile; fileRef = F8DF765F23E38FC100063910 /* BLEPeripheral+CoreDataClass.swift */; };
F8DF766223E390D100063910 /* BLEPeripheral+CoreDataProperties.swift in Sources */ = {isa = PBXBuildFile; fileRef = F8DF766123E390D100063910 /* BLEPeripheral+CoreDataProperties.swift */; };
F8DF766423E781C100063910 /* BLEPeripheralAccessor.swift in Sources */ = {isa = PBXBuildFile; fileRef = F8DF766323E781C100063910 /* BLEPeripheralAccessor.swift */; };
F8DF766823E782E400063910 /* DexcomG5Accessor.swift in Sources */ = {isa = PBXBuildFile; fileRef = F8DF766723E782E400063910 /* DexcomG5Accessor.swift */; };
F8DF766D23ED9B0900063910 /* DexcomG5BluetoothPeripheralViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = F8DF766C23ED9B0900063910 /* DexcomG5BluetoothPeripheralViewModel.swift */; };
F8E3A2A323D4E7E200E5E98A /* Default-568h@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = F8E3A2A223D4E7E200E5E98A /* Default-568h@2x.png */; };
F8E3A2A523D78FBD00E5E98A /* SettingsViewAppleWatchSettingsViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = F8E3A2A423D78FBD00E5E98A /* SettingsViewAppleWatchSettingsViewModel.swift */; };
F8E3A2A923D906C200E5E98A /* WatchManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = F8E3A2A823D906C200E5E98A /* WatchManager.swift */; };
@ -633,6 +642,7 @@
F8C5EBE622F38F0E00563B5F /* Trace.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Trace.swift; sourceTree = "<group>"; };
F8C5EBED22F5A52400563B5F /* pt-BR */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "pt-BR"; path = "pt-BR.lproj/Common.strings"; sourceTree = "<group>"; };
F8C5EBEE22F5A52800563B5F /* pt */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = pt; path = pt.lproj/Common.strings; sourceTree = "<group>"; };
F8C9784C2428052D00A09483 /* CGMSensorType.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CGMSensorType.swift; sourceTree = "<group>"; };
F8DF764E23DCF64F00063910 /* xdrip v10.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = "xdrip v10.xcdatamodel"; sourceTree = "<group>"; };
F8E3A2A223D4E7E200E5E98A /* Default-568h@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Default-568h@2x.png"; sourceTree = "<group>"; };
F8E3A2A423D78FBD00E5E98A /* SettingsViewAppleWatchSettingsViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsViewAppleWatchSettingsViewModel.swift; sourceTree = "<group>"; };
@ -1686,6 +1696,7 @@
F8F971F223A5915900C3F17D /* TransmitterBatteryInfo.swift */,
F8F971F323A5915900C3F17D /* CGMTransmitterDelegate.swift */,
F8F971F423A5915900C3F17D /* GlucoseData.swift */,
F8C9784C2428052D00A09483 /* CGMSensorType.swift */,
);
path = Generic;
sourceTree = "<group>";
@ -1998,6 +2009,7 @@
F8EA6CA921BBE3010082976B /* UniqueId.swift in Sources */,
F8A1585122EDB597007F5B5D /* ConstantsBGGraphBuilder.swift in Sources */,
F81D6D4822BD5F62005EFAE2 /* DexcomShareUploadManager.swift in Sources */,
F8C9784D2428052E00A09483 /* CGMSensorType.swift in Sources */,
F8A1586B22EDB967007F5B5D /* ConstantsMaster.swift in Sources */,
F8F9723923A5928D00C3F17D /* M5StackBluetoothPeripheralViewModel.swift in Sources */,
F8F9722B23A5915900C3F17D /* CGMTransmitterDelegate.swift in Sources */,

View File

@ -52,4 +52,6 @@ extension BLEPeripheral {
/// sensorSerialNumber of last sensor that was read
@NSManaged public var sensorSerialNumber: String?
/// timestamp when connection changed to connected or not connected
@NSManaged public var lastConnectionStatusChangeTimeStamp: Date?
}

View File

@ -40,6 +40,7 @@
<entity name="BLEPeripheral" representedClassName=".BLEPeripheral" syncable="YES">
<attribute name="address" attributeType="String"/>
<attribute name="alias" optional="YES" attributeType="String"/>
<attribute name="lastConnectionStatusChangeTimeStamp" optional="YES" attributeType="Date" usesScalarValueType="NO"/>
<attribute name="name" attributeType="String"/>
<attribute name="oopWebSite" optional="YES" attributeType="String"/>
<attribute name="oopWebToken" optional="YES" attributeType="String"/>
@ -113,7 +114,7 @@
<element name="AlertEntry" positionX="-648" positionY="189" width="128" height="105"/>
<element name="AlertType" positionX="-657" positionY="180" width="128" height="165"/>
<element name="BgReading" positionX="-285.87109375" positionY="31.9921875" width="128" height="330"/>
<element name="BLEPeripheral" positionX="-630" positionY="216" width="128" height="268"/>
<element name="BLEPeripheral" positionX="-630" positionY="216" width="128" height="283"/>
<element name="Bubble" positionX="-657" positionY="189" width="128" height="103"/>
<element name="Calibration" positionX="-859.21484375" positionY="46.21484375" width="128" height="285"/>
<element name="DexcomG5" positionX="-648" positionY="198" width="128" height="163"/>

View File

@ -47,6 +47,14 @@ extension Date {
return dateFormatter.string(from: self).appending("Z")
}
/// date to short string, according to locale
func toShortString() -> String {
let dateFormatter = DateFormatter()
dateFormatter.timeStyle = .short
dateFormatter.dateStyle = .short
return dateFormatter.string(from: self)
}
/// returns seconds since 1.1.1970 local time for current timezone
func toSecondsAsInt64Local() -> Int64 {
let calendar = Calendar.current

View File

@ -127,7 +127,9 @@ extension BluetoothPeripheralManager: BluetoothTransmitterDelegate {
func reset(for bluetoothTransmitter: BluetoothTransmitter, successful: Bool) {
// set resetrequired to false in coredata, there's no need to reset as it's just been done
getBluetoothPeripheral(for: bluetoothTransmitter).blePeripheral.resetrequired = false
if let bluetoothPeripheral = getBluetoothPeripheral(for: bluetoothTransmitter) {
bluetoothPeripheral.blePeripheral.resetrequired = false
}
// Create Notification Content to give info about reset result of reset attempt
let notificationContent = UNMutableNotificationContent()
@ -151,8 +153,13 @@ extension BluetoothPeripheralManager: BluetoothTransmitterDelegate {
func didConnectTo(bluetoothTransmitter: BluetoothTransmitter) {
/// if bluetoothTransmitter is a CGMTransmitter and if it's a new one (ie address is different than currentCgmTransmitterAddress then call cgmTransmitterChanged
let checkCurrentCGMTransmitterHelper = { (_ bluetoothTransmitter : BluetoothTransmitter) in
// before exiting save the changes
defer {
coreDataManager.saveChanges()
}
/// helper function : if bluetoothTransmitter is a CGMTransmitter and if it's a new one (ie address is different than currentCgmTransmitterAddress then call cgmTransmitterChanged
let checkCurrentCGMTransmitterHelper = {
// if it's a CGMTransmitter and if it's a new one then call cgmTransmitterChanged,
if bluetoothTransmitter is CGMTransmitter, bluetoothTransmitter.deviceAddress != self.currentCgmTransmitterAddress {
@ -166,12 +173,18 @@ extension BluetoothPeripheralManager: BluetoothTransmitterDelegate {
}
// if tempBlueToothTransmitterWhileScanningForNewBluetoothPeripheral is nil, then this is a connection to an already known/stored BluetoothTransmitter. BluetoothPeripheralManager is not interested in this info.
// if tempBlueToothTransmitterWhileScanningForNewBluetoothPeripheral is nil, then this is a connection to an already known/stored BluetoothTransmitter.
guard let tempBlueToothTransmitterWhileScanningForNewBluetoothPeripheral = tempBlueToothTransmitterWhileScanningForNewBluetoothPeripheral else {
trace(" in didConnect, tempBlueToothTransmitterWhileScanningForNewBluetoothPeripheral is nil", log: log, category: ConstantsLog.categoryBluetoothPeripheralManager, type: .info)
checkCurrentCGMTransmitterHelper(bluetoothTransmitter)
// Need to call checkCurrentCGMTransmitterHelper
checkCurrentCGMTransmitterHelper()
// set lastConnectionStatusChangeTimeStamp in blePeripheral to now
if let bluetoothPeripheral = getBluetoothPeripheral(for: bluetoothTransmitter) {
bluetoothPeripheral.blePeripheral.lastConnectionStatusChangeTimeStamp = Date()
}
return
@ -191,7 +204,13 @@ extension BluetoothPeripheralManager: BluetoothTransmitterDelegate {
trace("in didConnect, tempBlueToothTransmitterWhileScanningForNewBluetoothPeripheral is not nil and not equal to bluetoothTransmitter", log: log, category: ConstantsLog.categoryBluetoothPeripheralManager, type: .info)
checkCurrentCGMTransmitterHelper(bluetoothTransmitter)
// Need to call checkCurrentCGMTransmitterHelper
checkCurrentCGMTransmitterHelper()
// set lastConnectionStatusChangeTimeStamp in blePeripheral to now
if let bluetoothPeripheral = getBluetoothPeripheral(for: bluetoothTransmitter) {
bluetoothPeripheral.blePeripheral.lastConnectionStatusChangeTimeStamp = Date()
}
return
@ -229,22 +248,40 @@ extension BluetoothPeripheralManager: BluetoothTransmitterDelegate {
self.callBackAfterDiscoveringDevice = nil
}
checkCurrentCGMTransmitterHelper(bluetoothTransmitter)
// Need to call checkCurrentCGMTransmitterHelper
checkCurrentCGMTransmitterHelper()
// set lastConnectionStatusChangeTimeStamp in blePeripheral to now
if let bluetoothPeripheral = getBluetoothPeripheral(for: bluetoothTransmitter) {
bluetoothPeripheral.blePeripheral.lastConnectionStatusChangeTimeStamp = Date()
}
// assign tempBlueToothTransmitterWhileScanningForNewBluetoothPeripheral to nil here
self.tempBlueToothTransmitterWhileScanningForNewBluetoothPeripheral = nil
coreDataManager.saveChanges()
}
func deviceDidUpdateBluetoothState(state: CBManagerState, bluetoothTransmitter: BluetoothTransmitter) {
trace("in deviceDidUpdateBluetoothState, no further action", log: log, category: ConstantsLog.categoryBluetoothPeripheralManager, type: .info)
trace("in deviceDidUpdateBluetoothState", log: log, category: ConstantsLog.categoryBluetoothPeripheralManager, type: .info)
if bluetoothTransmitter.deviceAddress == nil {
/// this bluetoothTransmitter is created to start scanning for a new, unknown M5Stack, so start scanning
/// this bluetoothTransmitter is created to start scanning for a new, unknown bluetoothtransmitter, so start scanning
_ = bluetoothTransmitter.startScanning()
}
// disconnect doesn't get triggered if status changes to off
// so if the device already has a lastConnectionStatusChangeTimeStamp and if new state = poweredoff then set lastConnectionStatusChangeTimeStamp to current date
if let bluetoothPeripheral = getBluetoothPeripheral(for: bluetoothTransmitter) {
if bluetoothPeripheral.blePeripheral.lastConnectionStatusChangeTimeStamp != nil && state == .poweredOff {
bluetoothPeripheral.blePeripheral.lastConnectionStatusChangeTimeStamp = Date()
}
}
coreDataManager.saveChanges()
}
func error(message: String) {
@ -254,9 +291,16 @@ extension BluetoothPeripheralManager: BluetoothTransmitterDelegate {
}
func didDisconnectFrom(bluetoothTransmitter: BluetoothTransmitter) {
// no further action, This is for UIViewcontroller's that also receive this info, means info can only be shown if this happens while user has one of the UIViewcontrollers open
trace("in didDisconnectFrom", log: log, category: ConstantsLog.categoryBluetoothPeripheralManager, type: .info)
// set lastConnectionStatusChangeTimeStamp in blePeripheral to now
if let bluetoothPeripheral = getBluetoothPeripheral(for: bluetoothTransmitter) {
bluetoothPeripheral.blePeripheral.lastConnectionStatusChangeTimeStamp = Date()
}
coreDataManager.saveChanges()
}
/// will call bluetoothTransmitter.initiatePairing() - also sets timer, if no successful pairing within a few seconds, then info will be given to user asking to wait another few minutes

View File

@ -31,7 +31,7 @@ class BluetoothPeripheralManager: NSObject {
public var bluetoothTransmitterThatNeedsPairing: BluetoothTransmitter?
/// when xdrip connects to a BluetoothTransmitter that is also CGMTransmitter, then we'll call this function with the BluetoothTransmitter as argument. This function is defined by RootViewController, it will allow the RootViewController to set the CGMTransmitter, calibrator ...
public var cgmTransmitterChanged: () -> ()
public var cgmTransmitterInfoChanged: () -> ()
/// address of the last active cgmTransmitter
///
@ -39,7 +39,7 @@ class BluetoothPeripheralManager: NSObject {
public var currentCgmTransmitterAddress: String? {
didSet(newValue) {
if newValue != currentCgmTransmitterAddress {
cgmTransmitterChanged()
cgmTransmitterInfoChanged()
}
}
}
@ -64,14 +64,14 @@ class BluetoothPeripheralManager: NSObject {
// MARK: - initializer
/// - parameters:
/// - cgmTransmitterChanged : to be called when currently used cgmTransmitter changes or is set to nil
init(coreDataManager: CoreDataManager, cgmTransmitterDelegate: CGMTransmitterDelegate, uIViewController: UIViewController, cgmTransmitterChanged: @escaping () -> ()) {
/// - cgmTransmitterInfoChanged : to be called when currently used cgmTransmitter changes or is set to nil
init(coreDataManager: CoreDataManager, cgmTransmitterDelegate: CGMTransmitterDelegate, uIViewController: UIViewController, cgmTransmitterInfoChanged: @escaping () -> ()) {
// initialize properties
self.coreDataManager = coreDataManager
self.bgReadingsAccessor = BgReadingsAccessor(coreDataManager: coreDataManager)
self.cgmTransmitterDelegate = cgmTransmitterDelegate
self.cgmTransmitterChanged = cgmTransmitterChanged
self.cgmTransmitterInfoChanged = cgmTransmitterInfoChanged
self.bLEPeripheralAccessor = BLEPeripheralAccessor(coreDataManager: coreDataManager)
self.uIViewController = uIViewController
@ -503,20 +503,20 @@ class BluetoothPeripheralManager: NSObject {
}
private func setTransmitterToNilAndCallCgmTransmitterChangedIfNecessary(indexInBluetoothTransmittersArray index: Int) {
private func setTransmitterToNilAndCallcgmTransmitterInfoChangedIfNecessary(indexInBluetoothTransmittersArray index: Int) {
// check if transmitter being deleted is the currently assigned CGMTransmitter and if yes call
var callCgmTransmitterChanged = false
// check if transmitter being deleted is the currently assigned CGMTransmitter and if yes call cgmTransmitterInfoChanged after setting bluetoothTransmitter to nil
var callcgmTransmitterInfoChanged = false
if transmitterIsCurrentlyUsedCGMTransmitter(bluetoothTransmitter: bluetoothTransmitters[index]) {
callCgmTransmitterChanged = true
callcgmTransmitterInfoChanged = true
}
// set bluetoothTransmitter to nil, this will also initiate a disconnect
bluetoothTransmitters[index] = nil
if callCgmTransmitterChanged {
if callcgmTransmitterInfoChanged {
// set currentCgmTransmitterAddress to nil, this will implicitly call cgmTransmitterChanged
// set currentCgmTransmitterAddress to nil, this will implicitly call cgmTransmitterInfoChanged
currentCgmTransmitterAddress = nil
}
@ -692,6 +692,9 @@ extension BluetoothPeripheralManager: BluetoothPeripheralManaging {
// webOOPEnabled changed, initate a reading immediately should user gets either a new value or a calibration request, depending on value of webOOPEnabled
cgmTransmitter.requestNewReading()
// call cgmTransmitterInfoChanged
cgmTransmitterInfoChanged()
}
@ -704,6 +707,15 @@ extension BluetoothPeripheralManager: BluetoothPeripheralManaging {
getCGMTransmitter(for: bluetoothPeripheral)?.setWebOOPSite(oopWebSite: oopWebSite)
if let cgmTransmitter = getCGMTransmitter(for: bluetoothPeripheral) {
cgmTransmitter.setWebOOPSite(oopWebSite: oopWebSite)
// oopWebSite changed, initate a reading immediately should user gets either a new value or a calibration request, depending on value of webOOPEnabled
cgmTransmitter.requestNewReading()
}
}
func receivedNewValue(oopWebToken: String?, for bluetoothPeripheral: BluetoothPeripheral) {
@ -711,7 +723,14 @@ extension BluetoothPeripheralManager: BluetoothPeripheralManaging {
/// if oopWebToken is nil, then there's no need to send that value to the transmitter, because this should only be the case if oopWebToken is false
guard let oopWebToken = oopWebToken else {return}
getCGMTransmitter(for: bluetoothPeripheral)?.setWebOOPToken(oopWebToken: oopWebToken)
if let cgmTransmitter = getCGMTransmitter(for: bluetoothPeripheral) {
cgmTransmitter.setWebOOPToken(oopWebToken: oopWebToken)
// oopWebToken changed, initate a reading immediately should user gets either a new value or a calibration request, depending on value of webOOPEnabled
cgmTransmitter.requestNewReading()
}
}
@ -727,7 +746,6 @@ extension BluetoothPeripheralManager: BluetoothPeripheralManaging {
}
/// stops scanning for new device
func stopScanningForNewDevice() {
if let tempBlueToothTransmitterWhileScanningForNewBluetoothPeripheral = tempBlueToothTransmitterWhileScanningForNewBluetoothPeripheral {
@ -753,7 +771,6 @@ extension BluetoothPeripheralManager: BluetoothPeripheralManaging {
}
/// try to connect to the M5Stack
func connect(to bluetoothPeripheral: BluetoothPeripheral) {
// the trick : by calling bluetoothTransmitter(forBluetoothPeripheral: bluetoothPeripheral, createANewOneIfNecesssary: true), there's two cases
@ -766,20 +783,14 @@ extension BluetoothPeripheralManager: BluetoothPeripheralManaging {
}
/// returns the BluetoothPeripheral for the specified BluetoothTransmitter
/// - parameters:
/// - for : the bluetoothTransmitter, for which BluetoothPeripheral should be returned
func getBluetoothPeripheral(for bluetoothTransmitter: BluetoothTransmitter) -> BluetoothPeripheral {
func getBluetoothPeripheral(for bluetoothTransmitter: BluetoothTransmitter) -> BluetoothPeripheral? {
guard let index = bluetoothTransmitters.firstIndex(of: bluetoothTransmitter) else {
fatalError("in BluetoothPeripheralManager, function getBluetoothPeripherals, could not find specified bluetoothTransmitter")
}
guard let index = bluetoothTransmitters.firstIndex(of: bluetoothTransmitter) else {return nil}
return bluetoothPeripherals[index]
}
/// deletes the BluetoothPeripheral in coredata, and also the corresponding BluetoothTransmitter if there is one will be deleted
func deleteBluetoothPeripheral(bluetoothPeripheral: BluetoothPeripheral) {
// find the bluetoothPeripheral in array bluetoothPeripherals, if it's not there then this looks like a coding error
@ -788,7 +799,7 @@ extension BluetoothPeripheralManager: BluetoothPeripheralManaging {
return
}
setTransmitterToNilAndCallCgmTransmitterChangedIfNecessary(indexInBluetoothTransmittersArray: index)
setTransmitterToNilAndCallcgmTransmitterInfoChangedIfNecessary(indexInBluetoothTransmittersArray: index)
// delete in coredataManager
coreDataManager.mainManagedObjectContext.delete(bluetoothPeripherals[index] as! NSManagedObject)
@ -802,14 +813,12 @@ extension BluetoothPeripheralManager: BluetoothPeripheralManaging {
}
/// - returns: the bluetoothPeripheral's managed by this BluetoothPeripheralManager
func getBluetoothPeripherals() -> [BluetoothPeripheral] {
return bluetoothPeripherals
}
/// - returns: the bluetoothTransmitters managed by this BluetoothPeripheralManager
func getBluetoothTransmitters() -> [BluetoothTransmitter] {
var bluetoothTransmitters: [BluetoothTransmitter] = []
@ -824,12 +833,11 @@ extension BluetoothPeripheralManager: BluetoothPeripheralManaging {
}
/// bluetoothTransmitter for this bluetoothPeripheral will be deleted, as a result this will also disconnect the bluetoothPeripheral
func setBluetoothTransmitterToNil(forBluetoothPeripheral bluetoothPeripheral: BluetoothPeripheral) {
if let index = firstIndexInBluetoothPeripherals(bluetoothPeripheral: bluetoothPeripheral) {
setTransmitterToNilAndCallCgmTransmitterChangedIfNecessary(indexInBluetoothTransmittersArray: index)
setTransmitterToNilAndCallcgmTransmitterInfoChangedIfNecessary(indexInBluetoothTransmittersArray: index)
}
}

View File

@ -8,13 +8,13 @@ protocol BluetoothPeripheralManaging: BluetoothTransmitterDelegate {
/// - transmitterId : only for devices that need a transmitterID (currently only Dexcom and Blucon)
func startScanningForNewDevice(type: BluetoothPeripheralType, transmitterId: String?, callback: @escaping (BluetoothPeripheral) -> Void)
/// will stop scanning, this is again for the case where scanning for a new BluetoothPeripheral has started
/// stops scanning for new device
func stopScanningForNewDevice()
/// to know if bluetoothperipheralmanager is currently scanning for a new device
func isScanning() -> Bool
/// try to connect to the BluetoothPeripheral
/// try to connect to the M5Stack
func connect(to bluetoothPeripheral: BluetoothPeripheral)
/// returns the BluetoothTransmitter for the specified bluetoothPeripheral
@ -26,7 +26,9 @@ protocol BluetoothPeripheralManaging: BluetoothTransmitterDelegate {
/// returns the BluetoothPeripheral for the specified BluetoothTransmitter
/// - parameters:
/// - for : the bluetoothTransmitter, for which BluetoothPeripheral should be returned
func getBluetoothPeripheral(for bluetoothTransmitter: BluetoothTransmitter) -> BluetoothPeripheral
/// - returns:
/// - bluetoothPeripheral for the transmitter, can be nil (example if called while scanning)
func getBluetoothPeripheral(for bluetoothTransmitter: BluetoothTransmitter) -> BluetoothPeripheral?
/// deletes the BluetoothPeripheral in coredata, and also the corresponding BluetoothTransmitter if there is one will be deleted
func deleteBluetoothPeripheral(bluetoothPeripheral: BluetoothPeripheral)

View File

@ -2,7 +2,6 @@
"status" = "Status";
"connected" = "connected";
"notConnected" = "not connected";
"alwaysconnect" = "Always Connect";
"donotconnect" = "Don't try to connect";
"selectAliasText" = "Choose an alias for this Bluetooth Peripheral, the name will be shown in the app and is easier for you to recognize";
"aliasAlreadyExists" = "There is already a Bluetooth Peripheral with this alias";
@ -17,3 +16,5 @@
"tryingToConnect" = "Trying to connect";
"connect" = "Connect";
"notTryingToConnect" = "Not trying to connect";
"disConnectedAt" = "Disconnected At";
"connectedAt" = "Connected At";

View File

@ -3,4 +3,4 @@
"selectCategory" = "Select Category";
"selectType" = "Select Type";
"batteryLevel" = "Battery Level";
"noMultipleActiveCGMsAllowed" = "You can not have more than one CGM Transmitter which is connected or trying to connect.\nVerify your other CGM Transmitters and either click 'Don't connect' or delete it.";
"noMultipleActiveCGMsAllowed" = "You can not have more than one CGM Transmitter which is connected or trying to connect.\nVerify your other CGM Transmitters and either click 'Don't try to connect' or delete it.";

View File

@ -19,7 +19,7 @@
<key>CFBundleShortVersionString</key>
<string>$(MARKETING_VERSION)</string>
<key>CFBundleVersion</key>
<string>3575</string>
<string>3605</string>
<key>LSRequiresIPhoneOS</key>
<true/>
<key>NSAppTransportSecurity</key>

View File

@ -20,10 +20,6 @@ class Texts_BluetoothPeripheralView {
return NSLocalizedString("notConnected", tableName: filename, bundle: Bundle.main, value: "Not Connected", comment: "when Bluetooth Peripheral is shown, connection status, not connected")
}()
static let alwaysConnect: String = {
return NSLocalizedString("alwaysconnect", tableName: filename, bundle: Bundle.main, value: "Always Connect", comment: "text in button top right, by clicking, user says that device should always try to connect")
}()
static let donotconnect: String = {
return NSLocalizedString("donotconnect", tableName: filename, bundle: Bundle.main, value: "Don't try to connect", comment: "text in button top right, this button will disable automatic connect")
}()
@ -83,4 +79,13 @@ class Texts_BluetoothPeripheralView {
static let connect: String = {
return NSLocalizedString("connect", tableName: filename, bundle: Bundle.main, value: "Connect", comment: "button text, to connect")
}()
static let connectedAt: String = {
return NSLocalizedString("connectedAt", tableName: filename, bundle: Bundle.main, value: "Connected At", comment: "cell text, where the connection timestamp is shown")
}()
static let disConnectedAt: String = {
return NSLocalizedString("disConnectedAt", tableName: filename, bundle: Bundle.main, value: "Disconnected At", comment: "cell text, where the disconnection timestamp is shown")
}()
}

View File

@ -21,6 +21,6 @@ class Texts_BluetoothPeripheralsView {
}()
static let noMultipleActiveCGMsAllowed: String = {
return NSLocalizedString("noMultipleActiveCGMsAllowed", tableName: filename, bundle: Bundle.main, value: "You can not have more than one CGM Transmitter which is connected or trying to connect.\nVerify your other CGM Transmitters and either click 'Don't connect' or delete it.", comment: "When adding a new cgm transmitter, but the user has another one already which is either connected or trying to connect")
return NSLocalizedString("noMultipleActiveCGMsAllowed", tableName: filename, bundle: Bundle.main, value: "You can not have more than one CGM Transmitter which is connected or trying to connect.\nVerify your other CGM Transmitters and either click 'Don't try to connect' or delete it.", comment: "When adding a new cgm transmitter, but the user has another one already which is either connected or trying to connect")
}()
}

View File

@ -19,10 +19,13 @@ fileprivate enum Setting:Int, CaseIterable {
/// the current connection status
case connectionStatus = 3
/// timestamp when connection changed to connected or not connected
case connectOrDisconnectTimeStamp = 4
/// ANY NEW SETTINGS SHOULD BE INSERTED HERE
/// transmitterID, only for devices that need it
case transmitterId = 4
case transmitterId = 5
}
@ -579,7 +582,9 @@ extension BluetoothPeripheralViewController: UITableViewDataSource, UITableViewD
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// expectedBluetoothPeripheralType should not be nil here, unwrap it
guard let expectedBluetoothPeripheralType = expectedBluetoothPeripheralType else {return 0}
guard let expectedBluetoothPeripheralType = expectedBluetoothPeripheralType else {
fatalError("in tableView numberOfRowsInSection, expectedBluetoothPeripheralType is nil")
}
if section == 0 {
@ -597,31 +602,32 @@ extension BluetoothPeripheralViewController: UITableViewDataSource, UITableViewD
} else if section == 1 {
// this is the section with the web oop settings
// if weboop not enabled then just one row
// if the bluetoothperipheral type supports oopweb then this is the oop web section
if bluetoothPeripheralViewModel?.canWebOOP() ?? false {
if let bluetoothPeripheral = bluetoothPeripheral {
if bluetoothPeripheral.blePeripheral.webOOPEnabled {
return WebOOPSettings.allCases.count
} else {
return 1
// check if weboopenabled and if yes return the number of settings in that section
if let bluetoothPeripheral = bluetoothPeripheral {
if bluetoothPeripheral.blePeripheral.webOOPEnabled {
return WebOOPSettings.allCases.count
}
}
} else {
// weboop supported by the peripheral but not enabled
return 1
}
}
// it's not section 0 and it's not section 1 && weboop supported
// this is the section with the transmitter specific settings
// unwrap bluetoothPeripheralViewModel
if let bluetoothPeripheralViewModel = bluetoothPeripheralViewModel {
return bluetoothPeripheralViewModel.numberOfSettings(inSection: section)
} else {
// this is the section with the transmitter specific settings
// unwrap bluetoothPeripheralViewModel
if let bluetoothPeripheralViewModel = bluetoothPeripheralViewModel {
return bluetoothPeripheralViewModel.numberOfSettings(inSection: section)
} else {
return 0
}
fatalError("in tableView numberOfRowsInSection, bluetoothPeripheralViewModel is nil")
}
}
@ -629,7 +635,7 @@ extension BluetoothPeripheralViewController: UITableViewDataSource, UITableViewD
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
guard let cell = tableView.dequeueReusableCell(withIdentifier: SettingsTableViewCell.reuseIdentifier, for: indexPath) as? SettingsTableViewCell else { fatalError("BluetoothPeripheralViewController cellforrowat, Unexpected Table View Cell ") }
// unwrap bluetoothPeripheralManager
guard let bluetoothPeripheralManager = bluetoothPeripheralManager else {return cell}
@ -705,13 +711,34 @@ extension BluetoothPeripheralViewController: UITableViewDataSource, UITableViewD
// if transmitterId already has a value, then it can't be changed anymore. To change it, user must delete the transmitter and recreate one.
cell.accessoryType = transmitterIdTempValue == nil ? .disclosureIndicator : .none
case .connectOrDisconnectTimeStamp:
if let bluetoothPeripheral = bluetoothPeripheral, let lastConnectionStatusChangeTimeStamp = bluetoothPeripheral.blePeripheral.lastConnectionStatusChangeTimeStamp {
if BluetoothPeripheralViewController.bluetoothPeripheralIsConnected(bluetoothPeripheral: bluetoothPeripheral, bluetoothPeripheralManager: bluetoothPeripheralManager as! BluetoothPeripheralManager) {
cell.textLabel?.text = Texts_BluetoothPeripheralView.connectedAt
} else {
cell.textLabel?.text = Texts_BluetoothPeripheralView.disConnectedAt
}
cell.detailTextLabel?.text = lastConnectionStatusChangeTimeStamp.toShortString()
} else {
cell.textLabel?.text = Texts_BluetoothPeripheralView.connectedAt
cell.detailTextLabel?.text = ""
}
}
} else {
// web oop settings
guard let setting = WebOOPSettings(rawValue: indexPath.row) else { fatalError("BluetoothPeripheralViewController cellForRowAt, Unexpected setting") }
guard let setting = WebOOPSettings(rawValue: indexPath.row) else { fatalError("BluetoothPeripheralViewController cellForRowAt, Unexpected setting, row = " + indexPath.row.description) }
// configure the cell depending on setting
switch setting {
@ -853,6 +880,9 @@ extension BluetoothPeripheralViewController: UITableViewDataSource, UITableViewD
// present the alert
self.present(alert, animated: true, completion: nil)
case .connectOrDisconnectTimeStamp:
break
case .transmitterId:
// if transmitterId already has a value, then it can't be changed anymore. To change it, user must delete the transmitter and recreate one.
@ -865,7 +895,7 @@ extension BluetoothPeripheralViewController: UITableViewDataSource, UITableViewD
// web oop settings
guard let setting = WebOOPSettings(rawValue: indexPath.row) else { fatalError("BluetoothPeripheralViewController cellForRowAt, Unexpected setting") }
guard let setting = WebOOPSettings(rawValue: indexPath.row) else { fatalError("BluetoothPeripheralViewController didSelectRowAt, Unexpected setting") }
switch setting {
@ -979,8 +1009,12 @@ extension BluetoothPeripheralViewController: BluetoothTransmitterDelegate {
// handled in BluetoothPeripheralManager
bluetoothPeripheralManager?.didConnectTo(bluetoothTransmitter: bluetoothTransmitter)
// refresh row with status
tableView.reloadRows(at: [IndexPath(row: Setting.connectionStatus.rawValue, section: 0)], with: .none)
// refresh row with connection timestamp
tableView.reloadRows(at: [IndexPath(row: Setting.connectOrDisconnectTimeStamp.rawValue, section: 0)], with: .none)
}
func didDisconnectFrom(bluetoothTransmitter: BluetoothTransmitter) {
@ -988,8 +1022,12 @@ extension BluetoothPeripheralViewController: BluetoothTransmitterDelegate {
// handled in BluetoothPeripheralManager
bluetoothPeripheralManager?.didDisconnectFrom(bluetoothTransmitter: bluetoothTransmitter)
// refresh row with status
tableView.reloadRows(at: [IndexPath(row: Setting.connectionStatus.rawValue, section: 0)], with: .none)
// refresh row with connection timestamp
tableView.reloadRows(at: [IndexPath(row: Setting.connectOrDisconnectTimeStamp.rawValue, section: 0)], with: .none)
}
func deviceDidUpdateBluetoothState(state: CBManagerState, bluetoothTransmitter: BluetoothTransmitter) {
@ -1000,6 +1038,9 @@ extension BluetoothPeripheralViewController: BluetoothTransmitterDelegate {
// when bluetooth status changes to powered off, the device, if connected, will disconnect, however didDisConnect doesn't get call (looks like an error in iOS) - so let's reload the cell that shows the connection status, this will refresh the cell
// do this whenever the bluetooth status changes
tableView.reloadRows(at: [IndexPath(row: Setting.connectionStatus.rawValue, section: 0)], with: .none)
// same explanation for connection timestamp
tableView.reloadRows(at: [IndexPath(row: Setting.connectOrDisconnectTimeStamp.rawValue, section: 0)], with: .none)
}

View File

@ -407,7 +407,11 @@ class M5StackBluetoothPeripheralViewModel {
case .batteryLevel:
cell.textLabel?.text = Texts_BluetoothPeripheralsView.batteryLevel
cell.detailTextLabel?.text = m5Stack.batteryLevel.description
if m5Stack.batteryLevel > 0 {
cell.detailTextLabel?.text = m5Stack.batteryLevel.description
} else {
cell.detailTextLabel?.text = ""
}
cell.accessoryType = .none
case .powerOff:
@ -502,7 +506,7 @@ extension M5StackBluetoothPeripheralViewModel: M5StackBluetoothTransmitterDelega
if !success, let m5StackPeripheral = bluetoothPeripheralManager?.getBluetoothPeripheral(for: m5StackBluetoothTransmitter) as? M5Stack {
// show warning, inform that user should set password or reset M5Stack
let alert = UIAlertController(title: Texts_Common.warning, message: Texts_M5StackView.authenticationFailureWarning + " " + Texts_BluetoothPeripheralView.alwaysConnect, actionHandler: {
let alert = UIAlertController(title: Texts_Common.warning, message: Texts_M5StackView.authenticationFailureWarning + " " + Texts_BluetoothPeripheralView.connect, actionHandler: {
// by the time user clicks 'ok', the M5stack will be disconnected by the BluetoothPeripheralManager (see authentication in BluetoothPeripheralManager)
self.bluetoothPeripheralViewController?.setShouldConnectToFalse(for: m5StackPeripheral)
@ -521,7 +525,7 @@ extension M5StackBluetoothPeripheralViewModel: M5StackBluetoothTransmitterDelega
guard let m5StackPeripheral = bluetoothPeripheralManager?.getBluetoothPeripheral(for: m5StackBluetoothTransmitter) as? M5Stack else {return}
// show warning, inform that user should set password
let alert = UIAlertController(title: Texts_Common.warning, message: Texts_M5StackView.authenticationFailureWarning + " " + Texts_BluetoothPeripheralView.alwaysConnect, actionHandler: {
let alert = UIAlertController(title: Texts_Common.warning, message: Texts_M5StackView.authenticationFailureWarning + " " + Texts_BluetoothPeripheralView.connect, actionHandler: {
// by the time user clicks 'ok', the M5stack will be disconnected by the BluetoothPeripheralManager (see authentication in BluetoothPeripheralManager)
self.bluetoothPeripheralViewController?.setShouldConnectToFalse(for: m5StackPeripheral)
@ -540,7 +544,7 @@ extension M5StackBluetoothPeripheralViewModel: M5StackBluetoothTransmitterDelega
guard let m5StackBluetoothPeripheral = bluetoothPeripheralManager?.getBluetoothPeripheral(for: m5StackBluetoothTransmitter) as? M5Stack else {return}
// show warning, inform that user should reset M5Stack
let alert = UIAlertController(title: Texts_Common.warning, message: Texts_M5StackView.m5StackResetRequiredWarning + " " + Texts_BluetoothPeripheralView.alwaysConnect, actionHandler: {
let alert = UIAlertController(title: Texts_Common.warning, message: Texts_M5StackView.m5StackResetRequiredWarning + " " + Texts_BluetoothPeripheralView.connect, actionHandler: {
// by the time user clicks 'ok', the M5stack will be disconnected by the BluetoothPeripheralManager (see authentication in BluetoothPeripheralManager)
self.bluetoothPeripheralViewController?.setShouldConnectToFalse(for: m5StackBluetoothPeripheral)
@ -567,9 +571,9 @@ extension M5StackBluetoothPeripheralViewModel: BluetoothPeripheralViewModel {
}
func numberOfSettings(inSection section:Int) -> Int {
switch section {
case 1:
case 1://starts at 1 since oopweb is not enabled for M5Stack
return CommonM5Setting.allCases.count
case 2:
return SpecificM5StackSettings.allCases.count

View File

@ -375,10 +375,10 @@ extension BluetoothPeripheralsViewController: BluetoothTransmitterDelegate {
bluetoothPeripheralManager?.didConnectTo(bluetoothTransmitter: bluetoothTransmitter)
// unwrap bluetoothPeripheralManager
guard let bluetoothPeripheralManager = bluetoothPeripheralManager else {return}
guard let bluetoothPeripheralManager = bluetoothPeripheralManager, let bluetoothPeripheral = bluetoothPeripheralManager.getBluetoothPeripheral(for: bluetoothTransmitter) else {return}
// row with connection status in the view must be updated
updateRow(for: bluetoothPeripheralManager.getBluetoothPeripheral(for: bluetoothTransmitter))
updateRow(for: bluetoothPeripheral)
}
@ -388,10 +388,10 @@ extension BluetoothPeripheralsViewController: BluetoothTransmitterDelegate {
bluetoothPeripheralManager?.didDisconnectFrom(bluetoothTransmitter: bluetoothTransmitter)
// unwrap bluetoothPeripheralManager
guard let bluetoothPeripheralManager = bluetoothPeripheralManager else {return}
guard let bluetoothPeripheralManager = bluetoothPeripheralManager, let bluetoothPeripheral = bluetoothPeripheralManager.getBluetoothPeripheral(for: bluetoothTransmitter) else {return}
// row with connection status in the view must be updated
updateRow(for: bluetoothPeripheralManager.getBluetoothPeripheral(for: bluetoothTransmitter))
updateRow(for: bluetoothPeripheral)
}
@ -401,11 +401,11 @@ extension BluetoothPeripheralsViewController: BluetoothTransmitterDelegate {
bluetoothPeripheralManager?.deviceDidUpdateBluetoothState(state: state, bluetoothTransmitter: bluetoothTransmitter)
// unwrap bluetoothPeripheralManager
guard let bluetoothPeripheralManager = bluetoothPeripheralManager else {return}
guard let bluetoothPeripheralManager = bluetoothPeripheralManager, let bluetoothPeripheral = bluetoothPeripheralManager.getBluetoothPeripheral(for: bluetoothTransmitter) else {return}
// when bluetooth status changes to powered off, the device, if connected, will disconnect, however didDisConnect doesn't get call (looks like an error in iOS) - so let's reload the cell that shows the connection status, this will refresh the cell
if state == CBManagerState.poweredOff {
updateRow(for: bluetoothPeripheralManager.getBluetoothPeripheral(for: bluetoothTransmitter))
updateRow(for: bluetoothPeripheral)
}
}