fix duration sync to NSClient

This commit is contained in:
Milos Kozak 2021-10-07 22:53:46 +02:00
parent 7fe403d52c
commit bdffe22803
23 changed files with 94 additions and 253 deletions

View file

@ -6,7 +6,6 @@ import info.nightscout.androidaps.plugins.general.food.FoodPlugin
import info.nightscout.androidaps.plugins.general.nsclient.NSClientAddAckWorker
import info.nightscout.androidaps.plugins.general.nsclient.NSClientAddUpdateWorker
import info.nightscout.androidaps.plugins.general.nsclient.NSClientMbgWorker
import info.nightscout.androidaps.plugins.general.nsclient.NSClientRemoveWorker
import info.nightscout.androidaps.plugins.general.nsclient.NSClientUpdateRemoveAckWorker
import info.nightscout.androidaps.plugins.general.smsCommunicator.SmsCommunicatorPlugin
import info.nightscout.androidaps.plugins.profile.local.LocalProfilePlugin
@ -29,7 +28,6 @@ abstract class WorkersModule {
@ContributesAndroidInjector abstract fun contributesNSClientWorker(): NSClientAddUpdateWorker
@ContributesAndroidInjector abstract fun contributesNSClientAddAckWorker(): NSClientAddAckWorker
@ContributesAndroidInjector abstract fun contributesNSClientUpdateRemoveAckWorker(): NSClientUpdateRemoveAckWorker
@ContributesAndroidInjector abstract fun contributesNSClientRemoveWorker(): NSClientRemoveWorker
@ContributesAndroidInjector abstract fun contributesNSClientMbgWorker(): NSClientMbgWorker
@ContributesAndroidInjector abstract fun contributesFoodWorker(): FoodPlugin.FoodWorker
}

View file

@ -75,7 +75,7 @@ class FoodPlugin @Inject constructor(
isValid = false
).also { it.interfaceIDs.nightscoutId = JsonHelper.safeGetString(jsonFood, "_id") }
repository.runTransactionForResult(SyncNsFoodTransaction(delFood, true))
repository.runTransactionForResult(SyncNsFoodTransaction(delFood))
.doOnError {
aapsLogger.error(LTag.DATABASE, "Error while removing food", it)
ret = Result.failure(workDataOf("Error" to it.toString()))
@ -89,7 +89,7 @@ class FoodPlugin @Inject constructor(
else -> {
val food = foodFromJson(jsonFood)
if (food != null) {
repository.runTransactionForResult(SyncNsFoodTransaction(food, false))
repository.runTransactionForResult(SyncNsFoodTransaction(food))
.doOnError {
aapsLogger.error(LTag.DATABASE, "Error while adding/updating food", it)
ret = Result.failure(workDataOf("Error" to it.toString()))

View file

@ -74,7 +74,7 @@ class NSClientAddUpdateWorker(
if (insulin > 0) {
if (sp.getBoolean(R.string.key_ns_receive_insulin, false) && buildHelper.isEngineeringMode() || config.NSCLIENT) {
bolusFromJson(json)?.let { bolus ->
repository.runTransactionForResult(SyncNsBolusTransaction(bolus, invalidateByNsOnly = false))
repository.runTransactionForResult(SyncNsBolusTransaction(bolus))
.doOnError {
aapsLogger.error(LTag.DATABASE, "Error while saving bolus", it)
ret = Result.failure(workDataOf("Error" to it.toString()))
@ -105,7 +105,7 @@ class NSClientAddUpdateWorker(
if (carbs > 0) {
if (sp.getBoolean(R.string.key_ns_receive_carbs, false) && buildHelper.isEngineeringMode() || config.NSCLIENT) {
carbsFromJson(json)?.let { carb ->
repository.runTransactionForResult(SyncNsCarbsTransaction(carb, invalidateByNsOnly = false))
repository.runTransactionForResult(SyncNsCarbsTransaction(carb))
.doOnError {
aapsLogger.error(LTag.DATABASE, "Error while saving carbs", it)
ret = Result.failure(workDataOf("Error" to it.toString()))
@ -145,7 +145,7 @@ class NSClientAddUpdateWorker(
eventType == TherapyEvent.Type.TEMPORARY_TARGET.text ->
if (sp.getBoolean(R.string.key_ns_receive_temp_target, false) && buildHelper.isEngineeringMode() || config.NSCLIENT) {
temporaryTargetFromJson(json)?.let { temporaryTarget ->
repository.runTransactionForResult(SyncNsTemporaryTargetTransaction(temporaryTarget, invalidateByNsOnly = false))
repository.runTransactionForResult(SyncNsTemporaryTargetTransaction(temporaryTarget))
.doOnError {
aapsLogger.error(LTag.DATABASE, "Error while saving temporary target", it)
ret = Result.failure(workDataOf("Error" to it.toString()))
@ -182,13 +182,16 @@ class NSClientAddUpdateWorker(
result.updatedNsId.forEach {
aapsLogger.debug(LTag.DATABASE, "Updated nsId TemporaryTarget $it")
}
result.updatedDuration.forEach {
aapsLogger.debug(LTag.DATABASE, "Updated duration TemporaryTarget $it")
}
}
} ?: aapsLogger.error("Error parsing TT json $json")
}
eventType == TherapyEvent.Type.NOTE.text && json.isEffectiveProfileSwitch() -> // replace this by new Type when available in NS
if (sp.getBoolean(R.string.key_ns_receive_profile_switch, false) && buildHelper.isEngineeringMode() || config.NSCLIENT) {
effectiveProfileSwitchFromJson(json, dateUtil)?.let { effectiveProfileSwitch ->
repository.runTransactionForResult(SyncNsEffectiveProfileSwitchTransaction(effectiveProfileSwitch, invalidateByNsOnly = false))
repository.runTransactionForResult(SyncNsEffectiveProfileSwitchTransaction(effectiveProfileSwitch))
.doOnError {
aapsLogger.error(LTag.DATABASE, "Error while saving EffectiveProfileSwitch", it)
ret = Result.failure(workDataOf("Error" to it.toString()))
@ -223,7 +226,7 @@ class NSClientAddUpdateWorker(
eventType == TherapyEvent.Type.PUMP_BATTERY_CHANGE.text ->
if (sp.getBoolean(R.string.key_ns_receive_therapy_events, false) || config.NSCLIENT) {
therapyEventFromJson(json)?.let { therapyEvent ->
repository.runTransactionForResult(SyncNsTherapyEventTransaction(therapyEvent, invalidateByNsOnly = false))
repository.runTransactionForResult(SyncNsTherapyEventTransaction(therapyEvent))
.doOnError {
aapsLogger.error(LTag.DATABASE, "Error while saving therapy event", it)
ret = Result.failure(workDataOf("Error" to it.toString()))
@ -254,13 +257,16 @@ class NSClientAddUpdateWorker(
result.updatedNsId.forEach {
aapsLogger.debug(LTag.DATABASE, "Updated nsId TherapyEvent $it")
}
result.updatedDuration.forEach {
aapsLogger.debug(LTag.DATABASE, "Updated nsId TherapyEvent $it")
}
}
} ?: aapsLogger.error("Error parsing TherapyEvent json $json")
}
eventType == TherapyEvent.Type.COMBO_BOLUS.text ->
if (config.NSCLIENT) {
extendedBolusFromJson(json)?.let { extendedBolus ->
repository.runTransactionForResult(SyncNsExtendedBolusTransaction(extendedBolus, invalidateByNsOnly = false))
repository.runTransactionForResult(SyncNsExtendedBolusTransaction(extendedBolus))
.doOnError {
aapsLogger.error(LTag.DATABASE, "Error while saving extended bolus", it)
ret = Result.failure(workDataOf("Error" to it.toString()))
@ -297,13 +303,16 @@ class NSClientAddUpdateWorker(
result.updatedNsId.forEach {
aapsLogger.debug(LTag.DATABASE, "Updated nsId ExtendedBolus $it")
}
result.updatedDuration.forEach {
aapsLogger.debug(LTag.DATABASE, "Updated duration ExtendedBolus $it")
}
}
} ?: aapsLogger.error("Error parsing ExtendedBolus json $json")
}
eventType == TherapyEvent.Type.TEMPORARY_BASAL.text ->
if (config.NSCLIENT) {
temporaryBasalFromJson(json)?.let { temporaryBasal ->
repository.runTransactionForResult(SyncNsTemporaryBasalTransaction(temporaryBasal, invalidateByNsOnly = false))
repository.runTransactionForResult(SyncNsTemporaryBasalTransaction(temporaryBasal))
.doOnError {
aapsLogger.error(LTag.DATABASE, "Error while saving temporary basal", it)
ret = Result.failure(workDataOf("Error" to it.toString()))
@ -337,13 +346,16 @@ class NSClientAddUpdateWorker(
result.updatedNsId.forEach {
aapsLogger.debug(LTag.DATABASE, "Updated nsId TemporaryBasal $it")
}
result.updatedDuration.forEach {
aapsLogger.debug(LTag.DATABASE, "Updated duration TemporaryBasal $it")
}
}
} ?: aapsLogger.error("Error parsing TemporaryBasal json $json")
}
eventType == TherapyEvent.Type.PROFILE_SWITCH.text ->
if (sp.getBoolean(R.string.key_ns_receive_profile_switch, false) && buildHelper.isEngineeringMode() || config.NSCLIENT) {
profileSwitchFromJson(json, dateUtil, activePlugin)?.let { profileSwitch ->
repository.runTransactionForResult(SyncNsProfileSwitchTransaction(profileSwitch, invalidateByNsOnly = false))
repository.runTransactionForResult(SyncNsProfileSwitchTransaction(profileSwitch))
.doOnError {
aapsLogger.error(LTag.DATABASE, "Error while saving ProfileSwitch", it)
ret = Result.failure(workDataOf("Error" to it.toString()))
@ -369,7 +381,7 @@ class NSClientAddUpdateWorker(
eventType == TherapyEvent.Type.APS_OFFLINE.text ->
if (sp.getBoolean(R.string.key_ns_receive_offline_event, false) && buildHelper.isEngineeringMode() || config.NSCLIENT) {
offlineEventFromJson(json)?.let { offlineEvent ->
repository.runTransactionForResult(SyncNsOfflineEventTransaction(offlineEvent, invalidateByNsOnly = false))
repository.runTransactionForResult(SyncNsOfflineEventTransaction(offlineEvent))
.doOnError {
aapsLogger.error(LTag.DATABASE, "Error while saving OfflineEvent", it)
ret = Result.failure(workDataOf("Error" to it.toString()))
@ -400,6 +412,9 @@ class NSClientAddUpdateWorker(
result.updatedNsId.forEach {
aapsLogger.debug(LTag.DATABASE, "Updated nsId OfflineEvent $it")
}
result.updatedDuration.forEach {
aapsLogger.debug(LTag.DATABASE, "Updated duration OfflineEvent $it")
}
}
} ?: aapsLogger.error("Error parsing OfflineEvent json $json")
}

View file

@ -41,7 +41,7 @@ class NSClientMbgWorker(
for (i in 0 until mbgArray.length()) {
val nsMbg = NSMbg(mbgArray.getJSONObject(i))
if (!nsMbg.isValid()) continue
repository.runTransactionForResult(SyncNsTherapyEventTransaction(therapyEventFromNsMbg(nsMbg), false))
repository.runTransactionForResult(SyncNsTherapyEventTransaction(therapyEventFromNsMbg(nsMbg)))
.doOnError {
aapsLogger.error("Error while saving therapy event", it)
ret = Result.failure(workDataOf("Error" to it.toString()))

View file

@ -1,182 +0,0 @@
package info.nightscout.androidaps.plugins.general.nsclient
import android.content.Context
import androidx.work.Worker
import androidx.work.WorkerParameters
import androidx.work.workDataOf
import dagger.android.HasAndroidInjector
import info.nightscout.androidaps.R
import info.nightscout.androidaps.database.AppRepository
import info.nightscout.androidaps.database.entities.UserEntry.Action
import info.nightscout.androidaps.database.entities.UserEntry.Sources
import info.nightscout.androidaps.database.entities.ValueWithUnit
import info.nightscout.androidaps.database.transactions.*
import info.nightscout.androidaps.extensions.*
import info.nightscout.androidaps.interfaces.Config
import info.nightscout.androidaps.logging.AAPSLogger
import info.nightscout.androidaps.logging.LTag
import info.nightscout.androidaps.logging.UserEntryLogger
import info.nightscout.androidaps.plugins.bus.RxBusWrapper
import info.nightscout.androidaps.receivers.DataWorker
import info.nightscout.androidaps.utils.JsonHelper
import info.nightscout.androidaps.utils.buildHelper.BuildHelper
import info.nightscout.androidaps.utils.sharedPreferences.SP
import java.util.concurrent.TimeUnit
import javax.inject.Inject
// This will not be needed fpr NS v3
// Now NS provides on _id of removed records
class NSClientRemoveWorker(
context: Context,
params: WorkerParameters) : Worker(context, params) {
@Inject lateinit var nsClientPlugin: NSClientPlugin
@Inject lateinit var dataWorker: DataWorker
@Inject lateinit var aapsLogger: AAPSLogger
@Inject lateinit var buildHelper: BuildHelper
@Inject lateinit var sp: SP
@Inject lateinit var config: Config
@Inject lateinit var repository: AppRepository
@Inject lateinit var rxBus: RxBusWrapper
@Inject lateinit var uel: UserEntryLogger
override fun doWork(): Result {
// Do not accept removed data over WS. Only invalidated trough NSClient
@Suppress("ConstantConditionIf")
if (true) return Result.success()
var ret = Result.success()
val treatments = dataWorker.pickupJSONArray(inputData.getLong(DataWorker.STORE_KEY, -1))
?: return Result.failure(workDataOf("Error" to "missing input data"))
for (i in 0 until treatments.length()) {
val json = treatments.getJSONObject(i)
val nsId = JsonHelper.safeGetString(json, "_id") ?: continue
// room Temporary target
val temporaryTarget = temporaryTargetFromNsIdForInvalidating(nsId)
repository.runTransactionForResult(SyncNsTemporaryTargetTransaction(temporaryTarget, invalidateByNsOnly = true))
.doOnError {
aapsLogger.error(LTag.DATABASE, "Error while invalidating temporary target", it)
ret = Result.failure(workDataOf("Error" to it.toString()))
}
.blockingGet()
.also { result ->
result.invalidated.forEach { tt ->
uel.log(
Action.TT_REMOVED, Sources.NSClient,
ValueWithUnit.TherapyEventTTReason(tt.reason),
ValueWithUnit.Mgdl(tt.lowTarget),
ValueWithUnit.Mgdl(tt.highTarget).takeIf { tt.lowTarget != tt.highTarget },
ValueWithUnit.Minute(TimeUnit.MILLISECONDS.toMinutes(tt.duration).toInt()).takeIf { tt.duration != 0L }
)
}
}
// room Therapy Event
val therapyEvent = therapyEventFromNsIdForInvalidating(nsId)
repository.runTransactionForResult(SyncNsTherapyEventTransaction(therapyEvent, invalidateByNsOnly = true))
.doOnError {
aapsLogger.error(LTag.DATABASE, "Error while invalidating therapy event", it)
ret = Result.failure(workDataOf("Error" to it.toString()))
}
.blockingGet()
.also { result ->
result.invalidated.forEach {
uel.log(Action.CAREPORTAL_REMOVED, Sources.NSClient,
(it.note ?: ""),
ValueWithUnit.Timestamp(it.timestamp),
ValueWithUnit.TherapyEventType(it.type))
}
}
// room Bolus
val bolus = bolusFromNsIdForInvalidating(nsId)
repository.runTransactionForResult(SyncNsBolusTransaction(bolus, invalidateByNsOnly = true))
.doOnError {
aapsLogger.error(LTag.DATABASE, "Error while invalidating bolus", it)
ret = Result.failure(workDataOf("Error" to it.toString()))
}
.blockingGet()
.also { result ->
result.invalidated.forEach {
uel.log(Action.CAREPORTAL_REMOVED, Sources.NSClient,
ValueWithUnit.Timestamp(it.timestamp),
ValueWithUnit.Insulin(it.amount))
}
}
// room Carbs
val carbs = carbsFromNsIdForInvalidating(nsId)
repository.runTransactionForResult(SyncNsCarbsTransaction(carbs, invalidateByNsOnly = true))
.doOnError {
aapsLogger.error(LTag.DATABASE, "Error while invalidating carbs", it)
ret = Result.failure(workDataOf("Error" to it.toString()))
}
.blockingGet()
.also { result ->
result.invalidated.forEach {
uel.log(Action.CAREPORTAL_REMOVED, Sources.NSClient,
ValueWithUnit.Timestamp(it.timestamp),
ValueWithUnit.Gram(it.amount.toInt()))
}
}
// room TemporaryBasal
val temporaryBasal = temporaryBasalFromNsIdForInvalidating(nsId)
repository.runTransactionForResult(SyncNsTemporaryBasalTransaction(temporaryBasal, invalidateByNsOnly = true))
.doOnError {
aapsLogger.error(LTag.DATABASE, "Error while invalidating temporary basal", it)
ret = Result.failure(workDataOf("Error" to it.toString()))
}
.blockingGet()
.also { result ->
result.invalidated.forEach {
uel.log(
Action.CAREPORTAL_REMOVED, Sources.NSClient,
ValueWithUnit.Timestamp(it.timestamp),
ValueWithUnit.UnitPerHour(it.rate))
}
}
// room ExtendedBolus
val extendedBolus = extendedBolusFromNsIdForInvalidating(nsId)
repository.runTransactionForResult(SyncNsExtendedBolusTransaction(extendedBolus, invalidateByNsOnly = true))
.doOnError {
aapsLogger.error(LTag.DATABASE, "Error while invalidating extended bolus", it)
ret = Result.failure(workDataOf("Error" to it.toString()))
}
.blockingGet()
.also { result ->
result.invalidated.forEach {
uel.log(
Action.CAREPORTAL_REMOVED, Sources.NSClient,
ValueWithUnit.Timestamp(it.timestamp),
ValueWithUnit.UnitPerHour(it.rate))
}
}
// room ProfileSwitch
repository.runTransactionForResult(InvalidateNsIdProfileSwitchTransaction(nsId))
.doOnError {
aapsLogger.error(LTag.DATABASE, "Error while invalidating ProfileSwitch", it)
ret = Result.failure(workDataOf("Error" to it.toString()))
}
.blockingGet()
.also { result ->
result.invalidated.forEach {
uel.log(
Action.CAREPORTAL_REMOVED, Sources.NSClient,
ValueWithUnit.Timestamp(it.timestamp))
}
}
}
return ret
}
init {
(context.applicationContext as HasAndroidInjector).androidInjector().inject(this)
}
}

View file

@ -491,30 +491,13 @@ class NSClientService : DaggerService() {
}
if (data.has("treatments")) {
val treatments = data.getJSONArray("treatments")
val removedTreatments = JSONArray()
val addedOrUpdatedTreatments = JSONArray()
if (treatments.length() > 0) rxBus.send(EventNSClientNewLog("DATA", "received " + treatments.length() + " treatments"))
for (index in 0 until treatments.length()) {
val jsonTreatment = treatments.getJSONObject(index)
val action = safeGetStringAllowNull(jsonTreatment, "action", null)
val mills = safeGetLong(jsonTreatment, "mills")
if (action == null) addedOrUpdatedTreatments.put(jsonTreatment) else if (action == "update") addedOrUpdatedTreatments.put(jsonTreatment) else if (action == "remove" && mills > dateUtil.now() - days(1).msecs()) // handle 1 day old deletions only
removedTreatments.put(jsonTreatment)
}
if (removedTreatments.length() > 0) {
dataWorker.enqueue(
OneTimeWorkRequest.Builder(NSClientRemoveWorker::class.java)
.setInputData(dataWorker.storeInputData(removedTreatments, null))
.build())
if (sp.getBoolean(R.string.key_nsclient_localbroadcasts, false)) {
val bundle = Bundle()
bundle.putString("treatments", removedTreatments.toString())
bundle.putBoolean("delta", isDelta)
val intent = Intent(Intents.ACTION_REMOVED_TREATMENT)
intent.putExtras(bundle)
intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES)
broadcast(intent)
}
if (action == null) addedOrUpdatedTreatments.put(jsonTreatment)
else if (action == "update") addedOrUpdatedTreatments.put(jsonTreatment)
}
if (addedOrUpdatedTreatments.length() > 0) {
dataWorker.enqueue(
@ -602,7 +585,8 @@ class NSClientService : DaggerService() {
message.put("_id", _id)
message.put("data", data)
socket?.emit("dbUpdate", message, NSUpdateAck("dbUpdate", _id, aapsLogger, rxBus, originalObject))
rxBus.send(EventNSClientNewLog("DBUPDATE $collection", "Sent " + originalObject.javaClass.simpleName + " " + _id + " " + progress))
rxBus.send(EventNSClientNewLog("DBUPDATE $collection", "Sent " + originalObject.javaClass.simpleName + " " +
"" + _id + " " + data + progress))
} catch (e: JSONException) {
aapsLogger.error("Unhandled exception", e)
}

View file

@ -8,7 +8,7 @@ import org.json.JSONException
import org.json.JSONObject
@Suppress("SpellCheckingInspection")
class IobTotal(var time: Long) : DataPointWithLabelInterface {
class IobTotal(val time: Long) : DataPointWithLabelInterface {
@JvmField var iob = 0.0
@JvmField var activity = 0.0

View file

@ -63,6 +63,7 @@ fun ExtendedBolus.toRealJson(isAdd: Boolean, dateUtil: DateUtil): JSONObject =
.put("enteredBy", "openaps://" + "AndroidAPS")
.put("eventType", TherapyEvent.Type.COMBO_BOLUS.text)
.put("duration", T.msecs(duration).mins())
.put("durationInMilliseconds", duration)
.put("splitNow", 0)
.put("splitExt", 100)
.put("enteredinsulin", amount)
@ -99,6 +100,7 @@ fun extendedBolusFromJson(jsonObject: JSONObject): ExtendedBolus? {
if (JsonHelper.safeGetIntAllowNull(jsonObject, "splitExt") != 100) return null
val amount = JsonHelper.safeGetDoubleAllowNull(jsonObject, "enteredinsulin") ?: return null
val duration = JsonHelper.safeGetLongAllowNull(jsonObject, "duration") ?: return null
val durationInMilliseconds = JsonHelper.safeGetLongAllowNull(jsonObject, "durationInMilliseconds")
val isValid = JsonHelper.safeGetBoolean(jsonObject, "isValid", true)
val isEmulatingTempBasal = JsonHelper.safeGetBoolean(jsonObject, "isEmulatingTempBasal", false)
val id = JsonHelper.safeGetStringAllowNull(jsonObject, "_id", null) ?: return null
@ -114,7 +116,7 @@ fun extendedBolusFromJson(jsonObject: JSONObject): ExtendedBolus? {
return ExtendedBolus(
timestamp = timestamp,
amount = amount,
duration = T.mins(duration).msecs(),
duration = durationInMilliseconds ?: T.mins(duration).msecs(),
isEmulatingTempBasal = isEmulatingTempBasal,
isValid = isValid
).also {

View file

@ -15,6 +15,7 @@ fun OfflineEvent.toJson(isAdd: Boolean, dateUtil: DateUtil): JSONObject =
.put("eventType", TherapyEvent.Type.APS_OFFLINE.text)
.put("isValid", isValid)
.put("duration", T.msecs(duration).mins())
.put("durationInMilliseconds", duration)
.put("reason", reason.name)
.also {
if (interfaceIDs.pumpId != null) it.put("pumpId", interfaceIDs.pumpId)
@ -39,6 +40,7 @@ fun OfflineEvent.toJson(isAdd: Boolean, dateUtil: DateUtil): JSONObject =
fun offlineEventFromJson(jsonObject: JSONObject): OfflineEvent? {
val timestamp = JsonHelper.safeGetLongAllowNull(jsonObject, "mills", null) ?: return null
val duration = JsonHelper.safeGetLong(jsonObject, "duration")
val durationInMilliseconds = JsonHelper.safeGetLongAllowNull(jsonObject, "durationInMilliseconds")
val isValid = JsonHelper.safeGetBoolean(jsonObject, "isValid", true)
val id = JsonHelper.safeGetStringAllowNull(jsonObject, "_id", null)
val pumpId = JsonHelper.safeGetLongAllowNull(jsonObject, "pumpId", null)
@ -50,7 +52,7 @@ fun offlineEventFromJson(jsonObject: JSONObject): OfflineEvent? {
return OfflineEvent(
timestamp = timestamp,
duration = T.mins(duration).msecs(),
duration = durationInMilliseconds ?: T.mins(duration).msecs(),
isValid = isValid,
reason = reason
).also {

View file

@ -69,6 +69,7 @@ fun TemporaryBasal.toJson(isAdd: Boolean, profile: Profile, dateUtil: DateUtil,
.put("eventType", TherapyEvent.Type.TEMPORARY_BASAL.text)
.put("isValid", isValid)
.put("duration", T.msecs(duration).mins())
.put("durationInMilliseconds", duration) // rounded duration leads to different basal IOB
.put("rate", rate)
.put("type", type.name)
.also {
@ -99,6 +100,7 @@ fun temporaryBasalFromJson(jsonObject: JSONObject): TemporaryBasal? {
val percent = JsonHelper.safeGetDoubleAllowNull(jsonObject, "percent")
val absolute = JsonHelper.safeGetDoubleAllowNull(jsonObject, "absolute")
val duration = JsonHelper.safeGetLongAllowNull(jsonObject, "duration") ?: return null
val durationInMilliseconds = JsonHelper.safeGetLongAllowNull(jsonObject, "durationInMilliseconds")
val type = fromString(JsonHelper.safeGetString(jsonObject, "type"))
val isValid = JsonHelper.safeGetBoolean(jsonObject, "isValid", true)
val id = JsonHelper.safeGetStringAllowNull(jsonObject, "_id", null) ?: return null
@ -114,7 +116,7 @@ fun temporaryBasalFromJson(jsonObject: JSONObject): TemporaryBasal? {
return TemporaryBasal(
timestamp = timestamp,
rate = rate,
duration = T.mins(duration).msecs(),
duration = durationInMilliseconds ?: T.mins(duration).msecs(),
type = type,
isAbsolute = percent == null,
isValid = isValid

View file

@ -50,6 +50,7 @@ fun temporaryTargetFromJson(jsonObject: JSONObject): TemporaryTarget? {
val units = GlucoseUnit.fromText(JsonHelper.safeGetString(jsonObject, "units", Constants.MGDL))
val timestamp = JsonHelper.safeGetLongAllowNull(jsonObject, "mills", null) ?: return null
val duration = JsonHelper.safeGetLongAllowNull(jsonObject, "duration", null) ?: return null
val durationInMilliseconds = JsonHelper.safeGetLongAllowNull(jsonObject, "durationInMilliseconds")
var low = JsonHelper.safeGetDouble(jsonObject, "targetBottom")
low = Profile.toMgdl(low, units)
var high = JsonHelper.safeGetDouble(jsonObject, "targetTop")
@ -81,7 +82,7 @@ fun temporaryTargetFromJson(jsonObject: JSONObject): TemporaryTarget? {
}
val tt = TemporaryTarget(
timestamp = timestamp,
duration = TimeUnit.MINUTES.toMillis(duration),
duration = durationInMilliseconds ?: T.mins(duration).msecs(),
reason = reason,
lowTarget = low,
highTarget = high,
@ -95,6 +96,7 @@ fun TemporaryTarget.toJson(isAdd: Boolean, units: GlucoseUnit, dateUtil: DateUti
JSONObject()
.put("eventType", TherapyEvent.Type.TEMPORARY_TARGET.text)
.put("duration", T.msecs(duration).mins())
.put("durationInMilliseconds", duration)
.put("isValid", isValid)
.put("created_at", dateUtil.toISOString(timestamp))
.put("enteredBy", "AndroidAPS").also {

View file

@ -73,6 +73,7 @@ fun therapyEventFromJson(jsonObject: JSONObject): TherapyEvent? {
val timestamp = JsonHelper.safeGetLongAllowNull(jsonObject, "mills", null) ?: return null
val type = TherapyEvent.Type.fromString(JsonHelper.safeGetString(jsonObject, "eventType", TherapyEvent.Type.NONE.text))
val duration = JsonHelper.safeGetLong(jsonObject, "duration")
val durationInMilliseconds = JsonHelper.safeGetLongAllowNull(jsonObject, "durationInMilliseconds")
val glucose = JsonHelper.safeGetDoubleAllowNull(jsonObject, "glucose")
val glucoseType = TherapyEvent.MeterType.fromString(JsonHelper.safeGetString(jsonObject, "glucoseType"))
val enteredBy = JsonHelper.safeGetStringAllowNull(jsonObject, "enteredBy", null)
@ -84,7 +85,7 @@ fun therapyEventFromJson(jsonObject: JSONObject): TherapyEvent? {
val te = TherapyEvent(
timestamp = timestamp,
duration = TimeUnit.MINUTES.toMillis(duration),
duration = durationInMilliseconds ?: T.mins(duration).msecs(),
glucoseUnit = glucoseUnit,
type = type,
glucose = glucose,
@ -106,6 +107,7 @@ fun TherapyEvent.toJson(isAdd: Boolean, dateUtil: DateUtil): JSONObject =
.put("units", if (glucoseUnit == TherapyEvent.GlucoseUnit.MGDL) Constants.MGDL else Constants.MMOL)
.also {
if (duration != 0L) it.put("duration", T.msecs(duration).mins())
if (duration != 0L) it.put("durationInMilliseconds", duration)
if (note != null) it.put("notes", note)
if (glucose != null) it.put("glucose", glucose)
if (glucoseType != null) it.put("glucoseType", glucoseType!!.text)

View file

@ -24,7 +24,7 @@ class CobInfo(val timestamp: Long, val displayCob: Double?, val futureCarbs: Dou
var cobText = resourceHelper.gs(R.string.format_carbs, displayCob.toInt())
if (futureCarbs > 0) cobText += "(" + DecimalFormatter.to0Decimal(futureCarbs) + ")"
// This is only temporary for debugging
if (isDev) cobText += "\n" + dateUtil.timeStringWithSeconds(timestamp)
if (isDev) cobText += "\n" + dateUtil.timeString(timestamp)
cobText
} else null
}

View file

@ -5,7 +5,7 @@ import info.nightscout.androidaps.database.entities.Bolus
/**
* Sync the Bolus from NS
*/
class SyncNsBolusTransaction(private val bolus: Bolus, private val invalidateByNsOnly: Boolean) : Transaction<SyncNsBolusTransaction.TransactionResult>() {
class SyncNsBolusTransaction(private val bolus: Bolus) : Transaction<SyncNsBolusTransaction.TransactionResult>() {
override fun run(): TransactionResult {
val result = TransactionResult()
@ -25,8 +25,6 @@ class SyncNsBolusTransaction(private val bolus: Bolus, private val invalidateByN
return result
}
if (invalidateByNsOnly) return result
// not known nsId
val existing = database.bolusDao.findByTimestamp(bolus.timestamp)
if (existing != null && existing.interfaceIDs.nightscoutId == null) {

View file

@ -5,7 +5,7 @@ import info.nightscout.androidaps.database.entities.Carbs
/**
* Sync the carbs from NS
*/
class SyncNsCarbsTransaction(private val carbs: Carbs, private val invalidateByNsOnly: Boolean) : Transaction<SyncNsCarbsTransaction.TransactionResult>() {
class SyncNsCarbsTransaction(private val carbs: Carbs) : Transaction<SyncNsCarbsTransaction.TransactionResult>() {
override fun run(): TransactionResult {
val result = TransactionResult()
@ -25,8 +25,6 @@ class SyncNsCarbsTransaction(private val carbs: Carbs, private val invalidateByN
return result
}
if (invalidateByNsOnly) return result
// not known nsId
val existing = database.carbsDao.findByTimestamp(carbs.timestamp)
if (existing != null && existing.interfaceIDs.nightscoutId == null) {

View file

@ -5,7 +5,7 @@ import info.nightscout.androidaps.database.entities.EffectiveProfileSwitch
/**
* Sync the EffectiveProfileSwitch from NS
*/
class SyncNsEffectiveProfileSwitchTransaction(private val effectiveProfileSwitch: EffectiveProfileSwitch, private val invalidateByNsOnly: Boolean) : Transaction<SyncNsEffectiveProfileSwitchTransaction.TransactionResult>() {
class SyncNsEffectiveProfileSwitchTransaction(private val effectiveProfileSwitch: EffectiveProfileSwitch) : Transaction<SyncNsEffectiveProfileSwitchTransaction.TransactionResult>() {
override fun run(): TransactionResult {
val result = TransactionResult()
@ -25,8 +25,6 @@ class SyncNsEffectiveProfileSwitchTransaction(private val effectiveProfileSwitch
return result
}
if (invalidateByNsOnly) return result
// not known nsId
val existing = database.effectiveProfileSwitchDao.findByTimestamp(effectiveProfileSwitch.timestamp)
if (existing != null && existing.interfaceIDs.nightscoutId == null) {

View file

@ -7,7 +7,8 @@ import kotlin.math.abs
/**
* Sync the Extended bolus from NS
*/
class SyncNsExtendedBolusTransaction(private val extendedBolus: ExtendedBolus, private val invalidateByNsOnly: Boolean) : Transaction<SyncNsExtendedBolusTransaction.TransactionResult>() {
class SyncNsExtendedBolusTransaction(private val extendedBolus: ExtendedBolus) :
Transaction<SyncNsExtendedBolusTransaction.TransactionResult>() {
override fun run(): TransactionResult {
val result = TransactionResult()
@ -26,11 +27,14 @@ class SyncNsExtendedBolusTransaction(private val extendedBolus: ExtendedBolus, p
database.extendedBolusDao.updateExistingEntry(current)
result.invalidated.add(current)
}
if (current.duration != extendedBolus.duration) {
current.duration = extendedBolus.duration
database.extendedBolusDao.updateExistingEntry(current)
result.updatedDuration.add(current)
}
return result
}
if (invalidateByNsOnly) return result
// not known nsId
val running = database.extendedBolusDao.getExtendedBolusActiveAt(extendedBolus.timestamp).blockingGet()
if (running != null && abs(running.timestamp - extendedBolus.timestamp) < 1000 && running.interfaceIDs.nightscoutId == null) { // allow missing milliseconds
@ -66,6 +70,7 @@ class SyncNsExtendedBolusTransaction(private val extendedBolus: ExtendedBolus, p
class TransactionResult {
val updatedNsId = mutableListOf<ExtendedBolus>()
val updatedDuration = mutableListOf<ExtendedBolus>()
val inserted = mutableListOf<ExtendedBolus>()
val invalidated = mutableListOf<ExtendedBolus>()
val ended = mutableListOf<ExtendedBolus>()

View file

@ -5,7 +5,7 @@ import info.nightscout.androidaps.database.entities.Food
/**
* Sync the TherapyEvents from NS
*/
class SyncNsFoodTransaction(private val food: Food, private val invalidateByNsOnly: Boolean) : Transaction<SyncNsFoodTransaction.TransactionResult>() {
class SyncNsFoodTransaction(private val food: Food) : Transaction<SyncNsFoodTransaction.TransactionResult>() {
override fun run(): TransactionResult {
val result = TransactionResult()
@ -26,8 +26,6 @@ class SyncNsFoodTransaction(private val food: Food, private val invalidateByNsOn
return result
}
if (invalidateByNsOnly) return result
// not known nsId, add
database.foodDao.insertNewEntry(food)
result.inserted.add(food)

View file

@ -7,7 +7,8 @@ import kotlin.math.abs
/**
* Sync the OfflineEvent from NS
*/
class SyncNsOfflineEventTransaction(private val offlineEvent: OfflineEvent, private val invalidateByNsOnly: Boolean) : Transaction<SyncNsOfflineEventTransaction.TransactionResult>() {
class SyncNsOfflineEventTransaction(private val offlineEvent: OfflineEvent) :
Transaction<SyncNsOfflineEventTransaction.TransactionResult>() {
override fun run(): TransactionResult {
val result = TransactionResult()
@ -26,11 +27,14 @@ class SyncNsOfflineEventTransaction(private val offlineEvent: OfflineEvent, priv
database.offlineEventDao.updateExistingEntry(current)
result.invalidated.add(current)
}
if (current.duration != offlineEvent.duration) {
current.duration = offlineEvent.duration
database.offlineEventDao.updateExistingEntry(current)
result.updatedDuration.add(current)
}
return result
}
if (invalidateByNsOnly) return result
// not known nsId
val running = database.offlineEventDao.getOfflineEventActiveAt(offlineEvent.timestamp).blockingGet()
if (running != null && abs(running.timestamp - offlineEvent.timestamp) < 1000 && running.interfaceIDs.nightscoutId == null) { // allow missing milliseconds
@ -66,6 +70,7 @@ class SyncNsOfflineEventTransaction(private val offlineEvent: OfflineEvent, priv
class TransactionResult {
val updatedNsId = mutableListOf<OfflineEvent>()
val updatedDuration = mutableListOf<OfflineEvent>()
val inserted = mutableListOf<OfflineEvent>()
val invalidated = mutableListOf<OfflineEvent>()
val ended = mutableListOf<OfflineEvent>()

View file

@ -5,7 +5,7 @@ import info.nightscout.androidaps.database.entities.ProfileSwitch
/**
* Sync the ProfileSwitch from NS
*/
class SyncNsProfileSwitchTransaction(private val profileSwitch: ProfileSwitch, private val invalidateByNsOnly: Boolean) : Transaction<SyncNsProfileSwitchTransaction.TransactionResult>() {
class SyncNsProfileSwitchTransaction(private val profileSwitch: ProfileSwitch) : Transaction<SyncNsProfileSwitchTransaction.TransactionResult>() {
override fun run(): TransactionResult {
val result = TransactionResult()
@ -25,8 +25,6 @@ class SyncNsProfileSwitchTransaction(private val profileSwitch: ProfileSwitch, p
return result
}
if (invalidateByNsOnly) return result
// not known nsId
val existing = database.profileSwitchDao.findByTimestamp(profileSwitch.timestamp)
if (existing != null && existing.interfaceIDs.nightscoutId == null) {

View file

@ -7,7 +7,9 @@ import kotlin.math.abs
/**
* Sync the Temporary Basal from NS
*/
class SyncNsTemporaryBasalTransaction(private val temporaryBasal: TemporaryBasal, private val invalidateByNsOnly: Boolean) : Transaction<SyncNsTemporaryBasalTransaction.TransactionResult>() {
class SyncNsTemporaryBasalTransaction(
private val temporaryBasal: TemporaryBasal
) : Transaction<SyncNsTemporaryBasalTransaction.TransactionResult>() {
override fun run(): TransactionResult {
val result = TransactionResult()
@ -26,11 +28,14 @@ class SyncNsTemporaryBasalTransaction(private val temporaryBasal: TemporaryBasal
database.temporaryBasalDao.updateExistingEntry(current)
result.invalidated.add(current)
}
if (current.duration != temporaryBasal.duration) {
current.duration = temporaryBasal.duration
database.temporaryBasalDao.updateExistingEntry(current)
result.updatedDuration.add(current)
}
return result
}
if (invalidateByNsOnly) return result
// not known nsId
val running = database.temporaryBasalDao.getTemporaryBasalActiveAt(temporaryBasal.timestamp).blockingGet()
if (running != null && abs(running.timestamp - temporaryBasal.timestamp) < 1000 && running.interfaceIDs.nightscoutId == null) { // allow missing milliseconds
@ -57,6 +62,7 @@ class SyncNsTemporaryBasalTransaction(private val temporaryBasal: TemporaryBasal
class TransactionResult {
val updatedNsId = mutableListOf<TemporaryBasal>()
val updatedDuration = mutableListOf<TemporaryBasal>()
val inserted = mutableListOf<TemporaryBasal>()
val invalidated = mutableListOf<TemporaryBasal>()
val ended = mutableListOf<TemporaryBasal>()

View file

@ -7,7 +7,8 @@ import kotlin.math.abs
/**
* Sync the TemporaryTarget from NS
*/
class SyncNsTemporaryTargetTransaction(private val temporaryTarget: TemporaryTarget, private val invalidateByNsOnly: Boolean) : Transaction<SyncNsTemporaryTargetTransaction.TransactionResult>() {
class SyncNsTemporaryTargetTransaction(private val temporaryTarget: TemporaryTarget) :
Transaction<SyncNsTemporaryTargetTransaction.TransactionResult>() {
override fun run(): TransactionResult {
val result = TransactionResult()
@ -26,11 +27,14 @@ class SyncNsTemporaryTargetTransaction(private val temporaryTarget: TemporaryTar
database.temporaryTargetDao.updateExistingEntry(current)
result.invalidated.add(current)
}
if (current.duration != temporaryTarget.duration) {
current.duration = temporaryTarget.duration
database.temporaryTargetDao.updateExistingEntry(current)
result.updatedDuration.add(current)
}
return result
}
if (invalidateByNsOnly) return result
// not known nsId
val running = database.temporaryTargetDao.getTemporaryTargetActiveAt(temporaryTarget.timestamp).blockingGet()
if (running != null && abs(running.timestamp - temporaryTarget.timestamp) < 1000 && running.interfaceIDs.nightscoutId == null) { // allow missing milliseconds
@ -66,6 +70,7 @@ class SyncNsTemporaryTargetTransaction(private val temporaryTarget: TemporaryTar
class TransactionResult {
val updatedNsId = mutableListOf<TemporaryTarget>()
val updatedDuration = mutableListOf<TemporaryTarget>()
val inserted = mutableListOf<TemporaryTarget>()
val invalidated = mutableListOf<TemporaryTarget>()
val ended = mutableListOf<TemporaryTarget>()

View file

@ -5,7 +5,8 @@ import info.nightscout.androidaps.database.entities.TherapyEvent
/**
* Sync the TherapyEvents from NS
*/
class SyncNsTherapyEventTransaction(private val therapyEvent: TherapyEvent, private val invalidateByNsOnly: Boolean) : Transaction<SyncNsTherapyEventTransaction.TransactionResult>() {
class SyncNsTherapyEventTransaction(private val therapyEvent: TherapyEvent) :
Transaction<SyncNsTherapyEventTransaction.TransactionResult>() {
override fun run(): TransactionResult {
val result = TransactionResult()
@ -22,11 +23,14 @@ class SyncNsTherapyEventTransaction(private val therapyEvent: TherapyEvent, priv
database.therapyEventDao.updateExistingEntry(current)
result.invalidated.add(current)
}
if (current.duration != therapyEvent.duration) {
current.duration = therapyEvent.duration
database.therapyEventDao.updateExistingEntry(current)
result.updatedDuration.add(current)
}
return result
}
if (invalidateByNsOnly) return result
// not known nsId
val existing = database.therapyEventDao.findByTimestamp(therapyEvent.type, therapyEvent.timestamp)
if (existing != null && existing.interfaceIDs.nightscoutId == null) {
@ -46,6 +50,7 @@ class SyncNsTherapyEventTransaction(private val therapyEvent: TherapyEvent, priv
class TransactionResult {
val updatedNsId = mutableListOf<TherapyEvent>()
val updatedDuration = mutableListOf<TherapyEvent>()
val inserted = mutableListOf<TherapyEvent>()
val invalidated = mutableListOf<TherapyEvent>()
}