From e1cc42635cf205f230835f1fab3e3eae44af5fc1 Mon Sep 17 00:00:00 2001 From: Milos Kozak Date: Sun, 11 Dec 2022 17:52:29 +0100 Subject: [PATCH] NSTreatment -> RemoteTreatment conversion --- .../nightscout/sdk/NSAndroidClientImpl.kt | 20 ++ .../InvalidFormatNightscoutException.kt | 3 + .../UnknownResponseNightscoutException.kt | 3 + .../sdk/interfaces/NSAndroidClient.kt | 2 + .../treatment/CreateUpdateResponse.kt | 8 + .../sdk/localmodel/treatment/NSBolus.kt | 4 +- .../sdk/localmodel/treatment/NSBolusWizard.kt | 4 +- .../sdk/localmodel/treatment/NSCarbs.kt | 4 +- .../treatment/NSEffectiveProfileSwitch.kt | 4 +- .../localmodel/treatment/NSExtendedBolus.kt | 6 +- .../localmodel/treatment/NSOfflineEvent.kt | 4 +- .../localmodel/treatment/NSProfileSwitch.kt | 4 +- .../localmodel/treatment/NSTemporaryBasal.kt | 10 +- .../localmodel/treatment/NSTemporaryTarget.kt | 4 +- .../localmodel/treatment/NSTherapyEvent.kt | 4 +- .../sdk/localmodel/treatment/NSTreatment.kt | 4 +- .../nightscout/sdk/mapper/TreatmentMapper.kt | 264 +++++++++++++++++- .../sdk/networking/NightscoutRemoteService.kt | 10 + .../sdk/remotemodel/RemoteStatusResponse.kt | 7 + .../sdk/remotemodel/RemoteTreatment.kt | 111 ++++---- .../extensions/ProfileSwitchExtension.kt | 3 +- .../extensions/ExtendedBolusExtension.kt | 2 +- 22 files changed, 400 insertions(+), 85 deletions(-) create mode 100644 core/ns-sdk/src/main/java/info/nightscout/sdk/exceptions/InvalidFormatNightscoutException.kt create mode 100644 core/ns-sdk/src/main/java/info/nightscout/sdk/exceptions/UnknownResponseNightscoutException.kt create mode 100644 core/ns-sdk/src/main/java/info/nightscout/sdk/localmodel/treatment/CreateUpdateResponse.kt diff --git a/core/ns-sdk/src/main/java/info/nightscout/sdk/NSAndroidClientImpl.kt b/core/ns-sdk/src/main/java/info/nightscout/sdk/NSAndroidClientImpl.kt index 019c16a914..183c8e09ca 100644 --- a/core/ns-sdk/src/main/java/info/nightscout/sdk/NSAndroidClientImpl.kt +++ b/core/ns-sdk/src/main/java/info/nightscout/sdk/NSAndroidClientImpl.kt @@ -3,12 +3,16 @@ package info.nightscout.sdk import android.content.Context import info.nightscout.sdk.exceptions.DateHeaderOutOfToleranceException import info.nightscout.sdk.exceptions.InvalidAccessTokenException +import info.nightscout.sdk.exceptions.InvalidFormatNightscoutException import info.nightscout.sdk.exceptions.TodoNightscoutException +import info.nightscout.sdk.exceptions.UnknownResponseNightscoutException import info.nightscout.sdk.interfaces.NSAndroidClient import info.nightscout.sdk.localmodel.Status import info.nightscout.sdk.localmodel.entry.NSSgvV3 +import info.nightscout.sdk.localmodel.treatment.CreateUpdateResponse import info.nightscout.sdk.localmodel.treatment.NSTreatment import info.nightscout.sdk.mapper.toLocal +import info.nightscout.sdk.mapper.toRemoteTreatment import info.nightscout.sdk.mapper.toSgv import info.nightscout.sdk.mapper.toTreatment import info.nightscout.sdk.networking.NetworkStackBuilder @@ -154,6 +158,22 @@ class NSAndroidClientImpl( } } + override suspend fun createTreatment(nsTreatment: NSTreatment): CreateUpdateResponse = callWrapper(dispatcher) { + + val remoteTreatment = nsTreatment.toRemoteTreatment() ?: throw InvalidFormatNightscoutException() + val response = api.createTreatment(remoteTreatment) + if (response.isSuccessful) { + return@callWrapper CreateUpdateResponse( + identifier = response.body()?.result?.identifier ?: throw UnknownResponseNightscoutException(), + isDeduplication = response.body()?.result?.isDeduplication ?: false, + deduplicatedIdentifier = response.body()?.result?.deduplicatedIdentifier, + lastModified = response.body()?.result?.lastModified + ) + } else { + throw TodoNightscoutException() // TODO: react to response errors (offline, ...) + } + } + private suspend fun callWrapper(dispatcher: CoroutineDispatcher, block: suspend () -> T): T = withContext(dispatcher) { retry( diff --git a/core/ns-sdk/src/main/java/info/nightscout/sdk/exceptions/InvalidFormatNightscoutException.kt b/core/ns-sdk/src/main/java/info/nightscout/sdk/exceptions/InvalidFormatNightscoutException.kt new file mode 100644 index 0000000000..80ab0f019e --- /dev/null +++ b/core/ns-sdk/src/main/java/info/nightscout/sdk/exceptions/InvalidFormatNightscoutException.kt @@ -0,0 +1,3 @@ +package info.nightscout.sdk.exceptions + +class InvalidFormatNightscoutException : NightscoutException() diff --git a/core/ns-sdk/src/main/java/info/nightscout/sdk/exceptions/UnknownResponseNightscoutException.kt b/core/ns-sdk/src/main/java/info/nightscout/sdk/exceptions/UnknownResponseNightscoutException.kt new file mode 100644 index 0000000000..f706d499b9 --- /dev/null +++ b/core/ns-sdk/src/main/java/info/nightscout/sdk/exceptions/UnknownResponseNightscoutException.kt @@ -0,0 +1,3 @@ +package info.nightscout.sdk.exceptions + +class UnknownResponseNightscoutException : NightscoutException() diff --git a/core/ns-sdk/src/main/java/info/nightscout/sdk/interfaces/NSAndroidClient.kt b/core/ns-sdk/src/main/java/info/nightscout/sdk/interfaces/NSAndroidClient.kt index e57144a74f..bfb07f1490 100644 --- a/core/ns-sdk/src/main/java/info/nightscout/sdk/interfaces/NSAndroidClient.kt +++ b/core/ns-sdk/src/main/java/info/nightscout/sdk/interfaces/NSAndroidClient.kt @@ -2,6 +2,7 @@ package info.nightscout.sdk.interfaces import info.nightscout.sdk.localmodel.Status import info.nightscout.sdk.localmodel.entry.NSSgvV3 +import info.nightscout.sdk.localmodel.treatment.CreateUpdateResponse import info.nightscout.sdk.localmodel.treatment.NSTreatment import info.nightscout.sdk.remotemodel.LastModified import info.nightscout.sdk.remotemodel.RemoteDeviceStatus @@ -19,4 +20,5 @@ interface NSAndroidClient { suspend fun getSgvsNewerThan(from: Long, limit: Long): List suspend fun getTreatmentsModifiedSince(from: Long, limit: Long): List suspend fun getDeviceStatusModifiedSince(from: Long): List + suspend fun createTreatment(NsTreatment: NSTreatment): CreateUpdateResponse } \ No newline at end of file diff --git a/core/ns-sdk/src/main/java/info/nightscout/sdk/localmodel/treatment/CreateUpdateResponse.kt b/core/ns-sdk/src/main/java/info/nightscout/sdk/localmodel/treatment/CreateUpdateResponse.kt new file mode 100644 index 0000000000..ad7a3835a2 --- /dev/null +++ b/core/ns-sdk/src/main/java/info/nightscout/sdk/localmodel/treatment/CreateUpdateResponse.kt @@ -0,0 +1,8 @@ +package info.nightscout.sdk.localmodel.treatment + +class CreateUpdateResponse( + val identifier: String?, + val isDeduplication: Boolean? = false, + val deduplicatedIdentifier: String? = null, + val lastModified: Long? = null +) \ No newline at end of file diff --git a/core/ns-sdk/src/main/java/info/nightscout/sdk/localmodel/treatment/NSBolus.kt b/core/ns-sdk/src/main/java/info/nightscout/sdk/localmodel/treatment/NSBolus.kt index 76d482f222..dbc9f63408 100644 --- a/core/ns-sdk/src/main/java/info/nightscout/sdk/localmodel/treatment/NSBolus.kt +++ b/core/ns-sdk/src/main/java/info/nightscout/sdk/localmodel/treatment/NSBolus.kt @@ -7,8 +7,8 @@ data class NSBolus( override val device: String?, override val identifier: String, override val units: NsUnits?, - override val srvModified: Long, - override val srvCreated: Long, + override val srvModified: Long?, + override val srvCreated: Long?, override val utcOffset: Long, override val subject: String?, override var isReadOnly: Boolean, diff --git a/core/ns-sdk/src/main/java/info/nightscout/sdk/localmodel/treatment/NSBolusWizard.kt b/core/ns-sdk/src/main/java/info/nightscout/sdk/localmodel/treatment/NSBolusWizard.kt index 11a1ab3a48..d192577c70 100644 --- a/core/ns-sdk/src/main/java/info/nightscout/sdk/localmodel/treatment/NSBolusWizard.kt +++ b/core/ns-sdk/src/main/java/info/nightscout/sdk/localmodel/treatment/NSBolusWizard.kt @@ -8,8 +8,8 @@ data class NSBolusWizard( override val device: String?, override val identifier: String, override val units: NsUnits?, - override val srvModified: Long, - override val srvCreated: Long, + override val srvModified: Long?, + override val srvCreated: Long?, override val utcOffset: Long, override val subject: String?, override var isReadOnly: Boolean, diff --git a/core/ns-sdk/src/main/java/info/nightscout/sdk/localmodel/treatment/NSCarbs.kt b/core/ns-sdk/src/main/java/info/nightscout/sdk/localmodel/treatment/NSCarbs.kt index 9f3dd66be2..b3069a4a1d 100644 --- a/core/ns-sdk/src/main/java/info/nightscout/sdk/localmodel/treatment/NSCarbs.kt +++ b/core/ns-sdk/src/main/java/info/nightscout/sdk/localmodel/treatment/NSCarbs.kt @@ -7,8 +7,8 @@ data class NSCarbs( override val device: String?, override val identifier: String, override val units: NsUnits?, - override val srvModified: Long, - override val srvCreated: Long, + override val srvModified: Long?, + override val srvCreated: Long?, override val utcOffset: Long, override val subject: String?, override var isReadOnly: Boolean, diff --git a/core/ns-sdk/src/main/java/info/nightscout/sdk/localmodel/treatment/NSEffectiveProfileSwitch.kt b/core/ns-sdk/src/main/java/info/nightscout/sdk/localmodel/treatment/NSEffectiveProfileSwitch.kt index 4fa8b1e322..731048b678 100644 --- a/core/ns-sdk/src/main/java/info/nightscout/sdk/localmodel/treatment/NSEffectiveProfileSwitch.kt +++ b/core/ns-sdk/src/main/java/info/nightscout/sdk/localmodel/treatment/NSEffectiveProfileSwitch.kt @@ -8,8 +8,8 @@ data class NSEffectiveProfileSwitch( override val device: String?, override val identifier: String, override val units: NsUnits?, - override val srvModified: Long, - override val srvCreated: Long, + override val srvModified: Long?, + override val srvCreated: Long?, override val utcOffset: Long, override val subject: String?, override var isReadOnly: Boolean, diff --git a/core/ns-sdk/src/main/java/info/nightscout/sdk/localmodel/treatment/NSExtendedBolus.kt b/core/ns-sdk/src/main/java/info/nightscout/sdk/localmodel/treatment/NSExtendedBolus.kt index 0fc041d9e5..cb179b70d2 100644 --- a/core/ns-sdk/src/main/java/info/nightscout/sdk/localmodel/treatment/NSExtendedBolus.kt +++ b/core/ns-sdk/src/main/java/info/nightscout/sdk/localmodel/treatment/NSExtendedBolus.kt @@ -7,8 +7,8 @@ data class NSExtendedBolus( override val device: String?, override val identifier: String, override val units: NsUnits?, - override val srvModified: Long, - override val srvCreated: Long, + override val srvModified: Long?, + override val srvCreated: Long?, override val utcOffset: Long, override val subject: String?, override var isReadOnly: Boolean, @@ -21,5 +21,5 @@ data class NSExtendedBolus( override val pumpSerial: String?, val duration: Long, val enteredinsulin: Double, - val isEmulatingTempbasal: Boolean + val isEmulatingTempBasal: Boolean? ) : NSTreatment diff --git a/core/ns-sdk/src/main/java/info/nightscout/sdk/localmodel/treatment/NSOfflineEvent.kt b/core/ns-sdk/src/main/java/info/nightscout/sdk/localmodel/treatment/NSOfflineEvent.kt index 1abffef44c..1d64e0c6cd 100644 --- a/core/ns-sdk/src/main/java/info/nightscout/sdk/localmodel/treatment/NSOfflineEvent.kt +++ b/core/ns-sdk/src/main/java/info/nightscout/sdk/localmodel/treatment/NSOfflineEvent.kt @@ -7,8 +7,8 @@ data class NSOfflineEvent( override val device: String?, override val identifier: String, override val units: NsUnits?, - override val srvModified: Long, - override val srvCreated: Long, + override val srvModified: Long?, + override val srvCreated: Long?, override val utcOffset: Long, override val subject: String?, override var isReadOnly: Boolean, diff --git a/core/ns-sdk/src/main/java/info/nightscout/sdk/localmodel/treatment/NSProfileSwitch.kt b/core/ns-sdk/src/main/java/info/nightscout/sdk/localmodel/treatment/NSProfileSwitch.kt index c97e5de38c..d36056eebd 100644 --- a/core/ns-sdk/src/main/java/info/nightscout/sdk/localmodel/treatment/NSProfileSwitch.kt +++ b/core/ns-sdk/src/main/java/info/nightscout/sdk/localmodel/treatment/NSProfileSwitch.kt @@ -8,8 +8,8 @@ data class NSProfileSwitch( override val device: String?, override val identifier: String, override val units: NsUnits?, - override val srvModified: Long, - override val srvCreated: Long, + override val srvModified: Long?, + override val srvCreated: Long?, override val utcOffset: Long, override val subject: String?, override var isReadOnly: Boolean, diff --git a/core/ns-sdk/src/main/java/info/nightscout/sdk/localmodel/treatment/NSTemporaryBasal.kt b/core/ns-sdk/src/main/java/info/nightscout/sdk/localmodel/treatment/NSTemporaryBasal.kt index 8a025e7097..b3dabf908a 100644 --- a/core/ns-sdk/src/main/java/info/nightscout/sdk/localmodel/treatment/NSTemporaryBasal.kt +++ b/core/ns-sdk/src/main/java/info/nightscout/sdk/localmodel/treatment/NSTemporaryBasal.kt @@ -8,8 +8,8 @@ data class NSTemporaryBasal( override val device: String?, override val identifier: String, override val units: NsUnits?, - override val srvModified: Long, - override val srvCreated: Long, + override val srvModified: Long?, + override val srvCreated: Long?, override val utcOffset: Long, override val subject: String?, override var isReadOnly: Boolean, @@ -21,9 +21,11 @@ data class NSTemporaryBasal( override val pumpType: String?, override val pumpSerial: String?, val duration: Long, - val rate: Double, + val rate: Double, // when sending to NS always convertedToAbsolute(timestamp, profile) val isAbsolute: Boolean, - val type: Type + val type: Type, + val percent: Double? = null, // when sending to NS (rate - 100) + val absolute: Double? = null // when sending to NS (rate) ) : NSTreatment { enum class Type { diff --git a/core/ns-sdk/src/main/java/info/nightscout/sdk/localmodel/treatment/NSTemporaryTarget.kt b/core/ns-sdk/src/main/java/info/nightscout/sdk/localmodel/treatment/NSTemporaryTarget.kt index c4a03bca18..77276096db 100644 --- a/core/ns-sdk/src/main/java/info/nightscout/sdk/localmodel/treatment/NSTemporaryTarget.kt +++ b/core/ns-sdk/src/main/java/info/nightscout/sdk/localmodel/treatment/NSTemporaryTarget.kt @@ -7,8 +7,8 @@ data class NSTemporaryTarget( override val device: String?, override val identifier: String, override val units: NsUnits?, - override val srvModified: Long, - override val srvCreated: Long, + override val srvModified: Long?, + override val srvCreated: Long?, override val utcOffset: Long, override val subject: String?, override var isReadOnly: Boolean, diff --git a/core/ns-sdk/src/main/java/info/nightscout/sdk/localmodel/treatment/NSTherapyEvent.kt b/core/ns-sdk/src/main/java/info/nightscout/sdk/localmodel/treatment/NSTherapyEvent.kt index 503c9ee65f..1fe671107c 100644 --- a/core/ns-sdk/src/main/java/info/nightscout/sdk/localmodel/treatment/NSTherapyEvent.kt +++ b/core/ns-sdk/src/main/java/info/nightscout/sdk/localmodel/treatment/NSTherapyEvent.kt @@ -8,8 +8,8 @@ data class NSTherapyEvent( override val device: String?, override val identifier: String, override val units: NsUnits?, - override val srvModified: Long, - override val srvCreated: Long, + override val srvModified: Long?, + override val srvCreated: Long?, override val utcOffset: Long, override val subject: String?, override var isReadOnly: Boolean, diff --git a/core/ns-sdk/src/main/java/info/nightscout/sdk/localmodel/treatment/NSTreatment.kt b/core/ns-sdk/src/main/java/info/nightscout/sdk/localmodel/treatment/NSTreatment.kt index f522b0673c..04a10c17eb 100644 --- a/core/ns-sdk/src/main/java/info/nightscout/sdk/localmodel/treatment/NSTreatment.kt +++ b/core/ns-sdk/src/main/java/info/nightscout/sdk/localmodel/treatment/NSTreatment.kt @@ -8,8 +8,8 @@ interface NSTreatment { val identifier: String val units: NsUnits? val eventType: EventType - val srvModified: Long - val srvCreated: Long + val srvModified: Long? + val srvCreated: Long? val utcOffset: Long val subject: String? var isReadOnly: Boolean diff --git a/core/ns-sdk/src/main/java/info/nightscout/sdk/mapper/TreatmentMapper.kt b/core/ns-sdk/src/main/java/info/nightscout/sdk/mapper/TreatmentMapper.kt index 7af6badcbb..47cb5e7b2a 100644 --- a/core/ns-sdk/src/main/java/info/nightscout/sdk/mapper/TreatmentMapper.kt +++ b/core/ns-sdk/src/main/java/info/nightscout/sdk/mapper/TreatmentMapper.kt @@ -117,7 +117,7 @@ internal fun RemoteTreatment.toTreatment(): NSTreatment? { pumpSerial = extendedEmulated.pumpSerial, enteredinsulin = extendedEmulated.enteredinsulin ?: 0.0, duration = extendedEmulated.durationInMilliseconds ?: TimeUnit.MINUTES.toMillis(extendedEmulated.duration ?: 0L), - isEmulatingTempbasal = extendedEmulated.isEmulatingTempBasal + isEmulatingTempBasal = extendedEmulated.isEmulatingTempBasal ) } @@ -329,10 +329,270 @@ internal fun RemoteTreatment.toTreatment(): NSTreatment? { pumpSerial = this.pumpSerial, enteredinsulin = this.enteredinsulin, duration = this.durationInMilliseconds ?: TimeUnit.MINUTES.toMillis(this.duration ?: 0L), - isEmulatingTempbasal = this.isEmulatingTempBasal + isEmulatingTempBasal = this.isEmulatingTempBasal ) } } return null } + +internal fun NSTreatment.toRemoteTreatment(): RemoteTreatment? = + when (this) { + is NSBolus -> RemoteTreatment( + date = date, + device = device, + identifier = identifier, + units = units?.value, + utcOffset = utcOffset, + subject = subject, + isReadOnly = isReadOnly, + isValid = isValid, + eventType = eventType, + notes = notes, + pumpId = pumpId, + endId = endId, + pumpType = pumpType, + pumpSerial = pumpSerial, + insulin = insulin, + type = type.name + ) + + is NSCarbs -> RemoteTreatment( + date = date, + device = device, + identifier = identifier, + units = units?.value, + utcOffset = utcOffset, + subject = subject, + isReadOnly = isReadOnly, + isValid = isValid, + eventType = eventType, + notes = notes, + pumpId = pumpId, + endId = endId, + pumpType = pumpType, + pumpSerial = pumpSerial, + carbs = carbs, + duration = duration + ) + + is NSTemporaryTarget -> RemoteTreatment( + date = date, + device = device, + identifier = identifier, + units = units?.value, + srvModified = srvModified, + srvCreated = srvCreated, + utcOffset = utcOffset, + subject = subject, + isReadOnly = isReadOnly, + isValid = isValid, + eventType = eventType, + notes = notes, + pumpId = pumpId, + endId = endId, + pumpType = pumpType, + pumpSerial = pumpSerial, + duration = TimeUnit.MILLISECONDS.toMinutes(duration), + durationInMilliseconds = duration, + targetBottom = targetBottom, + targetTop = targetTop, + reason = reason.text + ) + /* + // Convert back emulated TBR -> EB + eventType == EventType.TEMPORARY_BASAL && extendedEmulated != null -> + + return RemoteTreatment( + date = treatmentTimestamp, + device = device, + identifier = identifier, + units = NsUnits.fromString(extendedEmulated.units), + srvModified = srvModified, + srvCreated = srvCreated, + utcOffset = utcOffset ?: 0, + subject = subject, + isReadOnly = extendedEmulated.isReadOnly ?: false, + isValid = extendedEmulated.isValid ?: true, + eventType = extendedEmulated.eventType, + notes = extendedEmulated.notes, + pumpId = extendedEmulated.pumpId, + endId = extendedEmulated.endId, + pumpType = extendedEmulated.pumpType, + pumpSerial = extendedEmulated.pumpSerial, + enteredinsulin = extendedEmulated.enteredinsulin ?: 0.0, + duration = extendedEmulated.durationInMilliseconds ?: TimeUnit.MINUTES.toMillis(extendedEmulated.duration ?: 0L), + isEmulatingTempbasal = extendedEmulated.isEmulatingTempBasal + ) + } + */ + is NSTemporaryBasal -> RemoteTreatment( + date = date, + device = device, + identifier = identifier, + units = units?.value, + srvModified = srvModified, + srvCreated = srvCreated, + utcOffset = utcOffset, + subject = subject, + isReadOnly = isReadOnly, + isValid = isValid, + eventType = eventType, + notes = notes, + pumpId = pumpId, + endId = endId, + pumpType = pumpType, + pumpSerial = pumpSerial, + duration = TimeUnit.MILLISECONDS.toMinutes(duration), + durationInMilliseconds = duration, + absolute = absolute, + percent = percent, + rate = absolute, + type = type.name + ) + + is NSEffectiveProfileSwitch -> RemoteTreatment( + date = date, + device = device, + identifier = identifier, + units = units?.value, + srvModified = srvModified, + srvCreated = srvCreated, + utcOffset = utcOffset, + subject = subject, + isReadOnly = isReadOnly, + isValid = isValid, + eventType = eventType, + notes = notes, + pumpId = pumpId, + endId = endId, + pumpType = pumpType, + pumpSerial = pumpSerial, + profileJson = profileJson.toString(), + originalProfileName = originalProfileName, + originalCustomizedName = originalCustomizedName, + originalTimeshift = originalTimeshift, + originalPercentage = originalPercentage, + originalDuration = originalDuration, + originalEnd = originalEnd + ) + + is NSProfileSwitch -> RemoteTreatment( + date = date, + device = device, + identifier = identifier, + units = units?.value, + srvModified = srvModified, + srvCreated = srvCreated, + utcOffset = utcOffset, + subject = subject, + isReadOnly = isReadOnly, + isValid = isValid, + eventType = eventType, + notes = notes, + pumpId = pumpId, + endId = endId, + pumpType = pumpType, + pumpSerial = pumpSerial, + profileJson = profileJson.toString(), // must be de-customized + profile = profileName, + originalProfileName = originalProfileName, + originalDuration = originalDuration, + duration = duration, + timeshift = timeShift, + percentage = percentage, + ) + + is NSBolusWizard -> RemoteTreatment( + date = date, + device = device, + identifier = identifier, + units = units?.value, + srvModified = srvModified, + srvCreated = srvCreated, + utcOffset = utcOffset, + subject = subject, + isReadOnly = isReadOnly, + isValid = isValid, + eventType = eventType, + notes = notes, + pumpId = pumpId, + endId = endId, + pumpType = pumpType, + pumpSerial = pumpSerial, + bolusCalculatorResult = bolusCalculatorResult, + glucose = glucose + ) + + is NSTherapyEvent -> RemoteTreatment( + date = date, + device = device, + identifier = identifier, + units = units?.value, + srvModified = srvModified, + srvCreated = srvCreated, + utcOffset = utcOffset, + subject = subject, + isReadOnly = isReadOnly, + isValid = isValid, + eventType = eventType, + notes = notes, + pumpId = pumpId, + endId = endId, + pumpType = pumpType, + pumpSerial = pumpSerial, + duration = TimeUnit.MILLISECONDS.toMinutes(duration), + durationInMilliseconds = duration, + glucose = glucose, + enteredBy = enteredBy, + glucoseType = glucoseType?.text + ) + + is NSOfflineEvent -> RemoteTreatment( + date = date, + device = device, + identifier = identifier, + units = units?.value, + srvModified = srvModified, + srvCreated = srvCreated, + utcOffset = utcOffset, + subject = subject, + isReadOnly = isReadOnly, + isValid = isValid, + eventType = eventType, + notes = notes, + pumpId = pumpId, + endId = endId, + pumpType = pumpType, + pumpSerial = pumpSerial, + duration = TimeUnit.MILLISECONDS.toMinutes(duration), + durationInMilliseconds = duration, + reason = reason.name + ) + + is NSExtendedBolus -> RemoteTreatment( + date = date, + device = device, + identifier = identifier, + units = units?.value, + srvModified = srvModified, + srvCreated = srvCreated, + utcOffset = utcOffset, + subject = subject, + isReadOnly = isReadOnly, + isValid = isValid, + eventType = eventType, + notes = notes, + pumpId = pumpId, + endId = endId, + pumpType = pumpType, + pumpSerial = pumpSerial, + enteredinsulin = enteredinsulin, + duration = TimeUnit.MILLISECONDS.toMinutes(duration), + durationInMilliseconds = duration, + isEmulatingTempBasal = isEmulatingTempBasal + ) + + else -> null + } diff --git a/core/ns-sdk/src/main/java/info/nightscout/sdk/networking/NightscoutRemoteService.kt b/core/ns-sdk/src/main/java/info/nightscout/sdk/networking/NightscoutRemoteService.kt index 4619aef0c0..3ae740d2db 100644 --- a/core/ns-sdk/src/main/java/info/nightscout/sdk/networking/NightscoutRemoteService.kt +++ b/core/ns-sdk/src/main/java/info/nightscout/sdk/networking/NightscoutRemoteService.kt @@ -4,11 +4,17 @@ import com.google.gson.JsonElement import info.nightscout.sdk.remotemodel.LastModified import info.nightscout.sdk.remotemodel.RemoteDeviceStatus import info.nightscout.sdk.remotemodel.NSResponse +import info.nightscout.sdk.remotemodel.RemoteCreateUpdateResponse import info.nightscout.sdk.remotemodel.RemoteEntry import info.nightscout.sdk.remotemodel.RemoteStatusResponse import info.nightscout.sdk.remotemodel.RemoteTreatment +import okhttp3.RequestBody +import retrofit2.Call import retrofit2.Response +import retrofit2.http.Body import retrofit2.http.GET +import retrofit2.http.Header +import retrofit2.http.POST import retrofit2.http.Path import retrofit2.http.Query @@ -48,4 +54,8 @@ internal interface NightscoutRemoteService { @GET("v3/devicestatus/history/{from}") suspend fun getDeviceStatusModifiedSince(@Path("from") from: Long): Response>> + + @POST("v3/treatments") + fun createTreatment(@Body remoteTreatment: RemoteTreatment): Response> + } diff --git a/core/ns-sdk/src/main/java/info/nightscout/sdk/remotemodel/RemoteStatusResponse.kt b/core/ns-sdk/src/main/java/info/nightscout/sdk/remotemodel/RemoteStatusResponse.kt index 15055f9051..be313118ba 100644 --- a/core/ns-sdk/src/main/java/info/nightscout/sdk/remotemodel/RemoteStatusResponse.kt +++ b/core/ns-sdk/src/main/java/info/nightscout/sdk/remotemodel/RemoteStatusResponse.kt @@ -17,6 +17,13 @@ internal data class RemoteStorage( @SerializedName("version") val version: String ) +internal data class RemoteCreateUpdateResponse( + @SerializedName("identifier") val identifier: String?, + @SerializedName("isDeduplication") val isDeduplication: Boolean?, + @SerializedName("deduplicatedIdentifier") val deduplicatedIdentifier: String?, + @SerializedName("lastModified") val lastModified: Long? +) + internal data class RemoteApiPermissions( @SerializedName("devicestatus") val deviceStatus: RemoteApiPermission, @SerializedName("entries") val entries: RemoteApiPermission, diff --git a/core/ns-sdk/src/main/java/info/nightscout/sdk/remotemodel/RemoteTreatment.kt b/core/ns-sdk/src/main/java/info/nightscout/sdk/remotemodel/RemoteTreatment.kt index 80929a2133..d73f0098fc 100644 --- a/core/ns-sdk/src/main/java/info/nightscout/sdk/remotemodel/RemoteTreatment.kt +++ b/core/ns-sdk/src/main/java/info/nightscout/sdk/remotemodel/RemoteTreatment.kt @@ -18,72 +18,71 @@ import org.json.JSONObject * */ internal data class RemoteTreatment( @SerializedName("identifier") val identifier: String, // string Main addressing, required field that identifies document in the collection. The client should not create the identifier, the server automatically assigns it when the document is inserted. - @SerializedName("date") val date: Long?, // integer($int64) or string required timestamp when the record or event occurred, you can choose from three input formats Unix epoch in milliseconds (1525383610088), Unix epoch in seconds (1525383610), ISO 8601 with optional timezone ('2018-05-03T21:40:10.088Z' or '2018-05-03T23:40:10.088+02:00') - @SerializedName("mills") val mills: Long?, // integer($int64) or string required timestamp when the record or event occurred, you can choose from three input formats Unix - @SerializedName("timestamp") val timestamp: Long?, // integer($int64) or string required timestamp when the record or event occurred, you can choose from three input formats Unix epoch in milliseconds (1525383610088), Unix epoch in seconds (1525383610), ISO 8601 with optional timezone ('2018-05-03T21:40:10.088Z' or '2018-05-03T23:40:10.088+02:00') - @SerializedName("created_at") val created_at: String, // integer($int64) or string timestamp on previous version of api, in my examples, a lot of treatments don't have date, only created_at, some of them with string others with long... - @SerializedName("utcOffset") val utcOffset: Long?, // integer Local UTC offset (timezone) of the event in minutes. This field can be set either directly by the client (in the incoming - // document) or it is automatically parsed from the date field. + @SerializedName("date") val date: Long? = null, // integer($int64) or string required timestamp when the record or event occurred, you can choose from three input formats Unix epoch in milliseconds (1525383610088), Unix epoch in seconds (1525383610), ISO 8601 with optional timezone ('2018-05-03T21:40:10.088Z' or '2018-05-03T23:40:10.088+02:00') + @SerializedName("mills") val mills: Long? = null, // integer($int64) or string required timestamp when the record or event occurred, you can choose from three input formats Unix + @SerializedName("timestamp") val timestamp: Long? = null, // integer($int64) or string required timestamp when the record or event occurred, you can choose from three input formats Unix epoch in milliseconds (1525383610088), Unix epoch in seconds (1525383610), ISO 8601 with optional timezone ('2018-05-03T21:40:10.088Z' or '2018-05-03T23:40:10.088+02:00') + @SerializedName("created_at") val created_at: String? = null, // integer($int64) or string timestamp on previous version of api, in my examples, a lot of treatments don't have date, only created_at, some of them with string others with long... + @SerializedName("utcOffset") val utcOffset: Long? = null, // integer Local UTC offset (timezone) of the event in minutes. This field can be set either directly by the client (in the incoming document) or it is automatically parsed from the date field. // @SerializedName("app") val app : String, // TODO required ? Application or system in which the record was entered by human or device for the first time. - @SerializedName("device") val device: String?, // string The device from which the data originated (including serial number of the device, if it is relevant and safe). - @SerializedName("srvCreated") val srvCreated: Long, // integer($int64) example: 1525383610088 The server's timestamp of document insertion into the database (Unix epoch in ms). This field appears only for documents which were inserted by API v3. - @SerializedName("subject") val subject: String?, // string Name of the security subject (within Nightscout scope) which has created the document. This field is automatically set by the server from the passed token or JWT. - @SerializedName("srvModified") val srvModified: Long, // integer($int64) example: 1525383610088 The server's timestamp of the last document modification in the database (Unix epoch in ms). This field appears only for documents which were somehow modified by API v3 (inserted, updated or deleted). - @SerializedName("modifiedBy") val modifiedBy: String?, // string Name of the security subject (within Nightscout scope) which has patched or deleted the document for the last time. This field is automatically set by the server. - @SerializedName("isValid") val isValid: Boolean?, // boolean A flag set by the server only for deleted documents. This field appears only within history operation and for documents which were deleted by API v3 (and they always have a false value) - @SerializedName("isReadOnly") val isReadOnly: Boolean?, // boolean A flag set by client that locks the document from any changes. Every document marked with isReadOnly=true is forever immutable and cannot even be deleted. + @SerializedName("device") val device: String? = null, // string The device from which the data originated (including serial number of the device, if it is relevant and safe). + @SerializedName("srvCreated") val srvCreated: Long? = null, // integer($int64) example: 1525383610088 The server's timestamp of document insertion into the database (Unix epoch in ms). This field appears only for documents which were inserted by API v3. + @SerializedName("subject") val subject: String? = null, // string Name of the security subject (within Nightscout scope) which has created the document. This field is automatically set by the server from the passed token or JWT. + @SerializedName("srvModified") val srvModified: Long? = null, // integer($int64) example: 1525383610088 The server's timestamp of the last document modification in the database (Unix epoch in ms). This field appears only for documents which were somehow modified by API v3 (inserted, updated or deleted). + @SerializedName("modifiedBy") val modifiedBy: String? = null, // string Name of the security subject (within Nightscout scope) which has patched or deleted the document for the last time. This field is automatically set by the server. + @SerializedName("isValid") val isValid: Boolean? = null, // boolean A flag set by the server only for deleted documents. This field appears only within history operation and for documents which were deleted by API v3 (and they always have a false value) + @SerializedName("isReadOnly") val isReadOnly: Boolean? = null, // boolean A flag set by client that locks the document from any changes. Every document marked with isReadOnly=true is forever immutable and cannot even be deleted. @SerializedName("eventType") val eventType: EventType, // string "BG Check", "Snack Bolus", "Meal Bolus", "Correction Bolus", "Carb Correction", "Combo Bolus", "Announcement", "Note", "Question", "Exercise", "Site Change", "Sensor Start", "Sensor Change", "Pump Battery Change", "Insulin Change", "Temp Basal", "Profile Switch", "D.A.D. Alert", "Temporary Target", "OpenAPS Offline", "Bolus Wizard" - @SerializedName("glucose") val glucose: Double?, // double Current glucose - @SerializedName("glucoseType") val glucoseType: String?, // string example: "Sensor", "Finger", "Manual" - @SerializedName("units") val units: String?, // string The units for the glucose value, mg/dl or mmol/l. It is strongly recommended to fill in this field. - @SerializedName("carbs") val carbs: Double?, // number... Amount of carbs given. - @SerializedName("protein") val protein: Int?, // number... Amount of protein given. - @SerializedName("fat") val fat: Int?, // number... Amount of fat given. - @SerializedName("insulin") val insulin: Double?, // number... Amount of insulin, if any. - @SerializedName("duration") val duration: Long?, // number... Duration in minutes. - @SerializedName("durationInMilliseconds") val durationInMilliseconds: Long?, // number... Duration in milliseconds. - @SerializedName("preBolus") val preBolus: Int?, // number... How many minutes the bolus was given before the meal started. - @SerializedName("splitNow") val splitNow: Int?, // number... Immediate part of combo bolus (in percent). - @SerializedName("splitExt") val splitExt: Int?, // number... Extended part of combo bolus (in percent). - @SerializedName("percent") val percent: Double?, // number... Eventual basal change in percent. - @SerializedName("absolute") val absolute: Double?, // number... Eventual basal change in absolute value (insulin units per hour). - @SerializedName("targetTop") val targetTop: Double?, // number... Top limit of temporary target. - @SerializedName("targetBottom") val targetBottom: Double?, // number... Bottom limit of temporary target. - @SerializedName("profile") val profile: String?, // string Name of the profile to which the pump has been switched. - @SerializedName("reason") val reason: String?, // string For example the reason why the profile has been switched or why the temporary target has been set. - @SerializedName("notes") val notes: String?, // string Description/notes of treatment. - @SerializedName("enteredBy") val enteredBy: String?, // string Who entered the treatment. + @SerializedName("glucose") val glucose: Double? = null, // double Current glucose + @SerializedName("glucoseType") val glucoseType: String? = null, // string example: "Sensor", "Finger", "Manual" + @SerializedName("units") val units: String? = null, // string The units for the glucose value, mg/dl or mmol/l. It is strongly recommended to fill in this field. + @SerializedName("carbs") val carbs: Double? = null, // number... Amount of carbs given. + @SerializedName("protein") val protein: Int? = null, // number... Amount of protein given. + @SerializedName("fat") val fat: Int? = null, // number... Amount of fat given. + @SerializedName("insulin") val insulin: Double? = null, // number... Amount of insulin, if any. + @SerializedName("duration") val duration: Long? = null, // number... Duration in minutes. + @SerializedName("durationInMilliseconds") val durationInMilliseconds: Long? = null, // number... Duration in milliseconds. + @SerializedName("preBolus") val preBolus: Int? = null, // number... How many minutes the bolus was given before the meal started. + @SerializedName("splitNow") val splitNow: Int? = null, // number... Immediate part of combo bolus (in percent). + @SerializedName("splitExt") val splitExt: Int? = null, // number... Extended part of combo bolus (in percent). + @SerializedName("percent") val percent: Double? = null, // number... Eventual basal change in percent. + @SerializedName("absolute") val absolute: Double? = null, // number... Eventual basal change in absolute value (insulin units per hour). + @SerializedName("targetTop") val targetTop: Double? = null, // number... Top limit of temporary target. + @SerializedName("targetBottom") val targetBottom: Double? = null, // number... Bottom limit of temporary target. + @SerializedName("profile") val profile: String? = null, // string Name of the profile to which the pump has been switched. + @SerializedName("reason") val reason: String? = null, // string For example the reason why the profile has been switched or why the temporary target has been set. + @SerializedName("notes") val notes: String? = null, // string Description/notes of treatment. + @SerializedName("enteredBy") val enteredBy: String? = null, // string Who entered the treatment. - @SerializedName("endId") val endId: Long?, // long id of record which ended this - @SerializedName("pumpId") val pumpId: Long?, // long or "Meal Bolus", "Correction Bolus", "Combo Bolus" ex 4102 not sure if long or int - @SerializedName("pumpType") val pumpType: String?, // string "Meal Bolus", "Correction Bolus", "Combo Bolus" ex "ACCU_CHEK_INSIGHT_BLUETOOTH", - @SerializedName("pumpSerial") val pumpSerial: String?, // string "Meal Bolus", "Correction Bolus", "Combo Bolus" "33013206", + @SerializedName("endId") val endId: Long? = null, // long id of record which ended this + @SerializedName("pumpId") val pumpId: Long? = null, // long or "Meal Bolus", "Correction Bolus", "Combo Bolus" ex 4102 not sure if long or int + @SerializedName("pumpType") val pumpType: String? = null, // string "Meal Bolus", "Correction Bolus", "Combo Bolus" ex "ACCU_CHEK_INSIGHT_BLUETOOTH", + @SerializedName("pumpSerial") val pumpSerial: String? = null, // string "Meal Bolus", "Correction Bolus", "Combo Bolus" "33013206", // other fields found in examples but not in documentation - @SerializedName("profileJson") val profileJson: String?, // string "Profile Switch" ex json toString "{\"units\":\"mg\\/dl\",\"dia\":5,\"timezone\":\"Africa\\/Cairo\", + @SerializedName("profileJson") val profileJson: String? = null, // string "Profile Switch" ex json toString "{\"units\":\"mg\\/dl\",\"dia\":5,\"timezone\":\"Africa\\/Cairo\", // \"sens\":[{\"time\":\"00:00\",\"timeAsSeconds\":0,\"value\":60},{\"time\":\"07:00\",\"timeAsSeconds\":25200,\"value\":60},{\"time\":\"08:00\",\"timeAsSeconds\":28800,\"value\":61.33333333333333},{\"time\":\"09:00\",\"timeAsSeconds\":32400,\"value\":65.33333333333333},{\"time\":\"10:00\",\"timeAsSeconds\":36000,\"value\":69.33333333333333},{\"time\":\"11:00\",\"timeAsSeconds\":39600,\"value\":73.33333333333333},{\"time\":\"13:00\",\"timeAsSeconds\":46800,\"value\":72},{\"time\":\"14:00\",\"timeAsSeconds\":50400,\"value\":68},{\"time\":\"15:00\",\"timeAsSeconds\":54000,\"value\":65.33333333333333},{\"time\":\"16:00\",\"timeAsSeconds\":57600,\"value\":65.33333333333333}],\"carbratio\":[{\"time\":\"00:00\",\"timeAsSeconds\":0,\"value\":5.7333333333333325},{\"time\":\"11:00\",\"timeAsSeconds\":39600,\"value\":7.333333333333333},{\"time\":\"16:00\",\"timeAsSeconds\":57600,\"value\":6.666666666666666}],\"basal\":[{\"time\":\"00:00\",\"timeAsSeconds\":0,\"value\":0.5249999999999999},{\"time\":\"01:00\",\"timeAsSeconds\":3600,\"value\":0.585},{\"time\":\"02:00\",\"timeAsSeconds\":7200,\"value\":0.6375},{\"time\":\"03:00\",\"timeAsSeconds\":10800,\"value\":0.5625},{\"time\":\"04:00\",\"timeAsSeconds\":14400,\"value\":0.4575},{\"time\":\"05:00\",\"timeAsSeconds\":18000,\"value\":0.5175},{\"time\":\"06:00\",\"timeAsSeconds\":21600,\"value\":0.48},{\"time\":\"07:00\",\"timeAsSeconds\":25200,\"value\":0.51},{\"time\":\"08:00\",\"timeAsSeconds\":28800,\"value\":0.48750000000000004},{\"time\":\"09:00\",\"timeAsSeconds\":32400,\"value\":0.48},{\"time\":\"10:00\",\"timeAsSeconds\":36000,\"value\":0.48750000000000004},{\"time\":\"11:00\",\"timeAsSeconds\":39600,\"value\":0.5025000000000001},{\"time\":\"12:00\",\"timeAsSeconds\":43200,\"value\":0.5549999999999999},{\"time\":\"13:00\",\"timeAsSeconds\":46800,\"value\":0.5700000000000001},{\"time\":\"14:00\",\"timeAsSeconds\":50400,\"value\":0.5700000000000001},{\"time\":\"15:00\",\"timeAsSeconds\":54000,\"value\":0.5775},{\"time\":\"16:00\",\"timeAsSeconds\":57600,\"value\":0.51},{\"time\":\"17:00\",\"timeAsSeconds\":61200,\"value\":0.54},{\"time\":\"18:00\",\"timeAsSeconds\":64800,\"value\":0.48750000000000004},{\"time\":\"19:00\",\"timeAsSeconds\":68400,\"value\":0.5249999999999999},{\"time\":\"20:00\",\"timeAsSeconds\":72000,\"value\":0.46499999999999997},{\"time\":\"21:00\",\"timeAsSeconds\":75600,\"value\":0.46499999999999997},{\"time\":\"22:00\",\"timeAsSeconds\":79200,\"value\":0.43499999999999994},{\"time\":\"23:00\",\"timeAsSeconds\":82800,\"value\":0.41250000000000003}],\"target_low\":[{\"time\":\"00:00\",\"timeAsSeconds\":0,\"value\":100},{\"time\":\"06:00\",\"timeAsSeconds\":21600,\"value\":90},{\"time\":\"09:00\",\"timeAsSeconds\":32400,\"value\":100},{\"time\":\"11:00\",\"timeAsSeconds\":39600,\"value\":90},{\"time\":\"14:00\",\"timeAsSeconds\":50400,\"value\":100},{\"time\":\"18:00\",\"timeAsSeconds\":64800,\"value\":90},{\"time\":\"21:00\",\"timeAsSeconds\":75600,\"value\":100}],\"target_high\":[{\"time\":\"00:00\",\"timeAsSeconds\":0,\"value\":100},{\"time\":\"06:00\",\"timeAsSeconds\":21600,\"value\":90},{\"time\":\"09:00\",\"timeAsSeconds\":32400,\"value\":100},{\"time\":\"11:00\",\"timeAsSeconds\":39600,\"value\":90},{\"time\":\"14:00\",\"timeAsSeconds\":50400,\"value\":100},{\"time\":\"18:00\",\"timeAsSeconds\":64800,\"value\":90},{\"time\":\"21:00\",\"timeAsSeconds\":75600,\"value\":100}]}", - @SerializedName("originalProfileName") val originalProfileName: String?, // string "Effective Profile Switch" - @SerializedName("originalCustomizedName") val originalCustomizedName: String?, // string "Effective Profile Switch" - @SerializedName("originalTimeshift") val originalTimeshift: Long?, // long "Effective Profile Switch" - @SerializedName("originalPercentage") val originalPercentage: Int?, // int "Effective Profile Switch" - @SerializedName("originalDuration") val originalDuration: Long?, // long "Effective Profile Switch" - @SerializedName("originalEnd") val originalEnd: Long?, // long "Effective Profile Switch" + @SerializedName("originalProfileName") val originalProfileName: String? = null, // string "Effective Profile Switch" + @SerializedName("originalCustomizedName") val originalCustomizedName: String? = null, // string "Effective Profile Switch" + @SerializedName("originalTimeshift") val originalTimeshift: Long? = null, // long "Effective Profile Switch" + @SerializedName("originalPercentage") val originalPercentage: Int? = null, // int "Effective Profile Switch" + @SerializedName("originalDuration") val originalDuration: Long? = null, // long "Effective Profile Switch" + @SerializedName("originalEnd") val originalEnd: Long? = null, // long "Effective Profile Switch" - @SerializedName("bolusCalculatorResult") val bolusCalculatorResult: String?, // string "Bolus Wizard" json toString ex "bolusCalculatorResult": "{\"basalIOB\":-0.247,\"bolusIOB\":-1.837,\"carbs\":45.0,\"carbsInsulin\":9.0,\"cob\":0.0,\"cobInsulin\":0.0,\"dateCreated\":1626202788810,\"glucoseDifference\":44.0,\"glucoseInsulin\":0.8979591836734694,\"glucoseTrend\":5.5,\"glucoseValue\":134.0,\"ic\":5.0,\"id\":331,\"interfaceIDs_backing\":{\"nightscoutId\":\"60ede2a4c574da0004a3869d\"},\"isValid\":true,\"isf\":49.0,\"note\":\"\",\"otherCorrection\":0.0,\"percentageCorrection\":90,\"profileName\":\"Tuned 13/01 90%Lyum\",\"superbolusInsulin\":0.0,\"targetBGHigh\":90.0,\"targetBGLow\":90.0,\"timestamp\":1626202783325,\"totalInsulin\":7.34,\"trendInsulin\":0.336734693877551,\"utcOffset\":7200000,\"version\":1,\"wasBasalIOBUsed\":true,\"wasBolusIOBUsed\":true,\"wasCOBUsed\":true,\"wasGlucoseUsed\":true,\"wasSuperbolusUsed\":false,\"wasTempTargetUsed\":false,\"wasTrendUsed\":true,\"wereCarbsUsed\":false}", - @SerializedName("type") val type: String?, // string "Meal Bolus", "Correction Bolus", "Combo Bolus", "Temp Basal" type of bolus "NORMAL", "SMB", "FAKE_EXTENDED" - @SerializedName("isSMB") val isSMB: Boolean, // boolean "Meal Bolus", "Correction Bolus", "Combo Bolus" - @SerializedName("enteredinsulin") val enteredinsulin: Double?, // number... "Combo Bolus" insulin is missing only enteredinsulin field found - @SerializedName("relative") val relative: Double?, // number... "Combo Bolus", "extendedEmulated" (not in doc see below) - @SerializedName("isEmulatingTempBasal") val isEmulatingTempBasal: Boolean, // boolean "Combo Bolus", "extendedEmulated" (not in doc see below) - @SerializedName("isAnnouncement") val isAnnouncement: Boolean, // boolean "Announcement" - @SerializedName("rate") val rate: Double?, // Double "Temp Basal" absolute rate (could be calculated with percent and profile information...) - @SerializedName("extendedEmulated") val extendedEmulated: RemoteTreatment?, // Gson of emulated EB - @SerializedName("timeshift") val timeshift: Long, // integer "Profile Switch" - @SerializedName("percentage") val percentage: Int?, // integer "Profile Switch" + @SerializedName("bolusCalculatorResult") val bolusCalculatorResult: String? = null, // string "Bolus Wizard" json toString ex "bolusCalculatorResult": "{\"basalIOB\":-0.247,\"bolusIOB\":-1.837,\"carbs\":45.0,\"carbsInsulin\":9.0,\"cob\":0.0,\"cobInsulin\":0.0,\"dateCreated\":1626202788810,\"glucoseDifference\":44.0,\"glucoseInsulin\":0.8979591836734694,\"glucoseTrend\":5.5,\"glucoseValue\":134.0,\"ic\":5.0,\"id\":331,\"interfaceIDs_backing\":{\"nightscoutId\":\"60ede2a4c574da0004a3869d\"},\"isValid\":true,\"isf\":49.0,\"note\":\"\",\"otherCorrection\":0.0,\"percentageCorrection\":90,\"profileName\":\"Tuned 13/01 90%Lyum\",\"superbolusInsulin\":0.0,\"targetBGHigh\":90.0,\"targetBGLow\":90.0,\"timestamp\":1626202783325,\"totalInsulin\":7.34,\"trendInsulin\":0.336734693877551,\"utcOffset\":7200000,\"version\":1,\"wasBasalIOBUsed\":true,\"wasBolusIOBUsed\":true,\"wasCOBUsed\":true,\"wasGlucoseUsed\":true,\"wasSuperbolusUsed\":false,\"wasTempTargetUsed\":false,\"wasTrendUsed\":true,\"wereCarbsUsed\":false}", + @SerializedName("type") val type: String? = null, // string "Meal Bolus", "Correction Bolus", "Combo Bolus", "Temp Basal" type of bolus "NORMAL", "SMB", "FAKE_EXTENDED" + @SerializedName("isSMB") val isSMB: Boolean? = null, // boolean "Meal Bolus", "Correction Bolus", "Combo Bolus" + @SerializedName("enteredinsulin") val enteredinsulin: Double? = null, // number... "Combo Bolus" insulin is missing only enteredinsulin field found + @SerializedName("relative") val relative: Double? = null, // number... "Combo Bolus", "extendedEmulated" (not in doc see below) + @SerializedName("isEmulatingTempBasal") val isEmulatingTempBasal: Boolean? = null, // boolean "Combo Bolus", "extendedEmulated" (not in doc see below) + @SerializedName("isAnnouncement") val isAnnouncement: Boolean? = null, // boolean "Announcement" + @SerializedName("rate") val rate: Double? = null, // Double "Temp Basal" absolute rate (could be calculated with percent and profile information...) + @SerializedName("extendedEmulated") val extendedEmulated: RemoteTreatment? = null, // Gson of emulated EB + @SerializedName("timeshift") val timeshift: Long? = null, // integer "Profile Switch" + @SerializedName("percentage") val percentage: Int? = null // integer "Profile Switch" ) { fun timestamp(): Long { - return date ?: mills ?: timestamp ?: fromISODateString(created_at) + return date ?: mills ?: timestamp ?: created_at?. let { fromISODateString(created_at) } ?: 0L } private fun fromISODateString(isoDateString: String): Long = diff --git a/plugins/sync/src/main/java/info/nightscout/plugins/sync/nsclient/extensions/ProfileSwitchExtension.kt b/plugins/sync/src/main/java/info/nightscout/plugins/sync/nsclient/extensions/ProfileSwitchExtension.kt index 09bc1e7f48..6975c1febb 100644 --- a/plugins/sync/src/main/java/info/nightscout/plugins/sync/nsclient/extensions/ProfileSwitchExtension.kt +++ b/plugins/sync/src/main/java/info/nightscout/plugins/sync/nsclient/extensions/ProfileSwitchExtension.kt @@ -5,6 +5,7 @@ import info.nightscout.core.extensions.getCustomizedName import info.nightscout.core.extensions.pureProfileFromJson import info.nightscout.core.profile.ProfileSealed import info.nightscout.database.entities.ProfileSwitch +import info.nightscout.database.entities.TherapyEvent import info.nightscout.database.entities.embedments.InterfaceIDs import info.nightscout.interfaces.plugin.ActivePlugin import info.nightscout.interfaces.utils.JsonHelper @@ -23,7 +24,7 @@ fun ProfileSwitch.toJson(isAdd: Boolean, dateUtil: DateUtil): JSONObject = .put("created_at", dateUtil.toISOString(timestamp)) .put("enteredBy", "openaps://" + "AndroidAPS") .put("isValid", isValid) - .put("eventType", info.nightscout.database.entities.TherapyEvent.Type.PROFILE_SWITCH.text) + .put("eventType", TherapyEvent.Type.PROFILE_SWITCH.text) .also { // remove customization to store original profileJson in toPureNsJson call timeshift = 0 percentage = 100 diff --git a/plugins/sync/src/main/java/info/nightscout/plugins/sync/nsclientV3/extensions/ExtendedBolusExtension.kt b/plugins/sync/src/main/java/info/nightscout/plugins/sync/nsclientV3/extensions/ExtendedBolusExtension.kt index c2dfeaa81b..090b71f7b2 100644 --- a/plugins/sync/src/main/java/info/nightscout/plugins/sync/nsclientV3/extensions/ExtendedBolusExtension.kt +++ b/plugins/sync/src/main/java/info/nightscout/plugins/sync/nsclientV3/extensions/ExtendedBolusExtension.kt @@ -11,6 +11,6 @@ fun NSExtendedBolus.toExtendedBolus(): ExtendedBolus = utcOffset = utcOffset, amount = enteredinsulin, duration = duration, - isEmulatingTempBasal = isEmulatingTempbasal, + isEmulatingTempBasal = isEmulatingTempBasal ?: false, interfaceIDs_backing = InterfaceIDs(nightscoutId = identifier, pumpId = pumpId, pumpType = InterfaceIDs.PumpType.fromString(pumpType), pumpSerial = pumpSerial, endId = endId) )