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
private val disposable = CompositeDisposable()
private lateinit var unfiltered: List<Food>
private lateinit var filtered: MutableList<Food>
private var unfiltered: List<Food> = arrayListOf()
private var filtered: MutableList<Food> = arrayListOf()
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_temporary_basal_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) {

View file

@ -27,7 +27,6 @@ import info.nightscout.androidaps.utils.DateUtil
import info.nightscout.androidaps.utils.JsonHelper
import info.nightscout.androidaps.utils.JsonHelper.safeGetLong
import info.nightscout.androidaps.utils.buildHelper.BuildHelper
import info.nightscout.androidaps.utils.extensions.*
import info.nightscout.androidaps.utils.sharedPreferences.SP
import java.util.concurrent.TimeUnit
import javax.inject.Inject
@ -60,7 +59,7 @@ class NSClientAddUpdateWorker(
var latestDateInReceivedData = 0L
for (i in 0 until treatments.length()) {
val json = treatments.getJSONObject(i)
var json = treatments.getJSONObject(i)
// new DB model
val insulin = JsonHelper.safeGetDouble(json, "insulin")
val carbs = JsonHelper.safeGetDouble(json, "carbs")
@ -133,6 +132,13 @@ class NSClientAddUpdateWorker(
}
} ?: 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 {
insulin > 0 || carbs > 0 -> Any()
eventType == TherapyEvent.Type.TEMPORARY_TARGET.text ->
@ -220,44 +226,6 @@ class NSClientAddUpdateWorker(
}
}
} ?: 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 ->
extendedBolusFromJson(json)?.let { extendedBolus ->
repository.runTransactionForResult(SyncNsExtendedBolusTransaction(extendedBolus))
@ -299,6 +267,44 @@ class NSClientAddUpdateWorker(
}
}
} ?: 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 ->
databaseHelper.createProfileSwitchFromJsonIfNotExists(json)
}

View file

@ -637,7 +637,8 @@ open class IobCobCalculatorPlugin @Inject constructor(
result.slopeFromMaxDeviation = autosensData.slopeFromMaxDeviation
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
}

View file

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

View file

@ -121,7 +121,8 @@ class TreatmentsExtendedBolusesFragment : DaggerFragment() {
override fun onBindViewHolder(holder: ExtendedBolusesViewHolder, position: Int) {
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()
@SuppressLint("SetTextI18n")
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.extensions.iobCalc
import info.nightscout.androidaps.extensions.toStringFull
import info.nightscout.androidaps.extensions.toTemporaryBasal
import info.nightscout.androidaps.extensions.toVisibility
import info.nightscout.androidaps.interfaces.ActivePluginProvider
import info.nightscout.androidaps.interfaces.ProfileFunction
@ -76,18 +77,49 @@ class TreatmentsTemporaryBasalsFragment : DaggerFragment() {
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() {
val now = System.currentTimeMillis()
disposable +=
if (activePlugin.activePump.isFakingTempsByExtendedBoluses) {
if (binding.showInvalidated.isChecked)
repository
.getTemporaryBasalsDataIncludingInvalidFromTime(now - millsToThePast, false)
tempBasalsWithInvalid(now)
.zipWith(extendedBolusesWithInvalid(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
repository
.getTemporaryBasalsDataFromTime(now - millsToThePast, false)
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
@ -95,16 +127,15 @@ class TreatmentsTemporaryBasalsFragment : DaggerFragment() {
super.onResume()
swapAdapter()
disposable.add(rxBus
disposable += rxBus
.toObservable(EventTempBasalChange::class.java)
.observeOn(aapsSchedulers.main)
.subscribe({ swapAdapter() }, fabricPrivacy::logException)
)
disposable.add(rxBus
disposable += rxBus
.toObservable(EventAutosensCalculationFinished::class.java)
.observeOn(aapsSchedulers.main)
.subscribe({ swapAdapter() }, fabricPrivacy::logException)
)
}
@Synchronized
@ -146,8 +177,10 @@ class TreatmentsTemporaryBasalsFragment : DaggerFragment() {
if (profile != null) iob = tempBasal.iobCalc(now, profile, activePlugin.activeInsulin)
holder.binding.iob.text = resourceHelper.gs(R.string.formatinsulinunits, iob.basaliob)
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)
holder.binding.type.text = tempBasal.type.toString()
holder.binding.remove.tag = tempBasal
}

View file

@ -69,6 +69,33 @@
android:textColor="@color/colorSetExtendedButton"
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
android:id="@+id/ph"
android:layout_width="wrap_content"
@ -124,15 +151,6 @@
android:layout_height="wrap_content"
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
android:id="@+id/invalid"
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 pumpSerial = JsonHelper.safeGetStringAllowNull(jsonObject, "pumpSerial", null)
if (timestamp == 0L) return null
if (amount == 0.0) return null
return Bolus(
timestamp = timestamp,
amount = amount,

View file

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

View file

@ -105,10 +105,14 @@ fun extendedBolusFromJson(jsonObject: JSONObject): ExtendedBolus? {
val pumpType = InterfaceIDs.PumpType.fromString(JsonHelper.safeGetStringAllowNull(jsonObject, "pumpType", 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(
timestamp = timestamp,
amount = amount,
duration = duration,
duration = T.mins(duration).msecs(),
isEmulatingTempBasal = isEmulatingTempBasal,
isValid = isValid
).also {

View file

@ -87,8 +87,8 @@ fun temporaryBasalFromNsIdForInvalidating(nsId: String): TemporaryBasal =
temporaryBasalFromJson(
JSONObject()
.put("mills", 1)
.put("absolute", -1.0)
.put("duration", -1.0)
.put("absolute", 1.0)
.put("duration", 1.0)
.put("_id", nsId)
.put("isValid", false)
)!!
@ -106,15 +106,16 @@ fun temporaryBasalFromJson(jsonObject: JSONObject): TemporaryBasal? {
val pumpType = InterfaceIDs.PumpType.fromString(JsonHelper.safeGetStringAllowNull(jsonObject, "pumpType", null))
val pumpSerial = JsonHelper.safeGetStringAllowNull(jsonObject, "pumpSerial", null)
val rate = if (percent != null) percent + 100
else absolute ?: return null
val rate = if (percent != null) percent + 100 else absolute ?: return null
if (duration == 0L) return null
if (timestamp == 0L) return null
return TemporaryBasal(
timestamp = timestamp,
rate = rate,
duration = duration,
duration = T.mins(duration).msecs(),
type = type,
isAbsolute = absolute != null,
isAbsolute = percent == null,
isValid = isValid
).also {
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 isValid = JsonHelper.safeGetBoolean(jsonObject, "isValid", true)
if (timestamp == 0L) return null
if (duration > 0L) {
// not ending event
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 isValid = JsonHelper.safeGetBoolean(jsonObject, "isValid", true)
if (timestamp == 0L) return null
val te = TherapyEvent(
timestamp = timestamp,
duration = TimeUnit.MINUTES.toMillis(duration),

View file

@ -7,4 +7,5 @@ interface DanaRInterface {
fun loadHistory(type: Byte): PumpEnactResult // for history browser
fun loadEvents(): PumpEnactResult // events history to build treatments from
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.alertDialogs.OKDialog
import info.nightscout.androidaps.extensions.toVisibility
import info.nightscout.androidaps.interfaces.DanaRInterface
import info.nightscout.androidaps.utils.resources.ResourceHelper
import info.nightscout.androidaps.utils.rx.AapsSchedulers
import info.nightscout.androidaps.utils.sharedPreferences.SP
@ -111,7 +112,7 @@ class DanaFragment : DaggerFragment() {
activity?.let {
OKDialog.showConfirmation(it, resourceHelper.gs(R.string.resetpairing)) {
uel.log(Action.CLEAR_PAIRING_KEYS, Sources.Dana)
(activePlugin.activePump as DanaPumpInterface).clearPairing()
(activePlugin.activePump as DanaRInterface).clearPairing()
}
}
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 ConstraintChecker constraintChecker;
private final FabricPrivacy fabricPrivacy;
private final PumpSync pumpSync;
@Inject
public DanaRKoreanPlugin(
@ -58,23 +57,22 @@ public class DanaRKoreanPlugin extends AbstractDanaRPlugin {
AAPSLogger aapsLogger,
AapsSchedulers aapsSchedulers,
RxBusWrapper rxBus,
DanaPump danaPump,
Context context,
ResourceHelper resourceHelper,
ConstraintChecker constraintChecker,
ActivePluginProvider activePlugin,
SP sp,
CommandQueueProvider commandQueue,
DanaPump danaPump,
DateUtil dateUtil,
PumpSync pumpSync,
FabricPrivacy fabricPrivacy
FabricPrivacy fabricPrivacy,
PumpSync pumpSync
) {
super(injector, danaPump, resourceHelper, constraintChecker, aapsLogger, aapsSchedulers, commandQueue, rxBus, activePlugin, sp, dateUtil, pumpSync);
this.aapsLogger = aapsLogger;
this.context = context;
this.resourceHelper = resourceHelper;
this.constraintChecker = constraintChecker;
this.pumpSync = pumpSync;
this.fabricPrivacy = fabricPrivacy;
getPluginDescription().description(R.string.description_pump_dana_r_korean);
@ -111,6 +109,7 @@ public class DanaRKoreanPlugin extends AbstractDanaRPlugin {
@Override
protected void onStop() {
context.unbindService(mConnection);
disposable.clear();
super.onStop();
}
@ -166,22 +165,21 @@ public class DanaRKoreanPlugin extends AbstractDanaRPlugin {
public PumpEnactResult deliverTreatment(DetailedBolusInfo detailedBolusInfo) {
detailedBolusInfo.insulin = constraintChecker.applyBolusConstraints(new Constraint<>(detailedBolusInfo.insulin)).value();
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;
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());
result.success(connectionOK && Math.abs(detailedBolusInfo.insulin - treatment.insulin) < pumpDescription.getBolusStep())
.bolusDelivered(treatment.insulin)
result.success(connectionOK && Math.abs(detailedBolusInfo.insulin - t.insulin) < pumpDescription.getBolusStep())
.bolusDelivered(t.insulin)
.carbsDelivered(detailedBolusInfo.carbs);
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
result.comment(R.string.ok);
aapsLogger.debug(LTag.PUMP, "deliverTreatment: OK. Asked: " + detailedBolusInfo.insulin + " Delivered: " + result.getBolusDelivered());
detailedBolusInfo.insulin = treatment.insulin;
detailedBolusInfo.insulin = t.insulin;
detailedBolusInfo.timestamp = System.currentTimeMillis();
if (detailedBolusInfo.insulin > 0)
pumpSync.syncBolusWithPumpId(
detailedBolusInfo.timestamp,
@ -262,7 +260,7 @@ public class DanaRKoreanPlugin extends AbstractDanaRPlugin {
// Check if some temp is already in progress
if (danaPump.isTempBasalInProgress()) {
// 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 (enforceNew) {
cancelTempBasal(true);
@ -348,7 +346,16 @@ public class DanaRKoreanPlugin extends AbstractDanaRPlugin {
PumpEnactResult result = new PumpEnactResult(getInjector());
if (danaPump.isTempBasalInProgress()) {
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 {
result.success(true).isTempCancel(true).comment(R.string.ok);
aapsLogger.debug(LTag.PUMP, "cancelRealTempBasal: OK");

View file

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

View file

@ -10,7 +10,6 @@ import java.util.Date;
import dagger.android.HasAndroidInjector;
import info.nightscout.androidaps.dana.DanaFragment;
import info.nightscout.androidaps.dana.DanaPump;
import info.nightscout.androidaps.dana.DanaPumpInterface;
import info.nightscout.androidaps.dana.comm.RecordTypes;
import info.nightscout.androidaps.danar.services.AbstractDanaRExecutionService;
import info.nightscout.androidaps.data.Profile;
@ -49,7 +48,7 @@ import io.reactivex.disposables.CompositeDisposable;
* 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 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);
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);
if (connectionOK && danaPump.isExtendedInProgress() && Math.abs(danaPump.getExtendedBolusAmount() - insulin) < getPumpDescription().getExtendedBolusStep()) {
result.enacted(true)
@ -294,11 +301,21 @@ public abstract class AbstractDanaRPlugin extends PumpPluginBase implements Pump
.isPercent(false);
if (!sp.getBoolean("danar_useextended", false))
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");
return result;
}
result.enacted(false).success(false).comment(R.string.danar_valuenotsetproperly);
getAapsLogger().error("setExtendedBolus: Failed to extended bolus");
getAapsLogger().error("inProgress: " + danaPump.isExtendedInProgress() + " start: " + danaPump.getExtendedBolusStart() + " amount: " + danaPump.getExtendedBolusAmount() + " duration: " + danaPump.getExtendedBolusDuration());
return result;
}
@ -307,9 +324,18 @@ public abstract class AbstractDanaRPlugin extends PumpPluginBase implements Pump
PumpEnactResult result = new PumpEnactResult(getInjector());
if (danaPump.isExtendedInProgress()) {
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 {
result.success(true).comment(R.string.ok);
result.success(true).comment(R.string.ok).isTempCancel(true);
getAapsLogger().debug(LTag.PUMP, "cancelExtendedBolus: OK");
}
return result;

View file

@ -340,7 +340,16 @@ public class DanaRPlugin extends AbstractDanaRPlugin {
PumpEnactResult result = new PumpEnactResult(getInjector());
if (danaPump.isTempBasalInProgress()) {
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 {
result.success(true).isTempCancel(true).comment(R.string.ok);
aapsLogger.debug(LTag.PUMP, "cancelRealTempBasal: OK");

View file

@ -23,9 +23,9 @@ class MsgInitConnStatusBasic(
danaPump.reservoirRemainingUnits = intFromBuff(bytes, 7, 3) / 750.0
danaPump.bolusBlocked = intFromBuff(bytes, 10, 1) == 1
danaPump.currentBasal = intFromBuff(bytes, 11, 2) / 100.0
danaPump.tempBasalPercent = intFromBuff(bytes, 13, 1)
danaPump.isExtendedInProgress = intFromBuff(bytes, 14, 1) == 1
danaPump.isTempBasalInProgress = intFromBuff(bytes, 15, 1) == 1
val tempBasalPercent = intFromBuff(bytes, 13, 1)
val isExtendedInProgress = intFromBuff(bytes, 14, 1) == 1
val isTempBasalInProgress = intFromBuff(bytes, 15, 1) == 1
val statusBasalUDOption = intFromBuff(bytes, 16, 1)
danaPump.isDualBolusInProgress = intFromBuff(bytes, 17, 1) == 1
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, "Bolus blocked: " + danaPump.bolusBlocked)
aapsLogger.debug(LTag.PUMPCOMM, "Current basal: " + danaPump.currentBasal)
aapsLogger.debug(LTag.PUMPCOMM, "Current temp basal percent: " + danaPump.tempBasalPercent)
aapsLogger.debug(LTag.PUMPCOMM, "Is extended bolus running: " + danaPump.isExtendedInProgress)
aapsLogger.debug(LTag.PUMPCOMM, "Current temp basal percent: " + tempBasalPercent)
aapsLogger.debug(LTag.PUMPCOMM, "Is extended bolus running: " + isExtendedInProgress)
aapsLogger.debug(LTag.PUMPCOMM, "statusBasalUDOption: $statusBasalUDOption")
aapsLogger.debug(LTag.PUMPCOMM, "Is dual bolus running: " + danaPump.isDualBolusInProgress)
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!!!")
} else {
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 info.nightscout.androidaps.logging.LTag
import info.nightscout.androidaps.utils.T
import kotlin.math.ceil
import kotlin.math.abs
import kotlin.math.floor
class MsgStatusBolusExtended(
injector: HasAndroidInjector
@ -27,9 +28,17 @@ class MsgStatusBolusExtended(
val extendedBolusAbsoluteRate = if (isExtendedInProgress) extendedBolusAmount / extendedBolusMinutes * 60 else 0.0
val extendedBolusStart = if (isExtendedInProgress) getDateFromSecAgo(extendedBolusSoFarInSecs) else 0
val extendedBolusRemainingMinutes = extendedBolusMinutes - extendedBolusSoFarInMinutes
if (isExtendedInProgress && !isWithin3Sec(extendedBolusStart)) {
danaPump.extendedBolusDuration = T.mins(extendedBolusMinutes).msecs()
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, "Extended bolus min: $extendedBolusMinutes")
aapsLogger.debug(LTag.PUMPCOMM, "Extended bolus amount: $extendedBolusAmount")
@ -40,6 +49,9 @@ class MsgStatusBolusExtended(
}
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 info.nightscout.androidaps.logging.LTag
import info.nightscout.androidaps.utils.T
import kotlin.math.abs
import kotlin.math.ceil
import kotlin.math.floor
class MsgStatusTempBasal(
injector: HasAndroidInjector
@ -19,26 +21,33 @@ class MsgStatusTempBasal(
val isAPSTempBasalInProgress = intFromBuff(bytes, 0, 1) and 0x02 == 0x02
var tempBasalPercent = intFromBuff(bytes, 1, 1)
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 tempBasalRemainingMin = (tempBasalTotalSec - tempBasalRunningSeconds) / 60
val tempBasalStart = if (isTempBasalInProgress) getDateFromTempBasalSecAgo(tempBasalRunningSeconds) else 0
val tempBasalStart = if (isTempBasalInProgress) getDateFromSecAgo(tempBasalRunningSeconds) else 0
if (isTempBasalInProgress && !isWithin3Sec(tempBasalStart)) {
danaPump.tempBasalStart = tempBasalStart
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 APS temp basal running: $isAPSTempBasalInProgress")
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 total sec: $tempBasalTotalSec")
aapsLogger.debug(LTag.PUMPCOMM, "Current temp basal total min: $tempBasalTotalMin")
aapsLogger.debug(LTag.PUMPCOMM, "Current temp basal start: " + dateUtil.dateAndTimeString(tempBasalStart))
}
private fun getDateFromTempBasalSecAgo(tempBasalAgoSecs: Int): Long {
return (ceil(System.currentTimeMillis() / 1000.0) - tempBasalAgoSecs).toLong() * 1000
private fun getDateFromSecAgo(tempBasalAgoSecs: Int): Long {
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

View file

@ -295,7 +295,7 @@ public abstract class AbstractDanaRExecutionService extends DaggerService {
if (pumpState.getTemporaryBasal() != null) {
if (danaPump.isTempBasalInProgress()) {
if (pumpState.getTemporaryBasal().getRate() != danaPump.getTempBasalPercent()
|| pumpState.getTemporaryBasal().getTimestamp() != danaPump.getTempBasalStart()
|| Math.abs(pumpState.getTemporaryBasal().getTimestamp() - danaPump.getTempBasalStart()) > 10000
) { // Close current temp basal
Notification notification = new Notification(Notification.UNSUPPORTED_ACTION_IN_PUMP, resourceHelper.gs(R.string.unsupported_action_in_pump), Notification.URGENT);
rxBus.send(new EventNewNotification(notification));
@ -341,7 +341,8 @@ public abstract class AbstractDanaRExecutionService extends DaggerService {
if (pumpState.getExtendedBolus() != null) {
if (danaPump.isExtendedInProgress()) {
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);
rxBus.send(new EventNewNotification(notification));
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 dagger.android.HasAndroidInjector
import info.nightscout.androidaps.dana.DanaPump
import info.nightscout.androidaps.dana.DanaPumpInterface
import info.nightscout.androidaps.danars.events.EventDanaRSDeviceChange
import info.nightscout.androidaps.danars.services.DanaRSService
import info.nightscout.androidaps.data.DetailedBolusInfo
@ -72,7 +71,7 @@ class DanaRSPlugin @Inject constructor(
.preferencesId(R.xml.pref_danars)
.description(R.string.description_pump_dana_rs),
injector, aapsLogger, resourceHelper, commandQueue
), PumpInterface, DanaRInterface, ConstraintsInterface, DanaPumpInterface {
), PumpInterface, DanaRInterface, ConstraintsInterface {
private val disposable = CompositeDisposable()
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))
dataIndex += dataSize
dataSize = 1
danaPump.isExtendedInProgress = byteArrayToInt(getBytes(data, dataIndex, dataSize)) == 0x01
val isExtendedInProgress = byteArrayToInt(getBytes(data, dataIndex, dataSize)) == 0x01
aapsLogger.debug(LTag.PUMPCOMM, "extendedMenuOption: $extendedMenuOption")
}

View file

@ -289,6 +289,11 @@ open class AppRepository @Inject internal constructor(
fun getLastBolusRecord():Bolus? =
database.bolusDao.getLastBolusRecord()
fun getLastBolusRecordWrapped():Single<ValueWrapper<Bolus>> =
database.bolusDao.getLastBolusRecordMaybe()
.subscribeOn(Schedulers.io())
.toWrappedSingle()
fun getLastBolusRecordOfType(type: Bolus.Type): Bolus? =
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")
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")
fun getLastBolusRecordOfType(only: Bolus.Type): Bolus?

View file

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

View file

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