DanaR working

This commit is contained in:
Milos Kozak 2021-04-09 08:02:46 +02:00
parent ec9efefb93
commit 4120e9eef9
32 changed files with 281 additions and 129 deletions

View file

@ -53,8 +53,8 @@ class FoodFragment : DaggerFragment() {
@Inject lateinit var uel: UserEntryLogger @Inject lateinit var uel: UserEntryLogger
private val disposable = CompositeDisposable() private val disposable = CompositeDisposable()
private lateinit var unfiltered: List<Food> private var unfiltered: List<Food> = arrayListOf()
private lateinit var filtered: MutableList<Food> private var filtered: MutableList<Food> = arrayListOf()
private var _binding: FoodFragmentBinding? = null private var _binding: FoodFragmentBinding? = null

View file

@ -32,6 +32,7 @@ class DataSyncSelectorImplementation @Inject constructor(
sp.remove(R.string.key_ns_device_status_last_synced_id) sp.remove(R.string.key_ns_device_status_last_synced_id)
sp.remove(R.string.key_ns_temporary_basal_last_synced_id) sp.remove(R.string.key_ns_temporary_basal_last_synced_id)
sp.remove(R.string.key_ns_extended_bolus_last_synced_id) sp.remove(R.string.key_ns_extended_bolus_last_synced_id)
sp.remove(R.string.key_ns_therapy_event_last_synced_id)
} }
override fun confirmLastBolusIdIfGreater(lastSynced: Long) { override fun confirmLastBolusIdIfGreater(lastSynced: Long) {

View file

@ -27,7 +27,6 @@ import info.nightscout.androidaps.utils.DateUtil
import info.nightscout.androidaps.utils.JsonHelper import info.nightscout.androidaps.utils.JsonHelper
import info.nightscout.androidaps.utils.JsonHelper.safeGetLong import info.nightscout.androidaps.utils.JsonHelper.safeGetLong
import info.nightscout.androidaps.utils.buildHelper.BuildHelper import info.nightscout.androidaps.utils.buildHelper.BuildHelper
import info.nightscout.androidaps.utils.extensions.*
import info.nightscout.androidaps.utils.sharedPreferences.SP import info.nightscout.androidaps.utils.sharedPreferences.SP
import java.util.concurrent.TimeUnit import java.util.concurrent.TimeUnit
import javax.inject.Inject import javax.inject.Inject
@ -60,7 +59,7 @@ class NSClientAddUpdateWorker(
var latestDateInReceivedData = 0L var latestDateInReceivedData = 0L
for (i in 0 until treatments.length()) { for (i in 0 until treatments.length()) {
val json = treatments.getJSONObject(i) var json = treatments.getJSONObject(i)
// new DB model // new DB model
val insulin = JsonHelper.safeGetDouble(json, "insulin") val insulin = JsonHelper.safeGetDouble(json, "insulin")
val carbs = JsonHelper.safeGetDouble(json, "carbs") val carbs = JsonHelper.safeGetDouble(json, "carbs")
@ -133,6 +132,13 @@ class NSClientAddUpdateWorker(
} }
} ?: aapsLogger.error("Error parsing bolus json $json") } ?: aapsLogger.error("Error parsing bolus json $json")
} }
// Convert back emulated TBR -> EB
if (eventType == TherapyEvent.Type.TEMPORARY_BASAL.text && json.has("extendedEmulated")) {
val ebJson = json.getJSONObject("extendedEmulated")
ebJson.put("_id", json.getString("_id"))
ebJson.put("isValid", json.getBoolean("isValid"))
json = ebJson
}
when { when {
insulin > 0 || carbs > 0 -> Any() insulin > 0 || carbs > 0 -> Any()
eventType == TherapyEvent.Type.TEMPORARY_TARGET.text -> eventType == TherapyEvent.Type.TEMPORARY_TARGET.text ->
@ -195,9 +201,9 @@ class NSClientAddUpdateWorker(
.blockingGet() .blockingGet()
.also { result -> .also { result ->
val action = when (eventType) { val action = when (eventType) {
TherapyEvent.Type.CANNULA_CHANGE.text -> Action.SITE_CHANGE TherapyEvent.Type.CANNULA_CHANGE.text -> Action.SITE_CHANGE
TherapyEvent.Type.INSULIN_CHANGE.text -> Action.RESERVOIR_CHANGE TherapyEvent.Type.INSULIN_CHANGE.text -> Action.RESERVOIR_CHANGE
else -> Action.CAREPORTAL else -> Action.CAREPORTAL
} }
result.inserted.forEach { result.inserted.forEach {
uel.log(action, Sources.NSClient, uel.log(action, Sources.NSClient,
@ -220,44 +226,6 @@ class NSClientAddUpdateWorker(
} }
} }
} ?: aapsLogger.error("Error parsing TherapyEvent json $json") } ?: aapsLogger.error("Error parsing TherapyEvent json $json")
eventType == TherapyEvent.Type.TEMPORARY_BASAL.text ->
temporaryBasalFromJson(json)?.let { temporaryBasal ->
repository.runTransactionForResult(SyncNsTemporaryBasalTransaction(temporaryBasal))
.doOnError {
aapsLogger.error(LTag.DATABASE, "Error while saving temporary basal", it)
ret = Result.failure(workDataOf("Error" to it))
}
.blockingGet()
.also { result ->
result.inserted.forEach {
uel.log(Action.TEMP_BASAL, Sources.NSClient,
ValueWithUnit.Timestamp(it.timestamp),
ValueWithUnit.UnitPerHour(it.rate),
ValueWithUnit.Minute(TimeUnit.MILLISECONDS.toMinutes(it.duration).toInt())
)
aapsLogger.debug(LTag.DATABASE, "Inserted TemporaryBasal $it")
}
result.invalidated.forEach {
uel.log(Action.TEMP_BASAL_REMOVED, Sources.NSClient,
ValueWithUnit.Timestamp(it.timestamp),
ValueWithUnit.UnitPerHour(it.rate),
ValueWithUnit.Minute(TimeUnit.MILLISECONDS.toMinutes(it.duration).toInt())
)
aapsLogger.debug(LTag.DATABASE, "Invalidated TemporaryBasal $it")
}
result.ended.forEach {
uel.log(Action.CANCEL_TEMP_BASAL, Sources.NSClient,
ValueWithUnit.Timestamp(it.timestamp),
ValueWithUnit.UnitPerHour(it.rate),
ValueWithUnit.Minute(TimeUnit.MILLISECONDS.toMinutes(it.duration).toInt())
)
aapsLogger.debug(LTag.DATABASE, "Updated TemporaryBasal $it")
}
result.updatedNsId.forEach {
aapsLogger.debug(LTag.DATABASE, "Updated nsId TemporaryBasal $it")
}
}
} ?: aapsLogger.error("Error parsing TemporaryBasal json $json")
eventType == TherapyEvent.Type.COMBO_BOLUS.text -> eventType == TherapyEvent.Type.COMBO_BOLUS.text ->
extendedBolusFromJson(json)?.let { extendedBolus -> extendedBolusFromJson(json)?.let { extendedBolus ->
repository.runTransactionForResult(SyncNsExtendedBolusTransaction(extendedBolus)) repository.runTransactionForResult(SyncNsExtendedBolusTransaction(extendedBolus))
@ -299,6 +267,44 @@ class NSClientAddUpdateWorker(
} }
} }
} ?: aapsLogger.error("Error parsing ExtendedBolus json $json") } ?: aapsLogger.error("Error parsing ExtendedBolus json $json")
eventType == TherapyEvent.Type.TEMPORARY_BASAL.text ->
temporaryBasalFromJson(json)?.let { temporaryBasal ->
repository.runTransactionForResult(SyncNsTemporaryBasalTransaction(temporaryBasal))
.doOnError {
aapsLogger.error(LTag.DATABASE, "Error while saving temporary basal", it)
ret = Result.failure(workDataOf("Error" to it))
}
.blockingGet()
.also { result ->
result.inserted.forEach {
uel.log(Action.TEMP_BASAL, Sources.NSClient,
ValueWithUnit.Timestamp(it.timestamp),
ValueWithUnit.UnitPerHour(it.rate),
ValueWithUnit.Minute(TimeUnit.MILLISECONDS.toMinutes(it.duration).toInt())
)
aapsLogger.debug(LTag.DATABASE, "Inserted TemporaryBasal $it")
}
result.invalidated.forEach {
uel.log(Action.TEMP_BASAL_REMOVED, Sources.NSClient,
ValueWithUnit.Timestamp(it.timestamp),
ValueWithUnit.UnitPerHour(it.rate),
ValueWithUnit.Minute(TimeUnit.MILLISECONDS.toMinutes(it.duration).toInt())
)
aapsLogger.debug(LTag.DATABASE, "Invalidated TemporaryBasal $it")
}
result.ended.forEach {
uel.log(Action.CANCEL_TEMP_BASAL, Sources.NSClient,
ValueWithUnit.Timestamp(it.timestamp),
ValueWithUnit.UnitPerHour(it.rate),
ValueWithUnit.Minute(TimeUnit.MILLISECONDS.toMinutes(it.duration).toInt())
)
aapsLogger.debug(LTag.DATABASE, "Ended TemporaryBasal $it")
}
result.updatedNsId.forEach {
aapsLogger.debug(LTag.DATABASE, "Updated nsId TemporaryBasal $it")
}
}
} ?: aapsLogger.error("Error parsing TemporaryBasal json $json")
eventType == TherapyEvent.Type.PROFILE_SWITCH.text -> eventType == TherapyEvent.Type.PROFILE_SWITCH.text ->
databaseHelper.createProfileSwitchFromJsonIfNotExists(json) databaseHelper.createProfileSwitchFromJsonIfNotExists(json)
} }

View file

@ -637,7 +637,8 @@ open class IobCobCalculatorPlugin @Inject constructor(
result.slopeFromMaxDeviation = autosensData.slopeFromMaxDeviation result.slopeFromMaxDeviation = autosensData.slopeFromMaxDeviation
result.usedMinCarbsImpact = autosensData.usedMinCarbsImpact result.usedMinCarbsImpact = autosensData.usedMinCarbsImpact
} }
result.lastBolusTime = repository.getLastBolusRecord()?.timestamp ?: 0L val lastBolus = repository.getLastBolusRecordWrapped().blockingGet()
result.lastBolusTime = if (lastBolus is ValueWrapper.Existing) lastBolus.value.timestamp else 0L
return result return result
} }

View file

@ -59,7 +59,7 @@ class RandomBgPlugin @Inject constructor(
const val interval = 5L // minutes const val interval = 5L // minutes
const val min = 70 // mgdl const val min = 70 // mgdl
const val max = 190 // mgdl const val max = 190 // mgdl
const val period = 30.0 // minutes const val period = 90.0 // minutes
} }
init { init {

View file

@ -121,7 +121,8 @@ class TreatmentsExtendedBolusesFragment : DaggerFragment() {
override fun onBindViewHolder(holder: ExtendedBolusesViewHolder, position: Int) { override fun onBindViewHolder(holder: ExtendedBolusesViewHolder, position: Int) {
val extendedBolus = extendedBolusList[position] val extendedBolus = extendedBolusList[position]
holder.binding.ph.visibility = (extendedBolus.interfaceIDs.nightscoutId != null).toVisibility() holder.binding.ns.visibility = (extendedBolus.interfaceIDs.nightscoutId != null).toVisibility()
holder.binding.ph.visibility = (extendedBolus.interfaceIDs.pumpId != null).toVisibility()
holder.binding.invalid.visibility = extendedBolus.isValid.not().toVisibility() holder.binding.invalid.visibility = extendedBolus.isValid.not().toVisibility()
@SuppressLint("SetTextI18n") @SuppressLint("SetTextI18n")
if (extendedBolus.isInProgress(dateUtil)) { if (extendedBolus.isInProgress(dateUtil)) {

View file

@ -25,6 +25,7 @@ import info.nightscout.androidaps.events.EventAutosensCalculationFinished
import info.nightscout.androidaps.events.EventTempBasalChange import info.nightscout.androidaps.events.EventTempBasalChange
import info.nightscout.androidaps.extensions.iobCalc import info.nightscout.androidaps.extensions.iobCalc
import info.nightscout.androidaps.extensions.toStringFull import info.nightscout.androidaps.extensions.toStringFull
import info.nightscout.androidaps.extensions.toTemporaryBasal
import info.nightscout.androidaps.extensions.toVisibility import info.nightscout.androidaps.extensions.toVisibility
import info.nightscout.androidaps.interfaces.ActivePluginProvider import info.nightscout.androidaps.interfaces.ActivePluginProvider
import info.nightscout.androidaps.interfaces.ProfileFunction import info.nightscout.androidaps.interfaces.ProfileFunction
@ -76,18 +77,49 @@ class TreatmentsTemporaryBasalsFragment : DaggerFragment() {
binding.recyclerview.layoutManager = LinearLayoutManager(view.context) binding.recyclerview.layoutManager = LinearLayoutManager(view.context)
} }
private fun tempBasalsWithInvalid(now: Long) = repository
.getTemporaryBasalsDataIncludingInvalidFromTime(now - millsToThePast, false)
private fun tempBasals(now: Long) = repository
.getTemporaryBasalsDataFromTime(now - millsToThePast, false)
private fun extendedBolusesWithInvalid(now: Long) = repository
.getExtendedBolusDataIncludingInvalidFromTime(now - millsToThePast, false)
.map { eb -> eb.map { profileFunction.getProfile(it.timestamp)?.let { profile -> it.toTemporaryBasal(profile) } } }
private fun extendedBoluses(now: Long) = repository
.getExtendedBolusDataFromTime(now - millsToThePast, false)
.map { eb -> eb.map { profileFunction.getProfile(it.timestamp)?.let { profile -> it.toTemporaryBasal(profile) } } }
fun swapAdapter() { fun swapAdapter() {
val now = System.currentTimeMillis() val now = System.currentTimeMillis()
if (binding.showInvalidated.isChecked) disposable +=
repository if (activePlugin.activePump.isFakingTempsByExtendedBoluses) {
.getTemporaryBasalsDataIncludingInvalidFromTime(now - millsToThePast, false) if (binding.showInvalidated.isChecked)
.observeOn(aapsSchedulers.main) tempBasalsWithInvalid(now)
.subscribe { list -> binding.recyclerview.swapAdapter(RecyclerViewAdapter(list), true) } .zipWith(extendedBolusesWithInvalid(now)) { first, second -> first + second }
else .map { list -> list.filterNotNull() }
repository .map { list -> list.sortedByDescending { it.timestamp } }
.getTemporaryBasalsDataFromTime(now - millsToThePast, false) .observeOn(aapsSchedulers.main)
.observeOn(aapsSchedulers.main) .subscribe { list -> binding.recyclerview.swapAdapter(RecyclerViewAdapter(list), true) }
.subscribe { list -> binding.recyclerview.swapAdapter(RecyclerViewAdapter(list), true) } else
tempBasals(now)
.zipWith(extendedBoluses(now)) { first, second -> first + second }
.map { list -> list.filterNotNull() }
.map { list -> list.sortedByDescending { it.timestamp } }
.observeOn(aapsSchedulers.main)
.subscribe { list -> binding.recyclerview.swapAdapter(RecyclerViewAdapter(list), true) }
} else {
if (binding.showInvalidated.isChecked)
tempBasalsWithInvalid(now)
.observeOn(aapsSchedulers.main)
.subscribe { list -> binding.recyclerview.swapAdapter(RecyclerViewAdapter(list), true) }
else
tempBasals(now)
.observeOn(aapsSchedulers.main)
.subscribe { list -> binding.recyclerview.swapAdapter(RecyclerViewAdapter(list), true) }
}
} }
@Synchronized @Synchronized
@ -95,16 +127,15 @@ class TreatmentsTemporaryBasalsFragment : DaggerFragment() {
super.onResume() super.onResume()
swapAdapter() swapAdapter()
disposable.add(rxBus disposable += rxBus
.toObservable(EventTempBasalChange::class.java) .toObservable(EventTempBasalChange::class.java)
.observeOn(aapsSchedulers.main) .observeOn(aapsSchedulers.main)
.subscribe({ swapAdapter() }, fabricPrivacy::logException) .subscribe({ swapAdapter() }, fabricPrivacy::logException)
)
disposable.add(rxBus disposable += rxBus
.toObservable(EventAutosensCalculationFinished::class.java) .toObservable(EventAutosensCalculationFinished::class.java)
.observeOn(aapsSchedulers.main) .observeOn(aapsSchedulers.main)
.subscribe({ swapAdapter() }, fabricPrivacy::logException) .subscribe({ swapAdapter() }, fabricPrivacy::logException)
)
} }
@Synchronized @Synchronized
@ -146,8 +177,10 @@ class TreatmentsTemporaryBasalsFragment : DaggerFragment() {
if (profile != null) iob = tempBasal.iobCalc(now, profile, activePlugin.activeInsulin) if (profile != null) iob = tempBasal.iobCalc(now, profile, activePlugin.activeInsulin)
holder.binding.iob.text = resourceHelper.gs(R.string.formatinsulinunits, iob.basaliob) holder.binding.iob.text = resourceHelper.gs(R.string.formatinsulinunits, iob.basaliob)
holder.binding.extendedFlag.visibility = (tempBasal.type == TemporaryBasal.Type.FAKE_EXTENDED).toVisibility() holder.binding.extendedFlag.visibility = (tempBasal.type == TemporaryBasal.Type.FAKE_EXTENDED).toVisibility()
holder.binding.suspendFlag.visibility = (tempBasal.type == TemporaryBasal.Type.PUMP_SUSPEND).toVisibility()
holder.binding.emulatedSuspendFlag.visibility = (tempBasal.type == TemporaryBasal.Type.EMULATED_PUMP_SUSPEND).toVisibility()
holder.binding.superBolusFlag.visibility = (tempBasal.type == TemporaryBasal.Type.SUPERBOLUS).toVisibility()
if (abs(iob.basaliob) > 0.01) holder.binding.iob.setTextColor(resourceHelper.gc(R.color.colorActive)) else holder.binding.iob.setTextColor(holder.binding.duration.currentTextColor) if (abs(iob.basaliob) > 0.01) holder.binding.iob.setTextColor(resourceHelper.gc(R.color.colorActive)) else holder.binding.iob.setTextColor(holder.binding.duration.currentTextColor)
holder.binding.type.text = tempBasal.type.toString()
holder.binding.remove.tag = tempBasal holder.binding.remove.tag = tempBasal
} }

View file

@ -69,6 +69,33 @@
android:textColor="@color/colorSetExtendedButton" android:textColor="@color/colorSetExtendedButton"
tools:ignore="HardcodedText,RtlSymmetry" /> tools:ignore="HardcodedText,RtlSymmetry" />
<TextView
android:id="@+id/suspend_flag"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="5dp"
android:text="S"
android:textColor="@color/colorSetExtendedButton"
tools:ignore="HardcodedText,RtlSymmetry" />
<TextView
android:id="@+id/emulated_suspend_flag"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="5dp"
android:text="ES"
android:textColor="@color/colorSetExtendedButton"
tools:ignore="HardcodedText,RtlSymmetry" />
<TextView
android:id="@+id/super_bolus_flag"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="5dp"
android:text="SB"
android:textColor="@color/colorSetExtendedButton"
tools:ignore="HardcodedText,RtlSymmetry" />
<TextView <TextView
android:id="@+id/ph" android:id="@+id/ph"
android:layout_width="wrap_content" android:layout_width="wrap_content"
@ -124,15 +151,6 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_weight="1" /> android:layout_weight="1" />
<TextView
android:id="@+id/type"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="5dp"
android:text="NORMAL"
android:textColor="@color/colorSetTempButton"
tools:ignore="HardcodedText" />
<TextView <TextView
android:id="@+id/invalid" android:id="@+id/invalid"
android:layout_width="wrap_content" android:layout_width="wrap_content"

View file

@ -53,6 +53,9 @@ fun bolusFromJson(jsonObject: JSONObject): Bolus? {
val pumpType = InterfaceIDs.PumpType.fromString(JsonHelper.safeGetStringAllowNull(jsonObject, "pumpType", null)) val pumpType = InterfaceIDs.PumpType.fromString(JsonHelper.safeGetStringAllowNull(jsonObject, "pumpType", null))
val pumpSerial = JsonHelper.safeGetStringAllowNull(jsonObject, "pumpSerial", null) val pumpSerial = JsonHelper.safeGetStringAllowNull(jsonObject, "pumpSerial", null)
if (timestamp == 0L) return null
if (amount == 0.0) return null
return Bolus( return Bolus(
timestamp = timestamp, timestamp = timestamp,
amount = amount, amount = amount,

View file

@ -42,6 +42,9 @@ fun carbsFromJson(jsonObject: JSONObject): Carbs? {
val pumpType = InterfaceIDs.PumpType.fromString(JsonHelper.safeGetStringAllowNull(jsonObject, "pumpType", null)) val pumpType = InterfaceIDs.PumpType.fromString(JsonHelper.safeGetStringAllowNull(jsonObject, "pumpType", null))
val pumpSerial = JsonHelper.safeGetStringAllowNull(jsonObject, "pumpSerial", null) val pumpSerial = JsonHelper.safeGetStringAllowNull(jsonObject, "pumpSerial", null)
if (timestamp == 0L) return null
if (amount == 0.0) return null
return Carbs( return Carbs(
timestamp = timestamp, timestamp = timestamp,
duration = duration, duration = duration,

View file

@ -105,10 +105,14 @@ fun extendedBolusFromJson(jsonObject: JSONObject): ExtendedBolus? {
val pumpType = InterfaceIDs.PumpType.fromString(JsonHelper.safeGetStringAllowNull(jsonObject, "pumpType", null)) val pumpType = InterfaceIDs.PumpType.fromString(JsonHelper.safeGetStringAllowNull(jsonObject, "pumpType", null))
val pumpSerial = JsonHelper.safeGetStringAllowNull(jsonObject, "pumpSerial", null) val pumpSerial = JsonHelper.safeGetStringAllowNull(jsonObject, "pumpSerial", null)
if (timestamp == 0L) return null
if (duration == 0L) return null
if (amount == 0.0) return null
return ExtendedBolus( return ExtendedBolus(
timestamp = timestamp, timestamp = timestamp,
amount = amount, amount = amount,
duration = duration, duration = T.mins(duration).msecs(),
isEmulatingTempBasal = isEmulatingTempBasal, isEmulatingTempBasal = isEmulatingTempBasal,
isValid = isValid isValid = isValid
).also { ).also {

View file

@ -87,8 +87,8 @@ fun temporaryBasalFromNsIdForInvalidating(nsId: String): TemporaryBasal =
temporaryBasalFromJson( temporaryBasalFromJson(
JSONObject() JSONObject()
.put("mills", 1) .put("mills", 1)
.put("absolute", -1.0) .put("absolute", 1.0)
.put("duration", -1.0) .put("duration", 1.0)
.put("_id", nsId) .put("_id", nsId)
.put("isValid", false) .put("isValid", false)
)!! )!!
@ -106,15 +106,16 @@ fun temporaryBasalFromJson(jsonObject: JSONObject): TemporaryBasal? {
val pumpType = InterfaceIDs.PumpType.fromString(JsonHelper.safeGetStringAllowNull(jsonObject, "pumpType", null)) val pumpType = InterfaceIDs.PumpType.fromString(JsonHelper.safeGetStringAllowNull(jsonObject, "pumpType", null))
val pumpSerial = JsonHelper.safeGetStringAllowNull(jsonObject, "pumpSerial", null) val pumpSerial = JsonHelper.safeGetStringAllowNull(jsonObject, "pumpSerial", null)
val rate = if (percent != null) percent + 100 val rate = if (percent != null) percent + 100 else absolute ?: return null
else absolute ?: return null if (duration == 0L) return null
if (timestamp == 0L) return null
return TemporaryBasal( return TemporaryBasal(
timestamp = timestamp, timestamp = timestamp,
rate = rate, rate = rate,
duration = duration, duration = T.mins(duration).msecs(),
type = type, type = type,
isAbsolute = absolute != null, isAbsolute = percent == null,
isValid = isValid isValid = isValid
).also { ).also {
it.interfaceIDs.nightscoutId = id it.interfaceIDs.nightscoutId = id

View file

@ -57,6 +57,8 @@ fun temporaryTargetFromJson(jsonObject: JSONObject): TemporaryTarget? {
val id = JsonHelper.safeGetStringAllowNull(jsonObject, "_id", null) ?: return null val id = JsonHelper.safeGetStringAllowNull(jsonObject, "_id", null) ?: return null
val isValid = JsonHelper.safeGetBoolean(jsonObject, "isValid", true) val isValid = JsonHelper.safeGetBoolean(jsonObject, "isValid", true)
if (timestamp == 0L) return null
if (duration > 0L) { if (duration > 0L) {
// not ending event // not ending event
if (units == Constants.MMOL) { if (units == Constants.MMOL) {

View file

@ -71,6 +71,8 @@ fun therapyEventFromJson(jsonObject: JSONObject): TherapyEvent? {
val id = JsonHelper.safeGetStringAllowNull(jsonObject, "_id", null) ?: return null val id = JsonHelper.safeGetStringAllowNull(jsonObject, "_id", null) ?: return null
val isValid = JsonHelper.safeGetBoolean(jsonObject, "isValid", true) val isValid = JsonHelper.safeGetBoolean(jsonObject, "isValid", true)
if (timestamp == 0L) return null
val te = TherapyEvent( val te = TherapyEvent(
timestamp = timestamp, timestamp = timestamp,
duration = TimeUnit.MINUTES.toMillis(duration), duration = TimeUnit.MINUTES.toMillis(duration),

View file

@ -7,4 +7,5 @@ interface DanaRInterface {
fun loadHistory(type: Byte): PumpEnactResult // for history browser fun loadHistory(type: Byte): PumpEnactResult // for history browser
fun loadEvents(): PumpEnactResult // events history to build treatments from fun loadEvents(): PumpEnactResult // events history to build treatments from
fun setUserOptions(): PumpEnactResult // like AnyDana does fun setUserOptions(): PumpEnactResult // like AnyDana does
fun clearPairing()
} }

View file

@ -32,6 +32,7 @@ import info.nightscout.androidaps.utils.userEntry.UserEntryMapper.Sources
import info.nightscout.androidaps.utils.WarnColors import info.nightscout.androidaps.utils.WarnColors
import info.nightscout.androidaps.utils.alertDialogs.OKDialog import info.nightscout.androidaps.utils.alertDialogs.OKDialog
import info.nightscout.androidaps.extensions.toVisibility import info.nightscout.androidaps.extensions.toVisibility
import info.nightscout.androidaps.interfaces.DanaRInterface
import info.nightscout.androidaps.utils.resources.ResourceHelper import info.nightscout.androidaps.utils.resources.ResourceHelper
import info.nightscout.androidaps.utils.rx.AapsSchedulers import info.nightscout.androidaps.utils.rx.AapsSchedulers
import info.nightscout.androidaps.utils.sharedPreferences.SP import info.nightscout.androidaps.utils.sharedPreferences.SP
@ -111,7 +112,7 @@ class DanaFragment : DaggerFragment() {
activity?.let { activity?.let {
OKDialog.showConfirmation(it, resourceHelper.gs(R.string.resetpairing)) { OKDialog.showConfirmation(it, resourceHelper.gs(R.string.resetpairing)) {
uel.log(Action.CLEAR_PAIRING_KEYS, Sources.Dana) uel.log(Action.CLEAR_PAIRING_KEYS, Sources.Dana)
(activePlugin.activePump as DanaPumpInterface).clearPairing() (activePlugin.activePump as DanaRInterface).clearPairing()
} }
} }
true true

View file

@ -1,5 +0,0 @@
package info.nightscout.androidaps.dana
interface DanaPumpInterface {
fun clearPairing()
}

View file

@ -50,7 +50,6 @@ public class DanaRKoreanPlugin extends AbstractDanaRPlugin {
private final ResourceHelper resourceHelper; private final ResourceHelper resourceHelper;
private final ConstraintChecker constraintChecker; private final ConstraintChecker constraintChecker;
private final FabricPrivacy fabricPrivacy; private final FabricPrivacy fabricPrivacy;
private final PumpSync pumpSync;
@Inject @Inject
public DanaRKoreanPlugin( public DanaRKoreanPlugin(
@ -58,23 +57,22 @@ public class DanaRKoreanPlugin extends AbstractDanaRPlugin {
AAPSLogger aapsLogger, AAPSLogger aapsLogger,
AapsSchedulers aapsSchedulers, AapsSchedulers aapsSchedulers,
RxBusWrapper rxBus, RxBusWrapper rxBus,
DanaPump danaPump,
Context context, Context context,
ResourceHelper resourceHelper, ResourceHelper resourceHelper,
ConstraintChecker constraintChecker, ConstraintChecker constraintChecker,
ActivePluginProvider activePlugin, ActivePluginProvider activePlugin,
SP sp, SP sp,
CommandQueueProvider commandQueue, CommandQueueProvider commandQueue,
DanaPump danaPump,
DateUtil dateUtil, DateUtil dateUtil,
PumpSync pumpSync, FabricPrivacy fabricPrivacy,
FabricPrivacy fabricPrivacy PumpSync pumpSync
) { ) {
super(injector, danaPump, resourceHelper, constraintChecker, aapsLogger, aapsSchedulers, commandQueue, rxBus, activePlugin, sp, dateUtil, pumpSync); super(injector, danaPump, resourceHelper, constraintChecker, aapsLogger, aapsSchedulers, commandQueue, rxBus, activePlugin, sp, dateUtil, pumpSync);
this.aapsLogger = aapsLogger; this.aapsLogger = aapsLogger;
this.context = context; this.context = context;
this.resourceHelper = resourceHelper; this.resourceHelper = resourceHelper;
this.constraintChecker = constraintChecker; this.constraintChecker = constraintChecker;
this.pumpSync = pumpSync;
this.fabricPrivacy = fabricPrivacy; this.fabricPrivacy = fabricPrivacy;
getPluginDescription().description(R.string.description_pump_dana_r_korean); getPluginDescription().description(R.string.description_pump_dana_r_korean);
@ -111,6 +109,7 @@ public class DanaRKoreanPlugin extends AbstractDanaRPlugin {
@Override @Override
protected void onStop() { protected void onStop() {
context.unbindService(mConnection); context.unbindService(mConnection);
disposable.clear(); disposable.clear();
super.onStop(); super.onStop();
} }
@ -166,22 +165,21 @@ public class DanaRKoreanPlugin extends AbstractDanaRPlugin {
public PumpEnactResult deliverTreatment(DetailedBolusInfo detailedBolusInfo) { public PumpEnactResult deliverTreatment(DetailedBolusInfo detailedBolusInfo) {
detailedBolusInfo.insulin = constraintChecker.applyBolusConstraints(new Constraint<>(detailedBolusInfo.insulin)).value(); detailedBolusInfo.insulin = constraintChecker.applyBolusConstraints(new Constraint<>(detailedBolusInfo.insulin)).value();
if (detailedBolusInfo.insulin > 0 || detailedBolusInfo.carbs > 0) { if (detailedBolusInfo.insulin > 0 || detailedBolusInfo.carbs > 0) {
EventOverviewBolusProgress.Treatment treatment = new EventOverviewBolusProgress.Treatment(0, 0, detailedBolusInfo.getBolusType() == DetailedBolusInfo.BolusType.SMB); EventOverviewBolusProgress.Treatment t = new EventOverviewBolusProgress.Treatment(0, 0, detailedBolusInfo.getBolusType() == DetailedBolusInfo.BolusType.SMB);
boolean connectionOK = false; boolean connectionOK = false;
if (detailedBolusInfo.insulin > 0 || detailedBolusInfo.carbs > 0) if (detailedBolusInfo.insulin > 0 || detailedBolusInfo.carbs > 0)
connectionOK = sExecutionService.bolus(detailedBolusInfo.insulin, (int) detailedBolusInfo.carbs, detailedBolusInfo.carbTime, treatment); connectionOK = sExecutionService.bolus(detailedBolusInfo.insulin, (int) detailedBolusInfo.carbs, detailedBolusInfo.carbTime, t);
PumpEnactResult result = new PumpEnactResult(getInjector()); PumpEnactResult result = new PumpEnactResult(getInjector());
result.success(connectionOK && Math.abs(detailedBolusInfo.insulin - treatment.insulin) < pumpDescription.getBolusStep()) result.success(connectionOK && Math.abs(detailedBolusInfo.insulin - t.insulin) < pumpDescription.getBolusStep())
.bolusDelivered(treatment.insulin) .bolusDelivered(t.insulin)
.carbsDelivered(detailedBolusInfo.carbs); .carbsDelivered(detailedBolusInfo.carbs);
if (!result.getSuccess()) if (!result.getSuccess())
result.comment(resourceHelper.gs(R.string.boluserrorcode, detailedBolusInfo.insulin, treatment.insulin, danaPump.getBolusStartErrorCode())); result.comment(resourceHelper.gs(R.string.boluserrorcode, detailedBolusInfo.insulin, t.insulin, danaPump.getBolusStartErrorCode()));
else else
result.comment(R.string.ok); result.comment(R.string.ok);
aapsLogger.debug(LTag.PUMP, "deliverTreatment: OK. Asked: " + detailedBolusInfo.insulin + " Delivered: " + result.getBolusDelivered()); aapsLogger.debug(LTag.PUMP, "deliverTreatment: OK. Asked: " + detailedBolusInfo.insulin + " Delivered: " + result.getBolusDelivered());
detailedBolusInfo.insulin = treatment.insulin; detailedBolusInfo.insulin = t.insulin;
detailedBolusInfo.timestamp = System.currentTimeMillis(); detailedBolusInfo.timestamp = System.currentTimeMillis();
if (detailedBolusInfo.insulin > 0) if (detailedBolusInfo.insulin > 0)
pumpSync.syncBolusWithPumpId( pumpSync.syncBolusWithPumpId(
detailedBolusInfo.timestamp, detailedBolusInfo.timestamp,
@ -262,7 +260,7 @@ public class DanaRKoreanPlugin extends AbstractDanaRPlugin {
// Check if some temp is already in progress // Check if some temp is already in progress
if (danaPump.isTempBasalInProgress()) { if (danaPump.isTempBasalInProgress()) {
// Correct basal already set ? // Correct basal already set ?
aapsLogger.debug(LTag.PUMP, "setTempBasalAbsolute: currently running: " + danaPump.getTempBasalPercent() + "%"); aapsLogger.debug(LTag.PUMP, "setTempBasalAbsolute: currently running: " + danaPump.temporaryBasalToString());
if (danaPump.getTempBasalPercent() == percentRate && danaPump.getTempBasalRemainingMin() > 4) { if (danaPump.getTempBasalPercent() == percentRate && danaPump.getTempBasalRemainingMin() > 4) {
if (enforceNew) { if (enforceNew) {
cancelTempBasal(true); cancelTempBasal(true);
@ -348,7 +346,16 @@ public class DanaRKoreanPlugin extends AbstractDanaRPlugin {
PumpEnactResult result = new PumpEnactResult(getInjector()); PumpEnactResult result = new PumpEnactResult(getInjector());
if (danaPump.isTempBasalInProgress()) { if (danaPump.isTempBasalInProgress()) {
sExecutionService.tempBasalStop(); sExecutionService.tempBasalStop();
result.enacted(true).isTempCancel(true); if (!danaPump.isTempBasalInProgress()) {
pumpSync.syncStopTemporaryBasalWithPumpId(
dateUtil._now(),
dateUtil._now(),
getPumpDescription().getPumpType(),
serialNumber()
);
result.success(true).enacted(true).isTempCancel(true);
} else
result.success(false).enacted(false).isTempCancel(true);
} else { } else {
result.success(true).isTempCancel(true).comment(R.string.ok); result.success(true).isTempCancel(true).comment(R.string.ok);
aapsLogger.debug(LTag.PUMP, "cancelRealTempBasal: OK"); aapsLogger.debug(LTag.PUMP, "cancelRealTempBasal: OK");

View file

@ -62,12 +62,12 @@ public class DanaRv2Plugin extends AbstractDanaRPlugin {
AapsSchedulers aapsSchedulers, AapsSchedulers aapsSchedulers,
RxBusWrapper rxBus, RxBusWrapper rxBus,
Context context, Context context,
DanaPump danaPump,
ResourceHelper resourceHelper, ResourceHelper resourceHelper,
ConstraintChecker constraintChecker, ConstraintChecker constraintChecker,
ActivePluginProvider activePlugin, ActivePluginProvider activePlugin,
SP sp, SP sp,
CommandQueueProvider commandQueue, CommandQueueProvider commandQueue,
DanaPump danaPump,
DetailedBolusInfoStorage detailedBolusInfoStorage, DetailedBolusInfoStorage detailedBolusInfoStorage,
TemporaryBasalStorage temporaryBasalStorage, TemporaryBasalStorage temporaryBasalStorage,
DateUtil dateUtil, DateUtil dateUtil,

View file

@ -10,7 +10,6 @@ import java.util.Date;
import dagger.android.HasAndroidInjector; import dagger.android.HasAndroidInjector;
import info.nightscout.androidaps.dana.DanaFragment; import info.nightscout.androidaps.dana.DanaFragment;
import info.nightscout.androidaps.dana.DanaPump; import info.nightscout.androidaps.dana.DanaPump;
import info.nightscout.androidaps.dana.DanaPumpInterface;
import info.nightscout.androidaps.dana.comm.RecordTypes; import info.nightscout.androidaps.dana.comm.RecordTypes;
import info.nightscout.androidaps.danar.services.AbstractDanaRExecutionService; import info.nightscout.androidaps.danar.services.AbstractDanaRExecutionService;
import info.nightscout.androidaps.data.Profile; import info.nightscout.androidaps.data.Profile;
@ -49,7 +48,7 @@ import io.reactivex.disposables.CompositeDisposable;
* Created by mike on 28.01.2018. * Created by mike on 28.01.2018.
*/ */
public abstract class AbstractDanaRPlugin extends PumpPluginBase implements PumpInterface, DanaRInterface, ConstraintsInterface, DanaPumpInterface { public abstract class AbstractDanaRPlugin extends PumpPluginBase implements PumpInterface, DanaRInterface, ConstraintsInterface {
protected AbstractDanaRExecutionService sExecutionService; protected AbstractDanaRExecutionService sExecutionService;
protected CompositeDisposable disposable = new CompositeDisposable(); protected CompositeDisposable disposable = new CompositeDisposable();
@ -283,6 +282,14 @@ public abstract class AbstractDanaRPlugin extends PumpPluginBase implements Pump
getAapsLogger().debug(LTag.PUMP, "setExtendedBolus: Correct extended bolus already set. Current: " + danaPump.getExtendedBolusAmount() + " Asked: " + insulin); getAapsLogger().debug(LTag.PUMP, "setExtendedBolus: Correct extended bolus already set. Current: " + danaPump.getExtendedBolusAmount() + " Asked: " + insulin);
return result; return result;
} }
if (danaPump.isExtendedInProgress()) {
cancelExtendedBolus();
if (danaPump.isExtendedInProgress()) {
result.enacted(false).success(false);
getAapsLogger().debug(LTag.PUMP, "cancelExtendedBolus failed. aborting setExtendedBolus");
return result;
}
}
boolean connectionOK = sExecutionService.extendedBolus(insulin, durationInHalfHours); boolean connectionOK = sExecutionService.extendedBolus(insulin, durationInHalfHours);
if (connectionOK && danaPump.isExtendedInProgress() && Math.abs(danaPump.getExtendedBolusAmount() - insulin) < getPumpDescription().getExtendedBolusStep()) { if (connectionOK && danaPump.isExtendedInProgress() && Math.abs(danaPump.getExtendedBolusAmount() - insulin) < getPumpDescription().getExtendedBolusStep()) {
result.enacted(true) result.enacted(true)
@ -294,11 +301,21 @@ public abstract class AbstractDanaRPlugin extends PumpPluginBase implements Pump
.isPercent(false); .isPercent(false);
if (!sp.getBoolean("danar_useextended", false)) if (!sp.getBoolean("danar_useextended", false))
result.bolusDelivered(danaPump.getExtendedBolusAmount()); result.bolusDelivered(danaPump.getExtendedBolusAmount());
pumpSync.syncExtendedBolusWithPumpId(
danaPump.getExtendedBolusStart(),
danaPump.getExtendedBolusAmount(),
danaPump.getExtendedBolusDuration(),
sp.getBoolean("danar_useextended", false),
danaPump.getExtendedBolusStart(),
getPumpDescription().getPumpType(),
serialNumber()
);
getAapsLogger().debug(LTag.PUMP, "setExtendedBolus: OK"); getAapsLogger().debug(LTag.PUMP, "setExtendedBolus: OK");
return result; return result;
} }
result.enacted(false).success(false).comment(R.string.danar_valuenotsetproperly); result.enacted(false).success(false).comment(R.string.danar_valuenotsetproperly);
getAapsLogger().error("setExtendedBolus: Failed to extended bolus"); getAapsLogger().error("setExtendedBolus: Failed to extended bolus");
getAapsLogger().error("inProgress: " + danaPump.isExtendedInProgress() + " start: " + danaPump.getExtendedBolusStart() + " amount: " + danaPump.getExtendedBolusAmount() + " duration: " + danaPump.getExtendedBolusDuration());
return result; return result;
} }
@ -307,9 +324,18 @@ public abstract class AbstractDanaRPlugin extends PumpPluginBase implements Pump
PumpEnactResult result = new PumpEnactResult(getInjector()); PumpEnactResult result = new PumpEnactResult(getInjector());
if (danaPump.isExtendedInProgress()) { if (danaPump.isExtendedInProgress()) {
sExecutionService.extendedBolusStop(); sExecutionService.extendedBolusStop();
result.enacted(true).isTempCancel(true); if (!danaPump.isExtendedInProgress()) {
result.success(true).enacted(true).isTempCancel(true);
pumpSync.syncStopExtendedBolusWithPumpId(
dateUtil._now(),
dateUtil._now(),
getPumpDescription().getPumpType(),
serialNumber()
);
} else
result.success(false).enacted(false).isTempCancel(true);
} else { } else {
result.success(true).comment(R.string.ok); result.success(true).comment(R.string.ok).isTempCancel(true);
getAapsLogger().debug(LTag.PUMP, "cancelExtendedBolus: OK"); getAapsLogger().debug(LTag.PUMP, "cancelExtendedBolus: OK");
} }
return result; return result;

View file

@ -340,7 +340,16 @@ public class DanaRPlugin extends AbstractDanaRPlugin {
PumpEnactResult result = new PumpEnactResult(getInjector()); PumpEnactResult result = new PumpEnactResult(getInjector());
if (danaPump.isTempBasalInProgress()) { if (danaPump.isTempBasalInProgress()) {
sExecutionService.tempBasalStop(); sExecutionService.tempBasalStop();
result.enacted(true).isTempCancel(true); if (!danaPump.isTempBasalInProgress()) {
pumpSync.syncStopTemporaryBasalWithPumpId(
dateUtil._now(),
dateUtil._now(),
getPumpDescription().getPumpType(),
serialNumber()
);
result.success(true).enacted(true).isTempCancel(true);
} else
result.success(false).enacted(false).isTempCancel(true);
} else { } else {
result.success(true).isTempCancel(true).comment(R.string.ok); result.success(true).isTempCancel(true).comment(R.string.ok);
aapsLogger.debug(LTag.PUMP, "cancelRealTempBasal: OK"); aapsLogger.debug(LTag.PUMP, "cancelRealTempBasal: OK");

View file

@ -23,9 +23,9 @@ class MsgInitConnStatusBasic(
danaPump.reservoirRemainingUnits = intFromBuff(bytes, 7, 3) / 750.0 danaPump.reservoirRemainingUnits = intFromBuff(bytes, 7, 3) / 750.0
danaPump.bolusBlocked = intFromBuff(bytes, 10, 1) == 1 danaPump.bolusBlocked = intFromBuff(bytes, 10, 1) == 1
danaPump.currentBasal = intFromBuff(bytes, 11, 2) / 100.0 danaPump.currentBasal = intFromBuff(bytes, 11, 2) / 100.0
danaPump.tempBasalPercent = intFromBuff(bytes, 13, 1) val tempBasalPercent = intFromBuff(bytes, 13, 1)
danaPump.isExtendedInProgress = intFromBuff(bytes, 14, 1) == 1 val isExtendedInProgress = intFromBuff(bytes, 14, 1) == 1
danaPump.isTempBasalInProgress = intFromBuff(bytes, 15, 1) == 1 val isTempBasalInProgress = intFromBuff(bytes, 15, 1) == 1
val statusBasalUDOption = intFromBuff(bytes, 16, 1) val statusBasalUDOption = intFromBuff(bytes, 16, 1)
danaPump.isDualBolusInProgress = intFromBuff(bytes, 17, 1) == 1 danaPump.isDualBolusInProgress = intFromBuff(bytes, 17, 1) == 1
val extendedBolusRate = intFromBuff(bytes, 18, 2) / 100.0 val extendedBolusRate = intFromBuff(bytes, 18, 2) / 100.0
@ -46,8 +46,8 @@ class MsgInitConnStatusBasic(
aapsLogger.debug(LTag.PUMPCOMM, "Reservoir remaining units: " + danaPump.reservoirRemainingUnits) aapsLogger.debug(LTag.PUMPCOMM, "Reservoir remaining units: " + danaPump.reservoirRemainingUnits)
aapsLogger.debug(LTag.PUMPCOMM, "Bolus blocked: " + danaPump.bolusBlocked) aapsLogger.debug(LTag.PUMPCOMM, "Bolus blocked: " + danaPump.bolusBlocked)
aapsLogger.debug(LTag.PUMPCOMM, "Current basal: " + danaPump.currentBasal) aapsLogger.debug(LTag.PUMPCOMM, "Current basal: " + danaPump.currentBasal)
aapsLogger.debug(LTag.PUMPCOMM, "Current temp basal percent: " + danaPump.tempBasalPercent) aapsLogger.debug(LTag.PUMPCOMM, "Current temp basal percent: " + tempBasalPercent)
aapsLogger.debug(LTag.PUMPCOMM, "Is extended bolus running: " + danaPump.isExtendedInProgress) aapsLogger.debug(LTag.PUMPCOMM, "Is extended bolus running: " + isExtendedInProgress)
aapsLogger.debug(LTag.PUMPCOMM, "statusBasalUDOption: $statusBasalUDOption") aapsLogger.debug(LTag.PUMPCOMM, "statusBasalUDOption: $statusBasalUDOption")
aapsLogger.debug(LTag.PUMPCOMM, "Is dual bolus running: " + danaPump.isDualBolusInProgress) aapsLogger.debug(LTag.PUMPCOMM, "Is dual bolus running: " + danaPump.isDualBolusInProgress)
aapsLogger.debug(LTag.PUMPCOMM, "Extended bolus rate: $extendedBolusRate") aapsLogger.debug(LTag.PUMPCOMM, "Extended bolus rate: $extendedBolusRate")

View file

@ -19,7 +19,7 @@ class MsgSetExtendedBolusStop(
aapsLogger.debug(LTag.PUMPBTCOMM, "Set extended bolus stop result: $result FAILED!!!") aapsLogger.debug(LTag.PUMPBTCOMM, "Set extended bolus stop result: $result FAILED!!!")
} else { } else {
failed = false failed = false
aapsLogger.debug(LTag.PUMPBTCOMM, "Set extended bolus stop result: $result") aapsLogger.debug(LTag.PUMPBTCOMM, "Set extended bolus stop result: $result OK")
} }
} }
} }

View file

@ -3,7 +3,8 @@ package info.nightscout.androidaps.danar.comm
import dagger.android.HasAndroidInjector import dagger.android.HasAndroidInjector
import info.nightscout.androidaps.logging.LTag import info.nightscout.androidaps.logging.LTag
import info.nightscout.androidaps.utils.T import info.nightscout.androidaps.utils.T
import kotlin.math.ceil import kotlin.math.abs
import kotlin.math.floor
class MsgStatusBolusExtended( class MsgStatusBolusExtended(
injector: HasAndroidInjector injector: HasAndroidInjector
@ -27,9 +28,17 @@ class MsgStatusBolusExtended(
val extendedBolusAbsoluteRate = if (isExtendedInProgress) extendedBolusAmount / extendedBolusMinutes * 60 else 0.0 val extendedBolusAbsoluteRate = if (isExtendedInProgress) extendedBolusAmount / extendedBolusMinutes * 60 else 0.0
val extendedBolusStart = if (isExtendedInProgress) getDateFromSecAgo(extendedBolusSoFarInSecs) else 0 val extendedBolusStart = if (isExtendedInProgress) getDateFromSecAgo(extendedBolusSoFarInSecs) else 0
val extendedBolusRemainingMinutes = extendedBolusMinutes - extendedBolusSoFarInMinutes val extendedBolusRemainingMinutes = extendedBolusMinutes - extendedBolusSoFarInMinutes
danaPump.extendedBolusDuration = T.mins(extendedBolusMinutes).msecs() if (isExtendedInProgress && !isWithin3Sec(extendedBolusStart)) {
danaPump.extendedBolusAmount = extendedBolusAmount danaPump.extendedBolusDuration = T.mins(extendedBolusMinutes).msecs()
danaPump.extendedBolusStart = extendedBolusStart danaPump.extendedBolusAmount = extendedBolusAmount
danaPump.extendedBolusStart = extendedBolusStart
aapsLogger.debug(LTag.PUMPCOMM, "New extended bolus detected")
} else if (!isExtendedInProgress) {
aapsLogger.debug(LTag.PUMPCOMM, "Extended bolus stopped. Previous state: ${danaPump.isExtendedInProgress}")
danaPump.isExtendedInProgress = false
} else {
aapsLogger.debug(LTag.PUMPCOMM, "No change in extended bolus. Current state: ${danaPump.isExtendedInProgress}")
}
aapsLogger.debug(LTag.PUMPCOMM, "Is extended bolus running: $isExtendedInProgress") aapsLogger.debug(LTag.PUMPCOMM, "Is extended bolus running: $isExtendedInProgress")
aapsLogger.debug(LTag.PUMPCOMM, "Extended bolus min: $extendedBolusMinutes") aapsLogger.debug(LTag.PUMPCOMM, "Extended bolus min: $extendedBolusMinutes")
aapsLogger.debug(LTag.PUMPCOMM, "Extended bolus amount: $extendedBolusAmount") aapsLogger.debug(LTag.PUMPCOMM, "Extended bolus amount: $extendedBolusAmount")
@ -40,6 +49,9 @@ class MsgStatusBolusExtended(
} }
private fun getDateFromSecAgo(tempBasalAgoSecs: Int): Long { private fun getDateFromSecAgo(tempBasalAgoSecs: Int): Long {
return (ceil(System.currentTimeMillis() / 1000.0) - tempBasalAgoSecs).toLong() * 1000 return (floor(System.currentTimeMillis() / 1000.0) - tempBasalAgoSecs).toLong() * 1000
} }
// because there is no fixed timestamp of start allow update of tbr only if tbr start differs more
private fun isWithin3Sec(newStart: Long) = abs(newStart - danaPump.tempBasalStart) < 3000
} }

View file

@ -2,8 +2,10 @@ package info.nightscout.androidaps.danar.comm
import dagger.android.HasAndroidInjector import dagger.android.HasAndroidInjector
import info.nightscout.androidaps.logging.LTag import info.nightscout.androidaps.logging.LTag
import info.nightscout.androidaps.utils.T
import kotlin.math.abs import kotlin.math.abs
import kotlin.math.ceil import kotlin.math.ceil
import kotlin.math.floor
class MsgStatusTempBasal( class MsgStatusTempBasal(
injector: HasAndroidInjector injector: HasAndroidInjector
@ -19,26 +21,33 @@ class MsgStatusTempBasal(
val isAPSTempBasalInProgress = intFromBuff(bytes, 0, 1) and 0x02 == 0x02 val isAPSTempBasalInProgress = intFromBuff(bytes, 0, 1) and 0x02 == 0x02
var tempBasalPercent = intFromBuff(bytes, 1, 1) var tempBasalPercent = intFromBuff(bytes, 1, 1)
if (tempBasalPercent > 200) tempBasalPercent = (tempBasalPercent - 200) * 10 if (tempBasalPercent > 200) tempBasalPercent = (tempBasalPercent - 200) * 10
val tempBasalTotalSec: Int = if (intFromBuff(bytes, 2, 1) == 150) 15 * 60 else if (intFromBuff(bytes, 2, 1) == 160) 30 * 60 else intFromBuff(bytes, 2, 1) * 60 * 60 var tempBasalTotalMin = intFromBuff(bytes, 2, 1) * 60
tempBasalTotalMin = if (tempBasalTotalMin == 150) 15 else if (tempBasalTotalMin == 160) 30 else tempBasalTotalMin
val tempBasalTotalSec = tempBasalTotalMin * 60
val tempBasalRunningSeconds = intFromBuff(bytes, 3, 3) val tempBasalRunningSeconds = intFromBuff(bytes, 3, 3)
val tempBasalRemainingMin = (tempBasalTotalSec - tempBasalRunningSeconds) / 60 val tempBasalRemainingMin = (tempBasalTotalSec - tempBasalRunningSeconds) / 60
val tempBasalStart = if (isTempBasalInProgress) getDateFromTempBasalSecAgo(tempBasalRunningSeconds) else 0 val tempBasalStart = if (isTempBasalInProgress) getDateFromSecAgo(tempBasalRunningSeconds) else 0
if (isTempBasalInProgress && !isWithin3Sec(tempBasalStart)) { if (isTempBasalInProgress && !isWithin3Sec(tempBasalStart)) {
danaPump.tempBasalStart = tempBasalStart danaPump.tempBasalStart = tempBasalStart
danaPump.tempBasalPercent = tempBasalPercent danaPump.tempBasalPercent = tempBasalPercent
danaPump.tempBasalTotalSec = tempBasalTotalSec.toLong() danaPump.tempBasalDuration = T.mins(tempBasalTotalMin.toLong()).msecs()
aapsLogger.debug(LTag.PUMPCOMM, "New temp basal detected")
} else if (!isTempBasalInProgress) {
aapsLogger.debug(LTag.PUMPCOMM, "Temp basal stopped. Previous state: ${danaPump.isTempBasalInProgress}")
danaPump.isTempBasalInProgress = false
} else {
aapsLogger.debug(LTag.PUMPCOMM, "No change in temp basal. Current state: ${danaPump.isTempBasalInProgress}")
} }
if (!isTempBasalInProgress) danaPump.isTempBasalInProgress = false
aapsLogger.debug(LTag.PUMPCOMM, "Is temp basal running: $isTempBasalInProgress") aapsLogger.debug(LTag.PUMPCOMM, "Is temp basal running: $isTempBasalInProgress")
aapsLogger.debug(LTag.PUMPCOMM, "Is APS temp basal running: $isAPSTempBasalInProgress") aapsLogger.debug(LTag.PUMPCOMM, "Is APS temp basal running: $isAPSTempBasalInProgress")
aapsLogger.debug(LTag.PUMPCOMM, "Current temp basal percent: $tempBasalPercent") aapsLogger.debug(LTag.PUMPCOMM, "Current temp basal percent: $tempBasalPercent")
aapsLogger.debug(LTag.PUMPCOMM, "Current temp basal remaining min: $tempBasalRemainingMin") aapsLogger.debug(LTag.PUMPCOMM, "Current temp basal remaining min: $tempBasalRemainingMin")
aapsLogger.debug(LTag.PUMPCOMM, "Current temp basal total sec: $tempBasalTotalSec") aapsLogger.debug(LTag.PUMPCOMM, "Current temp basal total min: $tempBasalTotalMin")
aapsLogger.debug(LTag.PUMPCOMM, "Current temp basal start: " + dateUtil.dateAndTimeString(tempBasalStart)) aapsLogger.debug(LTag.PUMPCOMM, "Current temp basal start: " + dateUtil.dateAndTimeString(tempBasalStart))
} }
private fun getDateFromTempBasalSecAgo(tempBasalAgoSecs: Int): Long { private fun getDateFromSecAgo(tempBasalAgoSecs: Int): Long {
return (ceil(System.currentTimeMillis() / 1000.0) - tempBasalAgoSecs).toLong() * 1000 return (floor(System.currentTimeMillis() / 1000.0) - tempBasalAgoSecs).toLong() * 1000
} }
// because there is no fixed timestamp of start allow update of tbr only if tbr start differs more // because there is no fixed timestamp of start allow update of tbr only if tbr start differs more

View file

@ -295,7 +295,7 @@ public abstract class AbstractDanaRExecutionService extends DaggerService {
if (pumpState.getTemporaryBasal() != null) { if (pumpState.getTemporaryBasal() != null) {
if (danaPump.isTempBasalInProgress()) { if (danaPump.isTempBasalInProgress()) {
if (pumpState.getTemporaryBasal().getRate() != danaPump.getTempBasalPercent() if (pumpState.getTemporaryBasal().getRate() != danaPump.getTempBasalPercent()
|| pumpState.getTemporaryBasal().getTimestamp() != danaPump.getTempBasalStart() || Math.abs(pumpState.getTemporaryBasal().getTimestamp() - danaPump.getTempBasalStart()) > 10000
) { // Close current temp basal ) { // Close current temp basal
Notification notification = new Notification(Notification.UNSUPPORTED_ACTION_IN_PUMP, resourceHelper.gs(R.string.unsupported_action_in_pump), Notification.URGENT); Notification notification = new Notification(Notification.UNSUPPORTED_ACTION_IN_PUMP, resourceHelper.gs(R.string.unsupported_action_in_pump), Notification.URGENT);
rxBus.send(new EventNewNotification(notification)); rxBus.send(new EventNewNotification(notification));
@ -341,7 +341,8 @@ public abstract class AbstractDanaRExecutionService extends DaggerService {
if (pumpState.getExtendedBolus() != null) { if (pumpState.getExtendedBolus() != null) {
if (danaPump.isExtendedInProgress()) { if (danaPump.isExtendedInProgress()) {
if (pumpState.getExtendedBolus().getRate() != danaPump.getExtendedBolusAbsoluteRate() if (pumpState.getExtendedBolus().getRate() != danaPump.getExtendedBolusAbsoluteRate()
|| pumpState.getExtendedBolus().getTimestamp() != danaPump.getExtendedBolusStart()) { // Close current extended || Math.abs(pumpState.getExtendedBolus().getTimestamp() - danaPump.getExtendedBolusStart()) > 10000
) { // Close current extended
Notification notification = new Notification(Notification.UNSUPPORTED_ACTION_IN_PUMP, resourceHelper.gs(R.string.unsupported_action_in_pump), Notification.URGENT); Notification notification = new Notification(Notification.UNSUPPORTED_ACTION_IN_PUMP, resourceHelper.gs(R.string.unsupported_action_in_pump), Notification.URGENT);
rxBus.send(new EventNewNotification(notification)); rxBus.send(new EventNewNotification(notification));
aapsLogger.error(LTag.PUMP, "Different extended bolus found running AAPS: " + (pumpState.getExtendedBolus() + " DanaPump " + danaPump.extendedBolusToString())); aapsLogger.error(LTag.PUMP, "Different extended bolus found running AAPS: " + (pumpState.getExtendedBolus() + " DanaPump " + danaPump.extendedBolusToString()));

View file

@ -9,7 +9,6 @@ import android.text.format.DateFormat
import androidx.preference.Preference import androidx.preference.Preference
import dagger.android.HasAndroidInjector import dagger.android.HasAndroidInjector
import info.nightscout.androidaps.dana.DanaPump import info.nightscout.androidaps.dana.DanaPump
import info.nightscout.androidaps.dana.DanaPumpInterface
import info.nightscout.androidaps.danars.events.EventDanaRSDeviceChange import info.nightscout.androidaps.danars.events.EventDanaRSDeviceChange
import info.nightscout.androidaps.danars.services.DanaRSService import info.nightscout.androidaps.danars.services.DanaRSService
import info.nightscout.androidaps.data.DetailedBolusInfo import info.nightscout.androidaps.data.DetailedBolusInfo
@ -72,7 +71,7 @@ class DanaRSPlugin @Inject constructor(
.preferencesId(R.xml.pref_danars) .preferencesId(R.xml.pref_danars)
.description(R.string.description_pump_dana_rs), .description(R.string.description_pump_dana_rs),
injector, aapsLogger, resourceHelper, commandQueue injector, aapsLogger, resourceHelper, commandQueue
), PumpInterface, DanaRInterface, ConstraintsInterface, DanaPumpInterface { ), PumpInterface, DanaRInterface, ConstraintsInterface {
private val disposable = CompositeDisposable() private val disposable = CompositeDisposable()
private var danaRSService: DanaRSService? = null private var danaRSService: DanaRSService? = null

View file

@ -23,7 +23,7 @@ class DanaRS_Packet_Bolus_Get_Extended_Menu_Option_State(
val extendedMenuOption = byteArrayToInt(getBytes(data, dataIndex, dataSize)) val extendedMenuOption = byteArrayToInt(getBytes(data, dataIndex, dataSize))
dataIndex += dataSize dataIndex += dataSize
dataSize = 1 dataSize = 1
danaPump.isExtendedInProgress = byteArrayToInt(getBytes(data, dataIndex, dataSize)) == 0x01 val isExtendedInProgress = byteArrayToInt(getBytes(data, dataIndex, dataSize)) == 0x01
aapsLogger.debug(LTag.PUMPCOMM, "extendedMenuOption: $extendedMenuOption") aapsLogger.debug(LTag.PUMPCOMM, "extendedMenuOption: $extendedMenuOption")
} }

View file

@ -286,9 +286,14 @@ open class AppRepository @Inject internal constructor(
database.bolusDao.getModifiedFrom(lastId) database.bolusDao.getModifiedFrom(lastId)
.subscribeOn(Schedulers.io()) .subscribeOn(Schedulers.io())
fun getLastBolusRecord(): Bolus? = fun getLastBolusRecord():Bolus? =
database.bolusDao.getLastBolusRecord() database.bolusDao.getLastBolusRecord()
fun getLastBolusRecordWrapped():Single<ValueWrapper<Bolus>> =
database.bolusDao.getLastBolusRecordMaybe()
.subscribeOn(Schedulers.io())
.toWrappedSingle()
fun getLastBolusRecordOfType(type: Bolus.Type): Bolus? = fun getLastBolusRecordOfType(type: Bolus.Type): Bolus? =
database.bolusDao.getLastBolusRecordOfType(type) database.bolusDao.getLastBolusRecordOfType(type)

View file

@ -33,6 +33,9 @@ internal interface BolusDao : TraceableDao<Bolus> {
@Query("SELECT * FROM $TABLE_BOLUSES WHERE isValid = 1 AND type <> :exclude AND referenceId IS NULL ORDER BY id ASC LIMIT 1") @Query("SELECT * FROM $TABLE_BOLUSES WHERE isValid = 1 AND type <> :exclude AND referenceId IS NULL ORDER BY id ASC LIMIT 1")
fun getLastBolusRecord(exclude: Bolus.Type = Bolus.Type.PRIMING): Bolus? fun getLastBolusRecord(exclude: Bolus.Type = Bolus.Type.PRIMING): Bolus?
@Query("SELECT * FROM $TABLE_BOLUSES WHERE isValid = 1 AND type <> :exclude AND referenceId IS NULL ORDER BY id ASC LIMIT 1")
fun getLastBolusRecordMaybe(exclude: Bolus.Type = Bolus.Type.PRIMING): Maybe<Bolus>
@Query("SELECT * FROM $TABLE_BOLUSES WHERE isValid = 1 AND type == :only AND referenceId IS NULL ORDER BY id ASC LIMIT 1") @Query("SELECT * FROM $TABLE_BOLUSES WHERE isValid = 1 AND type == :only AND referenceId IS NULL ORDER BY id ASC LIMIT 1")
fun getLastBolusRecordOfType(only: Bolus.Type): Bolus? fun getLastBolusRecordOfType(only: Bolus.Type): Bolus?

View file

@ -33,6 +33,10 @@ data class ExtendedBolus(
var isEmulatingTempBasal: Boolean = false var isEmulatingTempBasal: Boolean = false
) : TraceableDBEntry, DBEntryWithTimeAndDuration { ) : TraceableDBEntry, DBEntryWithTimeAndDuration {
init {
require(duration > 0)
}
val rate: Double // in U/h val rate: Double // in U/h
get() = amount * (60 * 60 * 1000.0) / duration get() = amount * (60 * 60 * 1000.0) / duration
} }

View file

@ -34,6 +34,11 @@ data class TemporaryBasal(
override var duration: Long override var duration: Long
) : TraceableDBEntry, DBEntryWithTimeAndDuration { ) : TraceableDBEntry, DBEntryWithTimeAndDuration {
init {
if (duration <= 0)
require(duration > 0)
}
enum class Type { enum class Type {
NORMAL, NORMAL,
EMULATED_PUMP_SUSPEND, EMULATED_PUMP_SUSPEND,