react-native-spike-sdk 2.4.4 → 2.5.0
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/android/src/main/java/com/spikesdk/SpikeSdkModule.kt +174 -124
- package/ios/SpikeDataTypeMapper.swift +16 -0
- package/lib/commonjs/DataModels/SpikeDataTypes.js +2 -1
- package/lib/commonjs/DataModels/SpikeDataTypes.js.map +1 -1
- package/lib/commonjs/DataModels/SpikeEcgDataEntry.js +2 -0
- package/lib/commonjs/DataModels/SpikeEcgDataEntry.js.map +1 -0
- package/lib/commonjs/DataTypes/SpikeDataType.js +5 -1
- package/lib/commonjs/DataTypes/SpikeDataType.js.map +1 -1
- package/lib/commonjs/SpikeConnection.js +48 -0
- package/lib/commonjs/SpikeConnection.js.map +1 -1
- package/lib/module/DataModels/SpikeDataTypes.js +3 -2
- package/lib/module/DataModels/SpikeDataTypes.js.map +1 -1
- package/lib/module/DataModels/SpikeEcgDataEntry.js +2 -0
- package/lib/module/DataModels/SpikeEcgDataEntry.js.map +1 -0
- package/lib/module/DataTypes/SpikeDataType.js +3 -0
- package/lib/module/DataTypes/SpikeDataType.js.map +1 -1
- package/lib/module/SpikeConnection.js +49 -1
- package/lib/module/SpikeConnection.js.map +1 -1
- package/lib/typescript/DataModels/SpikeDataTypes.d.ts +2 -1
- package/lib/typescript/DataModels/SpikeDataTypes.d.ts.map +1 -1
- package/lib/typescript/DataModels/SpikeEcgDataEntry.d.ts +13 -0
- package/lib/typescript/DataModels/SpikeEcgDataEntry.d.ts.map +1 -0
- package/lib/typescript/DataTypes/SpikeDataType.d.ts +6 -1
- package/lib/typescript/DataTypes/SpikeDataType.d.ts.map +1 -1
- package/lib/typescript/SpikeConnection.d.ts +3 -1
- package/lib/typescript/SpikeConnection.d.ts.map +1 -1
- package/lib/typescript/SpikeConnectionTypes.d.ts +12 -4
- package/lib/typescript/SpikeConnectionTypes.d.ts.map +1 -1
- package/package.json +2 -2
- package/src/DataModels/SpikeDataTypes.ts +2 -0
- package/src/DataModels/SpikeEcgDataEntry.ts +12 -0
- package/src/DataTypes/SpikeDataType.ts +9 -1
- package/src/SpikeConnection.ts +60 -0
- package/src/SpikeConnectionTypes.ts +14 -3
|
@@ -18,6 +18,8 @@ import kotlinx.coroutines.CoroutineScope
|
|
|
18
18
|
import kotlinx.coroutines.Dispatchers
|
|
19
19
|
import kotlinx.coroutines.SupervisorJob
|
|
20
20
|
import kotlinx.coroutines.launch
|
|
21
|
+
import kotlinx.coroutines.sync.Mutex
|
|
22
|
+
import kotlinx.coroutines.sync.withLock
|
|
21
23
|
import java.time.OffsetDateTime
|
|
22
24
|
import java.util.UUID
|
|
23
25
|
|
|
@@ -32,7 +34,8 @@ fun <I, O> ComponentActivity.registerActivityResultLauncher(
|
|
|
32
34
|
class SpikeSdkModule(reactContext: ReactApplicationContext) :
|
|
33
35
|
ReactContextBaseJavaModule(reactContext), LifecycleEventListener {
|
|
34
36
|
|
|
35
|
-
|
|
37
|
+
// Do not use this directly, use `addConnection` and `getConnection` instead
|
|
38
|
+
private val _connections = mutableMapOf<String, SpikeConnection>()
|
|
36
39
|
|
|
37
40
|
private val scope = CoroutineScope(SupervisorJob() + Dispatchers.Main.immediate)
|
|
38
41
|
|
|
@@ -85,7 +88,7 @@ class SpikeSdkModule(reactContext: ReactApplicationContext) :
|
|
|
85
88
|
} else {
|
|
86
89
|
null
|
|
87
90
|
}
|
|
88
|
-
|
|
91
|
+
addConnection(connection = SpikeConnection.createConnection(
|
|
89
92
|
context = reactApplicationContext,
|
|
90
93
|
authToken = authToken,
|
|
91
94
|
customerEndUserId = customerEndUserId,
|
|
@@ -93,7 +96,7 @@ class SpikeSdkModule(reactContext: ReactApplicationContext) :
|
|
|
93
96
|
callbackUrl = callbackUrl,
|
|
94
97
|
env = SpikeEnvironment.PROD,
|
|
95
98
|
logger = logger,
|
|
96
|
-
)
|
|
99
|
+
), uuid = uuid)
|
|
97
100
|
promise.resolve(uuid)
|
|
98
101
|
} catch (e: SpikeExceptions) {
|
|
99
102
|
promise.reject(e.mapException(), e.message)
|
|
@@ -103,38 +106,43 @@ class SpikeSdkModule(reactContext: ReactApplicationContext) :
|
|
|
103
106
|
|
|
104
107
|
@ReactMethod
|
|
105
108
|
fun getAppId(uuid: String, promise: Promise) {
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
109
|
+
scope.launch {
|
|
110
|
+
try {
|
|
111
|
+
val connection = getConnection(uuid) ?: return@launch promise.reject(
|
|
112
|
+
SpikeExceptions.SpikeException(
|
|
113
|
+
"Connection not found"
|
|
114
|
+
).mapException(), "Connection not found"
|
|
115
|
+
)
|
|
116
|
+
val appId = connection.getAppId()
|
|
117
|
+
promise.resolve(appId)
|
|
118
|
+
} catch (e: SpikeExceptions) {
|
|
119
|
+
promise.reject(e.mapException(), e.message)
|
|
120
|
+
}
|
|
116
121
|
}
|
|
117
122
|
}
|
|
118
123
|
|
|
119
124
|
@ReactMethod
|
|
120
125
|
fun getSpikeEndUserId(uuid: String, promise: Promise) {
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
126
|
+
scope.launch {
|
|
127
|
+
try {
|
|
128
|
+
val connection = getConnection(uuid) ?: return@launch promise.reject(
|
|
129
|
+
SpikeExceptions.SpikeException(
|
|
130
|
+
"Connection not found"
|
|
131
|
+
).mapException(), "Connection not found"
|
|
132
|
+
)
|
|
133
|
+
val spikeEndUserId = connection.getSpikeUserId()
|
|
134
|
+
promise.resolve(spikeEndUserId)
|
|
135
|
+
} catch (e: SpikeExceptions) {
|
|
136
|
+
promise.reject(e.mapException(), e.message)
|
|
137
|
+
}
|
|
131
138
|
}
|
|
132
139
|
}
|
|
133
140
|
|
|
134
141
|
@ReactMethod
|
|
135
142
|
fun getCustomerEndUserId(uuid: String, promise: Promise) {
|
|
143
|
+
scope.launch {
|
|
136
144
|
try {
|
|
137
|
-
val connection =
|
|
145
|
+
val connection = getConnection(uuid) ?: return@launch promise.reject(
|
|
138
146
|
SpikeExceptions.SpikeException(
|
|
139
147
|
"Connection not found"
|
|
140
148
|
).mapException(), "Connection not found"
|
|
@@ -144,21 +152,23 @@ class SpikeSdkModule(reactContext: ReactApplicationContext) :
|
|
|
144
152
|
} catch (e: SpikeExceptions) {
|
|
145
153
|
promise.reject(e.mapException(), e.message)
|
|
146
154
|
}
|
|
155
|
+
}
|
|
147
156
|
}
|
|
148
157
|
|
|
149
158
|
@ReactMethod
|
|
150
159
|
fun getCallbackUrl(uuid: String, promise: Promise) {
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
160
|
+
scope.launch {
|
|
161
|
+
try {
|
|
162
|
+
val connection = getConnection(uuid) ?: return@launch promise.reject(
|
|
154
163
|
SpikeExceptions.SpikeException(
|
|
155
164
|
"Connection not found"
|
|
156
165
|
).mapException(), "Connection not found"
|
|
157
166
|
)
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
167
|
+
val callbackUrl = connection.getPostbackUrl()
|
|
168
|
+
promise.resolve(callbackUrl)
|
|
169
|
+
} catch (e: SpikeExceptions) {
|
|
170
|
+
promise.reject(e.mapException(), e.message)
|
|
171
|
+
}
|
|
162
172
|
}
|
|
163
173
|
}
|
|
164
174
|
|
|
@@ -167,7 +177,7 @@ class SpikeSdkModule(reactContext: ReactApplicationContext) :
|
|
|
167
177
|
fun close(uuid: String, promise: Promise) {
|
|
168
178
|
scope.launch {
|
|
169
179
|
try {
|
|
170
|
-
val connection =
|
|
180
|
+
val connection = getConnection(uuid) ?: return@launch promise.reject(
|
|
171
181
|
SpikeExceptions.SpikeException(
|
|
172
182
|
"Connection not found"
|
|
173
183
|
).mapException(), "Connection not found"
|
|
@@ -190,7 +200,7 @@ class SpikeSdkModule(reactContext: ReactApplicationContext) :
|
|
|
190
200
|
) {
|
|
191
201
|
scope.launch {
|
|
192
202
|
try {
|
|
193
|
-
val connection =
|
|
203
|
+
val connection = getConnection(connectionUUID) ?: return@launch promise.reject(
|
|
194
204
|
SpikeExceptions.SpikeException(
|
|
195
205
|
"Connection not found"
|
|
196
206
|
).mapException(), "Connection not found"
|
|
@@ -217,7 +227,7 @@ class SpikeSdkModule(reactContext: ReactApplicationContext) :
|
|
|
217
227
|
) {
|
|
218
228
|
scope.launch {
|
|
219
229
|
try {
|
|
220
|
-
val connection =
|
|
230
|
+
val connection = getConnection(connectionUUID) ?: return@launch promise.reject(
|
|
221
231
|
SpikeExceptions.SpikeException(
|
|
222
232
|
"Connection not found"
|
|
223
233
|
).mapException(), "Connection not found"
|
|
@@ -242,7 +252,7 @@ class SpikeSdkModule(reactContext: ReactApplicationContext) :
|
|
|
242
252
|
) {
|
|
243
253
|
scope.launch {
|
|
244
254
|
try {
|
|
245
|
-
val connection =
|
|
255
|
+
val connection = getConnection(connectionUUID) ?: return@launch promise.reject(
|
|
246
256
|
SpikeExceptions.SpikeException(
|
|
247
257
|
"Connection not found"
|
|
248
258
|
).mapException(), "Connection not found"
|
|
@@ -265,7 +275,7 @@ class SpikeSdkModule(reactContext: ReactApplicationContext) :
|
|
|
265
275
|
) {
|
|
266
276
|
scope.launch {
|
|
267
277
|
try {
|
|
268
|
-
val connection =
|
|
278
|
+
val connection = getConnection(connectionUUID) ?: return@launch promise.reject(
|
|
269
279
|
SpikeExceptions.SpikeException(
|
|
270
280
|
"Connection not found"
|
|
271
281
|
).mapException(), "Connection not found"
|
|
@@ -282,16 +292,18 @@ class SpikeSdkModule(reactContext: ReactApplicationContext) :
|
|
|
282
292
|
|
|
283
293
|
@ReactMethod
|
|
284
294
|
fun manageHealthConnect(connectionUUID: String, promise: Promise) {
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
+
scope.launch {
|
|
296
|
+
try {
|
|
297
|
+
val connection = getConnection(connectionUUID) ?: return@launch promise.reject(
|
|
298
|
+
SpikeExceptions.SpikeException(
|
|
299
|
+
"Connection not found"
|
|
300
|
+
).mapException(), "Connection not found"
|
|
301
|
+
)
|
|
302
|
+
connection.manageHealthConnect()
|
|
303
|
+
promise.resolve(true)
|
|
304
|
+
} catch (e: SpikeExceptions) {
|
|
305
|
+
promise.reject(e.mapException(), e.message)
|
|
306
|
+
}
|
|
295
307
|
}
|
|
296
308
|
}
|
|
297
309
|
|
|
@@ -299,7 +311,7 @@ class SpikeSdkModule(reactContext: ReactApplicationContext) :
|
|
|
299
311
|
fun checkPermissionsGranted(connectionUUID: String, dataType: String, promise: Promise) {
|
|
300
312
|
scope.launch {
|
|
301
313
|
try {
|
|
302
|
-
val connection =
|
|
314
|
+
val connection = getConnection(connectionUUID) ?: return@launch promise.reject(
|
|
303
315
|
SpikeExceptions.SpikeException(
|
|
304
316
|
"Connection not found"
|
|
305
317
|
).mapException(), "Connection not found"
|
|
@@ -320,7 +332,7 @@ class SpikeSdkModule(reactContext: ReactApplicationContext) :
|
|
|
320
332
|
fun getHealthConnectAvailability(connectionUUID: String, promise: Promise) {
|
|
321
333
|
scope.launch {
|
|
322
334
|
try {
|
|
323
|
-
val connection =
|
|
335
|
+
val connection = getConnection(connectionUUID) ?: return@launch promise.reject(
|
|
324
336
|
SpikeExceptions.SpikeException(
|
|
325
337
|
"Connection not found"
|
|
326
338
|
).mapException(), "Connection not found"
|
|
@@ -337,7 +349,7 @@ class SpikeSdkModule(reactContext: ReactApplicationContext) :
|
|
|
337
349
|
fun revokeAllPermissions(connectionUUID: String, promise: Promise) {
|
|
338
350
|
scope.launch {
|
|
339
351
|
try {
|
|
340
|
-
val connection =
|
|
352
|
+
val connection = getConnection(connectionUUID) ?: return@launch promise.reject(
|
|
341
353
|
SpikeExceptions.SpikeException(
|
|
342
354
|
"Connection not found"
|
|
343
355
|
).mapException(), "Connection not found"
|
|
@@ -352,98 +364,117 @@ class SpikeSdkModule(reactContext: ReactApplicationContext) :
|
|
|
352
364
|
|
|
353
365
|
@ReactMethod
|
|
354
366
|
fun requestHealthPermissions(connectionUUID: String, dataType: String, promise: Promise) {
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
val availability = connection.getHealthConnectAvailability()
|
|
370
|
-
if (availability == HealthConnectAvailability.INSTALLED) {
|
|
371
|
-
reactApplicationContext.currentActivity?.startActivityForResult(
|
|
372
|
-
intent,
|
|
373
|
-
REQUEST_CODE
|
|
367
|
+
scope.launch {
|
|
368
|
+
val connection = getConnection(connectionUUID) ?: return@launch promise.reject(
|
|
369
|
+
SpikeExceptions.SpikeException(
|
|
370
|
+
"Connection not found"
|
|
371
|
+
).mapException(), "Connection not found"
|
|
372
|
+
)
|
|
373
|
+
|
|
374
|
+
val permissions =
|
|
375
|
+
connection.getRequiredHealthPermissionsMetadata(dataType.toSpikeDataType())
|
|
376
|
+
|
|
377
|
+
if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.TIRAMISU) {
|
|
378
|
+
val intent = SpikeConnection.requestReadAuthorization().createIntent(
|
|
379
|
+
reactApplicationContext, permissions
|
|
374
380
|
)
|
|
375
|
-
promise.resolve(true)
|
|
376
|
-
} else {
|
|
377
|
-
promise.reject(SpikeExceptions.SpikeException().mapException(), SpikeExceptions.SpikeException().message)
|
|
378
|
-
}
|
|
379
|
-
} else {
|
|
380
|
-
val activity = reactApplicationContext.currentActivity
|
|
381
|
-
if (activity is ComponentActivity) {
|
|
382
|
-
checkPermissionsFor = Triple(connectionUUID, setOf(dataType), promise)
|
|
383
|
-
val launcher =
|
|
384
|
-
activity.registerActivityResultLauncher(
|
|
385
|
-
SpikeConnection.requestReadAuthorization()
|
|
386
|
-
) {
|
|
387
381
|
|
|
382
|
+
val availability = connection.getHealthConnectAvailability()
|
|
383
|
+
if (availability == HealthConnectAvailability.INSTALLED) {
|
|
384
|
+
reactApplicationContext.currentActivity?.startActivityForResult(
|
|
385
|
+
intent,
|
|
386
|
+
REQUEST_CODE
|
|
387
|
+
)
|
|
388
|
+
promise.resolve(true)
|
|
389
|
+
} else {
|
|
390
|
+
promise.reject(
|
|
391
|
+
SpikeExceptions.SpikeException().mapException(),
|
|
392
|
+
SpikeExceptions.SpikeException().message
|
|
393
|
+
)
|
|
394
|
+
}
|
|
395
|
+
} else {
|
|
396
|
+
val activity = reactApplicationContext.currentActivity
|
|
397
|
+
if (activity is ComponentActivity) {
|
|
398
|
+
checkPermissionsFor = Triple(connectionUUID, setOf(dataType), promise)
|
|
399
|
+
val launcher =
|
|
400
|
+
activity.registerActivityResultLauncher(
|
|
401
|
+
SpikeConnection.requestReadAuthorization()
|
|
402
|
+
) {
|
|
403
|
+
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
if (permissions.isNotEmpty()) {
|
|
407
|
+
launcher.launch(permissions)
|
|
408
|
+
} else {
|
|
409
|
+
promise.resolve(false)
|
|
388
410
|
}
|
|
389
|
-
|
|
390
|
-
if (permissions.isNotEmpty()) {
|
|
391
|
-
launcher.launch(permissions)
|
|
392
411
|
} else {
|
|
393
412
|
promise.resolve(false)
|
|
394
413
|
}
|
|
395
|
-
} else {
|
|
396
|
-
promise.resolve(false)
|
|
397
414
|
}
|
|
398
415
|
}
|
|
399
416
|
}
|
|
400
417
|
|
|
401
418
|
@ReactMethod
|
|
402
419
|
fun requestMultipleHealthPermissions(connectionUUID: String, dataTypes: ReadableArray, promise: Promise) {
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
val permissions = mutableSetOf<String>()
|
|
410
|
-
dataTypes.toArrayList().forEach {
|
|
411
|
-
connection.getRequiredHealthPermissionsMetadata((it as String).toSpikeDataType()).forEach {
|
|
412
|
-
permissions.add(it)
|
|
413
|
-
}
|
|
414
|
-
}
|
|
415
|
-
|
|
416
|
-
if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.TIRAMISU) {
|
|
417
|
-
val availability = connection.getHealthConnectAvailability()
|
|
418
|
-
if (permissions.isNotEmpty() && availability == HealthConnectAvailability.INSTALLED) {
|
|
419
|
-
val intent = SpikeConnection.requestReadAuthorization().createIntent(
|
|
420
|
-
reactApplicationContext, permissions
|
|
421
|
-
)
|
|
420
|
+
scope.launch {
|
|
421
|
+
val connection = getConnection(connectionUUID) ?: return@launch promise.reject(
|
|
422
|
+
SpikeExceptions.SpikeException(
|
|
423
|
+
"Connection not found"
|
|
424
|
+
).mapException(), "Connection not found"
|
|
425
|
+
)
|
|
422
426
|
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
promise.reject(SpikeExceptions.SpikeException().mapException(), SpikeExceptions.SpikeException().message)
|
|
427
|
+
val permissions = mutableSetOf<String>()
|
|
428
|
+
dataTypes.toArrayList().forEach {
|
|
429
|
+
connection.getRequiredHealthPermissionsMetadata((it as String).toSpikeDataType())
|
|
430
|
+
.forEach {
|
|
431
|
+
permissions.add(it)
|
|
432
|
+
}
|
|
430
433
|
}
|
|
431
|
-
} else {
|
|
432
|
-
val activity = reactApplicationContext.currentActivity
|
|
433
|
-
if (activity is ComponentActivity) {
|
|
434
|
-
checkPermissionsFor = Triple(connectionUUID, dataTypes.toArrayList().toSet() as Set<String>, promise)
|
|
435
|
-
val launcher =
|
|
436
|
-
activity.registerActivityResultLauncher(
|
|
437
|
-
SpikeConnection.requestReadAuthorization()
|
|
438
|
-
) {
|
|
439
434
|
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
435
|
+
if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.TIRAMISU) {
|
|
436
|
+
val availability = connection.getHealthConnectAvailability()
|
|
437
|
+
if (permissions.isNotEmpty() && availability == HealthConnectAvailability.INSTALLED) {
|
|
438
|
+
val intent = SpikeConnection.requestReadAuthorization().createIntent(
|
|
439
|
+
reactApplicationContext, permissions
|
|
440
|
+
)
|
|
441
|
+
|
|
442
|
+
reactApplicationContext.currentActivity?.startActivityForResult(
|
|
443
|
+
intent,
|
|
444
|
+
REQUEST_CODE
|
|
445
|
+
)
|
|
446
|
+
promise.resolve(true)
|
|
443
447
|
} else {
|
|
444
|
-
promise.reject(
|
|
448
|
+
promise.reject(
|
|
449
|
+
SpikeExceptions.SpikeException().mapException(),
|
|
450
|
+
SpikeExceptions.SpikeException().message
|
|
451
|
+
)
|
|
452
|
+
}
|
|
445
453
|
} else {
|
|
446
|
-
|
|
454
|
+
val activity = reactApplicationContext.currentActivity
|
|
455
|
+
if (activity is ComponentActivity) {
|
|
456
|
+
checkPermissionsFor = Triple(
|
|
457
|
+
connectionUUID,
|
|
458
|
+
dataTypes.toArrayList().toSet() as Set<String>,
|
|
459
|
+
promise
|
|
460
|
+
)
|
|
461
|
+
val launcher =
|
|
462
|
+
activity.registerActivityResultLauncher(
|
|
463
|
+
SpikeConnection.requestReadAuthorization()
|
|
464
|
+
) {
|
|
465
|
+
|
|
466
|
+
}
|
|
467
|
+
if (permissions.isNotEmpty()) {
|
|
468
|
+
launcher.launch(permissions)
|
|
469
|
+
} else {
|
|
470
|
+
promise.reject(
|
|
471
|
+
SpikeExceptions.SpikeException().mapException(),
|
|
472
|
+
SpikeExceptions.SpikeException().message
|
|
473
|
+
)
|
|
474
|
+
}
|
|
475
|
+
} else {
|
|
476
|
+
promise.resolve(false)
|
|
477
|
+
}
|
|
447
478
|
}
|
|
448
479
|
}
|
|
449
480
|
}
|
|
@@ -504,4 +535,23 @@ class SpikeSdkModule(reactContext: ReactApplicationContext) :
|
|
|
504
535
|
const val NAME = "SpikeSdk"
|
|
505
536
|
const val REQUEST_CODE = 4200
|
|
506
537
|
}
|
|
538
|
+
|
|
539
|
+
// Connections
|
|
540
|
+
|
|
541
|
+
private val mutex = Mutex()
|
|
542
|
+
|
|
543
|
+
// Add new connection to the dictionary in a thread-safe manner
|
|
544
|
+
private suspend fun addConnection(connection: SpikeConnection, uuid: String) {
|
|
545
|
+
mutex.withLock {
|
|
546
|
+
_connections[uuid] = connection
|
|
547
|
+
}
|
|
548
|
+
}
|
|
549
|
+
|
|
550
|
+
// Synchronised read for safe multithreaded usage
|
|
551
|
+
private suspend fun getConnection(uuid: String): SpikeConnection? {
|
|
552
|
+
mutex.withLock {
|
|
553
|
+
return _connections[uuid]
|
|
554
|
+
}
|
|
555
|
+
}
|
|
556
|
+
|
|
507
557
|
}
|
|
@@ -29,6 +29,8 @@ class SpikeDataTypeMapper {
|
|
|
29
29
|
return SpikeDataTypes.stepsIntraday
|
|
30
30
|
case "body":
|
|
31
31
|
return SpikeDataTypes.body
|
|
32
|
+
case "ecg":
|
|
33
|
+
return SpikeDataTypes.ecg
|
|
32
34
|
default:
|
|
33
35
|
return SpikeDataTypes.activitiesSummary
|
|
34
36
|
}
|
|
@@ -60,6 +62,8 @@ class SpikeDataTypeMapper {
|
|
|
60
62
|
return "steps_intraday"
|
|
61
63
|
case is SpikeBodyDataType:
|
|
62
64
|
return "body"
|
|
65
|
+
case is SpikeECGDataType:
|
|
66
|
+
return "ecg"
|
|
63
67
|
default:
|
|
64
68
|
return "activities_summary"
|
|
65
69
|
}
|
|
@@ -103,6 +107,9 @@ class SpikeDataTypeMapper {
|
|
|
103
107
|
case "body":
|
|
104
108
|
let value = try await connection.extractData(SpikeDataTypes.body)
|
|
105
109
|
return try? String(data: JSONEncoder().encode(value), encoding: .utf8)
|
|
110
|
+
case "ecg":
|
|
111
|
+
let value = try await connection.extractData(SpikeDataTypes.ecg)
|
|
112
|
+
return try? String(data: JSONEncoder().encode(value), encoding: .utf8)
|
|
106
113
|
default:
|
|
107
114
|
return nil
|
|
108
115
|
}
|
|
@@ -146,6 +153,9 @@ class SpikeDataTypeMapper {
|
|
|
146
153
|
case "body":
|
|
147
154
|
let value = try await connection.extractData(SpikeDataTypes.body, from: from, to: to)
|
|
148
155
|
return try? String(data: JSONEncoder().encode(value), encoding: .utf8)
|
|
156
|
+
case "ecg":
|
|
157
|
+
let value = try await connection.extractData(SpikeDataTypes.ecg, from: from, to: to)
|
|
158
|
+
return try? String(data: JSONEncoder().encode(value), encoding: .utf8)
|
|
149
159
|
default:
|
|
150
160
|
return nil
|
|
151
161
|
}
|
|
@@ -189,6 +199,9 @@ class SpikeDataTypeMapper {
|
|
|
189
199
|
case "body":
|
|
190
200
|
let value = try await connection.extractAndPostData(SpikeDataTypes.body)
|
|
191
201
|
return try? String(data: JSONEncoder().encode(value), encoding: .utf8)
|
|
202
|
+
case "ecg":
|
|
203
|
+
let value = try await connection.extractAndPostData(SpikeDataTypes.ecg)
|
|
204
|
+
return try? String(data: JSONEncoder().encode(value), encoding: .utf8)
|
|
192
205
|
default:
|
|
193
206
|
return nil
|
|
194
207
|
}
|
|
@@ -232,6 +245,9 @@ class SpikeDataTypeMapper {
|
|
|
232
245
|
case "body":
|
|
233
246
|
let value = try await connection.extractAndPostData(SpikeDataTypes.body, from: from, to: to)
|
|
234
247
|
return try? String(data: JSONEncoder().encode(value), encoding: .utf8)
|
|
248
|
+
case "ecg":
|
|
249
|
+
let value = try await connection.extractAndPostData(SpikeDataTypes.ecg, from: from, to: to)
|
|
250
|
+
return try? String(data: JSONEncoder().encode(value), encoding: .utf8)
|
|
235
251
|
default:
|
|
236
252
|
return nil
|
|
237
253
|
}
|
|
@@ -17,6 +17,7 @@ const SpikeDataTypes = exports.SpikeDataTypes = {
|
|
|
17
17
|
sleep: new _SpikeDataType.SpikeSleepDataType(),
|
|
18
18
|
steps: new _SpikeDataType.SpikeStepsDataType(),
|
|
19
19
|
stepsIntraday: new _SpikeDataType.SpikeStepsIntradayDataType(),
|
|
20
|
-
body: new _SpikeDataType.SpikeBodyDataType()
|
|
20
|
+
body: new _SpikeDataType.SpikeBodyDataType(),
|
|
21
|
+
ecg: new _SpikeDataType.SpikeEcgDataType()
|
|
21
22
|
};
|
|
22
23
|
//# sourceMappingURL=SpikeDataTypes.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["_SpikeDataType","require","SpikeDataTypes","exports","activitiesSummary","SpikeActivitiesSummaryDataType","activitiesStream","SpikeActivitiesStreamDataType","breathing","SpikeBreathingDataType","calories","SpikeCaloriesDataType","distance","SpikeDistanceDataType","glucose","SpikeGlucoseDataType","heart","SpikeHeartDataType","oxygenSaturation","SpikeOxygenSaturationDataType","sleep","SpikeSleepDataType","steps","SpikeStepsDataType","stepsIntraday","SpikeStepsIntradayDataType","body","SpikeBodyDataType"],"sourceRoot":"../../../src","sources":["DataModels/SpikeDataTypes.ts"],"mappings":";;;;;;AAAA,IAAAA,cAAA,GAAAC,OAAA;
|
|
1
|
+
{"version":3,"names":["_SpikeDataType","require","SpikeDataTypes","exports","activitiesSummary","SpikeActivitiesSummaryDataType","activitiesStream","SpikeActivitiesStreamDataType","breathing","SpikeBreathingDataType","calories","SpikeCaloriesDataType","distance","SpikeDistanceDataType","glucose","SpikeGlucoseDataType","heart","SpikeHeartDataType","oxygenSaturation","SpikeOxygenSaturationDataType","sleep","SpikeSleepDataType","steps","SpikeStepsDataType","stepsIntraday","SpikeStepsIntradayDataType","body","SpikeBodyDataType","ecg","SpikeEcgDataType"],"sourceRoot":"../../../src","sources":["DataModels/SpikeDataTypes.ts"],"mappings":";;;;;;AAAA,IAAAA,cAAA,GAAAC,OAAA;AAgBO,MAAMC,cAAc,GAAAC,OAAA,CAAAD,cAAA,GAAG;EAC5BE,iBAAiB,EAAE,IAAIC,6CAA8B,CAAC,CAAC;EACvDC,gBAAgB,EAAE,IAAIC,4CAA6B,CAAC,CAAC;EACrDC,SAAS,EAAE,IAAIC,qCAAsB,CAAC,CAAC;EACvCC,QAAQ,EAAE,IAAIC,oCAAqB,CAAC,CAAC;EACrCC,QAAQ,EAAE,IAAIC,oCAAqB,CAAC,CAAC;EACrCC,OAAO,EAAE,IAAIC,mCAAoB,CAAC,CAAC;EACnCC,KAAK,EAAE,IAAIC,iCAAkB,CAAC,CAAC;EAC/BC,gBAAgB,EAAE,IAAIC,4CAA6B,CAAC,CAAC;EACrDC,KAAK,EAAE,IAAIC,iCAAkB,CAAC,CAAC;EAC/BC,KAAK,EAAE,IAAIC,iCAAkB,CAAC,CAAC;EAC/BC,aAAa,EAAE,IAAIC,yCAA0B,CAAC,CAAC;EAC/CC,IAAI,EAAE,IAAIC,gCAAiB,CAAC,CAAC;EAC7BC,GAAG,EAAE,IAAIC,+BAAgB,CAAC;AAC5B,CAAC","ignoreList":[]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":[],"sourceRoot":"../../../src","sources":["DataModels/SpikeEcgDataEntry.ts"],"mappings":"","ignoreList":[]}
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
Object.defineProperty(exports, "__esModule", {
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
|
-
exports.SpikeStepsIntradayDataType = exports.SpikeStepsDataType = exports.SpikeSleepDataType = exports.SpikeOxygenSaturationDataType = exports.SpikeHeartDataType = exports.SpikeGlucoseDataType = exports.SpikeDistanceDataType = exports.SpikeCaloriesDataType = exports.SpikeBreathingDataType = exports.SpikeBodyDataType = exports.SpikeActivitiesSummaryDataType = exports.SpikeActivitiesStreamDataType = void 0;
|
|
6
|
+
exports.SpikeStepsIntradayDataType = exports.SpikeStepsDataType = exports.SpikeSleepDataType = exports.SpikeOxygenSaturationDataType = exports.SpikeHeartDataType = exports.SpikeGlucoseDataType = exports.SpikeEcgDataType = exports.SpikeDistanceDataType = exports.SpikeCaloriesDataType = exports.SpikeBreathingDataType = exports.SpikeBodyDataType = exports.SpikeActivitiesSummaryDataType = exports.SpikeActivitiesStreamDataType = void 0;
|
|
7
7
|
class SpikeActivitiesStreamDataType {
|
|
8
8
|
rawValue = 'activities_stream';
|
|
9
9
|
}
|
|
@@ -52,4 +52,8 @@ class SpikeBodyDataType {
|
|
|
52
52
|
rawValue = 'body';
|
|
53
53
|
}
|
|
54
54
|
exports.SpikeBodyDataType = SpikeBodyDataType;
|
|
55
|
+
class SpikeEcgDataType {
|
|
56
|
+
rawValue = 'ecg';
|
|
57
|
+
}
|
|
58
|
+
exports.SpikeEcgDataType = SpikeEcgDataType;
|
|
55
59
|
//# sourceMappingURL=SpikeDataType.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["SpikeActivitiesStreamDataType","rawValue","exports","SpikeActivitiesSummaryDataType","SpikeBreathingDataType","SpikeCaloriesDataType","SpikeDistanceDataType","SpikeGlucoseDataType","SpikeHeartDataType","SpikeOxygenSaturationDataType","SpikeSleepDataType","SpikeStepsDataType","SpikeStepsIntradayDataType","SpikeBodyDataType"],"sourceRoot":"../../../src","sources":["DataTypes/SpikeDataType.ts"],"mappings":";;;;;;
|
|
1
|
+
{"version":3,"names":["SpikeActivitiesStreamDataType","rawValue","exports","SpikeActivitiesSummaryDataType","SpikeBreathingDataType","SpikeCaloriesDataType","SpikeDistanceDataType","SpikeGlucoseDataType","SpikeHeartDataType","SpikeOxygenSaturationDataType","SpikeSleepDataType","SpikeStepsDataType","SpikeStepsIntradayDataType","SpikeBodyDataType","SpikeEcgDataType"],"sourceRoot":"../../../src","sources":["DataTypes/SpikeDataType.ts"],"mappings":";;;;;;AA6BO,MAAMA,6BAA6B,CAAC;EACzCC,QAAQ,GAAwB,mBAAmB;AAErD;AAACC,OAAA,CAAAF,6BAAA,GAAAA,6BAAA;AAEM,MAAMG,8BAA8B,CAAC;EAC1CF,QAAQ,GAAwB,oBAAoB;AAEtD;AAACC,OAAA,CAAAC,8BAAA,GAAAA,8BAAA;AAEM,MAAMC,sBAAsB,CAAC;EAClCH,QAAQ,GAAwB,WAAW;AAE7C;AAACC,OAAA,CAAAE,sBAAA,GAAAA,sBAAA;AAEM,MAAMC,qBAAqB,CAAC;EACjCJ,QAAQ,GAAwB,UAAU;AAE5C;AAACC,OAAA,CAAAG,qBAAA,GAAAA,qBAAA;AAEM,MAAMC,qBAAqB,CAAC;EACjCL,QAAQ,GAAwB,UAAU;AAE5C;AAACC,OAAA,CAAAI,qBAAA,GAAAA,qBAAA;AAEM,MAAMC,oBAAoB,CAAC;EAChCN,QAAQ,GAAwB,SAAS;AAE3C;AAACC,OAAA,CAAAK,oBAAA,GAAAA,oBAAA;AAEM,MAAMC,kBAAkB,CAAC;EAC9BP,QAAQ,GAAwB,OAAO;AAEzC;AAACC,OAAA,CAAAM,kBAAA,GAAAA,kBAAA;AAEM,MAAMC,6BAA6B,CAAC;EACzCR,QAAQ,GAAwB,mBAAmB;AAErD;AAACC,OAAA,CAAAO,6BAAA,GAAAA,6BAAA;AAEM,MAAMC,kBAAkB,CAAC;EAC9BT,QAAQ,GAAwB,OAAO;AAEzC;AAACC,OAAA,CAAAQ,kBAAA,GAAAA,kBAAA;AAEM,MAAMC,kBAAkB,CAAC;EAC9BV,QAAQ,GAAwB,OAAO;AAEzC;AAACC,OAAA,CAAAS,kBAAA,GAAAA,kBAAA;AAEM,MAAMC,0BAA0B,CAAC;EACtCX,QAAQ,GAAwB,gBAAgB;AAElD;AAACC,OAAA,CAAAU,0BAAA,GAAAA,0BAAA;AAEM,MAAMC,iBAAiB,CAAC;EAC7BZ,QAAQ,GAAwB,MAAM;AAExC;AAACC,OAAA,CAAAW,iBAAA,GAAAA,iBAAA;AAEM,MAAMC,gBAAgB,CAAC;EAC5Bb,QAAQ,GAAwB,KAAK;AAEvC;AAACC,OAAA,CAAAY,gBAAA,GAAAA,gBAAA","ignoreList":[]}
|
|
@@ -118,6 +118,31 @@ class SpikeConnection {
|
|
|
118
118
|
}
|
|
119
119
|
async extractData(config) {
|
|
120
120
|
if (!_SpikeSdk.SpikeSdk) throw new _SpikeException.SpikeException();
|
|
121
|
+
if (_reactNative.Platform.OS === 'android' && config.dataType.rawValue === 'ecg') {
|
|
122
|
+
let dateFrom;
|
|
123
|
+
let dateTo;
|
|
124
|
+
let collectedAt = new Date();
|
|
125
|
+
if ('from' in config) {
|
|
126
|
+
dateFrom = config.from;
|
|
127
|
+
dateTo = config.to;
|
|
128
|
+
} else {
|
|
129
|
+
dateFrom = new Date();
|
|
130
|
+
dateTo = new Date();
|
|
131
|
+
}
|
|
132
|
+
const result = {
|
|
133
|
+
dateFrom: dateFrom.toISOString(),
|
|
134
|
+
dateTo: dateTo.toISOString(),
|
|
135
|
+
collectedAt: collectedAt.toISOString(),
|
|
136
|
+
endUserId: await this.getSpikeEndUserId(),
|
|
137
|
+
sources: [{
|
|
138
|
+
name: 'android',
|
|
139
|
+
isSuccess: false,
|
|
140
|
+
message: 'No ECG data on android health connect'
|
|
141
|
+
}],
|
|
142
|
+
entries: []
|
|
143
|
+
};
|
|
144
|
+
return result;
|
|
145
|
+
}
|
|
121
146
|
try {
|
|
122
147
|
let json = '';
|
|
123
148
|
if ('from' in config) {
|
|
@@ -133,6 +158,27 @@ class SpikeConnection {
|
|
|
133
158
|
}
|
|
134
159
|
async extractAndPostData(config) {
|
|
135
160
|
if (!_SpikeSdk.SpikeSdk) throw new _SpikeException.SpikeException();
|
|
161
|
+
if (_reactNative.Platform.OS === 'android' && config.dataType.rawValue === 'ecg') {
|
|
162
|
+
let dateFrom;
|
|
163
|
+
let dateTo;
|
|
164
|
+
let collectedAt = new Date();
|
|
165
|
+
if ('from' in config) {
|
|
166
|
+
dateFrom = config.from;
|
|
167
|
+
dateTo = config.to;
|
|
168
|
+
} else {
|
|
169
|
+
dateFrom = new Date();
|
|
170
|
+
dateTo = new Date();
|
|
171
|
+
}
|
|
172
|
+
const result = {
|
|
173
|
+
dataType: config.dataType.rawValue,
|
|
174
|
+
payloadSize: 0,
|
|
175
|
+
callbackUrl: new URL(await this.getCallbackUrl()),
|
|
176
|
+
dateFrom: dateFrom,
|
|
177
|
+
dateTo: dateTo,
|
|
178
|
+
collectedAt: collectedAt
|
|
179
|
+
};
|
|
180
|
+
return result;
|
|
181
|
+
}
|
|
136
182
|
try {
|
|
137
183
|
let json = '';
|
|
138
184
|
if ('from' in config) {
|
|
@@ -245,6 +291,8 @@ class SpikeConnection {
|
|
|
245
291
|
return new _SpikeDataType.SpikeStepsDataType();
|
|
246
292
|
} else if (dataType === 'body') {
|
|
247
293
|
return new _SpikeDataType.SpikeBodyDataType();
|
|
294
|
+
} else if (dataType === 'ecg') {
|
|
295
|
+
return new _SpikeDataType.SpikeEcgDataType();
|
|
248
296
|
}
|
|
249
297
|
return new _SpikeDataType.SpikeStepsDataType();
|
|
250
298
|
}
|