react-native-mytatva-rn-sdk 1.2.30 → 1.2.32

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.
@@ -61,730 +61,856 @@ import kotlin.coroutines.suspendCoroutine
61
61
 
62
62
  @ReactModule(name = "CgmTrackyLib")
63
63
  class CgmTrackyLibModule(reactContext: ReactApplicationContext) :
64
- ReactContextBaseJavaModule(reactContext) {
65
- private val mModel: MainActivityModel
66
- var authenticateSDKService: AuthenticateSDKService
67
- private val job = Job()
68
- private val scope = CoroutineScope(Dispatchers.IO + job)
69
- var prefsHelper: SharedPreferencesLibraryUtil
70
- private val apiScope = CoroutineScope(Dispatchers.IO + SupervisorJob())
71
- private var debounceJob: Job? = null
72
- private var lastDeviceStatus: PocDevice? = null
73
-
74
- private var glucoseObserver: Observer<PocGlucose?>? = null
75
- private var isObserving = false
76
-
77
- init {
78
- mReactContext = reactContext
79
- prefsHelper = SharedPreferencesLibraryUtil(mReactContext)
80
- val viewModelStore = ViewModelStore()
81
- val factory =
82
- ViewModelProvider.AndroidViewModelFactory.getInstance(reactContext.applicationContext as Application)
83
- mModel = ViewModelProvider(viewModelStore, factory)[MainActivityModel::class.java]
84
- authenticateSDKService = AuthenticateSDKService(scope = scope)
85
- }
86
-
87
-
88
- companion object {
89
- var mReactContext: ReactApplicationContext? = null
90
- var userToken: String = ""
91
- }
92
-
93
- override fun getName(): String {
94
- return "CgmTrackyLib"
95
- }
96
-
97
- @ReactMethod
98
- fun observeDeviceStatus(token: String) {
99
- try {
100
- userToken = token
101
- Handler(Looper.getMainLooper()).post {
102
- mModel.device.observeForever { device ->
103
- if (device != lastDeviceStatus) {
104
- lastDeviceStatus = device
105
- postEventDataToAPI(device, "", lastDeviceStatus?.qrMessage ?: "")
106
- resetDebounceTimer()
107
- }
108
-
109
- if (device != null) {
110
- Log.d("observeDeviceStatus: ", device.toString())
111
- }
64
+ ReactContextBaseJavaModule(reactContext) {
65
+ private val mModel: MainActivityModel
66
+ var authenticateSDKService: AuthenticateSDKService
67
+ private val job = Job()
68
+ private val scope = CoroutineScope(Dispatchers.IO + job)
69
+ var prefsHelper: SharedPreferencesLibraryUtil
70
+ private val apiScope = CoroutineScope(Dispatchers.IO + SupervisorJob())
71
+ private var debounceJob: Job? = null
72
+
73
+ @Volatile
74
+ private var lastDeviceStatus: PocDevice? = null
75
+
76
+ private var glucoseObserver: Observer<PocGlucose?>? = null
77
+ private var isObserving = false
78
+
79
+ init {
80
+ mReactContext = reactContext
81
+ prefsHelper = SharedPreferencesLibraryUtil(mReactContext)
82
+ val viewModelStore = ViewModelStore()
83
+ val factory =
84
+ ViewModelProvider.AndroidViewModelFactory.getInstance(reactContext.applicationContext as Application)
85
+ mModel = ViewModelProvider(viewModelStore, factory)[MainActivityModel::class.java]
86
+ authenticateSDKService = AuthenticateSDKService(scope = scope)
87
+ }
88
+
89
+
90
+ companion object {
91
+ var mReactContext: ReactApplicationContext? = null
92
+ var userToken: String = ""
93
+ }
94
+
95
+ override fun getName(): String {
96
+ return "CgmTrackyLib"
97
+ }
98
+
99
+ @ReactMethod
100
+ fun observeDeviceStatus(token: String) {
101
+ try {
102
+ userToken = token
103
+
104
+ // Reset previous state
105
+ lastDeviceStatus = null
106
+ debounceJob?.cancel()
107
+
108
+ Handler(Looper.getMainLooper()).post {
109
+ mModel.device.observeForever { device ->
110
+ if (device != lastDeviceStatus) {
111
+ lastDeviceStatus = device
112
+ postEventDataToAPI(device, "", lastDeviceStatus?.qrMessage ?: "")
113
+ resetDebounceTimer()
114
+ }
115
+
116
+ if (device != null) {
117
+ Log.d("observeDeviceStatus: ", device.toString())
118
+ }
119
+ }
120
+ }
121
+ } catch (e: Exception) {
122
+ Log.e("observeDeviceStatus", "observeDeviceStatus: ${e.message}")
112
123
  }
113
- }
114
- } catch (e: Exception) {
115
- Log.e("observeDeviceStatus", "observeDeviceStatus: ${e.message}")
116
124
  }
117
- }
118
125
 
119
- @ReactMethod
120
- fun observeTransmitterUnbindStatus(token: String) {
121
- try {
122
- userToken = token
126
+ @ReactMethod
127
+ fun observeTransmitterUnbindStatus(token: String, apiResponse: String) {
128
+ try {
129
+ userToken = token
130
+
131
+ /*authenticateSDKService.getCGMData(
132
+ environment = if ("uat".uppercase() == "PROD") TATVA_ENVIRONMENT.PROD else TATVA_ENVIRONMENT.STAGE,
133
+ token = userToken,
134
+ responseListener = object : AuthenticateSDKService.ResponseListener {
135
+ override fun onResponseSuccess(response: String) {
136
+
137
+ val response = Gson().fromJson(response, CgmSensorResponse::class.java)
138
+ val sensor = response.data?.firstOrNull()
139
+
140
+ if (sensor != null && !sensor.startDate.isNullOrEmpty() && !sensor.endDate.isNullOrEmpty()) {
141
+ val startDate = sensor.startDate
142
+ val endDate = sensor.endDate
143
+ val sensorId = sensor.sensorId
144
+
145
+ println("Start Date: $startDate")
146
+ println("End Date: $endDate")
147
+
148
+ if (isCurrentDateInRange(startDate, endDate)) {
149
+
150
+ println("Current date is in range")
151
+
152
+ val pocDevice =
153
+ RepositoryDevice.getInstance(BApplication.getContext()).latestDeviceIoThread
154
+
155
+ if (pocDevice != null) {
156
+ Log.d("pocDevice logsss", pocDevice.toString())
157
+
158
+ if (pocDevice.isUnBind) {
159
+ postEventDataToAPI(
160
+ pocDevice,
161
+ DeviceStatus.TRANSMITTER_DISCONNECT.id,
162
+ pocDevice.qrMessage
163
+ )
164
+ }
165
+ } else {
166
+ Log.d("pocDevice logsss", "Data null")
167
+
168
+ postEventDataToAPI(
169
+ pocDevice,
170
+ DeviceStatus.TRANSMITTER_DISCONNECT.id,
171
+ sensorId
172
+ )
173
+ }
174
+
175
+ } else {
176
+ println("Current date is out of range")
177
+ }
178
+ } else {
179
+ println("Start or End date not available")
180
+ }
181
+ }
123
182
 
124
- authenticateSDKService.getCGMData(
125
- environment = if ("uat".uppercase() == "PROD") TATVA_ENVIRONMENT.PROD else TATVA_ENVIRONMENT.STAGE,
126
- token = userToken,
127
- responseListener = object : AuthenticateSDKService.ResponseListener {
128
- override fun onResponseSuccess(response: String) {
183
+ override fun onResponseFail() {
184
+ }
185
+ }
186
+ )*/
129
187
 
130
- val response = Gson().fromJson(response, CgmSensorResponse::class.java)
188
+ val response = Gson().fromJson(apiResponse, CgmSensorResponse::class.java)
131
189
  val sensor = response.data?.firstOrNull()
132
190
 
133
191
  if (sensor != null && !sensor.startDate.isNullOrEmpty() && !sensor.endDate.isNullOrEmpty()) {
134
- val startDate = sensor.startDate
135
- val endDate = sensor.endDate
136
- val sensorId = sensor.sensorId
192
+ val startDate = sensor.startDate
193
+ val endDate = sensor.endDate
194
+ val sensorId = sensor.sensorId
137
195
 
138
- println("Start Date: $startDate")
139
- println("End Date: $endDate")
196
+ println("Start Date: $startDate")
197
+ println("End Date: $endDate")
140
198
 
141
- if (isCurrentDateInRange(startDate, endDate)) {
199
+ if (isCurrentDateInRange(startDate, endDate)) {
142
200
 
143
- println("Current date is in range")
201
+ println("Current date is in range")
144
202
 
145
- val pocDevice =
146
- RepositoryDevice.getInstance(BApplication.getContext()).latestDeviceIoThread
203
+ val pocDevice =
204
+ RepositoryDevice.getInstance(BApplication.getContext()).latestDeviceIoThread
147
205
 
148
- if (pocDevice != null) {
149
- Log.d("pocDevice logsss", pocDevice.toString())
206
+ if (pocDevice != null) {
207
+ Log.d("pocDevice logsss", pocDevice.toString())
150
208
 
151
- if (pocDevice.isUnBind) {
152
- postEventDataToAPI(
153
- pocDevice,
154
- DeviceStatus.TRANSMITTER_DISCONNECT.id,
155
- pocDevice.qrMessage
156
- )
157
- }
158
- } else {
159
- Log.d("pocDevice logsss", "Data null")
209
+ if (pocDevice.isUnBind) {
210
+ postEventDataToAPI(
211
+ pocDevice,
212
+ DeviceStatus.TRANSMITTER_DISCONNECT.id,
213
+ pocDevice.qrMessage
214
+ )
215
+ }
216
+ } else {
217
+ Log.d("pocDevice logsss", "Data null")
160
218
 
161
- postEventDataToAPI(
162
- pocDevice,
163
- DeviceStatus.TRANSMITTER_DISCONNECT.id,
164
- sensorId
165
- )
166
- }
219
+ postEventDataToAPI(
220
+ pocDevice,
221
+ DeviceStatus.TRANSMITTER_DISCONNECT.id,
222
+ sensorId
223
+ )
224
+ }
167
225
 
168
- } else {
169
- println("Current date is out of range")
170
- }
226
+ } else {
227
+ println("Current date is out of range")
228
+ }
171
229
  } else {
172
- println("Start or End date not available")
230
+ println("Start or End date not available")
173
231
  }
174
- }
175
232
 
176
- override fun onResponseFail() {
177
- }
178
- }
179
- )
180
233
 
181
- } catch (e: Exception) {
182
- Log.e("observeTransmitterUnbindStatus", "observeTransmitterUnbindStatus: ${e.message}")
183
- }
184
- }
185
-
186
- private fun postEventDataToAPI(device: PocDevice?, mStatus: String, sensorId: String?) {
187
- apiScope.launch {
188
- try {
189
- val bluetoothAdapter: BluetoothAdapter? = BluetoothAdapter.getDefaultAdapter()
190
- val bleStatus = bluetoothAdapter?.isEnabled == true
191
- var status = ""
192
-
193
- status = if (mStatus.isEmpty()) {
194
- when {
195
- device?.isBoundAndConnect == true -> DeviceStatus.CONNECTED.id
196
- !bleStatus -> DeviceStatus.BLUETOOTH_OFF.id
197
- device?.isUnBind == true -> DeviceStatus.TRANSMITTER_DISCONNECT.id
198
- device?.isBoundButDisConnect == true -> DeviceStatus.DISCONNECTED.id
199
- else -> "" // fallback if no status matches
200
- }
201
- } else {
202
- mStatus
234
+ } catch (e: Exception) {
235
+ Log.e("observeTransmitterUnbindStatus", "observeTransmitterUnbindStatus: ${e.message}")
203
236
  }
237
+ }
238
+
239
+ private fun postEventDataToAPI(device: PocDevice?, mStatus: String, sensorId: String?) {
240
+ apiScope.launch {
241
+ try {
242
+ val bluetoothAdapter: BluetoothAdapter? = BluetoothAdapter.getDefaultAdapter()
243
+ val bleStatus = bluetoothAdapter?.isEnabled == true
244
+ var status = ""
245
+
246
+ status = if (mStatus.isEmpty()) {
247
+ when {
248
+ device?.isBoundAndConnect == true -> DeviceStatus.CONNECTED.id
249
+ !bleStatus -> DeviceStatus.BLUETOOTH_OFF.id
250
+ device?.isUnBind == true -> DeviceStatus.TRANSMITTER_DISCONNECT.id
251
+ device?.isBoundButDisConnect == true -> DeviceStatus.DISCONNECTED.id
252
+ else -> "" // fallback if no status matches
253
+ }
254
+ } else {
255
+ mStatus
256
+ }
204
257
 
205
- if (status.isNotEmpty()) {
206
- val rawData = JSONObject().apply {
207
- put("transmitterName", device?.name ?: "")
208
- put("SensorId", sensorId ?: "")
209
- put("Sensor", sensorId ?: "")
210
- put("timeInMillis", Date().time)
211
- }
212
-
213
- val obj = JSONObject().apply {
214
- put("sensorId", sensorId ?: "")
215
- put("status", status)
216
- put("rawData", rawData)
217
- }
218
-
219
- authenticateSDKService.postDeviceData(
220
- environment = if ("uat".uppercase() == "PROD") TATVA_ENVIRONMENT.PROD else TATVA_ENVIRONMENT.STAGE,
221
- data = obj.toString(),
222
- token = userToken,
223
- loaderListener = object : LoaderListener {
224
- override fun onShowLoader() {}
225
- override fun onHideLoader() {}
258
+ if (status.isNotEmpty()) {
259
+ val rawData = JSONObject().apply {
260
+ put("transmitterName", device?.name ?: "")
261
+ put("SensorId", sensorId ?: "")
262
+ put("Sensor", sensorId ?: "")
263
+ put("timeInMillis", Date().time)
264
+ }
265
+
266
+ val obj = JSONObject().apply {
267
+ put("sensorId", sensorId ?: "")
268
+ put("status", status)
269
+ put("rawData", rawData)
270
+ }
271
+
272
+ authenticateSDKService.postDeviceData(
273
+ environment = if ("uat".uppercase() == "PROD") TATVA_ENVIRONMENT.PROD else TATVA_ENVIRONMENT.STAGE,
274
+ data = obj.toString(),
275
+ token = userToken,
276
+ loaderListener = object : LoaderListener {
277
+ override fun onShowLoader() {}
278
+ override fun onHideLoader() {}
279
+ }
280
+ )
281
+ }
282
+
283
+ } catch (e: Exception) {
284
+ e.printStackTrace()
226
285
  }
227
- )
228
286
  }
287
+ }
229
288
 
230
- } catch (e: Exception) {
231
- e.printStackTrace()
232
- }
289
+ private fun resetDebounceTimer() {
290
+ debounceJob?.cancel() // Cancel any existing timer
291
+ debounceJob = apiScope.launch {
292
+ delay(60 * 60 * 1000L) // 60 minutes in ms
293
+ lastDeviceStatus = null // Reset status after timeout
294
+ println("60 min window expired, status reset.")
295
+ }
233
296
  }
234
- }
235
-
236
- private fun resetDebounceTimer() {
237
- debounceJob?.cancel() // Cancel any existing timer
238
- debounceJob = apiScope.launch {
239
- delay(60 * 60 * 1000L) // 60 minutes in ms
240
- lastDeviceStatus = null // Reset status after timeout
241
- println("60 min window expired, status reset.")
297
+
298
+ @ReactMethod
299
+ fun startCgmTracky(token: String) {
300
+ try {
301
+ userToken = token
302
+ val intent = Intent(currentActivity, StartCGMActivity::class.java)
303
+ currentActivity?.startActivity(intent)
304
+ } catch (e: Exception) {
305
+ Log.e("startCgmTracky", "startCgmTracky: ${e.message}")
306
+ }
242
307
  }
243
- }
244
-
245
- @ReactMethod
246
- fun startCgmTracky(token: String) {
247
- try {
248
- userToken = token
249
- val intent = Intent(currentActivity, StartCGMActivity::class.java)
250
- currentActivity?.startActivity(intent)
251
- } catch (e: Exception) {
252
- Log.e("startCgmTracky", "startCgmTracky: ${e.message}")
308
+
309
+ fun isCurrentDateInRange(startDateStr: String, endDateStr: String): Boolean {
310
+ val format = SimpleDateFormat("yyyy-MM-dd", Locale.getDefault())
311
+
312
+ val startDate = format.parse(startDateStr)
313
+ val endDate = format.parse(endDateStr)
314
+ val currentDate = Date()
315
+
316
+ return startDate != null && endDate != null &&
317
+ !currentDate.before(startDate) && !currentDate.after(endDate)
253
318
  }
254
- }
255
-
256
- fun isCurrentDateInRange(startDateStr: String, endDateStr: String): Boolean {
257
- val format = SimpleDateFormat("yyyy-MM-dd", Locale.getDefault())
258
-
259
- val startDate = format.parse(startDateStr)
260
- val endDate = format.parse(endDateStr)
261
- val currentDate = Date()
262
-
263
- return startDate != null && endDate != null &&
264
- !currentDate.before(startDate) && !currentDate.after(endDate)
265
- }
266
-
267
- @ReactMethod
268
- fun reconnectCgmTracky(token: String) {
269
- try {
270
- userToken = token
271
- val intent = if (areAllPermissionsGranted()) {
272
- Intent(currentActivity, SearchTransmitterActivity::class.java).putExtra(
273
- "IsForReconnect",
274
- true
275
- )
276
- } else {
277
- Intent(currentActivity, PermissionActivity::class.java).putExtra(
278
- "IsForReconnect",
279
- true
280
- )
281
- }
282
- currentActivity?.startActivity(intent)
283
- } catch (e: Exception) {
284
- Log.e("reconnectCgmTracky", "reconnectCgmTracky: ${e.message}")
319
+
320
+ @ReactMethod
321
+ fun reconnectCgmTracky(token: String) {
322
+ try {
323
+ userToken = token
324
+ val intent = if (areAllPermissionsGranted()) {
325
+ Intent(currentActivity, SearchTransmitterActivity::class.java).putExtra(
326
+ "IsForReconnect",
327
+ true
328
+ )
329
+ } else {
330
+ Intent(currentActivity, PermissionActivity::class.java).putExtra(
331
+ "IsForReconnect",
332
+ true
333
+ )
334
+ }
335
+ currentActivity?.startActivity(intent)
336
+ } catch (e: Exception) {
337
+ Log.e("reconnectCgmTracky", "reconnectCgmTracky: ${e.message}")
338
+ }
285
339
  }
286
- }
287
-
288
- @ReactMethod
289
- fun openHelpSupport() {
290
- try {
291
- val intent = Intent(currentActivity, HelpActivity::class.java)
292
- currentActivity?.startActivity(intent)
293
- } catch (e: Exception) {
294
- Log.e("openHelpSupport", "openHelpSupport: ${e.message}")
340
+
341
+ @ReactMethod
342
+ fun openHelpSupport() {
343
+ try {
344
+ val intent = Intent(currentActivity, HelpActivity::class.java)
345
+ currentActivity?.startActivity(intent)
346
+ } catch (e: Exception) {
347
+ Log.e("openHelpSupport", "openHelpSupport: ${e.message}")
348
+ }
295
349
  }
296
- }
297
350
 
298
- private fun areAllPermissionsGranted(): Boolean {
299
- val requiredPermissions = mutableListOf<String>()
351
+ private fun areAllPermissionsGranted(): Boolean {
352
+ val requiredPermissions = mutableListOf<String>()
300
353
 
301
- // Add Bluetooth permissions
302
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
303
- requiredPermissions.addAll(PermissionUtils.BLUETOOTH_S)
304
- }
354
+ // Add Bluetooth permissions
355
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
356
+ requiredPermissions.addAll(PermissionUtils.BLUETOOTH_S)
357
+ }
305
358
 
306
- // Add location permissions
307
- requiredPermissions.addAll(PermissionUtils.LOCAL_PERMISSION)
359
+ // Add location permissions
360
+ requiredPermissions.addAll(PermissionUtils.LOCAL_PERMISSION)
308
361
 
309
- // Add camera permission
310
- requiredPermissions.addAll(PermissionUtils.CAMERA_PERMISSION)
362
+ // Add camera permission
363
+ requiredPermissions.addAll(PermissionUtils.CAMERA_PERMISSION)
311
364
 
312
- return requiredPermissions.all {
313
- ContextCompat.checkSelfPermission(
314
- mReactContext!!,
315
- it
316
- ) == PackageManager.PERMISSION_GRANTED
317
- }
318
- }
319
-
320
- @ReactMethod
321
- fun observeGlucoseData(token: String) {
322
- try {
323
- userToken = token
324
-
325
- // Remove existing observer if any to prevent memory leaks
326
- stopObservingGlucoseData()
327
-
328
- // Create new observer with explicit nullable parameter type
329
- glucoseObserver = Observer<PocGlucose?> { pocGlucose ->
330
- if (pocGlucose != null) {
331
- // Add timestamp check to prevent processing old data
332
- val currentTime = System.currentTimeMillis()
333
- val dataAge = currentTime - pocGlucose.timeInMillis
334
-
335
- // Only process data that's relatively recent (within last 10 minutes as example)
336
- // Adjust this threshold based on your requirements
337
- if (dataAge <= 10 * 60 * 1000L) { // 10 minutes
338
- handleGlucoseData(pocGlucose)
339
- } else {
340
- Log.d("observeGlucoseData", "Skipping old glucose data: age = ${dataAge}ms")
341
- }
342
- } else {
343
- Log.w("observeGlucoseData", "Received null glucose data - skipping processing")
365
+ return requiredPermissions.all {
366
+ ContextCompat.checkSelfPermission(
367
+ mReactContext!!,
368
+ it
369
+ ) == PackageManager.PERMISSION_GRANTED
344
370
  }
345
- }
346
-
347
- // Add observer on main thread
348
- Handler(Looper.getMainLooper()).post {
349
- glucoseObserver?.let { observer ->
350
- try {
351
- mModel.latestGlucose.observeForever(observer)
352
- isObserving = true
353
- Log.d("observeGlucoseData", "Live glucose observer started successfully")
354
- } catch (e: Exception) {
355
- Log.e("observeGlucoseData", "Error adding observer: ${e.message}")
371
+ }
372
+
373
+ @ReactMethod
374
+ fun observeGlucoseData(token: String) {
375
+ try {
376
+ userToken = token
377
+
378
+ // Ensure we're not already observing
379
+ if (isObserving && glucoseObserver != null) {
380
+ Log.d(
381
+ "observeGlucoseData",
382
+ "Already observing glucose data, skipping duplicate setup"
383
+ )
384
+ return
385
+ }
386
+
387
+ // Remove existing observer if any to prevent memory leaks
388
+ stopObservingGlucoseData()
389
+
390
+ // Wait a bit for cleanup to complete
391
+ Handler(Looper.getMainLooper()).postDelayed({
392
+ // Create new observer with explicit nullable parameter type
393
+ glucoseObserver = Observer<PocGlucose?> { pocGlucose ->
394
+ if (pocGlucose != null) {
395
+ // Add timestamp check to prevent processing old data
396
+ val currentTime = System.currentTimeMillis()
397
+ val dataAge = currentTime - pocGlucose.timeInMillis
398
+
399
+ // Only process data that's relatively recent (within last 10 minutes as example)
400
+ if (dataAge <= 10 * 60 * 1000L) { // 10 minutes
401
+ handleGlucoseData(pocGlucose)
402
+ } else {
403
+ Log.d(
404
+ "observeGlucoseData",
405
+ "Skipping old glucose data: age = ${dataAge}ms"
406
+ )
407
+ }
408
+ } else {
409
+ Log.w(
410
+ "observeGlucoseData",
411
+ "Received null glucose data - skipping processing"
412
+ )
413
+ }
414
+ }
415
+
416
+ // Add observer on main thread
417
+ glucoseObserver?.let { observer ->
418
+ try {
419
+ mModel.latestGlucose.observeForever(observer)
420
+ isObserving = true
421
+ Log.d("observeGlucoseData", "Live glucose observer started successfully")
422
+ } catch (e: Exception) {
423
+ Log.e("observeGlucoseData", "Error adding observer: ${e.message}")
424
+ glucoseObserver = null
425
+ isObserving = false
426
+ }
427
+ }
428
+ }, 50) // Small delay to ensure previous cleanup is complete
429
+
430
+ } catch (e: Exception) {
431
+ Log.e("observeGlucoseData", "observeGlucoseData: ${e.message}")
432
+ e.printStackTrace()
433
+ isObserving = false
356
434
  glucoseObserver = null
357
- }
358
435
  }
359
- }
360
- } catch (e: Exception) {
361
- Log.e("observeGlucoseData", "observeGlucoseData: ${e.message}")
362
- e.printStackTrace()
363
436
  }
364
- }
365
-
366
- private fun handleGlucoseData(pocGlucose: PocGlucose) {
367
- try {
368
- // Additional safety check
369
- if (pocGlucose.glucoseId == null) {
370
- Log.w("handleGlucoseData", "Glucose ID is null, skipping processing")
371
- return
372
- }
373
-
374
- Log.d("handleGlucoseData", "Processing glucose data: ${pocGlucose.glucoseId}")
375
-
376
- if (pocGlucose.errorCode == enumError.NONE) {
377
- if (pocGlucose.showGlucoseMG > 0) {
378
- val dto: GlucoseLog = mapToDto(pocGlucose)
379
- val logs: ArrayList<GlucoseLog> = ArrayList()
380
- logs.add(dto)
381
-
382
- val request: GlucoseLogRequest =
383
- GlucoseLogRequest(vendor = "GoodFlip", logs = logs)
384
- val gson: Gson = GsonBuilder().create()
385
- val json = gson.toJson(request)
386
-
387
- Log.d("Glucose data 3 min==> ", "Glucose data 3 min==> final Json: $json")
388
-
389
- authenticateSDKService.postCGMData(
390
- environment = if ("uat".uppercase() == "PROD") TATVA_ENVIRONMENT.PROD else TATVA_ENVIRONMENT.STAGE,
391
- data = json,
392
- token = userToken,
393
- responseListener = object : AuthenticateSDKService.ResponseListener {
394
- override fun onResponseSuccess(response: String) {
395
- updateSyncMetadata(pocGlucose)
396
- Log.d("CGM Data", "Single glucose data uploaded successfully")
397
- }
398
437
 
399
- override fun onResponseFail() {
400
- Log.e("CGM Data", "Failed to upload single glucose data")
401
- }
438
+ private fun handleGlucoseData(pocGlucose: PocGlucose) {
439
+ try {
440
+ // Additional safety check
441
+ if (pocGlucose.glucoseId == null) {
442
+ Log.w("handleGlucoseData", "Glucose ID is null, skipping processing")
443
+ return
444
+ }
445
+
446
+ Log.d("handleGlucoseData", "Processing glucose data: ${pocGlucose.glucoseId}")
447
+
448
+ if (pocGlucose.errorCode == enumError.NONE) {
449
+ if (pocGlucose.showGlucoseMG > 0) {
450
+ val dto: GlucoseLog = mapToDto(pocGlucose)
451
+ val logs: ArrayList<GlucoseLog> = ArrayList()
452
+ logs.add(dto)
453
+
454
+ val request: GlucoseLogRequest =
455
+ GlucoseLogRequest(vendor = "GoodFlip", logs = logs)
456
+ val gson: Gson = GsonBuilder().create()
457
+ val json = gson.toJson(request)
458
+
459
+ Log.d("Glucose data 3 min==> ", "Glucose data 3 min==> final Json: $json")
460
+
461
+ authenticateSDKService.postCGMData(
462
+ environment = if ("uat".uppercase() == "PROD") TATVA_ENVIRONMENT.PROD else TATVA_ENVIRONMENT.STAGE,
463
+ data = json,
464
+ token = userToken,
465
+ responseListener = object : AuthenticateSDKService.ResponseListener {
466
+ override fun onResponseSuccess(response: String) {
467
+ updateSyncMetadata(pocGlucose)
468
+ Log.d("CGM Data", "Single glucose data uploaded successfully")
469
+ }
470
+
471
+ override fun onResponseFail() {
472
+ Log.e("CGM Data", "Failed to upload single glucose data")
473
+ }
474
+ }
475
+ )
476
+ } else {
477
+ Log.d(
478
+ "handleGlucoseData",
479
+ "Glucose value is 0 or negative: ${pocGlucose.showGlucoseMG}"
480
+ )
481
+ }
482
+ } else {
483
+ Log.d("handleGlucoseData", "Glucose data has error: ${pocGlucose.errorCode}")
484
+ handleGlucoseError(pocGlucose)
402
485
  }
403
- )
404
- } else {
405
- Log.d(
406
- "handleGlucoseData",
407
- "Glucose value is 0 or negative: ${pocGlucose.showGlucoseMG}"
408
- )
486
+ } catch (e: Exception) {
487
+ Log.e("handleGlucoseData", "Error handling glucose data: ${e.message}")
488
+ e.printStackTrace()
409
489
  }
410
- } else {
411
- Log.d("handleGlucoseData", "Glucose data has error: ${pocGlucose.errorCode}")
412
- handleGlucoseError(pocGlucose)
413
- }
414
- } catch (e: Exception) {
415
- Log.e("handleGlucoseData", "Error handling glucose data: ${e.message}")
416
- e.printStackTrace()
417
490
  }
418
- }
419
-
420
- // Extract error handling logic
421
- private fun handleGlucoseError(pocGlucose: PocGlucose) {
422
- try {
423
- // Additional safety check for deviceId
424
- if (pocGlucose.deviceId == null) {
425
- Log.e("handleGlucoseError", "Device ID is null, cannot process error")
426
- return
427
- }
428
-
429
- val deviceInfo = mModel.getDeviceInfo(pocGlucose.deviceId.toInt())
430
- deviceInfo?.let {
431
- val statusId = when (pocGlucose.errorCode) {
432
- enumError.ERROR_FLOODING_WATER -> {
433
- Log.d("handleGlucoseError", "Moisture detected")
434
- DeviceStatus.MOISTURE_DETECT.id
435
- }
436
-
437
- enumError.ERROR_CURRENT_SMALL,
438
- enumError.ERROR_NOISE,
439
- enumError.ERROR_SENSITIVITY_ATTENUATION -> {
440
- Log.d("handleGlucoseError", "Weak signal detected")
441
- DeviceStatus.WEAK_SIGNAL.id
442
- }
443
-
444
- else -> {
445
- Log.d(
446
- "handleGlucoseError",
447
- "Common error detected: ${pocGlucose.errorCode}"
448
- )
449
- DeviceStatus.ERROR_COMMON.id
450
- }
491
+
492
+ // Extract error handling logic
493
+ private fun handleGlucoseError(pocGlucose: PocGlucose) {
494
+ try {
495
+ // Additional safety check for deviceId
496
+ if (pocGlucose.deviceId == null) {
497
+ Log.e("handleGlucoseError", "Device ID is null, cannot process error")
498
+ return
499
+ }
500
+
501
+ val deviceInfo = mModel.getDeviceInfo(pocGlucose.deviceId.toInt())
502
+ deviceInfo?.let {
503
+ val statusId = when (pocGlucose.errorCode) {
504
+ enumError.ERROR_FLOODING_WATER -> {
505
+ Log.d("handleGlucoseError", "Moisture detected")
506
+ DeviceStatus.MOISTURE_DETECT.id
507
+ }
508
+
509
+ enumError.ERROR_CURRENT_SMALL,
510
+ enumError.ERROR_NOISE,
511
+ enumError.ERROR_SENSITIVITY_ATTENUATION -> {
512
+ Log.d("handleGlucoseError", "Weak signal detected")
513
+ DeviceStatus.WEAK_SIGNAL.id
514
+ }
515
+
516
+ else -> {
517
+ Log.d(
518
+ "handleGlucoseError",
519
+ "Common error detected: ${pocGlucose.errorCode}"
520
+ )
521
+ DeviceStatus.ERROR_COMMON.id
522
+ }
523
+ }
524
+
525
+ postEventDataToAPI(it, statusId, it.qrMessage)
526
+ resetDebounceTimer()
527
+ } ?: run {
528
+ Log.e(
529
+ "handleGlucoseError",
530
+ "Device info not found for deviceId: ${pocGlucose.deviceId}"
531
+ )
532
+ }
533
+ } catch (e: Exception) {
534
+ Log.e("handleGlucoseError", "Error handling glucose error: ${e.message}")
535
+ e.printStackTrace()
451
536
  }
537
+ }
452
538
 
453
- postEventDataToAPI(it, statusId, it.qrMessage)
454
- resetDebounceTimer()
455
- } ?: run {
456
- Log.e(
457
- "handleGlucoseError",
458
- "Device info not found for deviceId: ${pocGlucose.deviceId}"
459
- )
460
- }
461
- } catch (e: Exception) {
462
- Log.e("handleGlucoseError", "Error handling glucose error: ${e.message}")
463
- e.printStackTrace()
539
+
540
+ @ReactMethod
541
+ fun observeAllGlucoseData(token: String) {
542
+ userToken = token
543
+
544
+ // FIX: Ensure proper cleanup and reset state
545
+ stopObservingGlucoseData()
546
+
547
+ // Add a small delay to ensure cleanup is complete
548
+ Handler(Looper.getMainLooper()).postDelayed({
549
+ try {
550
+ val lastSyncData = prefsHelper.lastSyncData
551
+ Log.d("lastSyncData: ", Gson().toJson(lastSyncData).toString())
552
+
553
+ if (lastSyncData != null) {
554
+ CoroutineScope(Dispatchers.IO).launch {
555
+ val glucoseData = mModel.getGlucoseBetweenTime(lastSyncData.lastSyncTime)
556
+ if (glucoseData != null && glucoseData.isNotEmpty()) {
557
+ processBatchDataAndStartObserver(glucoseData)
558
+ } else {
559
+ Log.d(
560
+ "observeAllGlucoseData",
561
+ "No historical data found, starting live observation"
562
+ )
563
+ Handler(Looper.getMainLooper()).post {
564
+ observeGlucoseData(userToken)
565
+ }
566
+ }
567
+ }
568
+ } else {
569
+ observeGlucoseData(userToken)
570
+ }
571
+ } catch (e: Exception) {
572
+ Log.e("observeAllGlucoseData", "observeAllGlucoseData Error: ${e.message}")
573
+ observeGlucoseData(userToken)
574
+ }
575
+ }, 100) // Small delay to ensure cleanup
464
576
  }
465
- }
466
577
 
578
+ // New method to handle batch processing and ensure proper sequencing
579
+ private suspend fun processBatchDataAndStartObserver(dataList: List<PocGlucose>) {
580
+ try {
581
+ Log.d(
582
+ "processBatchDataAndStartObserver",
583
+ "Starting batch processing with ${dataList.size} records"
584
+ )
467
585
 
468
- @ReactMethod
469
- fun observeAllGlucoseData(token: String) {
470
- userToken = token
586
+ val success = processBatchDataSynchronously(dataList)
471
587
 
472
- // Stop current observation to prevent duplicates
473
- stopObservingGlucoseData()
588
+ if (success) {
589
+ Log.d("processBatchDataAndStartObserver", "Batch processing completed successfully")
590
+ } else {
591
+ Log.w("processBatchDataAndStartObserver", "Batch processing had failures")
592
+ }
474
593
 
475
- try {
476
- val lastSyncData = prefsHelper.lastSyncData
477
- Log.d("lastSyncData: ", Gson().toJson(lastSyncData).toString())
594
+ // Ensure we're on main thread and not already observing
595
+ Handler(Looper.getMainLooper()).post {
596
+ if (!isObserving) {
597
+ Log.d(
598
+ "processBatchDataAndStartObserver",
599
+ "Starting live observer after batch completion"
600
+ )
601
+ observeGlucoseData(userToken)
602
+ } else {
603
+ Log.d(
604
+ "processBatchDataAndStartObserver",
605
+ "Already observing, skipping duplicate observer setup"
606
+ )
607
+ }
608
+ }
478
609
 
479
- if (lastSyncData != null) {
480
- CoroutineScope(Dispatchers.IO).launch {
481
- val glucoseData = mModel.getGlucoseBetweenTime(lastSyncData.lastSyncTime)
482
- if (glucoseData != null && glucoseData.isNotEmpty()) {
483
- // Process batch data and wait for completion
484
- processBatchDataAndStartObserver(glucoseData)
485
- } else {
486
- Log.d("observeAllGlucoseData", "No historical data found, starting live observation")
487
- // Start live observation immediately if no historical data
610
+ } catch (e: Exception) {
611
+ Log.e("processBatchDataAndStartObserver", "Error in batch processing: ${e.message}")
612
+ // Start live observation even on error
488
613
  Handler(Looper.getMainLooper()).post {
489
- observeGlucoseData(userToken)
614
+ if (!isObserving) {
615
+ observeGlucoseData(userToken)
616
+ }
490
617
  }
491
- }
492
618
  }
493
- } else {
494
- // No sync data exists, start live observation
495
- observeGlucoseData(userToken)
496
- }
497
- } catch (e: Exception) {
498
- Log.e("observeAllGlucoseData", "observeAllGlucoseData Error: ${e.message}")
499
- // Fallback to live observation on error
500
- observeGlucoseData(userToken)
501
619
  }
502
- }
503
620
 
504
- // New method to handle batch processing and ensure proper sequencing
505
- private suspend fun processBatchDataAndStartObserver(dataList: List<PocGlucose>) {
506
- try {
507
- // Process all batches
508
- val success = processBatchDataSynchronously(dataList)
621
+ @ReactMethod
622
+ fun resetCgmState() {
623
+ Log.d("resetCgmState", "Resetting CGM state for logout")
509
624
 
510
- // Only start live observer after batch processing is completely done
511
- if (success) {
512
- Log.d(
513
- "processBatchDataAndStartObserver",
514
- "Batch processing completed successfully, starting live observer"
515
- )
516
- } else {
517
- Log.w(
518
- "processBatchDataAndStartObserver",
519
- "Batch processing had failures, still starting live observer"
520
- )
521
- }
625
+ try {
626
+ // Stop all observations
627
+ stopObservingGlucoseData()
522
628
 
523
- // Start live observation on main thread after batch completion
524
- Handler(Looper.getMainLooper()).post {
525
- if (!isObserving) {
526
- observeGlucoseData(userToken)
527
- }
528
- }
529
-
530
- } catch (e: Exception) {
531
- Log.e("processBatchDataAndStartObserver", "Error in batch processing: ${e.message}")
532
- // Start live observation even on error
533
- Handler(Looper.getMainLooper()).post {
534
- if (!isObserving) {
535
- observeGlucoseData(userToken)
536
- }
537
- }
538
- }
539
- }
629
+ // Cancel all coroutines
630
+ debounceJob?.cancel()
631
+ debounceJob = null
540
632
 
541
- // Updated batch processing method with better sync control
542
- private suspend fun processBatchDataSynchronously(dataList: List<PocGlucose>): Boolean {
543
- if (dataList.isEmpty()) {
544
- Log.d("processBatchDataSynchronously", "No data to upload")
545
- return true
546
- }
633
+ // Reset user token
634
+ userToken = ""
547
635
 
548
- val batchSize = 40
549
- val chunks = dataList.chunked(batchSize)
550
- var lastSyncedRecord: PocGlucose? = null
551
- var allBatchesSuccessful = true
552
-
553
- Log.d("processBatchDataSynchronously", "Starting batch upload with ${chunks.size} batches")
554
-
555
- for ((index, batch) in chunks.withIndex()) {
556
- try {
557
- val transformedLogs = batch.filter { it.showGlucoseMG > 0 }.map { pocGlucose ->
558
- CgmLog(
559
- timeInMillis = pocGlucose.timeInMillis,
560
- countdownMinutes = pocGlucose.countdownMinutes,
561
- countdownDays = pocGlucose.countdownDays,
562
- hypoglycemiaEarlyWarnMinutes = pocGlucose.hypoglycemiaEarlyWarnMinutes,
563
- showGlucoseMG = pocGlucose.showGlucoseMG,
564
- glucoseId = pocGlucose.glucoseId,
565
- name = pocGlucose.name,
566
- bytes = pocGlucose.bytes,
567
- showGlucose = pocGlucose.showGlucose,
568
- Ib = pocGlucose.ib,
569
- Iw = pocGlucose.iw,
570
- countdownHours = pocGlucose.countdownHours,
571
- T = pocGlucose.t,
572
- year = pocGlucose.year,
573
- month = pocGlucose.month,
574
- day = pocGlucose.day,
575
- hour = pocGlucose.hour,
576
- minute = pocGlucose.minute,
577
- trendObject = com.mytatvarnsdk.model.TrendObject(
578
- trendId = pocGlucose.trend.trendId,
579
- drawableId = pocGlucose.trend.drawableId,
580
- widgetImg = pocGlucose.trend.widgetImg,
581
- apsChangeRate = pocGlucose.trend.apsChangeRate
582
- ),
583
- glucoseStatusObject = com.mytatvarnsdk.model.GlucoseStatusObject(
584
- statusId = pocGlucose.glucoseStatus.statusId
585
- ),
586
- errorObject = com.mytatvarnsdk.model.ErrorObject(
587
- errorId = pocGlucose.errorCode.errorId,
588
- sound = pocGlucose.errorCode.sound
589
- )
590
- )
636
+ // Reset device status
637
+ lastDeviceStatus = null
638
+
639
+ // Clear any cached data if needed
640
+ // prefsHelper.clearCache() // if you have such method
641
+
642
+ } catch (e: Exception) {
643
+ Log.e("resetCgmState", "Error resetting CGM state: ${e.message}")
591
644
  }
645
+ }
592
646
 
593
- if (transformedLogs.isEmpty()) {
594
- Log.d("processBatchDataSynchronously", "Batch $index skipped - no valid glucose readings")
595
- continue
647
+ // Updated batch processing method with better sync control
648
+ private suspend fun processBatchDataSynchronously(dataList: List<PocGlucose>): Boolean {
649
+ if (dataList.isEmpty()) {
650
+ Log.d("processBatchDataSynchronously", "No data to upload")
651
+ return true
596
652
  }
597
653
 
598
- val allResult = AllCGMLogRequest(vendor = "GoodFlip", logs = transformedLogs)
599
- val json = Gson().toJson(allResult)
654
+ val batchSize = 40
655
+ val chunks = dataList.chunked(batchSize)
656
+ var lastSyncedRecord: PocGlucose? = null
657
+ var allBatchesSuccessful = true
658
+
659
+ Log.d("processBatchDataSynchronously", "Starting batch upload with ${chunks.size} batches")
660
+
661
+ for ((index, batch) in chunks.withIndex()) {
662
+ try {
663
+ val transformedLogs = batch.filter { it.showGlucoseMG > 0 }.map { pocGlucose ->
664
+ CgmLog(
665
+ timeInMillis = pocGlucose.timeInMillis,
666
+ countdownMinutes = pocGlucose.countdownMinutes,
667
+ countdownDays = pocGlucose.countdownDays,
668
+ hypoglycemiaEarlyWarnMinutes = pocGlucose.hypoglycemiaEarlyWarnMinutes,
669
+ showGlucoseMG = pocGlucose.showGlucoseMG,
670
+ glucoseId = pocGlucose.glucoseId,
671
+ name = pocGlucose.name,
672
+ bytes = pocGlucose.bytes,
673
+ showGlucose = pocGlucose.showGlucose,
674
+ Ib = pocGlucose.ib,
675
+ Iw = pocGlucose.iw,
676
+ countdownHours = pocGlucose.countdownHours,
677
+ T = pocGlucose.t,
678
+ year = pocGlucose.year,
679
+ month = pocGlucose.month,
680
+ day = pocGlucose.day,
681
+ hour = pocGlucose.hour,
682
+ minute = pocGlucose.minute,
683
+ trendObject = com.mytatvarnsdk.model.TrendObject(
684
+ trendId = pocGlucose.trend.trendId,
685
+ drawableId = pocGlucose.trend.drawableId,
686
+ widgetImg = pocGlucose.trend.widgetImg,
687
+ apsChangeRate = pocGlucose.trend.apsChangeRate
688
+ ),
689
+ glucoseStatusObject = com.mytatvarnsdk.model.GlucoseStatusObject(
690
+ statusId = pocGlucose.glucoseStatus.statusId
691
+ ),
692
+ errorObject = com.mytatvarnsdk.model.ErrorObject(
693
+ errorId = pocGlucose.errorCode.errorId,
694
+ sound = pocGlucose.errorCode.sound
695
+ )
696
+ )
697
+ }
698
+
699
+ if (transformedLogs.isEmpty()) {
700
+ Log.d(
701
+ "processBatchDataSynchronously",
702
+ "Batch $index skipped - no valid glucose readings"
703
+ )
704
+ continue
705
+ }
706
+
707
+ val allResult = AllCGMLogRequest(vendor = "GoodFlip", logs = transformedLogs)
708
+ val json = Gson().toJson(allResult)
709
+
710
+ Log.d(
711
+ "Batch Upload",
712
+ "Processing batch $index with ${transformedLogs.size} records"
713
+ )
714
+ logLongJson("Batch $index JSON=>>> ", json)
600
715
 
601
- Log.d("Batch Upload", "Processing batch $index with ${transformedLogs.size} records")
602
- logLongJson("Batch $index JSON=>>> ", json)
716
+ val uploadSuccessful = uploadBatchSynchronously(json, index)
603
717
 
604
- val uploadSuccessful = uploadBatchSynchronously(json, index)
718
+ if (uploadSuccessful) {
719
+ lastSyncedRecord = batch.lastOrNull()
720
+ // Update sync metadata after each successful batch
721
+ updateSyncMetadata(lastSyncedRecord)
722
+ Log.d("Batch Upload", "✅ Batch $index uploaded and synced successfully")
723
+ } else {
724
+ allBatchesSuccessful = false
725
+ Log.e("Batch Upload", "❌ Batch $index failed")
726
+ // Continue with next batch instead of breaking (optional based on your needs)
727
+ // break
728
+ }
729
+
730
+ // Rate limiting between batches
731
+ delay(500L)
605
732
 
606
- if (uploadSuccessful) {
607
- lastSyncedRecord = batch.lastOrNull()
608
- // Update sync metadata after each successful batch
609
- updateSyncMetadata(lastSyncedRecord)
610
- Log.d("Batch Upload", "✅ Batch $index uploaded and synced successfully")
611
- } else {
612
- allBatchesSuccessful = false
613
- Log.e("Batch Upload", "❌ Batch $index failed")
614
- // Continue with next batch instead of breaking (optional based on your needs)
615
- // break
733
+ } catch (e: Exception) {
734
+ Log.e("Batch Upload", "❌ Batch $index exception: ${e.message}")
735
+ allBatchesSuccessful = false
736
+ // Continue processing other batches
737
+ }
616
738
  }
617
739
 
618
- // Rate limiting between batches
619
- delay(500L)
740
+ // Handle error status for the last processed record
741
+ lastSyncedRecord?.let { record ->
742
+ if (record.errorCode != enumError.NONE) {
743
+ handleGlucoseError(record)
744
+ }
745
+ }
620
746
 
621
- } catch (e: Exception) {
622
- Log.e("Batch Upload", "❌ Batch $index exception: ${e.message}")
623
- allBatchesSuccessful = false
624
- // Continue processing other batches
625
- }
747
+ Log.d(
748
+ "processBatchDataSynchronously",
749
+ "Batch processing completed. Overall success: $allBatchesSuccessful"
750
+ )
751
+ return allBatchesSuccessful
626
752
  }
627
753
 
628
- // Handle error status for the last processed record
629
- lastSyncedRecord?.let { record ->
630
- if (record.errorCode != enumError.NONE) {
631
- handleGlucoseError(record)
632
- }
633
- }
634
754
 
635
- Log.d(
636
- "processBatchDataSynchronously",
637
- "Batch processing completed. Overall success: $allBatchesSuccessful"
638
- )
639
- return allBatchesSuccessful
640
- }
641
-
642
-
643
- @ReactMethod
644
- fun stopObservingGlucoseData() {
645
- try {
646
- glucoseObserver?.let { observer ->
647
- Handler(Looper.getMainLooper()).post {
648
- try {
649
- mModel.latestGlucose.removeObserver(observer)
650
- isObserving = false
651
- Log.d("stopObservingGlucoseData", "Observer removed successfully")
652
- } catch (e: Exception) {
653
- Log.e("stopObservingGlucoseData", "Error removing observer: ${e.message}")
654
- }
755
+ @ReactMethod
756
+ fun stopObservingGlucoseData() {
757
+ Log.d("stopObservingGlucoseData", "Stopping glucose data observation")
758
+
759
+ try {
760
+ // Cancel any ongoing coroutines
761
+ debounceJob?.cancel()
762
+ debounceJob = null
763
+
764
+ // Remove observer on main thread with completion callback
765
+ glucoseObserver?.let { observer ->
766
+ Handler(Looper.getMainLooper()).post {
767
+ try {
768
+ mModel.latestGlucose.removeObserver(observer)
769
+ isObserving = false
770
+ Log.d("stopObservingGlucoseData", "Observer removed successfully")
771
+ } catch (e: Exception) {
772
+ Log.e("stopObservingGlucoseData", "Error removing observer: ${e.message}")
773
+ }
774
+ }
775
+ }
776
+
777
+ // Reset observer reference
778
+ glucoseObserver = null
779
+
780
+ // Reset last device status
781
+ lastDeviceStatus = null
782
+
783
+ } catch (e: Exception) {
784
+ Log.e("stopObservingGlucoseData", "Error stopping observer: ${e.message}")
655
785
  }
656
- }
657
- glucoseObserver = null
658
- } catch (e: Exception) {
659
- Log.e("stopObservingGlucoseData", "Error stopping observer: ${e.message}")
660
786
  }
661
- }
662
-
663
- // Helper method for synchronous batch upload
664
- private suspend fun uploadBatchSynchronously(json: String, batchIndex: Int): Boolean {
665
- return suspendCoroutine { continuation ->
666
- try {
667
- authenticateSDKService.postCGMData(
668
- environment = if ("uat".uppercase() == "PROD") TATVA_ENVIRONMENT.PROD else TATVA_ENVIRONMENT.STAGE,
669
- data = json,
670
- token = userToken,
671
- responseListener = object : AuthenticateSDKService.ResponseListener {
672
- override fun onResponseSuccess(response: String) {
673
- continuation.resume(true)
674
- }
675
787
 
676
- override fun onResponseFail() {
677
- continuation.resume(false)
788
+ // Helper method for synchronous batch upload
789
+ private suspend fun uploadBatchSynchronously(json: String, batchIndex: Int): Boolean {
790
+ return suspendCoroutine { continuation ->
791
+ try {
792
+ authenticateSDKService.postCGMData(
793
+ environment = if ("uat".uppercase() == "PROD") TATVA_ENVIRONMENT.PROD else TATVA_ENVIRONMENT.STAGE,
794
+ data = json,
795
+ token = userToken,
796
+ responseListener = object : AuthenticateSDKService.ResponseListener {
797
+ override fun onResponseSuccess(response: String) {
798
+ continuation.resume(true)
799
+ }
800
+
801
+ override fun onResponseFail() {
802
+ continuation.resume(false)
803
+ }
804
+ }
805
+ )
806
+ } catch (e: Exception) {
807
+ Log.e("uploadBatchSynchronously", "Exception in batch $batchIndex: ${e.message}")
808
+ continuation.resume(false)
678
809
  }
679
- }
680
- )
681
- } catch (e: Exception) {
682
- Log.e("uploadBatchSynchronously", "Exception in batch $batchIndex: ${e.message}")
683
- continuation.resume(false)
684
- }
810
+ }
685
811
  }
686
- }
687
-
688
- private fun updateSyncMetadata(lastRecord: PocGlucose?) {
689
- lastRecord?.let {
690
- try {
691
- val syncData = SyncMeta(
692
- Date().time,
693
- it.timeInMillis,
694
- it.deviceId,
695
- it.glucoseId
696
- )
697
- prefsHelper.lastSyncData = syncData
698
- Log.d(
699
- "Sync Metadata",
700
- "Sync metadata updated: glucoseId=${it.glucoseId}, time=${it.timeInMillis}"
701
- )
702
- } catch (e: Exception) {
703
- Log.e("updateSyncMetadata", "Error updating sync metadata: ${e.message}")
704
- }
812
+
813
+ private fun updateSyncMetadata(lastRecord: PocGlucose?) {
814
+ lastRecord?.let {
815
+ try {
816
+ val syncData = SyncMeta(
817
+ Date().time,
818
+ it.timeInMillis,
819
+ it.deviceId,
820
+ it.glucoseId
821
+ )
822
+ prefsHelper.lastSyncData = syncData
823
+ Log.d(
824
+ "Sync Metadata",
825
+ "Sync metadata updated: glucoseId=${it.glucoseId}, time=${it.timeInMillis}"
826
+ )
827
+ } catch (e: Exception) {
828
+ Log.e("updateSyncMetadata", "Error updating sync metadata: ${e.message}")
829
+ }
830
+ }
705
831
  }
706
- }
707
832
 
708
833
 
709
- fun logLongJson(tag: String, message: String) {
710
- val maxLogSize = 4000
711
- for (i in 0..message.length / maxLogSize) {
712
- val start = i * maxLogSize
713
- val end = (i + 1) * maxLogSize
714
- if (start < message.length) {
715
- Log.d(tag, message.substring(start, minOf(end, message.length)))
716
- }
834
+ fun logLongJson(tag: String, message: String) {
835
+ val maxLogSize = 4000
836
+ for (i in 0..message.length / maxLogSize) {
837
+ val start = i * maxLogSize
838
+ val end = (i + 1) * maxLogSize
839
+ if (start < message.length) {
840
+ Log.d(tag, message.substring(start, minOf(end, message.length)))
841
+ }
842
+ }
717
843
  }
718
- }
719
-
720
- fun mapToDto(glucose: PocGlucose): GlucoseLog {
721
- val dto: GlucoseLog = GlucoseLog()
722
- dto.timeInMillis = glucose.getTimeInMillis()
723
- dto.countdownMinutes = glucose.getCountdownMinutes()
724
- dto.countdownHours = glucose.getCountdownHours()
725
- dto.countdownDays = glucose.getCountdownDays()
726
- dto.hypoglycemiaEarlyWarnMinutes = glucose.getHypoglycemiaEarlyWarnMinutes()
727
- dto.showGlucoseMG = glucose.getShowGlucoseMG()
728
- dto.glucoseId = glucose.getGlucoseId()
729
- dto.name = glucose.getName()
730
- dto.showGlucose = glucose.getShowGlucose()
731
- dto.Ib = glucose.getIb()
732
- dto.Iw = glucose.getIw()
733
- dto.T = glucose.getT()
734
- dto.year = glucose.getYear()
735
- dto.month = glucose.getMonth()
736
- dto.day = glucose.getDay()
737
- dto.hour = glucose.getHour()
738
- dto.minute = glucose.getMinute()
739
-
740
- // Convert byte[] to List<Integer>
741
- dto.bytes = ArrayList()
742
- for (b in glucose.getBytes()) {
743
- dto.bytes?.add(b.toInt() and 0xFF) // Prevent negative values
844
+
845
+ fun mapToDto(glucose: PocGlucose): GlucoseLog {
846
+ val dto: GlucoseLog = GlucoseLog()
847
+ dto.timeInMillis = glucose.getTimeInMillis()
848
+ dto.countdownMinutes = glucose.getCountdownMinutes()
849
+ dto.countdownHours = glucose.getCountdownHours()
850
+ dto.countdownDays = glucose.getCountdownDays()
851
+ dto.hypoglycemiaEarlyWarnMinutes = glucose.getHypoglycemiaEarlyWarnMinutes()
852
+ dto.showGlucoseMG = glucose.getShowGlucoseMG()
853
+ dto.glucoseId = glucose.getGlucoseId()
854
+ dto.name = glucose.getName()
855
+ dto.showGlucose = glucose.getShowGlucose()
856
+ dto.Ib = glucose.getIb()
857
+ dto.Iw = glucose.getIw()
858
+ dto.T = glucose.getT()
859
+ dto.year = glucose.getYear()
860
+ dto.month = glucose.getMonth()
861
+ dto.day = glucose.getDay()
862
+ dto.hour = glucose.getHour()
863
+ dto.minute = glucose.getMinute()
864
+
865
+ // Convert byte[] to List<Integer>
866
+ dto.bytes = ArrayList()
867
+ for (b in glucose.getBytes()) {
868
+ dto.bytes?.add(b.toInt() and 0xFF) // Prevent negative values
869
+ }
870
+
871
+ // Trend
872
+ val trendObj: TrendObject = TrendObject()
873
+ trendObj.trendId = glucose.getTrend().getTrendId()
874
+ trendObj.drawableId = glucose.getTrend().getDrawableId()
875
+ trendObj.widgetImg = glucose.getTrend().getWidgetImg()
876
+ trendObj.apsChangeRate = glucose.getTrend().getApsChangeRate()
877
+ dto.trendObject = trendObj
878
+
879
+ // Status
880
+ val statusObj: GlucoseStatusObject = GlucoseStatusObject()
881
+ statusObj.statusId = glucose.getGlucoseStatus().getStatusId()
882
+ dto.glucoseStatusObject = statusObj
883
+
884
+ // Error
885
+ val errorObj: ErrorObject = ErrorObject()
886
+ errorObj.errorId = glucose.getErrorCode().getErrorId()
887
+ errorObj.sound = glucose.getErrorCode().getSound().toString()
888
+ dto.errorObject = errorObj
889
+
890
+ return dto
744
891
  }
745
892
 
746
- // Trend
747
- val trendObj: TrendObject = TrendObject()
748
- trendObj.trendId = glucose.getTrend().getTrendId()
749
- trendObj.drawableId = glucose.getTrend().getDrawableId()
750
- trendObj.widgetImg = glucose.getTrend().getWidgetImg()
751
- trendObj.apsChangeRate = glucose.getTrend().getApsChangeRate()
752
- dto.trendObject = trendObj
753
-
754
- // Status
755
- val statusObj: GlucoseStatusObject = GlucoseStatusObject()
756
- statusObj.statusId = glucose.getGlucoseStatus().getStatusId()
757
- dto.glucoseStatusObject = statusObj
758
-
759
- // Error
760
- val errorObj: ErrorObject = ErrorObject()
761
- errorObj.errorId = glucose.getErrorCode().getErrorId()
762
- errorObj.sound = glucose.getErrorCode().getSound().toString()
763
- dto.errorObject = errorObj
764
-
765
- return dto
766
- }
767
-
768
-
769
- @ReactMethod
770
- fun sendDataToReact(data: String, status: String, eventName: String) {
771
- Log.d("sendDataToReact: data ", data)
772
-
773
- try {
774
- val map: WritableMap = Arguments.createMap().apply {
775
- putString("data", data)
776
- putString("status", status)
777
- }
778
-
779
- Log.d("sendDataToReact: ", map.toString())
780
-
781
- mReactContext?.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter::class.java)
782
- ?.emit(eventName, map)
783
- } catch (e: Exception) {
784
- Log.e("Error sendDataToReact: ", e.message.toString())
785
- e.printStackTrace()
893
+
894
+ @ReactMethod
895
+ fun sendDataToReact(data: String, status: String, eventName: String) {
896
+ Log.d("sendDataToReact: data ", data)
897
+
898
+ try {
899
+ val map: WritableMap = Arguments.createMap().apply {
900
+ putString("data", data)
901
+ putString("status", status)
902
+ }
903
+
904
+ Log.d("sendDataToReact: ", map.toString())
905
+
906
+ mReactContext?.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter::class.java)
907
+ ?.emit(eventName, map)
908
+ } catch (e: Exception) {
909
+ Log.e("Error sendDataToReact: ", e.message.toString())
910
+ e.printStackTrace()
911
+ }
786
912
  }
787
- }
913
+
788
914
 
789
915
  }
790
916