react-native-mytatva-rn-sdk 1.2.21 → 1.2.22

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -117,8 +117,14 @@ RCT_EXPORT_METHOD(reconnectCgmTracky:(NSString *)token)
117
117
  [reconnectVC setValue:@(YES) forKey:@"isForReconnect"];
118
118
  }
119
119
  // Present it directly without navigation
120
+ // if (reconnectVC) {
121
+ // [rootVC presentViewController:reconnectVC animated:YES completion:nil];
122
+ // }
123
+
124
+ UINavigationController *navController = [[UINavigationController alloc] initWithRootViewController:reconnectVC];
125
+ navController.modalPresentationStyle = UIModalPresentationOverFullScreen;
120
126
  if (reconnectVC) {
121
- [rootVC presentViewController:reconnectVC animated:YES completion:nil];
127
+ [rootVC presentViewController:navController animated:YES completion:nil];
122
128
  }
123
129
  });
124
130
  }
@@ -278,9 +278,10 @@ class API {
278
278
 
279
279
  if self.isCurrentDateInRange(startDate: startDateStr, endDate: endDateStr) {
280
280
  print("Current date is in range")
281
- if KLTBluetoothManager.shared().currentDevice.initialEndDate != nil {
282
- self.sendStatus(status: .transmitterDisconnect)
283
- }
281
+
282
+ //if KLTBluetoothManager.shared().currentDevice.initialEndDate != nil {
283
+ //self.sendStatus(status: .transmitterDisconnect)
284
+ // }
284
285
  }
285
286
  }
286
287
  }
@@ -18,6 +18,7 @@ class EnumDebouncer<T: Equatable> {
18
18
  func update(with newValue: T) {
19
19
  if storedValue == nil || storedValue != newValue {
20
20
  reset(newValue: newValue)
21
+ onDebounceSuccess?(newValue)
21
22
  } else if let startTime = startTime {
22
23
  let elapsed = Date().timeIntervalSince(startTime)
23
24
  if elapsed >= debounceInterval {
@@ -36,14 +36,15 @@ class ConnectToSensorViewController: UIViewController {
36
36
  case image
37
37
  case watchVideo
38
38
  }
39
-
39
+
40
40
  enum enumScreenType {
41
41
  case camera
42
42
  case success
43
43
  case error
44
44
  }
45
-
46
- var connectedTime: Date?
45
+
46
+ var isFromReconnect: Bool = false
47
+ var connectedTime: Date?
47
48
  var connected:(()->())?
48
49
  var screenType: enumScreenType = .camera
49
50
  var isCodeDetected = false
@@ -58,7 +59,7 @@ class ConnectToSensorViewController: UIViewController {
58
59
 
59
60
  func setupLayout() {
60
61
  manager?.addObserver(self, forKeyPath: "status", options: [.new], context: nil)
61
-
62
+
62
63
 
63
64
  tableView.delegate = self
64
65
  tableView.dataSource = self
@@ -87,7 +88,7 @@ class ConnectToSensorViewController: UIViewController {
87
88
  let vc = PutOnTheSensorViewController.instantiate(fromStoryboard: Enum_stroyboard.Main.rawValue)
88
89
  self.navigationController?.pushViewController(vc, animated: false)
89
90
  }
90
-
91
+
91
92
  customTopView.onCloseTapped = {
92
93
  let vc = ExitJourneyViewController.instantiate(fromStoryboard: Enum_stroyboard.Main.rawValue)
93
94
  vc.modalPresentationStyle = .overFullScreen
@@ -103,7 +104,7 @@ class ConnectToSensorViewController: UIViewController {
103
104
 
104
105
  func checkCameraPermission() {
105
106
  let status = AVCaptureDevice.authorizationStatus(for: .video)
106
-
107
+
107
108
  switch status {
108
109
  case .authorized:
109
110
  self.isPermissionGiven = true
@@ -146,7 +147,7 @@ class ConnectToSensorViewController: UIViewController {
146
147
  UIApplication.shared.open(settingsURL)
147
148
  }
148
149
  })
149
-
150
+
150
151
  DispatchQueue.main.async {
151
152
  self.present(alert, animated: true)
152
153
  }
@@ -155,10 +156,10 @@ class ConnectToSensorViewController: UIViewController {
155
156
  func connectSensor(value: String, controller: ConnectToSensorViewController) {
156
157
  UserDefaults.standard.set(value, forKey: "sensorId")
157
158
  var isMatch = false
158
-
159
+
159
160
  var regex = #"^[A-Z0-9][0-9](0[1-9]|[1-9][0-9]|[A-Z][1-9A-Z])(00[1-9]|0[1-9][0-9]|[1-9][0-9][0-9]){2}[0-9]{4,5}[0-9A-Z]{3}$"#
160
161
  var predicate = NSPredicate(format: "SELF MATCHES %@", regex)
161
-
162
+
162
163
  if predicate.evaluate(with: value) {
163
164
  isMatch = true
164
165
  } else {
@@ -168,10 +169,10 @@ class ConnectToSensorViewController: UIViewController {
168
169
  isMatch = true
169
170
  }
170
171
  }
171
-
172
+
172
173
  if isMatch {
173
174
  let data = AlgorithmTools.decodeCT(value)
174
-
175
+
175
176
  if data.k > 0 || data.r > 0 {
176
177
  //KLTLocalSettingManager.shareInstance.deviceInfoSensor = value
177
178
  UserDefaults.standard.set(data.k, forKey: "algo_k")
@@ -184,17 +185,17 @@ class ConnectToSensorViewController: UIViewController {
184
185
  return
185
186
  }
186
187
  }
187
-
188
+
188
189
  //controller.resumeScanning()
189
190
  }
190
191
  func connectThisSensor() {
191
192
  // Connect the transmitter
192
193
  manager?.connectPeripheral(manager?.readyToConnectedPeripheral)
193
194
  }
194
-
195
+
195
196
  func showConfirmInsulinUser() {
196
197
  let typeOfDiabetes = UserDefaults.standard.object(forKey: "profilePatientType") as? NSNumber
197
-
198
+
198
199
  if let diabetesType = typeOfDiabetes {
199
200
  // LocalizedString(@"user_diabete_no") index is 0
200
201
  if diabetesType.intValue == 0 {
@@ -208,9 +209,9 @@ class ConnectToSensorViewController: UIViewController {
208
209
  // Not selected
209
210
  UserDefaults.standard.set(0, forKey: "algo_user_type")
210
211
  }
211
-
212
+
212
213
  UserDefaults.standard.synchronize() // Optional, rarely needed in modern iOS
213
-
214
+
214
215
  connectThisSensor()
215
216
  }
216
217
  override func observeValue(forKeyPath keyPath: String?,
@@ -221,16 +222,27 @@ class ConnectToSensorViewController: UIViewController {
221
222
  if let newValue = change?[.newKey] as? Int {
222
223
  //let btStatus = newValue
223
224
  let btStatus: BluetoothManagerStatus = BluetoothManagerStatus(rawValue: newValue) ?? .scanStart
224
-
225
+
225
226
  if btStatus == .initialStart {
226
- self.connectedTime = Date()
227
+ self.connectedTime = Date()
227
228
  print("Success")
228
229
  screenType = .success
229
230
  tableView.reloadData()
230
231
  bottomButton.enable()
232
+ if self.isFromReconnect {
233
+ let _ = FinalViewModelManager.shared
234
+ NotificationCenter.default.post(name: Notification.Name("cgmDeviceEvent"), object: nil, userInfo: ["a":"a"])
235
+ if let rootVC = UIApplication.shared.connectedScenes
236
+ .compactMap({ ($0 as? UIWindowScene)?.windows.first?.rootViewController })
237
+ .first {
238
+ rootVC.dismiss(animated: true, completion: nil)
239
+ } else if let rootViewController = UIApplication.shared.keyWindow?.rootViewController {
240
+ rootViewController.dismiss(animated: true, completion: nil)
241
+ }
242
+ }
231
243
  } else if btStatus == .closed || btStatus == .modifyVoltageFailed {
232
244
  // Handle failed or closed status
233
-
245
+
234
246
  navigationController?.popToRootViewController(animated: true)
235
247
  }
236
248
  }
@@ -238,7 +250,7 @@ class ConnectToSensorViewController: UIViewController {
238
250
  if let playerItem = object as? AVPlayerItem {
239
251
  if playerItem.status == .readyToPlay {
240
252
  if UserDefaults.standard.integer(forKey: "bgmode") == 0 {
241
- // player?.play()
253
+ // player?.play()
242
254
  }
243
255
  }
244
256
  }
@@ -246,7 +258,7 @@ class ConnectToSensorViewController: UIViewController {
246
258
  super.observeValue(forKeyPath: keyPath, of: object, change: change, context: context)
247
259
  }
248
260
  }
249
-
261
+
250
262
  }
251
263
 
252
264
  extension ConnectToSensorViewController: UITableViewDelegate, UITableViewDataSource {
@@ -330,24 +342,24 @@ extension ConnectToSensorViewController: UITableViewDelegate, UITableViewDataSou
330
342
  return cell
331
343
  }
332
344
  case .success:
333
- switch enumSuccessTableRow(rawValue: indexPath.row)! {
334
- case .success:
335
- let cell: ConnectSuccessTVC = tableView.dequeueReusableCell(for: indexPath)
336
- let dateFormatter = DateFormatter()
337
- dateFormatter.dateFormat = "dd-MM-yyyy hh:mm a"
338
- dateFormatter.timeZone = TimeZone.current
339
- if let connectedTime = connectedTime {
340
- // Convert the Date to a String
341
- let dateString = dateFormatter.string(from: connectedTime)
342
- cell.labelDate.text = "Connected on \(String(describing: dateString))"
343
- } else {
344
- cell.labelDate.text = ""
345
+ switch enumSuccessTableRow(rawValue: indexPath.row)! {
346
+ case .success:
347
+ let cell: ConnectSuccessTVC = tableView.dequeueReusableCell(for: indexPath)
348
+ let dateFormatter = DateFormatter()
349
+ dateFormatter.dateFormat = "dd-MM-yyyy hh:mm a"
350
+ dateFormatter.timeZone = TimeZone.current
351
+ if let connectedTime = connectedTime {
352
+ // Convert the Date to a String
353
+ let dateString = dateFormatter.string(from: connectedTime)
354
+ cell.labelDate.text = "Connected on \(String(describing: dateString))"
355
+ } else {
356
+ cell.labelDate.text = ""
357
+ }
358
+ cell.labelDesc.isHidden = true
359
+ cell.labelTitle.text = "Sensor Connected Successfully"
360
+ cell.setImageForCGM()
361
+ return cell
345
362
  }
346
- cell.labelDesc.isHidden = true
347
- cell.labelTitle.text = "Sensor Connected Successfully"
348
- cell.setImageForCGM()
349
- return cell
350
- }
351
363
  case .error:
352
364
  switch enumFailureTableRow(rawValue: indexPath.row)! {
353
365
  case .failAnimation:
@@ -95,14 +95,20 @@ class ConnectToTransmitterViewController: UIViewController, KLTBluetoothDelegate
95
95
  }
96
96
  bottomButton.buttonTapCallback = {
97
97
  if self.isForReconnect {
98
- NotificationCenter.default.post(name: Notification.Name("cgmDeviceEvent"), object: nil, userInfo: ["a":"a"])
99
- if let rootVC = UIApplication.shared.connectedScenes
100
- .compactMap({ ($0 as? UIWindowScene)?.windows.first?.rootViewController })
101
- .first {
102
- rootVC.dismiss(animated: true, completion: nil)
103
- } else if let rootViewController = UIApplication.shared.keyWindow?.rootViewController {
104
- rootViewController.dismiss(animated: true, completion: nil)
98
+ let vc = ConnectToSensorViewController.instantiate(fromStoryboard: Enum_stroyboard.Main.rawValue)
99
+ vc.connected = {
100
+ //self.showConfirmInsulinUser()
105
101
  }
102
+ vc.isFromReconnect = true
103
+ self.navigationController?.pushViewController(vc, animated: false)
104
+ // NotificationCenter.default.post(name: Notification.Name("cgmDeviceEvent"), object: nil, userInfo: ["a":"a"])
105
+ // if let rootVC = UIApplication.shared.connectedScenes
106
+ // .compactMap({ ($0 as? UIWindowScene)?.windows.first?.rootViewController })
107
+ // .first {
108
+ // rootVC.dismiss(animated: true, completion: nil)
109
+ // } else if let rootViewController = UIApplication.shared.keyWindow?.rootViewController {
110
+ // rootViewController.dismiss(animated: true, completion: nil)
111
+ // }
106
112
  } else {
107
113
  if self.screenType == .error {
108
114
  self.bottomButton.disable()
@@ -130,9 +136,9 @@ class ConnectToTransmitterViewController: UIViewController, KLTBluetoothDelegate
130
136
  }
131
137
 
132
138
  if isForReconnect {
133
- customTopView.showOnlyClose()
134
- customStepProgressBar.isHidden = true
135
- customStepProgressHeightConstraint.constant = 0
139
+ //customTopView.showOnlyClose()
140
+ //customStepProgressBar.isHidden = true
141
+ //customStepProgressHeightConstraint.constant = 0
136
142
  bottomButton.labelText = "Complete"
137
143
  bottomButton.showRightArrow()
138
144
 
@@ -176,6 +182,20 @@ class ConnectToTransmitterViewController: UIViewController, KLTBluetoothDelegate
176
182
  super.observeValue(forKeyPath: keyPath, of: object, change: change, context: context)
177
183
  }
178
184
  }
185
+
186
+ func sensorForceEnd() {
187
+ if let manager = manager {
188
+ if ((manager.connectedPeripheral) != nil) {
189
+ if (manager.status == .resendEnd || manager.status == .getGLU || manager.status == .initialStart) {
190
+ manager.closeBleSensor()
191
+ }
192
+ } else {
193
+ if (manager.currentDevice != nil) {
194
+ manager.forceEndBleSensor()
195
+ }
196
+ }
197
+ }
198
+ }
179
199
  }
180
200
 
181
201
  extension ConnectToTransmitterViewController: UITableViewDelegate, UITableViewDataSource {
@@ -270,22 +290,27 @@ extension ConnectToTransmitterViewController: UITableViewDelegate, UITableViewDa
270
290
 
271
291
  //cell.labelDesc.text = "Sno:\(devices[indexPath.row].name)"
272
292
  cell.button.buttonTapCallback = {
293
+ if self.isForReconnect {
294
+ self.sensorForceEnd()
295
+ }
296
+
273
297
  if !KLTLocalSettingManager.shareInstance().canConnectOtherDevice {
274
298
  return
275
299
  }
276
300
 
277
301
  self.manager?.stopScan()
278
-
279
- let peripheral = self.foundDevices[indexPath.row] as! CBPeripheral
280
- if let device = KLTDatabaseHandler.shared().queryDevice(withId: peripheral.identifier.uuidString) {
281
- //let snLocalName = device.advertise?.localName?.trimmingCharacters(in: .whitespacesAndNewlines)
282
- self.connectedTime = Date()
283
- print("Connected device", device)
284
- self.manager?.readyToConnectedPeripheral = peripheral
285
- self.screenType = .success
286
- API.shared.sendStatus(status: .connected)
287
- self.bottomButton.enable()
288
- tableView.reloadData()
302
+ if self.foundDevices.count > indexPath.row {
303
+ let peripheral = self.foundDevices[indexPath.row] as! CBPeripheral
304
+ if let device = KLTDatabaseHandler.shared().queryDevice(withId: peripheral.identifier.uuidString) {
305
+ //let snLocalName = device.advertise?.localName?.trimmingCharacters(in: .whitespacesAndNewlines)
306
+ self.connectedTime = Date()
307
+ print("Connected device", device)
308
+ self.manager?.readyToConnectedPeripheral = peripheral
309
+ self.screenType = .success
310
+ //API.shared.sendStatus(status: .connected)
311
+ self.bottomButton.enable()
312
+ tableView.reloadData()
313
+ }
289
314
  }
290
315
  }
291
316
  return cell
@@ -340,31 +365,3 @@ extension ConnectToTransmitterViewController: UITableViewDelegate, UITableViewDa
340
365
  }
341
366
 
342
367
  }
343
-
344
- extension ConnectToTransmitterViewController: BluetoothManagerDelegate {
345
- func didDiscoverDevice(_ device: CBPeripheral) {
346
- DispatchQueue.main.async {
347
- self.devices = BluetoothManager.shared.discoveredDevices
348
- self.screenType = .listOfDevice
349
- self.tableView.reloadData()
350
- }
351
- }
352
-
353
- func didConnectDevice(_ device: CBPeripheral) {
354
- DispatchQueue.main.async {
355
- self.screenType = .success
356
- self.tableView.reloadData()
357
- }
358
- }
359
-
360
- func didFailToConnect(_ device: CBPeripheral, error: Error?) {
361
- DispatchQueue.main.async {
362
- self.screenType = .error
363
- self.tableView.reloadData()
364
- }
365
- }
366
-
367
- func didDisconnectDevice(_ device: CBPeripheral, error: Error?) {
368
- print("Disconnected from device: \(device.name ?? "Unknown")")
369
- }
370
- }
@@ -48,7 +48,7 @@ class FinalViewModel: NSObject {
48
48
  manager.startScan()
49
49
  } else {
50
50
  debouncer.update(with: .connected)
51
- API.shared.sendStatus(status: .connected)
51
+ //API.shared.sendStatus(status: .connected)
52
52
  }
53
53
  }
54
54
  func startCountDown() {
@@ -147,14 +147,18 @@ class FinalViewModel: NSObject {
147
147
 
148
148
  let errorCode = ErrorCode(rawValue: Int32(receiveData.error?.intValue ?? 0))
149
149
  if errorCode == ErrorCode.ERROR_CODE_FLOODING_WATER {
150
- API.shared.sendStatus(status: .moistureDetect)
150
+ debouncer.update(with: CGMConnectionStatus.moistureDetect)
151
+ //API.shared.sendStatus(status: .moistureDetect)
151
152
  } else if errorCode == ErrorCode.ERROR_CODE_CURRENT_SMALL || errorCode == ErrorCode.ERROR_CODE_NOISE || errorCode == ErrorCode.ERROR_CODE_SENSITIVITY_ATTENUATION {
152
- API.shared.sendStatus(status: .weakSignal)
153
+ debouncer.update(with: CGMConnectionStatus.weakSignal)
154
+ //API.shared.sendStatus(status: .weakSignal)
153
155
  } else if errorCode != ErrorCode.ERROR_CODE_NONE {
154
- API.shared.sendStatus(status: .errorCommon)
156
+ debouncer.update(with: CGMConnectionStatus.errorCommon)
157
+ //API.shared.sendStatus(status: .errorCommon)
155
158
  }
156
159
  if receiveData.countdownDays == 0 && receiveData.countdownHours == 0 && receiveData.countdownMinutes == 0 {
157
- API.shared.sendStatus(status: .expired)
160
+ debouncer.update(with: CGMConnectionStatus.expired)
161
+ //API.shared.sendStatus(status: .expired)
158
162
  }
159
163
  }
160
164
 
@@ -190,7 +194,8 @@ class FinalViewModel: NSObject {
190
194
  @objc func bluetoothEnable(_ notification: Notification) {
191
195
  if let isBluetoothEnabled = notification.object as? Bool {
192
196
  if !isBluetoothEnabled {
193
- API.shared.sendStatus(status: .bluetoothOff)
197
+ debouncer.update(with: CGMConnectionStatus.bluetoothOff)
198
+ //API.shared.sendStatus(status: .bluetoothOff)
194
199
  }
195
200
  }
196
201
  if ((manager.connectedPeripheral == nil) && !KLTLocalSettingManager.shareInstance().canConnectOtherDevice) {
@@ -244,17 +249,17 @@ class FinalViewModel: NSObject {
244
249
  manager.startScan()
245
250
  }
246
251
  }
247
- API.shared.sendStatus(status: .disconnected)
252
+ //API.shared.sendStatus(status: .disconnected)
248
253
  print("===>device is disconnected")
249
- debouncer.update(with: CGMConnectionStatus.connected)
254
+ debouncer.update(with: CGMConnectionStatus.disconnected)
250
255
  case .connected:
251
256
  if let timer = startScanTimer {
252
257
  timer.invalidate()
253
258
  startScanTimer = nil
254
259
  }
255
- API.shared.sendStatus(status: .connected)
260
+ //API.shared.sendStatus(status: .connected)
256
261
  print("===>device is connected")
257
- debouncer.update(with: CGMConnectionStatus.disconnected)
262
+ debouncer.update(with: CGMConnectionStatus.connected)
258
263
  case .timeOut:
259
264
  if !KLTLocalSettingManager.shareInstance().canConnectOtherDevice {
260
265
  startScanTimer = Timer.scheduledTimer(timeInterval: 20,
@@ -271,7 +276,8 @@ class FinalViewModel: NSObject {
271
276
  //KLTLaunchConfiguration.sharedManager.bindSuccessRootViewController()
272
277
  print("Success done")
273
278
  case .closed:
274
- API.shared.sendStatus(status: .transmitterDisconnectBox)
279
+ debouncer.update(with: CGMConnectionStatus.transmitterDisconnectBox)
280
+ //API.shared.sendStatus(status: .transmitterDisconnectBox)
275
281
  default:
276
282
  break
277
283
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-native-mytatva-rn-sdk",
3
- "version": "1.2.21",
3
+ "version": "1.2.22",
4
4
  "description": "a package to inject data into visit health pwa",
5
5
  "main": "lib/commonjs/index",
6
6
  "module": "lib/module/index",
@@ -1,472 +0,0 @@
1
- //
2
- // BluetoothManager.swift
3
- // MyTatvaCare
4
- //
5
- // Created by Nirav Ramani on 12/05/25.
6
- //
7
-
8
- import CoreBluetooth
9
-
10
- protocol BluetoothManagerDelegate: AnyObject {
11
- func didDiscoverDevice(_ device: CBPeripheral)
12
- func didConnectDevice(_ device: CBPeripheral)
13
- func didFailToConnect(_ device: CBPeripheral, error: Error?)
14
- func didDisconnectDevice(_ device: CBPeripheral, error: Error?)
15
- }
16
-
17
- class BluetoothManager: NSObject {
18
-
19
- static let shared = BluetoothManager()
20
-
21
- private(set) var centralManager: CBCentralManager!
22
- private(set) var discoveredDevices: [(CBPeripheral,String)] = []
23
- private(set) var peripherals: [CBPeripheral] = []
24
-
25
- private var connectedPeripheral: CBPeripheral?
26
- private var connectedDeviceName: String = ""
27
-
28
- weak var delegate: BluetoothManagerDelegate?
29
-
30
- var writeReadCharacteristic: CBCharacteristic?
31
- var notifyCharacteristic: CBCharacteristic?
32
- var eDevice: EDevice?
33
- private override init() {
34
- super.init()
35
- centralManager = CBCentralManager(delegate: self, queue: nil)
36
- }
37
-
38
- func startScanning() {
39
- discoveredDevices.removeAll()
40
- centralManager.scanForPeripherals(withServices: nil, options: nil)
41
- print("Started scanning for peripherals...")
42
- }
43
-
44
- func stopScanning() {
45
- centralManager.stopScan()
46
- print("Stopped scanning.")
47
- }
48
-
49
- func connect(to peripheral: CBPeripheral, name: String) {
50
- centralManager.connect(peripheral, options: nil)
51
- peripheral.delegate = self
52
- connectedPeripheral = peripheral
53
- connectedDeviceName = name
54
- }
55
-
56
- func disconnect() {
57
- if let peripheral = connectedPeripheral {
58
- centralManager.cancelPeripheralConnection(peripheral)
59
- }
60
- }
61
-
62
- func requestResendCT3() {
63
- if let eDevice = eDevice,
64
- let writeReadCharacteristic = writeReadCharacteristic {
65
- if let value = ProtocalTools.check_request(eDevice) {
66
- connectedPeripheral?.writeValue(value,
67
- for: writeReadCharacteristic,
68
- type: .withoutResponse)
69
- }
70
- }
71
- /*guard let currentDevice = currentDevice else { return }
72
-
73
- if KLTLocalSettingManager.shareInstance.canConnectOtherDevice {
74
- if let eDevice = eDevice,
75
- let writeReadCharacteristic = writeReadCharacteristic {
76
- if let value = ProtocalTools.check_request(eDevice) {
77
- connectedPeripheral?.writeValue(value,
78
- for: writeReadCharacteristic,
79
- type: .withoutResponse)
80
- }
81
- }
82
- } else {
83
- let maxGlucoseId = KLTDatabaseHandler.shared()
84
- .getLatestAndMaxGlucoseId(of: currentDevice)
85
- pullGlucouseSeriesRequest(glucoseId: maxGlucoseId)
86
- }*/
87
- }
88
-
89
- }
90
-
91
- // MARK: - CBCentralManagerDelegate
92
-
93
- extension BluetoothManager: CBCentralManagerDelegate {
94
- func centralManagerDidUpdateState(_ central: CBCentralManager) {
95
- if central.state == .poweredOn {
96
- startScanning()
97
- } else {
98
- print("Central Manager State: \(central.state.rawValue)")
99
- }
100
- }
101
-
102
- func centralManager(_ central: CBCentralManager, didDiscover peripheral: CBPeripheral,
103
- advertisementData: [String : Any], rssi RSSI: NSNumber) {
104
- print("Discovered: \(peripheral.name ?? "Unknown") - RSSI: \(RSSI)",advertisementData["kCBAdvDataLocalName"])
105
- guard let name = advertisementData["kCBAdvDataLocalName"] as? String, name.hasPrefix("SN") else { return }
106
- if !discoveredDevices.contains(where: { $0.0 == peripheral }) {
107
- discoveredDevices.append((peripheral,name))
108
- print("advertisementData-kCBAdvDataLocalName",advertisementData["kCBAdvDataLocalName"])
109
- eDevice = EDevice.getEnumDevice(advertisementData["kCBAdvDataLocalName"] as? String ?? "")
110
-
111
- delegate?.didDiscoverDevice(peripheral)
112
- }
113
- }
114
-
115
- func centralManager(_ central: CBCentralManager, didConnect peripheral: CBPeripheral) {
116
- print("Connected to: \(peripheral.name ?? "Unknown")")
117
- delegate?.didConnectDevice(peripheral)
118
- peripheral.delegate = self
119
- if let eDevice = eDevice {
120
- peripheral.discoverServices([CBUUID(string: eDevice.eGattMessage.uuid_SERVICE)])
121
- }
122
- }
123
-
124
- func centralManager(_ central: CBCentralManager, didFailToConnect peripheral: CBPeripheral, error: Error?) {
125
- print("Failed to connect: \(error?.localizedDescription ?? "Unknown error")")
126
- delegate?.didFailToConnect(peripheral, error: error)
127
- }
128
-
129
- func centralManager(_ central: CBCentralManager, didDisconnectPeripheral peripheral: CBPeripheral, error: Error?) {
130
- print("Disconnected from: \(peripheral.name ?? "Unknown")")
131
- delegate?.didDisconnectDevice(peripheral, error: error)
132
- }
133
- }
134
-
135
- // MARK: - CBPeripheralDelegate
136
-
137
- extension BluetoothManager: CBPeripheralDelegate {
138
- func peripheral(_ peripheral: CBPeripheral, didDiscoverServices error: Error?) {
139
- if let error = error {
140
- print("Service discovery failed: \(error.localizedDescription)")
141
- return
142
- }
143
- guard let services = peripheral.services else { return }
144
- for service in services {
145
- print("Discovered service: \(service.uuid)")
146
- peripheral.discoverCharacteristics(nil, for: service)
147
- }
148
- }
149
-
150
- func peripheral(_ peripheral: CBPeripheral, didDiscoverCharacteristicsFor service: CBService, error: Error?) {
151
- if let error = error {
152
- print("Characteristic discovery failed: \(error.localizedDescription)")
153
- return
154
- }
155
- service.characteristics?.forEach {
156
- print("Discovered characteristic: \($0.uuid)")
157
- }
158
- guard let characteristics = service.characteristics else { return }
159
-
160
- for characteristic in characteristics {
161
- /*if characteristic.properties.contains(.notify) {
162
- peripheral.setNotifyValue(true, for: characteristic)
163
- }
164
-
165
- if characteristic.properties.contains(.read) {
166
- peripheral.readValue(for: characteristic)
167
- }*/
168
- guard let eDevice = eDevice else { return }
169
- if characteristic.uuid == CBUUID(string: eDevice.eGattMessage.uuid_WRITE) {
170
- writeReadCharacteristic = characteristic
171
- if eDevice.deviceType == "CT4" {
172
- // CT3 / CT4 handle first bind & reconnect logic
173
- requestResendCT3()
174
- }
175
- }
176
-
177
- if characteristic.uuid == CBUUID(string: eDevice.eGattMessage.uuid_READ) {
178
- notifyCharacteristic = characteristic
179
- peripheral.setNotifyValue(true, for: characteristic)
180
- }
181
- }
182
- }
183
-
184
- func peripheral(_ peripheral: CBPeripheral, didUpdateValueFor characteristic: CBCharacteristic, error: Error?) {
185
- guard error == nil else { return }
186
- //handleResendDataWithPrefix22(characteristic.value!)
187
-
188
- guard let eDevice = eDevice else { return }
189
- if characteristic.uuid == CBUUID(string: eDevice.eGattMessage.uuid_READ) {
190
- guard let value = characteristic.value, !value.isEmpty else { return }
191
-
192
- let hex = KLTFormat.dataToHexString(value, isReverse: false)
193
- let command = String(hex.prefix(2))
194
-
195
- switch command {
196
- case "05":
197
- // CT3/CT4 self-check protocol response (only checks voltage >= 3.9)
198
- let ret: HW_CHECK_RET = ProtocalTools.check_response(value, andEDevice: eDevice)
199
-
200
- switch ret {
201
- case .SUCCESS:
202
- //KLTDatabaseHandler.shared.updateDevice(currentDevice, initialBeginDate: nil, endDate: nil)
203
- if let writeReadCharacteristic = writeReadCharacteristic {
204
- if let data = ProtocalTools.setDate_request(eDevice) {
205
- peripheral.writeValue(data, for: writeReadCharacteristic, type: .withoutResponse)
206
- }
207
- }
208
- case .FAIL_POWER:
209
- //NotificationCenter.default.post(name: Notification.Name(KLTAlertSelfCheckFailedNotify), object: ret.rawValue)
210
- resetBleSensorData()
211
-
212
- case .FAIL:
213
- //status = .closed
214
- resetBleSensorData()
215
- default:
216
- break
217
- }
218
-
219
- case "22":
220
- // CT4 retransmitted data, response for pullGlucose_series_request
221
- handleResendDataWithPrefix22(value)
222
-
223
- case "03":
224
- //CT4 set time protocol response
225
- if ProtocalTools.setDate_response(value, andEDevice: eDevice) {
226
- if let writeReadCharacteristic = writeReadCharacteristic {
227
- if let data = ProtocalTools.start_init_request(eDevice) {
228
- connectedPeripheral?.writeValue(data, for: writeReadCharacteristic, type: .withoutResponse)
229
- }
230
- }
231
- } else {
232
- //status = .closed
233
- resetBleSensorData()
234
- }
235
- break
236
- case "06":
237
- // Initialization protocol response
238
- // if ProtocalTools.init_response(value, andEDevice: eDevice) {
239
- // KLTLocalSettingManager.shareInstance.canConnectOtherDevice = false
240
- //
241
- // let snLocalName = currentDevice.advertise.localName
242
- // let runLog = KLTAppDelegate.getCurrentKLTRunLog()
243
- // runLog.createNewCSV(snLocalName)
244
- //
245
- // status = .initialStart
246
- // isInResend = false
247
- //
248
- // let interval = Date().timeIntervalSinceReferenceDate + 180 * TimeInterval(eDevice.initNumber)
249
- // let newDate = Date(timeIntervalSinceReferenceDate: interval)
250
- // KLTDatabaseHandler.shared.updateDevice(currentDevice, initialBeginDate: Date().getWholeString(), endDate: newDate.getWholeString())
251
- //
252
- // dataType = .receiveDataBeforeSetUserReference
253
- //
254
- // let lowPowerData = ProtocalTools.lowPower_request(eDevice)
255
- // connectedPeripheral?.writeValue(lowPowerData, for: writeReadCharacteristic, type: .withoutResponse)
256
- //
257
- // let recordId = "\(snLocalName)_\(Int(Date().timeIntervalSince1970))"
258
- // UserDefaults.standard.set(recordId, forKey: "wearingRecordId")
259
- // UserDefaults.standard.synchronize()
260
- // } else {
261
- // status = .closed
262
- // resetBleSensorData()
263
- // }
264
- break
265
- case "07":
266
- // Data received every 3 minutes
267
- handleReceiveDataWithPrefix07(value)
268
-
269
- case "0A":
270
- // Unbind protocol response
271
- // let success = ProtocalTools.unBind_response(value, andEDevice: eDevice)
272
- // if success {
273
- // status = .closed
274
- // resetBleSensorData()
275
- // bluetoothDelegate?.onFindDevices(peripherals, connectedDevice: nil)
276
- // }
277
- break
278
- case "11":
279
- // Reset protocol response after retransmission
280
- // let resetData = ProtocalTools.reset_response2(value, andEDevice: eDevice)
281
- // if resetData.isBind {
282
- // let lowPowerData = ProtocalTools.lowPower_request(eDevice)
283
- // peripheral.writeValue(lowPowerData, for: writeReadCharacteristic, type: .withoutResponse)
284
- // } else {
285
- // status = .sensorLostPower
286
- // }
287
- break
288
- default:
289
- break
290
- }
291
- }
292
- }
293
-
294
- func peripheral(_ peripheral: CBPeripheral, didWriteValueFor characteristic: CBCharacteristic, error: (any Error)?) {
295
-
296
- }
297
-
298
- func peripheral(_ peripheral: CBPeripheral, didUpdateNotificationStateFor characteristic: CBCharacteristic, error: (any Error)?) {
299
- guard let eDevice = eDevice else { return }
300
- guard characteristic.uuid == CBUUID(string: eDevice.eGattMessage.uuid_READ) else {
301
- return
302
- }
303
-
304
- print(#function) // Equivalent to KLTLog(@"%s", __FUNCTION__)
305
-
306
- if !characteristic.isNotifying {
307
- centralManager?.cancelPeripheralConnection(peripheral)
308
- }
309
- }
310
- // CT3/CT4 每3分钟上来的数据
311
- func handleReceiveDataWithPrefix07(_ receiveData: Data) {
312
- /*if status == .resendStart || isInResend {
313
- // 重发数据期间不处理新收到的数据
314
- return
315
- }*/
316
-
317
- //let maxGlucoseId = KLTDatabaseHandler.shared().getLatestAndMaxGlucoseId(of: currentDevice)
318
- guard let gluData = ProtocalTools.getGlucose(receiveData, andEDevice: eDevice) else {
319
- return
320
- }
321
-
322
- handleReceiveDataWithPrefix07Glucose(gluData)
323
- /*if gluData.gluID == maxGlucoseId + 1 {
324
- handleReceiveDataWithPrefix07Glucose(gluData)
325
- } else if gluData.gluID > maxGlucoseId + 1 {
326
- // 如果拿到的数据大于下一条数据的gluID,证明需要重新拉取中间漏掉的数据(22拉取协议)
327
- pullGlucouseSeriesRequest(withGlucoseId: maxGlucoseId)
328
- }*/
329
- }
330
-
331
- func handleReceiveDataWithPrefix07Glucose(_ gluData: Glucose) {
332
- let glucoseId = gluData.gluID
333
- let operatingCurrent = gluData.iw
334
- let blankCurrent = gluData.ib
335
- let temperature = gluData.t
336
- print("glucoseId: \(glucoseId),operatingCurrent: \(operatingCurrent), blankCurrent: \(blankCurrent), temperature: \(temperature)")
337
- //sendCGMLog()
338
-
339
- let cgmLogs = CGMLog(timeInMillis: Double(Date().timeIntervalSince1970 * 1000),
340
- countdownMinutes: 42,
341
- countdownDays: 12,
342
- hypoglycemiaEarlyWarnMinutes: 8,
343
- showGlucoseMG: 140,
344
- glucoseId: Int(glucoseId),
345
- name: connectedDeviceName,
346
- bytes: [1,2,3],
347
- showGlucose: 5.67 ,
348
- Ib: blankCurrent,
349
- Iw: operatingCurrent,
350
- countdownHours: 15,
351
- T: temperature,
352
- year: gluData.year,
353
- month: gluData.month,
354
- day: gluData.day,
355
- hour: gluData.hour,
356
- minute: gluData.minute,
357
- trendObject: TrendObject(trendId: 11, drawableId: 2103818652, widgetImg: -1, apsChangeRate: "FLAT"),
358
- glucoseStatusObject: GlucoseStatusObject(statusId: 1),
359
- errorObject: ErrorObject(errorId: 1, sound: "None"))
360
- let payload = Payload(logs: [cgmLogs])
361
- API.shared.postCGMData(environment: .stage, data: payload) {
362
- print("Success")
363
- } onFailure: { error in
364
- print("Error")
365
- }
366
-
367
- /*let receive = handleCommonReceiveGluData(gluData, commandText: "07")
368
-
369
- NotificationCenter.default.post(name: Notification.Name("didReceiveNewData"), object: receive)
370
-
371
- handleCommonCT3GlucoseData(withReceiveData: receive)
372
-
373
- NotificationCenter.default.post(name: Notification.Name("DidHandleResendDataNoReload"), object: nil)
374
-
375
- let remainPoints = KLTDatabaseHandler.shared().numberOfLifeCycleSensor(
376
- withDevice: currentDevice,
377
- endNumber: eDevice.endNumber
378
- )
379
-
380
- if remainPoints <= 0 {
381
- closeBleSensor()
382
- }*/
383
- }
384
-
385
- func resetBleSensorData() {
386
- // Disconnect from peripheral and stop listening to characteristics
387
- terminateConnection()
388
-
389
- /*if let currentDevice = self.currentDevice {
390
- currentDevice.userBG = nil
391
- currentDevice.connectedDateTime = nil
392
- currentDevice.disconnectedDateTime = nil
393
- currentDevice.initialBeginDate = nil
394
- currentDevice.initialEndDate = nil
395
-
396
- KLTDatabaseHandler.shared().appDelegate.saveContext()
397
- }*/
398
-
399
- //self.currentDevice = nil
400
- //self.dataType = .receiveDataBeforeSetUserReference
401
- //self.resendType = .resendDataBeforeSetUserBG
402
-
403
- self.peripherals.removeAll()
404
- self.connectedPeripheral = nil
405
-
406
- //connectTimer?.invalidate()
407
- //connectTimer = nil
408
- //rescanTimer?.invalidate()
409
- //rescanTimer = nil
410
-
411
- //UserDefaults.standard.removeObject(forKey: KLTLocalDeviceQRCodeInfoKey)
412
- //KLTLocalSettingManager.shared.canConnectOtherDevice = true
413
- UserDefaults.standard.set(nil, forKey: "silenceStart")
414
- UserDefaults.standard.set(nil, forKey: "alertKindOnSilence")
415
- UserDefaults.standard.synchronize()
416
- }
417
- func terminateConnection() {
418
- for peripheral in peripherals {
419
- if let services = peripheral.services {
420
- for service in services {
421
- if let characteristics = service.characteristics {
422
- for characteristic in characteristics {
423
- if let eDevice = eDevice {
424
- if characteristic.uuid == CBUUID(string: eDevice.eGattMessage.uuid_READ) {
425
- if characteristic.isNotifying {
426
- peripheral.setNotifyValue(false, for: characteristic)
427
- return
428
- }
429
- }
430
- }
431
- }
432
- }
433
- }
434
- }
435
- }
436
-
437
- if let connectedPeripheral = connectedPeripheral {
438
- centralManager.cancelPeripheralConnection(connectedPeripheral)
439
- }
440
- }
441
- func handleResendDataWithPrefix22(_ resendData: Data) {
442
- //eDevice = EDevice.getEnumDevice(connectedPeripheral?.name ?? "")
443
- let glucoseList: [Glucose] = ProtocalTools.getGlucose_series(resendData, andEDevice: eDevice)
444
-
445
- if glucoseList.isEmpty {
446
- // Resend finished
447
- //self.isInResend = false
448
- //self.status = .resendEnd
449
-
450
- NotificationCenter.default.post(name: Notification.Name("DidHandleResendData"), object: nil)
451
-
452
- // Send reset command (0x11) to end resend state
453
- if let peripheral = connectedPeripheral, let characteristic = writeReadCharacteristic {
454
- if let resetCommand = ProtocalTools.reset_request(eDevice) {
455
- peripheral.writeValue(resetCommand, for: characteristic, type: .withoutResponse)
456
- }
457
- }
458
-
459
- } else {
460
- for glucose in glucoseList {
461
- let glucoseId = glucose.gluID
462
- let operatingCurrent = glucose.iw
463
- let blankCurrent = glucose.ib
464
- let temperature = glucose.t
465
-
466
- print(glucose)
467
- }
468
-
469
- }
470
- }
471
-
472
- }