react-native-mytatva-rn-sdk 1.2.20 → 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.
@@ -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
- }