Merge pull request #2945 from AAPS-Omnipod/omnipod_eros_dev_upstream_merge

More Omnipod updates & cleanup
This commit is contained in:
Milos Kozak 2020-09-08 16:20:24 +02:00 committed by GitHub
commit a87a69be38
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
242 changed files with 4895 additions and 4438 deletions

View file

@ -440,7 +440,7 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
}
private void scheduleBgHistoryChange(@Nullable final long timestamp) {
private void scheduleBgHistoryChange(@Nullable final long timestamp) {
class PostRunnable implements Runnable {
public void run() {
aapsLogger.debug(LTag.DATABASE, "Firing EventNewBg");
@ -455,8 +455,9 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
scheduledBgHistoryPost.cancel(false);
Runnable task = new PostRunnable();
final int sec = 3;
if (oldestBgHistoryChange == 0 || oldestBgHistoryChange > timestamp) oldestBgHistoryChange = timestamp;
scheduledBgHistoryPost = bgHistoryWorker.schedule(task, sec, TimeUnit.SECONDS);
if (oldestBgHistoryChange == 0 || oldestBgHistoryChange > timestamp)
oldestBgHistoryChange = timestamp;
scheduledBgHistoryPost = bgHistoryWorker.schedule(task, sec, TimeUnit.SECONDS);
}
@ -1974,7 +1975,6 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
}
}
public List<OmnipodHistoryRecord> getAllOmnipodHistoryRecordsFromTimeStamp(long from, boolean ascending) {
try {
Dao<OmnipodHistoryRecord, Long> daoPodHistory = getDaoPodHistory();
@ -1993,6 +1993,20 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
return new ArrayList<>();
}
public OmnipodHistoryRecord findOmnipodHistoryRecordByPumpId(long pumpId) {
try {
Dao<OmnipodHistoryRecord, Long> daoPodHistory = getDaoPodHistory();
QueryBuilder<OmnipodHistoryRecord, Long> queryBuilder = daoPodHistory.queryBuilder();
queryBuilder.orderBy("date", false);
Where<OmnipodHistoryRecord, Long> where = queryBuilder.where();
where.eq("pumpId", pumpId);
PreparedQuery<OmnipodHistoryRecord> preparedQuery = queryBuilder.prepare();
return daoPodHistory.queryForFirst(preparedQuery);
} catch (SQLException e) {
aapsLogger.error("Unhandled exception", e);
}
return null;
}
// Copied from xDrip+
String calculateDirection(BgReading bgReading) {

View file

@ -3,6 +3,7 @@ package info.nightscout.androidaps.db;
import com.j256.ormlite.dao.CloseableIterator;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.sql.SQLException;
import java.util.List;
@ -99,6 +100,10 @@ public class DatabaseHelperProvider implements DatabaseHelperInterface {
return MainApp.getDbHelper().getAllOmnipodHistoryRecordsFromTimeStamp(timestamp, ascending);
}
@Nullable @Override public OmnipodHistoryRecord findOmnipodHistoryRecordByPumpId(long pumpId) {
return MainApp.getDbHelper().findOmnipodHistoryRecordByPumpId(pumpId);
}
@NotNull @Override public List<TDD> getTDDsForLastXDays(int days) {
return MainApp.getDbHelper().getTDDsForLastXDays(days);
}

View file

@ -9,6 +9,7 @@ import info.nightscout.androidaps.core.di.CoreModule
import info.nightscout.androidaps.dana.di.DanaModule
import info.nightscout.androidaps.danar.di.DanaRModule
import info.nightscout.androidaps.danars.di.DanaRSModule
import info.nightscout.androidaps.plugins.pump.common.dagger.RileyLinkModule
import javax.inject.Singleton
@Singleton

View file

@ -25,7 +25,6 @@ import info.nightscout.androidaps.plugins.general.actions.defs.CustomAction
import info.nightscout.androidaps.plugins.general.overview.StatusLightHandler
import info.nightscout.androidaps.queue.Callback
import info.nightscout.androidaps.utils.FabricPrivacy
import info.nightscout.androidaps.utils.ui.SingleClickButton
import info.nightscout.androidaps.utils.alertDialogs.OKDialog
import info.nightscout.androidaps.utils.buildHelper.BuildHelper
import info.nightscout.androidaps.utils.extensions.plusAssign
@ -33,6 +32,7 @@ import info.nightscout.androidaps.utils.extensions.toVisibility
import info.nightscout.androidaps.utils.protection.ProtectionCheck
import info.nightscout.androidaps.utils.resources.ResourceHelper
import info.nightscout.androidaps.utils.sharedPreferences.SP
import info.nightscout.androidaps.utils.ui.SingleClickButton
import info.nightscout.androidaps.utils.ui.UIRunnable
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.disposables.CompositeDisposable
@ -236,6 +236,7 @@ class ActionsFragment : DaggerFragment() {
actions_historybrowser.visibility = (profile != null).toVisibility()
actions_fill?.visibility = (pump.pumpDescription.isRefillingCapable && pump.isInitialized && !pump.isSuspended).toVisibility()
actions_pumpbatterychange?.visibility = pump.pumpDescription.isBatteryReplaceable.toVisibility()
actions_temptarget?.visibility = (profile != null && config.APS).toVisibility()
actions_tddstats?.visibility = pump.pumpDescription.supportsTDDs.toVisibility()

View file

@ -11,7 +11,6 @@ import javax.inject.Inject;
import javax.inject.Singleton;
import dagger.android.HasAndroidInjector;
import info.nightscout.androidaps.BuildConfig;
import info.nightscout.androidaps.R;
import info.nightscout.androidaps.data.DetailedBolusInfo;
import info.nightscout.androidaps.data.Profile;
@ -69,6 +68,7 @@ public class MDIPlugin extends PumpPluginBase implements PumpInterface {
pumpDescription.isTempBasalCapable = false;
pumpDescription.isSetBasalProfileCapable = false;
pumpDescription.isRefillingCapable = false;
pumpDescription.isBatteryReplaceable = false;
}
@Override

View file

@ -2,6 +2,8 @@ package info.nightscout.androidaps.queue.commands
import dagger.android.HasAndroidInjector
import info.nightscout.androidaps.interfaces.ActivePluginProvider
import info.nightscout.androidaps.interfaces.ProfileFunction
import info.nightscout.androidaps.plugins.pump.common.defs.PumpType
import info.nightscout.androidaps.plugins.pump.insight.LocalInsightPlugin
import info.nightscout.androidaps.queue.Callback
import javax.inject.Inject
@ -12,12 +14,17 @@ class CommandStartPump(
) : Command(injector, CommandType.START_PUMP, callback) {
@Inject lateinit var activePlugin: ActivePluginProvider
@Inject lateinit var profileFunction: ProfileFunction
override fun execute() {
val pump = activePlugin.activePump
if (pump is LocalInsightPlugin) {
val result = pump.startPump()
callback?.result(result)?.run()
} else if (pump.pumpDescription.pumpType == PumpType.Insulet_Omnipod) {
// When using CommandQueue.setProfile, it refuses to set the profile is the same as the current profile
// However we need to set the current profile to resume delivery in case the Pod is suspended
pump.setNewBasalProfile(profileFunction.getProfile())
}
}

View file

@ -1,6 +1,7 @@
package info.nightscout.androidaps.utils
import info.nightscout.androidaps.Config
import info.nightscout.androidaps.Constants
import info.nightscout.androidaps.R
import info.nightscout.androidaps.db.BgReading
import info.nightscout.androidaps.interfaces.ActivePluginProvider
@ -36,11 +37,11 @@ class LocalAlertUtils @Inject constructor(
) {
fun missedReadingsThreshold(): Long {
return T.mins(sp.getInt(resourceHelper.gs(R.string.key_missed_bg_readings_threshold), 30).toLong()).msecs()
return T.mins(sp.getInt(resourceHelper.gs(R.string.key_missed_bg_readings_threshold_minutes), Constants.DEFAULT_MISSED_BG_READINGS_THRESHOLD_MINUTES).toLong()).msecs()
}
fun pumpUnreachableThreshold(): Long {
return T.mins(sp.getInt(resourceHelper.gs(R.string.key_pump_unreachable_threshold), 30).toLong()).msecs()
return T.mins(sp.getInt(resourceHelper.gs(R.string.key_pump_unreachable_threshold_minutes), Constants.DEFAULT_PUMP_UNREACHABLE_THRESHOLD_MINUTES).toLong()).msecs()
}
fun checkPumpUnreachableAlarm(lastConnection: Long, isStatusOutdated: Boolean, isDisconnected: Boolean) {

View file

@ -669,8 +669,6 @@
<string name="enable_pump_unreachable_alert">Alert if pump is unreachable</string>
<string name="pump_unreachable_threshold">Pump unreachable threshold [min]</string>
<string name="enable_carbs_req_alert">Alert if carbs are required</string>
<string name="key_pump_unreachable_threshold" translatable="false">pump_unreachable_threshold</string>
<string name="key_missed_bg_readings_threshold" translatable="false">missed_bg_readings_threshold</string>
<string name="urgent_alarm">Urgent Alarm</string>
<string name="info">INFO</string>
<string name="eversense">Eversense App (patched)</string>

View file

@ -16,7 +16,7 @@
android:defaultValue="30"
android:dependency="@string/key_enable_missed_bg_readings_alert"
android:inputType="number"
android:key="@string/key_missed_bg_readings_threshold"
android:key="@string/key_missed_bg_readings_threshold_minutes"
android:title="@string/nsalarm_staledatavalue_label"
validate:maxNumber="10000"
validate:minNumber="15"
@ -36,7 +36,7 @@
android:defaultValue="30"
android:dependency="@string/key_enable_pump_unreachable_alert"
android:inputType="number"
android:key="@string/key_pump_unreachable_threshold"
android:key="@string/key_pump_unreachable_threshold_minutes"
android:title="@string/pump_unreachable_threshold"
validate:maxNumber="300"
validate:minNumber="30"

View file

@ -89,6 +89,9 @@ public class Constants {
// Local profile
public static final String LOCAL_PROFILE = "LocalProfile";
// Local Alerts
public static final int DEFAULT_PUMP_UNREACHABLE_THRESHOLD_MINUTES = 30;
public static final int DEFAULT_MISSED_BG_READINGS_THRESHOLD_MINUTES = 30;
// One Time Password

View file

@ -24,6 +24,7 @@ interface DatabaseHelperInterface {
fun getTemporaryBasalsDataFromTime(mills: Long, ascending: Boolean): List<TemporaryBasal>
fun getCareportalEventFromTimestamp(timestamp: Long): CareportalEvent?
fun getAllOmnipodHistoryRecordsFromTimestamp(timestamp: Long, ascending: Boolean): List<OmnipodHistoryRecord>
fun findOmnipodHistoryRecordByPumpId(pumpId: Long): OmnipodHistoryRecord?
fun getTDDsForLastXDays(days: Int): List<TDD>
fun getProfileSwitchData(from: Long, ascending: Boolean): List<ProfileSwitch>
}

View file

@ -11,11 +11,11 @@ import info.nightscout.androidaps.plugins.pump.common.defs.PumpType;
public class PumpDescription {
public PumpType pumpType = PumpType.GenericAAPS;
public PumpDescription () {
public PumpDescription() {
resetSettings();
}
public PumpDescription (PumpType pumpType) {
public PumpDescription(PumpType pumpType) {
this();
setPumpDescription(pumpType);
}
@ -52,6 +52,7 @@ public class PumpDescription {
public double basalMaximumRate;
public boolean isRefillingCapable;
public boolean isBatteryReplaceable;
public boolean storesCarbInfo;
@ -88,7 +89,8 @@ public class PumpDescription {
basalMaximumRate = 25d;
is30minBasalRatesCapable = false;
isRefillingCapable = false;
isRefillingCapable = true;
isBatteryReplaceable = true;
storesCarbInfo = true;
supportsTDDs = false;
@ -136,6 +138,7 @@ public class PumpDescription {
basalMinimumRate = pumpType.getBaseBasalMinValue();
isRefillingCapable = pumpCapability.hasCapability(PumpCapability.Refill);
isBatteryReplaceable = pumpCapability.hasCapability(PumpCapability.ReplaceBattery);
storesCarbInfo = pumpCapability.hasCapability(PumpCapability.StoreCarbInfo);
supportsTDDs = pumpCapability.hasCapability(PumpCapability.TDD);

View file

@ -71,6 +71,9 @@ public class Notification {
public static final int TIME_OR_TIMEZONE_CHANGE = 58;
public static final int OMNIPOD_POD_NOT_ATTACHED = 59;
public static final int CARBS_REQUIRED = 60;
public static final int OMNIPOD_POD_SUSPENDED = 61;
public static final int OMNIPOD_POD_ALERTS_UPDATED = 62;
public static final int IMPORTANCE_HIGH = 2;
public static final String CATEGORY_ALARM = "alarm";

View file

@ -474,8 +474,4 @@ public abstract class PumpPluginAbstract extends PumpPluginBase implements PumpI
return new PumpEnactResult(getInjector()).success(false).enacted(false).comment(getResourceHelper().gs(resourceId));
}
protected FabricPrivacy getFabricPrivacy() {
return this.fabricPrivacy;
}
}

View file

@ -11,18 +11,19 @@ public enum PumpCapability {
TempBasal, // isTempBasalCapable
BasalProfileSet, // isSetBasalProfileCapable
Refill, // isRefillingCapable
ReplaceBattery, // isBatteryReplaceable
StoreCarbInfo, // storesCarbInfo
TDD, // supportsTDDs
ManualTDDLoad, // needsManualTDDLoad
BasalRate30min, // is30minBasalRatesCapable
// grouped by pump
VirtualPumpCapabilities(Bolus, ExtendedBolus, TempBasal, BasalProfileSet, Refill), //
ComboCapabilities(Bolus, TempBasal, BasalProfileSet, Refill, TDD, ManualTDDLoad), //
DanaCapabilities(Bolus, ExtendedBolus, TempBasal, BasalProfileSet, Refill, TDD, ManualTDDLoad), //
DanaWithHistoryCapabilities(Bolus, ExtendedBolus, TempBasal, BasalProfileSet, Refill, StoreCarbInfo, TDD, ManualTDDLoad), //
InsightCapabilities(Bolus, ExtendedBolus, TempBasal, BasalProfileSet, Refill,TDD,BasalRate30min), //
MedtronicCapabilities(Bolus, TempBasal, BasalProfileSet, Refill, TDD), //
VirtualPumpCapabilities(Bolus, ExtendedBolus, TempBasal, BasalProfileSet, Refill, ReplaceBattery), //
ComboCapabilities(Bolus, TempBasal, BasalProfileSet, Refill, ReplaceBattery, TDD, ManualTDDLoad), //
DanaCapabilities(Bolus, ExtendedBolus, TempBasal, BasalProfileSet, Refill, ReplaceBattery, TDD, ManualTDDLoad), //
DanaWithHistoryCapabilities(Bolus, ExtendedBolus, TempBasal, BasalProfileSet, Refill, ReplaceBattery, StoreCarbInfo, TDD, ManualTDDLoad), //
InsightCapabilities(Bolus, ExtendedBolus, TempBasal, BasalProfileSet, Refill, ReplaceBattery, TDD, BasalRate30min), //
MedtronicCapabilities(Bolus, TempBasal, BasalProfileSet, Refill, ReplaceBattery, TDD), //
OmnipodCapabilities(Bolus, TempBasal, BasalProfileSet, BasalRate30min), //
// BasalRates (separately grouped)
@ -35,19 +36,16 @@ public enum PumpCapability {
PumpCapability[] children;
PumpCapability()
{
PumpCapability() {
}
PumpCapability(PumpCapability...children)
{
PumpCapability(PumpCapability... children) {
this.children = children;
}
public boolean hasCapability(PumpCapability capability)
{
public boolean hasCapability(PumpCapability capability) {
// we can only check presense of simple capabilities
if (capability.children != null)
return false;
@ -55,19 +53,16 @@ public enum PumpCapability {
if (this == capability)
return true;
if (this.children!=null)
{
if (this.children != null) {
for (PumpCapability child : children) {
if (child == capability)
return true;
}
return false;
}
else
} else
return false;
}
}

View file

@ -1,7 +1,6 @@
package info.nightscout.androidaps.utils.textValidator
import android.content.Context
import android.content.res.TypedArray
import android.text.Editable
import android.text.TextUtils
import android.text.TextWatcher
@ -37,25 +36,20 @@ class DefaultEditTextValidator : EditTextValidator {
resetValidators(context)
}
constructor(editTextView: EditText, typedArray: TypedArray, context: Context) {
emptyAllowed = typedArray.getBoolean(R.styleable.FormEditText_emptyAllowed, false)
testType = typedArray.getInt(R.styleable.FormEditText_testType, EditTextValidator.TEST_NOCHECK)
testErrorString = typedArray.getString(R.styleable.FormEditText_testErrorString)
classType = typedArray.getString(R.styleable.FormEditText_classType)
customRegexp = typedArray.getString(R.styleable.FormEditText_customRegexp)
emptyErrorStringDef = typedArray.getString(R.styleable.FormEditText_emptyErrorString)
customFormat = typedArray.getString(R.styleable.FormEditText_customFormat)
if (testType == EditTextValidator.TEST_MIN_LENGTH)
minLength = typedArray.getInt(R.styleable.FormEditText_minLength, 0)
if (testType == EditTextValidator.TEST_NUMERIC_RANGE) {
minNumber = typedArray.getInt(R.styleable.FormEditText_minNumber, Int.MIN_VALUE)
maxNumber = typedArray.getInt(R.styleable.FormEditText_maxNumber, Int.MAX_VALUE)
}
if (testType == EditTextValidator.TEST_FLOAT_NUMERIC_RANGE) {
floatminNumber = typedArray.getFloat(R.styleable.FormEditText_floatminNumber, Float.MIN_VALUE)
floatmaxNumber = typedArray.getFloat(R.styleable.FormEditText_floatmaxNumber, Float.MAX_VALUE)
}
typedArray.recycle()
constructor(editTextView: EditText, parameters: Parameters, context: Context) {
emptyAllowed = parameters.emptyAllowed
testType = parameters.testType
testErrorString = parameters.testErrorString
classType = parameters.classType
customRegexp = parameters.customRegexp
emptyErrorStringDef = parameters.emptyErrorStringDef
customFormat = parameters.customFormat
minLength = parameters.minLength
minNumber = parameters.minNumber
maxNumber = parameters.maxNumber
floatminNumber = parameters.floatminNumber
floatmaxNumber = parameters.floatmaxNumber
setEditText(editTextView)
resetValidators(context)
}
@ -168,7 +162,7 @@ class DefaultEditTextValidator : EditTextValidator {
}
@Suppress("unused")
fun setClassType(classType: String?, testErrorString: String?, context: Context) : DefaultEditTextValidator{
fun setClassType(classType: String?, testErrorString: String?, context: Context): DefaultEditTextValidator {
testType = EditTextValidator.TEST_CUSTOM
this.classType = classType
this.testErrorString = testErrorString
@ -177,7 +171,7 @@ class DefaultEditTextValidator : EditTextValidator {
}
@Suppress("unused")
fun setCustomRegexp(customRegexp: String?, context: Context) : DefaultEditTextValidator {
fun setCustomRegexp(customRegexp: String?, context: Context): DefaultEditTextValidator {
testType = EditTextValidator.TEST_REGEXP
this.customRegexp = customRegexp
resetValidators(context)
@ -185,13 +179,13 @@ class DefaultEditTextValidator : EditTextValidator {
}
@Suppress("unused")
fun setEmptyAllowed(emptyAllowed: Boolean, context: Context) : DefaultEditTextValidator {
fun setEmptyAllowed(emptyAllowed: Boolean, context: Context): DefaultEditTextValidator {
this.emptyAllowed = emptyAllowed
resetValidators(context)
return this
}
fun setEmptyErrorString(emptyErrorString: String?) : DefaultEditTextValidator {
fun setEmptyErrorString(emptyErrorString: String?): DefaultEditTextValidator {
emptyErrorStringActual = if (!TextUtils.isEmpty(emptyErrorString)) {
emptyErrorString
} else {
@ -201,14 +195,14 @@ class DefaultEditTextValidator : EditTextValidator {
}
@Suppress("unused")
fun setTestErrorString(testErrorString: String?, context: Context) : DefaultEditTextValidator {
fun setTestErrorString(testErrorString: String?, context: Context): DefaultEditTextValidator {
this.testErrorString = testErrorString
resetValidators(context)
return this
}
@Suppress("unused")
fun setTestType(testType: Int, context: Context) : DefaultEditTextValidator {
fun setTestType(testType: Int, context: Context): DefaultEditTextValidator {
this.testType = testType
resetValidators(context)
return this
@ -248,4 +242,19 @@ class DefaultEditTextValidator : EditTextValidator {
} catch (e: Throwable) {
!TextUtils.isEmpty(editTextView.error)
}
data class Parameters(
val testErrorString: String? = null,
val emptyAllowed: Boolean = false,
val testType: Int = EditTextValidator.TEST_NOCHECK,
val classType: String? = null,
val customRegexp: String? = null,
val customFormat: String? = null,
val emptyErrorStringDef: String? = null,
var minLength: Int = 0,
var minNumber: Int = 0,
var maxNumber: Int = 0,
var floatminNumber: Float = 0f,
var floatmaxNumber: Float = 0f
)
}

View file

@ -1,22 +1,24 @@
package info.nightscout.androidaps.utils.textValidator
import android.annotation.SuppressLint
import android.content.Context
import android.util.AttributeSet
import androidx.preference.EditTextPreference
import androidx.preference.EditTextPreference.OnBindEditTextListener
import androidx.preference.PreferenceViewHolder
import info.nightscout.androidaps.core.R
class ValidatingEditTextPreference(ctx: Context, attrs: AttributeSet, defStyleAttr: Int, defStyleRes: Int)
: EditTextPreference(ctx, attrs, defStyleAttr, defStyleRes) {
private val validatorParameters: DefaultEditTextValidator.Parameters = obtainValidatorParameters(attrs)
private var validator: DefaultEditTextValidator? = null
init {
val typedArray = context.obtainStyledAttributes(attrs, R.styleable.FormEditText, 0, 0)
val onBindEditTextListener = OnBindEditTextListener { editText ->
editTextValidator = DefaultEditTextValidator(editText, typedArray, context)
setOnBindEditTextListener { editText ->
validator = DefaultEditTextValidator(editText, validatorParameters, context)
}
setOnPreferenceChangeListener { preference, newValue ->
validator?.testValidity(false) ?: true
}
setOnBindEditTextListener(onBindEditTextListener)
}
constructor(ctx: Context, attrs: AttributeSet, defStyle: Int)
@ -25,11 +27,33 @@ class ValidatingEditTextPreference(ctx: Context, attrs: AttributeSet, defStyleAt
constructor(ctx: Context, attrs: AttributeSet)
: this(ctx, attrs, R.attr.editTextPreferenceStyle)
private lateinit var editTextValidator: EditTextValidator
override fun onBindViewHolder(holder: PreferenceViewHolder?) {
super.onBindViewHolder(holder)
holder?.isDividerAllowedAbove = false
holder?.isDividerAllowedBelow = false
}
private fun obtainValidatorParameters(attrs: AttributeSet): DefaultEditTextValidator.Parameters {
val typedArray = context.obtainStyledAttributes(attrs, R.styleable.FormEditText, 0, 0)
return DefaultEditTextValidator.Parameters(
emptyAllowed = typedArray.getBoolean(R.styleable.FormEditText_emptyAllowed, false),
testType = typedArray.getInt(R.styleable.FormEditText_testType, EditTextValidator.TEST_NOCHECK),
testErrorString = typedArray.getString(R.styleable.FormEditText_testErrorString),
classType = typedArray.getString(R.styleable.FormEditText_classType),
customRegexp = typedArray.getString(R.styleable.FormEditText_customRegexp),
emptyErrorStringDef = typedArray.getString(R.styleable.FormEditText_emptyErrorString),
customFormat = typedArray.getString(R.styleable.FormEditText_customFormat)).also { params ->
if (params.testType == EditTextValidator.TEST_MIN_LENGTH)
params.minLength = typedArray.getInt(R.styleable.FormEditText_minLength, 0)
if (params.testType == EditTextValidator.TEST_NUMERIC_RANGE) {
params.minNumber = typedArray.getInt(R.styleable.FormEditText_minNumber, Int.MIN_VALUE)
params.maxNumber = typedArray.getInt(R.styleable.FormEditText_maxNumber, Int.MAX_VALUE)
}
if (params.testType == EditTextValidator.TEST_FLOAT_NUMERIC_RANGE) {
params.floatminNumber = typedArray.getFloat(R.styleable.FormEditText_floatminNumber, Float.MIN_VALUE)
params.floatmaxNumber = typedArray.getFloat(R.styleable.FormEditText_floatmaxNumber, Float.MAX_VALUE)
}
typedArray.recycle()
}
}
}

View file

@ -1,5 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!-- Keys-->
<string name="key_enable_fabric" translatable="false">enable_fabric</string>
<string name="key_language" translatable="false">language</string>
<string name="key_units" translatable="false">units</string>
@ -22,8 +23,9 @@
<string name="key_ns_uploadlocalprofile" translatable="false">ns_uploadlocalprofile</string>
<string name="key_btwatchdog" translatable="false">bt_watchdog</string>
<string name="key_btwatchdog_lastbark" translatable="false">bt_watchdog_last</string>
<string name="key_pump_unreachable_threshold_minutes" translatable="false">pump_unreachable_threshold</string>
<string name="key_missed_bg_readings_threshold_minutes" translatable="false">missed_bg_readings_threshold</string>
<string name="key_gradually_increase_notification_volume" translatable="false">gradually_increase_notification_volume</string>
<string name="pairing">Pairing</string>
<!-- General-->
<string name="error">Error</string>
@ -89,6 +91,7 @@
<string name="bluetooth">Bluetooth</string>
<string name="btwatchdog_title">BT Watchdog</string>
<string name="btwatchdog_summary">Switches off the phone\'s bluetooth for one second if no connection to the pump is possible. This may help on some phones where the bluetooth stack freezes.</string>
<string name="pairing">Pairing</string>
<!-- Constraints-->
<string name="limitingbasalratio">Limiting max basal rate to %1$.2f U/h because of %2$s</string>

View file

@ -19,5 +19,7 @@ files:
translation: /dana/src/main/res/values-%android_code%/strings.xml
- source: /medtronic/src/main/res/values/strings.xml
translation: /medtronic/src/main/res/values-%android_code%/strings.xml
- source: /omnipod/src/main/res/values/strings.xml
translation: /omnipod/src/main/res/values-%android_code%/strings.xml
- source: /rileylink/src/main/res/values/strings.xml
translation: /rileylink/src/main/res/values-%android_code%/strings.xml

View file

@ -3,12 +3,12 @@
<application>
<service
android:name=".service.RileyLinkOmnipodService"
android:name=".rileylink.service.RileyLinkOmnipodService"
android:enabled="true"
android:exported="true" />
<activity android:name=".dialogs.PodManagementActivity" />
<activity android:name=".dialogs.PodHistoryActivity" />
<activity android:name=".ui.PodManagementActivity" />
<activity android:name=".ui.PodHistoryActivity" />
<activity
android:name="com.atech.android.library.wizardpager.WizardPagerActivity"
android:theme="@style/AppTheme.NoActionBar" />

View file

@ -1,391 +0,0 @@
package info.nightscout.androidaps.plugins.pump.omnipod
import android.content.Intent
import android.graphics.Color
import android.os.Bundle
import android.os.Handler
import android.text.TextUtils
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import dagger.android.support.DaggerFragment
import info.nightscout.androidaps.events.EventPreferenceChange
import info.nightscout.androidaps.interfaces.ActivePluginProvider
import info.nightscout.androidaps.interfaces.CommandQueueProvider
import info.nightscout.androidaps.logging.AAPSLogger
import info.nightscout.androidaps.logging.LTag
import info.nightscout.androidaps.plugins.bus.RxBusWrapper
import info.nightscout.androidaps.plugins.pump.common.events.EventRileyLinkDeviceStatusChange
import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.defs.RileyLinkServiceState
import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.defs.RileyLinkTargetDevice
import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.dialog.RileyLinkStatusActivity
import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.service.RileyLinkServiceData
import info.nightscout.androidaps.plugins.pump.omnipod.defs.OmnipodStatusRequest
import info.nightscout.androidaps.plugins.pump.omnipod.defs.PodProgressStatus
import info.nightscout.androidaps.plugins.pump.omnipod.defs.state.PodStateManager
import info.nightscout.androidaps.plugins.pump.omnipod.dialogs.PodManagementActivity
import info.nightscout.androidaps.plugins.pump.omnipod.driver.OmnipodPumpStatus
import info.nightscout.androidaps.plugins.pump.omnipod.events.EventOmnipodAcknowledgeAlertsChanged
import info.nightscout.androidaps.plugins.pump.omnipod.events.EventOmnipodPumpValuesChanged
import info.nightscout.androidaps.plugins.pump.omnipod.events.EventOmnipodRefreshButtonState
import info.nightscout.androidaps.plugins.pump.omnipod.util.OmnipodConst
import info.nightscout.androidaps.plugins.pump.omnipod.util.OmnipodUtil
import info.nightscout.androidaps.queue.Callback
import info.nightscout.androidaps.utils.DateUtil
import info.nightscout.androidaps.utils.FabricPrivacy
import info.nightscout.androidaps.utils.T
import info.nightscout.androidaps.utils.WarnColors
import info.nightscout.androidaps.utils.alertDialogs.OKDialog
import info.nightscout.androidaps.utils.extensions.plusAssign
import info.nightscout.androidaps.utils.protection.ProtectionCheck
import info.nightscout.androidaps.utils.resources.ResourceHelper
import info.nightscout.androidaps.utils.sharedPreferences.SP
import info.nightscout.androidaps.utils.ui.UIRunnable
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.disposables.CompositeDisposable
import io.reactivex.schedulers.Schedulers
import kotlinx.android.synthetic.main.omnipod_fragment.*
import org.apache.commons.lang3.StringUtils
import org.joda.time.DateTime
import org.joda.time.Duration
import javax.inject.Inject
class OmnipodFragment : DaggerFragment() {
@Inject lateinit var aapsLogger: AAPSLogger
@Inject lateinit var fabricPrivacy: FabricPrivacy
@Inject lateinit var resourceHelper: ResourceHelper
@Inject lateinit var rxBus: RxBusWrapper
@Inject lateinit var commandQueue: CommandQueueProvider
@Inject lateinit var activePlugin: ActivePluginProvider
@Inject lateinit var omnipodPumpPlugin: OmnipodPumpPlugin
@Inject lateinit var warnColors: WarnColors
@Inject lateinit var omnipodPumpStatus: OmnipodPumpStatus
@Inject lateinit var podStateManager: PodStateManager
@Inject lateinit var sp: SP
@Inject lateinit var omnipodUtil: OmnipodUtil
@Inject lateinit var rileyLinkServiceData: RileyLinkServiceData
@Inject lateinit var dateUtil: DateUtil
// TODO somehow obtain the pumpUnreachableThreshold in order to display last connection time red or white
// @Inject lateinit var localAlertUtils: LocalAlertUtils
@Inject lateinit var protectionCheck: ProtectionCheck
private var disposables: CompositeDisposable = CompositeDisposable()
private val loopHandler = Handler()
private lateinit var refreshLoop: Runnable
init {
refreshLoop = Runnable {
activity?.runOnUiThread { updateUi() }
loopHandler.postDelayed(refreshLoop, T.mins(1).msecs())
}
}
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
return inflater.inflate(R.layout.omnipod_fragment, container, false)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
omnipod_pod_mgmt.setOnClickListener {
if (omnipodPumpPlugin.rileyLinkService?.verifyConfiguration() == true) {
activity?.let { activity ->
protectionCheck.queryProtection(
activity, ProtectionCheck.Protection.PREFERENCES,
UIRunnable(Runnable { startActivity(Intent(context, PodManagementActivity::class.java)) })
)
}
} else {
displayNotConfiguredDialog()
}
}
omnipod_refresh.setOnClickListener {
if (omnipodPumpPlugin.rileyLinkService?.verifyConfiguration() != true) {
displayNotConfiguredDialog()
} else {
omnipod_refresh.isEnabled = false
omnipodPumpPlugin.addPodStatusRequest(OmnipodStatusRequest.GetPodState);
commandQueue.readStatus("Clicked Refresh", object : Callback() {
override fun run() {
activity?.runOnUiThread { omnipod_refresh.isEnabled = true }
}
})
}
}
omnipod_stats.setOnClickListener {
if (omnipodPumpPlugin.rileyLinkService?.verifyConfiguration() == true) {
startActivity(Intent(context, RileyLinkStatusActivity::class.java))
} else {
displayNotConfiguredDialog()
}
}
omnipod_pod_active_alerts_ack.setOnClickListener {
if (omnipodPumpPlugin.rileyLinkService?.verifyConfiguration() != true) {
displayNotConfiguredDialog()
} else {
omnipod_pod_active_alerts_ack.isEnabled = false
omnipodPumpPlugin.addPodStatusRequest(OmnipodStatusRequest.AcknowledgeAlerts);
commandQueue.readStatus("Clicked Alert Ack", null)
}
}
omnipod_pod_debug.setOnClickListener {
if (omnipodPumpPlugin.rileyLinkService?.verifyConfiguration() != true) {
displayNotConfiguredDialog()
} else {
omnipod_pod_debug.isEnabled = false
omnipodPumpPlugin.addPodStatusRequest(OmnipodStatusRequest.GetPodPulseLog);
commandQueue.readStatus("Clicked Refresh", object : Callback() {
override fun run() {
activity?.runOnUiThread { omnipod_pod_debug.isEnabled = true }
}
})
}
}
omnipod_lastconnection.setTextColor(Color.WHITE)
}
override fun onResume() {
super.onResume()
loopHandler.postDelayed(refreshLoop, T.mins(1).msecs())
disposables += rxBus
.toObservable(EventOmnipodRefreshButtonState::class.java)
.observeOn(AndroidSchedulers.mainThread())
.subscribe({ omnipod_refresh.isEnabled = it.newState }, { fabricPrivacy.logException(it) })
disposables += rxBus
.toObservable(EventRileyLinkDeviceStatusChange::class.java)
.observeOn(AndroidSchedulers.mainThread())
.subscribe({ updateRileyLinkUiElements() }, { fabricPrivacy.logException(it) })
disposables += rxBus
.toObservable(EventOmnipodPumpValuesChanged::class.java)
.observeOn(AndroidSchedulers.mainThread())
.subscribe({ updateOmipodUiElements() }, { fabricPrivacy.logException(it) })
disposables += rxBus
.toObservable(EventOmnipodAcknowledgeAlertsChanged::class.java)
.observeOn(AndroidSchedulers.mainThread())
.subscribe({ updateAcknowledgeAlertsUiElements() }, { fabricPrivacy.logException(it) })
disposables += rxBus
.toObservable(EventPreferenceChange::class.java)
.observeOn(Schedulers.io())
.subscribe({
setVisibilityOfPodDebugButton()
}, { fabricPrivacy.logException(it) })
updateUi()
}
fun setVisibilityOfPodDebugButton() {
val isEnabled = sp.getBoolean(OmnipodConst.Prefs.PodDebuggingOptionsEnabled, false)
if (isEnabled)
omnipod_pod_debug.visibility = View.VISIBLE
else
omnipod_pod_debug.visibility = View.GONE
}
private fun displayNotConfiguredDialog() {
context?.let {
OKDialog.show(it, resourceHelper.gs(R.string.omnipod_warning),
resourceHelper.gs(R.string.omnipod_error_operation_not_possible_no_configuration), null)
}
}
override fun onPause() {
super.onPause()
disposables.clear()
loopHandler.removeCallbacks(refreshLoop)
}
fun updateUi() {
updateRileyLinkUiElements()
updateOmipodUiElements()
}
@Synchronized
private fun updateRileyLinkUiElements() {
aapsLogger.info(LTag.PUMP, "OmnipodFragment.setDeviceStatus")
val rileyLinkServiceState = rileyLinkServiceData.rileyLinkServiceState
val resourceId = rileyLinkServiceState.getResourceId()
val rileyLinkError = rileyLinkServiceData.rileyLinkError
omnipod_rl_status.text =
when {
rileyLinkServiceState == RileyLinkServiceState.NotStarted -> resourceHelper.gs(resourceId)
rileyLinkServiceState.isConnecting -> "{fa-bluetooth-b spin} " + resourceHelper.gs(resourceId)
rileyLinkServiceState.isError && rileyLinkError == null -> "{fa-bluetooth-b} " + resourceHelper.gs(resourceId)
rileyLinkServiceState.isError && rileyLinkError != null -> "{fa-bluetooth-b} " + resourceHelper.gs(rileyLinkError.getResourceId(RileyLinkTargetDevice.Omnipod))
else -> "{fa-bluetooth-b} " + resourceHelper.gs(resourceId)
}
omnipod_rl_status.setTextColor(if (rileyLinkServiceState.isError || rileyLinkError != null) Color.RED else Color.WHITE)
}
fun updateOmipodUiElements() {
updateLastConnectionUiElements()
updateAcknowledgeAlertsUiElements()
setVisibilityOfPodDebugButton()
val errors = ArrayList<String>();
val rileyLinkErrorInfo = omnipodPumpStatus.errorInfo
if (rileyLinkErrorInfo != null) {
errors.add(rileyLinkErrorInfo)
}
if (!podStateManager.hasPodState() || !podStateManager.isPodInitialized) {
if (podStateManager.hasPodState()) {
omnipod_pod_address.text = podStateManager.address.toString()
} else {
omnipod_pod_address.text = "-"
}
omnipod_pod_lot.text = "-"
omnipod_pod_tid.text = "-"
omnipod_pod_firmware_version.text = "-"
omnipod_pod_expiry.text = "-"
omnipod_basabasalrate.text = "-"
omnipod_reservoir.text = "-"
omnipod_tempbasal.text = "-"
omnipod_lastbolus.text = "-"
omnipod_lastconnection.setTextColor(Color.WHITE)
if (podStateManager.hasPodState()) {
omnipod_pod_status.text = resourceHelper.gs(R.string.omnipod_pod_status_not_initalized)
} else {
omnipod_pod_status.text = resourceHelper.gs(R.string.omnipod_pod_status_no_pod_connected)
}
} else {
omnipod_pod_address.text = podStateManager.address.toString()
omnipod_pod_lot.text = podStateManager.lot.toString()
omnipod_pod_tid.text = podStateManager.tid.toString()
omnipod_pod_firmware_version.text = resourceHelper.gs(R.string.omnipod_pod_firmware_version_value, podStateManager.pmVersion.toString(), podStateManager.piVersion.toString())
val expiresAt = podStateManager.expiresAt
omnipod_pod_expiry.text = if (expiresAt == null) "???" else dateUtil.dateAndTimeString(expiresAt.toDate())
val stateText: String
when {
podStateManager.hasFaultEvent() -> {
val faultEventCode = podStateManager.faultEvent.faultEventCode
stateText = resourceHelper.gs(R.string.omnipod_pod_status_pod_fault)
errors.add(resourceHelper.gs(R.string.omnipod_pod_status_pod_fault_description, faultEventCode.value, faultEventCode.name))
}
podStateManager.isPodRunning -> {
stateText = resourceHelper.gs(R.string.omnipod_pod_status_pod_running, if (podStateManager.lastDeliveryStatus == null) null else podStateManager.lastDeliveryStatus.name)
}
else -> {
stateText = resourceHelper.gs(R.string.omnipod_pod_setup_in_progress, podStateManager.podProgressStatus.name)
}
}
omnipod_pod_status.text = stateText
updateLastConnectionUiElements()
// last bolus
if (podStateManager.lastBolusStartTime != null && podStateManager.lastBolusAmount != null) {
val ago = readableDuration(podStateManager.lastBolusStartTime)
omnipod_lastbolus.text = resourceHelper.gs(R.string.omnipod_last_bolus, omnipodPumpPlugin.pumpType.determineCorrectBolusSize(podStateManager.lastBolusAmount), resourceHelper.gs(R.string.insulin_unit_shortname), ago)
} else {
omnipod_lastbolus.text = "-"
}
// base basal rate
omnipod_basabasalrate.text = resourceHelper.gs(R.string.pump_basebasalrate, omnipodPumpPlugin.pumpType.determineCorrectBasalSize(omnipodPumpPlugin.baseBasalRate))
omnipod_tempbasal.text = activePlugin.activeTreatments
.getTempBasalFromHistory(System.currentTimeMillis())?.toStringFull() ?: "-"
// reservoir
if (podStateManager.reservoirLevel == null) {
omnipod_reservoir.text = resourceHelper.gs(R.string.omnipod_reservoir_over50)
omnipod_reservoir.setTextColor(Color.WHITE)
} else {
omnipod_reservoir.text = resourceHelper.gs(R.string.omnipod_reservoir_left, podStateManager.reservoirLevel)
warnColors.setColorInverse(omnipod_reservoir, podStateManager.reservoirLevel, 50.0, 20.0)
}
}
omnipod_pod_status.setTextColor(if (podStateManager.hasFaultEvent()) Color.RED else Color.WHITE)
omnipod_errors.text = if (errors.size == 0) "-" else StringUtils.join(errors, System.lineSeparator())
val status = commandQueue.spannedStatus()
if (status.toString() == "") {
omnipod_queue.visibility = View.GONE
} else {
omnipod_queue.visibility = View.VISIBLE
omnipod_queue.text = status
}
omnipod_refresh.isEnabled = podStateManager.isPodInitialized && podStateManager.podProgressStatus.isAtLeast(PodProgressStatus.PAIRING_COMPLETED)
}
private fun updateLastConnectionUiElements() {
if (podStateManager.isPodInitialized && podStateManager.lastSuccessfulCommunication != null) { // Null check for backwards compatibility
omnipod_lastconnection.text = readableDuration(podStateManager.lastSuccessfulCommunication)
omnipod_lastconnection.setTextColor(Color.WHITE)
/*
// TODO
if (omnipodPumpPlugin.isUnreachableAlertTimeoutExceeded(localAlertUtils.pumpUnreachableThreshold())) {
omnipod_lastconnection.setTextColor(Color.RED)
} else {
omnipod_lastconnection.setTextColor(Color.WHITE)
}
*/
} else {
omnipod_lastconnection.setTextColor(Color.WHITE)
if (podStateManager.hasPodState() && podStateManager.lastSuccessfulCommunication != null) {
omnipod_lastconnection.text = readableDuration(podStateManager.lastSuccessfulCommunication)
} else {
omnipod_lastconnection.text = "-"
}
}
}
private fun updateAcknowledgeAlertsUiElements() {
if (podStateManager.isPodInitialized && podStateManager.hasActiveAlerts()) {
omnipod_pod_active_alerts_ack.isEnabled = true
omnipod_pod_active_alerts.text = TextUtils.join(System.lineSeparator(), omnipodUtil.getTranslatedActiveAlerts(podStateManager))
} else {
omnipod_pod_active_alerts_ack.isEnabled = false
omnipod_pod_active_alerts.text = "-"
}
}
private fun readableDuration(dateTime: DateTime): String {
val minutes = Duration(dateTime, DateTime.now()).standardMinutes.toInt()
when {
minutes == 0 -> {
return resourceHelper.gs(R.string.omnipod_moments_ago)
}
minutes < 60 -> {
return resourceHelper.gs(R.string.omnipod_time_ago, resourceHelper.gq(R.plurals.omnipod_minutes, minutes, minutes))
}
minutes < 1440 -> {
val hours = minutes / 60
val minutesLeft = minutes % 60
if (minutesLeft > 0)
return resourceHelper.gs(R.string.omnipod_time_ago,
resourceHelper.gs(R.string.omnipod_composite_time, resourceHelper.gq(R.plurals.omnipod_hours, hours, hours), resourceHelper.gq(R.plurals.omnipod_minutes, minutesLeft, minutesLeft)))
return resourceHelper.gs(R.string.omnipod_time_ago, resourceHelper.gq(R.plurals.omnipod_hours, hours, hours))
}
else -> {
val hours = minutes / 60
val days = hours / 24
val hoursLeft = hours % 24
if (hoursLeft > 0)
return resourceHelper.gs(R.string.omnipod_time_ago,
resourceHelper.gs(R.string.omnipod_composite_time, resourceHelper.gq(R.plurals.omnipod_days, days, days), resourceHelper.gq(R.plurals.omnipod_hours, hoursLeft, hoursLeft)))
return resourceHelper.gs(R.string.omnipod_time_ago, resourceHelper.gq(R.plurals.omnipod_days, days, days))
}
}
}
}

View file

@ -1,36 +0,0 @@
package info.nightscout.androidaps.plugins.pump.omnipod.comm.action;
import java.util.List;
import info.nightscout.androidaps.plugins.pump.omnipod.comm.OmnipodCommunicationManager;
import info.nightscout.androidaps.plugins.pump.omnipod.comm.exception.ActionInitializationException;
import info.nightscout.androidaps.plugins.pump.omnipod.comm.message.command.ConfigureAlertsCommand;
import info.nightscout.androidaps.plugins.pump.omnipod.comm.message.response.StatusResponse;
import info.nightscout.androidaps.plugins.pump.omnipod.defs.AlertConfiguration;
import info.nightscout.androidaps.plugins.pump.omnipod.defs.state.PodStateManager;
public class ConfigureAlertsAction implements OmnipodAction<StatusResponse> {
private final PodStateManager podStateManager;
private final List<AlertConfiguration> alertConfigurations;
public ConfigureAlertsAction(PodStateManager podStateManager, List<AlertConfiguration> alertConfigurations) {
if (podStateManager == null) {
throw new ActionInitializationException("Pod state manager cannot be null");
}
if (alertConfigurations == null) {
throw new ActionInitializationException("Alert configurations cannot be null");
}
this.podStateManager = podStateManager;
this.alertConfigurations = alertConfigurations;
}
@Override
public StatusResponse execute(OmnipodCommunicationManager communicationService) {
ConfigureAlertsCommand configureAlertsCommand = new ConfigureAlertsCommand(podStateManager.getCurrentNonce(), alertConfigurations);
StatusResponse statusResponse = communicationService.sendCommand(StatusResponse.class, podStateManager, configureAlertsCommand);
for (AlertConfiguration alertConfiguration : alertConfigurations) {
podStateManager.putConfiguredAlert(alertConfiguration.getAlertSlot(), alertConfiguration.getAlertType());
}
return statusResponse;
}
}

View file

@ -1,29 +0,0 @@
package info.nightscout.androidaps.plugins.pump.omnipod.comm.action;
import info.nightscout.androidaps.plugins.pump.omnipod.comm.OmnipodCommunicationManager;
import info.nightscout.androidaps.plugins.pump.omnipod.comm.exception.ActionInitializationException;
import info.nightscout.androidaps.plugins.pump.omnipod.comm.message.command.GetStatusCommand;
import info.nightscout.androidaps.plugins.pump.omnipod.comm.message.response.podinfo.PodInfoResponse;
import info.nightscout.androidaps.plugins.pump.omnipod.defs.PodInfoType;
import info.nightscout.androidaps.plugins.pump.omnipod.defs.state.PodStateManager;
public class GetPodInfoAction implements OmnipodAction<PodInfoResponse> {
private final PodStateManager podStateManager;
private final PodInfoType podInfoType;
public GetPodInfoAction(PodStateManager podStateManager, PodInfoType podInfoType) {
if (podStateManager == null) {
throw new ActionInitializationException("Pod state manager cannot be null");
}
if (podInfoType == null) {
throw new ActionInitializationException("Pod info type cannot be null");
}
this.podStateManager = podStateManager;
this.podInfoType = podInfoType;
}
@Override
public PodInfoResponse execute(OmnipodCommunicationManager communicationService) {
return communicationService.sendCommand(PodInfoResponse.class, podStateManager, new GetStatusCommand(podInfoType));
}
}

View file

@ -1,24 +0,0 @@
package info.nightscout.androidaps.plugins.pump.omnipod.comm.action;
import info.nightscout.androidaps.plugins.pump.omnipod.comm.OmnipodCommunicationManager;
import info.nightscout.androidaps.plugins.pump.omnipod.comm.exception.ActionInitializationException;
import info.nightscout.androidaps.plugins.pump.omnipod.comm.message.command.GetStatusCommand;
import info.nightscout.androidaps.plugins.pump.omnipod.comm.message.response.StatusResponse;
import info.nightscout.androidaps.plugins.pump.omnipod.defs.PodInfoType;
import info.nightscout.androidaps.plugins.pump.omnipod.defs.state.PodStateManager;
public class GetStatusAction implements OmnipodAction<StatusResponse> {
private final PodStateManager podStateManager;
public GetStatusAction(PodStateManager podState) {
if (podState == null) {
throw new ActionInitializationException("Pod state manager cannot be null");
}
this.podStateManager = podState;
}
@Override
public StatusResponse execute(OmnipodCommunicationManager communicationService) {
return communicationService.sendCommand(StatusResponse.class, podStateManager, new GetStatusCommand(PodInfoType.NORMAL));
}
}

View file

@ -1,55 +0,0 @@
package info.nightscout.androidaps.plugins.pump.omnipod.comm.action;
import info.nightscout.androidaps.plugins.pump.omnipod.comm.OmnipodCommunicationManager;
import info.nightscout.androidaps.plugins.pump.omnipod.comm.action.service.InsertCannulaService;
import info.nightscout.androidaps.plugins.pump.omnipod.comm.exception.ActionInitializationException;
import info.nightscout.androidaps.plugins.pump.omnipod.comm.exception.IllegalPodProgressException;
import info.nightscout.androidaps.plugins.pump.omnipod.comm.message.response.StatusResponse;
import info.nightscout.androidaps.plugins.pump.omnipod.defs.PodProgressStatus;
import info.nightscout.androidaps.plugins.pump.omnipod.defs.schedule.BasalSchedule;
import info.nightscout.androidaps.plugins.pump.omnipod.defs.state.PodStateManager;
public class InsertCannulaAction implements OmnipodAction<StatusResponse> {
private final PodStateManager podStateManager;
private final InsertCannulaService service;
private final BasalSchedule initialBasalSchedule;
public InsertCannulaAction(InsertCannulaService insertCannulaService, PodStateManager podStateManager, BasalSchedule initialBasalSchedule) {
if (insertCannulaService == null) {
throw new ActionInitializationException("Insert cannula service cannot be null");
}
if (podStateManager == null) {
throw new ActionInitializationException("Pod state manager cannot be null");
}
if (initialBasalSchedule == null) {
throw new ActionInitializationException("Initial basal schedule cannot be null");
}
this.service = insertCannulaService;
this.podStateManager = podStateManager;
this.initialBasalSchedule = initialBasalSchedule;
}
@Override
public StatusResponse execute(OmnipodCommunicationManager communicationService) {
if (!podStateManager.isPodInitialized() || podStateManager.getPodProgressStatus().isBefore(PodProgressStatus.PRIMING_COMPLETED)) {
throw new IllegalPodProgressException(PodProgressStatus.PRIMING_COMPLETED, podStateManager.isPodInitialized() ? podStateManager.getPodProgressStatus() : null);
}
if (podStateManager.getPodProgressStatus().isBefore(PodProgressStatus.BASAL_INITIALIZED)) {
service.programInitialBasalSchedule(communicationService, podStateManager, initialBasalSchedule);
}
if (podStateManager.getPodProgressStatus().isBefore(PodProgressStatus.INSERTING_CANNULA)) {
}
if (podStateManager.getPodProgressStatus().isBefore(PodProgressStatus.INSERTING_CANNULA)) {
service.executeExpirationRemindersAlertCommand(communicationService, podStateManager);
return service.executeInsertionBolusCommand(communicationService, podStateManager);
} else if (podStateManager.getPodProgressStatus().equals(PodProgressStatus.INSERTING_CANNULA)) {
// Check status
return communicationService.executeAction(new GetStatusAction(podStateManager));
} else {
throw new IllegalPodProgressException(null, podStateManager.getPodProgressStatus());
}
}
}

View file

@ -1,7 +0,0 @@
package info.nightscout.androidaps.plugins.pump.omnipod.comm.action;
import info.nightscout.androidaps.plugins.pump.omnipod.comm.OmnipodCommunicationManager;
public interface OmnipodAction<T> {
T execute(OmnipodCommunicationManager communicationService);
}

View file

@ -1,59 +0,0 @@
package info.nightscout.androidaps.plugins.pump.omnipod.comm.action.service;
import org.joda.time.DateTime;
import org.joda.time.Duration;
import java.util.Arrays;
import java.util.List;
import info.nightscout.androidaps.plugins.pump.omnipod.comm.OmnipodCommunicationManager;
import info.nightscout.androidaps.plugins.pump.omnipod.comm.action.BolusAction;
import info.nightscout.androidaps.plugins.pump.omnipod.comm.action.ConfigureAlertsAction;
import info.nightscout.androidaps.plugins.pump.omnipod.comm.action.SetBasalScheduleAction;
import info.nightscout.androidaps.plugins.pump.omnipod.comm.message.response.StatusResponse;
import info.nightscout.androidaps.plugins.pump.omnipod.defs.AlertConfiguration;
import info.nightscout.androidaps.plugins.pump.omnipod.defs.AlertConfigurationFactory;
import info.nightscout.androidaps.plugins.pump.omnipod.defs.schedule.BasalSchedule;
import info.nightscout.androidaps.plugins.pump.omnipod.defs.state.PodStateManager;
import info.nightscout.androidaps.plugins.pump.omnipod.util.OmnipodConst;
public class InsertCannulaService {
public StatusResponse programInitialBasalSchedule(OmnipodCommunicationManager communicationService,
PodStateManager podStateManager, BasalSchedule basalSchedule) {
return communicationService.executeAction(new SetBasalScheduleAction(podStateManager, basalSchedule,
true, podStateManager.getScheduleOffset(), false));
}
public StatusResponse executeExpirationRemindersAlertCommand(OmnipodCommunicationManager communicationService,
PodStateManager podStateManager) {
AlertConfiguration lowReservoirAlertConfiguration = AlertConfigurationFactory.createLowReservoirAlertConfiguration(OmnipodConst.LOW_RESERVOIR_ALERT);
DateTime endOfServiceTime = podStateManager.getActivatedAt().plus(OmnipodConst.SERVICE_DURATION);
Duration timeUntilExpirationAdvisoryAlarm = new Duration(DateTime.now(),
endOfServiceTime.minus(OmnipodConst.EXPIRATION_ADVISORY_WINDOW));
Duration timeUntilShutdownImminentAlarm = new Duration(DateTime.now(),
endOfServiceTime.minus(OmnipodConst.END_OF_SERVICE_IMMINENT_WINDOW));
AlertConfiguration expirationAdvisoryAlertConfiguration = AlertConfigurationFactory.createExpirationAdvisoryAlertConfiguration(
timeUntilExpirationAdvisoryAlarm, OmnipodConst.EXPIRATION_ADVISORY_WINDOW);
AlertConfiguration shutdownImminentAlertConfiguration = AlertConfigurationFactory.createShutdownImminentAlertConfiguration(
timeUntilShutdownImminentAlarm);
AlertConfiguration autoOffAlertConfiguration = AlertConfigurationFactory.createAutoOffAlertConfiguration(
false, Duration.ZERO);
List<AlertConfiguration> alertConfigurations = Arrays.asList( //
lowReservoirAlertConfiguration, //
expirationAdvisoryAlertConfiguration, //
shutdownImminentAlertConfiguration, //
autoOffAlertConfiguration //
);
return communicationService.executeAction(new ConfigureAlertsAction(podStateManager, alertConfigurations));
}
public StatusResponse executeInsertionBolusCommand(OmnipodCommunicationManager communicationService, PodStateManager podStateManager) {
return communicationService.executeAction(new BolusAction(podStateManager, OmnipodConst.POD_CANNULA_INSERTION_BOLUS_UNITS,
Duration.standardSeconds(1), false, false));
}
}

View file

@ -1,37 +0,0 @@
package info.nightscout.androidaps.plugins.pump.omnipod.comm.action.service;
import org.joda.time.Duration;
import java.util.Collections;
import info.nightscout.androidaps.plugins.pump.omnipod.comm.OmnipodCommunicationManager;
import info.nightscout.androidaps.plugins.pump.omnipod.comm.action.BolusAction;
import info.nightscout.androidaps.plugins.pump.omnipod.comm.action.ConfigureAlertsAction;
import info.nightscout.androidaps.plugins.pump.omnipod.comm.message.OmnipodMessage;
import info.nightscout.androidaps.plugins.pump.omnipod.comm.message.command.FaultConfigCommand;
import info.nightscout.androidaps.plugins.pump.omnipod.comm.message.response.StatusResponse;
import info.nightscout.androidaps.plugins.pump.omnipod.defs.AlertConfiguration;
import info.nightscout.androidaps.plugins.pump.omnipod.defs.AlertConfigurationFactory;
import info.nightscout.androidaps.plugins.pump.omnipod.defs.state.PodStateManager;
import info.nightscout.androidaps.plugins.pump.omnipod.util.OmnipodConst;
public class PrimeService {
public StatusResponse executeDisableTab5Sub16FaultConfigCommand(OmnipodCommunicationManager communicationService, PodStateManager podStateManager) {
FaultConfigCommand faultConfigCommand = new FaultConfigCommand(podStateManager.getCurrentNonce(), (byte) 0x00, (byte) 0x00);
OmnipodMessage faultConfigMessage = new OmnipodMessage(podStateManager.getAddress(),
Collections.singletonList(faultConfigCommand), podStateManager.getMessageNumber());
return communicationService.exchangeMessages(StatusResponse.class, podStateManager, faultConfigMessage);
}
public StatusResponse executeFinishSetupReminderAlertCommand(OmnipodCommunicationManager communicationService, PodStateManager podStateManager) {
AlertConfiguration finishSetupReminderAlertConfiguration = AlertConfigurationFactory.createFinishSetupReminderAlertConfiguration();
return communicationService.executeAction(new ConfigureAlertsAction(podStateManager,
Collections.singletonList(finishSetupReminderAlertConfiguration)));
}
public StatusResponse executePrimeBolusCommand(OmnipodCommunicationManager communicationService, PodStateManager podStateManager) {
return communicationService.executeAction(new BolusAction(podStateManager, OmnipodConst.POD_PRIME_BOLUS_UNITS,
Duration.standardSeconds(1), false, false));
}
}

View file

@ -1,9 +0,0 @@
package info.nightscout.androidaps.plugins.pump.omnipod.comm.exception;
import info.nightscout.androidaps.plugins.pump.omnipod.exception.OmnipodException;
public class NonceOutOfSyncException extends OmnipodException {
public NonceOutOfSyncException() {
super("Nonce out of sync", true);
}
}

View file

@ -1,9 +0,0 @@
package info.nightscout.androidaps.plugins.pump.omnipod.comm.exception;
import info.nightscout.androidaps.plugins.pump.omnipod.exception.OmnipodException;
public class NonceResyncException extends OmnipodException {
public NonceResyncException() {
super("Nonce resync failed", true);
}
}

View file

@ -1,5 +0,0 @@
package info.nightscout.androidaps.plugins.pump.omnipod.comm.message;
public interface IRawRepresentable {
byte[] getRawData();
}

View file

@ -0,0 +1,45 @@
package info.nightscout.androidaps.plugins.pump.omnipod.dagger
import dagger.Module
import dagger.Provides
import dagger.android.ContributesAndroidInjector
import info.nightscout.androidaps.plugins.pump.omnipod.data.RLHistoryItemOmnipod
import info.nightscout.androidaps.plugins.pump.omnipod.driver.manager.PodStateManager
import info.nightscout.androidaps.plugins.pump.omnipod.manager.AapsPodStateManager
import info.nightscout.androidaps.plugins.pump.omnipod.rileylink.manager.OmnipodRileyLinkCommunicationManager
import info.nightscout.androidaps.plugins.pump.omnipod.ui.PodHistoryActivity
import info.nightscout.androidaps.plugins.pump.omnipod.ui.PodManagementActivity
import info.nightscout.androidaps.plugins.pump.omnipod.ui.wizard.initpod.InitActionFragment
import info.nightscout.androidaps.plugins.pump.omnipod.ui.wizard.initpod.InitPodTask
import info.nightscout.androidaps.plugins.pump.omnipod.ui.wizard.pages.InitPodRefreshAction
import info.nightscout.androidaps.plugins.pump.omnipod.ui.wizard.pages.PodInfoFragment
import info.nightscout.androidaps.plugins.pump.omnipod.ui.wizard.removepod.RemoveActionFragment
@Module
@Suppress("unused")
abstract class OmnipodModule {
// Activities
@ContributesAndroidInjector
abstract fun contributesPodManagementActivity(): PodManagementActivity
@ContributesAndroidInjector abstract fun contributesPodHistoryActivity(): PodHistoryActivity
// Fragments
@ContributesAndroidInjector abstract fun initActionFragment(): InitActionFragment
@ContributesAndroidInjector abstract fun removeActionFragment(): RemoveActionFragment
@ContributesAndroidInjector abstract fun podInfoFragment(): PodInfoFragment
// Service
@ContributesAndroidInjector
abstract fun omnipodCommunicationManagerProvider(): OmnipodRileyLinkCommunicationManager
// Data
@ContributesAndroidInjector abstract fun initPodRefreshAction(): InitPodRefreshAction
@ContributesAndroidInjector abstract fun initPodTask(): InitPodTask
@ContributesAndroidInjector abstract fun rlHistoryItemOmnipod(): RLHistoryItemOmnipod
companion object {
@Provides
fun podStateManagerProvider(aapsPodStateManager: AapsPodStateManager): PodStateManager = aapsPodStateManager
}
}

View file

@ -0,0 +1,79 @@
package info.nightscout.androidaps.plugins.pump.omnipod.data;
import org.apache.commons.lang3.StringUtils;
import org.json.JSONException;
import org.json.JSONObject;
import info.nightscout.androidaps.data.DetailedBolusInfo;
import info.nightscout.androidaps.logging.AAPSLogger;
import info.nightscout.androidaps.logging.LTag;
// Used for storing active bolus during bolus,
// so we can recover it and add it to treatments after the app crashed or got killed
// Storing DetailedBolusInfo itself is no good because it contains a reference to Context
// and to JSONObject, which are both not serializable
// TODO add tests
public class ActiveBolus {
private long date;
private long lastKnownBolusTime;
private String eventType;
private double insulin;
private double carbs;
private int source;
private boolean isValid;
private double glucose;
private String glucoseType;
private int carbTime;
private String boluscalc;
private long pumpId;
private boolean isSMB;
private long deliverAt;
private String notes;
public static ActiveBolus fromDetailedBolusInfo(DetailedBolusInfo detailedBolusInfo) {
ActiveBolus activeBolus = new ActiveBolus();
activeBolus.date = detailedBolusInfo.date;
activeBolus.lastKnownBolusTime = detailedBolusInfo.lastKnownBolusTime;
activeBolus.eventType = detailedBolusInfo.eventType;
activeBolus.insulin = detailedBolusInfo.insulin;
activeBolus.carbs = detailedBolusInfo.carbs;
activeBolus.source = detailedBolusInfo.source;
activeBolus.isValid = detailedBolusInfo.isValid;
activeBolus.glucose = detailedBolusInfo.glucose;
activeBolus.glucoseType = detailedBolusInfo.glucoseType;
activeBolus.carbTime = detailedBolusInfo.carbTime;
activeBolus.boluscalc = detailedBolusInfo.boluscalc == null ? null : detailedBolusInfo.boluscalc.toString();
activeBolus.pumpId = detailedBolusInfo.pumpId;
activeBolus.isSMB = detailedBolusInfo.isSMB;
activeBolus.deliverAt = detailedBolusInfo.deliverAt;
activeBolus.notes = detailedBolusInfo.notes;
return activeBolus;
}
public DetailedBolusInfo toDetailedBolusInfo(AAPSLogger aapsLogger) {
DetailedBolusInfo detailedBolusInfo = new DetailedBolusInfo();
detailedBolusInfo.date = date;
detailedBolusInfo.lastKnownBolusTime = lastKnownBolusTime;
detailedBolusInfo.eventType = eventType;
detailedBolusInfo.insulin = insulin;
detailedBolusInfo.carbs = carbs;
detailedBolusInfo.source = source;
detailedBolusInfo.isValid = isValid;
detailedBolusInfo.glucose = glucose;
detailedBolusInfo.glucoseType = glucoseType;
detailedBolusInfo.carbTime = carbTime;
if (!StringUtils.isEmpty(boluscalc)) {
try {
detailedBolusInfo.boluscalc = new JSONObject(boluscalc);
} catch (JSONException ex) {
// ignore
aapsLogger.warn(LTag.PUMP, "Could not parse bolusCalc string to JSON: " + boluscalc, ex);
}
}
detailedBolusInfo.pumpId = pumpId;
detailedBolusInfo.isSMB = isSMB;
detailedBolusInfo.deliverAt = deliverAt;
detailedBolusInfo.notes = notes;
return detailedBolusInfo;
}
}

View file

@ -2,24 +2,29 @@ package info.nightscout.androidaps.plugins.pump.omnipod.data;
import org.joda.time.LocalDateTime;
import javax.inject.Inject;
import dagger.android.HasAndroidInjector;
import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.data.RLHistoryItem;
import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.defs.RileyLinkTargetDevice;
import info.nightscout.androidaps.plugins.pump.omnipod.defs.OmnipodCommandType;
import info.nightscout.androidaps.plugins.pump.omnipod.definition.OmnipodCommandType;
import info.nightscout.androidaps.utils.resources.ResourceHelper;
public class RLHistoryItemOmnipod extends RLHistoryItem {
private OmnipodCommandType omnipodCommandType;
@Inject ResourceHelper resourceHelper;
private final OmnipodCommandType omnipodCommandType;
public RLHistoryItemOmnipod(OmnipodCommandType omnipodCommandType) {
public RLHistoryItemOmnipod(HasAndroidInjector injector, OmnipodCommandType omnipodCommandType) {
super(new LocalDateTime(), RLHistoryItemSource.OmnipodCommand, RileyLinkTargetDevice.Omnipod);
injector.androidInjector().inject(this);
this.omnipodCommandType = omnipodCommandType;
}
@Override
public String getDescription(ResourceHelper resourceHelper) {
if (RLHistoryItemSource.OmnipodCommand.equals(source)) {
return omnipodCommandType.name();
return resourceHelper.gs(omnipodCommandType.getResourceId());
}
return super.getDescription(resourceHelper);
}

View file

@ -0,0 +1,34 @@
package info.nightscout.androidaps.plugins.pump.omnipod.definition;
import info.nightscout.androidaps.plugins.pump.omnipod.R;
/**
* Created by andy on 4.8.2019
*/
public enum OmnipodCommandType {
PAIR_AND_PRIME_POD(R.string.omnipod_cmd_pair_and_prime), // First step of Pod activation
FILL_CANNULA_AND_SET_BASAL_PROFILE(R.string.omnipod_cmd_fill_cannula_set_basal_profile), // Second step of Pod activation
DEACTIVATE_POD(R.string.omnipod_cmd_deactivate_pod), //
SET_BASAL_PROFILE(R.string.omnipod_cmd_set_basal_schedule), //
SET_BOLUS(R.string.omnipod_cmd_set_bolus), //
CANCEL_BOLUS(R.string.omnipod_cmd_cancel_bolus), //
SET_TEMPORARY_BASAL(R.string.omnipod_cmd_set_tbr), //
CANCEL_TEMPORARY_BASAL(R.string.omnipod_cmd_cancel_tbr_by_driver), //
DISCARD_POD(R.string.omnipod_cmd_discard_pod), //
GET_POD_STATUS(R.string.omnipod_cmd_get_pod_status), //
SET_TIME(R.string.omnipod_cmd_set_time), //
CONFIGURE_ALERTS(R.string.omnipod_cmd_configure_alerts), //
ACKNOWLEDGE_ALERTS(R.string.omnipod_cmd_acknowledge_alerts), //
GET_POD_PULSE_LOG(R.string.omnipod_cmd_get_pulse_log), //
SUSPEND_DELIVERY(R.string.omnipod_cmd_suspend_delivery);
private int resourceId;
OmnipodCommandType(int resourceId) {
this.resourceId = resourceId;
}
public int getResourceId() {
return resourceId;
}
}

View file

@ -1,4 +1,4 @@
package info.nightscout.androidaps.plugins.pump.omnipod.defs;
package info.nightscout.androidaps.plugins.pump.omnipod.definition;
import info.nightscout.androidaps.plugins.general.actions.defs.CustomActionType;
@ -7,14 +7,7 @@ import info.nightscout.androidaps.plugins.general.actions.defs.CustomActionType;
*/
public enum OmnipodCustomActionType implements CustomActionType {
ResetRileyLinkConfiguration(), //
PairAndPrime(), //
FillCanulaSetBasalProfile(), //
//InitPod(), //
DeactivatePod(), //
ResetPodStatus(), //
;
RESET_RILEY_LINK_CONFIGURATION;
@Override
public String getKey() {

View file

@ -0,0 +1,8 @@
package info.nightscout.androidaps.plugins.pump.omnipod.definition;
public enum OmnipodStatusRequestType {
ACKNOWLEDGE_ALERTS,
GET_POD_STATE,
GET_PULSE_LOG,
SUSPEND_DELIVERY
}

View file

@ -0,0 +1,29 @@
package info.nightscout.androidaps.plugins.pump.omnipod.definition;
import info.nightscout.androidaps.plugins.pump.omnipod.R;
public class OmnipodStorageKeys {
private static final String PREFIX = "AAPS.Omnipod.";
public static class Preferences {
public static final String POD_STATE = PREFIX + "pod_state";
public static final String ACTIVE_BOLUS = PREFIX + "current_bolus";
public static final int BASAL_BEEPS_ENABLED = R.string.key_omnipod_basal_beeps_enabled;
public static final int BOLUS_BEEPS_ENABLED = R.string.key_omnipod_bolus_beeps_enabled;
public static final int SMB_BEEPS_ENABLED = R.string.key_omnipod_smb_beeps_enabled;
public static final int TBR_BEEPS_ENABLED = R.string.key_omnipod_tbr_beeps_enabled;
public static final int SUSPEND_DELIVERY_BUTTON_ENABLED = R.string.key_omnipod_suspend_delivery_button_enabled;
public static final int PULSE_LOG_BUTTON_ENABLED = R.string.key_omnipod_pulse_log_button_enabled;
public static final int TIME_CHANGE_EVENT_ENABLED = R.string.key_omnipod_time_change_event_enabled;
public static final int EXPIRATION_REMINDER_ENABLED = R.string.key_omnipod_expiration_reminder_enabled;
public static final int EXPIRATION_REMINDER_HOURS_BEFORE_SHUTDOWN = R.string.key_omnipod_expiration_reminder_hours_before_shutdown;
public static final int LOW_RESERVOIR_ALERT_ENABLED = R.string.key_omnipod_low_reservoir_alert_enabled;
public static final int LOW_RESERVOIR_ALERT_UNITS = R.string.key_omnipod_low_reservoir_alert_units;
}
public static class Statistics {
public static final String TBRS_SET = PREFIX + "tbrs_set";
public static final String STANDARD_BOLUSES_DELIVERED = PREFIX + "std_boluses_delivered";
public static final String SMB_BOLUSES_DELIVERED = PREFIX + "smb_boluses_delivered";
}
}

View file

@ -0,0 +1,94 @@
package info.nightscout.androidaps.plugins.pump.omnipod.definition;
import androidx.annotation.StringRes;
import java.util.HashMap;
import java.util.Map;
import info.nightscout.androidaps.plugins.pump.common.defs.PumpHistoryEntryGroup;
import info.nightscout.androidaps.plugins.pump.omnipod.R;
/**
* Created by andy on 24.11.2019
*/
public enum PodHistoryEntryType {
PAIR_AND_PRIME(1, R.string.omnipod_init_pod_wizard_step2_title, PumpHistoryEntryGroup.Prime),
FILL_CANNULA_SET_BASAL_PROFILE(2, R.string.omnipod_init_pod_wizard_step4_title, PumpHistoryEntryGroup.Prime),
DEACTIVATE_POD(3, R.string.omnipod_cmd_deactivate_pod, PumpHistoryEntryGroup.Prime),
RESET_POD_STATE(4, R.string.omnipod_cmd_discard_pod, PumpHistoryEntryGroup.Prime),
SET_TEMPORARY_BASAL(10, R.string.omnipod_cmd_set_tbr, PumpHistoryEntryGroup.Basal),
CANCEL_TEMPORARY_BASAL_BY_DRIVER(11, R.string.omnipod_cmd_cancel_tbr_by_driver, PumpHistoryEntryGroup.Basal),
CANCEL_TEMPORARY_BASAL(12, R.string.omnipod_cmd_cancel_tbr, PumpHistoryEntryGroup.Basal),
SET_FAKE_SUSPENDED_TEMPORARY_BASAL(13, R.string.omnipod_cmd_set_fake_suspended_tbr, PumpHistoryEntryGroup.Basal),
CANCEL_FAKE_SUSPENDED_TEMPORARY_BASAL(14, R.string.omnipod_cmd_cancel_fake_suspended_tbr, PumpHistoryEntryGroup.Basal),
SET_BASAL_SCHEDULE(20, R.string.omnipod_cmd_set_basal_schedule, PumpHistoryEntryGroup.Basal),
GET_POD_STATUS(30, R.string.omnipod_cmd_get_pod_status, PumpHistoryEntryGroup.Configuration),
GET_POD_INFO(31, R.string.omnipod_cmd_get_pod_info, PumpHistoryEntryGroup.Configuration),
SET_TIME(32, R.string.omnipod_cmd_set_time, PumpHistoryEntryGroup.Configuration),
SET_BOLUS(40, R.string.omnipod_cmd_set_bolus, PumpHistoryEntryGroup.Bolus),
CANCEL_BOLUS(41, R.string.omnipod_cmd_cancel_bolus, PumpHistoryEntryGroup.Bolus),
CONFIGURE_ALERTS(50, R.string.omnipod_cmd_configure_alerts, PumpHistoryEntryGroup.Alarm),
ACKNOWLEDGE_ALERTS(51, R.string.omnipod_cmd_acknowledge_alerts, PumpHistoryEntryGroup.Alarm),
SUSPEND_DELIVERY(60, R.string.omnipod_cmd_suspend_delivery, PumpHistoryEntryGroup.Basal),
RESUME_DELIVERY(61, R.string.omnipod_cmd_resume_delivery, PumpHistoryEntryGroup.Basal),
UNKNOWN_ENTRY_TYPE(99, R.string.omnipod_cmd_unknown_entry);
private int code;
private static final Map<Integer, PodHistoryEntryType> instanceMap;
@StringRes
private int resourceId;
private PumpHistoryEntryGroup group;
static {
instanceMap = new HashMap<>();
for (PodHistoryEntryType value : values()) {
instanceMap.put(value.code, value);
}
}
PodHistoryEntryType(int code, @StringRes int resourceId) {
this.code = code;
this.resourceId = resourceId;
}
PodHistoryEntryType(int code, @StringRes int resourceId, PumpHistoryEntryGroup group) {
this.code = code;
this.resourceId = resourceId;
this.group = group;
}
public int getCode() {
return code;
}
public PumpHistoryEntryGroup getGroup() {
return this.group;
}
public static PodHistoryEntryType getByCode(long code) {
return getByCode((int) code);
}
public static PodHistoryEntryType getByCode(int code) {
if (instanceMap.containsKey(code)) {
return instanceMap.get(code);
} else {
return UNKNOWN_ENTRY_TYPE;
}
}
public int getResourceId() {
return resourceId;
}
}

View file

@ -1,4 +1,4 @@
package info.nightscout.androidaps.plugins.pump.omnipod.defs;
package info.nightscout.androidaps.plugins.pump.omnipod.definition;
import java.util.ArrayList;
import java.util.List;
@ -7,17 +7,17 @@ import info.nightscout.androidaps.plugins.pump.omnipod.R;
public enum PodInitActionType {
PairAndPrimeWizardStep(), //
PairPod(R.string.omnipod_init_pod_pair_pod, PairAndPrimeWizardStep), //
PrimePod(R.string.omnipod_init_pod_prime_pod, PairAndPrimeWizardStep), //
PAIR_AND_PRIME_WIZARD_STEP(), //
PAIR_POD(R.string.omnipod_init_pod_pair_pod, PAIR_AND_PRIME_WIZARD_STEP), //
PRIME_POD(R.string.omnipod_init_pod_prime_pod, PAIR_AND_PRIME_WIZARD_STEP), //
FillCannulaSetBasalProfileWizardStep(), //
FillCannula(R.string.omnipod_init_pod_fill_cannula, FillCannulaSetBasalProfileWizardStep), //
SetBasalProfile(R.string.omnipod_init_pod_set_basal_profile, FillCannulaSetBasalProfileWizardStep), //
FILL_CANNULA_SET_BASAL_PROFILE_WIZARD_STEP(), //
FILL_CANNULA(R.string.omnipod_init_pod_fill_cannula, FILL_CANNULA_SET_BASAL_PROFILE_WIZARD_STEP), //
SET_BASAL_PROFILE(R.string.omnipod_init_pod_set_basal_profile, FILL_CANNULA_SET_BASAL_PROFILE_WIZARD_STEP), //
DeactivatePodWizardStep(), //
CancelDelivery(R.string.omnipod_deactivate_pod_cancel_delivery, DeactivatePodWizardStep), //
DeactivatePod(R.string.omnipod_deactivate_pod_deactivate_pod, DeactivatePodWizardStep);
DEACTIVATE_POD_WIZARD_STEP(), //
CANCEL_DELIVERY(R.string.omnipod_deactivate_pod_cancel_delivery, DEACTIVATE_POD_WIZARD_STEP), //
DEACTIVATE_POD(R.string.omnipod_deactivate_pod_deactivate_pod, DEACTIVATE_POD_WIZARD_STEP);
private int resourceId;
private PodInitActionType parent;

View file

@ -1,4 +1,4 @@
package info.nightscout.androidaps.plugins.pump.omnipod.defs;
package info.nightscout.androidaps.plugins.pump.omnipod.definition;
public interface PodInitReceiver {

View file

@ -1,14 +0,0 @@
package info.nightscout.androidaps.plugins.pump.omnipod.defs;
public abstract class AlertTrigger<T> {
protected T value;
public AlertTrigger(T value) {
this.value = value;
}
public T getValue() {
return value;
}
}

View file

@ -1,74 +0,0 @@
package info.nightscout.androidaps.plugins.pump.omnipod.defs;
import info.nightscout.androidaps.data.DetailedBolusInfo;
import info.nightscout.androidaps.data.Profile;
import info.nightscout.androidaps.data.PumpEnactResult;
import info.nightscout.androidaps.plugins.pump.common.data.TempBasalPair;
import info.nightscout.androidaps.plugins.pump.omnipod.comm.message.response.podinfo.PodInfoRecentPulseLog;
// TODO remove?
// We only have this interface for possible Omnipod Dash implementation
public interface IOmnipodManager {
/**
* Initialize Pod
*/
PumpEnactResult initPod(PodInitActionType podInitActionType, PodInitReceiver podInitReceiver, Profile profile);
/**
* Get Pod Status (is pod running, battery left ?, reservoir, etc)
*/
// TODO we should probably return a (wrapped) StatusResponse instead of a PumpEnactResult
PumpEnactResult getPodStatus();
/**
* Deactivate Pod
*/
PumpEnactResult deactivatePod(PodInitReceiver podInitReceiver);
/**
* Set Basal Profile
*/
PumpEnactResult setBasalProfile(Profile basalProfile);
/**
* Reset Pod status (if we forget to disconnect Pod and want to init new pod, and want to forget current pod)
*/
PumpEnactResult resetPodStatus();
/**
* Set Bolus
*
* @param detailedBolusInfo DetailedBolusInfo instance with amount and all other required data
*/
PumpEnactResult setBolus(DetailedBolusInfo detailedBolusInfo);
/**
* Cancel Bolus (if bolus is already stopped, return acknowledgment)
*/
PumpEnactResult cancelBolus();
/**
* Set Temporary Basal
*
* @param tempBasalPair TempBasalPair object containg amount and duration in minutes
*/
PumpEnactResult setTemporaryBasal(TempBasalPair tempBasalPair);
/**
* Cancel Temporary Basal (if TB is already stopped, return acknowledgment)
*/
PumpEnactResult cancelTemporaryBasal();
/**
* Acknowledge alerts
*/
PumpEnactResult acknowledgeAlerts();
/**
* Set Time on Pod
*/
PumpEnactResult setTime();
PodInfoRecentPulseLog readPulseLog();
}

View file

@ -1,53 +0,0 @@
package info.nightscout.androidaps.plugins.pump.omnipod.defs;
import java.util.Arrays;
public class NonceState {
private final long[] table = new long[21];
private int index;
public NonceState(int lot, int tid) {
initializeTable(lot, tid, (byte) 0x00);
}
public NonceState(int lot, int tid, byte seed) {
initializeTable(lot, tid, seed);
}
private void initializeTable(int lot, int tid, byte seed) {
table[0] = (long) (lot & 0xFFFF) + 0x55543DC3L + (((long) (lot) & 0xFFFFFFFFL) >> 16);
table[0] = table[0] & 0xFFFFFFFFL;
table[1] = (tid & 0xFFFF) + 0xAAAAE44EL + (((long) (tid) & 0xFFFFFFFFL) >> 16);
table[1] = table[1] & 0xFFFFFFFFL;
index = 0;
table[0] += seed;
for (int i = 0; i < 16; i++) {
table[2 + i] = generateEntry();
}
index = (int) ((table[0] + table[1]) & 0X0F);
}
private int generateEntry() {
table[0] = (((table[0] >> 16) + (table[0] & 0xFFFF) * 0x5D7FL) & 0xFFFFFFFFL);
table[1] = (((table[1] >> 16) + (table[1] & 0xFFFF) * 0x8CA0L) & 0xFFFFFFFFL);
return (int) ((table[1] + (table[0] << 16)) & 0xFFFFFFFFL);
}
public int getCurrentNonce() {
return (int) table[(2 + index)];
}
public void advanceToNextNonce() {
int nonce = getCurrentNonce();
table[(2 + index)] = generateEntry();
index = (nonce & 0x0F);
}
@Override
public String toString() {
return "NonceState{" +
"table=" + Arrays.toString(table) +
", index=" + index +
'}';
}
}

View file

@ -1,24 +0,0 @@
package info.nightscout.androidaps.plugins.pump.omnipod.defs;
/**
* Created by andy on 4.8.2019
*/
public enum OmnipodCommandType {
PairAndPrimePod, //
FillCanulaAndSetBasalProfile, //
//InitPod, //
DeactivatePod, //
SetBasalProfile, //
SetBolus, //
CancelBolus, //
SetTemporaryBasal, //
CancelTemporaryBasal, //
ResetPodStatus, //
GetPodStatus, //
SetTime, //
AcknowledgeAlerts, //
GetPodPulseLog;
}

View file

@ -1,9 +0,0 @@
package info.nightscout.androidaps.plugins.pump.omnipod.defs;
import info.nightscout.androidaps.interfaces.PumpInterface;
public interface OmnipodPumpPluginInterface extends PumpInterface {
void addPodStatusRequest(OmnipodStatusRequest pumpStatusRequest);
}

View file

@ -1,19 +0,0 @@
package info.nightscout.androidaps.plugins.pump.omnipod.defs;
public enum OmnipodStatusRequest {
ResetState(OmnipodCommandType.ResetPodStatus), //
AcknowledgeAlerts(OmnipodCommandType.AcknowledgeAlerts), //
GetPodState(OmnipodCommandType.GetPodStatus), //
GetPodPulseLog(OmnipodCommandType.GetPodPulseLog);
private OmnipodCommandType commandType;
OmnipodStatusRequest(OmnipodCommandType commandType) {
this.commandType = commandType;
}
public OmnipodCommandType getCommandType() {
return commandType;
}
}

View file

@ -1,13 +0,0 @@
package info.nightscout.androidaps.plugins.pump.omnipod.defs;
/**
* Created by andy on 10/18/18.
*/
public enum OmnipodUIResponseType {
Data,
Error,
Invalid;
}

View file

@ -1,13 +0,0 @@
package info.nightscout.androidaps.plugins.pump.omnipod.defs;
public enum PodResponseType {
Acknowledgment, // set commands would just acknowledge if data was sent
Data, // query commands would return data
Error, // communication/response produced an error
Invalid; // invalid response (not supported, should never be returned)
public boolean isError() {
return this == Error || this == Invalid;
}
}

View file

@ -1,10 +0,0 @@
package info.nightscout.androidaps.plugins.pump.omnipod.defs.schedule;
import info.nightscout.androidaps.plugins.pump.omnipod.comm.message.IRawRepresentable;
public abstract class DeliverySchedule implements IRawRepresentable {
public abstract InsulinScheduleType getType();
public abstract int getChecksum();
}

View file

@ -1,7 +0,0 @@
package info.nightscout.androidaps.plugins.pump.omnipod.dialogs.wizard.defs;
public enum PodActionType {
InitPod,
RemovePod,
ResetPod
}

View file

@ -1,20 +0,0 @@
package info.nightscout.androidaps.plugins.pump.omnipod.dialogs.wizard.model;
import android.content.Context;
import androidx.fragment.app.Fragment;
import com.tech.freak.wizardpager.model.AbstractWizardModel;
import info.nightscout.androidaps.plugins.pump.omnipod.dialogs.wizard.pages.PodInfoFragment;
public abstract class InitPodWizardModel extends AbstractWizardModel {
public InitPodWizardModel(Context context) {
super(context);
}
@Override
public Fragment getReviewFragment() {
return PodInfoFragment.create("initPodInfoFragment", true);
}
}

View file

@ -1,34 +0,0 @@
package info.nightscout.androidaps.plugins.pump.omnipod.dialogs.wizard.pages;
import androidx.fragment.app.Fragment;
import com.tech.freak.wizardpager.model.ModelCallbacks;
import com.tech.freak.wizardpager.model.Page;
import com.tech.freak.wizardpager.model.ReviewItem;
import java.util.ArrayList;
/**
* Created by andy on 12/11/2019
*/
public class PodInfoPage extends Page {
public PodInfoPage(ModelCallbacks callbacks, String title) {
super(callbacks, title);
}
@Override
public Fragment createFragment() {
return PodInfoFragment.create(getKey(), true);
}
@Override
public void getReviewItems(ArrayList<ReviewItem> dest) {
}
@Override
public boolean isCompleted() {
return true;
}
}

View file

@ -1,162 +0,0 @@
package info.nightscout.androidaps.plugins.pump.omnipod.driver;
import java.util.Arrays;
import javax.inject.Inject;
import javax.inject.Singleton;
import info.nightscout.androidaps.plugins.bus.RxBusWrapper;
import info.nightscout.androidaps.plugins.pump.common.data.PumpStatus;
import info.nightscout.androidaps.plugins.pump.common.data.TempBasalPair;
import info.nightscout.androidaps.plugins.pump.common.defs.PumpDeviceState;
import info.nightscout.androidaps.plugins.pump.common.defs.PumpType;
import info.nightscout.androidaps.plugins.pump.common.events.EventRileyLinkDeviceStatusChange;
import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.RileyLinkUtil;
import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.data.RLHistoryItem;
import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.defs.RileyLinkTargetDevice;
import info.nightscout.androidaps.plugins.pump.omnipod.util.OmnipodConst;
import info.nightscout.androidaps.utils.sharedPreferences.SP;
/**
* Created by andy on 4.8.2019
*/
@Singleton
@Deprecated
public class OmnipodPumpStatus extends PumpStatus {
// TODO remove all fields that can also be obtained via PodStateManager
// We can probably get rid of this class altogether
private final SP sp;
private final RileyLinkUtil rileyLinkUtil;
private final RxBusWrapper rxBus;
public String rileyLinkErrorDescription = null;
public String rileyLinkAddress = null;
public boolean inPreInit = true;
// statuses
public double currentBasal = 0;
public long tempBasalStart;
public long tempBasalEnd;
public Double tempBasalAmount = 0.0d;
public Integer tempBasalLength;
public long tempBasalPumpId;
public PumpType pumpType;
public String regexMac = "([\\da-fA-F]{1,2}(?:\\:|$)){6}";
public boolean beepBolusEnabled = true;
public boolean beepBasalEnabled = true;
public boolean beepSMBEnabled = true;
public boolean beepTBREnabled = true;
public boolean podDebuggingOptionsEnabled = false;
public boolean timeChangeEventEnabled = true;
private PumpDeviceState pumpDeviceState;
@Inject
public OmnipodPumpStatus(SP sp,
RxBusWrapper rxBus,
RileyLinkUtil rileyLinkUtil) {
super(PumpType.Insulet_Omnipod);
this.sp = sp;
this.rxBus = rxBus;
this.rileyLinkUtil = rileyLinkUtil;
initSettings();
}
@Override
public void initSettings() {
this.activeProfileName = "";
this.reservoirRemainingUnits = 75d;
this.batteryRemaining = 75;
this.lastConnection = sp.getLong(OmnipodConst.Statistics.LastGoodPumpCommunicationTime, 0L);
this.pumpType = PumpType.Insulet_Omnipod;
}
// For Omnipod, this method only returns a RileyLink error description
@Override
public String getErrorInfo() {
return this.rileyLinkErrorDescription;
}
// public boolean setNotInPreInit() {
// this.inPreInit = false;
//
// return reconfigureService();
// }
public void clearTemporaryBasal() {
this.tempBasalStart = 0L;
this.tempBasalEnd = 0L;
this.tempBasalAmount = 0.0d;
this.tempBasalLength = 0;
}
public TempBasalPair getTemporaryBasal() {
TempBasalPair tbr = new TempBasalPair();
tbr.setDurationMinutes(tempBasalLength);
tbr.setInsulinRate(tempBasalAmount);
tbr.setStartTime(tempBasalStart);
tbr.setEndTime(tempBasalEnd);
return tbr;
}
@Override
public String toString() {
return "OmnipodPumpStatus{" +
"rileyLinkErrorDescription='" + rileyLinkErrorDescription + '\'' +
", rileyLinkAddress='" + rileyLinkAddress + '\'' +
", inPreInit=" + inPreInit +
", tempBasalStart=" + tempBasalStart +
", tempBasalEnd=" + tempBasalEnd +
", tempBasalAmount=" + tempBasalAmount +
", tempBasalLength=" + tempBasalLength +
", regexMac='" + regexMac + '\'' +
", lastDataTime=" + lastDataTime +
", lastConnection=" + lastConnection +
", previousConnection=" + previousConnection +
", lastBolusTime=" + lastBolusTime +
", lastBolusAmount=" + lastBolusAmount +
", activeProfileName='" + activeProfileName + '\'' +
", reservoirRemainingUnits=" + reservoirRemainingUnits +
", reservoirFullUnits=" + reservoirFullUnits +
", batteryRemaining=" + batteryRemaining +
", batteryVoltage=" + batteryVoltage +
", iob='" + iob + '\'' +
", dailyTotalUnits=" + dailyTotalUnits +
", maxDailyTotalUnits='" + maxDailyTotalUnits + '\'' +
", validBasalRateProfileSelectedOnPump=" + validBasalRateProfileSelectedOnPump +
", pumpType=" + pumpType +
", profileStore=" + profileStore +
", units='" + units + '\'' +
", pumpStatusType=" + pumpStatusType +
", basalsByHour=" + Arrays.toString(basalsByHour) +
", currentBasal=" + currentBasal +
", tempBasalInProgress=" + tempBasalInProgress +
", tempBasalRatio=" + tempBasalRatio +
", tempBasalRemainMin=" + tempBasalRemainMin +
", tempBasalStart=" + tempBasalStart +
", pumpType=" + pumpType +
"} ";
}
public PumpDeviceState getPumpDeviceState() {
return pumpDeviceState;
}
public void setPumpDeviceState(PumpDeviceState pumpDeviceState) {
this.pumpDeviceState = pumpDeviceState;
rileyLinkUtil.getRileyLinkHistory().add(new RLHistoryItem(pumpDeviceState, RileyLinkTargetDevice.Omnipod));
rxBus.send(new EventRileyLinkDeviceStatusChange(pumpDeviceState));
}
}

View file

@ -1,714 +0,0 @@
package info.nightscout.androidaps.plugins.pump.omnipod.driver.comm;
import android.content.Context;
import android.content.Intent;
import org.joda.time.DateTime;
import org.joda.time.Duration;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import javax.inject.Inject;
import javax.inject.Singleton;
import dagger.android.HasAndroidInjector;
import info.nightscout.androidaps.activities.ErrorHelperActivity;
import info.nightscout.androidaps.data.DetailedBolusInfo;
import info.nightscout.androidaps.data.Profile;
import info.nightscout.androidaps.data.PumpEnactResult;
import info.nightscout.androidaps.db.OmnipodHistoryRecord;
import info.nightscout.androidaps.db.Source;
import info.nightscout.androidaps.db.TemporaryBasal;
import info.nightscout.androidaps.events.Event;
import info.nightscout.androidaps.interfaces.ActivePluginProvider;
import info.nightscout.androidaps.interfaces.DatabaseHelperInterface;
import info.nightscout.androidaps.interfaces.TreatmentsInterface;
import info.nightscout.androidaps.logging.AAPSLogger;
import info.nightscout.androidaps.logging.LTag;
import info.nightscout.androidaps.plugins.bus.RxBusWrapper;
import info.nightscout.androidaps.plugins.general.overview.events.EventDismissNotification;
import info.nightscout.androidaps.plugins.general.overview.events.EventNewNotification;
import info.nightscout.androidaps.plugins.general.overview.events.EventOverviewBolusProgress;
import info.nightscout.androidaps.plugins.general.overview.notifications.Notification;
import info.nightscout.androidaps.plugins.pump.common.data.TempBasalPair;
import info.nightscout.androidaps.plugins.pump.common.defs.PumpType;
import info.nightscout.androidaps.plugins.pump.common.utils.ByteUtil;
import info.nightscout.androidaps.plugins.pump.common.utils.DateTimeUtil;
import info.nightscout.androidaps.plugins.pump.omnipod.R;
import info.nightscout.androidaps.plugins.pump.omnipod.comm.OmnipodCommunicationManager;
import info.nightscout.androidaps.plugins.pump.omnipod.comm.OmnipodManager;
import info.nightscout.androidaps.plugins.pump.omnipod.comm.SetupActionResult;
import info.nightscout.androidaps.plugins.pump.omnipod.comm.exception.ActionInitializationException;
import info.nightscout.androidaps.plugins.pump.omnipod.comm.exception.CommandInitializationException;
import info.nightscout.androidaps.plugins.pump.omnipod.comm.exception.CommunicationException;
import info.nightscout.androidaps.plugins.pump.omnipod.comm.exception.CrcMismatchException;
import info.nightscout.androidaps.plugins.pump.omnipod.comm.exception.IllegalDeliveryStatusException;
import info.nightscout.androidaps.plugins.pump.omnipod.comm.exception.IllegalMessageAddressException;
import info.nightscout.androidaps.plugins.pump.omnipod.comm.exception.IllegalMessageSequenceNumberException;
import info.nightscout.androidaps.plugins.pump.omnipod.comm.exception.IllegalPacketTypeException;
import info.nightscout.androidaps.plugins.pump.omnipod.comm.exception.IllegalPodProgressException;
import info.nightscout.androidaps.plugins.pump.omnipod.comm.exception.IllegalResponseException;
import info.nightscout.androidaps.plugins.pump.omnipod.comm.exception.IllegalVersionResponseTypeException;
import info.nightscout.androidaps.plugins.pump.omnipod.comm.exception.MessageDecodingException;
import info.nightscout.androidaps.plugins.pump.omnipod.comm.exception.NonceOutOfSyncException;
import info.nightscout.androidaps.plugins.pump.omnipod.comm.exception.NonceResyncException;
import info.nightscout.androidaps.plugins.pump.omnipod.comm.exception.NotEnoughDataException;
import info.nightscout.androidaps.plugins.pump.omnipod.comm.exception.PodFaultException;
import info.nightscout.androidaps.plugins.pump.omnipod.comm.exception.PodReturnedErrorResponseException;
import info.nightscout.androidaps.plugins.pump.omnipod.comm.message.response.StatusResponse;
import info.nightscout.androidaps.plugins.pump.omnipod.comm.message.response.podinfo.PodInfoRecentPulseLog;
import info.nightscout.androidaps.plugins.pump.omnipod.comm.message.response.podinfo.PodInfoResponse;
import info.nightscout.androidaps.plugins.pump.omnipod.defs.FaultEventCode;
import info.nightscout.androidaps.plugins.pump.omnipod.defs.IOmnipodManager;
import info.nightscout.androidaps.plugins.pump.omnipod.defs.PodInfoType;
import info.nightscout.androidaps.plugins.pump.omnipod.defs.PodInitActionType;
import info.nightscout.androidaps.plugins.pump.omnipod.defs.PodInitReceiver;
import info.nightscout.androidaps.plugins.pump.omnipod.defs.schedule.BasalSchedule;
import info.nightscout.androidaps.plugins.pump.omnipod.defs.schedule.BasalScheduleEntry;
import info.nightscout.androidaps.plugins.pump.omnipod.defs.state.PodStateManager;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.OmnipodPumpStatus;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.db.PodHistoryEntryType;
import info.nightscout.androidaps.plugins.pump.omnipod.exception.OmnipodException;
import info.nightscout.androidaps.plugins.pump.omnipod.util.OmnipodConst;
import info.nightscout.androidaps.plugins.pump.omnipod.util.OmnipodUtil;
import info.nightscout.androidaps.utils.resources.ResourceHelper;
import info.nightscout.androidaps.utils.sharedPreferences.SP;
import io.reactivex.disposables.Disposable;
import io.reactivex.subjects.SingleSubject;
@Singleton
public class AapsOmnipodManager implements IOmnipodManager {
private final PodStateManager podStateManager;
private final OmnipodUtil omnipodUtil;
private final AAPSLogger aapsLogger;
private final RxBusWrapper rxBus;
private final ResourceHelper resourceHelper;
private final HasAndroidInjector injector;
private final ActivePluginProvider activePlugin;
private final OmnipodPumpStatus pumpStatus;
private final Context context;
private final SP sp;
private final OmnipodManager delegate;
private DatabaseHelperInterface databaseHelper;
@Inject
public AapsOmnipodManager(OmnipodCommunicationManager communicationService,
PodStateManager podStateManager,
OmnipodPumpStatus pumpStatus,
OmnipodUtil omnipodUtil,
AAPSLogger aapsLogger,
RxBusWrapper rxBus,
SP sp,
ResourceHelper resourceHelper,
HasAndroidInjector injector,
ActivePluginProvider activePlugin,
Context context,
DatabaseHelperInterface databaseHelper) {
if (podStateManager == null) {
throw new IllegalArgumentException("Pod state manager can not be null");
}
this.podStateManager = podStateManager;
this.omnipodUtil = omnipodUtil;
this.aapsLogger = aapsLogger;
this.rxBus = rxBus;
this.resourceHelper = resourceHelper;
this.injector = injector;
this.activePlugin = activePlugin;
this.pumpStatus = pumpStatus;
this.context = context;
this.databaseHelper = databaseHelper;
this.sp = sp;
delegate = new OmnipodManager(aapsLogger, sp, communicationService, podStateManager);
}
public PodStateManager getPodStateManager() {
return podStateManager;
}
@Override
public PumpEnactResult initPod(PodInitActionType podInitActionType, PodInitReceiver podInitReceiver, Profile profile) {
long time = System.currentTimeMillis();
if (PodInitActionType.PairAndPrimeWizardStep.equals(podInitActionType)) {
try {
Disposable disposable = delegate.pairAndPrime().subscribe(res -> //
handleSetupActionResult(podInitActionType, podInitReceiver, res, time, null));
return new PumpEnactResult(injector).success(true).enacted(true);
} catch (Exception ex) {
String comment = handleAndTranslateException(ex);
podInitReceiver.returnInitTaskStatus(podInitActionType, false, comment);
addFailureToHistory(time, PodHistoryEntryType.PairAndPrime, comment);
return new PumpEnactResult(injector).success(false).enacted(false).comment(comment);
}
} else if (PodInitActionType.FillCannulaSetBasalProfileWizardStep.equals(podInitActionType)) {
try {
BasalSchedule basalSchedule;
try {
basalSchedule = mapProfileToBasalSchedule(profile);
} catch (Exception ex) {
throw new CommandInitializationException("Basal profile mapping failed", ex);
}
Disposable disposable = delegate.insertCannula(basalSchedule).subscribe(res -> //
handleSetupActionResult(podInitActionType, podInitReceiver, res, time, profile));
rxBus.send(new EventDismissNotification(Notification.OMNIPOD_POD_NOT_ATTACHED));
return new PumpEnactResult(injector).success(true).enacted(true);
} catch (Exception ex) {
String comment = handleAndTranslateException(ex);
podInitReceiver.returnInitTaskStatus(podInitActionType, false, comment);
addFailureToHistory(time, PodHistoryEntryType.FillCannulaSetBasalProfile, comment);
return new PumpEnactResult(injector).success(false).enacted(false).comment(comment);
}
}
return new PumpEnactResult(injector).success(false).enacted(false).comment(getStringResource(R.string.omnipod_error_illegal_init_action_type, podInitActionType.name()));
}
@Override
public PumpEnactResult getPodStatus() {
long time = System.currentTimeMillis();
try {
StatusResponse statusResponse = delegate.getPodStatus();
addSuccessToHistory(time, PodHistoryEntryType.GetPodStatus, statusResponse);
return new PumpEnactResult(injector).success(true).enacted(false);
} catch (Exception ex) {
String comment = handleAndTranslateException(ex);
addFailureToHistory(time, PodHistoryEntryType.GetPodStatus, comment);
return new PumpEnactResult(injector).success(false).enacted(false).comment(comment);
}
}
@Override
public PumpEnactResult deactivatePod(PodInitReceiver podInitReceiver) {
long time = System.currentTimeMillis();
try {
delegate.deactivatePod();
} catch (Exception ex) {
String comment = handleAndTranslateException(ex);
podInitReceiver.returnInitTaskStatus(PodInitActionType.DeactivatePodWizardStep, false, comment);
addFailureToHistory(time, PodHistoryEntryType.DeactivatePod, comment);
return new PumpEnactResult(injector).success(false).enacted(false).comment(comment);
}
reportImplicitlyCanceledTbr();
addSuccessToHistory(time, PodHistoryEntryType.DeactivatePod, null);
podInitReceiver.returnInitTaskStatus(PodInitActionType.DeactivatePodWizardStep, true, null);
return new PumpEnactResult(injector).success(true).enacted(true);
}
@Override
public PumpEnactResult setBasalProfile(Profile profile) {
long time = System.currentTimeMillis();
try {
BasalSchedule basalSchedule;
try {
basalSchedule = mapProfileToBasalSchedule(profile);
} catch (Exception ex) {
throw new CommandInitializationException("Basal profile mapping failed", ex);
}
delegate.setBasalSchedule(basalSchedule, isBasalBeepsEnabled());
// Because setting a basal profile actually suspends and then resumes delivery, TBR is implicitly cancelled
reportImplicitlyCanceledTbr();
addSuccessToHistory(time, PodHistoryEntryType.SetBasalSchedule, profile.getBasalValues());
} catch (Exception ex) {
if ((ex instanceof OmnipodException) && !((OmnipodException) ex).isCertainFailure()) {
reportImplicitlyCanceledTbr();
addToHistory(time, PodHistoryEntryType.SetBasalSchedule, "Uncertain failure", false);
return new PumpEnactResult(injector).success(false).enacted(false).comment(getStringResource(R.string.omnipod_error_set_basal_failed_uncertain));
}
String comment = handleAndTranslateException(ex);
reportImplicitlyCanceledTbr();
addFailureToHistory(time, PodHistoryEntryType.SetBasalSchedule, comment);
return new PumpEnactResult(injector).success(false).enacted(false).comment(comment);
}
return new PumpEnactResult(injector).success(true).enacted(true);
}
@Override
public PumpEnactResult resetPodStatus() {
getPodStateManager().removeState();
reportImplicitlyCanceledTbr();
addSuccessToHistory(System.currentTimeMillis(), PodHistoryEntryType.ResetPodState, null);
return new PumpEnactResult(injector).success(true).enacted(true);
}
@Override
public PumpEnactResult setBolus(DetailedBolusInfo detailedBolusInfo) {
OmnipodManager.BolusCommandResult bolusCommandResult;
boolean beepsEnabled = detailedBolusInfo.isSMB ? isSmbBeepsEnabled() : isBolusBeepsEnabled();
Date bolusStarted;
try {
bolusCommandResult = delegate.bolus(PumpType.Insulet_Omnipod.determineCorrectBolusSize(detailedBolusInfo.insulin), beepsEnabled, beepsEnabled, detailedBolusInfo.isSMB ? null :
(estimatedUnitsDelivered, percentage) -> {
EventOverviewBolusProgress progressUpdateEvent = EventOverviewBolusProgress.INSTANCE;
progressUpdateEvent.setStatus(getStringResource(R.string.bolusdelivering, detailedBolusInfo.insulin));
progressUpdateEvent.setPercent(percentage);
sendEvent(progressUpdateEvent);
});
bolusStarted = new Date();
} catch (Exception ex) {
String comment = handleAndTranslateException(ex);
addFailureToHistory(System.currentTimeMillis(), PodHistoryEntryType.SetBolus, comment);
return new PumpEnactResult(injector).success(false).enacted(false).comment(comment);
}
if (OmnipodManager.CommandDeliveryStatus.UNCERTAIN_FAILURE.equals(bolusCommandResult.getCommandDeliveryStatus())) {
// For safety reasons, we treat this as a bolus that has successfully been delivered, in order to prevent insulin overdose
showErrorDialog(getStringResource(R.string.omnipod_bolus_failed_uncertain), R.raw.boluserror);
}
detailedBolusInfo.date = bolusStarted.getTime();
detailedBolusInfo.source = Source.PUMP;
// Store the current bolus for in case the app crashes, gets killed, the phone dies or whatever before the bolus finishes
// If we have a stored value for the current bolus on startup, we'll create a Treatment for it
// However this can potentially be hours later if for example your phone died and you can't charge it
// FIXME !!!
// The proper solution here would be to create a treatment right after the bolus started,
// and update that treatment after the bolus has finished in case the actual units delivered don't match the requested bolus units
// That way, the bolus would immediately be sent to NS so in case the phone dies you could still see the bolus
// Unfortunately this doesn't work because
// a) when cancelling a bolus within a few seconds of starting it, after updating the Treatment,
// we get a new treatment event from NS containing the originally created treatment with the original insulin amount.
// This event is processed in TreatmentService.createTreatmentFromJsonIfNotExists().
// Opposed to what the name of this method suggests, it does createOrUpdate,
// overwriting the insulin delivered with the original value.
// So practically it seems impossible to update a Treatment when using NS
// b) we only send newly created treatments to NS, so the insulin amount in NS would never be updated
//
// I discussed this with the AAPS team but nobody seems to care so we're stuck with this ugly workaround for now
try {
sp.putString(OmnipodConst.Prefs.CurrentBolus, omnipodUtil.getGsonInstance().toJson(detailedBolusInfo));
} catch (Exception ex) {
aapsLogger.error(LTag.PUMP, "Failed to store current bolus to SP", ex);
}
// Wait for the bolus to finish
OmnipodManager.BolusDeliveryResult bolusDeliveryResult =
bolusCommandResult.getDeliveryResultSubject().blockingGet();
detailedBolusInfo.insulin = bolusDeliveryResult.getUnitsDelivered();
addBolusToHistory(detailedBolusInfo);
sp.remove(OmnipodConst.Prefs.CurrentBolus);
return new PumpEnactResult(injector).success(true).enacted(true).bolusDelivered(detailedBolusInfo.insulin);
}
@Override
public PumpEnactResult cancelBolus() {
SingleSubject<Boolean> bolusCommandExecutionSubject = delegate.getBolusCommandExecutionSubject();
if (bolusCommandExecutionSubject != null) {
// Wait until the bolus command has actually been executed before sending the cancel bolus command
aapsLogger.debug(LTag.PUMP, "Cancel bolus was requested, but the bolus command is still being executed. Awaiting bolus command execution");
boolean bolusCommandSuccessfullyExecuted = bolusCommandExecutionSubject.blockingGet();
if (bolusCommandSuccessfullyExecuted) {
aapsLogger.debug(LTag.PUMP, "Bolus command successfully executed. Proceeding bolus cancellation");
} else {
aapsLogger.debug(LTag.PUMP, "Not cancelling bolus: bolus command failed");
String comment = getStringResource(R.string.omnipod_bolus_did_not_succeed);
addFailureToHistory(System.currentTimeMillis(), PodHistoryEntryType.CancelBolus, comment);
return new PumpEnactResult(injector).success(true).enacted(false).comment(comment);
}
}
String comment = null;
for (int i = 1; delegate.hasActiveBolus(); i++) {
aapsLogger.debug(LTag.PUMP, "Attempting to cancel bolus (#{})", i);
try {
delegate.cancelBolus(isBolusBeepsEnabled());
aapsLogger.debug(LTag.PUMP, "Successfully cancelled bolus", i);
addSuccessToHistory(System.currentTimeMillis(), PodHistoryEntryType.CancelBolus, null);
return new PumpEnactResult(injector).success(true).enacted(true);
} catch (PodFaultException ex) {
aapsLogger.debug(LTag.PUMP, "Successfully cancelled bolus (implicitly because of a Pod Fault)");
showPodFaultErrorDialog(ex.getFaultEvent().getFaultEventCode(), null);
addSuccessToHistory(System.currentTimeMillis(), PodHistoryEntryType.CancelBolus, null);
return new PumpEnactResult(injector).success(true).enacted(true);
} catch (Exception ex) {
aapsLogger.debug(LTag.PUMP, "Failed to cancel bolus", ex);
comment = handleAndTranslateException(ex);
}
}
addFailureToHistory(System.currentTimeMillis(), PodHistoryEntryType.CancelBolus, comment);
return new PumpEnactResult(injector).success(false).enacted(false).comment(comment);
}
@Override
public PumpEnactResult setTemporaryBasal(TempBasalPair tempBasalPair) {
boolean beepsEnabled = isTempBasalBeepsEnabled();
long time = System.currentTimeMillis();
try {
delegate.setTemporaryBasal(PumpType.Insulet_Omnipod.determineCorrectBasalSize(tempBasalPair.getInsulinRate()), Duration.standardMinutes(tempBasalPair.getDurationMinutes()), beepsEnabled, beepsEnabled);
time = System.currentTimeMillis();
} catch (Exception ex) {
if ((ex instanceof OmnipodException) && !((OmnipodException) ex).isCertainFailure()) {
addToHistory(time, PodHistoryEntryType.SetTemporaryBasal, "Uncertain failure", false);
return new PumpEnactResult(injector).success(false).enacted(false).comment(getStringResource(R.string.omnipod_error_set_temp_basal_failed_uncertain));
}
String comment = handleAndTranslateException(ex);
addFailureToHistory(time, PodHistoryEntryType.SetTemporaryBasal, comment);
return new PumpEnactResult(injector).success(false).enacted(false).comment(comment);
}
reportImplicitlyCanceledTbr();
long pumpId = addSuccessToHistory(time, PodHistoryEntryType.SetTemporaryBasal, tempBasalPair);
pumpStatus.tempBasalStart = time;
pumpStatus.tempBasalAmount = tempBasalPair.getInsulinRate();
pumpStatus.tempBasalLength = tempBasalPair.getDurationMinutes();
pumpStatus.tempBasalEnd = DateTimeUtil.getTimeInFutureFromMinutes(time, tempBasalPair.getDurationMinutes());
pumpStatus.tempBasalPumpId = pumpId;
TemporaryBasal tempStart = new TemporaryBasal(injector) //
.date(time) //
.duration(tempBasalPair.getDurationMinutes()) //
.absolute(tempBasalPair.getInsulinRate()) //
.pumpId(pumpId)
.source(Source.PUMP);
activePlugin.getActiveTreatments().addToHistoryTempBasal(tempStart);
return new PumpEnactResult(injector).success(true).enacted(true);
}
@Override
public PumpEnactResult cancelTemporaryBasal() {
long time = System.currentTimeMillis();
try {
delegate.cancelTemporaryBasal(isTempBasalBeepsEnabled());
addSuccessToHistory(time, PodHistoryEntryType.CancelTemporaryBasalForce, null);
} catch (Exception ex) {
String comment = handleAndTranslateException(ex);
addFailureToHistory(time, PodHistoryEntryType.CancelTemporaryBasalForce, comment);
return new PumpEnactResult(injector).success(false).enacted(false).comment(comment);
}
return new PumpEnactResult(injector).success(true).enacted(true);
}
@Override
public PumpEnactResult acknowledgeAlerts() {
long time = System.currentTimeMillis();
try {
delegate.acknowledgeAlerts();
addSuccessToHistory(time, PodHistoryEntryType.AcknowledgeAlerts, null);
} catch (Exception ex) {
String comment = handleAndTranslateException(ex);
addFailureToHistory(time, PodHistoryEntryType.AcknowledgeAlerts, comment);
return new PumpEnactResult(injector).success(false).enacted(false).comment(comment);
}
return new PumpEnactResult(injector).success(true).enacted(true);
}
// TODO should we add this to the OmnipodCommunicationManager interface?
public PumpEnactResult getPodInfo(PodInfoType podInfoType) {
long time = System.currentTimeMillis();
try {
// TODO how can we return the PodInfo response?
// This method is useless unless we return the PodInfoResponse,
// because the pod state we keep, doesn't get updated from a PodInfoResponse.
// We use StatusResponses for that, which can be obtained from the getPodStatus method
PodInfoResponse podInfo = delegate.getPodInfo(podInfoType);
addSuccessToHistory(time, PodHistoryEntryType.GetPodInfo, podInfo);
return new PumpEnactResult(injector).success(true).enacted(true);
} catch (Exception ex) {
String comment = handleAndTranslateException(ex);
addFailureToHistory(time, PodHistoryEntryType.GetPodInfo, comment);
return new PumpEnactResult(injector).success(false).enacted(false).comment(comment);
}
}
public PumpEnactResult suspendDelivery() {
try {
delegate.suspendDelivery(isBasalBeepsEnabled());
} catch (Exception ex) {
String comment = handleAndTranslateException(ex);
return new PumpEnactResult(injector).success(false).enacted(false).comment(comment);
}
return new PumpEnactResult(injector).success(true).enacted(true);
}
public PumpEnactResult resumeDelivery() {
try {
delegate.resumeDelivery(isBasalBeepsEnabled());
} catch (Exception ex) {
String comment = handleAndTranslateException(ex);
return new PumpEnactResult(injector).success(false).enacted(false).comment(comment);
}
return new PumpEnactResult(injector).success(true).enacted(true);
}
// TODO should we add this to the OmnipodCommunicationManager interface?
// Updates the pods current time based on the device timezone and the pod's time zone
public PumpEnactResult setTime() {
long time = System.currentTimeMillis();
try {
delegate.setTime(isBasalBeepsEnabled());
// Because set time actually suspends and then resumes delivery, TBR is implicitly cancelled
reportImplicitlyCanceledTbr();
addSuccessToHistory(time, PodHistoryEntryType.SetTime, null);
} catch (Exception ex) {
if ((ex instanceof OmnipodException) && !((OmnipodException) ex).isCertainFailure()) {
reportImplicitlyCanceledTbr();
addFailureToHistory(time, PodHistoryEntryType.SetTime, "Uncertain failure");
return new PumpEnactResult(injector).success(false).enacted(false).comment(getStringResource(R.string.omnipod_error_set_time_failed_uncertain));
}
String comment = handleAndTranslateException(ex);
reportImplicitlyCanceledTbr();
addFailureToHistory(time, PodHistoryEntryType.SetTime, comment);
return new PumpEnactResult(injector).success(false).enacted(false).comment(comment);
}
return new PumpEnactResult(injector).success(true).enacted(true);
}
public PodInfoRecentPulseLog readPulseLog() {
PodInfoResponse response = delegate.getPodInfo(PodInfoType.RECENT_PULSE_LOG);
return response.getPodInfo();
}
public OmnipodCommunicationManager getCommunicationService() {
return delegate.getCommunicationService();
}
public DateTime getTime() {
return delegate.getTime();
}
public boolean isInitialized() {
return delegate.isPodRunning();
}
public void addBolusToHistory(DetailedBolusInfo detailedBolusInfo) {
long pumpId = addSuccessToHistory(detailedBolusInfo.date, PodHistoryEntryType.SetBolus, detailedBolusInfo.insulin + ";" + detailedBolusInfo.carbs);
detailedBolusInfo.pumpId = pumpId;
activePlugin.getActiveTreatments().addToHistoryTreatment(detailedBolusInfo, false);
}
private void reportImplicitlyCanceledTbr() {
//TreatmentsPlugin plugin = TreatmentsPlugin.getPlugin();
TreatmentsInterface plugin = activePlugin.getActiveTreatments();
if (plugin.isTempBasalInProgress()) {
aapsLogger.debug(LTag.PUMP, "Reporting implicitly cancelled TBR to Treatments plugin");
long time = System.currentTimeMillis() - 1000;
addSuccessToHistory(time, PodHistoryEntryType.CancelTemporaryBasal, null);
TemporaryBasal temporaryBasal = new TemporaryBasal(injector) //
.date(time) //
.duration(0) //
.pumpId(pumpStatus.tempBasalPumpId)
.source(Source.PUMP);
plugin.addToHistoryTempBasal(temporaryBasal);
}
}
private long addSuccessToHistory(long requestTime, PodHistoryEntryType entryType, Object data) {
return addToHistory(requestTime, entryType, data, true);
}
private long addFailureToHistory(long requestTime, PodHistoryEntryType entryType, Object data) {
return addToHistory(requestTime, entryType, data, false);
}
private long addToHistory(long requestTime, PodHistoryEntryType entryType, Object data, boolean success) {
OmnipodHistoryRecord omnipodHistoryRecord = new OmnipodHistoryRecord(requestTime, entryType.getCode());
if (data != null) {
if (data instanceof String) {
omnipodHistoryRecord.setData((String) data);
} else {
omnipodHistoryRecord.setData(omnipodUtil.getGsonInstance().toJson(data));
}
}
omnipodHistoryRecord.setSuccess(success);
omnipodHistoryRecord.setPodSerial(podStateManager.hasPodState() ? String.valueOf(podStateManager.getAddress()) : "None");
databaseHelper.createOrUpdate(omnipodHistoryRecord);
return omnipodHistoryRecord.getPumpId();
}
private void handleSetupActionResult(PodInitActionType podInitActionType, PodInitReceiver podInitReceiver, SetupActionResult res, long time, Profile profile) {
String comment = null;
switch (res.getResultType()) {
case FAILURE: {
aapsLogger.error(LTag.PUMP, "Setup action failed: illegal setup progress: {}", res.getPodProgressStatus());
comment = getStringResource(R.string.omnipod_driver_error_invalid_progress_state, res.getPodProgressStatus());
}
break;
case VERIFICATION_FAILURE: {
aapsLogger.error(LTag.PUMP, "Setup action verification failed: caught exception", res.getException());
comment = getStringResource(R.string.omnipod_driver_error_setup_action_verification_failed);
}
break;
}
if (podInitActionType == PodInitActionType.PairAndPrimeWizardStep) {
addToHistory(time, PodHistoryEntryType.PairAndPrime, comment, res.getResultType().isSuccess());
} else {
addToHistory(time, PodHistoryEntryType.FillCannulaSetBasalProfile, res.getResultType().isSuccess() ? profile.getBasalValues() : comment, res.getResultType().isSuccess());
}
podInitReceiver.returnInitTaskStatus(podInitActionType, res.getResultType().isSuccess(), comment);
}
private String handleAndTranslateException(Exception ex) {
String comment;
if (ex instanceof OmnipodException) {
if (ex instanceof ActionInitializationException || ex instanceof CommandInitializationException) {
comment = getStringResource(R.string.omnipod_driver_error_invalid_parameters);
} else if (ex instanceof CommunicationException) {
if (((CommunicationException) ex).getType() == CommunicationException.Type.TIMEOUT) {
comment = getStringResource(R.string.omnipod_driver_error_communication_failed_timeout);
} else {
comment = getStringResource(R.string.omnipod_driver_error_communication_failed_unexpected_exception);
}
} else if (ex instanceof CrcMismatchException) {
comment = getStringResource(R.string.omnipod_driver_error_crc_mismatch);
} else if (ex instanceof IllegalPacketTypeException) {
comment = getStringResource(R.string.omnipod_driver_error_invalid_packet_type);
} else if (ex instanceof IllegalPodProgressException || ex instanceof IllegalDeliveryStatusException) {
comment = getStringResource(R.string.omnipod_driver_error_invalid_progress_state);
} else if (ex instanceof IllegalVersionResponseTypeException) {
comment = getStringResource(R.string.omnipod_driver_error_invalid_response);
} else if (ex instanceof IllegalResponseException) {
comment = getStringResource(R.string.omnipod_driver_error_invalid_response);
} else if (ex instanceof IllegalMessageSequenceNumberException) {
comment = getStringResource(R.string.omnipod_driver_error_invalid_message_sequence_number);
} else if (ex instanceof IllegalMessageAddressException) {
comment = getStringResource(R.string.omnipod_driver_error_invalid_message_address);
} else if (ex instanceof MessageDecodingException) {
comment = getStringResource(R.string.omnipod_driver_error_message_decoding_failed);
} else if (ex instanceof NonceOutOfSyncException) {
comment = getStringResource(R.string.omnipod_driver_error_nonce_out_of_sync);
} else if (ex instanceof NonceResyncException) {
comment = getStringResource(R.string.omnipod_driver_error_nonce_resync_failed);
} else if (ex instanceof NotEnoughDataException) {
comment = getStringResource(R.string.omnipod_driver_error_not_enough_data);
} else if (ex instanceof PodFaultException) {
FaultEventCode faultEventCode = ((PodFaultException) ex).getFaultEvent().getFaultEventCode();
showPodFaultErrorDialog(faultEventCode);
comment = createPodFaultErrorMessage(faultEventCode);
} else if (ex instanceof PodReturnedErrorResponseException) {
comment = getStringResource(R.string.omnipod_driver_error_pod_returned_error_response);
} else {
// Shouldn't be reachable
comment = getStringResource(R.string.omnipod_driver_error_unexpected_exception_type, ex.getClass().getName());
}
aapsLogger.error(LTag.PUMP, String.format("Caught OmnipodException[certainFailure=%s] from OmnipodManager (user-friendly error message: %s)", ((OmnipodException) ex).isCertainFailure(), comment), ex);
} else {
comment = getStringResource(R.string.omnipod_driver_error_unexpected_exception_type, ex.getClass().getName());
aapsLogger.error(LTag.PUMP, String.format("Caught unexpected exception type[certainFailure=false] from OmnipodManager (user-friendly error message: %s)", comment), ex);
}
return comment;
}
private String createPodFaultErrorMessage(FaultEventCode faultEventCode) {
String comment;
comment = getStringResource(R.string.omnipod_driver_error_pod_fault,
ByteUtil.convertUnsignedByteToInt(faultEventCode.getValue()), faultEventCode.name());
return comment;
}
private void sendEvent(Event event) {
rxBus.send(event);
}
private void showPodFaultErrorDialog(FaultEventCode faultEventCode) {
showErrorDialog(createPodFaultErrorMessage(faultEventCode), null);
}
private void showPodFaultErrorDialog(FaultEventCode faultEventCode, Integer sound) {
showErrorDialog(createPodFaultErrorMessage(faultEventCode), sound);
}
private void showErrorDialog(String message) {
showErrorDialog(message, null);
}
private void showErrorDialog(String message, Integer sound) {
Intent intent = new Intent(context, ErrorHelperActivity.class);
intent.putExtra("soundid", sound);
intent.putExtra("status", message);
intent.putExtra("title", resourceHelper.gs(R.string.error));
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(intent);
}
private void showNotification(String message, int urgency, Integer sound) {
Notification notification = new Notification( //
Notification.OMNIPOD_PUMP_ALARM, //
message, //
urgency);
if (sound != null) {
notification.soundId = sound;
}
sendEvent(new EventNewNotification(notification));
}
private boolean isBolusBeepsEnabled() {
return this.pumpStatus.beepBolusEnabled;
}
private boolean isSmbBeepsEnabled() {
return this.pumpStatus.beepSMBEnabled;
}
private boolean isBasalBeepsEnabled() {
return this.pumpStatus.beepBasalEnabled;
}
private boolean isTempBasalBeepsEnabled() {
return this.pumpStatus.beepTBREnabled;
}
private String getStringResource(int id, Object... args) {
return resourceHelper.gs(id, args);
}
static BasalSchedule mapProfileToBasalSchedule(Profile profile) {
if (profile == null) {
throw new IllegalArgumentException("Profile can not be null");
}
Profile.ProfileValue[] basalValues = profile.getBasalValues();
if (basalValues == null) {
throw new IllegalArgumentException("Basal values can not be null");
}
List<BasalScheduleEntry> entries = new ArrayList<>();
for (Profile.ProfileValue basalValue : basalValues) {
entries.add(new BasalScheduleEntry(PumpType.Insulet_Omnipod.determineCorrectBasalSize(basalValue.value),
Duration.standardSeconds(basalValue.timeAsSeconds)));
}
return new BasalSchedule(entries);
}
}

View file

@ -1,108 +0,0 @@
package info.nightscout.androidaps.plugins.pump.omnipod.driver.comm;
import java.util.Date;
import java.util.Objects;
import javax.inject.Inject;
import javax.inject.Singleton;
import info.nightscout.androidaps.events.Event;
import info.nightscout.androidaps.events.EventRefreshOverview;
import info.nightscout.androidaps.logging.AAPSLogger;
import info.nightscout.androidaps.plugins.bus.RxBusWrapper;
import info.nightscout.androidaps.plugins.pump.common.defs.PumpStatusType;
import info.nightscout.androidaps.plugins.pump.omnipod.defs.state.PodStateManager;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.OmnipodPumpStatus;
import info.nightscout.androidaps.plugins.pump.omnipod.events.EventOmnipodPumpValuesChanged;
import info.nightscout.androidaps.plugins.pump.omnipod.util.OmnipodConst;
import info.nightscout.androidaps.utils.DateUtil;
import info.nightscout.androidaps.utils.resources.ResourceHelper;
import info.nightscout.androidaps.utils.sharedPreferences.SP;
@Singleton
public class AapsPodStateManager extends PodStateManager {
private final AAPSLogger aapsLogger;
private final SP sp;
private final OmnipodPumpStatus omnipodPumpStatus;
private final RxBusWrapper rxBus;
@Inject
public AapsPodStateManager(AAPSLogger aapsLogger, SP sp, OmnipodPumpStatus omnipodPumpStatus,
RxBusWrapper rxBus) {
super(aapsLogger);
if (aapsLogger == null) {
throw new IllegalArgumentException("aapsLogger can not be null");
}
if (sp == null) {
throw new IllegalArgumentException("sp can not be null");
}
if (omnipodPumpStatus == null) {
throw new IllegalArgumentException("omnipodPumpStatus can not be null");
}
if (rxBus == null) {
throw new IllegalArgumentException("rxBus can not be null");
}
this.aapsLogger = aapsLogger;
this.sp = sp;
this.omnipodPumpStatus = omnipodPumpStatus;
this.rxBus = rxBus;
}
@Override
protected String readPodState() {
return sp.getString(OmnipodConst.Prefs.PodState, "");
}
@Override
protected void storePodState(String podState) {
sp.putString(OmnipodConst.Prefs.PodState, podState);
}
@Override
protected void notifyPodStateChanged() {
if (!hasPodState()) {
omnipodPumpStatus.lastBolusTime = null;
omnipodPumpStatus.lastBolusAmount = null;
omnipodPumpStatus.reservoirRemainingUnits = 0.0;
// TODO this does not seem to set the pump status to suspended anymore
// Also, verify that AAPS is aware that no insulin is delivered anymore at this point
omnipodPumpStatus.pumpStatusType = PumpStatusType.Suspended;
sendEvent(new EventRefreshOverview("Omnipod Pump", false));
} else {
Date lastBolusStartTime = getLastBolusStartTime() == null ? null : getLastBolusStartTime().toDate();
Double lastBolusAmount = getLastBolusAmount();
// Update other info: last bolus, units remaining, suspended
boolean suspended = isSuspended() || !isPodRunning();
if (Objects.equals(lastBolusStartTime, omnipodPumpStatus.lastBolusTime) //
|| !Objects.equals(lastBolusAmount, omnipodPumpStatus.lastBolusAmount) //
|| !isReservoirStatusUpToDate(omnipodPumpStatus, getReservoirLevel())
|| suspended != PumpStatusType.Suspended.equals(omnipodPumpStatus.pumpStatusType)) {
omnipodPumpStatus.lastBolusTime = lastBolusStartTime;
omnipodPumpStatus.lastBolusAmount = lastBolusAmount;
omnipodPumpStatus.reservoirRemainingUnits = getReservoirLevel() == null ? 75.0 : getReservoirLevel();
boolean sendRefreshOverviewEvent = suspended != PumpStatusType.Suspended.equals(omnipodPumpStatus.pumpStatusType);
// TODO this does not seem to set the pump status to suspended anymore
// Also, verify that AAPS is aware that no insulin is delivered anymore at this point
omnipodPumpStatus.pumpStatusType = suspended ? PumpStatusType.Suspended : PumpStatusType.Running;
if (sendRefreshOverviewEvent) {
sendEvent(new EventRefreshOverview("Omnipod Pump", false));
}
}
}
sendEvent(new EventOmnipodPumpValuesChanged());
}
private static boolean isReservoirStatusUpToDate(OmnipodPumpStatus pumpStatus, Double unitsRemaining) {
double expectedUnitsRemaining = unitsRemaining == null ? 75.0 : unitsRemaining;
return Math.abs(expectedUnitsRemaining - pumpStatus.reservoirRemainingUnits) < 0.000001;
}
private void sendEvent(Event event) {
rxBus.send(event);
}
}

View file

@ -1,14 +1,14 @@
package info.nightscout.androidaps.plugins.pump.omnipod.comm.action;
package info.nightscout.androidaps.plugins.pump.omnipod.driver.communication.action;
import java.util.Collections;
import info.nightscout.androidaps.plugins.pump.omnipod.comm.OmnipodCommunicationManager;
import info.nightscout.androidaps.plugins.pump.omnipod.comm.exception.ActionInitializationException;
import info.nightscout.androidaps.plugins.pump.omnipod.comm.message.command.AcknowledgeAlertsCommand;
import info.nightscout.androidaps.plugins.pump.omnipod.comm.message.response.StatusResponse;
import info.nightscout.androidaps.plugins.pump.omnipod.defs.AlertSet;
import info.nightscout.androidaps.plugins.pump.omnipod.defs.AlertSlot;
import info.nightscout.androidaps.plugins.pump.omnipod.defs.state.PodStateManager;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.communication.message.command.AcknowledgeAlertsCommand;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.communication.message.response.StatusResponse;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.definition.AlertSet;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.definition.AlertSlot;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.exception.ActionInitializationException;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.manager.PodStateManager;
import info.nightscout.androidaps.plugins.pump.omnipod.rileylink.manager.OmnipodRileyLinkCommunicationManager;
public class AcknowledgeAlertsAction implements OmnipodAction<StatusResponse> {
private final PodStateManager podStateManager;
@ -32,7 +32,7 @@ public class AcknowledgeAlertsAction implements OmnipodAction<StatusResponse> {
}
@Override
public StatusResponse execute(OmnipodCommunicationManager communicationService) {
public StatusResponse execute(OmnipodRileyLinkCommunicationManager communicationService) {
return communicationService.sendCommand(StatusResponse.class, podStateManager,
new AcknowledgeAlertsCommand(podStateManager.getCurrentNonce(), alerts));
}

View file

@ -1,20 +1,20 @@
package info.nightscout.androidaps.plugins.pump.omnipod.comm.action;
package info.nightscout.androidaps.plugins.pump.omnipod.driver.communication.action;
import org.joda.time.DateTimeZone;
import java.util.Collections;
import java.util.Random;
import info.nightscout.androidaps.plugins.pump.omnipod.comm.OmnipodCommunicationManager;
import info.nightscout.androidaps.plugins.pump.omnipod.comm.exception.IllegalMessageAddressException;
import info.nightscout.androidaps.plugins.pump.omnipod.comm.exception.IllegalPodProgressException;
import info.nightscout.androidaps.plugins.pump.omnipod.comm.exception.IllegalVersionResponseTypeException;
import info.nightscout.androidaps.plugins.pump.omnipod.comm.message.OmnipodMessage;
import info.nightscout.androidaps.plugins.pump.omnipod.comm.message.command.AssignAddressCommand;
import info.nightscout.androidaps.plugins.pump.omnipod.comm.message.response.VersionResponse;
import info.nightscout.androidaps.plugins.pump.omnipod.defs.PodProgressStatus;
import info.nightscout.androidaps.plugins.pump.omnipod.defs.state.PodStateManager;
import info.nightscout.androidaps.plugins.pump.omnipod.util.OmnipodConst;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.communication.message.OmnipodMessage;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.communication.message.command.AssignAddressCommand;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.communication.message.response.VersionResponse;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.definition.OmnipodConstants;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.definition.PodProgressStatus;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.exception.IllegalMessageAddressException;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.exception.IllegalPodProgressException;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.exception.IllegalVersionResponseTypeException;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.manager.PodStateManager;
import info.nightscout.androidaps.plugins.pump.omnipod.rileylink.manager.OmnipodRileyLinkCommunicationManager;
public class AssignAddressAction implements OmnipodAction<VersionResponse> {
private final PodStateManager podStateManager;
@ -27,7 +27,7 @@ public class AssignAddressAction implements OmnipodAction<VersionResponse> {
}
@Override
public VersionResponse execute(OmnipodCommunicationManager communicationService) {
public VersionResponse execute(OmnipodRileyLinkCommunicationManager communicationService) {
if (!podStateManager.hasPodState()) {
podStateManager.initState(generateRandomAddress());
}
@ -36,11 +36,11 @@ public class AssignAddressAction implements OmnipodAction<VersionResponse> {
}
AssignAddressCommand assignAddress = new AssignAddressCommand(podStateManager.getAddress());
OmnipodMessage assignAddressMessage = new OmnipodMessage(OmnipodConst.DEFAULT_ADDRESS,
OmnipodMessage assignAddressMessage = new OmnipodMessage(OmnipodConstants.DEFAULT_ADDRESS,
Collections.singletonList(assignAddress), podStateManager.getMessageNumber());
VersionResponse assignAddressResponse = communicationService.exchangeMessages(VersionResponse.class, podStateManager, assignAddressMessage,
OmnipodConst.DEFAULT_ADDRESS, podStateManager.getAddress());
OmnipodConstants.DEFAULT_ADDRESS, podStateManager.getAddress());
if (!assignAddressResponse.isAssignAddressVersionResponse()) {
throw new IllegalVersionResponseTypeException("assignAddress", "setupPod");

View file

@ -1,17 +1,17 @@
package info.nightscout.androidaps.plugins.pump.omnipod.comm.action;
package info.nightscout.androidaps.plugins.pump.omnipod.driver.communication.action;
import org.joda.time.Duration;
import java.util.Arrays;
import info.nightscout.androidaps.plugins.pump.omnipod.comm.OmnipodCommunicationManager;
import info.nightscout.androidaps.plugins.pump.omnipod.comm.exception.ActionInitializationException;
import info.nightscout.androidaps.plugins.pump.omnipod.comm.message.OmnipodMessage;
import info.nightscout.androidaps.plugins.pump.omnipod.comm.message.command.BolusExtraCommand;
import info.nightscout.androidaps.plugins.pump.omnipod.comm.message.command.SetInsulinScheduleCommand;
import info.nightscout.androidaps.plugins.pump.omnipod.comm.message.response.StatusResponse;
import info.nightscout.androidaps.plugins.pump.omnipod.defs.schedule.BolusDeliverySchedule;
import info.nightscout.androidaps.plugins.pump.omnipod.defs.state.PodStateManager;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.communication.message.OmnipodMessage;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.communication.message.command.BolusExtraCommand;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.communication.message.command.SetInsulinScheduleCommand;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.communication.message.response.StatusResponse;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.definition.schedule.BolusDeliverySchedule;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.exception.ActionInitializationException;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.manager.PodStateManager;
import info.nightscout.androidaps.plugins.pump.omnipod.rileylink.manager.OmnipodRileyLinkCommunicationManager;
public class BolusAction implements OmnipodAction<StatusResponse> {
private final PodStateManager podStateManager;
@ -40,14 +40,14 @@ public class BolusAction implements OmnipodAction<StatusResponse> {
}
@Override
public StatusResponse execute(OmnipodCommunicationManager communicationService) {
public StatusResponse execute(OmnipodRileyLinkCommunicationManager communicationService) {
BolusDeliverySchedule bolusDeliverySchedule = new BolusDeliverySchedule(units, timeBetweenPulses);
SetInsulinScheduleCommand setInsulinScheduleCommand = new SetInsulinScheduleCommand(
podStateManager.getCurrentNonce(), bolusDeliverySchedule);
BolusExtraCommand bolusExtraCommand = new BolusExtraCommand(units, timeBetweenPulses,
acknowledgementBeep, completionBeep);
OmnipodMessage primeBolusMessage = new OmnipodMessage(podStateManager.getAddress(),
OmnipodMessage bolusMessage = new OmnipodMessage(podStateManager.getAddress(),
Arrays.asList(setInsulinScheduleCommand, bolusExtraCommand), podStateManager.getMessageNumber());
return communicationService.exchangeMessages(StatusResponse.class, podStateManager, primeBolusMessage);
return communicationService.exchangeMessages(StatusResponse.class, podStateManager, bolusMessage);
}
}

View file

@ -1,18 +1,18 @@
package info.nightscout.androidaps.plugins.pump.omnipod.comm.action;
package info.nightscout.androidaps.plugins.pump.omnipod.driver.communication.action;
import java.util.ArrayList;
import java.util.EnumSet;
import java.util.List;
import info.nightscout.androidaps.plugins.pump.omnipod.comm.OmnipodCommunicationManager;
import info.nightscout.androidaps.plugins.pump.omnipod.comm.exception.ActionInitializationException;
import info.nightscout.androidaps.plugins.pump.omnipod.comm.message.MessageBlock;
import info.nightscout.androidaps.plugins.pump.omnipod.comm.message.OmnipodMessage;
import info.nightscout.androidaps.plugins.pump.omnipod.comm.message.command.CancelDeliveryCommand;
import info.nightscout.androidaps.plugins.pump.omnipod.comm.message.response.StatusResponse;
import info.nightscout.androidaps.plugins.pump.omnipod.defs.BeepType;
import info.nightscout.androidaps.plugins.pump.omnipod.defs.DeliveryType;
import info.nightscout.androidaps.plugins.pump.omnipod.defs.state.PodStateManager;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.communication.message.MessageBlock;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.communication.message.OmnipodMessage;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.communication.message.command.CancelDeliveryCommand;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.communication.message.response.StatusResponse;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.definition.BeepType;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.definition.DeliveryType;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.exception.ActionInitializationException;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.manager.PodStateManager;
import info.nightscout.androidaps.plugins.pump.omnipod.rileylink.manager.OmnipodRileyLinkCommunicationManager;
public class CancelDeliveryAction implements OmnipodAction<StatusResponse> {
private final PodStateManager podStateManager;
@ -33,7 +33,7 @@ public class CancelDeliveryAction implements OmnipodAction<StatusResponse> {
}
@Override
public StatusResponse execute(OmnipodCommunicationManager communicationService) {
public StatusResponse execute(OmnipodRileyLinkCommunicationManager communicationService) {
List<MessageBlock> messageBlocks = new ArrayList<>();
if (acknowledgementBeep && deliveryTypes.size() > 1) {
@ -52,9 +52,7 @@ public class CancelDeliveryAction implements OmnipodAction<StatusResponse> {
StatusResponse statusResponse = communicationService.exchangeMessages(StatusResponse.class, podStateManager,
new OmnipodMessage(podStateManager.getAddress(), messageBlocks, podStateManager.getMessageNumber()));
if (deliveryTypes.contains(DeliveryType.TEMP_BASAL)) {
podStateManager.setLastTempBasal(null, null, null);
}
return statusResponse;
}
}

View file

@ -0,0 +1,44 @@
package info.nightscout.androidaps.plugins.pump.omnipod.driver.communication.action;
import java.util.List;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.communication.message.command.ConfigureAlertsCommand;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.communication.message.response.StatusResponse;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.definition.AlertConfiguration;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.exception.ActionInitializationException;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.manager.PodStateManager;
import info.nightscout.androidaps.plugins.pump.omnipod.rileylink.manager.OmnipodRileyLinkCommunicationManager;
public class ConfigureAlertsAction implements OmnipodAction<StatusResponse> {
private final PodStateManager podStateManager;
private final List<AlertConfiguration> alertConfigurations;
public ConfigureAlertsAction(PodStateManager podStateManager, List<AlertConfiguration> alertConfigurations) {
if (podStateManager == null) {
throw new ActionInitializationException("Pod state manager cannot be null");
}
if (alertConfigurations == null) {
throw new ActionInitializationException("Alert configurations cannot be null");
}
this.podStateManager = podStateManager;
this.alertConfigurations = alertConfigurations;
}
@Override
public StatusResponse execute(OmnipodRileyLinkCommunicationManager communicationService) {
ConfigureAlertsCommand configureAlertsCommand = new ConfigureAlertsCommand(podStateManager.getCurrentNonce(), alertConfigurations);
StatusResponse statusResponse = communicationService.sendCommand(StatusResponse.class, podStateManager, configureAlertsCommand);
updateConfiguredAlerts(podStateManager, alertConfigurations);
return statusResponse;
}
public static void updateConfiguredAlerts(PodStateManager podStateManager, List<AlertConfiguration> alertConfigurations) {
for (AlertConfiguration alertConfiguration : alertConfigurations) {
if (alertConfiguration.isActive()) {
podStateManager.putConfiguredAlert(alertConfiguration.getAlertSlot(), alertConfiguration.getAlertType());
} else {
podStateManager.removeConfiguredAlert(alertConfiguration.getAlertSlot());
}
}
}
}

View file

@ -1,14 +1,14 @@
package info.nightscout.androidaps.plugins.pump.omnipod.comm.action;
package info.nightscout.androidaps.plugins.pump.omnipod.driver.communication.action;
import java.util.EnumSet;
import info.nightscout.androidaps.plugins.pump.omnipod.comm.OmnipodCommunicationManager;
import info.nightscout.androidaps.plugins.pump.omnipod.comm.exception.ActionInitializationException;
import info.nightscout.androidaps.plugins.pump.omnipod.comm.exception.PodFaultException;
import info.nightscout.androidaps.plugins.pump.omnipod.comm.message.command.DeactivatePodCommand;
import info.nightscout.androidaps.plugins.pump.omnipod.comm.message.response.StatusResponse;
import info.nightscout.androidaps.plugins.pump.omnipod.defs.DeliveryType;
import info.nightscout.androidaps.plugins.pump.omnipod.defs.state.PodStateManager;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.communication.message.command.DeactivatePodCommand;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.communication.message.response.StatusResponse;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.definition.DeliveryType;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.exception.ActionInitializationException;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.exception.PodFaultException;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.manager.PodStateManager;
import info.nightscout.androidaps.plugins.pump.omnipod.rileylink.manager.OmnipodRileyLinkCommunicationManager;
public class DeactivatePodAction implements OmnipodAction<StatusResponse> {
private final PodStateManager podStateManager;
@ -23,8 +23,8 @@ public class DeactivatePodAction implements OmnipodAction<StatusResponse> {
}
@Override
public StatusResponse execute(OmnipodCommunicationManager communicationService) {
if (!podStateManager.isSuspended() && !podStateManager.hasFaultEvent()) {
public StatusResponse execute(OmnipodRileyLinkCommunicationManager communicationService) {
if (!podStateManager.isSuspended() && !podStateManager.isPodFaulted()) {
try {
communicationService.executeAction(new CancelDeliveryAction(podStateManager,
EnumSet.allOf(DeliveryType.class), acknowledgementBeep));

View file

@ -0,0 +1,29 @@
package info.nightscout.androidaps.plugins.pump.omnipod.driver.communication.action;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.communication.message.command.GetStatusCommand;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.communication.message.response.podinfo.PodInfoResponse;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.definition.PodInfoType;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.exception.ActionInitializationException;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.manager.PodStateManager;
import info.nightscout.androidaps.plugins.pump.omnipod.rileylink.manager.OmnipodRileyLinkCommunicationManager;
public class GetPodInfoAction implements OmnipodAction<PodInfoResponse> {
private final PodStateManager podStateManager;
private final PodInfoType podInfoType;
public GetPodInfoAction(PodStateManager podStateManager, PodInfoType podInfoType) {
if (podStateManager == null) {
throw new ActionInitializationException("Pod state manager cannot be null");
}
if (podInfoType == null) {
throw new ActionInitializationException("Pod info type cannot be null");
}
this.podStateManager = podStateManager;
this.podInfoType = podInfoType;
}
@Override
public PodInfoResponse execute(OmnipodRileyLinkCommunicationManager communicationService) {
return communicationService.sendCommand(PodInfoResponse.class, podStateManager, new GetStatusCommand(podInfoType));
}
}

View file

@ -0,0 +1,24 @@
package info.nightscout.androidaps.plugins.pump.omnipod.driver.communication.action;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.communication.message.command.GetStatusCommand;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.communication.message.response.StatusResponse;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.definition.PodInfoType;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.exception.ActionInitializationException;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.manager.PodStateManager;
import info.nightscout.androidaps.plugins.pump.omnipod.rileylink.manager.OmnipodRileyLinkCommunicationManager;
public class GetStatusAction implements OmnipodAction<StatusResponse> {
private final PodStateManager podStateManager;
public GetStatusAction(PodStateManager podState) {
if (podState == null) {
throw new ActionInitializationException("Pod state manager cannot be null");
}
this.podStateManager = podState;
}
@Override
public StatusResponse execute(OmnipodRileyLinkCommunicationManager communicationService) {
return communicationService.sendCommand(StatusResponse.class, podStateManager, new GetStatusCommand(PodInfoType.NORMAL));
}
}

View file

@ -0,0 +1,75 @@
package info.nightscout.androidaps.plugins.pump.omnipod.driver.communication.action;
import org.joda.time.Duration;
import java.util.List;
import java.util.Optional;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.communication.action.service.ExpirationReminderBuilder;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.communication.message.response.StatusResponse;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.definition.AlertConfiguration;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.definition.OmnipodConstants;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.definition.PodProgressStatus;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.definition.schedule.BasalSchedule;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.exception.ActionInitializationException;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.exception.IllegalPodProgressException;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.manager.PodStateManager;
import info.nightscout.androidaps.plugins.pump.omnipod.rileylink.manager.OmnipodRileyLinkCommunicationManager;
public class InsertCannulaAction implements OmnipodAction<StatusResponse> {
private final PodStateManager podStateManager;
private final BasalSchedule initialBasalSchedule;
private final Duration expirationReminderTimeBeforeShutdown;
private final Integer lowReservoirAlertUnits;
public InsertCannulaAction(PodStateManager podStateManager, BasalSchedule initialBasalSchedule,
Duration expirationReminderTimeBeforeShutdown, Integer lowReservoirAlertUnits) {
if (podStateManager == null) {
throw new ActionInitializationException("Pod state manager cannot be null");
}
if (initialBasalSchedule == null) {
throw new ActionInitializationException("Initial basal schedule cannot be null");
}
this.podStateManager = podStateManager;
this.initialBasalSchedule = initialBasalSchedule;
this.expirationReminderTimeBeforeShutdown = expirationReminderTimeBeforeShutdown;
this.lowReservoirAlertUnits = lowReservoirAlertUnits;
}
@Override
public StatusResponse execute(OmnipodRileyLinkCommunicationManager communicationService) {
if (!podStateManager.isPodInitialized() || podStateManager.getPodProgressStatus().isBefore(PodProgressStatus.PRIMING_COMPLETED)) {
throw new IllegalPodProgressException(PodProgressStatus.PRIMING_COMPLETED, podStateManager.isPodInitialized() ? podStateManager.getPodProgressStatus() : null);
}
if (podStateManager.getPodProgressStatus().isBefore(PodProgressStatus.BASAL_INITIALIZED)) {
podStateManager.setBasalSchedule(initialBasalSchedule);
communicationService.executeAction(new SetBasalScheduleAction(podStateManager, initialBasalSchedule,
true, podStateManager.getScheduleOffset(), false));
}
if (podStateManager.getPodProgressStatus().isBefore(PodProgressStatus.INSERTING_CANNULA)) {
communicationService.executeAction(new ConfigureAlertsAction(podStateManager, buildAlertConfigurations()));
podStateManager.setExpirationAlertTimeBeforeShutdown(expirationReminderTimeBeforeShutdown);
podStateManager.setLowReservoirAlertUnits(lowReservoirAlertUnits);
return communicationService.executeAction(new BolusAction(podStateManager, OmnipodConstants.POD_CANNULA_INSERTION_BOLUS_UNITS,
Duration.standardSeconds(1), false, false));
} else if (podStateManager.getPodProgressStatus().equals(PodProgressStatus.INSERTING_CANNULA)) {
// Check status
return communicationService.executeAction(new GetStatusAction(podStateManager));
} else {
throw new IllegalPodProgressException(null, podStateManager.getPodProgressStatus());
}
}
private List<AlertConfiguration> buildAlertConfigurations() {
ExpirationReminderBuilder builder = new ExpirationReminderBuilder(podStateManager).defaults();
builder.expirationAdvisory(expirationReminderTimeBeforeShutdown != null,
Optional.ofNullable(expirationReminderTimeBeforeShutdown).orElse(Duration.ZERO));
builder.lowReservoir(lowReservoirAlertUnits != null, Optional.ofNullable(lowReservoirAlertUnits).orElse(0));
return builder.build();
}
}

View file

@ -0,0 +1,7 @@
package info.nightscout.androidaps.plugins.pump.omnipod.driver.communication.action;
import info.nightscout.androidaps.plugins.pump.omnipod.rileylink.manager.OmnipodRileyLinkCommunicationManager;
public interface OmnipodAction<T> {
T execute(OmnipodRileyLinkCommunicationManager communicationService);
}

View file

@ -1,12 +1,12 @@
package info.nightscout.androidaps.plugins.pump.omnipod.comm.action;
package info.nightscout.androidaps.plugins.pump.omnipod.driver.communication.action;
import info.nightscout.androidaps.plugins.pump.omnipod.comm.OmnipodCommunicationManager;
import info.nightscout.androidaps.plugins.pump.omnipod.comm.action.service.PrimeService;
import info.nightscout.androidaps.plugins.pump.omnipod.comm.exception.ActionInitializationException;
import info.nightscout.androidaps.plugins.pump.omnipod.comm.exception.IllegalPodProgressException;
import info.nightscout.androidaps.plugins.pump.omnipod.comm.message.response.StatusResponse;
import info.nightscout.androidaps.plugins.pump.omnipod.defs.PodProgressStatus;
import info.nightscout.androidaps.plugins.pump.omnipod.defs.state.PodStateManager;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.communication.action.service.PrimeService;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.communication.message.response.StatusResponse;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.definition.PodProgressStatus;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.exception.ActionInitializationException;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.exception.IllegalPodProgressException;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.manager.PodStateManager;
import info.nightscout.androidaps.plugins.pump.omnipod.rileylink.manager.OmnipodRileyLinkCommunicationManager;
public class PrimeAction implements OmnipodAction<StatusResponse> {
@ -25,12 +25,14 @@ public class PrimeAction implements OmnipodAction<StatusResponse> {
}
@Override
public StatusResponse execute(OmnipodCommunicationManager communicationService) {
public StatusResponse execute(OmnipodRileyLinkCommunicationManager communicationService) {
if (!podStateManager.isPodInitialized() || podStateManager.getPodProgressStatus().isBefore(PodProgressStatus.PAIRING_COMPLETED)) {
throw new IllegalPodProgressException(PodProgressStatus.PAIRING_COMPLETED, podStateManager.isPodInitialized() ? podStateManager.getPodProgressStatus() : null);
}
if (podStateManager.getPodProgressStatus().isBefore(PodProgressStatus.PRIMING)) {
service.executeDisableTab5Sub16FaultConfigCommand(communicationService, podStateManager);
// FaultConfigCommand sets internal pod variables to effectively disable $6x faults which occur more often with a 0 TBR
service.executeDisableTab5Sub16And17FaultConfigCommand(communicationService, podStateManager);
service.executeFinishSetupReminderAlertCommand(communicationService, podStateManager);
return service.executePrimeBolusCommand(communicationService, podStateManager);
} else if (podStateManager.getPodProgressStatus().equals(PodProgressStatus.PRIMING)) {

View file

@ -1,17 +1,17 @@
package info.nightscout.androidaps.plugins.pump.omnipod.comm.action;
package info.nightscout.androidaps.plugins.pump.omnipod.driver.communication.action;
import org.joda.time.Duration;
import java.util.Arrays;
import info.nightscout.androidaps.plugins.pump.omnipod.comm.OmnipodCommunicationManager;
import info.nightscout.androidaps.plugins.pump.omnipod.comm.exception.ActionInitializationException;
import info.nightscout.androidaps.plugins.pump.omnipod.comm.message.OmnipodMessage;
import info.nightscout.androidaps.plugins.pump.omnipod.comm.message.command.BasalScheduleExtraCommand;
import info.nightscout.androidaps.plugins.pump.omnipod.comm.message.command.SetInsulinScheduleCommand;
import info.nightscout.androidaps.plugins.pump.omnipod.comm.message.response.StatusResponse;
import info.nightscout.androidaps.plugins.pump.omnipod.defs.schedule.BasalSchedule;
import info.nightscout.androidaps.plugins.pump.omnipod.defs.state.PodStateManager;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.communication.message.OmnipodMessage;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.communication.message.command.BasalScheduleExtraCommand;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.communication.message.command.SetInsulinScheduleCommand;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.communication.message.response.StatusResponse;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.definition.schedule.BasalSchedule;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.exception.ActionInitializationException;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.manager.PodStateManager;
import info.nightscout.androidaps.plugins.pump.omnipod.rileylink.manager.OmnipodRileyLinkCommunicationManager;
public class SetBasalScheduleAction implements OmnipodAction<StatusResponse> {
private final PodStateManager podStateManager;
@ -39,15 +39,13 @@ public class SetBasalScheduleAction implements OmnipodAction<StatusResponse> {
}
@Override
public StatusResponse execute(OmnipodCommunicationManager communicationService) {
public StatusResponse execute(OmnipodRileyLinkCommunicationManager communicationService) {
SetInsulinScheduleCommand setBasal = new SetInsulinScheduleCommand(podStateManager.getCurrentNonce(), basalSchedule, scheduleOffset);
BasalScheduleExtraCommand extraCommand = new BasalScheduleExtraCommand(basalSchedule, scheduleOffset,
acknowledgementBeep, confidenceReminder, Duration.ZERO);
OmnipodMessage basalMessage = new OmnipodMessage(podStateManager.getAddress(), Arrays.asList(setBasal, extraCommand),
podStateManager.getMessageNumber());
StatusResponse statusResponse = communicationService.exchangeMessages(StatusResponse.class, podStateManager, basalMessage);
podStateManager.setBasalSchedule(basalSchedule);
return statusResponse;
return communicationService.exchangeMessages(StatusResponse.class, podStateManager, basalMessage);
}
}

View file

@ -1,20 +1,18 @@
package info.nightscout.androidaps.plugins.pump.omnipod.comm.action;
package info.nightscout.androidaps.plugins.pump.omnipod.driver.communication.action;
import org.joda.time.DateTime;
import org.joda.time.Duration;
import java.util.Arrays;
import java.util.List;
import info.nightscout.androidaps.plugins.pump.omnipod.comm.OmnipodCommunicationManager;
import info.nightscout.androidaps.plugins.pump.omnipod.comm.exception.ActionInitializationException;
import info.nightscout.androidaps.plugins.pump.omnipod.comm.message.MessageBlock;
import info.nightscout.androidaps.plugins.pump.omnipod.comm.message.OmnipodMessage;
import info.nightscout.androidaps.plugins.pump.omnipod.comm.message.command.SetInsulinScheduleCommand;
import info.nightscout.androidaps.plugins.pump.omnipod.comm.message.command.TempBasalExtraCommand;
import info.nightscout.androidaps.plugins.pump.omnipod.comm.message.response.StatusResponse;
import info.nightscout.androidaps.plugins.pump.omnipod.defs.state.PodStateManager;
import info.nightscout.androidaps.plugins.pump.omnipod.util.OmnipodConst;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.communication.message.MessageBlock;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.communication.message.OmnipodMessage;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.communication.message.command.SetInsulinScheduleCommand;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.communication.message.command.TempBasalExtraCommand;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.communication.message.response.StatusResponse;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.exception.ActionInitializationException;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.manager.PodStateManager;
import info.nightscout.androidaps.plugins.pump.omnipod.rileylink.manager.OmnipodRileyLinkCommunicationManager;
public class SetTempBasalAction implements OmnipodAction<StatusResponse> {
private final PodStateManager podStateManager;
@ -39,14 +37,12 @@ public class SetTempBasalAction implements OmnipodAction<StatusResponse> {
}
@Override
public StatusResponse execute(OmnipodCommunicationManager communicationService) {
public StatusResponse execute(OmnipodRileyLinkCommunicationManager communicationService) {
List<MessageBlock> messageBlocks = Arrays.asList( //
new SetInsulinScheduleCommand(podStateManager.getCurrentNonce(), rate, duration),
new TempBasalExtraCommand(rate, duration, acknowledgementBeep, completionBeep, Duration.ZERO));
OmnipodMessage message = new OmnipodMessage(podStateManager.getAddress(), messageBlocks, podStateManager.getMessageNumber());
StatusResponse statusResponse = communicationService.exchangeMessages(StatusResponse.class, podStateManager, message);
podStateManager.setLastTempBasal(DateTime.now().minus(OmnipodConst.AVERAGE_TEMP_BASAL_COMMAND_COMMUNICATION_DURATION), rate, duration);
return statusResponse;
return communicationService.exchangeMessages(StatusResponse.class, podStateManager, message);
}
}

View file

@ -1,19 +1,19 @@
package info.nightscout.androidaps.plugins.pump.omnipod.comm.action;
package info.nightscout.androidaps.plugins.pump.omnipod.driver.communication.action;
import org.joda.time.DateTime;
import java.util.Collections;
import info.nightscout.androidaps.plugins.pump.omnipod.comm.OmnipodCommunicationManager;
import info.nightscout.androidaps.plugins.pump.omnipod.comm.exception.IllegalMessageAddressException;
import info.nightscout.androidaps.plugins.pump.omnipod.comm.exception.IllegalPodProgressException;
import info.nightscout.androidaps.plugins.pump.omnipod.comm.exception.IllegalVersionResponseTypeException;
import info.nightscout.androidaps.plugins.pump.omnipod.comm.message.OmnipodMessage;
import info.nightscout.androidaps.plugins.pump.omnipod.comm.message.command.SetupPodCommand;
import info.nightscout.androidaps.plugins.pump.omnipod.comm.message.response.VersionResponse;
import info.nightscout.androidaps.plugins.pump.omnipod.defs.PodProgressStatus;
import info.nightscout.androidaps.plugins.pump.omnipod.defs.state.PodStateManager;
import info.nightscout.androidaps.plugins.pump.omnipod.util.OmnipodConst;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.communication.message.OmnipodMessage;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.communication.message.command.SetupPodCommand;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.communication.message.response.VersionResponse;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.definition.OmnipodConstants;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.definition.PodProgressStatus;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.exception.IllegalMessageAddressException;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.exception.IllegalPodProgressException;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.exception.IllegalVersionResponseTypeException;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.manager.PodStateManager;
import info.nightscout.androidaps.plugins.pump.omnipod.rileylink.manager.OmnipodRileyLinkCommunicationManager;
public class SetupPodAction implements OmnipodAction<VersionResponse> {
private final PodStateManager podStateManager;
@ -26,7 +26,7 @@ public class SetupPodAction implements OmnipodAction<VersionResponse> {
}
@Override
public VersionResponse execute(OmnipodCommunicationManager communicationService) {
public VersionResponse execute(OmnipodRileyLinkCommunicationManager communicationService) {
if (!podStateManager.isPodInitialized() || !podStateManager.getPodProgressStatus().equals(PodProgressStatus.REMINDER_INITIALIZED)) {
throw new IllegalPodProgressException(PodProgressStatus.REMINDER_INITIALIZED, podStateManager.isPodInitialized() ? podStateManager.getPodProgressStatus() : null);
}
@ -34,11 +34,11 @@ public class SetupPodAction implements OmnipodAction<VersionResponse> {
SetupPodCommand setupPodCommand = new SetupPodCommand(podStateManager.getAddress(), activationDate,
podStateManager.getLot(), podStateManager.getTid());
OmnipodMessage message = new OmnipodMessage(OmnipodConst.DEFAULT_ADDRESS,
OmnipodMessage message = new OmnipodMessage(OmnipodConstants.DEFAULT_ADDRESS,
Collections.singletonList(setupPodCommand), podStateManager.getMessageNumber());
VersionResponse setupPodResponse;
setupPodResponse = communicationService.exchangeMessages(VersionResponse.class, podStateManager,
message, OmnipodConst.DEFAULT_ADDRESS, podStateManager.getAddress());
message, OmnipodConstants.DEFAULT_ADDRESS, podStateManager.getAddress());
if (!setupPodResponse.isSetupPodVersionResponse()) {
throw new IllegalVersionResponseTypeException("setupPod", "assignAddress");

View file

@ -0,0 +1,69 @@
package info.nightscout.androidaps.plugins.pump.omnipod.driver.communication.action.service;
import org.joda.time.DateTime;
import org.joda.time.Duration;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.definition.AlertConfiguration;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.definition.AlertSlot;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.definition.OmnipodConstants;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.manager.PodStateManager;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.util.AlertConfigurationUtil;
public final class ExpirationReminderBuilder {
private final Map<AlertSlot, AlertConfiguration> alerts = new HashMap<>();
private final DateTime endOfServiceTime;
private final PodStateManager podStateManager;
public ExpirationReminderBuilder(PodStateManager podStateManager) {
this.endOfServiceTime = podStateManager.getActivatedAt().plus(OmnipodConstants.SERVICE_DURATION);
this.podStateManager = podStateManager;
}
public ExpirationReminderBuilder defaults() {
DateTime shutdownImminentAlarmTime = endOfServiceTime.minus(OmnipodConstants.END_OF_SERVICE_IMMINENT_WINDOW);
if (DateTime.now().isBefore(shutdownImminentAlarmTime)) {
Duration timeUntilShutdownImminentAlarm = new Duration(DateTime.now(),
shutdownImminentAlarmTime);
AlertConfiguration shutdownImminentAlertConfiguration = AlertConfigurationUtil.createShutdownImminentAlertConfiguration(
timeUntilShutdownImminentAlarm);
alerts.put(shutdownImminentAlertConfiguration.getAlertSlot(), shutdownImminentAlertConfiguration);
}
AlertConfiguration autoOffAlertConfiguration = AlertConfigurationUtil.createAutoOffAlertConfiguration(
false, Duration.ZERO);
alerts.put(autoOffAlertConfiguration.getAlertSlot(), autoOffAlertConfiguration);
return this;
}
public ExpirationReminderBuilder expirationAdvisory(boolean active, Duration timeBeforeShutdown) {
DateTime expirationAdvisoryAlarmTime = endOfServiceTime.minus(timeBeforeShutdown);
if (DateTime.now().isBefore(expirationAdvisoryAlarmTime)) {
Duration timeUntilExpirationAdvisoryAlarm = new Duration(DateTime.now(),
expirationAdvisoryAlarmTime);
AlertConfiguration expirationAdvisoryAlertConfiguration = AlertConfigurationUtil.createExpirationAdvisoryAlertConfiguration(active,
timeUntilExpirationAdvisoryAlarm, timeBeforeShutdown);
alerts.put(expirationAdvisoryAlertConfiguration.getAlertSlot(), expirationAdvisoryAlertConfiguration);
}
return this;
}
public ExpirationReminderBuilder lowReservoir(boolean active, int units) {
if (podStateManager.getReservoirLevel() == null || podStateManager.getReservoirLevel().intValue() > units) {
AlertConfiguration lowReservoirAlertConfiguration = AlertConfigurationUtil.createLowReservoirAlertConfiguration(active, (double) units);
alerts.put(lowReservoirAlertConfiguration.getAlertSlot(), lowReservoirAlertConfiguration);
}
return this;
}
public List<AlertConfiguration> build() {
return new ArrayList<>(alerts.values());
}
}

View file

@ -0,0 +1,37 @@
package info.nightscout.androidaps.plugins.pump.omnipod.driver.communication.action.service;
import org.joda.time.Duration;
import java.util.Collections;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.communication.action.BolusAction;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.communication.action.ConfigureAlertsAction;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.communication.message.OmnipodMessage;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.communication.message.command.FaultConfigCommand;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.communication.message.response.StatusResponse;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.definition.AlertConfiguration;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.definition.OmnipodConstants;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.manager.PodStateManager;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.util.AlertConfigurationUtil;
import info.nightscout.androidaps.plugins.pump.omnipod.rileylink.manager.OmnipodRileyLinkCommunicationManager;
public class PrimeService {
public StatusResponse executeDisableTab5Sub16And17FaultConfigCommand(OmnipodRileyLinkCommunicationManager communicationService, PodStateManager podStateManager) {
FaultConfigCommand faultConfigCommand = new FaultConfigCommand(podStateManager.getCurrentNonce(), (byte) 0x00, (byte) 0x00);
OmnipodMessage faultConfigMessage = new OmnipodMessage(podStateManager.getAddress(),
Collections.singletonList(faultConfigCommand), podStateManager.getMessageNumber());
return communicationService.exchangeMessages(StatusResponse.class, podStateManager, faultConfigMessage);
}
public StatusResponse executeFinishSetupReminderAlertCommand(OmnipodRileyLinkCommunicationManager communicationService, PodStateManager podStateManager) {
AlertConfiguration finishSetupReminderAlertConfiguration = AlertConfigurationUtil.createFinishSetupReminderAlertConfiguration();
return communicationService.executeAction(new ConfigureAlertsAction(podStateManager,
Collections.singletonList(finishSetupReminderAlertConfiguration)));
}
public StatusResponse executePrimeBolusCommand(OmnipodRileyLinkCommunicationManager communicationService, PodStateManager podStateManager) {
return communicationService.executeAction(new BolusAction(podStateManager, OmnipodConstants.POD_PRIME_BOLUS_UNITS,
Duration.standardSeconds(1), false, false));
}
}

View file

@ -0,0 +1,5 @@
package info.nightscout.androidaps.plugins.pump.omnipod.driver.communication.message;
public interface IRawRepresentable {
byte[] getRawData();
}

View file

@ -1,14 +1,14 @@
package info.nightscout.androidaps.plugins.pump.omnipod.comm.message;
package info.nightscout.androidaps.plugins.pump.omnipod.driver.communication.message;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import info.nightscout.androidaps.plugins.pump.omnipod.defs.MessageBlockType;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.definition.MessageBlockType;
public abstract class MessageBlock {
protected byte[] encodedData = new byte[0];
public MessageBlock() {
protected MessageBlock() {
}
public abstract MessageBlockType getType();

View file

@ -1,4 +1,4 @@
package info.nightscout.androidaps.plugins.pump.omnipod.comm.message;
package info.nightscout.androidaps.plugins.pump.omnipod.driver.communication.message;
public abstract class NonceResyncableMessageBlock extends MessageBlock {
public abstract int getNonce();

View file

@ -1,16 +1,16 @@
package info.nightscout.androidaps.plugins.pump.omnipod.comm.message;
package info.nightscout.androidaps.plugins.pump.omnipod.driver.communication.message;
import java.util.ArrayList;
import java.util.List;
import info.nightscout.androidaps.plugins.pump.common.utils.ByteUtil;
import info.nightscout.androidaps.plugins.pump.omnipod.comm.exception.CrcMismatchException;
import info.nightscout.androidaps.plugins.pump.omnipod.comm.exception.MessageDecodingException;
import info.nightscout.androidaps.plugins.pump.omnipod.comm.exception.NotEnoughDataException;
import info.nightscout.androidaps.plugins.pump.omnipod.comm.message.command.GetStatusCommand;
import info.nightscout.androidaps.plugins.pump.omnipod.defs.MessageBlockType;
import info.nightscout.androidaps.plugins.pump.omnipod.defs.PodInfoType;
import info.nightscout.androidaps.plugins.pump.omnipod.util.OmniCRC;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.communication.message.command.GetStatusCommand;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.definition.MessageBlockType;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.definition.OmnipodCrc;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.definition.PodInfoType;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.exception.CrcMismatchException;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.exception.MessageDecodingException;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.exception.NotEnoughDataException;
public class OmnipodMessage {
@ -44,7 +44,7 @@ public class OmnipodMessage {
}
int sequenceNumber = (((int) b9 >> 2) & 0b11111);
int crc = ByteUtil.toInt(data[data.length - 2], data[data.length - 1]);
int calculatedCrc = OmniCRC.crc16(ByteUtil.substring(data, 0, data.length - 2));
int calculatedCrc = OmnipodCrc.crc16(ByteUtil.substring(data, 0, data.length - 2));
if (crc != calculatedCrc) {
throw new CrcMismatchException(calculatedCrc, crc);
}
@ -86,7 +86,7 @@ public class OmnipodMessage {
header = ByteUtil.concat(header, (byte) (((sequenceNumber & 0x1F) << 2) + ((encodedData.length >> 8) & 0x03)));
header = ByteUtil.concat(header, (byte) (encodedData.length & 0xFF));
encodedData = ByteUtil.concat(header, encodedData);
int crc = OmniCRC.crc16(encodedData);
int crc = OmnipodCrc.crc16(encodedData);
encodedData = ByteUtil.concat(encodedData, ByteUtil.substring(ByteUtil.getBytesFromInt(crc), 2, 2));
return encodedData;
}

View file

@ -1,11 +1,11 @@
package info.nightscout.androidaps.plugins.pump.omnipod.comm.message;
package info.nightscout.androidaps.plugins.pump.omnipod.driver.communication.message;
import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.ble.data.RLMessage;
import info.nightscout.androidaps.plugins.pump.common.utils.ByteUtil;
import info.nightscout.androidaps.plugins.pump.omnipod.comm.exception.CrcMismatchException;
import info.nightscout.androidaps.plugins.pump.omnipod.comm.exception.IllegalPacketTypeException;
import info.nightscout.androidaps.plugins.pump.omnipod.defs.PacketType;
import info.nightscout.androidaps.plugins.pump.omnipod.util.OmniCRC;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.definition.OmnipodCrc;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.definition.PacketType;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.exception.CrcMismatchException;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.exception.IllegalPacketTypeException;
/**
* Created by andy on 6/1/18.
@ -29,7 +29,7 @@ public class OmnipodPacket implements RLMessage {
throw new IllegalPacketTypeException(null, null);
}
this.sequenceNumber = (encoded[4] & 0b11111);
byte crc = OmniCRC.crc8(ByteUtil.substring(encoded, 0, encoded.length - 1));
byte crc = OmnipodCrc.crc8(ByteUtil.substring(encoded, 0, encoded.length - 1));
if (crc != encoded[encoded.length - 1]) {
throw new CrcMismatchException(crc, encoded[encoded.length - 1]);
}
@ -70,7 +70,7 @@ public class OmnipodPacket implements RLMessage {
output = ByteUtil.concat(output, ByteUtil.getBytesFromInt(this.packetAddress));
output = ByteUtil.concat(output, (byte) ((this.packetType.getValue() << 5) + (sequenceNumber & 0b11111)));
output = ByteUtil.concat(output, encodedMessage);
output = ByteUtil.concat(output, OmniCRC.crc8(output));
output = ByteUtil.concat(output, OmnipodCrc.crc8(output));
return output;
}

View file

@ -1,12 +1,12 @@
package info.nightscout.androidaps.plugins.pump.omnipod.comm.message.command;
package info.nightscout.androidaps.plugins.pump.omnipod.driver.communication.message.command;
import java.util.Collections;
import info.nightscout.androidaps.plugins.pump.common.utils.ByteUtil;
import info.nightscout.androidaps.plugins.pump.omnipod.comm.message.NonceResyncableMessageBlock;
import info.nightscout.androidaps.plugins.pump.omnipod.defs.AlertSet;
import info.nightscout.androidaps.plugins.pump.omnipod.defs.AlertSlot;
import info.nightscout.androidaps.plugins.pump.omnipod.defs.MessageBlockType;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.communication.message.NonceResyncableMessageBlock;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.definition.AlertSet;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.definition.AlertSlot;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.definition.MessageBlockType;
public class AcknowledgeAlertsCommand extends NonceResyncableMessageBlock {

View file

@ -1,9 +1,9 @@
package info.nightscout.androidaps.plugins.pump.omnipod.comm.message.command;
package info.nightscout.androidaps.plugins.pump.omnipod.driver.communication.message.command;
import java.nio.ByteBuffer;
import info.nightscout.androidaps.plugins.pump.omnipod.comm.message.MessageBlock;
import info.nightscout.androidaps.plugins.pump.omnipod.defs.MessageBlockType;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.communication.message.MessageBlock;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.definition.MessageBlockType;
public class AssignAddressCommand extends MessageBlock {
private final int address;

View file

@ -1,4 +1,4 @@
package info.nightscout.androidaps.plugins.pump.omnipod.comm.message.command;
package info.nightscout.androidaps.plugins.pump.omnipod.driver.communication.message.command;
import org.joda.time.Duration;
@ -6,11 +6,11 @@ import java.util.ArrayList;
import java.util.List;
import info.nightscout.androidaps.plugins.pump.common.utils.ByteUtil;
import info.nightscout.androidaps.plugins.pump.omnipod.comm.message.MessageBlock;
import info.nightscout.androidaps.plugins.pump.omnipod.defs.MessageBlockType;
import info.nightscout.androidaps.plugins.pump.omnipod.defs.schedule.BasalSchedule;
import info.nightscout.androidaps.plugins.pump.omnipod.defs.schedule.RateEntry;
import info.nightscout.androidaps.plugins.pump.omnipod.util.OmnipodConst;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.communication.message.MessageBlock;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.definition.MessageBlockType;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.definition.OmnipodConstants;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.definition.schedule.BasalSchedule;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.definition.schedule.RateEntry;
public class BasalScheduleExtraCommand extends MessageBlock {
private final boolean acknowledgementBeep;
@ -55,7 +55,7 @@ public class BasalScheduleExtraCommand extends MessageBlock {
currentEntryIndex = (byte) entryLookupResult.getIndex();
double timeRemainingInEntryInSeconds = entryLookupResult.getStartTime().minus(scheduleOffsetNearestSecond.minus(entryLookupResult.getDuration())).getMillis() / 1000.0;
double rate = mergedSchedule.rateAt(scheduleOffsetNearestSecond);
int pulsesPerHour = (int) Math.round(rate / OmnipodConst.POD_PULSE_SIZE);
int pulsesPerHour = (int) Math.round(rate / OmnipodConstants.POD_PULSE_SIZE);
double timeBetweenPulses = 3600.0 / pulsesPerHour;
delayUntilNextTenthOfPulseInSeconds = (timeRemainingInEntryInSeconds % (timeBetweenPulses / 10.0));
remainingPulses = pulsesPerHour * (timeRemainingInEntryInSeconds - delayUntilNextTenthOfPulseInSeconds) / 3600.0 + 0.1;

View file

@ -1,11 +1,11 @@
package info.nightscout.androidaps.plugins.pump.omnipod.comm.message.command;
package info.nightscout.androidaps.plugins.pump.omnipod.driver.communication.message.command;
import org.joda.time.Duration;
import info.nightscout.androidaps.plugins.pump.common.utils.ByteUtil;
import info.nightscout.androidaps.plugins.pump.omnipod.comm.message.MessageBlock;
import info.nightscout.androidaps.plugins.pump.omnipod.defs.BeepConfigType;
import info.nightscout.androidaps.plugins.pump.omnipod.defs.MessageBlockType;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.communication.message.MessageBlock;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.definition.BeepConfigType;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.definition.MessageBlockType;
public class BeepConfigCommand extends MessageBlock {
private final BeepConfigType beepType;

View file

@ -1,12 +1,12 @@
package info.nightscout.androidaps.plugins.pump.omnipod.comm.message.command;
package info.nightscout.androidaps.plugins.pump.omnipod.driver.communication.message.command;
import org.joda.time.Duration;
import info.nightscout.androidaps.plugins.pump.common.utils.ByteUtil;
import info.nightscout.androidaps.plugins.pump.omnipod.comm.exception.CommandInitializationException;
import info.nightscout.androidaps.plugins.pump.omnipod.comm.message.MessageBlock;
import info.nightscout.androidaps.plugins.pump.omnipod.defs.MessageBlockType;
import info.nightscout.androidaps.plugins.pump.omnipod.util.OmnipodConst;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.communication.message.MessageBlock;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.definition.MessageBlockType;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.definition.OmnipodConstants;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.exception.CommandInitializationException;
public class BolusExtraCommand extends MessageBlock {
private final boolean acknowledgementBeep;
@ -30,7 +30,7 @@ public class BolusExtraCommand extends MessageBlock {
Duration programReminderInterval, Duration timeBetweenPulses) {
if (units <= 0D) {
throw new CommandInitializationException("Units should be > 0");
} else if (units > OmnipodConst.MAX_BOLUS) {
} else if (units > OmnipodConstants.MAX_BOLUS) {
throw new CommandInitializationException("Units exceeds max bolus");
}
this.units = units;

View file

@ -1,12 +1,12 @@
package info.nightscout.androidaps.plugins.pump.omnipod.comm.message.command;
package info.nightscout.androidaps.plugins.pump.omnipod.driver.communication.message.command;
import java.util.EnumSet;
import info.nightscout.androidaps.plugins.pump.common.utils.ByteUtil;
import info.nightscout.androidaps.plugins.pump.omnipod.comm.message.NonceResyncableMessageBlock;
import info.nightscout.androidaps.plugins.pump.omnipod.defs.BeepType;
import info.nightscout.androidaps.plugins.pump.omnipod.defs.DeliveryType;
import info.nightscout.androidaps.plugins.pump.omnipod.defs.MessageBlockType;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.communication.message.NonceResyncableMessageBlock;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.definition.BeepType;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.definition.DeliveryType;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.definition.MessageBlockType;
public class CancelDeliveryCommand extends NonceResyncableMessageBlock {

View file

@ -1,11 +1,11 @@
package info.nightscout.androidaps.plugins.pump.omnipod.comm.message.command;
package info.nightscout.androidaps.plugins.pump.omnipod.driver.communication.message.command;
import java.util.List;
import info.nightscout.androidaps.plugins.pump.common.utils.ByteUtil;
import info.nightscout.androidaps.plugins.pump.omnipod.comm.message.NonceResyncableMessageBlock;
import info.nightscout.androidaps.plugins.pump.omnipod.defs.AlertConfiguration;
import info.nightscout.androidaps.plugins.pump.omnipod.defs.MessageBlockType;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.communication.message.NonceResyncableMessageBlock;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.definition.AlertConfiguration;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.definition.MessageBlockType;
public class ConfigureAlertsCommand extends NonceResyncableMessageBlock {
private final List<AlertConfiguration> configurations;

View file

@ -1,8 +1,8 @@
package info.nightscout.androidaps.plugins.pump.omnipod.comm.message.command;
package info.nightscout.androidaps.plugins.pump.omnipod.driver.communication.message.command;
import info.nightscout.androidaps.plugins.pump.common.utils.ByteUtil;
import info.nightscout.androidaps.plugins.pump.omnipod.comm.message.NonceResyncableMessageBlock;
import info.nightscout.androidaps.plugins.pump.omnipod.defs.MessageBlockType;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.communication.message.NonceResyncableMessageBlock;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.definition.MessageBlockType;
public class DeactivatePodCommand extends NonceResyncableMessageBlock {
private int nonce;

View file

@ -1,8 +1,8 @@
package info.nightscout.androidaps.plugins.pump.omnipod.comm.message.command;
package info.nightscout.androidaps.plugins.pump.omnipod.driver.communication.message.command;
import info.nightscout.androidaps.plugins.pump.common.utils.ByteUtil;
import info.nightscout.androidaps.plugins.pump.omnipod.comm.message.NonceResyncableMessageBlock;
import info.nightscout.androidaps.plugins.pump.omnipod.defs.MessageBlockType;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.communication.message.NonceResyncableMessageBlock;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.definition.MessageBlockType;
public class FaultConfigCommand extends NonceResyncableMessageBlock {
private final byte tab5sub16;

View file

@ -1,8 +1,8 @@
package info.nightscout.androidaps.plugins.pump.omnipod.comm.message.command;
package info.nightscout.androidaps.plugins.pump.omnipod.driver.communication.message.command;
import info.nightscout.androidaps.plugins.pump.omnipod.comm.message.MessageBlock;
import info.nightscout.androidaps.plugins.pump.omnipod.defs.MessageBlockType;
import info.nightscout.androidaps.plugins.pump.omnipod.defs.PodInfoType;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.communication.message.MessageBlock;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.definition.MessageBlockType;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.definition.PodInfoType;
public class GetStatusCommand extends MessageBlock {
private final PodInfoType podInfoType;

View file

@ -1,18 +1,18 @@
package info.nightscout.androidaps.plugins.pump.omnipod.comm.message.command;
package info.nightscout.androidaps.plugins.pump.omnipod.driver.communication.message.command;
import org.joda.time.Duration;
import info.nightscout.androidaps.plugins.pump.common.utils.ByteUtil;
import info.nightscout.androidaps.plugins.pump.omnipod.comm.exception.CommandInitializationException;
import info.nightscout.androidaps.plugins.pump.omnipod.comm.message.NonceResyncableMessageBlock;
import info.nightscout.androidaps.plugins.pump.omnipod.defs.MessageBlockType;
import info.nightscout.androidaps.plugins.pump.omnipod.defs.schedule.BasalDeliverySchedule;
import info.nightscout.androidaps.plugins.pump.omnipod.defs.schedule.BasalDeliveryTable;
import info.nightscout.androidaps.plugins.pump.omnipod.defs.schedule.BasalSchedule;
import info.nightscout.androidaps.plugins.pump.omnipod.defs.schedule.BolusDeliverySchedule;
import info.nightscout.androidaps.plugins.pump.omnipod.defs.schedule.DeliverySchedule;
import info.nightscout.androidaps.plugins.pump.omnipod.defs.schedule.TempBasalDeliverySchedule;
import info.nightscout.androidaps.plugins.pump.omnipod.util.OmnipodConst;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.communication.message.NonceResyncableMessageBlock;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.definition.MessageBlockType;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.definition.OmnipodConstants;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.definition.schedule.BasalDeliverySchedule;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.definition.schedule.BasalDeliveryTable;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.definition.schedule.BasalSchedule;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.definition.schedule.BolusDeliverySchedule;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.definition.schedule.DeliverySchedule;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.definition.schedule.TempBasalDeliverySchedule;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.exception.CommandInitializationException;
public class SetInsulinScheduleCommand extends NonceResyncableMessageBlock {
@ -37,7 +37,7 @@ public class SetInsulinScheduleCommand extends NonceResyncableMessageBlock {
int timeRemainingInSegment = BasalDeliveryTable.SEGMENT_DURATION - segmentOffset;
double timeBetweenPulses = 3600 / (rate / OmnipodConst.POD_PULSE_SIZE);
double timeBetweenPulses = 3600 / (rate / OmnipodConstants.POD_PULSE_SIZE);
double offsetToNextTenth = timeRemainingInSegment % (timeBetweenPulses / 10.0);
@ -52,13 +52,13 @@ public class SetInsulinScheduleCommand extends NonceResyncableMessageBlock {
public SetInsulinScheduleCommand(int nonce, double tempBasalRate, Duration duration) {
if (tempBasalRate < 0D) {
throw new CommandInitializationException("Rate should be >= 0");
} else if (tempBasalRate > OmnipodConst.MAX_BASAL_RATE) {
} else if (tempBasalRate > OmnipodConstants.MAX_BASAL_RATE) {
throw new CommandInitializationException("Rate exceeds max basal rate");
}
if (duration.isLongerThan(OmnipodConst.MAX_TEMP_BASAL_DURATION)) {
if (duration.isLongerThan(OmnipodConstants.MAX_TEMP_BASAL_DURATION)) {
throw new CommandInitializationException("Duration exceeds max temp basal duration");
}
int pulsesPerHour = (int) Math.round(tempBasalRate / OmnipodConst.POD_PULSE_SIZE);
int pulsesPerHour = (int) Math.round(tempBasalRate / OmnipodConstants.POD_PULSE_SIZE);
int pulsesPerSegment = pulsesPerHour / 2;
this.nonce = nonce;
this.schedule = new TempBasalDeliverySchedule(BasalDeliveryTable.SEGMENT_DURATION, pulsesPerSegment, new BasalDeliveryTable(tempBasalRate, duration));

View file

@ -1,10 +1,10 @@
package info.nightscout.androidaps.plugins.pump.omnipod.comm.message.command;
package info.nightscout.androidaps.plugins.pump.omnipod.driver.communication.message.command;
import org.joda.time.DateTime;
import info.nightscout.androidaps.plugins.pump.common.utils.ByteUtil;
import info.nightscout.androidaps.plugins.pump.omnipod.comm.message.MessageBlock;
import info.nightscout.androidaps.plugins.pump.omnipod.defs.MessageBlockType;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.communication.message.MessageBlock;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.definition.MessageBlockType;
public class SetupPodCommand extends MessageBlock {

View file

@ -1,4 +1,4 @@
package info.nightscout.androidaps.plugins.pump.omnipod.comm.message.command;
package info.nightscout.androidaps.plugins.pump.omnipod.driver.communication.message.command;
import org.joda.time.Duration;
@ -6,11 +6,11 @@ import java.util.ArrayList;
import java.util.List;
import info.nightscout.androidaps.plugins.pump.common.utils.ByteUtil;
import info.nightscout.androidaps.plugins.pump.omnipod.comm.exception.CommandInitializationException;
import info.nightscout.androidaps.plugins.pump.omnipod.comm.message.MessageBlock;
import info.nightscout.androidaps.plugins.pump.omnipod.defs.MessageBlockType;
import info.nightscout.androidaps.plugins.pump.omnipod.defs.schedule.RateEntry;
import info.nightscout.androidaps.plugins.pump.omnipod.util.OmnipodConst;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.communication.message.MessageBlock;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.definition.MessageBlockType;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.definition.OmnipodConstants;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.definition.schedule.RateEntry;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.exception.CommandInitializationException;
public class TempBasalExtraCommand extends MessageBlock {
private final boolean acknowledgementBeep;
@ -25,10 +25,10 @@ public class TempBasalExtraCommand extends MessageBlock {
Duration programReminderInterval) {
if (rate < 0D) {
throw new CommandInitializationException("Rate should be >= 0");
} else if (rate > OmnipodConst.MAX_BASAL_RATE) {
} else if (rate > OmnipodConstants.MAX_BASAL_RATE) {
throw new CommandInitializationException("Rate exceeds max basal rate");
}
if (duration.isLongerThan(OmnipodConst.MAX_TEMP_BASAL_DURATION)) {
if (duration.isLongerThan(OmnipodConstants.MAX_TEMP_BASAL_DURATION)) {
throw new CommandInitializationException("Duration exceeds max temp basal duration");
}

View file

@ -1,10 +1,10 @@
package info.nightscout.androidaps.plugins.pump.omnipod.comm.message.response;
package info.nightscout.androidaps.plugins.pump.omnipod.driver.communication.message.response;
import info.nightscout.androidaps.plugins.pump.common.utils.ByteUtil;
import info.nightscout.androidaps.plugins.pump.omnipod.comm.message.MessageBlock;
import info.nightscout.androidaps.plugins.pump.omnipod.defs.FaultEventCode;
import info.nightscout.androidaps.plugins.pump.omnipod.defs.MessageBlockType;
import info.nightscout.androidaps.plugins.pump.omnipod.defs.PodProgressStatus;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.communication.message.MessageBlock;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.definition.FaultEventCode;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.definition.MessageBlockType;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.definition.PodProgressStatus;
public class ErrorResponse extends MessageBlock {
public static final byte ERROR_RESPONSE_CODE_BAD_NONCE = (byte) 0x14;

View file

@ -1,4 +1,4 @@
package info.nightscout.androidaps.plugins.pump.omnipod.comm.message.response;
package info.nightscout.androidaps.plugins.pump.omnipod.driver.communication.message.response;
import org.joda.time.Duration;
@ -6,24 +6,25 @@ import java.io.ByteArrayOutputStream;
import java.io.IOException;
import info.nightscout.androidaps.plugins.pump.common.utils.ByteUtil;
import info.nightscout.androidaps.plugins.pump.omnipod.comm.message.MessageBlock;
import info.nightscout.androidaps.plugins.pump.omnipod.defs.AlertSet;
import info.nightscout.androidaps.plugins.pump.omnipod.defs.DeliveryStatus;
import info.nightscout.androidaps.plugins.pump.omnipod.defs.MessageBlockType;
import info.nightscout.androidaps.plugins.pump.omnipod.defs.PodProgressStatus;
import info.nightscout.androidaps.plugins.pump.omnipod.util.OmnipodConst;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.communication.message.MessageBlock;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.definition.AlertSet;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.definition.DeliveryStatus;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.definition.MessageBlockType;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.definition.OmnipodConstants;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.definition.PodProgressStatus;
public class StatusResponse extends MessageBlock {
public class StatusResponse extends MessageBlock implements StatusUpdatableResponse {
private static final int MESSAGE_LENGTH = 10;
private final DeliveryStatus deliveryStatus;
private final PodProgressStatus podProgressStatus;
private final Duration timeActive;
private final Double reservoirLevel;
private final int ticksDelivered;
private final double insulinDelivered;
private final double insulinNotDelivered;
private final double bolusNotDelivered;
private final byte podMessageCounter;
private final AlertSet alerts;
private final AlertSet unacknowledgedAlerts;
public StatusResponse(byte[] encodedData) {
if (encodedData.length < MESSAGE_LENGTH) {
@ -40,14 +41,15 @@ public class StatusResponse extends MessageBlock {
int highInsulinBits = (encodedData[2] & 0xF) << 9;
int middleInsulinBits = ByteUtil.convertUnsignedByteToInt(encodedData[3]) << 1;
int lowInsulinBits = ByteUtil.convertUnsignedByteToInt(encodedData[4]) >>> 7;
insulinDelivered = OmnipodConst.POD_PULSE_SIZE * (highInsulinBits | middleInsulinBits | lowInsulinBits);
ticksDelivered = (highInsulinBits | middleInsulinBits | lowInsulinBits);
insulinDelivered = OmnipodConstants.POD_PULSE_SIZE * ticksDelivered;
podMessageCounter = (byte) ((encodedData[4] >>> 3) & 0xf);
insulinNotDelivered = OmnipodConst.POD_PULSE_SIZE * (((encodedData[4] & 0x03) << 8) | ByteUtil.convertUnsignedByteToInt(encodedData[5]));
alerts = new AlertSet((byte) (((encodedData[6] & 0x7f) << 1) | (ByteUtil.convertUnsignedByteToInt(encodedData[7]) >>> 7)));
bolusNotDelivered = OmnipodConstants.POD_PULSE_SIZE * (((encodedData[4] & 0x03) << 8) | ByteUtil.convertUnsignedByteToInt(encodedData[5]));
unacknowledgedAlerts = new AlertSet((byte) (((encodedData[6] & 0x7f) << 1) | (ByteUtil.convertUnsignedByteToInt(encodedData[7]) >>> 7)));
double reservoirValue = (((encodedData[8] & 0x3) << 8) + ByteUtil.convertUnsignedByteToInt(encodedData[9])) * OmnipodConst.POD_PULSE_SIZE;
if (reservoirValue > OmnipodConst.MAX_RESERVOIR_READING) {
double reservoirValue = (((encodedData[8] & 0x3) << 8) + ByteUtil.convertUnsignedByteToInt(encodedData[9])) * OmnipodConstants.POD_PULSE_SIZE;
if (reservoirValue > OmnipodConstants.MAX_RESERVOIR_READING) {
reservoirLevel = null;
} else {
reservoirLevel = reservoirValue;
@ -59,39 +61,43 @@ public class StatusResponse extends MessageBlock {
return MessageBlockType.STATUS_RESPONSE;
}
public DeliveryStatus getDeliveryStatus() {
@Override public DeliveryStatus getDeliveryStatus() {
return deliveryStatus;
}
public PodProgressStatus getPodProgressStatus() {
@Override public PodProgressStatus getPodProgressStatus() {
return podProgressStatus;
}
public Duration getTimeActive() {
@Override public Duration getTimeActive() {
return timeActive;
}
public Double getReservoirLevel() {
@Override public Double getReservoirLevel() {
return reservoirLevel;
}
public double getInsulinDelivered() {
@Override public int getTicksDelivered() {
return ticksDelivered;
}
@Override public double getInsulinDelivered() {
return insulinDelivered;
}
public double getInsulinNotDelivered() {
return insulinNotDelivered;
@Override public double getBolusNotDelivered() {
return bolusNotDelivered;
}
public byte getPodMessageCounter() {
@Override public byte getPodMessageCounter() {
return podMessageCounter;
}
public AlertSet getAlerts() {
return alerts;
@Override public AlertSet getUnacknowledgedAlerts() {
return unacknowledgedAlerts;
}
public byte[] getRawData() {
@Override public byte[] getRawData() {
ByteArrayOutputStream stream = new ByteArrayOutputStream();
try {
stream.write(getType().getValue());
@ -103,17 +109,18 @@ public class StatusResponse extends MessageBlock {
return stream.toByteArray();
}
@Override
public String toString() {
@Override public String toString() {
return "StatusResponse{" +
"deliveryStatus=" + deliveryStatus +
", podProgressStatus=" + podProgressStatus +
", timeActive=" + timeActive +
", reservoirLevel=" + reservoirLevel +
", ticksDelivered=" + ticksDelivered +
", insulinDelivered=" + insulinDelivered +
", insulinNotDelivered=" + insulinNotDelivered +
", bolusNotDelivered=" + bolusNotDelivered +
", podMessageCounter=" + podMessageCounter +
", alerts=" + alerts +
", unacknowledgedAlerts=" + unacknowledgedAlerts +
", encodedData=" + ByteUtil.shortHexStringWithoutSpaces(encodedData) +
'}';
}
}

View file

@ -0,0 +1,27 @@
package info.nightscout.androidaps.plugins.pump.omnipod.driver.communication.message.response;
import org.joda.time.Duration;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.definition.AlertSet;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.definition.DeliveryStatus;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.definition.PodProgressStatus;
public interface StatusUpdatableResponse {
DeliveryStatus getDeliveryStatus();
PodProgressStatus getPodProgressStatus();
Duration getTimeActive();
Double getReservoirLevel();
int getTicksDelivered();
double getInsulinDelivered();
double getBolusNotDelivered();
byte getPodMessageCounter();
AlertSet getUnacknowledgedAlerts();
}

View file

@ -1,10 +1,10 @@
package info.nightscout.androidaps.plugins.pump.omnipod.comm.message.response;
package info.nightscout.androidaps.plugins.pump.omnipod.driver.communication.message.response;
import info.nightscout.androidaps.plugins.pump.common.utils.ByteUtil;
import info.nightscout.androidaps.plugins.pump.omnipod.comm.message.MessageBlock;
import info.nightscout.androidaps.plugins.pump.omnipod.defs.FirmwareVersion;
import info.nightscout.androidaps.plugins.pump.omnipod.defs.MessageBlockType;
import info.nightscout.androidaps.plugins.pump.omnipod.defs.PodProgressStatus;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.communication.message.MessageBlock;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.definition.FirmwareVersion;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.definition.MessageBlockType;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.definition.PodProgressStatus;
public class VersionResponse extends MessageBlock {
private static final int ASSIGN_ADDRESS_VERSION_RESPONSE_LENGTH = 0x15;

View file

@ -1,11 +1,11 @@
package info.nightscout.androidaps.plugins.pump.omnipod.comm.message.response.podinfo;
package info.nightscout.androidaps.plugins.pump.omnipod.driver.communication.message.response.podinfo;
import info.nightscout.androidaps.plugins.pump.omnipod.defs.PodInfoType;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.definition.PodInfoType;
public abstract class PodInfo {
private final byte[] encodedData;
public PodInfo(byte[] encodedData) {
PodInfo(byte[] encodedData) {
this.encodedData = encodedData;
}

View file

@ -1,4 +1,4 @@
package info.nightscout.androidaps.plugins.pump.omnipod.comm.message.response.podinfo;
package info.nightscout.androidaps.plugins.pump.omnipod.driver.communication.message.response.podinfo;
import org.joda.time.Duration;
@ -7,9 +7,9 @@ import java.util.Arrays;
import java.util.List;
import info.nightscout.androidaps.plugins.pump.common.utils.ByteUtil;
import info.nightscout.androidaps.plugins.pump.omnipod.defs.AlertSlot;
import info.nightscout.androidaps.plugins.pump.omnipod.defs.PodInfoType;
import info.nightscout.androidaps.plugins.pump.omnipod.util.OmnipodConst;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.definition.AlertSlot;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.definition.OmnipodConstants;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.definition.PodInfoType;
public class PodInfoActiveAlerts extends PodInfo {
private static final int MINIMUM_MESSAGE_LENGTH = 11;
@ -69,7 +69,7 @@ public class PodInfoActiveAlerts extends PodInfo {
}
public double getValueAsUnits() {
return value * OmnipodConst.POD_PULSE_SIZE;
return value * OmnipodConstants.POD_PULSE_SIZE;
}
public Duration getValueAsDuration() {

View file

@ -1,4 +1,4 @@
package info.nightscout.androidaps.plugins.pump.omnipod.comm.message.response.podinfo;
package info.nightscout.androidaps.plugins.pump.omnipod.driver.communication.message.response.podinfo;
import org.joda.time.Duration;
@ -7,8 +7,8 @@ import java.util.Collections;
import java.util.List;
import info.nightscout.androidaps.plugins.pump.common.utils.ByteUtil;
import info.nightscout.androidaps.plugins.pump.omnipod.defs.FaultEventCode;
import info.nightscout.androidaps.plugins.pump.omnipod.defs.PodInfoType;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.definition.FaultEventCode;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.definition.PodInfoType;
public class PodInfoDataLog extends PodInfo {
private static final int MINIMUM_MESSAGE_LENGTH = 8;

View file

@ -1,10 +1,10 @@
package info.nightscout.androidaps.plugins.pump.omnipod.comm.message.response.podinfo;
package info.nightscout.androidaps.plugins.pump.omnipod.driver.communication.message.response.podinfo;
import org.joda.time.DateTime;
import org.joda.time.Duration;
import info.nightscout.androidaps.plugins.pump.omnipod.defs.FaultEventCode;
import info.nightscout.androidaps.plugins.pump.omnipod.defs.PodInfoType;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.definition.FaultEventCode;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.definition.PodInfoType;
public class PodInfoFaultAndInitializationTime extends PodInfo {
private static final int MINIMUM_MESSAGE_LENGTH = 17;

View file

@ -1,28 +1,30 @@
package info.nightscout.androidaps.plugins.pump.omnipod.comm.message.response.podinfo;
package info.nightscout.androidaps.plugins.pump.omnipod.driver.communication.message.response.podinfo;
import org.joda.time.Duration;
import info.nightscout.androidaps.plugins.pump.common.utils.ByteUtil;
import info.nightscout.androidaps.plugins.pump.omnipod.defs.AlertSet;
import info.nightscout.androidaps.plugins.pump.omnipod.defs.DeliveryStatus;
import info.nightscout.androidaps.plugins.pump.omnipod.defs.FaultEventCode;
import info.nightscout.androidaps.plugins.pump.omnipod.defs.LogEventErrorCode;
import info.nightscout.androidaps.plugins.pump.omnipod.defs.PodInfoType;
import info.nightscout.androidaps.plugins.pump.omnipod.defs.PodProgressStatus;
import info.nightscout.androidaps.plugins.pump.omnipod.util.OmnipodConst;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.communication.message.response.StatusUpdatableResponse;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.definition.AlertSet;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.definition.DeliveryStatus;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.definition.FaultEventCode;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.definition.LogEventErrorCode;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.definition.OmnipodConstants;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.definition.PodInfoType;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.definition.PodProgressStatus;
public class PodInfoFaultEvent extends PodInfo {
public class PodInfoFaultEvent extends PodInfo implements StatusUpdatableResponse {
private static final int MINIMUM_MESSAGE_LENGTH = 21;
private final PodProgressStatus podProgressStatus;
private final DeliveryStatus deliveryStatus;
private final double insulinNotDelivered;
private final double bolusNotDelivered;
private final byte podMessageCounter;
private final double totalInsulinDelivered;
private final int ticksDelivered;
private final double insulinDelivered;
private final FaultEventCode faultEventCode;
private final Duration faultEventTime;
private final Double reservoirLevel;
private final Duration timeSinceActivation;
private final Duration timeActive;
private final AlertSet unacknowledgedAlerts;
private final boolean faultAccessingTables;
private final LogEventErrorCode logEventErrorType;
@ -41,9 +43,10 @@ public class PodInfoFaultEvent extends PodInfo {
podProgressStatus = PodProgressStatus.fromByte(encodedData[1]);
deliveryStatus = DeliveryStatus.fromByte(encodedData[2]);
insulinNotDelivered = OmnipodConst.POD_PULSE_SIZE * ByteUtil.toInt(encodedData[3], encodedData[4]);
bolusNotDelivered = OmnipodConstants.POD_PULSE_SIZE * ByteUtil.toInt(encodedData[3], encodedData[4]);
podMessageCounter = encodedData[5];
totalInsulinDelivered = OmnipodConst.POD_PULSE_SIZE * ByteUtil.toInt(encodedData[6], encodedData[7]);
ticksDelivered = ByteUtil.toInt(encodedData[6], encodedData[7]);
insulinDelivered = OmnipodConstants.POD_PULSE_SIZE * ticksDelivered;
faultEventCode = FaultEventCode.fromByte(encodedData[8]);
int minutesSinceActivation = ByteUtil.toInt(encodedData[9], encodedData[10]);
@ -54,15 +57,15 @@ public class PodInfoFaultEvent extends PodInfo {
}
double reservoirValue = ((encodedData[11] & 0x03) << 8) +
ByteUtil.convertUnsignedByteToInt(encodedData[12]) * OmnipodConst.POD_PULSE_SIZE;
if (reservoirValue > OmnipodConst.MAX_RESERVOIR_READING) {
ByteUtil.convertUnsignedByteToInt(encodedData[12]) * OmnipodConstants.POD_PULSE_SIZE;
if (reservoirValue > OmnipodConstants.MAX_RESERVOIR_READING) {
reservoirLevel = null;
} else {
reservoirLevel = reservoirValue;
}
int minutesActive = ByteUtil.toInt(encodedData[13], encodedData[14]);
timeSinceActivation = Duration.standardMinutes(minutesActive);
timeActive = Duration.standardMinutes(minutesActive);
unacknowledgedAlerts = new AlertSet(encodedData[15]);
faultAccessingTables = encodedData[16] == 0x02;
@ -79,24 +82,28 @@ public class PodInfoFaultEvent extends PodInfo {
return PodInfoType.FAULT_EVENT;
}
public PodProgressStatus getPodProgressStatus() {
@Override public PodProgressStatus getPodProgressStatus() {
return podProgressStatus;
}
public DeliveryStatus getDeliveryStatus() {
@Override public DeliveryStatus getDeliveryStatus() {
return deliveryStatus;
}
public double getInsulinNotDelivered() {
return insulinNotDelivered;
@Override public double getBolusNotDelivered() {
return bolusNotDelivered;
}
public byte getPodMessageCounter() {
@Override public byte getPodMessageCounter() {
return podMessageCounter;
}
public double getTotalInsulinDelivered() {
return totalInsulinDelivered;
@Override public int getTicksDelivered() {
return ticksDelivered;
}
@Override public double getInsulinDelivered() {
return insulinDelivered;
}
public FaultEventCode getFaultEventCode() {
@ -107,15 +114,15 @@ public class PodInfoFaultEvent extends PodInfo {
return faultEventTime;
}
public Double getReservoirLevel() {
@Override public Double getReservoirLevel() {
return reservoirLevel;
}
public Duration getTimeSinceActivation() {
return timeSinceActivation;
@Override public Duration getTimeActive() {
return timeActive;
}
public AlertSet getUnacknowledgedAlerts() {
@Override public AlertSet getUnacknowledgedAlerts() {
return unacknowledgedAlerts;
}
@ -147,18 +154,18 @@ public class PodInfoFaultEvent extends PodInfo {
return unknownValue;
}
@Override
public String toString() {
@Override public String toString() {
return "PodInfoFaultEvent{" +
"podProgressStatus=" + podProgressStatus +
", deliveryStatus=" + deliveryStatus +
", insulinNotDelivered=" + insulinNotDelivered +
", bolusNotDelivered=" + bolusNotDelivered +
", podMessageCounter=" + podMessageCounter +
", totalInsulinDelivered=" + totalInsulinDelivered +
", ticksDelivered=" + ticksDelivered +
", insulinDelivered=" + insulinDelivered +
", faultEventCode=" + faultEventCode +
", faultEventTime=" + faultEventTime +
", reservoirLevel=" + reservoirLevel +
", timeSinceActivation=" + timeSinceActivation +
", timeActive=" + timeActive +
", unacknowledgedAlerts=" + unacknowledgedAlerts +
", faultAccessingTables=" + faultAccessingTables +
", logEventErrorType=" + logEventErrorType +

Some files were not shown because too many files have changed in this diff Show more