react-native-mytatva-rn-sdk 1.2.53 → 1.2.54
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.
- package/ios/Database/KLTBluetoothManager.m +3 -2
- package/ios/Database/KLTDatabaseHandler.m +4 -1
- package/ios/Support/API.swift +22 -15
- package/ios/Support/Converter/DataConverter.swift +37 -22
- package/ios/ViewControllers/AttachTransmitterViewController.swift +3 -1
- package/ios/ViewModel/FinalViewModel.swift +42 -13
- package/package.json +1 -1
|
@@ -383,6 +383,7 @@
|
|
|
383
383
|
#pragma mark - 发射器通用接受数据处理、算法计算处理
|
|
384
384
|
|
|
385
385
|
// 发射器处理单条血糖数据的算法调用保存
|
|
386
|
+
//Is the algorithm used by the transmitter to process a single glucose data point also responsible for saving it?
|
|
386
387
|
- (void)handleCommonCT3GlucoseDataWithReceiveData:(ReceiveData *)receiveData {
|
|
387
388
|
int glucoseId = receiveData.glucoseId.intValue;
|
|
388
389
|
if (glucoseId >= self.eDevice.initNumber - 1) {
|
|
@@ -508,6 +509,7 @@
|
|
|
508
509
|
}
|
|
509
510
|
|
|
510
511
|
// CT3 CT4重传的数据,pullGlucose_series_request 22的返回
|
|
512
|
+
//Retransmitted data from CT3 and CT4, response of pullGlucose_series_request 0x22
|
|
511
513
|
- (void)handleResendDataWithPrefix22:(NSData *)resendData {
|
|
512
514
|
NSArray<Glucose *> *glucoseList = [ProtocalTools getGlucose_series:resendData andEDevice:self.eDevice];
|
|
513
515
|
if (glucoseList.count == 0) {
|
|
@@ -524,8 +526,7 @@
|
|
|
524
526
|
self.isFromPrefix22 = YES;
|
|
525
527
|
[self handleCommonCT3GlucoseDataWithReceiveData:receive];
|
|
526
528
|
}
|
|
527
|
-
|
|
528
|
-
|
|
529
|
+
|
|
529
530
|
[Notification_Center postNotificationName:KLTUpdateDataNotify object:NULL];
|
|
530
531
|
NSLog(@"----------------------------------------------called handleResendDataWithPrefix22 for KLTUpdateDataNotify");
|
|
531
532
|
NSInteger maxGlucoseId = [KLTDatabaseHandler.shared getLatestAndMaxGlucoseIdOfDevice:self.currentDevice];
|
|
@@ -396,6 +396,7 @@
|
|
|
396
396
|
}
|
|
397
397
|
|
|
398
398
|
// 查询最近一次连接的最大的血糖ID
|
|
399
|
+
//Query the highest glucose ID from the most recent connection.
|
|
399
400
|
- (NSInteger)getLatestAndMaxGlucoseIdOfDevice:(Device *)currentDevice {
|
|
400
401
|
NSArray *array = [self queryReceiveDataWithDevice:currentDevice needUserBG:NO];
|
|
401
402
|
if (array.count > 0) {
|
|
@@ -406,6 +407,7 @@
|
|
|
406
407
|
}
|
|
407
408
|
|
|
408
409
|
// 获取距离某个设备的到期时间还剩多少数据没有接收完
|
|
410
|
+
//Get how much data remains to be received before the device reaches its expiration time
|
|
409
411
|
- (NSInteger)numberOfLifeCycleSensorWithDevice:(Device *)currentDevice endNumber:(int)endNumber {
|
|
410
412
|
if (currentDevice) {
|
|
411
413
|
NSArray *array = [self queryReceiveDataWithDevice:currentDevice needUserBG:NO];
|
|
@@ -415,7 +417,7 @@
|
|
|
415
417
|
}
|
|
416
418
|
|
|
417
419
|
#pragma mark - APP重启后需要手动调用历史数据
|
|
418
|
-
|
|
420
|
+
//After restarting the app, is it necessary to manually request historical data?
|
|
419
421
|
- (void)reloadQueryHistoryData {
|
|
420
422
|
Device *currentDevice = KLTBluetoothManager.sharedManager.currentDevice;
|
|
421
423
|
if (nil == currentDevice) {
|
|
@@ -459,6 +461,7 @@
|
|
|
459
461
|
data.TsCount = (int)index + 1;
|
|
460
462
|
|
|
461
463
|
// 校准后的点
|
|
464
|
+
//Point after calibration
|
|
462
465
|
NSArray<ReceiveData*> *needUserBgs = [self queryReceiveDataWithDevice:currentDevice needUserBG:YES];
|
|
463
466
|
NSUInteger numberOfUserBgs = needUserBgs.count;
|
|
464
467
|
if (needUserBgs.count > 0) {
|
package/ios/Support/API.swift
CHANGED
|
@@ -10,6 +10,7 @@ import CommonCrypto
|
|
|
10
10
|
|
|
11
11
|
let PROD_API_KEY = "lChjFRJce3bxmoS3TSQk5w=="
|
|
12
12
|
let STAGE_API_KEY = "lChjFRJce3bxmoS3TSQk5w=="
|
|
13
|
+
|
|
13
14
|
let PROD_BASE_URL = "https://api.mytatva.in/api/v8"
|
|
14
15
|
let STAGE_BASE_URL = "https://api-uat.mytatva.in/api/v8"
|
|
15
16
|
|
|
@@ -41,23 +42,23 @@ let envType = UserDefaults.standard.string(forKey: "envType") ?? "uat"
|
|
|
41
42
|
|
|
42
43
|
struct CGMLog: Codable {
|
|
43
44
|
let timeInMillis: Double
|
|
44
|
-
|
|
45
|
-
|
|
45
|
+
// let countdownMinutes: Int
|
|
46
|
+
// let countdownDays: Int
|
|
46
47
|
let hypoglycemiaEarlyWarnMinutes: Int
|
|
47
48
|
let showGlucoseMG: Int
|
|
48
|
-
|
|
49
|
+
// let glucoseId: Int
|
|
49
50
|
let name: String
|
|
50
51
|
let bytes: [Int]
|
|
51
52
|
let showGlucose: Float
|
|
52
53
|
let Ib: Float
|
|
53
54
|
let Iw: Float
|
|
54
|
-
|
|
55
|
+
// let countdownHours: Int
|
|
55
56
|
let T: Float
|
|
56
|
-
let year: Int32
|
|
57
|
-
let month: Int32
|
|
58
|
-
let day: Int32
|
|
59
|
-
let hour: Int32
|
|
60
|
-
let minute: Int32
|
|
57
|
+
// let year: Int32
|
|
58
|
+
// let month: Int32
|
|
59
|
+
// let day: Int32
|
|
60
|
+
// let hour: Int32
|
|
61
|
+
// let minute: Int32
|
|
61
62
|
let trendObject: TrendObject
|
|
62
63
|
let glucoseStatusObject: GlucoseStatusObject
|
|
63
64
|
let errorObject: ErrorObject
|
|
@@ -97,6 +98,7 @@ class API {
|
|
|
97
98
|
|
|
98
99
|
func postCGMData(
|
|
99
100
|
data: Payload,
|
|
101
|
+
environment: TatvaEnvironment,
|
|
100
102
|
token: String = TOKEN,
|
|
101
103
|
encryptionKey: String = PROD_ENC_KEY,
|
|
102
104
|
encryptionIv: String = PROD_ENC_IV,
|
|
@@ -124,6 +126,7 @@ class API {
|
|
|
124
126
|
}
|
|
125
127
|
|
|
126
128
|
let urlString = (envType.lowercased() == "uat" ? STAGE_BASE_URL : PROD_BASE_URL) + "/cgm/logs"
|
|
129
|
+
// let urlString = (environment == .stage ? STAGE_BASE_URL : PROD_BASE_URL) + "/cgm/logs"
|
|
127
130
|
guard let url = URL(string: urlString) else {
|
|
128
131
|
throw URLError(.badURL)
|
|
129
132
|
}
|
|
@@ -131,10 +134,11 @@ class API {
|
|
|
131
134
|
var request = URLRequest(url: url)
|
|
132
135
|
request.httpMethod = "POST"
|
|
133
136
|
request.setValue(envType.lowercased() == "uat" ? STAGE_API_KEY : PROD_API_KEY, forHTTPHeaderField: "api-key")
|
|
137
|
+
// request.setValue(environment == .stage ? STAGE_API_KEY : PROD_API_KEY, forHTTPHeaderField: "api-key")
|
|
134
138
|
request.setValue(token, forHTTPHeaderField: "token")
|
|
135
139
|
request.setValue("text/plain", forHTTPHeaderField: "Content-Type")
|
|
136
140
|
request.httpBody = encrypted.data(using: .utf8)
|
|
137
|
-
|
|
141
|
+
print("===>url:", urlString)
|
|
138
142
|
let (data, response) = try await URLSession.shared.data(for: request)
|
|
139
143
|
|
|
140
144
|
if let httpResponse = response as? HTTPURLResponse {
|
|
@@ -144,7 +148,7 @@ class API {
|
|
|
144
148
|
if let responseStr = String(data: data, encoding: .utf8) {
|
|
145
149
|
print("===>Server Response: \(responseStr)")
|
|
146
150
|
if let decrypted = Crypto.shared.getDecryptedData(cipherText: responseStr, encryptionKey: encryptionKey, encryptionIv: encryptionIv) {
|
|
147
|
-
print("===>Decrypted response (for verification): \(decrypted)")
|
|
151
|
+
print("===>Decrypted post cgm data response (for verification): \(decrypted)")
|
|
148
152
|
}
|
|
149
153
|
|
|
150
154
|
}
|
|
@@ -165,13 +169,16 @@ class API {
|
|
|
165
169
|
//addCT3GlucoseDataWithReceiveData
|
|
166
170
|
//updatePOCAlgoBeforeRef
|
|
167
171
|
func sendStatus(sensorId: String = UserDefaults.standard.string(forKey: "sensorId") ?? "",
|
|
172
|
+
environment: TatvaEnvironment,
|
|
168
173
|
status: CGMConnectionStatus,
|
|
169
174
|
transmitterName: String = KLTBluetoothManager.shared().currentDevice?.advertise?.localName ?? "",
|
|
170
175
|
encryptionKey: String = PROD_ENC_KEY,
|
|
171
176
|
encryptionIv: String = PROD_ENC_IV) {
|
|
172
177
|
if sensorId.isEmpty { return }
|
|
173
|
-
|
|
178
|
+
// let envType = UserDefaults.standard.string(forKey: "envType") ?? "uat"
|
|
179
|
+
print("envType: \(envType.lowercased())")
|
|
174
180
|
let urlString = (envType.lowercased() == "uat" ? STAGE_BASE_URL : PROD_BASE_URL) + "/cgm/connection"
|
|
181
|
+
//let urlString = (environment == .stage ? STAGE_BASE_URL : PROD_BASE_URL) + "/cgm/connection"
|
|
175
182
|
let url = URL(string: urlString)!
|
|
176
183
|
var request = URLRequest(url: url)
|
|
177
184
|
request.httpMethod = "POST"
|
|
@@ -179,15 +186,15 @@ class API {
|
|
|
179
186
|
// Set headers
|
|
180
187
|
request.addValue("text/plain", forHTTPHeaderField: "Content-Type")
|
|
181
188
|
request.setValue(envType.lowercased() == "uat" ? STAGE_API_KEY : PROD_API_KEY, forHTTPHeaderField: "api-key")
|
|
189
|
+
//request.setValue(environment == .stage ? STAGE_API_KEY : PROD_API_KEY, forHTTPHeaderField: "api-key")
|
|
182
190
|
request.addValue(TOKEN, forHTTPHeaderField: "token")
|
|
183
|
-
print("===>url:",
|
|
191
|
+
print("===>url:", urlString)
|
|
184
192
|
print("===>api-key:", PROD_API_KEY)
|
|
185
193
|
print("===>httpmMethod:","POST")
|
|
186
194
|
print("===>ios token:", TOKEN)
|
|
187
195
|
// Set request body
|
|
188
196
|
let json: [String: Any] = [
|
|
189
197
|
"sensorId": sensorId,
|
|
190
|
-
// "sensorName": sensorId,
|
|
191
198
|
"status": status.rawValue,
|
|
192
199
|
"rawData": [
|
|
193
200
|
"transmitterName": transmitterName,
|
|
@@ -222,7 +229,7 @@ class API {
|
|
|
222
229
|
if let responseString = String(data: data, encoding: .utf8) {
|
|
223
230
|
print("===>Server Response: \(responseString)")
|
|
224
231
|
if let decrypted = Crypto.shared.getDecryptedData(cipherText: responseString, encryptionKey: encryptionKey, encryptionIv: encryptionIv) {
|
|
225
|
-
print("===>Decrypted response (for verification): \(decrypted)")
|
|
232
|
+
print("===>Decrypted connection api response (for verification): \(decrypted)")
|
|
226
233
|
}
|
|
227
234
|
}
|
|
228
235
|
}
|
|
@@ -7,28 +7,43 @@
|
|
|
7
7
|
|
|
8
8
|
import Foundation
|
|
9
9
|
|
|
10
|
-
func ReceiveDataToLog(data:
|
|
10
|
+
func ReceiveDataToLog(data: GlucoseData) -> CGMLog {
|
|
11
|
+
let cgmLogs = CGMLog(
|
|
12
|
+
timeInMillis: Double(Date().timeIntervalSince1970 * 1000),
|
|
13
|
+
// countdownMinutes: (data.countdownMinutes as? Int) ?? 0,
|
|
14
|
+
// countdownDays: (data.countdownDays as? Int) ?? 0,
|
|
15
|
+
hypoglycemiaEarlyWarnMinutes: 0, // still missing, you can map if available
|
|
16
|
+
showGlucoseMG: (data.gluADC as? Int) ?? 0,
|
|
17
|
+
// glucoseId: Int(truncating: data.glucoseId ?? 0),
|
|
18
|
+
name: data.device?.advertise?.localName ?? "",
|
|
19
|
+
bytes: [], // still missing: need raw data source
|
|
20
|
+
showGlucose: (data.glu as? Float) ?? 0,
|
|
21
|
+
Ib: (data.blankCurrent as? Float) ?? 0,
|
|
22
|
+
Iw: (data.operatingCurrent as? Float) ?? 0,
|
|
23
|
+
// countdownHours: (data.countdownHours as? Int) ?? 0,
|
|
24
|
+
T: (data.temperature as? Float) ?? 0.0,
|
|
25
|
+
// year: (data.year as? Int32) ?? 0,
|
|
26
|
+
// month: (data.month as? Int32) ?? 0,
|
|
27
|
+
// day: (data.day as? Int32) ?? 0,
|
|
28
|
+
// hour: (data.hour as? Int32) ?? 0,
|
|
29
|
+
// minute: (data.minute as? Int32) ?? 0,
|
|
30
|
+
|
|
31
|
+
trendObject: TrendObject(
|
|
32
|
+
trendId: (data.trend as? Int) ?? 0,
|
|
33
|
+
drawableId: 2103818652, // customize if needed
|
|
34
|
+
widgetImg: -1,
|
|
35
|
+
apsChangeRate: "FLAT" // you could map a real value if available
|
|
36
|
+
),
|
|
37
|
+
|
|
38
|
+
glucoseStatusObject: GlucoseStatusObject(
|
|
39
|
+
statusId: 1 // you may derive this from a field like `calibrationStatus`
|
|
40
|
+
),
|
|
41
|
+
|
|
42
|
+
errorObject: ErrorObject(
|
|
43
|
+
errorId: (data.errorCode as? Int) ?? 0,
|
|
44
|
+
sound: "None"
|
|
45
|
+
)
|
|
46
|
+
)
|
|
11
47
|
|
|
12
|
-
let cgmLogs = CGMLog(timeInMillis: Double(Date().timeIntervalSince1970 * 1000),
|
|
13
|
-
countdownMinutes: (data.countdownMinutes as? Int) ?? 0,
|
|
14
|
-
countdownDays: (data.countdownDays as? Int) ?? 0,
|
|
15
|
-
hypoglycemiaEarlyWarnMinutes: 0, //missing
|
|
16
|
-
showGlucoseMG: (data.gluADC as? Int) ?? 0,
|
|
17
|
-
glucoseId: Int(truncating: data.glucoseId ?? 0),
|
|
18
|
-
name: data.device?.advertise?.localName ?? "",
|
|
19
|
-
bytes: [], //missing
|
|
20
|
-
showGlucose: (data.glu as? Float) ?? 0 ,
|
|
21
|
-
Ib: (data.blankCurrent as? Float) ?? 0,
|
|
22
|
-
Iw: (data.operatingCurrent as? Float) ?? 0,
|
|
23
|
-
countdownHours: (data.countdownHours as? Int) ?? 0,
|
|
24
|
-
T: (data.temperature as? Float) ?? 0.0,
|
|
25
|
-
year: (data.year as? Int32) ?? 0,
|
|
26
|
-
month: (data.month as? Int32) ?? 0,
|
|
27
|
-
day: (data.day as? Int32) ?? 0,
|
|
28
|
-
hour: (data.hour as? Int32) ?? 0,
|
|
29
|
-
minute: (data.minute as? Int32) ?? 0,
|
|
30
|
-
trendObject: TrendObject(trendId: (data.trend as? Int) ?? 0, drawableId: 2103818652, widgetImg: -1, apsChangeRate: "FLAT"), //missing
|
|
31
|
-
glucoseStatusObject: GlucoseStatusObject(statusId: 1), //missing
|
|
32
|
-
errorObject: ErrorObject(errorId: (data.error as? Int) ?? 0, sound: "None"))
|
|
33
48
|
return cgmLogs
|
|
34
49
|
}
|
|
@@ -72,13 +72,15 @@ class AttachTransmitterViewController: UIViewController {
|
|
|
72
72
|
print(data)
|
|
73
73
|
print("===> all data count: ", data.count)
|
|
74
74
|
// KLTDatabaseHandler.shared().reloadQueryHistoryData()
|
|
75
|
+
|
|
75
76
|
if let device = KLTBluetoothManager.shared().currentDevice {
|
|
76
|
-
let arrayFromInitial = KLTDatabaseHandler.shared().
|
|
77
|
+
let arrayFromInitial = KLTDatabaseHandler.shared().queryGlucoseData(with: device) as! [GlucoseData]
|
|
77
78
|
print(arrayFromInitial)
|
|
78
79
|
print("===> arrayFromInitial count: ", arrayFromInitial.count)
|
|
79
80
|
|
|
80
81
|
self.viewModel.uploadData(data: arrayFromInitial)
|
|
81
82
|
}
|
|
83
|
+
|
|
82
84
|
NotificationCenter.default.post(name: Notification.Name("cgmDeviceEvent"), object: nil, userInfo: ["a":"a"])
|
|
83
85
|
if let rootVC = UIApplication.shared.connectedScenes
|
|
84
86
|
.compactMap({ ($0 as? UIWindowScene)?.windows.first?.rootViewController })
|
|
@@ -153,7 +153,7 @@ class FinalViewModel: NSObject {
|
|
|
153
153
|
super.init()
|
|
154
154
|
debouncer.onDebounceSuccess = { value in
|
|
155
155
|
print("Blutooth is------------------->>>>>>>>>> \(value)")
|
|
156
|
-
API.shared.sendStatus(status: value)
|
|
156
|
+
API.shared.sendStatus(environment: .stage, status: value)
|
|
157
157
|
// if value == .errorCommon {
|
|
158
158
|
// self.manager.startScan()
|
|
159
159
|
// }
|
|
@@ -331,7 +331,7 @@ class FinalViewModel: NSObject {
|
|
|
331
331
|
}
|
|
332
332
|
|
|
333
333
|
|
|
334
|
-
func uploadData(data: [
|
|
334
|
+
func uploadData(data: [GlucoseData]) {
|
|
335
335
|
let batchSize = 40
|
|
336
336
|
let batches = stride(from: 0, to: data.count, by: batchSize).map {
|
|
337
337
|
Array(data[$0..<min($0 + batchSize, data.count)])
|
|
@@ -340,7 +340,7 @@ class FinalViewModel: NSObject {
|
|
|
340
340
|
uploadBatch(batches: batches, index: 0)
|
|
341
341
|
}
|
|
342
342
|
|
|
343
|
-
private func uploadBatch(batches: [[
|
|
343
|
+
private func uploadBatch(batches: [[GlucoseData]], index: Int) {
|
|
344
344
|
guard index < batches.count else {
|
|
345
345
|
print("====================================> All batches uploaded")
|
|
346
346
|
print("✅ All batches uploaded")
|
|
@@ -352,7 +352,7 @@ class FinalViewModel: NSObject {
|
|
|
352
352
|
let payload = Payload(logs: cgmLogs)
|
|
353
353
|
|
|
354
354
|
print("====================================> called uploadBatch")
|
|
355
|
-
API.shared.postCGMData(data: payload
|
|
355
|
+
API.shared.postCGMData(data: payload, environment: .stage) {
|
|
356
356
|
print("====================================> uploaded successfully")
|
|
357
357
|
print("✅ Batch \(index + 1) uploaded successfully")
|
|
358
358
|
KLTDatabaseHandler.shared().deleteReceiveDataArray(batch)
|
|
@@ -362,19 +362,48 @@ class FinalViewModel: NSObject {
|
|
|
362
362
|
// Optionally retry or stop here
|
|
363
363
|
}
|
|
364
364
|
}
|
|
365
|
-
|
|
365
|
+
//
|
|
366
|
+
// @objc func updateData(_ notification: Notification) {
|
|
367
|
+
// let data = KLTDatabaseHandler.shared().queryAllReceiveData() as! [ReceiveData]
|
|
368
|
+
// print(data)
|
|
369
|
+
// print("===> all data count: ", data.count)
|
|
370
|
+
//// KLTDatabaseHandler.shared().reloadQueryHistoryData()
|
|
371
|
+
// if let device = KLTBluetoothManager.shared().currentDevice {
|
|
372
|
+
// let arrayFromInitial = KLTDatabaseHandler.shared().queryGlucoseData(with: device) as! [GlucoseData]
|
|
373
|
+
// print(arrayFromInitial)
|
|
374
|
+
// print("======================> arrayFromInitial count: ", arrayFromInitial.count)
|
|
375
|
+
// self.uploadData(data: arrayFromInitial)
|
|
376
|
+
// }
|
|
377
|
+
// }
|
|
378
|
+
|
|
366
379
|
@objc func updateData(_ notification: Notification) {
|
|
367
|
-
|
|
380
|
+
// Safely cast to [ReceiveData]
|
|
381
|
+
guard let data = KLTDatabaseHandler.shared().queryAllReceiveData() as? [ReceiveData] else {
|
|
382
|
+
print("⚠️ Failed to cast queryAllReceiveData() to [ReceiveData]")
|
|
383
|
+
return
|
|
384
|
+
}
|
|
385
|
+
|
|
368
386
|
print(data)
|
|
369
|
-
print("===> all data count:
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
print(
|
|
374
|
-
|
|
375
|
-
|
|
387
|
+
print("===> all data count: \(data.count)")
|
|
388
|
+
|
|
389
|
+
// Ensure device exists
|
|
390
|
+
guard let device = KLTBluetoothManager.shared().currentDevice else {
|
|
391
|
+
print("⚠️ No current device found")
|
|
392
|
+
return
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
// Get glucose data array
|
|
396
|
+
guard let arrayFromInitial = KLTDatabaseHandler.shared().queryGlucoseData(with: device) else {
|
|
397
|
+
print("⚠️ Failed to cast queryGlucoseData to [GlucoseData]")
|
|
398
|
+
return
|
|
376
399
|
}
|
|
400
|
+
|
|
401
|
+
print("======================> arrayFromInitial count: \(arrayFromInitial.count)")
|
|
402
|
+
|
|
403
|
+
// Call upload
|
|
404
|
+
self.uploadData(data: arrayFromInitial)
|
|
377
405
|
}
|
|
406
|
+
|
|
378
407
|
|
|
379
408
|
@objc func errorStatusFromTransmitter(_ notification: Notification) {
|
|
380
409
|
guard let receiveData = notification.object as? ReceiveData else { return }
|