Merge remote-tracking branch 'origin/dev' into layout
This commit is contained in:
commit
4a17fdc9a0
297 changed files with 15746 additions and 877 deletions
|
@ -29,7 +29,7 @@ ext {
|
||||||
powermockVersion = "1.7.3"
|
powermockVersion = "1.7.3"
|
||||||
dexmakerVersion = "1.2"
|
dexmakerVersion = "1.2"
|
||||||
retrofit2Version = '2.8.1'
|
retrofit2Version = '2.8.1'
|
||||||
okhttp3Version = '4.5.0'
|
okhttp3Version = '4.6.0'
|
||||||
coroutinesVersion = '1.3.5'
|
coroutinesVersion = '1.3.5'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -160,6 +160,7 @@ android {
|
||||||
}
|
}
|
||||||
firebaseDisable {
|
firebaseDisable {
|
||||||
System.setProperty("disableFirebase", "true")
|
System.setProperty("disableFirebase", "true")
|
||||||
|
ext.enableCrashlytics = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
productFlavors {
|
productFlavors {
|
||||||
|
@ -242,12 +243,14 @@ allprojects {
|
||||||
dependencies {
|
dependencies {
|
||||||
wearApp project(':wear')
|
wearApp project(':wear')
|
||||||
|
|
||||||
|
implementation project(':core')
|
||||||
|
|
||||||
implementation fileTree(include: ['*.jar'], dir: 'libs')
|
implementation fileTree(include: ['*.jar'], dir: 'libs')
|
||||||
implementation 'com.google.android.gms:play-services-wearable:17.0.0'
|
implementation 'com.google.android.gms:play-services-wearable:17.0.0'
|
||||||
implementation "com.google.android.gms:play-services-location:17.0.0"
|
implementation "com.google.android.gms:play-services-location:17.0.0"
|
||||||
implementation 'com.google.firebase:firebase-core:17.3.0'
|
implementation 'com.google.firebase:firebase-core:17.4.0'
|
||||||
implementation 'com.google.firebase:firebase-auth:19.3.0'
|
implementation 'com.google.firebase:firebase-auth:19.3.1'
|
||||||
implementation 'com.google.firebase:firebase-database:19.2.1'
|
implementation 'com.google.firebase:firebase-database:19.3.0'
|
||||||
implementation('com.crashlytics.sdk.android:crashlytics:2.10.1@aar') {
|
implementation('com.crashlytics.sdk.android:crashlytics:2.10.1@aar') {
|
||||||
transitive = true;
|
transitive = true;
|
||||||
}
|
}
|
||||||
|
@ -260,7 +263,7 @@ dependencies {
|
||||||
implementation 'androidx.recyclerview:recyclerview:1.1.0'
|
implementation 'androidx.recyclerview:recyclerview:1.1.0'
|
||||||
implementation 'androidx.gridlayout:gridlayout:1.0.0'
|
implementation 'androidx.gridlayout:gridlayout:1.0.0'
|
||||||
implementation 'androidx.percentlayout:percentlayout:1.0.0'
|
implementation 'androidx.percentlayout:percentlayout:1.0.0'
|
||||||
implementation "androidx.preference:preference-ktx:1.1.0"
|
implementation "androidx.preference:preference-ktx:1.1.1"
|
||||||
implementation 'com.google.android.material:material:1.1.0'
|
implementation 'com.google.android.material:material:1.1.0'
|
||||||
implementation 'com.wdullaer:materialdatetimepicker:4.2.3'
|
implementation 'com.wdullaer:materialdatetimepicker:4.2.3'
|
||||||
|
|
||||||
|
@ -271,13 +274,14 @@ dependencies {
|
||||||
implementation("com.github.tony19:logback-android-classic:1.1.1-6") {
|
implementation("com.github.tony19:logback-android-classic:1.1.1-6") {
|
||||||
exclude group: "com.google.android", module: "android"
|
exclude group: "com.google.android", module: "android"
|
||||||
}
|
}
|
||||||
implementation "org.apache.commons:commons-lang3:3.9"
|
implementation 'org.apache.commons:commons-lang3:3.10'
|
||||||
implementation 'org.slf4j:slf4j-api:1.7.30'
|
implementation 'org.slf4j:slf4j-api:1.7.30'
|
||||||
// Graphview cannot be upgraded
|
// Graphview cannot be upgraded
|
||||||
implementation "com.jjoe64:graphview:4.0.1"
|
implementation "com.jjoe64:graphview:4.0.1"
|
||||||
implementation "com.joanzapata.iconify:android-iconify-fontawesome:2.2.2"
|
implementation "com.joanzapata.iconify:android-iconify-fontawesome:2.2.2"
|
||||||
implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
|
implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
|
||||||
implementation 'com.madgag.spongycastle:core:1.58.0.0'
|
implementation 'com.madgag.spongycastle:core:1.58.0.0'
|
||||||
|
implementation(name: "com.atech-software.android.library.wizardpager-1.1.1", ext: "aar")
|
||||||
|
|
||||||
implementation("com.google.android:flexbox:0.3.0") {
|
implementation("com.google.android:flexbox:0.3.0") {
|
||||||
exclude group: "com.android.support"
|
exclude group: "com.android.support"
|
||||||
|
@ -287,28 +291,28 @@ dependencies {
|
||||||
exclude group: "org.json", module: "json"
|
exclude group: "org.json", module: "json"
|
||||||
}
|
}
|
||||||
implementation "com.google.code.gson:gson:2.8.6"
|
implementation "com.google.code.gson:gson:2.8.6"
|
||||||
implementation ("com.google.guava:guava:24.1-jre") {
|
implementation('com.google.guava:guava:29.0-jre') {
|
||||||
exclude group: "com.google.code.findbugs", module: "jsr305"
|
exclude group: "com.google.code.findbugs", module: "jsr305"
|
||||||
}
|
}
|
||||||
implementation 'com.google.code.findbugs:jsr305:3.0.2'
|
implementation 'com.google.code.findbugs:jsr305:3.0.2'
|
||||||
|
|
||||||
implementation "net.danlew:android.joda:2.10.3"
|
implementation 'net.danlew:android.joda:2.10.6'
|
||||||
|
|
||||||
implementation 'org.mozilla:rhino:1.7.11'
|
implementation 'org.mozilla:rhino:1.7.12'
|
||||||
|
|
||||||
implementation 'com.github.DavidProdinger:weekdays-selector:1.1.0'
|
implementation 'com.github.DavidProdinger:weekdays-selector:1.1.0'
|
||||||
|
|
||||||
implementation 'com.github.kenglxn.QRGen:android:2.6.0'
|
implementation 'com.github.kenglxn.QRGen:android:2.6.0'
|
||||||
implementation 'com.eatthepath:java-otp:0.2.0'
|
implementation 'com.eatthepath:java-otp:0.2.0'
|
||||||
|
|
||||||
testImplementation "junit:junit:4.12"
|
testImplementation "junit:junit:4.13"
|
||||||
testImplementation "org.json:json:20190722"
|
testImplementation "org.json:json:20190722"
|
||||||
testImplementation "org.mockito:mockito-core:2.8.47"
|
testImplementation "org.mockito:mockito-core:2.8.47"
|
||||||
testImplementation "org.powermock:powermock-api-mockito2:${powermockVersion}"
|
testImplementation "org.powermock:powermock-api-mockito2:${powermockVersion}"
|
||||||
testImplementation "org.powermock:powermock-module-junit4-rule-agent:${powermockVersion}"
|
testImplementation "org.powermock:powermock-module-junit4-rule-agent:${powermockVersion}"
|
||||||
testImplementation "org.powermock:powermock-module-junit4-rule:${powermockVersion}"
|
testImplementation "org.powermock:powermock-module-junit4-rule:${powermockVersion}"
|
||||||
testImplementation "org.powermock:powermock-module-junit4:${powermockVersion}"
|
testImplementation "org.powermock:powermock-module-junit4:${powermockVersion}"
|
||||||
testImplementation "joda-time:joda-time:2.10.5"
|
testImplementation 'joda-time:joda-time:2.10.6'
|
||||||
testImplementation('com.google.truth:truth:1.0.1') {
|
testImplementation('com.google.truth:truth:1.0.1') {
|
||||||
exclude group: "com.google.guava", module: "guava"
|
exclude group: "com.google.guava", module: "guava"
|
||||||
exclude group: "com.google.code.findbugs", module: "jsr305"
|
exclude group: "com.google.code.findbugs", module: "jsr305"
|
||||||
|
@ -329,24 +333,24 @@ dependencies {
|
||||||
implementation "com.squareup.retrofit2:converter-gson:$retrofit2Version"
|
implementation "com.squareup.retrofit2:converter-gson:$retrofit2Version"
|
||||||
|
|
||||||
// Phone checker
|
// Phone checker
|
||||||
implementation 'com.scottyab:rootbeer-lib:0.0.7'
|
implementation 'com.scottyab:rootbeer-lib:0.0.8'
|
||||||
|
|
||||||
androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0-alpha03'
|
androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0-alpha03'
|
||||||
androidTestImplementation 'androidx.test.ext:junit:1.1.1'
|
androidTestImplementation 'androidx.test.ext:junit:1.1.1'
|
||||||
androidTestImplementation 'androidx.test:rules:1.3.0-alpha03'
|
androidTestImplementation 'androidx.test:rules:1.3.0-beta01'
|
||||||
androidTestImplementation 'com.google.code.findbugs:jsr305:3.0.2'
|
androidTestImplementation 'com.google.code.findbugs:jsr305:3.0.2'
|
||||||
|
|
||||||
/* Dagger2 - We are going to use dagger.android which includes
|
/* Dagger2 - We are going to use dagger.android which includes
|
||||||
* support for Activity and fragment injection so we need to include
|
* support for Activity and fragment injection so we need to include
|
||||||
* the following dependencies */
|
* the following dependencies */
|
||||||
implementation 'com.google.dagger:dagger-android:2.25.2'
|
implementation "com.google.dagger:dagger-android:$dagger_version"
|
||||||
implementation 'com.google.dagger:dagger-android-support:2.25.2'
|
implementation "com.google.dagger:dagger-android-support:$dagger_version"
|
||||||
annotationProcessor 'com.google.dagger:dagger-compiler:2.25.2'
|
annotationProcessor "com.google.dagger:dagger-compiler:$dagger_version"
|
||||||
annotationProcessor 'com.google.dagger:dagger-android-processor:2.25.2'
|
annotationProcessor "com.google.dagger:dagger-android-processor:$dagger_version"
|
||||||
kapt 'com.google.dagger:dagger-android-processor:2.25.2'
|
kapt "com.google.dagger:dagger-android-processor:$dagger_version"
|
||||||
|
|
||||||
/* Dagger2 - default dependency */
|
/* Dagger2 - default dependency */
|
||||||
kapt 'com.google.dagger:dagger-compiler:2.25.2'
|
kapt "com.google.dagger:dagger-compiler:$dagger_version"
|
||||||
|
|
||||||
androidTestImplementation 'androidx.test.uiautomator:uiautomator:2.2.0'
|
androidTestImplementation 'androidx.test.uiautomator:uiautomator:2.2.0'
|
||||||
}
|
}
|
||||||
|
|
Binary file not shown.
|
@ -41,6 +41,8 @@ import info.nightscout.androidaps.logging.AAPSLogger
|
||||||
import info.nightscout.androidaps.logging.LTag
|
import info.nightscout.androidaps.logging.LTag
|
||||||
import info.nightscout.androidaps.plugins.aps.loop.LoopPlugin
|
import info.nightscout.androidaps.plugins.aps.loop.LoopPlugin
|
||||||
import info.nightscout.androidaps.plugins.bus.RxBusWrapper
|
import info.nightscout.androidaps.plugins.bus.RxBusWrapper
|
||||||
|
import info.nightscout.androidaps.plugins.configBuilder.ConstraintChecker
|
||||||
|
import info.nightscout.androidaps.plugins.constraints.signatureVerifier.SignatureVerifierPlugin
|
||||||
import info.nightscout.androidaps.plugins.constraints.versionChecker.VersionCheckerUtils
|
import info.nightscout.androidaps.plugins.constraints.versionChecker.VersionCheckerUtils
|
||||||
import info.nightscout.androidaps.plugins.general.nsclient.data.NSSettingsStatus
|
import info.nightscout.androidaps.plugins.general.nsclient.data.NSSettingsStatus
|
||||||
import info.nightscout.androidaps.plugins.general.smsCommunicator.SmsCommunicatorPlugin
|
import info.nightscout.androidaps.plugins.general.smsCommunicator.SmsCommunicatorPlugin
|
||||||
|
@ -53,11 +55,13 @@ import info.nightscout.androidaps.utils.alertDialogs.OKDialog
|
||||||
import info.nightscout.androidaps.utils.buildHelper.BuildHelper
|
import info.nightscout.androidaps.utils.buildHelper.BuildHelper
|
||||||
import info.nightscout.androidaps.utils.extensions.isRunningRealPumpTest
|
import info.nightscout.androidaps.utils.extensions.isRunningRealPumpTest
|
||||||
import info.nightscout.androidaps.utils.protection.ProtectionCheck
|
import info.nightscout.androidaps.utils.protection.ProtectionCheck
|
||||||
|
import info.nightscout.androidaps.utils.resources.IconsProvider
|
||||||
import info.nightscout.androidaps.utils.resources.ResourceHelper
|
import info.nightscout.androidaps.utils.resources.ResourceHelper
|
||||||
import info.nightscout.androidaps.utils.sharedPreferences.SP
|
import info.nightscout.androidaps.utils.sharedPreferences.SP
|
||||||
import io.reactivex.android.schedulers.AndroidSchedulers
|
import io.reactivex.android.schedulers.AndroidSchedulers
|
||||||
import io.reactivex.disposables.CompositeDisposable
|
import io.reactivex.disposables.CompositeDisposable
|
||||||
import kotlinx.android.synthetic.main.activity_main.*
|
import kotlinx.android.synthetic.main.activity_main.*
|
||||||
|
import java.util.*
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
import kotlin.system.exitProcess
|
import kotlin.system.exitProcess
|
||||||
|
|
||||||
|
@ -77,6 +81,9 @@ class MainActivity : NoSplashAppCompatActivity() {
|
||||||
@Inject lateinit var activePlugin: ActivePluginProvider
|
@Inject lateinit var activePlugin: ActivePluginProvider
|
||||||
@Inject lateinit var fabricPrivacy: FabricPrivacy
|
@Inject lateinit var fabricPrivacy: FabricPrivacy
|
||||||
@Inject lateinit var protectionCheck: ProtectionCheck
|
@Inject lateinit var protectionCheck: ProtectionCheck
|
||||||
|
@Inject lateinit var iconsProvider: IconsProvider
|
||||||
|
@Inject lateinit var constraintChecker: ConstraintChecker
|
||||||
|
@Inject lateinit var signatureVerifierPlugin: SignatureVerifierPlugin
|
||||||
|
|
||||||
private lateinit var actionBarDrawerToggle: ActionBarDrawerToggle
|
private lateinit var actionBarDrawerToggle: ActionBarDrawerToggle
|
||||||
private var pluginPreferencesMenuItem: MenuItem? = null
|
private var pluginPreferencesMenuItem: MenuItem? = null
|
||||||
|
@ -107,7 +114,7 @@ class MainActivity : NoSplashAppCompatActivity() {
|
||||||
|
|
||||||
//Check here if loop plugin is disabled. Else check via constraints
|
//Check here if loop plugin is disabled. Else check via constraints
|
||||||
if (!loopPlugin.isEnabled(PluginType.LOOP)) versionCheckerUtils.triggerCheckVersion()
|
if (!loopPlugin.isEnabled(PluginType.LOOP)) versionCheckerUtils.triggerCheckVersion()
|
||||||
fabricPrivacy.setUserStats()
|
setUserStats()
|
||||||
setupViews()
|
setupViews()
|
||||||
disposable.add(rxBus
|
disposable.add(rxBus
|
||||||
.toObservable(EventRebuildTabs::class.java)
|
.toObservable(EventRebuildTabs::class.java)
|
||||||
|
@ -284,7 +291,7 @@ class MainActivity : NoSplashAppCompatActivity() {
|
||||||
Linkify.addLinks(messageSpanned, Linkify.WEB_URLS)
|
Linkify.addLinks(messageSpanned, Linkify.WEB_URLS)
|
||||||
AlertDialog.Builder(this)
|
AlertDialog.Builder(this)
|
||||||
.setTitle(resourceHelper.gs(R.string.app_name) + " " + BuildConfig.VERSION)
|
.setTitle(resourceHelper.gs(R.string.app_name) + " " + BuildConfig.VERSION)
|
||||||
.setIcon(resourceHelper.getIcon())
|
.setIcon(iconsProvider.getIcon())
|
||||||
.setMessage(messageSpanned)
|
.setMessage(messageSpanned)
|
||||||
.setPositiveButton(resourceHelper.gs(R.string.ok), null)
|
.setPositiveButton(resourceHelper.gs(R.string.ok), null)
|
||||||
.create().also {
|
.create().also {
|
||||||
|
@ -324,4 +331,35 @@ class MainActivity : NoSplashAppCompatActivity() {
|
||||||
}
|
}
|
||||||
return actionBarDrawerToggle.onOptionsItemSelected(item)
|
return actionBarDrawerToggle.onOptionsItemSelected(item)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Correct place for calling setUserStats() would be probably MainApp
|
||||||
|
// but we need to have it called at least once a day. Thus this location
|
||||||
|
|
||||||
|
private fun setUserStats() {
|
||||||
|
if (!fabricPrivacy.fabricEnabled()) return
|
||||||
|
val closedLoopEnabled = if (constraintChecker.isClosedLoopAllowed().value()) "CLOSED_LOOP_ENABLED" else "CLOSED_LOOP_DISABLED"
|
||||||
|
// Size is limited to 36 chars
|
||||||
|
val remote = BuildConfig.REMOTE.toLowerCase(Locale.getDefault())
|
||||||
|
.replace("https://", "")
|
||||||
|
.replace("http://", "")
|
||||||
|
.replace(".git", "")
|
||||||
|
.replace(".com/", ":")
|
||||||
|
.replace(".org/", ":")
|
||||||
|
.replace(".net/", ":")
|
||||||
|
fabricPrivacy.firebaseAnalytics.setUserProperty("Mode", BuildConfig.APPLICATION_ID + "-" + closedLoopEnabled)
|
||||||
|
fabricPrivacy.firebaseAnalytics.setUserProperty("Language", sp.getString(R.string.key_language, Locale.getDefault().language))
|
||||||
|
fabricPrivacy.firebaseAnalytics.setUserProperty("Version", BuildConfig.VERSION)
|
||||||
|
fabricPrivacy.firebaseAnalytics.setUserProperty("HEAD", BuildConfig.HEAD)
|
||||||
|
fabricPrivacy.firebaseAnalytics.setUserProperty("Remote", remote)
|
||||||
|
val hashes: List<String> = signatureVerifierPlugin.shortHashes()
|
||||||
|
if (hashes.isNotEmpty()) fabricPrivacy.firebaseAnalytics.setUserProperty("Hash", hashes[0])
|
||||||
|
activePlugin.activePump.let { fabricPrivacy.firebaseAnalytics.setUserProperty("Pump", it::class.java.simpleName) }
|
||||||
|
if (!Config.NSCLIENT && !Config.PUMPCONTROL)
|
||||||
|
activePlugin.activeAPS.let { fabricPrivacy.firebaseAnalytics.setUserProperty("Aps", it::class.java.simpleName) }
|
||||||
|
activePlugin.activeBgSource.let { fabricPrivacy.firebaseAnalytics.setUserProperty("BgSource", it::class.java.simpleName) }
|
||||||
|
fabricPrivacy.firebaseAnalytics.setUserProperty("Profile", activePlugin.activeProfileInterface.javaClass.simpleName)
|
||||||
|
activePlugin.activeSensitivity.let { fabricPrivacy.firebaseAnalytics.setUserProperty("Sensitivity", it::class.java.simpleName) }
|
||||||
|
activePlugin.activeInsulin.let { fabricPrivacy.firebaseAnalytics.setUserProperty("Insulin", it::class.java.simpleName) }
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -26,7 +26,7 @@ import info.nightscout.androidaps.R;
|
||||||
import info.nightscout.androidaps.data.Profile;
|
import info.nightscout.androidaps.data.Profile;
|
||||||
import info.nightscout.androidaps.interfaces.Interval;
|
import info.nightscout.androidaps.interfaces.Interval;
|
||||||
import info.nightscout.androidaps.logging.AAPSLogger;
|
import info.nightscout.androidaps.logging.AAPSLogger;
|
||||||
import info.nightscout.androidaps.logging.L;
|
import info.nightscout.androidaps.logging.LTag;
|
||||||
import info.nightscout.androidaps.plugins.configBuilder.ProfileFunction;
|
import info.nightscout.androidaps.plugins.configBuilder.ProfileFunction;
|
||||||
import info.nightscout.androidaps.plugins.general.nsclient.data.NSMbg;
|
import info.nightscout.androidaps.plugins.general.nsclient.data.NSMbg;
|
||||||
import info.nightscout.androidaps.plugins.general.overview.graphExtensions.DataPointWithLabelInterface;
|
import info.nightscout.androidaps.plugins.general.overview.graphExtensions.DataPointWithLabelInterface;
|
||||||
|
@ -139,8 +139,7 @@ public class CareportalEvent implements DataPointWithLabelInterface, Interval {
|
||||||
for (int i = 0; i < list.size(); i++) {
|
for (int i = 0; i < list.size(); i++) {
|
||||||
CareportalEvent event = list.get(i);
|
CareportalEvent event = list.get(i);
|
||||||
if (event.date <= time && event.date > (time - T.mins(5).msecs())) {
|
if (event.date <= time && event.date > (time - T.mins(5).msecs())) {
|
||||||
if (L.isEnabled(L.DATABASE))
|
aapsLogger.debug(LTag.DATABASE, "Found event for time: " + DateUtil.dateAndTimeString(time) + " " + event.toString());
|
||||||
aapsLogger.debug("Found event for time: " + DateUtil.dateAndTimeString(time) + " " + event.toString());
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -47,6 +47,7 @@ import info.nightscout.androidaps.events.EventTempTargetChange;
|
||||||
import info.nightscout.androidaps.interfaces.ActivePluginProvider;
|
import info.nightscout.androidaps.interfaces.ActivePluginProvider;
|
||||||
import info.nightscout.androidaps.interfaces.ProfileInterface;
|
import info.nightscout.androidaps.interfaces.ProfileInterface;
|
||||||
import info.nightscout.androidaps.logging.L;
|
import info.nightscout.androidaps.logging.L;
|
||||||
|
import info.nightscout.androidaps.logging.LTag;
|
||||||
import info.nightscout.androidaps.logging.StacktraceLoggerWrapper;
|
import info.nightscout.androidaps.logging.StacktraceLoggerWrapper;
|
||||||
import info.nightscout.androidaps.plugins.bus.RxBus;
|
import info.nightscout.androidaps.plugins.bus.RxBus;
|
||||||
import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin;
|
import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin;
|
||||||
|
@ -57,6 +58,7 @@ import info.nightscout.androidaps.plugins.pump.danaR.comm.RecordTypes;
|
||||||
import info.nightscout.androidaps.plugins.pump.insight.database.InsightBolusID;
|
import info.nightscout.androidaps.plugins.pump.insight.database.InsightBolusID;
|
||||||
import info.nightscout.androidaps.plugins.pump.insight.database.InsightHistoryOffset;
|
import info.nightscout.androidaps.plugins.pump.insight.database.InsightHistoryOffset;
|
||||||
import info.nightscout.androidaps.plugins.pump.insight.database.InsightPumpID;
|
import info.nightscout.androidaps.plugins.pump.insight.database.InsightPumpID;
|
||||||
|
import info.nightscout.androidaps.plugins.pump.omnipod.driver.db.PodHistory;
|
||||||
import info.nightscout.androidaps.plugins.pump.virtual.VirtualPumpPlugin;
|
import info.nightscout.androidaps.plugins.pump.virtual.VirtualPumpPlugin;
|
||||||
import info.nightscout.androidaps.utils.JsonHelper;
|
import info.nightscout.androidaps.utils.JsonHelper;
|
||||||
import info.nightscout.androidaps.utils.PercentageSplitter;
|
import info.nightscout.androidaps.utils.PercentageSplitter;
|
||||||
|
@ -71,7 +73,7 @@ import info.nightscout.androidaps.utils.ToastUtils;
|
||||||
* direct calls to the corresponding methods (eg. resetDatabases) should be done by a central service.
|
* direct calls to the corresponding methods (eg. resetDatabases) should be done by a central service.
|
||||||
*/
|
*/
|
||||||
public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
|
public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
|
||||||
private static Logger log = StacktraceLoggerWrapper.getLogger(L.DATABASE);
|
private static Logger log = StacktraceLoggerWrapper.getLogger(LTag.DATABASE);
|
||||||
|
|
||||||
public static final String DATABASE_NAME = "AndroidAPSDb";
|
public static final String DATABASE_NAME = "AndroidAPSDb";
|
||||||
public static final String DATABASE_BGREADINGS = "BgReadings";
|
public static final String DATABASE_BGREADINGS = "BgReadings";
|
||||||
|
@ -86,8 +88,9 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
|
||||||
public static final String DATABASE_INSIGHT_HISTORY_OFFSETS = "InsightHistoryOffsets";
|
public static final String DATABASE_INSIGHT_HISTORY_OFFSETS = "InsightHistoryOffsets";
|
||||||
public static final String DATABASE_INSIGHT_BOLUS_IDS = "InsightBolusIDs";
|
public static final String DATABASE_INSIGHT_BOLUS_IDS = "InsightBolusIDs";
|
||||||
public static final String DATABASE_INSIGHT_PUMP_IDS = "InsightPumpIDs";
|
public static final String DATABASE_INSIGHT_PUMP_IDS = "InsightPumpIDs";
|
||||||
|
public static final String DATABASE_POD_HISTORY = "PodHistory";
|
||||||
|
|
||||||
private static final int DATABASE_VERSION = 11;
|
private static final int DATABASE_VERSION = 12;
|
||||||
|
|
||||||
public static Long earliestDataChange = null;
|
public static Long earliestDataChange = null;
|
||||||
|
|
||||||
|
@ -121,7 +124,7 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
|
||||||
@Override
|
@Override
|
||||||
public void onCreate(SQLiteDatabase database, ConnectionSource connectionSource) {
|
public void onCreate(SQLiteDatabase database, ConnectionSource connectionSource) {
|
||||||
try {
|
try {
|
||||||
if (L.isEnabled(L.DATABASE))
|
if (L.isEnabled(LTag.DATABASE))
|
||||||
log.info("onCreate");
|
log.info("onCreate");
|
||||||
TableUtils.createTableIfNotExists(connectionSource, TempTarget.class);
|
TableUtils.createTableIfNotExists(connectionSource, TempTarget.class);
|
||||||
TableUtils.createTableIfNotExists(connectionSource, BgReading.class);
|
TableUtils.createTableIfNotExists(connectionSource, BgReading.class);
|
||||||
|
@ -135,6 +138,7 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
|
||||||
TableUtils.createTableIfNotExists(connectionSource, InsightHistoryOffset.class);
|
TableUtils.createTableIfNotExists(connectionSource, InsightHistoryOffset.class);
|
||||||
TableUtils.createTableIfNotExists(connectionSource, InsightBolusID.class);
|
TableUtils.createTableIfNotExists(connectionSource, InsightBolusID.class);
|
||||||
TableUtils.createTableIfNotExists(connectionSource, InsightPumpID.class);
|
TableUtils.createTableIfNotExists(connectionSource, InsightPumpID.class);
|
||||||
|
TableUtils.createTableIfNotExists(connectionSource, PodHistory.class);
|
||||||
database.execSQL("INSERT INTO sqlite_sequence (name, seq) SELECT \"" + DATABASE_INSIGHT_BOLUS_IDS + "\", " + System.currentTimeMillis() + " " +
|
database.execSQL("INSERT INTO sqlite_sequence (name, seq) SELECT \"" + DATABASE_INSIGHT_BOLUS_IDS + "\", " + System.currentTimeMillis() + " " +
|
||||||
"WHERE NOT EXISTS (SELECT 1 FROM sqlite_sequence WHERE name = \"" + DATABASE_INSIGHT_BOLUS_IDS + "\")");
|
"WHERE NOT EXISTS (SELECT 1 FROM sqlite_sequence WHERE name = \"" + DATABASE_INSIGHT_BOLUS_IDS + "\")");
|
||||||
database.execSQL("INSERT INTO sqlite_sequence (name, seq) SELECT \"" + DATABASE_INSIGHT_PUMP_IDS + "\", " + System.currentTimeMillis() + " " +
|
database.execSQL("INSERT INTO sqlite_sequence (name, seq) SELECT \"" + DATABASE_INSIGHT_PUMP_IDS + "\", " + System.currentTimeMillis() + " " +
|
||||||
|
@ -211,6 +215,7 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
|
||||||
TableUtils.dropTable(connectionSource, CareportalEvent.class, true);
|
TableUtils.dropTable(connectionSource, CareportalEvent.class, true);
|
||||||
TableUtils.dropTable(connectionSource, ProfileSwitch.class, true);
|
TableUtils.dropTable(connectionSource, ProfileSwitch.class, true);
|
||||||
TableUtils.dropTable(connectionSource, TDD.class, true);
|
TableUtils.dropTable(connectionSource, TDD.class, true);
|
||||||
|
TableUtils.dropTable(connectionSource, PodHistory.class, true);
|
||||||
TableUtils.createTableIfNotExists(connectionSource, TempTarget.class);
|
TableUtils.createTableIfNotExists(connectionSource, TempTarget.class);
|
||||||
TableUtils.createTableIfNotExists(connectionSource, BgReading.class);
|
TableUtils.createTableIfNotExists(connectionSource, BgReading.class);
|
||||||
TableUtils.createTableIfNotExists(connectionSource, DanaRHistoryRecord.class);
|
TableUtils.createTableIfNotExists(connectionSource, DanaRHistoryRecord.class);
|
||||||
|
@ -220,6 +225,7 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
|
||||||
TableUtils.createTableIfNotExists(connectionSource, CareportalEvent.class);
|
TableUtils.createTableIfNotExists(connectionSource, CareportalEvent.class);
|
||||||
TableUtils.createTableIfNotExists(connectionSource, ProfileSwitch.class);
|
TableUtils.createTableIfNotExists(connectionSource, ProfileSwitch.class);
|
||||||
TableUtils.createTableIfNotExists(connectionSource, TDD.class);
|
TableUtils.createTableIfNotExists(connectionSource, TDD.class);
|
||||||
|
TableUtils.createTableIfNotExists(connectionSource, PodHistory.class);
|
||||||
updateEarliestDataChange(0);
|
updateEarliestDataChange(0);
|
||||||
} catch (SQLException e) {
|
} catch (SQLException e) {
|
||||||
log.error("Unhandled exception", e);
|
log.error("Unhandled exception", e);
|
||||||
|
@ -354,10 +360,14 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
|
||||||
return getDao(InsightHistoryOffset.class);
|
return getDao(InsightHistoryOffset.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private Dao<PodHistory, Long> getDaoPodHistory() throws SQLException {
|
||||||
|
return getDao(PodHistory.class);
|
||||||
|
}
|
||||||
|
|
||||||
public static long roundDateToSec(long date) {
|
public static long roundDateToSec(long date) {
|
||||||
long rounded = date - date % 1000;
|
long rounded = date - date % 1000;
|
||||||
if (rounded != date)
|
if (rounded != date)
|
||||||
if (L.isEnabled(L.DATABASE))
|
if (L.isEnabled(LTag.DATABASE))
|
||||||
log.debug("Rounding " + date + " to " + rounded);
|
log.debug("Rounding " + date + " to " + rounded);
|
||||||
return rounded;
|
return rounded;
|
||||||
}
|
}
|
||||||
|
@ -369,17 +379,17 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
|
||||||
BgReading old = getDaoBgReadings().queryForId(bgReading.date);
|
BgReading old = getDaoBgReadings().queryForId(bgReading.date);
|
||||||
if (old == null) {
|
if (old == null) {
|
||||||
getDaoBgReadings().create(bgReading);
|
getDaoBgReadings().create(bgReading);
|
||||||
if (L.isEnabled(L.DATABASE))
|
if (L.isEnabled(LTag.DATABASE))
|
||||||
log.debug("BG: New record from: " + from + " " + bgReading.toString());
|
log.debug("BG: New record from: " + from + " " + bgReading.toString());
|
||||||
scheduleBgChange(bgReading);
|
scheduleBgChange(bgReading);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (!old.isEqual(bgReading)) {
|
if (!old.isEqual(bgReading)) {
|
||||||
if (L.isEnabled(L.DATABASE))
|
if (L.isEnabled(LTag.DATABASE))
|
||||||
log.debug("BG: Similiar found: " + old.toString());
|
log.debug("BG: Similiar found: " + old.toString());
|
||||||
old.copyFrom(bgReading);
|
old.copyFrom(bgReading);
|
||||||
getDaoBgReadings().update(old);
|
getDaoBgReadings().update(old);
|
||||||
if (L.isEnabled(L.DATABASE))
|
if (L.isEnabled(LTag.DATABASE))
|
||||||
log.debug("BG: Updating record from: " + from + " New data: " + old.toString());
|
log.debug("BG: Updating record from: " + from + " New data: " + old.toString());
|
||||||
scheduleBgChange(bgReading);
|
scheduleBgChange(bgReading);
|
||||||
return false;
|
return false;
|
||||||
|
@ -402,7 +412,7 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
|
||||||
private static void scheduleBgChange(@Nullable final BgReading bgReading) {
|
private static void scheduleBgChange(@Nullable final BgReading bgReading) {
|
||||||
class PostRunnable implements Runnable {
|
class PostRunnable implements Runnable {
|
||||||
public void run() {
|
public void run() {
|
||||||
if (L.isEnabled(L.DATABASE))
|
if (L.isEnabled(LTag.DATABASE))
|
||||||
log.debug("Firing EventNewBg");
|
log.debug("Firing EventNewBg");
|
||||||
RxBus.Companion.getINSTANCE().send(new EventNewBG(bgReading));
|
RxBus.Companion.getINSTANCE().send(new EventNewBG(bgReading));
|
||||||
scheduledBgPost = null;
|
scheduledBgPost = null;
|
||||||
|
@ -631,7 +641,7 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
|
||||||
getDaoTempTargets().delete(old); // need to delete/create because date may change too
|
getDaoTempTargets().delete(old); // need to delete/create because date may change too
|
||||||
old.copyFrom(tempTarget);
|
old.copyFrom(tempTarget);
|
||||||
getDaoTempTargets().create(old);
|
getDaoTempTargets().create(old);
|
||||||
if (L.isEnabled(L.DATABASE))
|
if (L.isEnabled(LTag.DATABASE))
|
||||||
log.debug("TEMPTARGET: Updating record by date from: " + Source.getString(tempTarget.source) + " " + old.toString());
|
log.debug("TEMPTARGET: Updating record by date from: " + Source.getString(tempTarget.source) + " " + old.toString());
|
||||||
scheduleTemporaryTargetChange();
|
scheduleTemporaryTargetChange();
|
||||||
return true;
|
return true;
|
||||||
|
@ -651,7 +661,7 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
|
||||||
getDaoTempTargets().delete(old); // need to delete/create because date may change too
|
getDaoTempTargets().delete(old); // need to delete/create because date may change too
|
||||||
old.copyFrom(tempTarget);
|
old.copyFrom(tempTarget);
|
||||||
getDaoTempTargets().create(old);
|
getDaoTempTargets().create(old);
|
||||||
if (L.isEnabled(L.DATABASE))
|
if (L.isEnabled(LTag.DATABASE))
|
||||||
log.debug("TEMPTARGET: Updating record by _id from: " + Source.getString(tempTarget.source) + " " + old.toString());
|
log.debug("TEMPTARGET: Updating record by _id from: " + Source.getString(tempTarget.source) + " " + old.toString());
|
||||||
scheduleTemporaryTargetChange();
|
scheduleTemporaryTargetChange();
|
||||||
return true;
|
return true;
|
||||||
|
@ -659,14 +669,14 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
getDaoTempTargets().create(tempTarget);
|
getDaoTempTargets().create(tempTarget);
|
||||||
if (L.isEnabled(L.DATABASE))
|
if (L.isEnabled(LTag.DATABASE))
|
||||||
log.debug("TEMPTARGET: New record from: " + Source.getString(tempTarget.source) + " " + tempTarget.toString());
|
log.debug("TEMPTARGET: New record from: " + Source.getString(tempTarget.source) + " " + tempTarget.toString());
|
||||||
scheduleTemporaryTargetChange();
|
scheduleTemporaryTargetChange();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (tempTarget.source == Source.USER) {
|
if (tempTarget.source == Source.USER) {
|
||||||
getDaoTempTargets().create(tempTarget);
|
getDaoTempTargets().create(tempTarget);
|
||||||
if (L.isEnabled(L.DATABASE))
|
if (L.isEnabled(LTag.DATABASE))
|
||||||
log.debug("TEMPTARGET: New record from: " + Source.getString(tempTarget.source) + " " + tempTarget.toString());
|
log.debug("TEMPTARGET: New record from: " + Source.getString(tempTarget.source) + " " + tempTarget.toString());
|
||||||
scheduleTemporaryTargetChange();
|
scheduleTemporaryTargetChange();
|
||||||
return true;
|
return true;
|
||||||
|
@ -689,7 +699,7 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
|
||||||
private static void scheduleTemporaryTargetChange() {
|
private static void scheduleTemporaryTargetChange() {
|
||||||
class PostRunnable implements Runnable {
|
class PostRunnable implements Runnable {
|
||||||
public void run() {
|
public void run() {
|
||||||
if (L.isEnabled(L.DATABASE))
|
if (L.isEnabled(LTag.DATABASE))
|
||||||
log.debug("Firing EventTempTargetChange");
|
log.debug("Firing EventTempTargetChange");
|
||||||
RxBus.Companion.getINSTANCE().send(new EventTempTargetChange());
|
RxBus.Companion.getINSTANCE().send(new EventTempTargetChange());
|
||||||
scheduledTemTargetPost = null;
|
scheduledTemTargetPost = null;
|
||||||
|
@ -815,7 +825,7 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
|
||||||
List<TemporaryBasal> trList = getDaoTemporaryBasal().query(preparedQuery);
|
List<TemporaryBasal> trList = getDaoTemporaryBasal().query(preparedQuery);
|
||||||
if (trList.size() > 0) {
|
if (trList.size() > 0) {
|
||||||
// do nothing, pump history record cannot be changed
|
// do nothing, pump history record cannot be changed
|
||||||
if (L.isEnabled(L.DATABASE))
|
if (L.isEnabled(LTag.DATABASE))
|
||||||
log.debug("TEMPBASAL: Already exists from: " + Source.getString(tempBasal.source) + " " + tempBasal.toString());
|
log.debug("TEMPBASAL: Already exists from: " + Source.getString(tempBasal.source) + " " + tempBasal.toString());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -833,7 +843,7 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
|
||||||
old.copyFromPump(tempBasal);
|
old.copyFromPump(tempBasal);
|
||||||
old.source = Source.PUMP;
|
old.source = Source.PUMP;
|
||||||
|
|
||||||
if (L.isEnabled(L.DATABASE))
|
if (L.isEnabled(LTag.DATABASE))
|
||||||
log.debug("TEMPBASAL: Updated record with Pump Data : " + Source.getString(tempBasal.source) + " " + tempBasal.toString());
|
log.debug("TEMPBASAL: Updated record with Pump Data : " + Source.getString(tempBasal.source) + " " + tempBasal.toString());
|
||||||
|
|
||||||
getDaoTemporaryBasal().update(old);
|
getDaoTemporaryBasal().update(old);
|
||||||
|
@ -845,7 +855,7 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
|
||||||
}
|
}
|
||||||
|
|
||||||
getDaoTemporaryBasal().create(tempBasal);
|
getDaoTemporaryBasal().create(tempBasal);
|
||||||
if (L.isEnabled(L.DATABASE))
|
if (L.isEnabled(LTag.DATABASE))
|
||||||
log.debug("TEMPBASAL: New record from: " + Source.getString(tempBasal.source) + " " + tempBasal.toString());
|
log.debug("TEMPBASAL: New record from: " + Source.getString(tempBasal.source) + " " + tempBasal.toString());
|
||||||
updateEarliestDataChange(tempBasal.date);
|
updateEarliestDataChange(tempBasal.date);
|
||||||
scheduleTemporaryBasalChange();
|
scheduleTemporaryBasalChange();
|
||||||
|
@ -863,7 +873,7 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
|
||||||
getDaoTemporaryBasal().delete(old); // need to delete/create because date may change too
|
getDaoTemporaryBasal().delete(old); // need to delete/create because date may change too
|
||||||
old.copyFrom(tempBasal);
|
old.copyFrom(tempBasal);
|
||||||
getDaoTemporaryBasal().create(old);
|
getDaoTemporaryBasal().create(old);
|
||||||
if (L.isEnabled(L.DATABASE))
|
if (L.isEnabled(LTag.DATABASE))
|
||||||
log.debug("TEMPBASAL: Updating record by date from: " + Source.getString(tempBasal.source) + " " + old.toString());
|
log.debug("TEMPBASAL: Updating record by date from: " + Source.getString(tempBasal.source) + " " + old.toString());
|
||||||
updateEarliestDataChange(oldDate);
|
updateEarliestDataChange(oldDate);
|
||||||
updateEarliestDataChange(old.date);
|
updateEarliestDataChange(old.date);
|
||||||
|
@ -886,7 +896,7 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
|
||||||
getDaoTemporaryBasal().delete(old); // need to delete/create because date may change too
|
getDaoTemporaryBasal().delete(old); // need to delete/create because date may change too
|
||||||
old.copyFrom(tempBasal);
|
old.copyFrom(tempBasal);
|
||||||
getDaoTemporaryBasal().create(old);
|
getDaoTemporaryBasal().create(old);
|
||||||
if (L.isEnabled(L.DATABASE))
|
if (L.isEnabled(LTag.DATABASE))
|
||||||
log.debug("TEMPBASAL: Updating record by _id from: " + Source.getString(tempBasal.source) + " " + old.toString());
|
log.debug("TEMPBASAL: Updating record by _id from: " + Source.getString(tempBasal.source) + " " + old.toString());
|
||||||
updateEarliestDataChange(oldDate);
|
updateEarliestDataChange(oldDate);
|
||||||
updateEarliestDataChange(old.date);
|
updateEarliestDataChange(old.date);
|
||||||
|
@ -896,7 +906,7 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
getDaoTemporaryBasal().create(tempBasal);
|
getDaoTemporaryBasal().create(tempBasal);
|
||||||
if (L.isEnabled(L.DATABASE))
|
if (L.isEnabled(LTag.DATABASE))
|
||||||
log.debug("TEMPBASAL: New record from: " + Source.getString(tempBasal.source) + " " + tempBasal.toString());
|
log.debug("TEMPBASAL: New record from: " + Source.getString(tempBasal.source) + " " + tempBasal.toString());
|
||||||
updateEarliestDataChange(tempBasal.date);
|
updateEarliestDataChange(tempBasal.date);
|
||||||
scheduleTemporaryBasalChange();
|
scheduleTemporaryBasalChange();
|
||||||
|
@ -904,7 +914,7 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
|
||||||
}
|
}
|
||||||
if (tempBasal.source == Source.USER) {
|
if (tempBasal.source == Source.USER) {
|
||||||
getDaoTemporaryBasal().create(tempBasal);
|
getDaoTemporaryBasal().create(tempBasal);
|
||||||
if (L.isEnabled(L.DATABASE))
|
if (L.isEnabled(LTag.DATABASE))
|
||||||
log.debug("TEMPBASAL: New record from: " + Source.getString(tempBasal.source) + " " + tempBasal.toString());
|
log.debug("TEMPBASAL: New record from: " + Source.getString(tempBasal.source) + " " + tempBasal.toString());
|
||||||
updateEarliestDataChange(tempBasal.date);
|
updateEarliestDataChange(tempBasal.date);
|
||||||
scheduleTemporaryBasalChange();
|
scheduleTemporaryBasalChange();
|
||||||
|
@ -961,7 +971,7 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
|
||||||
private static void scheduleTemporaryBasalChange() {
|
private static void scheduleTemporaryBasalChange() {
|
||||||
class PostRunnable implements Runnable {
|
class PostRunnable implements Runnable {
|
||||||
public void run() {
|
public void run() {
|
||||||
if (L.isEnabled(L.DATABASE))
|
if (L.isEnabled(LTag.DATABASE))
|
||||||
log.debug("Firing EventTempBasalChange");
|
log.debug("Firing EventTempBasalChange");
|
||||||
RxBus.Companion.getINSTANCE().send(new EventReloadTempBasalData());
|
RxBus.Companion.getINSTANCE().send(new EventReloadTempBasalData());
|
||||||
RxBus.Companion.getINSTANCE().send(new EventTempBasalChange());
|
RxBus.Companion.getINSTANCE().send(new EventTempBasalChange());
|
||||||
|
@ -1056,7 +1066,7 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
|
||||||
public void deleteTempBasalById(String _id) {
|
public void deleteTempBasalById(String _id) {
|
||||||
TemporaryBasal stored = findTempBasalById(_id);
|
TemporaryBasal stored = findTempBasalById(_id);
|
||||||
if (stored != null) {
|
if (stored != null) {
|
||||||
if (L.isEnabled(L.DATABASE))
|
if (L.isEnabled(LTag.DATABASE))
|
||||||
log.debug("TEMPBASAL: Removing TempBasal record from database: " + stored.toString());
|
log.debug("TEMPBASAL: Removing TempBasal record from database: " + stored.toString());
|
||||||
delete(stored);
|
delete(stored);
|
||||||
updateEarliestDataChange(stored.date);
|
updateEarliestDataChange(stored.date);
|
||||||
|
@ -1111,7 +1121,7 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
|
||||||
|
|
||||||
public boolean createOrUpdate(ExtendedBolus extendedBolus) {
|
public boolean createOrUpdate(ExtendedBolus extendedBolus) {
|
||||||
try {
|
try {
|
||||||
if (L.isEnabled(L.DATABASE))
|
if (L.isEnabled(LTag.DATABASE))
|
||||||
log.debug("EXTENDEDBOLUS: createOrUpdate: " + Source.getString(extendedBolus.source) + " " + extendedBolus.log());
|
log.debug("EXTENDEDBOLUS: createOrUpdate: " + Source.getString(extendedBolus.source) + " " + extendedBolus.log());
|
||||||
|
|
||||||
ExtendedBolus old;
|
ExtendedBolus old;
|
||||||
|
@ -1136,7 +1146,7 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
|
||||||
}
|
}
|
||||||
getDaoExtendedBolus().createOrUpdate(extendedBolus);
|
getDaoExtendedBolus().createOrUpdate(extendedBolus);
|
||||||
}
|
}
|
||||||
if (L.isEnabled(L.DATABASE))
|
if (L.isEnabled(LTag.DATABASE))
|
||||||
log.debug("EXTENDEDBOLUS: New record from: " + Source.getString(extendedBolus.source) + " " + extendedBolus.log());
|
log.debug("EXTENDEDBOLUS: New record from: " + Source.getString(extendedBolus.source) + " " + extendedBolus.log());
|
||||||
updateEarliestDataChange(extendedBolus.date);
|
updateEarliestDataChange(extendedBolus.date);
|
||||||
scheduleExtendedBolusChange();
|
scheduleExtendedBolusChange();
|
||||||
|
@ -1150,7 +1160,7 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
|
||||||
getDaoExtendedBolus().delete(old); // need to delete/create because date may change too
|
getDaoExtendedBolus().delete(old); // need to delete/create because date may change too
|
||||||
old.copyFrom(extendedBolus);
|
old.copyFrom(extendedBolus);
|
||||||
getDaoExtendedBolus().create(old);
|
getDaoExtendedBolus().create(old);
|
||||||
if (L.isEnabled(L.DATABASE))
|
if (L.isEnabled(LTag.DATABASE))
|
||||||
log.debug("EXTENDEDBOLUS: Updating record by date from: " + Source.getString(extendedBolus.source) + " " + old.log());
|
log.debug("EXTENDEDBOLUS: Updating record by date from: " + Source.getString(extendedBolus.source) + " " + old.log());
|
||||||
updateEarliestDataChange(oldDate);
|
updateEarliestDataChange(oldDate);
|
||||||
updateEarliestDataChange(old.date);
|
updateEarliestDataChange(old.date);
|
||||||
|
@ -1173,7 +1183,7 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
|
||||||
getDaoExtendedBolus().delete(old); // need to delete/create because date may change too
|
getDaoExtendedBolus().delete(old); // need to delete/create because date may change too
|
||||||
old.copyFrom(extendedBolus);
|
old.copyFrom(extendedBolus);
|
||||||
getDaoExtendedBolus().create(old);
|
getDaoExtendedBolus().create(old);
|
||||||
if (L.isEnabled(L.DATABASE))
|
if (L.isEnabled(LTag.DATABASE))
|
||||||
log.debug("EXTENDEDBOLUS: Updating record by _id from: " + Source.getString(extendedBolus.source) + " " + old.log());
|
log.debug("EXTENDEDBOLUS: Updating record by _id from: " + Source.getString(extendedBolus.source) + " " + old.log());
|
||||||
updateEarliestDataChange(oldDate);
|
updateEarliestDataChange(oldDate);
|
||||||
updateEarliestDataChange(old.date);
|
updateEarliestDataChange(old.date);
|
||||||
|
@ -1183,7 +1193,7 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
getDaoExtendedBolus().create(extendedBolus);
|
getDaoExtendedBolus().create(extendedBolus);
|
||||||
if (L.isEnabled(L.DATABASE))
|
if (L.isEnabled(LTag.DATABASE))
|
||||||
log.debug("EXTENDEDBOLUS: New record from: " + Source.getString(extendedBolus.source) + " " + extendedBolus.log());
|
log.debug("EXTENDEDBOLUS: New record from: " + Source.getString(extendedBolus.source) + " " + extendedBolus.log());
|
||||||
updateEarliestDataChange(extendedBolus.date);
|
updateEarliestDataChange(extendedBolus.date);
|
||||||
scheduleExtendedBolusChange();
|
scheduleExtendedBolusChange();
|
||||||
|
@ -1191,7 +1201,7 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
|
||||||
}
|
}
|
||||||
if (extendedBolus.source == Source.USER) {
|
if (extendedBolus.source == Source.USER) {
|
||||||
getDaoExtendedBolus().create(extendedBolus);
|
getDaoExtendedBolus().create(extendedBolus);
|
||||||
if (L.isEnabled(L.DATABASE))
|
if (L.isEnabled(LTag.DATABASE))
|
||||||
log.debug("EXTENDEDBOLUS: New record from: " + Source.getString(extendedBolus.source) + " " + extendedBolus.log());
|
log.debug("EXTENDEDBOLUS: New record from: " + Source.getString(extendedBolus.source) + " " + extendedBolus.log());
|
||||||
updateEarliestDataChange(extendedBolus.date);
|
updateEarliestDataChange(extendedBolus.date);
|
||||||
scheduleExtendedBolusChange();
|
scheduleExtendedBolusChange();
|
||||||
|
@ -1240,10 +1250,26 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
|
||||||
return new ArrayList<ExtendedBolus>();
|
return new ArrayList<ExtendedBolus>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public List<ExtendedBolus> getExtendedBolusDataFromTime(long from, long to, boolean ascending) {
|
||||||
|
try {
|
||||||
|
List<ExtendedBolus> extendedBoluses;
|
||||||
|
QueryBuilder<ExtendedBolus, Long> queryBuilder = getDaoExtendedBolus().queryBuilder();
|
||||||
|
queryBuilder.orderBy("date", ascending);
|
||||||
|
Where where = queryBuilder.where();
|
||||||
|
where.between("date", from, to);
|
||||||
|
PreparedQuery<ExtendedBolus> preparedQuery = queryBuilder.prepare();
|
||||||
|
extendedBoluses = getDaoExtendedBolus().query(preparedQuery);
|
||||||
|
return extendedBoluses;
|
||||||
|
} catch (SQLException e) {
|
||||||
|
log.error("Unhandled exception", e);
|
||||||
|
}
|
||||||
|
return new ArrayList<ExtendedBolus>();
|
||||||
|
}
|
||||||
|
|
||||||
public void deleteExtendedBolusById(String _id) {
|
public void deleteExtendedBolusById(String _id) {
|
||||||
ExtendedBolus stored = findExtendedBolusById(_id);
|
ExtendedBolus stored = findExtendedBolusById(_id);
|
||||||
if (stored != null) {
|
if (stored != null) {
|
||||||
if (L.isEnabled(L.DATABASE))
|
if (L.isEnabled(LTag.DATABASE))
|
||||||
log.debug("EXTENDEDBOLUS: Removing ExtendedBolus record from database: " + stored.toString());
|
log.debug("EXTENDEDBOLUS: Removing ExtendedBolus record from database: " + stored.toString());
|
||||||
delete(stored);
|
delete(stored);
|
||||||
updateEarliestDataChange(stored.date);
|
updateEarliestDataChange(stored.date);
|
||||||
|
@ -1297,7 +1323,7 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
|
||||||
private static void scheduleExtendedBolusChange() {
|
private static void scheduleExtendedBolusChange() {
|
||||||
class PostRunnable implements Runnable {
|
class PostRunnable implements Runnable {
|
||||||
public void run() {
|
public void run() {
|
||||||
if (L.isEnabled(L.DATABASE))
|
if (L.isEnabled(LTag.DATABASE))
|
||||||
log.debug("Firing EventExtendedBolusChange");
|
log.debug("Firing EventExtendedBolusChange");
|
||||||
RxBus.Companion.getINSTANCE().send(new EventReloadTreatmentData(new EventExtendedBolusChange()));
|
RxBus.Companion.getINSTANCE().send(new EventReloadTreatmentData(new EventExtendedBolusChange()));
|
||||||
if (earliestDataChange != null)
|
if (earliestDataChange != null)
|
||||||
|
@ -1459,11 +1485,11 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
|
||||||
|
|
||||||
if (list.size() == 1) {
|
if (list.size() == 1) {
|
||||||
CareportalEvent record = list.get(0);
|
CareportalEvent record = list.get(0);
|
||||||
if (L.isEnabled(L.DATABASE))
|
if (L.isEnabled(LTag.DATABASE))
|
||||||
log.debug("Removing CareportalEvent record from database: " + record.toString());
|
log.debug("Removing CareportalEvent record from database: " + record.toString());
|
||||||
delete(record);
|
delete(record);
|
||||||
} else {
|
} else {
|
||||||
if (L.isEnabled(L.DATABASE))
|
if (L.isEnabled(LTag.DATABASE))
|
||||||
log.debug("CareportalEvent not found database: " + _id);
|
log.debug("CareportalEvent not found database: " + _id);
|
||||||
}
|
}
|
||||||
} catch (SQLException e) {
|
} catch (SQLException e) {
|
||||||
|
@ -1483,12 +1509,12 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
|
||||||
if (list.size() == 0) {
|
if (list.size() == 0) {
|
||||||
careportalEvent = new CareportalEvent(MainApp.instance());
|
careportalEvent = new CareportalEvent(MainApp.instance());
|
||||||
careportalEvent.source = Source.NIGHTSCOUT;
|
careportalEvent.source = Source.NIGHTSCOUT;
|
||||||
if (L.isEnabled(L.DATABASE))
|
if (L.isEnabled(LTag.DATABASE))
|
||||||
log.debug("Adding CareportalEvent record to database: " + trJson.toString());
|
log.debug("Adding CareportalEvent record to database: " + trJson.toString());
|
||||||
// Record does not exists. add
|
// Record does not exists. add
|
||||||
} else if (list.size() == 1) {
|
} else if (list.size() == 1) {
|
||||||
careportalEvent = list.get(0);
|
careportalEvent = list.get(0);
|
||||||
if (L.isEnabled(L.DATABASE))
|
if (L.isEnabled(LTag.DATABASE))
|
||||||
log.debug("Updating CareportalEvent record in database: " + trJson.toString());
|
log.debug("Updating CareportalEvent record in database: " + trJson.toString());
|
||||||
} else {
|
} else {
|
||||||
log.error("Something went wrong");
|
log.error("Something went wrong");
|
||||||
|
@ -1507,7 +1533,7 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
|
||||||
private static void scheduleCareportalEventChange() {
|
private static void scheduleCareportalEventChange() {
|
||||||
class PostRunnable implements Runnable {
|
class PostRunnable implements Runnable {
|
||||||
public void run() {
|
public void run() {
|
||||||
if (L.isEnabled(L.DATABASE))
|
if (L.isEnabled(LTag.DATABASE))
|
||||||
log.debug("Firing scheduleCareportalEventChange");
|
log.debug("Firing scheduleCareportalEventChange");
|
||||||
RxBus.Companion.getINSTANCE().send(new EventCareportalEventChange());
|
RxBus.Companion.getINSTANCE().send(new EventCareportalEventChange());
|
||||||
scheduledCareportalEventPost = null;
|
scheduledCareportalEventPost = null;
|
||||||
|
@ -1620,7 +1646,7 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
|
||||||
profileSwitch.profileName = old.profileName; // preserver profileName to prevent multiple CPP extension
|
profileSwitch.profileName = old.profileName; // preserver profileName to prevent multiple CPP extension
|
||||||
getDaoProfileSwitch().delete(old); // need to delete/create because date may change too
|
getDaoProfileSwitch().delete(old); // need to delete/create because date may change too
|
||||||
getDaoProfileSwitch().create(profileSwitch);
|
getDaoProfileSwitch().create(profileSwitch);
|
||||||
if (L.isEnabled(L.DATABASE))
|
if (L.isEnabled(LTag.DATABASE))
|
||||||
log.debug("PROFILESWITCH: Updating record by date from: " + Source.getString(profileSwitch.source) + " " + old.toString());
|
log.debug("PROFILESWITCH: Updating record by date from: " + Source.getString(profileSwitch.source) + " " + old.toString());
|
||||||
scheduleProfileSwitchChange();
|
scheduleProfileSwitchChange();
|
||||||
return true;
|
return true;
|
||||||
|
@ -1640,7 +1666,7 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
|
||||||
getDaoProfileSwitch().delete(old); // need to delete/create because date may change too
|
getDaoProfileSwitch().delete(old); // need to delete/create because date may change too
|
||||||
old.copyFrom(profileSwitch);
|
old.copyFrom(profileSwitch);
|
||||||
getDaoProfileSwitch().create(old);
|
getDaoProfileSwitch().create(old);
|
||||||
if (L.isEnabled(L.DATABASE))
|
if (L.isEnabled(LTag.DATABASE))
|
||||||
log.debug("PROFILESWITCH: Updating record by _id from: " + Source.getString(profileSwitch.source) + " " + old.toString());
|
log.debug("PROFILESWITCH: Updating record by _id from: " + Source.getString(profileSwitch.source) + " " + old.toString());
|
||||||
scheduleProfileSwitchChange();
|
scheduleProfileSwitchChange();
|
||||||
return true;
|
return true;
|
||||||
|
@ -1650,14 +1676,14 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
|
||||||
// look for already added percentage from NS
|
// look for already added percentage from NS
|
||||||
profileSwitch.profileName = PercentageSplitter.pureName(profileSwitch.profileName);
|
profileSwitch.profileName = PercentageSplitter.pureName(profileSwitch.profileName);
|
||||||
getDaoProfileSwitch().create(profileSwitch);
|
getDaoProfileSwitch().create(profileSwitch);
|
||||||
if (L.isEnabled(L.DATABASE))
|
if (L.isEnabled(LTag.DATABASE))
|
||||||
log.debug("PROFILESWITCH: New record from: " + Source.getString(profileSwitch.source) + " " + profileSwitch.toString());
|
log.debug("PROFILESWITCH: New record from: " + Source.getString(profileSwitch.source) + " " + profileSwitch.toString());
|
||||||
scheduleProfileSwitchChange();
|
scheduleProfileSwitchChange();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (profileSwitch.source == Source.USER) {
|
if (profileSwitch.source == Source.USER) {
|
||||||
getDaoProfileSwitch().create(profileSwitch);
|
getDaoProfileSwitch().create(profileSwitch);
|
||||||
if (L.isEnabled(L.DATABASE))
|
if (L.isEnabled(LTag.DATABASE))
|
||||||
log.debug("PROFILESWITCH: New record from: " + Source.getString(profileSwitch.source) + " " + profileSwitch.toString());
|
log.debug("PROFILESWITCH: New record from: " + Source.getString(profileSwitch.source) + " " + profileSwitch.toString());
|
||||||
scheduleProfileSwitchChange();
|
scheduleProfileSwitchChange();
|
||||||
return true;
|
return true;
|
||||||
|
@ -1680,7 +1706,7 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
|
||||||
private static void scheduleProfileSwitchChange() {
|
private static void scheduleProfileSwitchChange() {
|
||||||
class PostRunnable implements Runnable {
|
class PostRunnable implements Runnable {
|
||||||
public void run() {
|
public void run() {
|
||||||
if (L.isEnabled(L.DATABASE))
|
if (L.isEnabled(LTag.DATABASE))
|
||||||
log.debug("Firing EventProfileNeedsUpdate");
|
log.debug("Firing EventProfileNeedsUpdate");
|
||||||
RxBus.Companion.getINSTANCE().send(new EventReloadProfileSwitchData());
|
RxBus.Companion.getINSTANCE().send(new EventReloadProfileSwitchData());
|
||||||
RxBus.Companion.getINSTANCE().send(new EventProfileNeedsUpdate());
|
RxBus.Companion.getINSTANCE().send(new EventProfileNeedsUpdate());
|
||||||
|
@ -1732,17 +1758,17 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
|
||||||
Profile profile = store.getSpecificProfile(profileSwitch.profileName);
|
Profile profile = store.getSpecificProfile(profileSwitch.profileName);
|
||||||
if (profile != null) {
|
if (profile != null) {
|
||||||
profileSwitch.profileJson = profile.getData().toString();
|
profileSwitch.profileJson = profile.getData().toString();
|
||||||
if (L.isEnabled(L.DATABASE))
|
if (L.isEnabled(LTag.DATABASE))
|
||||||
log.debug("Profile switch prefilled with JSON from local store");
|
log.debug("Profile switch prefilled with JSON from local store");
|
||||||
// Update data in NS
|
// Update data in NS
|
||||||
NSUpload.updateProfileSwitch(profileSwitch);
|
NSUpload.updateProfileSwitch(profileSwitch);
|
||||||
} else {
|
} else {
|
||||||
if (L.isEnabled(L.DATABASE))
|
if (L.isEnabled(LTag.DATABASE))
|
||||||
log.debug("JSON for profile switch doesn't exist. Ignoring: " + trJson.toString());
|
log.debug("JSON for profile switch doesn't exist. Ignoring: " + trJson.toString());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (L.isEnabled(L.DATABASE))
|
if (L.isEnabled(LTag.DATABASE))
|
||||||
log.debug("Store for profile switch doesn't exist. Ignoring: " + trJson.toString());
|
log.debug("Store for profile switch doesn't exist. Ignoring: " + trJson.toString());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -1758,7 +1784,7 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
|
||||||
public void deleteProfileSwitchById(String _id) {
|
public void deleteProfileSwitchById(String _id) {
|
||||||
ProfileSwitch stored = findProfileSwitchById(_id);
|
ProfileSwitch stored = findProfileSwitchById(_id);
|
||||||
if (stored != null) {
|
if (stored != null) {
|
||||||
if (L.isEnabled(L.DATABASE))
|
if (L.isEnabled(LTag.DATABASE))
|
||||||
log.debug("PROFILESWITCH: Removing ProfileSwitch record from database: " + stored.toString());
|
log.debug("PROFILESWITCH: Removing ProfileSwitch record from database: " + stored.toString());
|
||||||
delete(stored);
|
delete(stored);
|
||||||
scheduleTemporaryTargetChange();
|
scheduleTemporaryTargetChange();
|
||||||
|
@ -1847,4 +1873,34 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
|
||||||
}
|
}
|
||||||
|
|
||||||
// ---------------- Food handling ---------------
|
// ---------------- Food handling ---------------
|
||||||
|
|
||||||
|
// ---------------- PodHistory handling ---------------
|
||||||
|
|
||||||
|
public void createOrUpdate(PodHistory podHistory) {
|
||||||
|
try {
|
||||||
|
getDaoPodHistory().createOrUpdate(podHistory);
|
||||||
|
} catch (SQLException e) {
|
||||||
|
log.error("Unhandled exception", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public List<PodHistory> getPodHistoryFromTime(long from, boolean ascending) {
|
||||||
|
try {
|
||||||
|
Dao<PodHistory, Long> daoPodHistory = getDaoPodHistory();
|
||||||
|
List<PodHistory> podHistories;
|
||||||
|
QueryBuilder<PodHistory, Long> queryBuilder = daoPodHistory.queryBuilder();
|
||||||
|
queryBuilder.orderBy("date", ascending);
|
||||||
|
//queryBuilder.limit(100L);
|
||||||
|
Where where = queryBuilder.where();
|
||||||
|
where.ge("date", from);
|
||||||
|
PreparedQuery<PodHistory> preparedQuery = queryBuilder.prepare();
|
||||||
|
podHistories = daoPodHistory.query(preparedQuery);
|
||||||
|
return podHistories;
|
||||||
|
} catch (SQLException e) {
|
||||||
|
log.error("Unhandled exception", e);
|
||||||
|
}
|
||||||
|
return new ArrayList<>();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,16 +1,13 @@
|
||||||
package info.nightscout.androidaps.db;
|
package info.nightscout.androidaps.db;
|
||||||
|
|
||||||
import com.google.common.base.Charsets;
|
|
||||||
import com.google.common.hash.Hashing;
|
|
||||||
import com.j256.ormlite.field.DatabaseField;
|
import com.j256.ormlite.field.DatabaseField;
|
||||||
import com.j256.ormlite.table.DatabaseTable;
|
import com.j256.ormlite.table.DatabaseTable;
|
||||||
|
|
||||||
import org.json.JSONException;
|
import org.json.JSONException;
|
||||||
import org.json.JSONObject;
|
import org.json.JSONObject;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
import info.nightscout.androidaps.logging.L;
|
import info.nightscout.androidaps.logging.LTag;
|
||||||
import info.nightscout.androidaps.logging.StacktraceLoggerWrapper;
|
import info.nightscout.androidaps.logging.StacktraceLoggerWrapper;
|
||||||
import info.nightscout.androidaps.utils.DateUtil;
|
import info.nightscout.androidaps.utils.DateUtil;
|
||||||
|
|
||||||
|
@ -21,7 +18,7 @@ import info.nightscout.androidaps.utils.DateUtil;
|
||||||
*/
|
*/
|
||||||
@DatabaseTable(tableName = DatabaseHelper.DATABASE_DBREQUESTS)
|
@DatabaseTable(tableName = DatabaseHelper.DATABASE_DBREQUESTS)
|
||||||
public class DbRequest {
|
public class DbRequest {
|
||||||
private static Logger log = StacktraceLoggerWrapper.getLogger(L.DATABASE);
|
private static Logger log = StacktraceLoggerWrapper.getLogger(LTag.DATABASE);
|
||||||
|
|
||||||
@DatabaseField(id = true)
|
@DatabaseField(id = true)
|
||||||
public String nsClientID = null;
|
public String nsClientID = null;
|
||||||
|
@ -88,9 +85,9 @@ public class DbRequest {
|
||||||
public String log() {
|
public String log() {
|
||||||
return
|
return
|
||||||
"\nnsClientID:" + nsClientID +
|
"\nnsClientID:" + nsClientID +
|
||||||
"\naction:" + action +
|
"\naction:" + action +
|
||||||
"\ncollection:" + collection +
|
"\ncollection:" + collection +
|
||||||
"\ndata:" + data +
|
"\ndata:" + data +
|
||||||
"\n_id:" + _id;
|
"\n_id:" + _id;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,6 +22,7 @@ import info.nightscout.androidaps.data.Profile;
|
||||||
import info.nightscout.androidaps.interfaces.Interval;
|
import info.nightscout.androidaps.interfaces.Interval;
|
||||||
import info.nightscout.androidaps.logging.AAPSLogger;
|
import info.nightscout.androidaps.logging.AAPSLogger;
|
||||||
import info.nightscout.androidaps.logging.L;
|
import info.nightscout.androidaps.logging.L;
|
||||||
|
import info.nightscout.androidaps.logging.LTag;
|
||||||
import info.nightscout.androidaps.plugins.bus.RxBusWrapper;
|
import info.nightscout.androidaps.plugins.bus.RxBusWrapper;
|
||||||
import info.nightscout.androidaps.plugins.general.overview.events.EventNewNotification;
|
import info.nightscout.androidaps.plugins.general.overview.events.EventNewNotification;
|
||||||
import info.nightscout.androidaps.plugins.general.overview.graphExtensions.DataPointWithLabelInterface;
|
import info.nightscout.androidaps.plugins.general.overview.graphExtensions.DataPointWithLabelInterface;
|
||||||
|
@ -253,13 +254,11 @@ public class ProfileSwitch implements Interval, DataPointWithLabelInterface {
|
||||||
if (event.date <= time && event.date > (time - T.mins(5).msecs())) {
|
if (event.date <= time && event.date > (time - T.mins(5).msecs())) {
|
||||||
if (zeroDurationOnly) {
|
if (zeroDurationOnly) {
|
||||||
if (event.durationInMinutes == 0) {
|
if (event.durationInMinutes == 0) {
|
||||||
if (L.isEnabled(L.DATABASE))
|
aapsLogger.debug(LTag.DATABASE, "Found ProfileSwitch event for time: " + DateUtil.dateAndTimeString(time) + " " + event.toString());
|
||||||
aapsLogger.debug("Found ProfileSwitch event for time: " + DateUtil.dateAndTimeString(time) + " " + event.toString());
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (L.isEnabled(L.DATABASE))
|
aapsLogger.debug(LTag.DATABASE, "Found ProfileSwitch event for time: " + DateUtil.dateAndTimeString(time) + " " + event.toString());
|
||||||
aapsLogger.debug("Found ProfileSwitch event for time: " + DateUtil.dateAndTimeString(time) + " " + event.toString());
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,6 +14,7 @@ import info.nightscout.androidaps.R;
|
||||||
import info.nightscout.androidaps.data.Profile;
|
import info.nightscout.androidaps.data.Profile;
|
||||||
import info.nightscout.androidaps.interfaces.Interval;
|
import info.nightscout.androidaps.interfaces.Interval;
|
||||||
import info.nightscout.androidaps.logging.L;
|
import info.nightscout.androidaps.logging.L;
|
||||||
|
import info.nightscout.androidaps.logging.LTag;
|
||||||
import info.nightscout.androidaps.logging.StacktraceLoggerWrapper;
|
import info.nightscout.androidaps.logging.StacktraceLoggerWrapper;
|
||||||
import info.nightscout.androidaps.utils.DateUtil;
|
import info.nightscout.androidaps.utils.DateUtil;
|
||||||
import info.nightscout.androidaps.utils.DecimalFormatter;
|
import info.nightscout.androidaps.utils.DecimalFormatter;
|
||||||
|
@ -21,7 +22,7 @@ import info.nightscout.androidaps.utils.resources.ResourceHelper;
|
||||||
|
|
||||||
@DatabaseTable(tableName = DatabaseHelper.DATABASE_TEMPTARGETS)
|
@DatabaseTable(tableName = DatabaseHelper.DATABASE_TEMPTARGETS)
|
||||||
public class TempTarget implements Interval {
|
public class TempTarget implements Interval {
|
||||||
private static Logger log = StacktraceLoggerWrapper.getLogger(L.DATABASE);
|
private static Logger log = StacktraceLoggerWrapper.getLogger(LTag.DATABASE);
|
||||||
|
|
||||||
@DatabaseField(id = true)
|
@DatabaseField(id = true)
|
||||||
public long date;
|
public long date;
|
||||||
|
|
|
@ -110,6 +110,8 @@ public class TemporaryBasal implements Interval, DbObjectBase {
|
||||||
}
|
}
|
||||||
|
|
||||||
public TemporaryBasal(ExtendedBolus extendedBolus) {
|
public TemporaryBasal(ExtendedBolus extendedBolus) {
|
||||||
|
injector = MainApp.instance();
|
||||||
|
injector.androidInjector().inject(this);
|
||||||
double basal = profileFunction.getProfile(extendedBolus.date).getBasal(extendedBolus.date);
|
double basal = profileFunction.getProfile(extendedBolus.date).getBasal(extendedBolus.date);
|
||||||
this.date = extendedBolus.date;
|
this.date = extendedBolus.date;
|
||||||
this.isValid = extendedBolus.isValid;
|
this.isValid = extendedBolus.isValid;
|
||||||
|
|
|
@ -5,6 +5,7 @@ import dagger.Component
|
||||||
import dagger.android.AndroidInjectionModule
|
import dagger.android.AndroidInjectionModule
|
||||||
import dagger.android.AndroidInjector
|
import dagger.android.AndroidInjector
|
||||||
import info.nightscout.androidaps.MainApp
|
import info.nightscout.androidaps.MainApp
|
||||||
|
import info.nightscout.androidaps.core.dependencyInjection.CoreModule
|
||||||
import info.nightscout.androidaps.data.Profile
|
import info.nightscout.androidaps.data.Profile
|
||||||
import info.nightscout.androidaps.data.ProfileStore
|
import info.nightscout.androidaps.data.ProfileStore
|
||||||
import info.nightscout.androidaps.data.PumpEnactResult
|
import info.nightscout.androidaps.data.PumpEnactResult
|
||||||
|
@ -53,6 +54,7 @@ import javax.inject.Singleton
|
||||||
@Component(
|
@Component(
|
||||||
modules = [
|
modules = [
|
||||||
AndroidInjectionModule::class,
|
AndroidInjectionModule::class,
|
||||||
|
CoreModule::class,
|
||||||
ActivitiesModule::class,
|
ActivitiesModule::class,
|
||||||
FragmentsModule::class,
|
FragmentsModule::class,
|
||||||
AppModule::class,
|
AppModule::class,
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
package info.nightscout.androidaps.dependencyInjection
|
package info.nightscout.androidaps.dependencyInjection
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import androidx.preference.PreferenceManager
|
|
||||||
import dagger.Binds
|
import dagger.Binds
|
||||||
import dagger.Lazy
|
import dagger.Lazy
|
||||||
import dagger.Module
|
import dagger.Module
|
||||||
|
@ -13,16 +12,13 @@ import info.nightscout.androidaps.interfaces.ActivePluginProvider
|
||||||
import info.nightscout.androidaps.interfaces.CommandQueueProvider
|
import info.nightscout.androidaps.interfaces.CommandQueueProvider
|
||||||
import info.nightscout.androidaps.interfaces.PluginBase
|
import info.nightscout.androidaps.interfaces.PluginBase
|
||||||
import info.nightscout.androidaps.logging.AAPSLogger
|
import info.nightscout.androidaps.logging.AAPSLogger
|
||||||
import info.nightscout.androidaps.logging.AAPSLoggerProduction
|
|
||||||
import info.nightscout.androidaps.plugins.configBuilder.PluginStore
|
import info.nightscout.androidaps.plugins.configBuilder.PluginStore
|
||||||
import info.nightscout.androidaps.plugins.configBuilder.ProfileFunction
|
import info.nightscout.androidaps.plugins.configBuilder.ProfileFunction
|
||||||
import info.nightscout.androidaps.plugins.configBuilder.ProfileFunctionImplementation
|
import info.nightscout.androidaps.plugins.configBuilder.ProfileFunctionImplementation
|
||||||
import info.nightscout.androidaps.queue.CommandQueue
|
import info.nightscout.androidaps.queue.CommandQueue
|
||||||
import info.nightscout.androidaps.utils.FabricPrivacy
|
import info.nightscout.androidaps.utils.FabricPrivacy
|
||||||
import info.nightscout.androidaps.utils.resources.ResourceHelper
|
import info.nightscout.androidaps.utils.resources.ResourceHelper
|
||||||
import info.nightscout.androidaps.utils.resources.ResourceHelperImplementation
|
|
||||||
import info.nightscout.androidaps.utils.sharedPreferences.SP
|
import info.nightscout.androidaps.utils.sharedPreferences.SP
|
||||||
import info.nightscout.androidaps.utils.sharedPreferences.SPImplementation
|
|
||||||
import info.nightscout.androidaps.utils.storage.FileStorage
|
import info.nightscout.androidaps.utils.storage.FileStorage
|
||||||
import info.nightscout.androidaps.utils.storage.Storage
|
import info.nightscout.androidaps.utils.storage.Storage
|
||||||
import javax.inject.Singleton
|
import javax.inject.Singleton
|
||||||
|
@ -34,36 +30,12 @@ import javax.inject.Singleton
|
||||||
])
|
])
|
||||||
open class AppModule {
|
open class AppModule {
|
||||||
|
|
||||||
@Provides
|
|
||||||
@Singleton
|
|
||||||
fun provideSharedPreferences(context: Context, resourceHelper: ResourceHelper): SP {
|
|
||||||
return SPImplementation(PreferenceManager.getDefaultSharedPreferences(context), resourceHelper)
|
|
||||||
}
|
|
||||||
|
|
||||||
@Provides
|
@Provides
|
||||||
@Singleton
|
@Singleton
|
||||||
fun provideProfileFunction(injector: HasAndroidInjector, aapsLogger: AAPSLogger, sp: SP, resourceHelper: ResourceHelper, activePlugin: ActivePluginProvider, fabricPrivacy: FabricPrivacy): ProfileFunction {
|
fun provideProfileFunction(injector: HasAndroidInjector, aapsLogger: AAPSLogger, sp: SP, resourceHelper: ResourceHelper, activePlugin: ActivePluginProvider, fabricPrivacy: FabricPrivacy): ProfileFunction {
|
||||||
return ProfileFunctionImplementation(injector, aapsLogger, sp, resourceHelper, activePlugin, fabricPrivacy)
|
return ProfileFunctionImplementation(injector, aapsLogger, sp, resourceHelper, activePlugin, fabricPrivacy)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Provides
|
|
||||||
@Singleton
|
|
||||||
fun provideResources(mainApp: MainApp): ResourceHelper {
|
|
||||||
return ResourceHelperImplementation(mainApp)
|
|
||||||
}
|
|
||||||
|
|
||||||
@Provides
|
|
||||||
@Singleton
|
|
||||||
fun provideAAPSLogger(): AAPSLogger {
|
|
||||||
return AAPSLoggerProduction()
|
|
||||||
/* if (BuildConfig.DEBUG) {
|
|
||||||
AAPSLoggerDebug()
|
|
||||||
} else {
|
|
||||||
AAPSLoggerProduction()
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
}
|
|
||||||
|
|
||||||
@Provides
|
@Provides
|
||||||
fun providesPlugins(@PluginsModule.AllConfigs allConfigs: Map<@JvmSuppressWildcards Int, @JvmSuppressWildcards PluginBase>,
|
fun providesPlugins(@PluginsModule.AllConfigs allConfigs: Map<@JvmSuppressWildcards Int, @JvmSuppressWildcards PluginBase>,
|
||||||
@PluginsModule.PumpDriver pumpDrivers: Lazy<Map<@JvmSuppressWildcards Int, @JvmSuppressWildcards PluginBase>>,
|
@PluginsModule.PumpDriver pumpDrivers: Lazy<Map<@JvmSuppressWildcards Int, @JvmSuppressWildcards PluginBase>>,
|
||||||
|
@ -90,10 +62,7 @@ open class AppModule {
|
||||||
|
|
||||||
@Binds fun bindContext(mainApp: MainApp): Context
|
@Binds fun bindContext(mainApp: MainApp): Context
|
||||||
@Binds fun bindInjector(mainApp: MainApp): HasAndroidInjector
|
@Binds fun bindInjector(mainApp: MainApp): HasAndroidInjector
|
||||||
|
@Binds fun bindActivePluginProvider(pluginStore: PluginStore): ActivePluginProvider
|
||||||
@Binds
|
|
||||||
fun bindActivePluginProvider(pluginStore: PluginStore): ActivePluginProvider
|
|
||||||
|
|
||||||
@Binds fun commandQueueProvider(commandQueue: CommandQueue): CommandQueueProvider
|
@Binds fun commandQueueProvider(commandQueue: CommandQueue): CommandQueueProvider
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,68 +0,0 @@
|
||||||
package info.nightscout.androidaps.logging
|
|
||||||
|
|
||||||
import android.util.Log
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Created by adrian on 2019-12-27.
|
|
||||||
*/
|
|
||||||
|
|
||||||
class AAPSLoggerDebug : AAPSLogger {
|
|
||||||
|
|
||||||
override fun debug(message: String) {
|
|
||||||
Log.d(LTag.CORE.tag, message)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun debug(enable: Boolean, tag: LTag, message: String) {
|
|
||||||
if (enable) Log.d(LTag.CORE.tag, message)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun debug(tag: LTag, message: String) {
|
|
||||||
Log.d(tag.tag, message)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun debug(tag: LTag, format: String, vararg arguments: Any?) {
|
|
||||||
Log.d(tag.tag, String.format(format, arguments))
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun warn(tag: LTag, message: String) {
|
|
||||||
Log.w(tag.tag, message)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun warn(tag: LTag, format: String, vararg arguments: Any?) {
|
|
||||||
Log.w(tag.tag, String.format(format, arguments))
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun info(tag: LTag, message: String) {
|
|
||||||
Log.i(tag.tag, message)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun info(tag: LTag, format: String, vararg arguments: Any?) {
|
|
||||||
Log.i(tag.tag, String.format(format, arguments))
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun error(tag: LTag, message: String) {
|
|
||||||
Log.e(tag.tag, message)
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun error(message: String) {
|
|
||||||
Log.e(LTag.CORE.tag, message)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun error(message: String, throwable: Throwable) {
|
|
||||||
Log.e(LTag.CORE.tag, message, throwable)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun error(format: String, vararg arguments: Any?) {
|
|
||||||
Log.e(LTag.CORE.tag, String.format(format, arguments))
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun error(tag: LTag, message: String, throwable: Throwable) {
|
|
||||||
Log.e(tag.tag, message, throwable)
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun error(tag: LTag, format: String, vararg arguments: Any?) {
|
|
||||||
Log.e(tag.tag, String.format(format, arguments))
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,80 +0,0 @@
|
||||||
package info.nightscout.androidaps.logging
|
|
||||||
|
|
||||||
import androidx.preference.PreferenceManager
|
|
||||||
import info.nightscout.androidaps.MainApp
|
|
||||||
import java.util.*
|
|
||||||
|
|
||||||
object L {
|
|
||||||
private var logElements: MutableList<LogElement> = ArrayList()
|
|
||||||
|
|
||||||
const val CORE = "CORE"
|
|
||||||
const val BGSOURCE = "BGSOURCE"
|
|
||||||
const val DATASERVICE = "DATASERVICE"
|
|
||||||
const val DATABASE = "DATABASE"
|
|
||||||
const val DATAFOOD = "DATAFOOD"
|
|
||||||
const val DATATREATMENTS = "DATATREATMENTS"
|
|
||||||
const val NSCLIENT = "NSCLIENT"
|
|
||||||
const val PUMP = "PUMP"
|
|
||||||
const val PUMPCOMM = "PUMPCOMM"
|
|
||||||
const val PUMPBTCOMM = "PUMPBTCOMM"
|
|
||||||
|
|
||||||
init {
|
|
||||||
LTag.values().forEach { logElements.add(LogElement(it)) }
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun findByName(name: String): LogElement {
|
|
||||||
for (element in logElements) {
|
|
||||||
if (element.name == name) return element
|
|
||||||
}
|
|
||||||
return LogElement(false)
|
|
||||||
}
|
|
||||||
|
|
||||||
@JvmStatic
|
|
||||||
fun isEnabled(name: String): Boolean {
|
|
||||||
return findByName(name).enabled
|
|
||||||
}
|
|
||||||
|
|
||||||
fun getLogElements(): List<LogElement> {
|
|
||||||
return logElements
|
|
||||||
}
|
|
||||||
|
|
||||||
fun resetToDefaults() {
|
|
||||||
for (element in logElements) {
|
|
||||||
element.resetToDefault()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class LogElement {
|
|
||||||
var name: String
|
|
||||||
var defaultValue: Boolean
|
|
||||||
var enabled: Boolean
|
|
||||||
private var requiresRestart = false
|
|
||||||
|
|
||||||
internal constructor(tag: LTag) {
|
|
||||||
this.name = tag.tag
|
|
||||||
this.defaultValue = tag.defaultValue
|
|
||||||
this.requiresRestart = tag.requiresRestart
|
|
||||||
//TODO: remove after getting rid of old logging style "if (L.isEnabled(...))"
|
|
||||||
@Suppress("DEPRECATION")
|
|
||||||
enabled = PreferenceManager.getDefaultSharedPreferences(MainApp.instance()).getBoolean(getSPName(), defaultValue)
|
|
||||||
}
|
|
||||||
|
|
||||||
internal constructor(defaultValue: Boolean) {
|
|
||||||
name = "NONEXISTING"
|
|
||||||
this.defaultValue = defaultValue
|
|
||||||
enabled = defaultValue
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun getSPName(): String = "log_$name"
|
|
||||||
|
|
||||||
fun enable(enabled: Boolean) {
|
|
||||||
this.enabled = enabled
|
|
||||||
@Suppress("DEPRECATION")
|
|
||||||
PreferenceManager.getDefaultSharedPreferences(MainApp.instance()).edit().putBoolean(getSPName(), enabled).apply()
|
|
||||||
}
|
|
||||||
|
|
||||||
fun resetToDefault() {
|
|
||||||
enable(defaultValue)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -3,9 +3,8 @@ package info.nightscout.androidaps.plugins.aps.loop;
|
||||||
import org.json.JSONException;
|
import org.json.JSONException;
|
||||||
import org.json.JSONObject;
|
import org.json.JSONObject;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
import info.nightscout.androidaps.logging.L;
|
import info.nightscout.androidaps.logging.LTag;
|
||||||
import info.nightscout.androidaps.logging.StacktraceLoggerWrapper;
|
import info.nightscout.androidaps.logging.StacktraceLoggerWrapper;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -366,7 +365,7 @@ import info.nightscout.androidaps.logging.StacktraceLoggerWrapper;
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public class DeviceStatus {
|
public class DeviceStatus {
|
||||||
private static Logger log = StacktraceLoggerWrapper.getLogger(L.NSCLIENT);
|
private static Logger log = StacktraceLoggerWrapper.getLogger(LTag.NSCLIENT);
|
||||||
|
|
||||||
public String device = null;
|
public String device = null;
|
||||||
public JSONObject pump = null;
|
public JSONObject pump = null;
|
||||||
|
|
|
@ -16,7 +16,6 @@ import org.json.JSONArray;
|
||||||
import org.json.JSONException;
|
import org.json.JSONException;
|
||||||
import org.json.JSONObject;
|
import org.json.JSONObject;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
import java.sql.SQLException;
|
import java.sql.SQLException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
@ -32,6 +31,7 @@ import info.nightscout.androidaps.events.Event;
|
||||||
import info.nightscout.androidaps.events.EventFoodDatabaseChanged;
|
import info.nightscout.androidaps.events.EventFoodDatabaseChanged;
|
||||||
import info.nightscout.androidaps.events.EventNsFood;
|
import info.nightscout.androidaps.events.EventNsFood;
|
||||||
import info.nightscout.androidaps.logging.L;
|
import info.nightscout.androidaps.logging.L;
|
||||||
|
import info.nightscout.androidaps.logging.LTag;
|
||||||
import info.nightscout.androidaps.logging.StacktraceLoggerWrapper;
|
import info.nightscout.androidaps.logging.StacktraceLoggerWrapper;
|
||||||
import info.nightscout.androidaps.plugins.bus.RxBus;
|
import info.nightscout.androidaps.plugins.bus.RxBus;
|
||||||
import info.nightscout.androidaps.utils.FabricPrivacy;
|
import info.nightscout.androidaps.utils.FabricPrivacy;
|
||||||
|
@ -43,7 +43,7 @@ import io.reactivex.schedulers.Schedulers;
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public class FoodService extends OrmLiteBaseService<DatabaseHelper> {
|
public class FoodService extends OrmLiteBaseService<DatabaseHelper> {
|
||||||
private Logger log = StacktraceLoggerWrapper.getLogger(L.DATAFOOD);
|
private Logger log = StacktraceLoggerWrapper.getLogger(LTag.DATAFOOD);
|
||||||
private CompositeDisposable disposable = new CompositeDisposable();
|
private CompositeDisposable disposable = new CompositeDisposable();
|
||||||
|
|
||||||
private static final ScheduledExecutorService foodEventWorker = Executors.newSingleThreadScheduledExecutor();
|
private static final ScheduledExecutorService foodEventWorker = Executors.newSingleThreadScheduledExecutor();
|
||||||
|
@ -98,7 +98,7 @@ public class FoodService extends OrmLiteBaseService<DatabaseHelper> {
|
||||||
public void onCreate() {
|
public void onCreate() {
|
||||||
super.onCreate();
|
super.onCreate();
|
||||||
try {
|
try {
|
||||||
if (L.isEnabled(L.DATAFOOD))
|
if (L.isEnabled(LTag.DATAFOOD))
|
||||||
log.info("onCreate");
|
log.info("onCreate");
|
||||||
TableUtils.createTableIfNotExists(this.getConnectionSource(), Food.class);
|
TableUtils.createTableIfNotExists(this.getConnectionSource(), Food.class);
|
||||||
} catch (SQLException e) {
|
} catch (SQLException e) {
|
||||||
|
@ -108,7 +108,7 @@ public class FoodService extends OrmLiteBaseService<DatabaseHelper> {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void onUpgrade(ConnectionSource connectionSource, int oldVersion, int newVersion) {
|
public void onUpgrade(ConnectionSource connectionSource, int oldVersion, int newVersion) {
|
||||||
if (L.isEnabled(L.DATAFOOD))
|
if (L.isEnabled(LTag.DATAFOOD))
|
||||||
log.info("onUpgrade");
|
log.info("onUpgrade");
|
||||||
// this.resetFood();
|
// this.resetFood();
|
||||||
}
|
}
|
||||||
|
@ -147,7 +147,7 @@ public class FoodService extends OrmLiteBaseService<DatabaseHelper> {
|
||||||
|
|
||||||
class PostRunnable implements Runnable {
|
class PostRunnable implements Runnable {
|
||||||
public void run() {
|
public void run() {
|
||||||
if (L.isEnabled(L.DATAFOOD))
|
if (L.isEnabled(LTag.DATAFOOD))
|
||||||
log.debug("Firing EventFoodChange");
|
log.debug("Firing EventFoodChange");
|
||||||
RxBus.Companion.getINSTANCE().send(event);
|
RxBus.Companion.getINSTANCE().send(event);
|
||||||
callback.setPost(null);
|
callback.setPost(null);
|
||||||
|
@ -258,7 +258,7 @@ public class FoodService extends OrmLiteBaseService<DatabaseHelper> {
|
||||||
public void deleteByNSId(String _id) throws SQLException {
|
public void deleteByNSId(String _id) throws SQLException {
|
||||||
Food stored = this.findByNSId(_id);
|
Food stored = this.findByNSId(_id);
|
||||||
if (stored != null) {
|
if (stored != null) {
|
||||||
if (L.isEnabled(L.DATAFOOD))
|
if (L.isEnabled(LTag.DATAFOOD))
|
||||||
log.debug("Removing Food record from database: " + stored.toString());
|
log.debug("Removing Food record from database: " + stored.toString());
|
||||||
this.delete(stored);
|
this.delete(stored);
|
||||||
}
|
}
|
||||||
|
@ -312,7 +312,7 @@ public class FoodService extends OrmLiteBaseService<DatabaseHelper> {
|
||||||
public void createOrUpdate(Food food) {
|
public void createOrUpdate(Food food) {
|
||||||
try {
|
try {
|
||||||
this.getDao().createOrUpdate(food);
|
this.getDao().createOrUpdate(food);
|
||||||
if (L.isEnabled(L.DATAFOOD))
|
if (L.isEnabled(LTag.DATAFOOD))
|
||||||
log.debug("Created or Updated: " + food.toString());
|
log.debug("Created or Updated: " + food.toString());
|
||||||
} catch (SQLException e) {
|
} catch (SQLException e) {
|
||||||
log.error("Unable to createOrUpdate Food", e);
|
log.error("Unable to createOrUpdate Food", e);
|
||||||
|
@ -323,7 +323,7 @@ public class FoodService extends OrmLiteBaseService<DatabaseHelper> {
|
||||||
public void create(Food food) {
|
public void create(Food food) {
|
||||||
try {
|
try {
|
||||||
this.getDao().create(food);
|
this.getDao().create(food);
|
||||||
if (L.isEnabled(L.DATAFOOD))
|
if (L.isEnabled(LTag.DATAFOOD))
|
||||||
log.debug("New record: " + food.toString());
|
log.debug("New record: " + food.toString());
|
||||||
} catch (SQLException e) {
|
} catch (SQLException e) {
|
||||||
log.error("Unable to create Food", e);
|
log.error("Unable to create Food", e);
|
||||||
|
|
|
@ -1,19 +1,14 @@
|
||||||
package info.nightscout.androidaps.plugins.general.maintenance;
|
package info.nightscout.androidaps.plugins.general.maintenance;
|
||||||
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
import ch.qos.logback.classic.LoggerContext;
|
import ch.qos.logback.classic.LoggerContext;
|
||||||
import info.nightscout.androidaps.logging.L;
|
|
||||||
import info.nightscout.androidaps.logging.StacktraceLoggerWrapper;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This class provides serveral methods for log-handling (eg. sending logs as emails).
|
* This class provides serveral methods for log-handling (eg. sending logs as emails).
|
||||||
*/
|
*/
|
||||||
public class LoggerUtils {
|
public class LoggerUtils {
|
||||||
|
|
||||||
private static final Logger LOGGER = StacktraceLoggerWrapper.getLogger(L.CORE);
|
|
||||||
|
|
||||||
public static String SUFFIX = ".log.zip";
|
public static String SUFFIX = ".log.zip";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -9,9 +9,12 @@ import info.nightscout.androidaps.R
|
||||||
import info.nightscout.androidaps.activities.NoSplashAppCompatActivity
|
import info.nightscout.androidaps.activities.NoSplashAppCompatActivity
|
||||||
import info.nightscout.androidaps.logging.L
|
import info.nightscout.androidaps.logging.L
|
||||||
import kotlinx.android.synthetic.main.activity_logsetting.*
|
import kotlinx.android.synthetic.main.activity_logsetting.*
|
||||||
|
import javax.inject.Inject
|
||||||
|
|
||||||
class LogSettingActivity : NoSplashAppCompatActivity() {
|
class LogSettingActivity : NoSplashAppCompatActivity() {
|
||||||
|
|
||||||
|
@Inject lateinit var l :L
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
setContentView(R.layout.activity_logsetting)
|
setContentView(R.layout.activity_logsetting)
|
||||||
|
@ -19,7 +22,7 @@ class LogSettingActivity : NoSplashAppCompatActivity() {
|
||||||
createViewsForSettings()
|
createViewsForSettings()
|
||||||
|
|
||||||
logsettings_reset.setOnClickListener {
|
logsettings_reset.setOnClickListener {
|
||||||
L.resetToDefaults()
|
l.resetToDefaults()
|
||||||
createViewsForSettings()
|
createViewsForSettings()
|
||||||
}
|
}
|
||||||
ok.setOnClickListener { finish() }
|
ok.setOnClickListener { finish() }
|
||||||
|
@ -27,7 +30,7 @@ class LogSettingActivity : NoSplashAppCompatActivity() {
|
||||||
|
|
||||||
private fun createViewsForSettings() {
|
private fun createViewsForSettings() {
|
||||||
logsettings_placeholder.removeAllViews()
|
logsettings_placeholder.removeAllViews()
|
||||||
for (element in L.getLogElements()) {
|
for (element in l.getLogElements()) {
|
||||||
val logViewHolder = LogViewHolder(element)
|
val logViewHolder = LogViewHolder(element)
|
||||||
logsettings_placeholder.addView(logViewHolder.baseView)
|
logsettings_placeholder.addView(logViewHolder.baseView)
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,6 +35,7 @@ import info.nightscout.androidaps.db.TempTarget;
|
||||||
import info.nightscout.androidaps.db.TemporaryBasal;
|
import info.nightscout.androidaps.db.TemporaryBasal;
|
||||||
import info.nightscout.androidaps.interfaces.PumpInterface;
|
import info.nightscout.androidaps.interfaces.PumpInterface;
|
||||||
import info.nightscout.androidaps.logging.L;
|
import info.nightscout.androidaps.logging.L;
|
||||||
|
import info.nightscout.androidaps.logging.LTag;
|
||||||
import info.nightscout.androidaps.logging.StacktraceLoggerWrapper;
|
import info.nightscout.androidaps.logging.StacktraceLoggerWrapper;
|
||||||
import info.nightscout.androidaps.plugins.aps.loop.APSResult;
|
import info.nightscout.androidaps.plugins.aps.loop.APSResult;
|
||||||
import info.nightscout.androidaps.plugins.aps.loop.DeviceStatus;
|
import info.nightscout.androidaps.plugins.aps.loop.DeviceStatus;
|
||||||
|
@ -50,7 +51,7 @@ import info.nightscout.androidaps.utils.SP;
|
||||||
* Created by mike on 26.05.2017.
|
* Created by mike on 26.05.2017.
|
||||||
*/
|
*/
|
||||||
public class NSUpload {
|
public class NSUpload {
|
||||||
private static Logger log = StacktraceLoggerWrapper.getLogger(L.NSCLIENT);
|
private static Logger log = StacktraceLoggerWrapper.getLogger(LTag.NSCLIENT);
|
||||||
|
|
||||||
public static void uploadTempBasalStartAbsolute(TemporaryBasal temporaryBasal, Double originalExtendedAmount) {
|
public static void uploadTempBasalStartAbsolute(TemporaryBasal temporaryBasal, Double originalExtendedAmount) {
|
||||||
try {
|
try {
|
||||||
|
@ -200,7 +201,7 @@ public class NSUpload {
|
||||||
deviceStatus.enacted.put("requested", requested);
|
deviceStatus.enacted.put("requested", requested);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (L.isEnabled(L.NSCLIENT))
|
if (L.isEnabled(LTag.NSCLIENT))
|
||||||
log.debug("OpenAPS data too old to upload, sending iob only");
|
log.debug("OpenAPS data too old to upload, sending iob only");
|
||||||
IobTotal[] iob = iobCobCalculatorPlugin.calculateIobArrayInDia(profile);
|
IobTotal[] iob = iobCobCalculatorPlugin.calculateIobArrayInDia(profile);
|
||||||
if (iob.length > 0) {
|
if (iob.length > 0) {
|
||||||
|
|
|
@ -9,7 +9,6 @@ import com.j256.ormlite.dao.CloseableIterator;
|
||||||
import org.json.JSONException;
|
import org.json.JSONException;
|
||||||
import org.json.JSONObject;
|
import org.json.JSONObject;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
import java.sql.SQLException;
|
import java.sql.SQLException;
|
||||||
|
|
||||||
|
@ -18,6 +17,7 @@ import info.nightscout.androidaps.R;
|
||||||
import info.nightscout.androidaps.db.DatabaseHelper;
|
import info.nightscout.androidaps.db.DatabaseHelper;
|
||||||
import info.nightscout.androidaps.db.DbRequest;
|
import info.nightscout.androidaps.db.DbRequest;
|
||||||
import info.nightscout.androidaps.logging.L;
|
import info.nightscout.androidaps.logging.L;
|
||||||
|
import info.nightscout.androidaps.logging.LTag;
|
||||||
import info.nightscout.androidaps.logging.StacktraceLoggerWrapper;
|
import info.nightscout.androidaps.logging.StacktraceLoggerWrapper;
|
||||||
import info.nightscout.androidaps.plugins.bus.RxBus;
|
import info.nightscout.androidaps.plugins.bus.RxBus;
|
||||||
import info.nightscout.androidaps.plugins.general.nsclient.events.EventNSClientResend;
|
import info.nightscout.androidaps.plugins.general.nsclient.events.EventNSClientResend;
|
||||||
|
@ -28,7 +28,7 @@ import info.nightscout.androidaps.utils.SP;
|
||||||
* Created by mike on 21.02.2016.
|
* Created by mike on 21.02.2016.
|
||||||
*/
|
*/
|
||||||
public class UploadQueue {
|
public class UploadQueue {
|
||||||
private static Logger log = StacktraceLoggerWrapper.getLogger(L.NSCLIENT);
|
private static Logger log = StacktraceLoggerWrapper.getLogger(LTag.NSCLIENT);
|
||||||
|
|
||||||
public static String status() {
|
public static String status() {
|
||||||
return "QUEUE: " + MainApp.getDbHelper().size(DatabaseHelper.DATABASE_DBREQUESTS);
|
return "QUEUE: " + MainApp.getDbHelper().size(DatabaseHelper.DATABASE_DBREQUESTS);
|
||||||
|
@ -48,7 +48,7 @@ public class UploadQueue {
|
||||||
|
|
||||||
public static void add(final DbRequest dbr) {
|
public static void add(final DbRequest dbr) {
|
||||||
if (SP.getBoolean(R.string.key_ns_noupload, false)) return;
|
if (SP.getBoolean(R.string.key_ns_noupload, false)) return;
|
||||||
if (L.isEnabled(L.NSCLIENT))
|
if (L.isEnabled(LTag.NSCLIENT))
|
||||||
log.debug("Adding to queue: " + dbr.log());
|
log.debug("Adding to queue: " + dbr.log());
|
||||||
try {
|
try {
|
||||||
MainApp.getDbHelper().create(dbr);
|
MainApp.getDbHelper().create(dbr);
|
||||||
|
@ -62,10 +62,10 @@ public class UploadQueue {
|
||||||
startService();
|
startService();
|
||||||
if (NSClientService.handler != null) {
|
if (NSClientService.handler != null) {
|
||||||
NSClientService.handler.post(() -> {
|
NSClientService.handler.post(() -> {
|
||||||
if (L.isEnabled(L.NSCLIENT))
|
if (L.isEnabled(LTag.NSCLIENT))
|
||||||
log.debug("ClearQueue");
|
log.debug("ClearQueue");
|
||||||
MainApp.getDbHelper().deleteAllDbRequests();
|
MainApp.getDbHelper().deleteAllDbRequests();
|
||||||
if (L.isEnabled(L.NSCLIENT))
|
if (L.isEnabled(LTag.NSCLIENT))
|
||||||
log.debug(status());
|
log.debug(status());
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -83,7 +83,7 @@ public class UploadQueue {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (MainApp.getDbHelper().deleteDbRequest(id) == 1) {
|
if (MainApp.getDbHelper().deleteDbRequest(id) == 1) {
|
||||||
if (L.isEnabled(L.NSCLIENT))
|
if (L.isEnabled(LTag.NSCLIENT))
|
||||||
log.debug("Removed item from UploadQueue. " + UploadQueue.status());
|
log.debug("Removed item from UploadQueue. " + UploadQueue.status());
|
||||||
}
|
}
|
||||||
} catch (JSONException e) {
|
} catch (JSONException e) {
|
||||||
|
@ -100,7 +100,7 @@ public class UploadQueue {
|
||||||
if (NSClientService.handler != null) {
|
if (NSClientService.handler != null) {
|
||||||
NSClientService.handler.post(() -> {
|
NSClientService.handler.post(() -> {
|
||||||
MainApp.getDbHelper().deleteDbRequestbyMongoId(action, _id);
|
MainApp.getDbHelper().deleteDbRequestbyMongoId(action, _id);
|
||||||
if (L.isEnabled(L.NSCLIENT))
|
if (L.isEnabled(LTag.NSCLIENT))
|
||||||
log.debug("Removing " + _id + " from UploadQueue. " + UploadQueue.status());
|
log.debug("Removing " + _id + " from UploadQueue. " + UploadQueue.status());
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,10 +3,10 @@ package info.nightscout.androidaps.plugins.general.nsclient.acks;
|
||||||
import org.json.JSONArray;
|
import org.json.JSONArray;
|
||||||
import org.json.JSONObject;
|
import org.json.JSONObject;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
import info.nightscout.androidaps.events.Event;
|
import info.nightscout.androidaps.events.Event;
|
||||||
import info.nightscout.androidaps.logging.L;
|
import info.nightscout.androidaps.logging.L;
|
||||||
|
import info.nightscout.androidaps.logging.LTag;
|
||||||
import info.nightscout.androidaps.logging.StacktraceLoggerWrapper;
|
import info.nightscout.androidaps.logging.StacktraceLoggerWrapper;
|
||||||
import info.nightscout.androidaps.plugins.bus.RxBus;
|
import info.nightscout.androidaps.plugins.bus.RxBus;
|
||||||
import info.nightscout.androidaps.plugins.general.nsclient.events.EventNSClientRestart;
|
import info.nightscout.androidaps.plugins.general.nsclient.events.EventNSClientRestart;
|
||||||
|
@ -16,7 +16,7 @@ import io.socket.client.Ack;
|
||||||
* Created by mike on 29.12.2015.
|
* Created by mike on 29.12.2015.
|
||||||
*/
|
*/
|
||||||
public class NSAddAck extends Event implements Ack {
|
public class NSAddAck extends Event implements Ack {
|
||||||
private static Logger log = StacktraceLoggerWrapper.getLogger(L.NSCLIENT);
|
private static Logger log = StacktraceLoggerWrapper.getLogger(LTag.NSCLIENT);
|
||||||
public String _id = null;
|
public String _id = null;
|
||||||
public String nsClientID = null;
|
public String nsClientID = null;
|
||||||
public JSONObject json = null;
|
public JSONObject json = null;
|
||||||
|
@ -48,7 +48,7 @@ public class NSAddAck extends Event implements Ack {
|
||||||
RxBus.Companion.getINSTANCE().send(new EventNSClientRestart());
|
RxBus.Companion.getINSTANCE().send(new EventNSClientRestart());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (L.isEnabled(L.NSCLIENT))
|
if (L.isEnabled(LTag.NSCLIENT))
|
||||||
log.debug("DBACCESS " + response.getString("result"));
|
log.debug("DBACCESS " + response.getString("result"));
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -3,10 +3,9 @@ package info.nightscout.androidaps.plugins.general.nsclient.acks;
|
||||||
import org.json.JSONException;
|
import org.json.JSONException;
|
||||||
import org.json.JSONObject;
|
import org.json.JSONObject;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
import info.nightscout.androidaps.events.Event;
|
import info.nightscout.androidaps.events.Event;
|
||||||
import info.nightscout.androidaps.logging.L;
|
import info.nightscout.androidaps.logging.LTag;
|
||||||
import info.nightscout.androidaps.logging.StacktraceLoggerWrapper;
|
import info.nightscout.androidaps.logging.StacktraceLoggerWrapper;
|
||||||
import info.nightscout.androidaps.plugins.bus.RxBus;
|
import info.nightscout.androidaps.plugins.bus.RxBus;
|
||||||
import io.socket.client.Ack;
|
import io.socket.client.Ack;
|
||||||
|
@ -15,12 +14,13 @@ import io.socket.client.Ack;
|
||||||
* Created by mike on 21.02.2016.
|
* Created by mike on 21.02.2016.
|
||||||
*/
|
*/
|
||||||
public class NSUpdateAck extends Event implements Ack {
|
public class NSUpdateAck extends Event implements Ack {
|
||||||
private static Logger log = StacktraceLoggerWrapper.getLogger(L.NSCLIENT);
|
private static Logger log = StacktraceLoggerWrapper.getLogger(LTag.NSCLIENT);
|
||||||
public boolean result = false;
|
public boolean result = false;
|
||||||
public String _id;
|
public String _id;
|
||||||
public String action;
|
public String action;
|
||||||
public void call(Object...args) {
|
|
||||||
JSONObject response = (JSONObject)args[0];
|
public void call(Object... args) {
|
||||||
|
JSONObject response = (JSONObject) args[0];
|
||||||
if (response.has("result"))
|
if (response.has("result"))
|
||||||
try {
|
try {
|
||||||
if (response.getString("result").equals("success"))
|
if (response.getString("result").equals("success"))
|
||||||
|
|
|
@ -3,13 +3,12 @@ package info.nightscout.androidaps.plugins.general.nsclient.data;
|
||||||
import org.json.JSONException;
|
import org.json.JSONException;
|
||||||
import org.json.JSONObject;
|
import org.json.JSONObject;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
import info.nightscout.androidaps.logging.L;
|
import info.nightscout.androidaps.logging.LTag;
|
||||||
import info.nightscout.androidaps.logging.StacktraceLoggerWrapper;
|
import info.nightscout.androidaps.logging.StacktraceLoggerWrapper;
|
||||||
|
|
||||||
public class NSMbg {
|
public class NSMbg {
|
||||||
private static Logger log = StacktraceLoggerWrapper.getLogger(L.NSCLIENT);
|
private static Logger log = StacktraceLoggerWrapper.getLogger(LTag.NSCLIENT);
|
||||||
public long date;
|
public long date;
|
||||||
public double mbg;
|
public double mbg;
|
||||||
public String json;
|
public String json;
|
||||||
|
|
|
@ -6,6 +6,7 @@ import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
import info.nightscout.androidaps.logging.L;
|
import info.nightscout.androidaps.logging.L;
|
||||||
|
import info.nightscout.androidaps.logging.LTag;
|
||||||
import info.nightscout.androidaps.logging.StacktraceLoggerWrapper;
|
import info.nightscout.androidaps.logging.StacktraceLoggerWrapper;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -13,7 +14,7 @@ import info.nightscout.androidaps.logging.StacktraceLoggerWrapper;
|
||||||
* {"mgdl":105,"mills":1455136282375,"device":"xDrip-BluetoothWixel","direction":"Flat","filtered":98272,"unfiltered":98272,"noise":1,"rssi":100}
|
* {"mgdl":105,"mills":1455136282375,"device":"xDrip-BluetoothWixel","direction":"Flat","filtered":98272,"unfiltered":98272,"noise":1,"rssi":100}
|
||||||
*/
|
*/
|
||||||
public class NSSgv {
|
public class NSSgv {
|
||||||
private static Logger log = StacktraceLoggerWrapper.getLogger(L.NSCLIENT);
|
private static Logger log = StacktraceLoggerWrapper.getLogger(LTag.NSCLIENT);
|
||||||
|
|
||||||
private JSONObject data;
|
private JSONObject data;
|
||||||
|
|
||||||
|
|
|
@ -3,15 +3,14 @@ package info.nightscout.androidaps.plugins.general.nsclient.data;
|
||||||
import org.json.JSONException;
|
import org.json.JSONException;
|
||||||
import org.json.JSONObject;
|
import org.json.JSONObject;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
|
|
||||||
import info.nightscout.androidaps.logging.L;
|
import info.nightscout.androidaps.logging.LTag;
|
||||||
import info.nightscout.androidaps.logging.StacktraceLoggerWrapper;
|
import info.nightscout.androidaps.logging.StacktraceLoggerWrapper;
|
||||||
|
|
||||||
public class NSTreatment {
|
public class NSTreatment {
|
||||||
private static Logger log = StacktraceLoggerWrapper.getLogger(L.NSCLIENT);
|
private static Logger log = StacktraceLoggerWrapper.getLogger(LTag.NSCLIENT);
|
||||||
|
|
||||||
private JSONObject data;
|
private JSONObject data;
|
||||||
private String action = null; // "update", "remove" or null (add)
|
private String action = null; // "update", "remove" or null (add)
|
||||||
|
@ -82,15 +81,47 @@ public class NSTreatment {
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getAction() { return action; }
|
public String getAction() {
|
||||||
public JSONObject getData() { return data; }
|
return action;
|
||||||
public String get_id() { return getStringOrNull("_id"); }
|
}
|
||||||
public String getEnteredBy() { return getStringOrNull("enteredBy"); }
|
|
||||||
public String getEventType() { return getStringOrNull("eventType"); }
|
public JSONObject getData() {
|
||||||
public Integer getHapp_id() { return getIntegerOrNull("happ_id"); }
|
return data;
|
||||||
public Integer getDuration() { return getIntegerOrNull("duration"); }
|
}
|
||||||
public Integer getMgdl() { return getIntegerOrNull("mgdl"); }
|
|
||||||
public Double getAbsolute() { return getDoubleOrNull("absolute"); }
|
public String get_id() {
|
||||||
public Long getMills() { return getLongOrNull("mills"); }
|
return getStringOrNull("_id");
|
||||||
public Date getCreated_at() { return getDateOrNull("created_at"); }
|
}
|
||||||
|
|
||||||
|
public String getEnteredBy() {
|
||||||
|
return getStringOrNull("enteredBy");
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getEventType() {
|
||||||
|
return getStringOrNull("eventType");
|
||||||
|
}
|
||||||
|
|
||||||
|
public Integer getHapp_id() {
|
||||||
|
return getIntegerOrNull("happ_id");
|
||||||
|
}
|
||||||
|
|
||||||
|
public Integer getDuration() {
|
||||||
|
return getIntegerOrNull("duration");
|
||||||
|
}
|
||||||
|
|
||||||
|
public Integer getMgdl() {
|
||||||
|
return getIntegerOrNull("mgdl");
|
||||||
|
}
|
||||||
|
|
||||||
|
public Double getAbsolute() {
|
||||||
|
return getDoubleOrNull("absolute");
|
||||||
|
}
|
||||||
|
|
||||||
|
public Long getMills() {
|
||||||
|
return getLongOrNull("mills");
|
||||||
|
}
|
||||||
|
|
||||||
|
public Date getCreated_at() {
|
||||||
|
return getDateOrNull("created_at");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -92,7 +92,7 @@ public class NSClientService extends DaggerService {
|
||||||
@Inject NSClientPlugin nsClientPlugin;
|
@Inject NSClientPlugin nsClientPlugin;
|
||||||
@Inject BuildHelper buildHelper;
|
@Inject BuildHelper buildHelper;
|
||||||
|
|
||||||
private static Logger log = StacktraceLoggerWrapper.getLogger(L.NSCLIENT);
|
private static Logger log = StacktraceLoggerWrapper.getLogger(LTag.NSCLIENT);
|
||||||
private CompositeDisposable disposable = new CompositeDisposable();
|
private CompositeDisposable disposable = new CompositeDisposable();
|
||||||
|
|
||||||
static public PowerManager.WakeLock mWakeLock;
|
static public PowerManager.WakeLock mWakeLock;
|
||||||
|
@ -178,7 +178,7 @@ public class NSClientService extends DaggerService {
|
||||||
.toObservable(EventAppExit.class)
|
.toObservable(EventAppExit.class)
|
||||||
.observeOn(Schedulers.io())
|
.observeOn(Schedulers.io())
|
||||||
.subscribe(event -> {
|
.subscribe(event -> {
|
||||||
if (L.isEnabled(L.NSCLIENT))
|
if (L.isEnabled(LTag.NSCLIENT))
|
||||||
log.debug("EventAppExit received");
|
log.debug("EventAppExit received");
|
||||||
destroy();
|
destroy();
|
||||||
stopSelf();
|
stopSelf();
|
||||||
|
@ -367,7 +367,7 @@ public class NSClientService extends DaggerService {
|
||||||
private Emitter.Listener onDisconnect = new Emitter.Listener() {
|
private Emitter.Listener onDisconnect = new Emitter.Listener() {
|
||||||
@Override
|
@Override
|
||||||
public void call(Object... args) {
|
public void call(Object... args) {
|
||||||
if (L.isEnabled(L.NSCLIENT))
|
if (L.isEnabled(LTag.NSCLIENT))
|
||||||
log.debug("disconnect reason: {}", args);
|
log.debug("disconnect reason: {}", args);
|
||||||
rxBus.send(new EventNSClientNewLog("NSCLIENT", "disconnect event"));
|
rxBus.send(new EventNSClientNewLog("NSCLIENT", "disconnect event"));
|
||||||
}
|
}
|
||||||
|
@ -804,7 +804,7 @@ public class NSClientService extends DaggerService {
|
||||||
if (mSocket == null || !mSocket.connected()) return;
|
if (mSocket == null || !mSocket.connected()) return;
|
||||||
|
|
||||||
if (lastResendTime > System.currentTimeMillis() - 10 * 1000L) {
|
if (lastResendTime > System.currentTimeMillis() - 10 * 1000L) {
|
||||||
if (L.isEnabled(L.NSCLIENT))
|
if (L.isEnabled(LTag.NSCLIENT))
|
||||||
log.debug("Skipping resend by lastResendTime: " + ((System.currentTimeMillis() - lastResendTime) / 1000L) + " sec");
|
log.debug("Skipping resend by lastResendTime: " + ((System.currentTimeMillis() - lastResendTime) / 1000L) + " sec");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,6 +24,7 @@ import info.nightscout.androidaps.plugins.bus.RxBusWrapper
|
||||||
import info.nightscout.androidaps.plugins.general.overview.events.EventDismissNotification
|
import info.nightscout.androidaps.plugins.general.overview.events.EventDismissNotification
|
||||||
import info.nightscout.androidaps.services.AlarmSoundService
|
import info.nightscout.androidaps.services.AlarmSoundService
|
||||||
import info.nightscout.androidaps.utils.DateUtil
|
import info.nightscout.androidaps.utils.DateUtil
|
||||||
|
import info.nightscout.androidaps.utils.resources.IconsProvider
|
||||||
import info.nightscout.androidaps.utils.resources.ResourceHelper
|
import info.nightscout.androidaps.utils.resources.ResourceHelper
|
||||||
import info.nightscout.androidaps.utils.sharedPreferences.SP
|
import info.nightscout.androidaps.utils.sharedPreferences.SP
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
@ -36,7 +37,8 @@ class NotificationStore @Inject constructor(
|
||||||
private val sp: SP,
|
private val sp: SP,
|
||||||
private val rxBus: RxBusWrapper,
|
private val rxBus: RxBusWrapper,
|
||||||
private val resourceHelper: ResourceHelper,
|
private val resourceHelper: ResourceHelper,
|
||||||
private val context: Context
|
private val context: Context,
|
||||||
|
private val iconsProvider: IconsProvider
|
||||||
) {
|
) {
|
||||||
|
|
||||||
var store: MutableList<Notification> = ArrayList()
|
var store: MutableList<Notification> = ArrayList()
|
||||||
|
@ -109,8 +111,8 @@ class NotificationStore @Inject constructor(
|
||||||
|
|
||||||
private fun raiseSystemNotification(n: Notification) {
|
private fun raiseSystemNotification(n: Notification) {
|
||||||
val mgr = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
|
val mgr = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
|
||||||
val largeIcon = resourceHelper.decodeResource(resourceHelper.getIcon())
|
val largeIcon = resourceHelper.decodeResource(iconsProvider.getIcon())
|
||||||
val smallIcon = resourceHelper.getNotificationIcon()
|
val smallIcon = iconsProvider.getNotificationIcon()
|
||||||
val sound = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_ALARM)
|
val sound = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_ALARM)
|
||||||
val notificationBuilder = NotificationCompat.Builder(context, CHANNEL_ID)
|
val notificationBuilder = NotificationCompat.Builder(context, CHANNEL_ID)
|
||||||
.setSmallIcon(smallIcon)
|
.setSmallIcon(smallIcon)
|
||||||
|
|
|
@ -28,6 +28,7 @@ import info.nightscout.androidaps.plugins.iob.iobCobCalculator.events.EventAutos
|
||||||
import info.nightscout.androidaps.utils.DecimalFormatter
|
import info.nightscout.androidaps.utils.DecimalFormatter
|
||||||
import info.nightscout.androidaps.utils.FabricPrivacy
|
import info.nightscout.androidaps.utils.FabricPrivacy
|
||||||
import info.nightscout.androidaps.utils.androidNotification.NotificationHolder
|
import info.nightscout.androidaps.utils.androidNotification.NotificationHolder
|
||||||
|
import info.nightscout.androidaps.utils.resources.IconsProvider
|
||||||
import info.nightscout.androidaps.utils.resources.ResourceHelper
|
import info.nightscout.androidaps.utils.resources.ResourceHelper
|
||||||
import io.reactivex.disposables.CompositeDisposable
|
import io.reactivex.disposables.CompositeDisposable
|
||||||
import io.reactivex.schedulers.Schedulers
|
import io.reactivex.schedulers.Schedulers
|
||||||
|
@ -45,7 +46,8 @@ class PersistentNotificationPlugin @Inject constructor(
|
||||||
private var iobCobCalculatorPlugin: IobCobCalculatorPlugin,
|
private var iobCobCalculatorPlugin: IobCobCalculatorPlugin,
|
||||||
private var rxBus: RxBusWrapper,
|
private var rxBus: RxBusWrapper,
|
||||||
private var context: Context,
|
private var context: Context,
|
||||||
private var notificationHolder: NotificationHolder
|
private var notificationHolder: NotificationHolder,
|
||||||
|
private val iconsProvider: IconsProvider
|
||||||
) : PluginBase(PluginDescription()
|
) : PluginBase(PluginDescription()
|
||||||
.mainType(PluginType.GENERAL)
|
.mainType(PluginType.GENERAL)
|
||||||
.neverVisible(true)
|
.neverVisible(true)
|
||||||
|
@ -209,8 +211,8 @@ class PersistentNotificationPlugin @Inject constructor(
|
||||||
builder.setOngoing(true)
|
builder.setOngoing(true)
|
||||||
builder.setOnlyAlertOnce(true)
|
builder.setOnlyAlertOnce(true)
|
||||||
builder.setCategory(NotificationCompat.CATEGORY_STATUS)
|
builder.setCategory(NotificationCompat.CATEGORY_STATUS)
|
||||||
builder.setSmallIcon(resourceHelper.getNotificationIcon())
|
builder.setSmallIcon(iconsProvider.getNotificationIcon())
|
||||||
builder.setLargeIcon(resourceHelper.decodeResource(resourceHelper.getIcon()))
|
builder.setLargeIcon(resourceHelper.decodeResource(iconsProvider.getIcon()))
|
||||||
if (line1 != null) builder.setContentTitle(line1)
|
if (line1 != null) builder.setContentTitle(line1)
|
||||||
if (line2 != null) builder.setContentText(line2)
|
if (line2 != null) builder.setContentText(line2)
|
||||||
if (line3 != null) builder.setSubText(line3)
|
if (line3 != null) builder.setSubText(line3)
|
||||||
|
|
|
@ -57,11 +57,14 @@ import io.reactivex.schedulers.Schedulers;
|
||||||
public abstract class PumpPluginAbstract extends PumpPluginBase implements PumpInterface, ConstraintsInterface {
|
public abstract class PumpPluginAbstract extends PumpPluginBase implements PumpInterface, ConstraintsInterface {
|
||||||
private CompositeDisposable disposable = new CompositeDisposable();
|
private CompositeDisposable disposable = new CompositeDisposable();
|
||||||
|
|
||||||
|
protected HasAndroidInjector injector;
|
||||||
protected AAPSLogger aapsLogger;
|
protected AAPSLogger aapsLogger;
|
||||||
protected RxBusWrapper rxBus;
|
protected RxBusWrapper rxBus;
|
||||||
protected ActivePluginProvider activePlugin;
|
protected ActivePluginProvider activePlugin;
|
||||||
protected Context context;
|
protected Context context;
|
||||||
protected FabricPrivacy fabricPrivacy;
|
protected FabricPrivacy fabricPrivacy;
|
||||||
|
protected ResourceHelper resourceHelper;
|
||||||
|
protected CommandQueueProvider commandQueue;
|
||||||
protected SP sp;
|
protected SP sp;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -99,7 +102,9 @@ public abstract class PumpPluginAbstract extends PumpPluginBase implements PumpI
|
||||||
this.activePlugin = activePlugin;
|
this.activePlugin = activePlugin;
|
||||||
this.context = context;
|
this.context = context;
|
||||||
this.fabricPrivacy = fabricPrivacy;
|
this.fabricPrivacy = fabricPrivacy;
|
||||||
|
this.resourceHelper = resourceHelper;
|
||||||
this.sp = sp;
|
this.sp = sp;
|
||||||
|
this.commandQueue = commandQueue;
|
||||||
|
|
||||||
pumpDescription.setPumpDescription(pumpType);
|
pumpDescription.setPumpDescription(pumpType);
|
||||||
this.pumpType = pumpType;
|
this.pumpType = pumpType;
|
||||||
|
@ -109,12 +114,6 @@ public abstract class PumpPluginAbstract extends PumpPluginBase implements PumpI
|
||||||
|
|
||||||
public abstract void initPumpStatusData();
|
public abstract void initPumpStatusData();
|
||||||
|
|
||||||
public abstract void resetRileyLinkConfiguration();
|
|
||||||
|
|
||||||
public abstract void doTuneUpDevice();
|
|
||||||
|
|
||||||
public abstract RileyLinkService getRileyLinkService();
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onStart() {
|
protected void onStart() {
|
||||||
super.onStart();
|
super.onStart();
|
||||||
|
@ -464,6 +463,7 @@ public abstract class PumpPluginAbstract extends PumpPluginBase implements PumpI
|
||||||
|
|
||||||
public void setPumpType(PumpType pumpType) {
|
public void setPumpType(PumpType pumpType) {
|
||||||
this.pumpType = pumpType;
|
this.pumpType = pumpType;
|
||||||
|
this.pumpDescription.setPumpDescription(pumpType);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -49,16 +49,20 @@ public abstract class PumpStatus {
|
||||||
public int tempBasalRatio = 0;
|
public int tempBasalRatio = 0;
|
||||||
public int tempBasalRemainMin = 0;
|
public int tempBasalRemainMin = 0;
|
||||||
public Date tempBasalStart;
|
public Date tempBasalStart;
|
||||||
|
private PumpType pumpType;
|
||||||
//protected PumpDescription pumpDescription;
|
//protected PumpDescription pumpDescription;
|
||||||
|
|
||||||
|
|
||||||
public PumpStatus() {
|
public PumpStatus(PumpType pumpType) {
|
||||||
// public PumpStatus(PumpDescription pumpDescription) {
|
// public PumpStatus(PumpDescription pumpDescription) {
|
||||||
// this.pumpDescription = pumpDescription;
|
// this.pumpDescription = pumpDescription;
|
||||||
|
|
||||||
// this.initSettings();
|
// this.initSettings();
|
||||||
|
this.pumpType = pumpType;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public abstract void initSettings();
|
||||||
|
|
||||||
|
|
||||||
public void setLastCommunicationToNow() {
|
public void setLastCommunicationToNow() {
|
||||||
this.lastDataTime = DateUtil.now();
|
this.lastDataTime = DateUtil.now();
|
||||||
|
|
|
@ -57,13 +57,13 @@ public enum PumpType {
|
||||||
new DoseSettings(0.01d, 15, 24 * 60, 0.05d), //
|
new DoseSettings(0.01d, 15, 24 * 60, 0.05d), //
|
||||||
PumpTempBasalType.Percent,
|
PumpTempBasalType.Percent,
|
||||||
new DoseSettings(10, 15, 24 * 60, 0d, 250d), PumpCapability.BasalRate_Duration15and30minAllowed, //
|
new DoseSettings(10, 15, 24 * 60, 0d, 250d), PumpCapability.BasalRate_Duration15and30minAllowed, //
|
||||||
0.02d, null, 0.01d, DoseStepSize.InsightBolus, PumpCapability.InsightCapabilities, false, false), //
|
0.02d, null, 0.01d, DoseStepSize.InsightBolus, PumpCapability.InsightCapabilities), //
|
||||||
|
|
||||||
AccuChekSolo("Accu-Chek Solo", ManufacturerType.Roche, "Solo", 0.01d, null, //
|
AccuChekSolo("Accu-Chek Solo", ManufacturerType.Roche, "Solo", 0.01d, null, //
|
||||||
new DoseSettings(0.01d, 15, 24 * 60, 0.05d), //
|
new DoseSettings(0.01d, 15, 24 * 60, 0.05d), //
|
||||||
PumpTempBasalType.Percent,
|
PumpTempBasalType.Percent,
|
||||||
new DoseSettings(10, 15, 24 * 60, 0d, 250d), PumpCapability.BasalRate_Duration15and30minAllowed, //
|
new DoseSettings(10, 15, 24 * 60, 0d, 250d), PumpCapability.BasalRate_Duration15and30minAllowed, //
|
||||||
0.02d, null, 0.01d, DoseStepSize.InsightBolus, PumpCapability.InsightCapabilities, false, false), //
|
0.02d, null, 0.01d, DoseStepSize.InsightBolus, PumpCapability.InsightCapabilities), //
|
||||||
|
|
||||||
|
|
||||||
// Animas
|
// Animas
|
||||||
|
|
|
@ -41,14 +41,20 @@ import javax.inject.Inject;
|
||||||
|
|
||||||
import info.nightscout.androidaps.R;
|
import info.nightscout.androidaps.R;
|
||||||
import info.nightscout.androidaps.activities.NoSplashAppCompatActivity;
|
import info.nightscout.androidaps.activities.NoSplashAppCompatActivity;
|
||||||
|
import info.nightscout.androidaps.interfaces.ActivePluginProvider;
|
||||||
|
import info.nightscout.androidaps.interfaces.PumpInterface;
|
||||||
import info.nightscout.androidaps.logging.AAPSLogger;
|
import info.nightscout.androidaps.logging.AAPSLogger;
|
||||||
import info.nightscout.androidaps.plugins.bus.RxBusWrapper;
|
import info.nightscout.androidaps.plugins.bus.RxBusWrapper;
|
||||||
|
import info.nightscout.androidaps.plugins.common.ManufacturerType;
|
||||||
|
import info.nightscout.androidaps.plugins.pump.common.defs.PumpType;
|
||||||
import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.RileyLinkConst;
|
import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.RileyLinkConst;
|
||||||
import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.RileyLinkUtil;
|
import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.RileyLinkUtil;
|
||||||
import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.ble.data.GattAttributes;
|
import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.ble.data.GattAttributes;
|
||||||
|
import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.defs.RileyLinkPumpDevice;
|
||||||
import info.nightscout.androidaps.plugins.pump.common.utils.LocationHelper;
|
import info.nightscout.androidaps.plugins.pump.common.utils.LocationHelper;
|
||||||
import info.nightscout.androidaps.plugins.pump.medtronic.MedtronicPumpPlugin;
|
import info.nightscout.androidaps.plugins.pump.medtronic.MedtronicPumpPlugin;
|
||||||
import info.nightscout.androidaps.plugins.pump.medtronic.events.EventMedtronicPumpConfigurationChanged;
|
import info.nightscout.androidaps.plugins.pump.medtronic.events.EventMedtronicPumpConfigurationChanged;
|
||||||
|
import info.nightscout.androidaps.plugins.pump.omnipod.events.EventOmnipodPumpValuesChanged;
|
||||||
import info.nightscout.androidaps.utils.resources.ResourceHelper;
|
import info.nightscout.androidaps.utils.resources.ResourceHelper;
|
||||||
import info.nightscout.androidaps.utils.sharedPreferences.SP;
|
import info.nightscout.androidaps.utils.sharedPreferences.SP;
|
||||||
|
|
||||||
|
@ -60,8 +66,7 @@ public class RileyLinkBLEScanActivity extends NoSplashAppCompatActivity {
|
||||||
@Inject RxBusWrapper rxBus;
|
@Inject RxBusWrapper rxBus;
|
||||||
@Inject ResourceHelper resourceHelper;
|
@Inject ResourceHelper resourceHelper;
|
||||||
@Inject RileyLinkUtil rileyLinkUtil;
|
@Inject RileyLinkUtil rileyLinkUtil;
|
||||||
// TODO change this. Currently verifyConfiguration uses MDT data not only RL
|
@Inject ActivePluginProvider activePlugin;
|
||||||
@Inject MedtronicPumpPlugin medtronicPumpPlugin;
|
|
||||||
|
|
||||||
private static final int PERMISSION_REQUEST_COARSE_LOCATION = 30241; // arbitrary.
|
private static final int PERMISSION_REQUEST_COARSE_LOCATION = 30241; // arbitrary.
|
||||||
private static final int REQUEST_ENABLE_BT = 30242; // arbitrary
|
private static final int REQUEST_ENABLE_BT = 30242; // arbitrary
|
||||||
|
@ -110,9 +115,24 @@ public class RileyLinkBLEScanActivity extends NoSplashAppCompatActivity {
|
||||||
|
|
||||||
sp.putString(RileyLinkConst.Prefs.RileyLinkAddress, bleAddress);
|
sp.putString(RileyLinkConst.Prefs.RileyLinkAddress, bleAddress);
|
||||||
|
|
||||||
medtronicPumpPlugin.getRileyLinkService().verifyConfiguration(); // force reloading of address
|
PumpInterface activePump = activePlugin.getActivePump();
|
||||||
|
|
||||||
rxBus.send(new EventMedtronicPumpConfigurationChanged());
|
if (activePump.manufacturer()== ManufacturerType.Medtronic) {
|
||||||
|
RileyLinkPumpDevice rileyLinkPump = (RileyLinkPumpDevice)activePump;
|
||||||
|
rileyLinkPump.getRileyLinkService().verifyConfiguration(); // force reloading of address
|
||||||
|
|
||||||
|
rxBus.send(new EventMedtronicPumpConfigurationChanged());
|
||||||
|
|
||||||
|
} else if (activePlugin.getActivePump().manufacturer()== ManufacturerType.Insulet) {
|
||||||
|
if (activePump.model()== PumpType.Insulet_Omnipod_Dash) {
|
||||||
|
aapsLogger.error("Omnipod Dash not yet implemented.");
|
||||||
|
} else {
|
||||||
|
RileyLinkPumpDevice rileyLinkPump = (RileyLinkPumpDevice)activePump;
|
||||||
|
rileyLinkPump.getRileyLinkService().verifyConfiguration(); // force reloading of address
|
||||||
|
|
||||||
|
rxBus.send(new EventOmnipodPumpValuesChanged());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
finish();
|
finish();
|
||||||
});
|
});
|
||||||
|
|
|
@ -21,7 +21,7 @@ import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.service.tasks
|
||||||
import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.service.tasks.WakeAndTuneTask;
|
import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.service.tasks.WakeAndTuneTask;
|
||||||
import info.nightscout.androidaps.plugins.pump.common.utils.ByteUtil;
|
import info.nightscout.androidaps.plugins.pump.common.utils.ByteUtil;
|
||||||
import info.nightscout.androidaps.plugins.pump.medtronic.defs.PumpDeviceState;
|
import info.nightscout.androidaps.plugins.pump.medtronic.defs.PumpDeviceState;
|
||||||
import info.nightscout.androidaps.plugins.pump.medtronic.driver.MedtronicPumpStatus;
|
import info.nightscout.androidaps.utils.Round;
|
||||||
import info.nightscout.androidaps.utils.sharedPreferences.SP;
|
import info.nightscout.androidaps.utils.sharedPreferences.SP;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -33,16 +33,14 @@ public abstract class RileyLinkCommunicationManager {
|
||||||
|
|
||||||
@Inject protected AAPSLogger aapsLogger;
|
@Inject protected AAPSLogger aapsLogger;
|
||||||
@Inject protected SP sp;
|
@Inject protected SP sp;
|
||||||
|
@Inject protected RileyLinkServiceData rileyLinkServiceData;
|
||||||
@Inject MedtronicPumpStatus medtronicPumpStatus;
|
@Inject protected ServiceTaskExecutor serviceTaskExecutor;
|
||||||
@Inject RileyLinkServiceData rileyLinkServiceData;
|
|
||||||
@Inject ServiceTaskExecutor serviceTaskExecutor;
|
|
||||||
|
|
||||||
|
|
||||||
private final int SCAN_TIMEOUT = 1500;
|
private final int SCAN_TIMEOUT = 1500;
|
||||||
private final int ALLOWED_PUMP_UNREACHABLE = 10 * 60 * 1000; // 10 minutes
|
private final int ALLOWED_PUMP_UNREACHABLE = 10 * 60 * 1000; // 10 minutes
|
||||||
|
|
||||||
protected final HasAndroidInjector injector;
|
public final HasAndroidInjector injector;
|
||||||
protected final RFSpy rfspy;
|
protected final RFSpy rfspy;
|
||||||
protected int receiverDeviceAwakeForMinutes = 1; // override this in constructor of specific implementation
|
protected int receiverDeviceAwakeForMinutes = 1; // override this in constructor of specific implementation
|
||||||
protected String receiverDeviceID; // String representation of receiver device (ex. Pump (xxxxxx) or Pod (yyyyyy))
|
protected String receiverDeviceID; // String representation of receiver device (ex. Pump (xxxxxx) or Pod (yyyyyy))
|
||||||
|
@ -77,7 +75,7 @@ public abstract class RileyLinkCommunicationManager {
|
||||||
return sendAndListen(msg, timeout_ms, repeatCount, 0, extendPreamble_ms, clazz);
|
return sendAndListen(msg, timeout_ms, repeatCount, 0, extendPreamble_ms, clazz);
|
||||||
}
|
}
|
||||||
|
|
||||||
private <E extends RLMessage> E sendAndListen(RLMessage msg, int timeout_ms, int repeatCount, int retryCount, Integer extendPreamble_ms, Class<E> clazz)
|
protected <E extends RLMessage> E sendAndListen(RLMessage msg, int timeout_ms, int repeatCount, int retryCount, Integer extendPreamble_ms, Class<E> clazz)
|
||||||
throws RileyLinkCommunicationException {
|
throws RileyLinkCommunicationException {
|
||||||
|
|
||||||
// internal flag
|
// internal flag
|
||||||
|
@ -129,6 +127,9 @@ public abstract class RileyLinkCommunicationManager {
|
||||||
public abstract <E extends RLMessage> E createResponseMessage(byte[] payload, Class<E> clazz);
|
public abstract <E extends RLMessage> E createResponseMessage(byte[] payload, Class<E> clazz);
|
||||||
|
|
||||||
|
|
||||||
|
public abstract void setPumpDeviceState(PumpDeviceState pumpDeviceState);
|
||||||
|
|
||||||
|
|
||||||
public void wakeUp(boolean force) {
|
public void wakeUp(boolean force) {
|
||||||
wakeUp(receiverDeviceAwakeForMinutes, force);
|
wakeUp(receiverDeviceAwakeForMinutes, force);
|
||||||
}
|
}
|
||||||
|
@ -150,7 +151,7 @@ public abstract class RileyLinkCommunicationManager {
|
||||||
// **** FIXME: this wakeup doesn't seem to work well... must revisit
|
// **** FIXME: this wakeup doesn't seem to work well... must revisit
|
||||||
// receiverDeviceAwakeForMinutes = duration_minutes;
|
// receiverDeviceAwakeForMinutes = duration_minutes;
|
||||||
|
|
||||||
medtronicPumpStatus.setPumpDeviceState(PumpDeviceState.WakingUp);
|
setPumpDeviceState(PumpDeviceState.WakingUp);
|
||||||
|
|
||||||
if (force)
|
if (force)
|
||||||
nextWakeUpRequired = 0L;
|
nextWakeUpRequired = 0L;
|
||||||
|
@ -208,7 +209,7 @@ public abstract class RileyLinkCommunicationManager {
|
||||||
double[] scanFrequencies = rileyLinkServiceData.rileyLinkTargetFrequency.getScanFrequencies();
|
double[] scanFrequencies = rileyLinkServiceData.rileyLinkTargetFrequency.getScanFrequencies();
|
||||||
|
|
||||||
if (scanFrequencies.length == 1) {
|
if (scanFrequencies.length == 1) {
|
||||||
return RileyLinkUtil.isSame(scanFrequencies[0], frequency);
|
return Round.isSame(scanFrequencies[0], frequency);
|
||||||
} else {
|
} else {
|
||||||
return (scanFrequencies[0] <= frequency && scanFrequencies[scanFrequencies.length - 1] >= frequency);
|
return (scanFrequencies[0] <= frequency && scanFrequencies[scanFrequencies.length - 1] >= frequency);
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,6 +18,7 @@ import javax.inject.Singleton;
|
||||||
import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.ble.data.encoding.Encoding4b6b;
|
import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.ble.data.encoding.Encoding4b6b;
|
||||||
import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.ble.data.encoding.Encoding4b6bGeoff;
|
import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.ble.data.encoding.Encoding4b6bGeoff;
|
||||||
import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.ble.defs.RileyLinkEncodingType;
|
import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.ble.defs.RileyLinkEncodingType;
|
||||||
|
import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.ble.defs.RileyLinkTargetFrequency;
|
||||||
import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.data.BleAdvertisedData;
|
import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.data.BleAdvertisedData;
|
||||||
import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.data.RLHistoryItem;
|
import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.data.RLHistoryItem;
|
||||||
import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.service.data.ServiceResult;
|
import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.service.data.ServiceResult;
|
||||||
|
@ -37,6 +38,9 @@ public class RileyLinkUtil {
|
||||||
private RileyLinkEncodingType encoding;
|
private RileyLinkEncodingType encoding;
|
||||||
private Encoding4b6b encoding4b6b;
|
private Encoding4b6b encoding4b6b;
|
||||||
|
|
||||||
|
// TODO maybe not needed
|
||||||
|
private RileyLinkTargetFrequency rileyLinkTargetFrequency;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
public RileyLinkUtil() {
|
public RileyLinkUtil() {
|
||||||
}
|
}
|
||||||
|
@ -154,4 +158,8 @@ public class RileyLinkUtil {
|
||||||
public Encoding4b6b getEncoding4b6b() {
|
public Encoding4b6b getEncoding4b6b() {
|
||||||
return encoding4b6b;
|
return encoding4b6b;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setRileyLinkTargetFrequency(RileyLinkTargetFrequency rileyLinkTargetFrequency_) {
|
||||||
|
this.rileyLinkTargetFrequency = rileyLinkTargetFrequency_;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -57,6 +57,7 @@ public class RFSpy {
|
||||||
private UUID radioDataUUID = UUID.fromString(GattAttributes.CHARA_RADIO_DATA);
|
private UUID radioDataUUID = UUID.fromString(GattAttributes.CHARA_RADIO_DATA);
|
||||||
private UUID radioVersionUUID = UUID.fromString(GattAttributes.CHARA_RADIO_VERSION);
|
private UUID radioVersionUUID = UUID.fromString(GattAttributes.CHARA_RADIO_VERSION);
|
||||||
private UUID responseCountUUID = UUID.fromString(GattAttributes.CHARA_RADIO_RESPONSE_COUNT);
|
private UUID responseCountUUID = UUID.fromString(GattAttributes.CHARA_RADIO_RESPONSE_COUNT);
|
||||||
|
private RileyLinkFirmwareVersion firmwareVersion;
|
||||||
private String bleVersion; // We don't use it so no need of sofisticated logic
|
private String bleVersion; // We don't use it so no need of sofisticated logic
|
||||||
private Double currentFrequencyMHz;
|
private Double currentFrequencyMHz;
|
||||||
|
|
||||||
|
@ -68,6 +69,12 @@ public class RFSpy {
|
||||||
reader = new RFSpyReader(aapsLogger, rileyLinkBle);
|
reader = new RFSpyReader(aapsLogger, rileyLinkBle);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public RileyLinkFirmwareVersion getRLVersionCached() {
|
||||||
|
return firmwareVersion;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public String getBLEVersionCached() {
|
public String getBLEVersionCached() {
|
||||||
return bleVersion;
|
return bleVersion;
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,6 +8,8 @@ import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.defs.RileyLin
|
||||||
import info.nightscout.androidaps.plugins.pump.medtronic.defs.MedtronicCommandType;
|
import info.nightscout.androidaps.plugins.pump.medtronic.defs.MedtronicCommandType;
|
||||||
import info.nightscout.androidaps.plugins.pump.medtronic.defs.PumpDeviceState;
|
import info.nightscout.androidaps.plugins.pump.medtronic.defs.PumpDeviceState;
|
||||||
import info.nightscout.androidaps.utils.resources.ResourceHelper;
|
import info.nightscout.androidaps.utils.resources.ResourceHelper;
|
||||||
|
import info.nightscout.androidaps.plugins.pump.omnipod.defs.OmnipodCommandType;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by andy on 5/19/18.
|
* Created by andy on 5/19/18.
|
||||||
|
@ -23,6 +25,7 @@ public class RLHistoryItem {
|
||||||
|
|
||||||
private RileyLinkTargetDevice targetDevice;
|
private RileyLinkTargetDevice targetDevice;
|
||||||
private PumpDeviceState pumpDeviceState;
|
private PumpDeviceState pumpDeviceState;
|
||||||
|
private OmnipodCommandType omnipodCommandType;
|
||||||
|
|
||||||
|
|
||||||
public RLHistoryItem(RileyLinkServiceState serviceState, RileyLinkError errorCode,
|
public RLHistoryItem(RileyLinkServiceState serviceState, RileyLinkError errorCode,
|
||||||
|
@ -50,6 +53,13 @@ public class RLHistoryItem {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public RLHistoryItem(OmnipodCommandType omnipodCommandType) {
|
||||||
|
this.dateTime = new LocalDateTime();
|
||||||
|
this.omnipodCommandType = omnipodCommandType;
|
||||||
|
source = RLHistoryItemSource.OmnipodCommand;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public LocalDateTime getDateTime() {
|
public LocalDateTime getDateTime() {
|
||||||
return dateTime;
|
return dateTime;
|
||||||
}
|
}
|
||||||
|
@ -79,6 +89,9 @@ public class RLHistoryItem {
|
||||||
case MedtronicCommand:
|
case MedtronicCommand:
|
||||||
return medtronicCommandType.name();
|
return medtronicCommandType.name();
|
||||||
|
|
||||||
|
case OmnipodCommand:
|
||||||
|
return omnipodCommandType.name();
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return "Unknown Description";
|
return "Unknown Description";
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,19 @@
|
||||||
|
package info.nightscout.androidaps.plugins.pump.common.hw.rileylink.defs;
|
||||||
|
|
||||||
|
import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.service.RileyLinkService;
|
||||||
|
|
||||||
|
public interface RileyLinkPumpDevice {
|
||||||
|
|
||||||
|
void setIsBusy(boolean isBusy_);
|
||||||
|
|
||||||
|
boolean isBusy();
|
||||||
|
|
||||||
|
void resetRileyLinkConfiguration();
|
||||||
|
|
||||||
|
boolean hasTuneUp();
|
||||||
|
|
||||||
|
void doTuneUpDevice();
|
||||||
|
|
||||||
|
RileyLinkService getRileyLinkService();
|
||||||
|
|
||||||
|
}
|
|
@ -13,7 +13,15 @@ import java.util.Locale;
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
|
|
||||||
import dagger.android.support.DaggerFragment;
|
import dagger.android.support.DaggerFragment;
|
||||||
|
import info.nightscout.androidaps.MainApp;
|
||||||
import info.nightscout.androidaps.R;
|
import info.nightscout.androidaps.R;
|
||||||
|
import info.nightscout.androidaps.interfaces.ActivePluginProvider;
|
||||||
|
import info.nightscout.androidaps.interfaces.PumpDescription;
|
||||||
|
import info.nightscout.androidaps.logging.AAPSLogger;
|
||||||
|
import info.nightscout.androidaps.plugins.common.ManufacturerType;
|
||||||
|
import info.nightscout.androidaps.plugins.pump.common.PumpPluginAbstract;
|
||||||
|
import info.nightscout.androidaps.plugins.pump.common.data.PumpStatus;
|
||||||
|
import info.nightscout.androidaps.plugins.pump.common.defs.PumpType;
|
||||||
import info.nightscout.androidaps.plugins.pump.common.dialog.RefreshableInterface;
|
import info.nightscout.androidaps.plugins.pump.common.dialog.RefreshableInterface;
|
||||||
import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.RileyLinkUtil;
|
import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.RileyLinkUtil;
|
||||||
import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.ble.defs.RileyLinkFirmwareVersion;
|
import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.ble.defs.RileyLinkFirmwareVersion;
|
||||||
|
@ -23,6 +31,7 @@ import info.nightscout.androidaps.plugins.pump.common.utils.StringUtil;
|
||||||
import info.nightscout.androidaps.plugins.pump.medtronic.MedtronicPumpPlugin;
|
import info.nightscout.androidaps.plugins.pump.medtronic.MedtronicPumpPlugin;
|
||||||
import info.nightscout.androidaps.plugins.pump.medtronic.driver.MedtronicPumpStatus;
|
import info.nightscout.androidaps.plugins.pump.medtronic.driver.MedtronicPumpStatus;
|
||||||
import info.nightscout.androidaps.plugins.pump.medtronic.util.MedtronicUtil;
|
import info.nightscout.androidaps.plugins.pump.medtronic.util.MedtronicUtil;
|
||||||
|
import info.nightscout.androidaps.plugins.pump.omnipod.driver.OmnipodPumpStatus;
|
||||||
import info.nightscout.androidaps.utils.resources.ResourceHelper;
|
import info.nightscout.androidaps.utils.resources.ResourceHelper;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -31,11 +40,10 @@ import info.nightscout.androidaps.utils.resources.ResourceHelper;
|
||||||
|
|
||||||
public class RileyLinkStatusGeneralFragment extends DaggerFragment implements RefreshableInterface {
|
public class RileyLinkStatusGeneralFragment extends DaggerFragment implements RefreshableInterface {
|
||||||
|
|
||||||
@Inject RileyLinkUtil rileyLinkUtil;
|
@Inject ActivePluginProvider activePlugin;
|
||||||
@Inject MedtronicUtil medtronicUtil;
|
|
||||||
@Inject MedtronicPumpStatus medtronicPumpStatus;
|
|
||||||
@Inject ResourceHelper resourceHelper;
|
@Inject ResourceHelper resourceHelper;
|
||||||
@Inject MedtronicPumpPlugin medtronicPumpPlugin;
|
@Inject MedtronicUtil medtronicUtil;
|
||||||
|
@Inject AAPSLogger aapsLogger;
|
||||||
@Inject RileyLinkServiceData rileyLinkServiceData;
|
@Inject RileyLinkServiceData rileyLinkServiceData;
|
||||||
|
|
||||||
TextView connectionStatus;
|
TextView connectionStatus;
|
||||||
|
@ -120,16 +128,16 @@ public class RileyLinkStatusGeneralFragment extends DaggerFragment implements Re
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO add handling for Omnipod pump status
|
PumpPluginAbstract pumpPlugin = (PumpPluginAbstract)activePlugin.getActivePump();
|
||||||
|
|
||||||
|
if (pumpPlugin.manufacturer()== ManufacturerType.Medtronic) {
|
||||||
|
MedtronicPumpStatus medtronicPumpStatus = (MedtronicPumpStatus)pumpPlugin.getPumpStatusData();
|
||||||
|
|
||||||
if (medtronicPumpStatus != null) {
|
|
||||||
this.deviceType.setText(resourceHelper.gs(RileyLinkTargetDevice.MedtronicPump.getResourceId()));
|
this.deviceType.setText(resourceHelper.gs(RileyLinkTargetDevice.MedtronicPump.getResourceId()));
|
||||||
this.deviceModel.setText(medtronicPumpPlugin.getPumpDescription().pumpType.getDescription());
|
this.deviceModel.setText(pumpPlugin.getPumpType().getDescription());
|
||||||
this.serialNumber.setText(medtronicPumpStatus.serialNumber);
|
this.serialNumber.setText(medtronicPumpStatus.serialNumber);
|
||||||
this.pumpFrequency.setText(resourceHelper.gs(medtronicPumpStatus.pumpFrequency.equals("medtronic_pump_frequency_us_ca") ? R.string.medtronic_pump_frequency_us_ca : R.string.medtronic_pump_frequency_worldwide));
|
this.pumpFrequency.setText(resourceHelper.gs(medtronicPumpStatus.pumpFrequency.equals("medtronic_pump_frequency_us_ca") ? R.string.medtronic_pump_frequency_us_ca : R.string.medtronic_pump_frequency_worldwide));
|
||||||
|
|
||||||
// TODO extend when Omnipod used
|
|
||||||
|
|
||||||
if (medtronicUtil.getMedtronicPumpModel() != null)
|
if (medtronicUtil.getMedtronicPumpModel() != null)
|
||||||
this.connectedDevice.setText("Medtronic " + medtronicUtil.getMedtronicPumpModel().getPumpModel());
|
this.connectedDevice.setText("Medtronic " + medtronicUtil.getMedtronicPumpModel().getPumpModel());
|
||||||
else
|
else
|
||||||
|
@ -143,7 +151,44 @@ public class RileyLinkStatusGeneralFragment extends DaggerFragment implements Re
|
||||||
this.lastDeviceContact.setText(StringUtil.toDateTimeString(new LocalDateTime(
|
this.lastDeviceContact.setText(StringUtil.toDateTimeString(new LocalDateTime(
|
||||||
medtronicPumpStatus.lastDataTime)));
|
medtronicPumpStatus.lastDataTime)));
|
||||||
else
|
else
|
||||||
this.lastDeviceContact.setText("Never");
|
this.lastDeviceContact.setText(resourceHelper.gs(R.string.common_never));
|
||||||
|
} else {
|
||||||
|
|
||||||
|
OmnipodPumpStatus omnipodPumpStatus = (OmnipodPumpStatus)pumpPlugin.getPumpStatusData();
|
||||||
|
|
||||||
|
this.deviceType.setText(resourceHelper.gs(RileyLinkTargetDevice.Omnipod.getResourceId()));
|
||||||
|
this.deviceModel.setText(pumpPlugin.getPumpType() == PumpType.Insulet_Omnipod ? "Eros" : "Dash");
|
||||||
|
|
||||||
|
if (pumpPlugin.getPumpType()== PumpType.Insulet_Omnipod_Dash) {
|
||||||
|
aapsLogger.error("Omnipod Dash not yet supported !!!");
|
||||||
|
|
||||||
|
this.pumpFrequency.setText("-");
|
||||||
|
} else {
|
||||||
|
|
||||||
|
this.pumpFrequency.setText(resourceHelper.gs(R.string.omnipod_frequency));
|
||||||
|
|
||||||
|
if (omnipodPumpStatus != null) {
|
||||||
|
|
||||||
|
if (omnipodPumpStatus.podAvailable) {
|
||||||
|
this.serialNumber.setText(omnipodPumpStatus.podLotNumber);
|
||||||
|
this.connectedDevice.setText(omnipodPumpStatus.pumpType == PumpType.Insulet_Omnipod ? "Eros Pod" : "Dash Pod");
|
||||||
|
} else {
|
||||||
|
this.serialNumber.setText("??");
|
||||||
|
this.connectedDevice.setText("-");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rileyLinkServiceData.lastGoodFrequency != null)
|
||||||
|
this.lastUsedFrequency.setText(String.format(Locale.ENGLISH, "%.2f MHz",
|
||||||
|
rileyLinkServiceData.lastGoodFrequency));
|
||||||
|
|
||||||
|
if (omnipodPumpStatus.lastConnection != 0)
|
||||||
|
this.lastDeviceContact.setText(StringUtil.toDateTimeString(new LocalDateTime(
|
||||||
|
omnipodPumpStatus.lastDataTime)));
|
||||||
|
else
|
||||||
|
this.lastDeviceContact.setText(resourceHelper.gs(R.string.common_never));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,6 +10,8 @@ import org.jetbrains.annotations.NotNull;
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
|
|
||||||
import dagger.android.DaggerService;
|
import dagger.android.DaggerService;
|
||||||
|
import dagger.android.HasAndroidInjector;
|
||||||
|
import info.nightscout.androidaps.interfaces.ActivePluginProvider;
|
||||||
import info.nightscout.androidaps.logging.AAPSLogger;
|
import info.nightscout.androidaps.logging.AAPSLogger;
|
||||||
import info.nightscout.androidaps.logging.LTag;
|
import info.nightscout.androidaps.logging.LTag;
|
||||||
import info.nightscout.androidaps.plugins.bus.RxBusWrapper;
|
import info.nightscout.androidaps.plugins.bus.RxBusWrapper;
|
||||||
|
@ -27,6 +29,7 @@ import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.service.data.
|
||||||
import info.nightscout.androidaps.plugins.pump.medtronic.defs.PumpDeviceState;
|
import info.nightscout.androidaps.plugins.pump.medtronic.defs.PumpDeviceState;
|
||||||
import info.nightscout.androidaps.plugins.pump.medtronic.driver.MedtronicPumpStatus;
|
import info.nightscout.androidaps.plugins.pump.medtronic.driver.MedtronicPumpStatus;
|
||||||
import info.nightscout.androidaps.plugins.pump.medtronic.util.MedtronicUtil;
|
import info.nightscout.androidaps.plugins.pump.medtronic.util.MedtronicUtil;
|
||||||
|
import info.nightscout.androidaps.utils.resources.ResourceHelper;
|
||||||
import info.nightscout.androidaps.utils.sharedPreferences.SP;
|
import info.nightscout.androidaps.utils.sharedPreferences.SP;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -40,9 +43,10 @@ public abstract class RileyLinkService extends DaggerService {
|
||||||
@Inject protected Context context;
|
@Inject protected Context context;
|
||||||
@Inject protected RxBusWrapper rxBus;
|
@Inject protected RxBusWrapper rxBus;
|
||||||
@Inject protected RileyLinkUtil rileyLinkUtil;
|
@Inject protected RileyLinkUtil rileyLinkUtil;
|
||||||
@Inject protected MedtronicUtil medtronicUtil; // TODO should be avoided here as it's MDT
|
@Inject protected HasAndroidInjector injector;
|
||||||
|
@Inject protected ResourceHelper resourceHelper;
|
||||||
@Inject protected RileyLinkServiceData rileyLinkServiceData;
|
@Inject protected RileyLinkServiceData rileyLinkServiceData;
|
||||||
@Inject protected MedtronicPumpStatus medtronicPumpStatus;
|
@Inject protected ActivePluginProvider activePlugin;
|
||||||
|
|
||||||
@NotNull protected RileyLinkBLE rileyLinkBLE; // android-bluetooth management, must be set in initRileyLinkServiceData
|
@NotNull protected RileyLinkBLE rileyLinkBLE; // android-bluetooth management, must be set in initRileyLinkServiceData
|
||||||
protected BluetoothAdapter bluetoothAdapter;
|
protected BluetoothAdapter bluetoothAdapter;
|
||||||
|
@ -202,11 +206,13 @@ public abstract class RileyLinkService extends DaggerService {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// FIXME: This needs to be run in a session so that is interruptable, has a separate thread, etc.
|
// FIXME: This needs to be run in a session so that is interruptable, has a separate thread, etc.
|
||||||
public void doTuneUpDevice() {
|
public void doTuneUpDevice() {
|
||||||
|
|
||||||
rileyLinkServiceData.setRileyLinkServiceState(RileyLinkServiceState.TuneUpDevice);
|
rileyLinkServiceData.setRileyLinkServiceState(RileyLinkServiceState.TuneUpDevice);
|
||||||
medtronicPumpStatus.setPumpDeviceState(PumpDeviceState.Sleeping);
|
setPumpDeviceState(PumpDeviceState.Sleeping);
|
||||||
|
|
||||||
double lastGoodFrequency = 0.0d;
|
double lastGoodFrequency = 0.0d;
|
||||||
|
|
||||||
|
@ -238,6 +244,9 @@ public abstract class RileyLinkService extends DaggerService {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public abstract void setPumpDeviceState(PumpDeviceState pumpDeviceState);
|
||||||
|
|
||||||
|
|
||||||
public void disconnectRileyLink() {
|
public void disconnectRileyLink() {
|
||||||
|
|
||||||
if (rileyLinkBLE.isConnected()) {
|
if (rileyLinkBLE.isConnected()) {
|
||||||
|
@ -272,4 +281,6 @@ public abstract class RileyLinkService extends DaggerService {
|
||||||
else
|
else
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public abstract boolean verifyConfiguration();
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,14 +8,18 @@ import dagger.android.HasAndroidInjector;
|
||||||
import info.nightscout.androidaps.interfaces.ActivePluginProvider;
|
import info.nightscout.androidaps.interfaces.ActivePluginProvider;
|
||||||
import info.nightscout.androidaps.logging.AAPSLogger;
|
import info.nightscout.androidaps.logging.AAPSLogger;
|
||||||
import info.nightscout.androidaps.logging.LTag;
|
import info.nightscout.androidaps.logging.LTag;
|
||||||
|
import info.nightscout.androidaps.plugins.common.ManufacturerType;
|
||||||
import info.nightscout.androidaps.plugins.pump.common.PumpPluginAbstract;
|
import info.nightscout.androidaps.plugins.pump.common.PumpPluginAbstract;
|
||||||
import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.RileyLinkCommunicationManager;
|
import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.RileyLinkCommunicationManager;
|
||||||
import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.RileyLinkConst;
|
import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.RileyLinkConst;
|
||||||
import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.RileyLinkUtil;
|
import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.RileyLinkUtil;
|
||||||
|
import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.ble.defs.RileyLinkTargetFrequency;
|
||||||
import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.defs.RileyLinkError;
|
import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.defs.RileyLinkError;
|
||||||
|
import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.defs.RileyLinkPumpDevice;
|
||||||
import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.defs.RileyLinkServiceState;
|
import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.defs.RileyLinkServiceState;
|
||||||
import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.service.RileyLinkServiceData;
|
import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.service.RileyLinkServiceData;
|
||||||
import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.service.data.ServiceTransport;
|
import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.service.data.ServiceTransport;
|
||||||
|
import info.nightscout.androidaps.utils.Round;
|
||||||
import info.nightscout.androidaps.utils.sharedPreferences.SP;
|
import info.nightscout.androidaps.utils.sharedPreferences.SP;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -62,29 +66,53 @@ public class InitializePumpManagerTask extends ServiceTask {
|
||||||
lastGoodFrequency = rileyLinkServiceData.lastGoodFrequency;
|
lastGoodFrequency = rileyLinkServiceData.lastGoodFrequency;
|
||||||
}
|
}
|
||||||
|
|
||||||
RileyLinkCommunicationManager rileyLinkCommunicationManager = ((PumpPluginAbstract) activePlugin.getActivePump()).getRileyLinkService().getDeviceCommunicationManager();
|
// TODO Omnipod/Dagger needs refactoring
|
||||||
|
RileyLinkCommunicationManager rileyLinkCommunicationManager = ((RileyLinkPumpDevice) activePlugin.getActivePump()).getRileyLinkService().getDeviceCommunicationManager();
|
||||||
|
|
||||||
|
if (activePlugin.getActivePump().manufacturer() == ManufacturerType.Medtronic) {
|
||||||
|
|
||||||
|
if ((lastGoodFrequency > 0.0d)
|
||||||
|
&& rileyLinkCommunicationManager.isValidFrequency(lastGoodFrequency)) {
|
||||||
|
|
||||||
|
rileyLinkServiceData.setRileyLinkServiceState(RileyLinkServiceState.RileyLinkReady);
|
||||||
|
|
||||||
|
aapsLogger.info(LTag.PUMPCOMM, "Setting radio frequency to {} MHz", lastGoodFrequency);
|
||||||
|
|
||||||
|
rileyLinkCommunicationManager.setRadioFrequencyForPump(lastGoodFrequency);
|
||||||
|
|
||||||
|
boolean foundThePump = rileyLinkCommunicationManager.tryToConnectToDevice();
|
||||||
|
|
||||||
|
if (foundThePump) {
|
||||||
|
rileyLinkServiceData.setRileyLinkServiceState(RileyLinkServiceState.PumpConnectorReady);
|
||||||
|
} else {
|
||||||
|
rileyLinkServiceData.setServiceState(RileyLinkServiceState.PumpConnectorError,
|
||||||
|
RileyLinkError.NoContactWithDevice);
|
||||||
|
rileyLinkUtil.sendBroadcastMessage(RileyLinkConst.IPC.MSG_PUMP_tunePump, context);
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
rileyLinkUtil.sendBroadcastMessage(RileyLinkConst.IPC.MSG_PUMP_tunePump, context);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
|
||||||
|
if (!Round.isSame(lastGoodFrequency, RileyLinkTargetFrequency.Omnipod.getScanFrequencies()[0])) {
|
||||||
|
lastGoodFrequency = RileyLinkTargetFrequency.Omnipod.getScanFrequencies()[0];
|
||||||
|
lastGoodFrequency = Math.round(lastGoodFrequency * 1000d) / 1000d;
|
||||||
|
|
||||||
|
rileyLinkServiceData.lastGoodFrequency = lastGoodFrequency;
|
||||||
|
}
|
||||||
|
|
||||||
if ((lastGoodFrequency > 0.0d)
|
|
||||||
&& rileyLinkCommunicationManager.isValidFrequency(lastGoodFrequency)) {
|
|
||||||
|
|
||||||
rileyLinkServiceData.setRileyLinkServiceState(RileyLinkServiceState.RileyLinkReady);
|
rileyLinkServiceData.setRileyLinkServiceState(RileyLinkServiceState.RileyLinkReady);
|
||||||
|
rileyLinkUtil.setRileyLinkTargetFrequency(RileyLinkTargetFrequency.Omnipod);
|
||||||
|
|
||||||
aapsLogger.info(LTag.PUMPCOMM, "Setting radio frequency to {} MHz", lastGoodFrequency);
|
aapsLogger.info(LTag.PUMPCOMM, "Setting radio frequency to {} MHz", lastGoodFrequency);
|
||||||
|
|
||||||
rileyLinkCommunicationManager.setRadioFrequencyForPump(lastGoodFrequency);
|
rileyLinkCommunicationManager.setRadioFrequencyForPump(lastGoodFrequency);
|
||||||
|
|
||||||
boolean foundThePump = rileyLinkCommunicationManager.tryToConnectToDevice();
|
rileyLinkServiceData.setRileyLinkServiceState(RileyLinkServiceState.PumpConnectorReady);
|
||||||
|
|
||||||
if (foundThePump) {
|
|
||||||
rileyLinkServiceData.setRileyLinkServiceState(RileyLinkServiceState.PumpConnectorReady);
|
|
||||||
} else {
|
|
||||||
rileyLinkServiceData.setServiceState(RileyLinkServiceState.PumpConnectorError,
|
|
||||||
RileyLinkError.NoContactWithDevice);
|
|
||||||
rileyLinkUtil.sendBroadcastMessage(RileyLinkConst.IPC.MSG_PUMP_tunePump, context);
|
|
||||||
}
|
|
||||||
|
|
||||||
} else {
|
|
||||||
rileyLinkUtil.sendBroadcastMessage(RileyLinkConst.IPC.MSG_PUMP_tunePump, context);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,10 +4,11 @@ import javax.inject.Inject;
|
||||||
|
|
||||||
import dagger.android.HasAndroidInjector;
|
import dagger.android.HasAndroidInjector;
|
||||||
import info.nightscout.androidaps.interfaces.ActivePluginProvider;
|
import info.nightscout.androidaps.interfaces.ActivePluginProvider;
|
||||||
import info.nightscout.androidaps.interfaces.PumpInterface;
|
|
||||||
import info.nightscout.androidaps.plugins.bus.RxBus;
|
import info.nightscout.androidaps.plugins.bus.RxBus;
|
||||||
import info.nightscout.androidaps.plugins.bus.RxBusWrapper;
|
import info.nightscout.androidaps.plugins.bus.RxBusWrapper;
|
||||||
|
import info.nightscout.androidaps.plugins.common.ManufacturerType;
|
||||||
import info.nightscout.androidaps.plugins.pump.common.PumpPluginAbstract;
|
import info.nightscout.androidaps.plugins.pump.common.PumpPluginAbstract;
|
||||||
|
import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.defs.RileyLinkPumpDevice;
|
||||||
import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.service.data.ServiceTransport;
|
import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.service.data.ServiceTransport;
|
||||||
import info.nightscout.androidaps.plugins.pump.medtronic.MedtronicPumpPlugin;
|
import info.nightscout.androidaps.plugins.pump.medtronic.MedtronicPumpPlugin;
|
||||||
import info.nightscout.androidaps.plugins.pump.medtronic.events.EventRefreshButtonState;
|
import info.nightscout.androidaps.plugins.pump.medtronic.events.EventRefreshButtonState;
|
||||||
|
@ -21,9 +22,6 @@ public class ResetRileyLinkConfigurationTask extends PumpTask {
|
||||||
@Inject ActivePluginProvider activePlugin;
|
@Inject ActivePluginProvider activePlugin;
|
||||||
@Inject RxBusWrapper rxBus;
|
@Inject RxBusWrapper rxBus;
|
||||||
|
|
||||||
private static final String TAG = "ResetRileyLinkTask";
|
|
||||||
|
|
||||||
|
|
||||||
public ResetRileyLinkConfigurationTask(HasAndroidInjector injector) {
|
public ResetRileyLinkConfigurationTask(HasAndroidInjector injector) {
|
||||||
super(injector);
|
super(injector);
|
||||||
}
|
}
|
||||||
|
@ -36,12 +34,16 @@ public class ResetRileyLinkConfigurationTask extends PumpTask {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
PumpPluginAbstract pump = (PumpPluginAbstract) activePlugin.getActivePump();
|
RileyLinkPumpDevice pumpAbstract = (RileyLinkPumpDevice)activePlugin.getActivePump();
|
||||||
|
|
||||||
rxBus.send(new EventRefreshButtonState(false));
|
rxBus.send(new EventRefreshButtonState(false));
|
||||||
MedtronicPumpPlugin.isBusy = true;
|
|
||||||
pump.resetRileyLinkConfiguration();
|
pumpAbstract.setIsBusy(true);
|
||||||
MedtronicPumpPlugin.isBusy = false;
|
pumpAbstract.resetRileyLinkConfiguration();
|
||||||
|
pumpAbstract.setIsBusy(false);
|
||||||
|
|
||||||
rxBus.send(new EventRefreshButtonState(true));
|
rxBus.send(new EventRefreshButtonState(true));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,6 +6,7 @@ import dagger.android.HasAndroidInjector;
|
||||||
import info.nightscout.androidaps.interfaces.ActivePluginProvider;
|
import info.nightscout.androidaps.interfaces.ActivePluginProvider;
|
||||||
import info.nightscout.androidaps.plugins.bus.RxBusWrapper;
|
import info.nightscout.androidaps.plugins.bus.RxBusWrapper;
|
||||||
import info.nightscout.androidaps.plugins.pump.common.PumpPluginAbstract;
|
import info.nightscout.androidaps.plugins.pump.common.PumpPluginAbstract;
|
||||||
|
import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.defs.RileyLinkPumpDevice;
|
||||||
import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.service.data.ServiceTransport;
|
import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.service.data.ServiceTransport;
|
||||||
import info.nightscout.androidaps.plugins.pump.medtronic.MedtronicPumpPlugin;
|
import info.nightscout.androidaps.plugins.pump.medtronic.MedtronicPumpPlugin;
|
||||||
import info.nightscout.androidaps.plugins.pump.medtronic.events.EventRefreshButtonState;
|
import info.nightscout.androidaps.plugins.pump.medtronic.events.EventRefreshButtonState;
|
||||||
|
@ -33,11 +34,11 @@ public class WakeAndTuneTask extends PumpTask {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
PumpPluginAbstract pump = (PumpPluginAbstract) activePlugin.getActivePump();
|
RileyLinkPumpDevice pumpDevice = (RileyLinkPumpDevice)activePlugin.getActivePump();
|
||||||
rxBus.send(new EventRefreshButtonState(false));
|
rxBus.send(new EventRefreshButtonState(false));
|
||||||
MedtronicPumpPlugin.isBusy = true;
|
pumpDevice.setIsBusy(true);
|
||||||
pump.doTuneUpDevice();
|
pumpDevice.doTuneUpDevice();
|
||||||
MedtronicPumpPlugin.isBusy = false;
|
pumpDevice.setIsBusy(false);
|
||||||
rxBus.send(new EventRefreshButtonState(true));
|
rxBus.send(new EventRefreshButtonState(true));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,13 +4,13 @@ import android.bluetooth.BluetoothSocket;
|
||||||
import android.os.SystemClock;
|
import android.os.SystemClock;
|
||||||
|
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.io.OutputStream;
|
import java.io.OutputStream;
|
||||||
|
|
||||||
import info.nightscout.androidaps.logging.L;
|
import info.nightscout.androidaps.logging.L;
|
||||||
|
import info.nightscout.androidaps.logging.LTag;
|
||||||
import info.nightscout.androidaps.logging.StacktraceLoggerWrapper;
|
import info.nightscout.androidaps.logging.StacktraceLoggerWrapper;
|
||||||
import info.nightscout.androidaps.plugins.pump.danaR.comm.MessageBase;
|
import info.nightscout.androidaps.plugins.pump.danaR.comm.MessageBase;
|
||||||
import info.nightscout.androidaps.plugins.pump.danaR.comm.MessageHashTableBase;
|
import info.nightscout.androidaps.plugins.pump.danaR.comm.MessageHashTableBase;
|
||||||
|
@ -21,7 +21,7 @@ import info.nightscout.androidaps.utils.CRC;
|
||||||
* Created by mike on 17.07.2016.
|
* Created by mike on 17.07.2016.
|
||||||
*/
|
*/
|
||||||
public class SerialIOThread extends AbstractSerialIOThread {
|
public class SerialIOThread extends AbstractSerialIOThread {
|
||||||
private static Logger log = StacktraceLoggerWrapper.getLogger(L.PUMPBTCOMM);
|
private static Logger log = StacktraceLoggerWrapper.getLogger(LTag.PUMPBTCOMM);
|
||||||
|
|
||||||
private InputStream mInputStream = null;
|
private InputStream mInputStream = null;
|
||||||
private OutputStream mOutputStream = null;
|
private OutputStream mOutputStream = null;
|
||||||
|
@ -76,7 +76,7 @@ public class SerialIOThread extends AbstractSerialIOThread {
|
||||||
message = hashTable.findMessage(command);
|
message = hashTable.findMessage(command);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (L.isEnabled(L.PUMPBTCOMM))
|
if (L.isEnabled(LTag.PUMPBTCOMM))
|
||||||
log.debug("<<<<< " + message.getMessageName() + " " + MessageBase.toHexString(extractedBuff));
|
log.debug("<<<<< " + message.getMessageName() + " " + MessageBase.toHexString(extractedBuff));
|
||||||
|
|
||||||
// process the message content
|
// process the message content
|
||||||
|
@ -152,7 +152,7 @@ public class SerialIOThread extends AbstractSerialIOThread {
|
||||||
processedMessage = message;
|
processedMessage = message;
|
||||||
|
|
||||||
byte[] messageBytes = message.getRawMessageBytes();
|
byte[] messageBytes = message.getRawMessageBytes();
|
||||||
if (L.isEnabled(L.PUMPBTCOMM))
|
if (L.isEnabled(LTag.PUMPBTCOMM))
|
||||||
log.debug(">>>>> " + message.getMessageName() + " " + MessageBase.toHexString(messageBytes));
|
log.debug(">>>>> " + message.getMessageName() + " " + MessageBase.toHexString(messageBytes));
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
@ -172,11 +172,11 @@ public class SerialIOThread extends AbstractSerialIOThread {
|
||||||
SystemClock.sleep(200);
|
SystemClock.sleep(200);
|
||||||
if (!message.isReceived()) {
|
if (!message.isReceived()) {
|
||||||
message.handleMessageNotReceived();
|
message.handleMessageNotReceived();
|
||||||
if (L.isEnabled(L.PUMPBTCOMM))
|
if (L.isEnabled(LTag.PUMPBTCOMM))
|
||||||
log.error("Reply not received " + message.getMessageName());
|
log.error("Reply not received " + message.getMessageName());
|
||||||
if (message.getCommand() == 0xF0F1) {
|
if (message.getCommand() == 0xF0F1) {
|
||||||
danaRPump.setNewPump(false);
|
danaRPump.setNewPump(false);
|
||||||
if (L.isEnabled(L.PUMPCOMM))
|
if (L.isEnabled(LTag.PUMPCOMM))
|
||||||
log.debug("Old firmware detected");
|
log.debug("Old firmware detected");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -188,28 +188,28 @@ public class SerialIOThread extends AbstractSerialIOThread {
|
||||||
try {
|
try {
|
||||||
mInputStream.close();
|
mInputStream.close();
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
if (L.isEnabled(L.PUMPBTCOMM))
|
if (L.isEnabled(LTag.PUMPBTCOMM))
|
||||||
log.debug(e.getMessage());
|
log.debug(e.getMessage());
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
mOutputStream.close();
|
mOutputStream.close();
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
if (L.isEnabled(L.PUMPBTCOMM))
|
if (L.isEnabled(LTag.PUMPBTCOMM))
|
||||||
log.debug(e.getMessage());
|
log.debug(e.getMessage());
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
mRfCommSocket.close();
|
mRfCommSocket.close();
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
if (L.isEnabled(L.PUMPBTCOMM))
|
if (L.isEnabled(LTag.PUMPBTCOMM))
|
||||||
log.debug(e.getMessage());
|
log.debug(e.getMessage());
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
System.runFinalization();
|
System.runFinalization();
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
if (L.isEnabled(L.PUMPBTCOMM))
|
if (L.isEnabled(LTag.PUMPBTCOMM))
|
||||||
log.debug(e.getMessage());
|
log.debug(e.getMessage());
|
||||||
}
|
}
|
||||||
if (L.isEnabled(L.PUMPBTCOMM))
|
if (L.isEnabled(LTag.PUMPBTCOMM))
|
||||||
log.debug("Disconnected: " + reason);
|
log.debug("Disconnected: " + reason);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -11,7 +11,6 @@ import info.nightscout.androidaps.events.EventInitializationChanged
|
||||||
import info.nightscout.androidaps.interfaces.CommandQueueProvider
|
import info.nightscout.androidaps.interfaces.CommandQueueProvider
|
||||||
import info.nightscout.androidaps.interfaces.PluginType
|
import info.nightscout.androidaps.interfaces.PluginType
|
||||||
import info.nightscout.androidaps.logging.AAPSLogger
|
import info.nightscout.androidaps.logging.AAPSLogger
|
||||||
import info.nightscout.androidaps.logging.L
|
|
||||||
import info.nightscout.androidaps.logging.LTag
|
import info.nightscout.androidaps.logging.LTag
|
||||||
import info.nightscout.androidaps.plugins.bus.RxBusWrapper
|
import info.nightscout.androidaps.plugins.bus.RxBusWrapper
|
||||||
import info.nightscout.androidaps.plugins.pump.danaR.DanaRPlugin
|
import info.nightscout.androidaps.plugins.pump.danaR.DanaRPlugin
|
||||||
|
@ -71,16 +70,15 @@ class DanaRUserOptionsActivity : NoSplashAppCompatActivity() {
|
||||||
|
|
||||||
save_user_options.setOnClickListener { onSaveClick() }
|
save_user_options.setOnClickListener { onSaveClick() }
|
||||||
|
|
||||||
if (L.isEnabled(L.PUMP))
|
aapsLogger.debug(LTag.PUMP,
|
||||||
aapsLogger.debug(LTag.PUMP,
|
"UserOptionsLoaded:" + (System.currentTimeMillis() - danaRPump.lastConnection) / 1000 + " s ago"
|
||||||
"UserOptionsLoaded:" + (System.currentTimeMillis() - danaRPump.lastConnection) / 1000 + " s ago"
|
+ "\ntimeDisplayType:" + danaRPump.timeDisplayType
|
||||||
+ "\ntimeDisplayType:" + danaRPump.timeDisplayType
|
+ "\nbuttonScroll:" + danaRPump.buttonScrollOnOff
|
||||||
+ "\nbuttonScroll:" + danaRPump.buttonScrollOnOff
|
+ "\ntimeDisplayType:" + danaRPump.timeDisplayType
|
||||||
+ "\ntimeDisplayType:" + danaRPump.timeDisplayType
|
+ "\nlcdOnTimeSec:" + danaRPump.lcdOnTimeSec
|
||||||
+ "\nlcdOnTimeSec:" + danaRPump.lcdOnTimeSec
|
+ "\nbackLight:" + danaRPump.backlightOnTimeSec
|
||||||
+ "\nbackLight:" + danaRPump.backlightOnTimeSec
|
+ "\npumpUnits:" + danaRPump.units
|
||||||
+ "\npumpUnits:" + danaRPump.units
|
+ "\nlowReservoir:" + danaRPump.lowReservoirRate)
|
||||||
+ "\nlowReservoir:" + danaRPump.lowReservoirRate)
|
|
||||||
|
|
||||||
danar_screentimeout.setParams(danaRPump.lcdOnTimeSec.toDouble(), 5.0, 240.0, 5.0, DecimalFormat("1"), false, save_user_options)
|
danar_screentimeout.setParams(danaRPump.lcdOnTimeSec.toDouble(), 5.0, 240.0, 5.0, DecimalFormat("1"), false, save_user_options)
|
||||||
danar_backlight.setParams(danaRPump.backlightOnTimeSec.toDouble(), 1.0, 60.0, 1.0, DecimalFormat("1"), false, save_user_options)
|
danar_backlight.setParams(danaRPump.backlightOnTimeSec.toDouble(), 1.0, 60.0, 1.0, DecimalFormat("1"), false, save_user_options)
|
||||||
|
|
|
@ -13,6 +13,7 @@ import java.util.Date;
|
||||||
import java.util.GregorianCalendar;
|
import java.util.GregorianCalendar;
|
||||||
|
|
||||||
import info.nightscout.androidaps.logging.L;
|
import info.nightscout.androidaps.logging.L;
|
||||||
|
import info.nightscout.androidaps.logging.LTag;
|
||||||
import info.nightscout.androidaps.logging.StacktraceLoggerWrapper;
|
import info.nightscout.androidaps.logging.StacktraceLoggerWrapper;
|
||||||
import info.nightscout.androidaps.utils.CRC;
|
import info.nightscout.androidaps.utils.CRC;
|
||||||
|
|
||||||
|
@ -23,7 +24,7 @@ import info.nightscout.androidaps.utils.CRC;
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public class MessageBase {
|
public class MessageBase {
|
||||||
private static Logger log = StacktraceLoggerWrapper.getLogger(L.PUMPCOMM);
|
private static Logger log = StacktraceLoggerWrapper.getLogger(LTag.PUMPCOMM);
|
||||||
public byte[] buffer = new byte[512];
|
public byte[] buffer = new byte[512];
|
||||||
private int position = 6;
|
private int position = 6;
|
||||||
|
|
||||||
|
@ -96,7 +97,7 @@ public class MessageBase {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void handleMessage(byte[] bytes) {
|
public void handleMessage(byte[] bytes) {
|
||||||
if (L.isEnabled(L.PUMPCOMM)) {
|
if (L.isEnabled(LTag.PUMPCOMM)) {
|
||||||
if (bytes.length > 6) {
|
if (bytes.length > 6) {
|
||||||
int command = (bytes[5] & 0xFF) | ((bytes[4] << 8) & 0xFF00);
|
int command = (bytes[5] & 0xFF) | ((bytes[4] << 8) & 0xFF00);
|
||||||
log.debug("UNPROCESSED MSG: " + getMessageName() + " Command: " + String.format("%04X", command) + " Data: " + toHexString(bytes));
|
log.debug("UNPROCESSED MSG: " + getMessageName() + " Command: " + String.format("%04X", command) + " Data: " + toHexString(bytes));
|
||||||
|
|
|
@ -1,11 +1,7 @@
|
||||||
package info.nightscout.androidaps.plugins.pump.danaR.comm
|
package info.nightscout.androidaps.plugins.pump.danaR.comm
|
||||||
|
|
||||||
import info.nightscout.androidaps.logging.AAPSLogger
|
import info.nightscout.androidaps.logging.AAPSLogger
|
||||||
import info.nightscout.androidaps.logging.L
|
|
||||||
import info.nightscout.androidaps.logging.L.isEnabled
|
|
||||||
import info.nightscout.androidaps.logging.LTag
|
import info.nightscout.androidaps.logging.LTag
|
||||||
import info.nightscout.androidaps.logging.StacktraceLoggerWrapper.Companion.getLogger
|
|
||||||
import org.slf4j.Logger
|
|
||||||
|
|
||||||
class MsgSetTempBasalStop(
|
class MsgSetTempBasalStop(
|
||||||
private val aapsLogger: AAPSLogger
|
private val aapsLogger: AAPSLogger
|
||||||
|
|
|
@ -2,10 +2,7 @@ package info.nightscout.androidaps.plugins.pump.danaRS.comm
|
||||||
|
|
||||||
import com.cozmo.danar.util.BleCommandUtil
|
import com.cozmo.danar.util.BleCommandUtil
|
||||||
import info.nightscout.androidaps.logging.AAPSLogger
|
import info.nightscout.androidaps.logging.AAPSLogger
|
||||||
import info.nightscout.androidaps.logging.L
|
|
||||||
import info.nightscout.androidaps.logging.L.isEnabled
|
|
||||||
import info.nightscout.androidaps.logging.LTag
|
import info.nightscout.androidaps.logging.LTag
|
||||||
import org.slf4j.LoggerFactory
|
|
||||||
|
|
||||||
class DanaRS_Packet_General_Set_User_Time_Change_Flag_Clear(
|
class DanaRS_Packet_General_Set_User_Time_Change_Flag_Clear(
|
||||||
private val aapsLogger: AAPSLogger
|
private val aapsLogger: AAPSLogger
|
||||||
|
@ -15,6 +12,7 @@ class DanaRS_Packet_General_Set_User_Time_Change_Flag_Clear(
|
||||||
opCode = BleCommandUtil.DANAR_PACKET__OPCODE_REVIEW__SET_USER_TIME_CHANGE_FLAG_CLEAR
|
opCode = BleCommandUtil.DANAR_PACKET__OPCODE_REVIEW__SET_USER_TIME_CHANGE_FLAG_CLEAR
|
||||||
aapsLogger.debug(LTag.PUMPCOMM, "New message")
|
aapsLogger.debug(LTag.PUMPCOMM, "New message")
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun handleMessage(data: ByteArray) {
|
override fun handleMessage(data: ByteArray) {
|
||||||
val result = intFromBuff(data, 0, 1)
|
val result = intFromBuff(data, 0, 1)
|
||||||
if (result == 0) {
|
if (result == 0) {
|
||||||
|
|
|
@ -26,6 +26,7 @@ import info.nightscout.androidaps.MainApp;
|
||||||
import info.nightscout.androidaps.R;
|
import info.nightscout.androidaps.R;
|
||||||
import info.nightscout.androidaps.events.EventPumpStatusChanged;
|
import info.nightscout.androidaps.events.EventPumpStatusChanged;
|
||||||
import info.nightscout.androidaps.logging.L;
|
import info.nightscout.androidaps.logging.L;
|
||||||
|
import info.nightscout.androidaps.logging.LTag;
|
||||||
import info.nightscout.androidaps.logging.StacktraceLoggerWrapper;
|
import info.nightscout.androidaps.logging.StacktraceLoggerWrapper;
|
||||||
import info.nightscout.androidaps.plugins.bus.RxBus;
|
import info.nightscout.androidaps.plugins.bus.RxBus;
|
||||||
import info.nightscout.androidaps.plugins.general.nsclient.NSUpload;
|
import info.nightscout.androidaps.plugins.general.nsclient.NSUpload;
|
||||||
|
@ -44,7 +45,7 @@ import info.nightscout.androidaps.utils.SP;
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public class BLEComm {
|
public class BLEComm {
|
||||||
private Logger log = StacktraceLoggerWrapper.getLogger(L.PUMPBTCOMM);
|
private Logger log = StacktraceLoggerWrapper.getLogger(LTag.PUMPBTCOMM);
|
||||||
|
|
||||||
private final long WRITE_DELAY_MILLIS = 50;
|
private final long WRITE_DELAY_MILLIS = 50;
|
||||||
|
|
||||||
|
@ -81,7 +82,7 @@ public class BLEComm {
|
||||||
private BluetoothGattCharacteristic UART_Write;
|
private BluetoothGattCharacteristic UART_Write;
|
||||||
|
|
||||||
private boolean initialize() {
|
private boolean initialize() {
|
||||||
if (L.isEnabled(L.PUMPBTCOMM))
|
if (L.isEnabled(LTag.PUMPBTCOMM))
|
||||||
log.debug("Initializing BLEComm.");
|
log.debug("Initializing BLEComm.");
|
||||||
|
|
||||||
if (mBluetoothManager == null) {
|
if (mBluetoothManager == null) {
|
||||||
|
@ -139,7 +140,7 @@ public class BLEComm {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (L.isEnabled(L.PUMPBTCOMM))
|
if (L.isEnabled(LTag.PUMPBTCOMM))
|
||||||
log.debug("Trying to create a new connection from: " + from);
|
log.debug("Trying to create a new connection from: " + from);
|
||||||
mBluetoothDeviceName = device.getName();
|
mBluetoothDeviceName = device.getName();
|
||||||
mBluetoothGatt = device.connectGatt(context, false, mGattCallback);
|
mBluetoothGatt = device.connectGatt(context, false, mGattCallback);
|
||||||
|
@ -152,7 +153,7 @@ public class BLEComm {
|
||||||
}
|
}
|
||||||
|
|
||||||
public synchronized void disconnect(String from) {
|
public synchronized void disconnect(String from) {
|
||||||
if (L.isEnabled(L.PUMPBTCOMM))
|
if (L.isEnabled(LTag.PUMPBTCOMM))
|
||||||
log.debug("disconnect from: " + from);
|
log.debug("disconnect from: " + from);
|
||||||
|
|
||||||
// cancel previous scheduled disconnection to prevent closing upcomming connection
|
// cancel previous scheduled disconnection to prevent closing upcomming connection
|
||||||
|
@ -172,7 +173,7 @@ public class BLEComm {
|
||||||
}
|
}
|
||||||
|
|
||||||
public synchronized void close() {
|
public synchronized void close() {
|
||||||
if (L.isEnabled(L.PUMPBTCOMM))
|
if (L.isEnabled(LTag.PUMPBTCOMM))
|
||||||
log.debug("BluetoothAdapter close");
|
log.debug("BluetoothAdapter close");
|
||||||
if (mBluetoothGatt == null) {
|
if (mBluetoothGatt == null) {
|
||||||
return;
|
return;
|
||||||
|
@ -193,7 +194,7 @@ public class BLEComm {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void onServicesDiscovered(BluetoothGatt gatt, int status) {
|
public void onServicesDiscovered(BluetoothGatt gatt, int status) {
|
||||||
if (L.isEnabled(L.PUMPBTCOMM))
|
if (L.isEnabled(LTag.PUMPBTCOMM))
|
||||||
log.debug("onServicesDiscovered");
|
log.debug("onServicesDiscovered");
|
||||||
if (status == BluetoothGatt.GATT_SUCCESS) {
|
if (status == BluetoothGatt.GATT_SUCCESS) {
|
||||||
findCharacteristic();
|
findCharacteristic();
|
||||||
|
@ -203,21 +204,21 @@ public class BLEComm {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
|
public void onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
|
||||||
if (L.isEnabled(L.PUMPBTCOMM))
|
if (L.isEnabled(LTag.PUMPBTCOMM))
|
||||||
log.debug("onCharacteristicRead" + (characteristic != null ? ":" + DanaRS_Packet.toHexString(characteristic.getValue()) : ""));
|
log.debug("onCharacteristicRead" + (characteristic != null ? ":" + DanaRS_Packet.toHexString(characteristic.getValue()) : ""));
|
||||||
addToReadBuffer(characteristic.getValue());
|
addToReadBuffer(characteristic.getValue());
|
||||||
readDataParsing();
|
readDataParsing();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void onCharacteristicChanged(BluetoothGatt gatt, final BluetoothGattCharacteristic characteristic) {
|
public void onCharacteristicChanged(BluetoothGatt gatt, final BluetoothGattCharacteristic characteristic) {
|
||||||
if (L.isEnabled(L.PUMPBTCOMM))
|
if (L.isEnabled(LTag.PUMPBTCOMM))
|
||||||
log.debug("onCharacteristicChanged" + (characteristic != null ? ":" + DanaRS_Packet.toHexString(characteristic.getValue()) : ""));
|
log.debug("onCharacteristicChanged" + (characteristic != null ? ":" + DanaRS_Packet.toHexString(characteristic.getValue()) : ""));
|
||||||
addToReadBuffer(characteristic.getValue());
|
addToReadBuffer(characteristic.getValue());
|
||||||
new Thread(() -> readDataParsing()).start();
|
new Thread(() -> readDataParsing()).start();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void onCharacteristicWrite(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
|
public void onCharacteristicWrite(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
|
||||||
if (L.isEnabled(L.PUMPBTCOMM))
|
if (L.isEnabled(LTag.PUMPBTCOMM))
|
||||||
log.debug("onCharacteristicWrite" + (characteristic != null ? ":" + DanaRS_Packet.toHexString(characteristic.getValue()) : ""));
|
log.debug("onCharacteristicWrite" + (characteristic != null ? ":" + DanaRS_Packet.toHexString(characteristic.getValue()) : ""));
|
||||||
new Thread(() -> {
|
new Thread(() -> {
|
||||||
synchronized (mSendQueue) {
|
synchronized (mSendQueue) {
|
||||||
|
@ -233,7 +234,7 @@ public class BLEComm {
|
||||||
};
|
};
|
||||||
|
|
||||||
private synchronized void setCharacteristicNotification(BluetoothGattCharacteristic characteristic, boolean enabled) {
|
private synchronized void setCharacteristicNotification(BluetoothGattCharacteristic characteristic, boolean enabled) {
|
||||||
if (L.isEnabled(L.PUMPBTCOMM))
|
if (L.isEnabled(LTag.PUMPBTCOMM))
|
||||||
log.debug("setCharacteristicNotification");
|
log.debug("setCharacteristicNotification");
|
||||||
if ((mBluetoothAdapter == null) || (mBluetoothGatt == null)) {
|
if ((mBluetoothAdapter == null) || (mBluetoothGatt == null)) {
|
||||||
log.error("BluetoothAdapter not initialized_ERROR");
|
log.error("BluetoothAdapter not initialized_ERROR");
|
||||||
|
@ -245,7 +246,7 @@ public class BLEComm {
|
||||||
}
|
}
|
||||||
|
|
||||||
public synchronized void readCharacteristic(BluetoothGattCharacteristic characteristic) {
|
public synchronized void readCharacteristic(BluetoothGattCharacteristic characteristic) {
|
||||||
if (L.isEnabled(L.PUMPBTCOMM))
|
if (L.isEnabled(LTag.PUMPBTCOMM))
|
||||||
log.debug("readCharacteristic");
|
log.debug("readCharacteristic");
|
||||||
if ((mBluetoothAdapter == null) || (mBluetoothGatt == null)) {
|
if ((mBluetoothAdapter == null) || (mBluetoothGatt == null)) {
|
||||||
log.error("BluetoothAdapter not initialized_ERROR");
|
log.error("BluetoothAdapter not initialized_ERROR");
|
||||||
|
@ -269,7 +270,7 @@ public class BLEComm {
|
||||||
|
|
||||||
characteristic.setValue(data);
|
characteristic.setValue(data);
|
||||||
characteristic.setWriteType(BluetoothGattCharacteristic.WRITE_TYPE_NO_RESPONSE);
|
characteristic.setWriteType(BluetoothGattCharacteristic.WRITE_TYPE_NO_RESPONSE);
|
||||||
if (L.isEnabled(L.PUMPBTCOMM))
|
if (L.isEnabled(LTag.PUMPBTCOMM))
|
||||||
log.debug("writeCharacteristic:" + DanaRS_Packet.toHexString(data));
|
log.debug("writeCharacteristic:" + DanaRS_Packet.toHexString(data));
|
||||||
mBluetoothGatt.writeCharacteristic(characteristic);
|
mBluetoothGatt.writeCharacteristic(characteristic);
|
||||||
}).start();
|
}).start();
|
||||||
|
@ -290,7 +291,7 @@ public class BLEComm {
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<BluetoothGattService> getSupportedGattServices() {
|
private List<BluetoothGattService> getSupportedGattServices() {
|
||||||
if (L.isEnabled(L.PUMPBTCOMM))
|
if (L.isEnabled(LTag.PUMPBTCOMM))
|
||||||
log.debug("getSupportedGattServices");
|
log.debug("getSupportedGattServices");
|
||||||
if ((mBluetoothAdapter == null) || (mBluetoothGatt == null)) {
|
if ((mBluetoothAdapter == null) || (mBluetoothGatt == null)) {
|
||||||
log.error("BluetoothAdapter not initialized_ERROR");
|
log.error("BluetoothAdapter not initialized_ERROR");
|
||||||
|
@ -326,7 +327,7 @@ public class BLEComm {
|
||||||
}
|
}
|
||||||
|
|
||||||
private synchronized void onConnectionStateChangeSynchronized(BluetoothGatt gatt, int status, int newState) {
|
private synchronized void onConnectionStateChangeSynchronized(BluetoothGatt gatt, int status, int newState) {
|
||||||
if (L.isEnabled(L.PUMPBTCOMM))
|
if (L.isEnabled(LTag.PUMPBTCOMM))
|
||||||
log.debug("onConnectionStateChange");
|
log.debug("onConnectionStateChange");
|
||||||
|
|
||||||
if (newState == BluetoothProfile.STATE_CONNECTED) {
|
if (newState == BluetoothProfile.STATE_CONNECTED) {
|
||||||
|
@ -336,7 +337,7 @@ public class BLEComm {
|
||||||
isConnected = false;
|
isConnected = false;
|
||||||
isConnecting = false;
|
isConnecting = false;
|
||||||
RxBus.Companion.getINSTANCE().send(new EventPumpStatusChanged(EventPumpStatusChanged.Status.DISCONNECTED));
|
RxBus.Companion.getINSTANCE().send(new EventPumpStatusChanged(EventPumpStatusChanged.Status.DISCONNECTED));
|
||||||
if (L.isEnabled(L.PUMPBTCOMM))
|
if (L.isEnabled(LTag.PUMPBTCOMM))
|
||||||
log.debug("Device was disconnected " + gatt.getDevice().getName());//Device was disconnected
|
log.debug("Device was disconnected " + gatt.getDevice().getName());//Device was disconnected
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -372,7 +373,7 @@ public class BLEComm {
|
||||||
if ((readBuffer[idxStartByte] == PACKET_START_BYTE) && (readBuffer[idxStartByte + 1] == PACKET_START_BYTE)) {
|
if ((readBuffer[idxStartByte] == PACKET_START_BYTE) && (readBuffer[idxStartByte + 1] == PACKET_START_BYTE)) {
|
||||||
if (idxStartByte > 0) {
|
if (idxStartByte > 0) {
|
||||||
// if buffer doesn't start with signature remove the leading trash
|
// if buffer doesn't start with signature remove the leading trash
|
||||||
if (L.isEnabled(L.PUMPBTCOMM))
|
if (L.isEnabled(LTag.PUMPBTCOMM))
|
||||||
log.debug("Shifting the input buffer by " + idxStartByte + " bytes");
|
log.debug("Shifting the input buffer by " + idxStartByte + " bytes");
|
||||||
System.arraycopy(readBuffer, idxStartByte, readBuffer, 0, bufferLength - idxStartByte);
|
System.arraycopy(readBuffer, idxStartByte, readBuffer, 0, bufferLength - idxStartByte);
|
||||||
bufferLength -= idxStartByte;
|
bufferLength -= idxStartByte;
|
||||||
|
@ -427,16 +428,16 @@ public class BLEComm {
|
||||||
// 1st packet
|
// 1st packet
|
||||||
case (byte) BleCommandUtil.DANAR_PACKET__OPCODE_ENCRYPTION__PUMP_CHECK:
|
case (byte) BleCommandUtil.DANAR_PACKET__OPCODE_ENCRYPTION__PUMP_CHECK:
|
||||||
if (inputBuffer.length == 4 && inputBuffer[2] == 'O' && inputBuffer[3] == 'K') {
|
if (inputBuffer.length == 4 && inputBuffer[2] == 'O' && inputBuffer[3] == 'K') {
|
||||||
if (L.isEnabled(L.PUMPBTCOMM))
|
if (L.isEnabled(LTag.PUMPBTCOMM))
|
||||||
log.debug("<<<<< " + "ENCRYPTION__PUMP_CHECK (OK)" + " " + DanaRS_Packet.toHexString(inputBuffer));
|
log.debug("<<<<< " + "ENCRYPTION__PUMP_CHECK (OK)" + " " + DanaRS_Packet.toHexString(inputBuffer));
|
||||||
// Grab pairing key from preferences if exists
|
// Grab pairing key from preferences if exists
|
||||||
String pairingKey = SP.getString(MainApp.gs(R.string.key_danars_pairingkey) + DanaRSPlugin.mDeviceName, null);
|
String pairingKey = SP.getString(MainApp.gs(R.string.key_danars_pairingkey) + DanaRSPlugin.mDeviceName, null);
|
||||||
if (L.isEnabled(L.PUMPBTCOMM))
|
if (L.isEnabled(LTag.PUMPBTCOMM))
|
||||||
log.debug("Using stored pairing key: " + pairingKey);
|
log.debug("Using stored pairing key: " + pairingKey);
|
||||||
if (pairingKey != null) {
|
if (pairingKey != null) {
|
||||||
byte[] encodedPairingKey = DanaRS_Packet.hexToBytes(pairingKey);
|
byte[] encodedPairingKey = DanaRS_Packet.hexToBytes(pairingKey);
|
||||||
byte[] bytes = BleCommandUtil.getInstance().getEncryptedPacket(BleCommandUtil.DANAR_PACKET__OPCODE_ENCRYPTION__CHECK_PASSKEY, encodedPairingKey, null);
|
byte[] bytes = BleCommandUtil.getInstance().getEncryptedPacket(BleCommandUtil.DANAR_PACKET__OPCODE_ENCRYPTION__CHECK_PASSKEY, encodedPairingKey, null);
|
||||||
if (L.isEnabled(L.PUMPBTCOMM))
|
if (L.isEnabled(LTag.PUMPBTCOMM))
|
||||||
log.debug(">>>>> " + "ENCRYPTION__CHECK_PASSKEY" + " " + DanaRS_Packet.toHexString(bytes));
|
log.debug(">>>>> " + "ENCRYPTION__CHECK_PASSKEY" + " " + DanaRS_Packet.toHexString(bytes));
|
||||||
writeCharacteristic_NO_RESPONSE(getUARTWriteBTGattChar(), bytes);
|
writeCharacteristic_NO_RESPONSE(getUARTWriteBTGattChar(), bytes);
|
||||||
} else {
|
} else {
|
||||||
|
@ -445,7 +446,7 @@ public class BLEComm {
|
||||||
}
|
}
|
||||||
|
|
||||||
} else if (inputBuffer.length == 6 && inputBuffer[2] == 'P' && inputBuffer[3] == 'U' && inputBuffer[4] == 'M' && inputBuffer[5] == 'P') {
|
} else if (inputBuffer.length == 6 && inputBuffer[2] == 'P' && inputBuffer[3] == 'U' && inputBuffer[4] == 'M' && inputBuffer[5] == 'P') {
|
||||||
if (L.isEnabled(L.PUMPBTCOMM))
|
if (L.isEnabled(LTag.PUMPBTCOMM))
|
||||||
log.debug("<<<<< " + "ENCRYPTION__PUMP_CHECK (PUMP)" + " " + DanaRS_Packet.toHexString(inputBuffer));
|
log.debug("<<<<< " + "ENCRYPTION__PUMP_CHECK (PUMP)" + " " + DanaRS_Packet.toHexString(inputBuffer));
|
||||||
mSendQueue.clear();
|
mSendQueue.clear();
|
||||||
RxBus.Companion.getINSTANCE().send(new EventPumpStatusChanged(EventPumpStatusChanged.Status.DISCONNECTED, MainApp.gs(R.string.pumperror)));
|
RxBus.Companion.getINSTANCE().send(new EventPumpStatusChanged(EventPumpStatusChanged.Status.DISCONNECTED, MainApp.gs(R.string.pumperror)));
|
||||||
|
@ -453,13 +454,13 @@ public class BLEComm {
|
||||||
Notification n = new Notification(Notification.PUMPERROR, MainApp.gs(R.string.pumperror), Notification.URGENT);
|
Notification n = new Notification(Notification.PUMPERROR, MainApp.gs(R.string.pumperror), Notification.URGENT);
|
||||||
RxBus.Companion.getINSTANCE().send(new EventNewNotification(n));
|
RxBus.Companion.getINSTANCE().send(new EventNewNotification(n));
|
||||||
} else if (inputBuffer.length == 6 && inputBuffer[2] == 'B' && inputBuffer[3] == 'U' && inputBuffer[4] == 'S' && inputBuffer[5] == 'Y') {
|
} else if (inputBuffer.length == 6 && inputBuffer[2] == 'B' && inputBuffer[3] == 'U' && inputBuffer[4] == 'S' && inputBuffer[5] == 'Y') {
|
||||||
if (L.isEnabled(L.PUMPBTCOMM))
|
if (L.isEnabled(LTag.PUMPBTCOMM))
|
||||||
log.debug("<<<<< " + "ENCRYPTION__PUMP_CHECK (BUSY)" + " " + DanaRS_Packet.toHexString(inputBuffer));
|
log.debug("<<<<< " + "ENCRYPTION__PUMP_CHECK (BUSY)" + " " + DanaRS_Packet.toHexString(inputBuffer));
|
||||||
mSendQueue.clear();
|
mSendQueue.clear();
|
||||||
RxBus.Companion.getINSTANCE().send(new EventPumpStatusChanged(EventPumpStatusChanged.Status.DISCONNECTED, MainApp.gs(R.string.pumpbusy)));
|
RxBus.Companion.getINSTANCE().send(new EventPumpStatusChanged(EventPumpStatusChanged.Status.DISCONNECTED, MainApp.gs(R.string.pumpbusy)));
|
||||||
} else {
|
} else {
|
||||||
// ERROR in response, wrong serial number
|
// ERROR in response, wrong serial number
|
||||||
if (L.isEnabled(L.PUMPBTCOMM))
|
if (L.isEnabled(LTag.PUMPBTCOMM))
|
||||||
log.debug("<<<<< " + "ENCRYPTION__PUMP_CHECK (ERROR)" + " " + DanaRS_Packet.toHexString(inputBuffer));
|
log.debug("<<<<< " + "ENCRYPTION__PUMP_CHECK (ERROR)" + " " + DanaRS_Packet.toHexString(inputBuffer));
|
||||||
mSendQueue.clear();
|
mSendQueue.clear();
|
||||||
RxBus.Companion.getINSTANCE().send(new EventPumpStatusChanged(EventPumpStatusChanged.Status.DISCONNECTED, MainApp.gs(R.string.connectionerror)));
|
RxBus.Companion.getINSTANCE().send(new EventPumpStatusChanged(EventPumpStatusChanged.Status.DISCONNECTED, MainApp.gs(R.string.connectionerror)));
|
||||||
|
@ -470,7 +471,7 @@ public class BLEComm {
|
||||||
break;
|
break;
|
||||||
// 2nd packet, pairing key
|
// 2nd packet, pairing key
|
||||||
case (byte) BleCommandUtil.DANAR_PACKET__OPCODE_ENCRYPTION__CHECK_PASSKEY:
|
case (byte) BleCommandUtil.DANAR_PACKET__OPCODE_ENCRYPTION__CHECK_PASSKEY:
|
||||||
if (L.isEnabled(L.PUMPBTCOMM))
|
if (L.isEnabled(LTag.PUMPBTCOMM))
|
||||||
log.debug("<<<<< " + "ENCRYPTION__CHECK_PASSKEY" + " " + DanaRS_Packet.toHexString(inputBuffer));
|
log.debug("<<<<< " + "ENCRYPTION__CHECK_PASSKEY" + " " + DanaRS_Packet.toHexString(inputBuffer));
|
||||||
if (inputBuffer[2] == (byte) 0x00) {
|
if (inputBuffer[2] == (byte) 0x00) {
|
||||||
// Paring is not requested, sending time info
|
// Paring is not requested, sending time info
|
||||||
|
@ -481,7 +482,7 @@ public class BLEComm {
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case (byte) BleCommandUtil.DANAR_PACKET__OPCODE_ENCRYPTION__PASSKEY_REQUEST:
|
case (byte) BleCommandUtil.DANAR_PACKET__OPCODE_ENCRYPTION__PASSKEY_REQUEST:
|
||||||
if (L.isEnabled(L.PUMPBTCOMM))
|
if (L.isEnabled(LTag.PUMPBTCOMM))
|
||||||
log.debug("<<<<< " + "ENCRYPTION__PASSKEY_REQUEST " + DanaRS_Packet.toHexString(inputBuffer));
|
log.debug("<<<<< " + "ENCRYPTION__PASSKEY_REQUEST " + DanaRS_Packet.toHexString(inputBuffer));
|
||||||
if (inputBuffer[2] != (byte) 0x00) {
|
if (inputBuffer[2] != (byte) 0x00) {
|
||||||
disconnect("passkey request failed");
|
disconnect("passkey request failed");
|
||||||
|
@ -489,7 +490,7 @@ public class BLEComm {
|
||||||
break;
|
break;
|
||||||
// Paring response, OK button on pump pressed
|
// Paring response, OK button on pump pressed
|
||||||
case (byte) BleCommandUtil.DANAR_PACKET__OPCODE_ENCRYPTION__PASSKEY_RETURN:
|
case (byte) BleCommandUtil.DANAR_PACKET__OPCODE_ENCRYPTION__PASSKEY_RETURN:
|
||||||
if (L.isEnabled(L.PUMPBTCOMM))
|
if (L.isEnabled(LTag.PUMPBTCOMM))
|
||||||
log.debug("<<<<< " + "ENCRYPTION__PASSKEY_RETURN " + DanaRS_Packet.toHexString(inputBuffer));
|
log.debug("<<<<< " + "ENCRYPTION__PASSKEY_RETURN " + DanaRS_Packet.toHexString(inputBuffer));
|
||||||
// Paring is successfull, sending time info
|
// Paring is successfull, sending time info
|
||||||
RxBus.Companion.getINSTANCE().send(new EventDanaRSPairingSuccess());
|
RxBus.Companion.getINSTANCE().send(new EventDanaRSPairingSuccess());
|
||||||
|
@ -497,24 +498,24 @@ public class BLEComm {
|
||||||
byte[] pairingKey = {inputBuffer[2], inputBuffer[3]};
|
byte[] pairingKey = {inputBuffer[2], inputBuffer[3]};
|
||||||
// store pairing key to preferences
|
// store pairing key to preferences
|
||||||
SP.putString(MainApp.gs(R.string.key_danars_pairingkey) + DanaRSPlugin.mDeviceName, DanaRS_Packet.bytesToHex(pairingKey));
|
SP.putString(MainApp.gs(R.string.key_danars_pairingkey) + DanaRSPlugin.mDeviceName, DanaRS_Packet.bytesToHex(pairingKey));
|
||||||
if (L.isEnabled(L.PUMPBTCOMM))
|
if (L.isEnabled(LTag.PUMPBTCOMM))
|
||||||
log.debug("Got pairing key: " + DanaRS_Packet.bytesToHex(pairingKey));
|
log.debug("Got pairing key: " + DanaRS_Packet.bytesToHex(pairingKey));
|
||||||
break;
|
break;
|
||||||
// time and user password information. last packet in handshake
|
// time and user password information. last packet in handshake
|
||||||
case (byte) BleCommandUtil.DANAR_PACKET__OPCODE_ENCRYPTION__TIME_INFORMATION:
|
case (byte) BleCommandUtil.DANAR_PACKET__OPCODE_ENCRYPTION__TIME_INFORMATION:
|
||||||
if (L.isEnabled(L.PUMPBTCOMM))
|
if (L.isEnabled(LTag.PUMPBTCOMM))
|
||||||
log.debug("<<<<< " + "ENCRYPTION__TIME_INFORMATION " + /*message.getMessageName() + " " + */ DanaRS_Packet.toHexString(inputBuffer));
|
log.debug("<<<<< " + "ENCRYPTION__TIME_INFORMATION " + /*message.getMessageName() + " " + */ DanaRS_Packet.toHexString(inputBuffer));
|
||||||
int size = inputBuffer.length;
|
int size = inputBuffer.length;
|
||||||
int pass = ((inputBuffer[size - 1] & 0x000000FF) << 8) + ((inputBuffer[size - 2] & 0x000000FF));
|
int pass = ((inputBuffer[size - 1] & 0x000000FF) << 8) + ((inputBuffer[size - 2] & 0x000000FF));
|
||||||
pass = pass ^ 3463;
|
pass = pass ^ 3463;
|
||||||
danaRPump.setRsPassword(Integer.toHexString(pass));
|
danaRPump.setRsPassword(Integer.toHexString(pass));
|
||||||
if (L.isEnabled(L.PUMPBTCOMM))
|
if (L.isEnabled(LTag.PUMPBTCOMM))
|
||||||
log.debug("Pump user password: " + Integer.toHexString(pass));
|
log.debug("Pump user password: " + Integer.toHexString(pass));
|
||||||
|
|
||||||
RxBus.Companion.getINSTANCE().send(new EventPumpStatusChanged(EventPumpStatusChanged.Status.CONNECTED));
|
RxBus.Companion.getINSTANCE().send(new EventPumpStatusChanged(EventPumpStatusChanged.Status.CONNECTED));
|
||||||
isConnected = true;
|
isConnected = true;
|
||||||
isConnecting = false;
|
isConnecting = false;
|
||||||
if (L.isEnabled(L.PUMPBTCOMM))
|
if (L.isEnabled(LTag.PUMPBTCOMM))
|
||||||
log.debug("RS connected and status read");
|
log.debug("RS connected and status read");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -533,7 +534,7 @@ public class BLEComm {
|
||||||
message = danaRSMessageHashTable.findMessage(receivedCommand);
|
message = danaRSMessageHashTable.findMessage(receivedCommand);
|
||||||
}
|
}
|
||||||
if (message != null) {
|
if (message != null) {
|
||||||
if (L.isEnabled(L.PUMPBTCOMM))
|
if (L.isEnabled(LTag.PUMPBTCOMM))
|
||||||
log.debug("<<<<< " + message.getFriendlyName() + " " + DanaRS_Packet.toHexString(inputBuffer));
|
log.debug("<<<<< " + message.getFriendlyName() + " " + DanaRS_Packet.toHexString(inputBuffer));
|
||||||
// process received data
|
// process received data
|
||||||
message.handleMessage(inputBuffer);
|
message.handleMessage(inputBuffer);
|
||||||
|
@ -570,7 +571,7 @@ public class BLEComm {
|
||||||
|
|
||||||
byte[] command = {(byte) message.getType(), (byte) message.getOpCode()};
|
byte[] command = {(byte) message.getType(), (byte) message.getOpCode()};
|
||||||
byte[] params = message.getRequestParams();
|
byte[] params = message.getRequestParams();
|
||||||
if (L.isEnabled(L.PUMPBTCOMM))
|
if (L.isEnabled(LTag.PUMPBTCOMM))
|
||||||
log.debug(">>>>> " + message.getFriendlyName() + " " + DanaRS_Packet.toHexString(command) + " " + DanaRS_Packet.toHexString(params));
|
log.debug(">>>>> " + message.getFriendlyName() + " " + DanaRS_Packet.toHexString(command) + " " + DanaRS_Packet.toHexString(params));
|
||||||
byte[] bytes = BleCommandUtil.getInstance().getEncryptedPacket(message.getOpCode(), params, null);
|
byte[] bytes = BleCommandUtil.getInstance().getEncryptedPacket(message.getOpCode(), params, null);
|
||||||
// If there is another message not completely sent, add to queue only
|
// If there is another message not completely sent, add to queue only
|
||||||
|
@ -652,7 +653,7 @@ public class BLEComm {
|
||||||
MainApp.instance().startActivity(i);
|
MainApp.instance().startActivity(i);
|
||||||
|
|
||||||
byte[] bytes = BleCommandUtil.getInstance().getEncryptedPacket(BleCommandUtil.DANAR_PACKET__OPCODE_ENCRYPTION__PASSKEY_REQUEST, null, null);
|
byte[] bytes = BleCommandUtil.getInstance().getEncryptedPacket(BleCommandUtil.DANAR_PACKET__OPCODE_ENCRYPTION__PASSKEY_REQUEST, null, null);
|
||||||
if (L.isEnabled(L.PUMPBTCOMM))
|
if (L.isEnabled(LTag.PUMPBTCOMM))
|
||||||
log.debug(">>>>> " + "ENCRYPTION__PASSKEY_REQUEST" + " " + DanaRS_Packet.toHexString(bytes));
|
log.debug(">>>>> " + "ENCRYPTION__PASSKEY_REQUEST" + " " + DanaRS_Packet.toHexString(bytes));
|
||||||
writeCharacteristic_NO_RESPONSE(getUARTWriteBTGattChar(), bytes);
|
writeCharacteristic_NO_RESPONSE(getUARTWriteBTGattChar(), bytes);
|
||||||
}
|
}
|
||||||
|
@ -666,14 +667,14 @@ public class BLEComm {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
byte[] bytes = BleCommandUtil.getInstance().getEncryptedPacket(BleCommandUtil.DANAR_PACKET__OPCODE_ENCRYPTION__PUMP_CHECK, null, devicename);
|
byte[] bytes = BleCommandUtil.getInstance().getEncryptedPacket(BleCommandUtil.DANAR_PACKET__OPCODE_ENCRYPTION__PUMP_CHECK, null, devicename);
|
||||||
if (L.isEnabled(L.PUMPBTCOMM))
|
if (L.isEnabled(LTag.PUMPBTCOMM))
|
||||||
log.debug(">>>>> " + "ENCRYPTION__PUMP_CHECK (0x00)" + " " + DanaRS_Packet.toHexString(bytes));
|
log.debug(">>>>> " + "ENCRYPTION__PUMP_CHECK (0x00)" + " " + DanaRS_Packet.toHexString(bytes));
|
||||||
writeCharacteristic_NO_RESPONSE(getUARTWriteBTGattChar(), bytes);
|
writeCharacteristic_NO_RESPONSE(getUARTWriteBTGattChar(), bytes);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void SendTimeInfo() {
|
private void SendTimeInfo() {
|
||||||
byte[] bytes = BleCommandUtil.getInstance().getEncryptedPacket(BleCommandUtil.DANAR_PACKET__OPCODE_ENCRYPTION__TIME_INFORMATION, null, null);
|
byte[] bytes = BleCommandUtil.getInstance().getEncryptedPacket(BleCommandUtil.DANAR_PACKET__OPCODE_ENCRYPTION__TIME_INFORMATION, null, null);
|
||||||
if (L.isEnabled(L.PUMPBTCOMM))
|
if (L.isEnabled(LTag.PUMPBTCOMM))
|
||||||
log.debug(">>>>> " + "ENCRYPTION__TIME_INFORMATION" + " " + DanaRS_Packet.toHexString(bytes));
|
log.debug(">>>>> " + "ENCRYPTION__TIME_INFORMATION" + " " + DanaRS_Packet.toHexString(bytes));
|
||||||
writeCharacteristic_NO_RESPONSE(getUARTWriteBTGattChar(), bytes);
|
writeCharacteristic_NO_RESPONSE(getUARTWriteBTGattChar(), bytes);
|
||||||
}
|
}
|
||||||
|
|
|
@ -57,6 +57,7 @@ import info.nightscout.androidaps.plugins.pump.common.defs.PumpDriverState;
|
||||||
import info.nightscout.androidaps.plugins.pump.common.defs.PumpType;
|
import info.nightscout.androidaps.plugins.pump.common.defs.PumpType;
|
||||||
import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.RileyLinkConst;
|
import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.RileyLinkConst;
|
||||||
import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.RileyLinkUtil;
|
import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.RileyLinkUtil;
|
||||||
|
import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.defs.RileyLinkPumpDevice;
|
||||||
import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.defs.RileyLinkServiceState;
|
import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.defs.RileyLinkServiceState;
|
||||||
import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.service.RileyLinkServiceData;
|
import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.service.RileyLinkServiceData;
|
||||||
import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.service.tasks.ResetRileyLinkConfigurationTask;
|
import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.service.tasks.ResetRileyLinkConfigurationTask;
|
||||||
|
@ -95,7 +96,7 @@ import info.nightscout.androidaps.utils.sharedPreferences.SP;
|
||||||
* @author Andy Rozman (andy.rozman@gmail.com)
|
* @author Andy Rozman (andy.rozman@gmail.com)
|
||||||
*/
|
*/
|
||||||
@Singleton
|
@Singleton
|
||||||
public class MedtronicPumpPlugin extends PumpPluginAbstract implements PumpInterface {
|
public class MedtronicPumpPlugin extends PumpPluginAbstract implements PumpInterface, RileyLinkPumpDevice {
|
||||||
|
|
||||||
private final SP sp;
|
private final SP sp;
|
||||||
private final RileyLinkUtil rileyLinkUtil;
|
private final RileyLinkUtil rileyLinkUtil;
|
||||||
|
@ -234,6 +235,11 @@ public class MedtronicPumpPlugin extends PumpPluginAbstract implements PumpInter
|
||||||
rileyLinkMedtronicService.resetRileyLinkConfiguration();
|
rileyLinkMedtronicService.resetRileyLinkConfiguration();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean hasTuneUp() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
@Override public void doTuneUpDevice() {
|
@Override public void doTuneUpDevice() {
|
||||||
rileyLinkMedtronicService.doTuneUpDevice();
|
rileyLinkMedtronicService.doTuneUpDevice();
|
||||||
}
|
}
|
||||||
|
@ -329,6 +335,11 @@ public class MedtronicPumpPlugin extends PumpPluginAbstract implements PumpInter
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setIsBusy(boolean isBusy_) {
|
||||||
|
isBusy = isBusy_;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isBusy() {
|
public boolean isBusy() {
|
||||||
if (displayConnectionMessages)
|
if (displayConnectionMessages)
|
||||||
|
|
|
@ -92,6 +92,11 @@ public class MedtronicCommunicationManager extends RileyLinkCommunicationManager
|
||||||
return (E) pumpMessage;
|
return (E) pumpMessage;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setPumpDeviceState(PumpDeviceState pumpDeviceState) {
|
||||||
|
this.medtronicPumpStatus.setPumpDeviceState(pumpDeviceState);
|
||||||
|
}
|
||||||
|
|
||||||
public void setDoWakeUpBeforeCommand(boolean doWakeUp) {
|
public void setDoWakeUpBeforeCommand(boolean doWakeUp) {
|
||||||
this.doWakeUpBeforeCommand = doWakeUp;
|
this.doWakeUpBeforeCommand = doWakeUp;
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,13 +2,12 @@ package info.nightscout.androidaps.plugins.pump.medtronic.comm.history.cgms;
|
||||||
|
|
||||||
import org.joda.time.LocalDateTime;
|
import org.joda.time.LocalDateTime;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import info.nightscout.androidaps.logging.L;
|
import info.nightscout.androidaps.logging.LTag;
|
||||||
import info.nightscout.androidaps.logging.StacktraceLoggerWrapper;
|
import info.nightscout.androidaps.logging.StacktraceLoggerWrapper;
|
||||||
import info.nightscout.androidaps.plugins.pump.common.utils.DateTimeUtil;
|
import info.nightscout.androidaps.plugins.pump.common.utils.DateTimeUtil;
|
||||||
import info.nightscout.androidaps.plugins.pump.medtronic.comm.history.MedtronicHistoryDecoder;
|
import info.nightscout.androidaps.plugins.pump.medtronic.comm.history.MedtronicHistoryDecoder;
|
||||||
|
@ -23,7 +22,7 @@ import info.nightscout.androidaps.plugins.pump.medtronic.comm.history.RecordDeco
|
||||||
|
|
||||||
public class MedtronicCGMSHistoryDecoder extends MedtronicHistoryDecoder<CGMSHistoryEntry> {
|
public class MedtronicCGMSHistoryDecoder extends MedtronicHistoryDecoder<CGMSHistoryEntry> {
|
||||||
|
|
||||||
private static final Logger LOG = StacktraceLoggerWrapper.getLogger(L.PUMPCOMM);
|
private static final Logger LOG = StacktraceLoggerWrapper.getLogger(LTag.PUMPCOMM);
|
||||||
|
|
||||||
|
|
||||||
// CGMSValuesWriter cgmsValuesWriter = null;
|
// CGMSValuesWriter cgmsValuesWriter = null;
|
||||||
|
|
|
@ -56,6 +56,7 @@ import info.nightscout.androidaps.plugins.treatments.Treatment;
|
||||||
import info.nightscout.androidaps.plugins.treatments.TreatmentService;
|
import info.nightscout.androidaps.plugins.treatments.TreatmentService;
|
||||||
import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin;
|
import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin;
|
||||||
import info.nightscout.androidaps.utils.DateUtil;
|
import info.nightscout.androidaps.utils.DateUtil;
|
||||||
|
import info.nightscout.androidaps.utils.Round;
|
||||||
import info.nightscout.androidaps.utils.sharedPreferences.SP;
|
import info.nightscout.androidaps.utils.sharedPreferences.SP;
|
||||||
|
|
||||||
|
|
||||||
|
@ -659,7 +660,7 @@ public class MedtronicHistoryData {
|
||||||
|
|
||||||
Treatment treatment = (Treatment) dbObjectBase;
|
Treatment treatment = (Treatment) dbObjectBase;
|
||||||
|
|
||||||
if (RileyLinkUtil.isSame(treatment.insulin, 0d)) {
|
if (Round.isSame(treatment.insulin, 0d)) {
|
||||||
removeList.add(dbObjectBase);
|
removeList.add(dbObjectBase);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -364,7 +364,7 @@ public class BasalProfile {
|
||||||
|
|
||||||
|
|
||||||
private boolean isLogEnabled() {
|
private boolean isLogEnabled() {
|
||||||
return L.isEnabled(L.PUMPCOMM);
|
return L.isEnabled(LTag.PUMPCOMM);
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean verify(PumpType pumpType) {
|
public boolean verify(PumpType pumpType) {
|
||||||
|
|
|
@ -42,7 +42,7 @@ public class TempBasalPair extends info.nightscout.androidaps.plugins.pump.commo
|
||||||
public TempBasalPair(AAPSLogger aapsLogger, byte[] response) {
|
public TempBasalPair(AAPSLogger aapsLogger, byte[] response) {
|
||||||
super();
|
super();
|
||||||
|
|
||||||
if (L.isEnabled(L.PUMPCOMM))
|
if (L.isEnabled(LTag.PUMPCOMM))
|
||||||
aapsLogger.debug(LTag.PUMPBTCOMM, "Received TempBasal response: " + ByteUtil.getHex(response));
|
aapsLogger.debug(LTag.PUMPBTCOMM, "Received TempBasal response: " + ByteUtil.getHex(response));
|
||||||
|
|
||||||
isPercent = response[0] == 1;
|
isPercent = response[0] == 1;
|
||||||
|
|
|
@ -60,13 +60,12 @@ public class MedtronicPumpStatus extends PumpStatus {
|
||||||
|
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
public MedtronicPumpStatus(
|
public MedtronicPumpStatus(ResourceHelper resourceHelper,
|
||||||
ResourceHelper resourceHelper,
|
|
||||||
SP sp,
|
SP sp,
|
||||||
RxBusWrapper rxBus,
|
RxBusWrapper rxBus,
|
||||||
RileyLinkUtil rileyLinkUtil
|
RileyLinkUtil rileyLinkUtil
|
||||||
) {
|
) {
|
||||||
super();
|
super(PumpType.Medtronic_522_722);
|
||||||
this.resourceHelper = resourceHelper;
|
this.resourceHelper = resourceHelper;
|
||||||
this.sp = sp;
|
this.sp = sp;
|
||||||
this.rxBus = rxBus;
|
this.rxBus = rxBus;
|
||||||
|
@ -75,7 +74,7 @@ public class MedtronicPumpStatus extends PumpStatus {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private void initSettings() {
|
public void initSettings() {
|
||||||
|
|
||||||
this.activeProfileName = "STD";
|
this.activeProfileName = "STD";
|
||||||
this.reservoirRemainingUnits = 75d;
|
this.reservoirRemainingUnits = 75d;
|
||||||
|
|
|
@ -38,8 +38,6 @@ import info.nightscout.androidaps.utils.resources.ResourceHelper;
|
||||||
*/
|
*/
|
||||||
public class RileyLinkMedtronicService extends RileyLinkService {
|
public class RileyLinkMedtronicService extends RileyLinkService {
|
||||||
|
|
||||||
@Inject HasAndroidInjector injector;
|
|
||||||
@Inject ResourceHelper resourceHelper;
|
|
||||||
@Inject MedtronicPumpPlugin medtronicPumpPlugin;
|
@Inject MedtronicPumpPlugin medtronicPumpPlugin;
|
||||||
@Inject MedtronicUtil medtronicUtil;
|
@Inject MedtronicUtil medtronicUtil;
|
||||||
@Inject MedtronicUIPostprocessor medtronicUIPostprocessor;
|
@Inject MedtronicUIPostprocessor medtronicUIPostprocessor;
|
||||||
|
@ -120,6 +118,12 @@ public class RileyLinkMedtronicService extends RileyLinkService {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setPumpDeviceState(PumpDeviceState pumpDeviceState) {
|
||||||
|
this.medtronicPumpStatus.setPumpDeviceState(pumpDeviceState);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public MedtronicUIComm getMedtronicUIComm() {
|
public MedtronicUIComm getMedtronicUIComm() {
|
||||||
return medtronicUIComm;
|
return medtronicUIComm;
|
||||||
}
|
}
|
||||||
|
@ -236,7 +240,7 @@ public class RileyLinkMedtronicService extends RileyLinkService {
|
||||||
} else {
|
} else {
|
||||||
PumpType pumpType = medtronicPumpStatus.getMedtronicPumpMap().get(pumpTypePart);
|
PumpType pumpType = medtronicPumpStatus.getMedtronicPumpMap().get(pumpTypePart);
|
||||||
medtronicPumpStatus.medtronicDeviceType = medtronicPumpStatus.getMedtronicDeviceTypeMap().get(pumpTypePart);
|
medtronicPumpStatus.medtronicDeviceType = medtronicPumpStatus.getMedtronicDeviceTypeMap().get(pumpTypePart);
|
||||||
medtronicPumpPlugin.getPumpDescription().setPumpDescription(pumpType);
|
medtronicPumpPlugin.setPumpType(pumpType);
|
||||||
|
|
||||||
if (pumpTypePart.startsWith("7"))
|
if (pumpTypePart.startsWith("7"))
|
||||||
medtronicPumpStatus.reservoirFullUnits = 300;
|
medtronicPumpStatus.reservoirFullUnits = 300;
|
||||||
|
|
|
@ -0,0 +1,458 @@
|
||||||
|
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.view.LayoutInflater
|
||||||
|
import android.view.View
|
||||||
|
import android.view.ViewGroup
|
||||||
|
import dagger.android.support.DaggerFragment
|
||||||
|
import info.nightscout.androidaps.MainApp
|
||||||
|
import info.nightscout.androidaps.R
|
||||||
|
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.defs.PumpType
|
||||||
|
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.omnipod.defs.OmnipodStatusRequest
|
||||||
|
import info.nightscout.androidaps.plugins.pump.omnipod.defs.PodDeviceState
|
||||||
|
import info.nightscout.androidaps.plugins.pump.omnipod.dialogs.PodManagementActivity
|
||||||
|
import info.nightscout.androidaps.plugins.pump.omnipod.driver.OmnipodDriverState
|
||||||
|
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.EventOmnipodDeviceStatusChange
|
||||||
|
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.Round
|
||||||
|
import info.nightscout.androidaps.utils.T
|
||||||
|
import info.nightscout.androidaps.utils.WarnColors
|
||||||
|
import info.nightscout.androidaps.utils.alertDialogs.OKDialog
|
||||||
|
import info.nightscout.androidaps.utils.resources.ResourceHelper
|
||||||
|
import info.nightscout.androidaps.utils.sharedPreferences.SP
|
||||||
|
import io.reactivex.android.schedulers.AndroidSchedulers
|
||||||
|
import io.reactivex.disposables.CompositeDisposable
|
||||||
|
import io.reactivex.disposables.Disposable
|
||||||
|
import io.reactivex.schedulers.Schedulers
|
||||||
|
import kotlinx.android.synthetic.main.omnipod_fragment.*
|
||||||
|
import javax.inject.Inject
|
||||||
|
|
||||||
|
class OmnipodFragment : DaggerFragment() {
|
||||||
|
|
||||||
|
@Inject lateinit var aapsLogger: AAPSLogger
|
||||||
|
@Inject lateinit var mainApp: MainApp
|
||||||
|
@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 sp: SP
|
||||||
|
@Inject lateinit var omnipodUtil: OmnipodUtil
|
||||||
|
|
||||||
|
private var disposable: CompositeDisposable = CompositeDisposable()
|
||||||
|
|
||||||
|
private val loopHandler = Handler()
|
||||||
|
private lateinit var refreshLoop: Runnable
|
||||||
|
|
||||||
|
operator fun CompositeDisposable.plusAssign(disposable: Disposable) {
|
||||||
|
add(disposable)
|
||||||
|
}
|
||||||
|
|
||||||
|
init {
|
||||||
|
refreshLoop = Runnable {
|
||||||
|
activity?.runOnUiThread { updateGUI() }
|
||||||
|
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_rl_status.text = resourceHelper.gs(RileyLinkServiceState.NotStarted.getResourceId(RileyLinkTargetDevice.Omnipod))
|
||||||
|
|
||||||
|
omnipod_pod_status.setTextColor(Color.WHITE)
|
||||||
|
omnipod_pod_status.text = "{fa-bed}"
|
||||||
|
|
||||||
|
omnipod_pod_mgmt.setOnClickListener {
|
||||||
|
if (omnipodPumpPlugin.rileyLinkService?.verifyConfiguration() == true) {
|
||||||
|
startActivity(Intent(context, PodManagementActivity::class.java))
|
||||||
|
} else {
|
||||||
|
displayNotConfiguredDialog()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
omnipod_refresh.setOnClickListener {
|
||||||
|
if (omnipodPumpPlugin.rileyLinkService?.verifyConfiguration() != true) {
|
||||||
|
OmnipodUtil.displayNotConfiguredDialog(context)
|
||||||
|
} 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)
|
||||||
|
|
||||||
|
setVisibilityOfPodDebugButton()
|
||||||
|
|
||||||
|
updateGUI()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onResume() {
|
||||||
|
super.onResume()
|
||||||
|
loopHandler.postDelayed(refreshLoop, T.mins(1).msecs())
|
||||||
|
disposable += rxBus
|
||||||
|
.toObservable(EventOmnipodRefreshButtonState::class.java)
|
||||||
|
.observeOn(AndroidSchedulers.mainThread())
|
||||||
|
.subscribe({ omnipod_refresh.isEnabled = it.newState }, { fabricPrivacy.logException(it) })
|
||||||
|
disposable += rxBus
|
||||||
|
.toObservable(EventOmnipodDeviceStatusChange::class.java)
|
||||||
|
.observeOn(AndroidSchedulers.mainThread())
|
||||||
|
.subscribe({
|
||||||
|
aapsLogger.info(LTag.PUMP, "onStatusEvent(EventOmnipodDeviceStatusChange): {}", it)
|
||||||
|
setDeviceStatus()
|
||||||
|
}, { fabricPrivacy.logException(it) })
|
||||||
|
disposable += rxBus
|
||||||
|
.toObservable(EventOmnipodPumpValuesChanged::class.java)
|
||||||
|
.observeOn(AndroidSchedulers.mainThread())
|
||||||
|
.subscribe({ updateGUI() }, { fabricPrivacy.logException(it) })
|
||||||
|
disposable += rxBus
|
||||||
|
.toObservable(EventOmnipodAcknowledgeAlertsChanged::class.java)
|
||||||
|
.observeOn(AndroidSchedulers.mainThread())
|
||||||
|
.subscribe({ updateAcknowledgeAlerts() }, { fabricPrivacy.logException(it) })
|
||||||
|
disposable += rxBus
|
||||||
|
.toObservable(EventPreferenceChange::class.java)
|
||||||
|
.observeOn(Schedulers.io())
|
||||||
|
.subscribe({ event ->
|
||||||
|
setVisibilityOfPodDebugButton()
|
||||||
|
}, { fabricPrivacy.logException(it) })
|
||||||
|
}
|
||||||
|
|
||||||
|
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.combo_warning),
|
||||||
|
resourceHelper.gs(R.string.omnipod_error_operation_not_possible_no_configuration), null)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onPause() {
|
||||||
|
super.onPause()
|
||||||
|
disposable.clear()
|
||||||
|
loopHandler.removeCallbacks(refreshLoop)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Synchronized
|
||||||
|
private fun setDeviceStatus() {
|
||||||
|
//val omnipodPumpStatus: OmnipodPumpStatus = OmnipodUtil.getPumpStatus()
|
||||||
|
// omnipodPumpStatus.rileyLinkServiceState = checkStatusSet(omnipodPumpStatus.rileyLinkServiceState,
|
||||||
|
// RileyLinkUtil.getServiceState()) as RileyLinkServiceState?
|
||||||
|
|
||||||
|
aapsLogger.info(LTag.PUMP, "setDeviceStatus: [pumpStatus={}]", omnipodPumpStatus)
|
||||||
|
|
||||||
|
val resourceId = omnipodPumpStatus.rileyLinkServiceState.getResourceId(RileyLinkTargetDevice.Omnipod)
|
||||||
|
val rileyLinkError = omnipodPumpPlugin.rileyLinkService?.error
|
||||||
|
|
||||||
|
omnipod_rl_status.text =
|
||||||
|
when {
|
||||||
|
omnipodPumpStatus.rileyLinkServiceState == RileyLinkServiceState.NotStarted -> resourceHelper.gs(resourceId)
|
||||||
|
omnipodPumpStatus.rileyLinkServiceState.isConnecting -> "{fa-bluetooth-b spin} " + resourceHelper.gs(resourceId)
|
||||||
|
omnipodPumpStatus.rileyLinkServiceState.isError && rileyLinkError == null -> "{fa-bluetooth-b} " + resourceHelper.gs(resourceId)
|
||||||
|
omnipodPumpStatus.rileyLinkServiceState.isError && rileyLinkError != null -> "{fa-bluetooth-b} " + resourceHelper.gs(rileyLinkError.getResourceId(RileyLinkTargetDevice.MedtronicPump))
|
||||||
|
else -> "{fa-bluetooth-b} " + resourceHelper.gs(resourceId)
|
||||||
|
}
|
||||||
|
omnipod_rl_status.setTextColor(if (rileyLinkError != null) Color.RED else Color.WHITE)
|
||||||
|
|
||||||
|
// omnipodPumpStatus.rileyLinkError = checkStatusSet(omnipodPumpStatus.rileyLinkError,
|
||||||
|
// RileyLinkUtil.getError()) as RileyLinkError?
|
||||||
|
|
||||||
|
omnipod_errors.text =
|
||||||
|
omnipodPumpStatus.rileyLinkError?.let {
|
||||||
|
resourceHelper.gs(it.getResourceId(RileyLinkTargetDevice.Omnipod))
|
||||||
|
} ?: "-"
|
||||||
|
|
||||||
|
val driverState = omnipodUtil.getDriverState();
|
||||||
|
|
||||||
|
aapsLogger.info(LTag.PUMP, "getDriverState: [driverState={}]", driverState)
|
||||||
|
|
||||||
|
if (driverState == OmnipodDriverState.NotInitalized) {
|
||||||
|
omnipod_pod_address.text = resourceHelper.gs(R.string.omnipod_pod_name_no_info)
|
||||||
|
omnipod_pod_expiry.text = "-"
|
||||||
|
omnipod_pod_status.text = resourceHelper.gs(R.string.omnipod_pod_not_initalized)
|
||||||
|
omnipodPumpStatus.podAvailable = false
|
||||||
|
omnipodPumpStatus.podNumber == null
|
||||||
|
} else if (driverState == OmnipodDriverState.Initalized_NoPod) {
|
||||||
|
omnipod_pod_address.text = resourceHelper.gs(R.string.omnipod_pod_name_no_info)
|
||||||
|
omnipod_pod_expiry.text = "-"
|
||||||
|
omnipod_pod_status.text = resourceHelper.gs(R.string.omnipod_pod_no_pod_connected)
|
||||||
|
omnipodPumpStatus.podAvailable = false
|
||||||
|
omnipodPumpStatus.podNumber == null
|
||||||
|
} else if (driverState == OmnipodDriverState.Initalized_PodInitializing) {
|
||||||
|
omnipod_pod_address.text = omnipodPumpStatus.podSessionState.address.toString()
|
||||||
|
omnipod_pod_expiry.text = "-"
|
||||||
|
omnipod_pod_status.text = omnipodPumpStatus.podSessionState.getSetupProgress().name
|
||||||
|
omnipodPumpStatus.podAvailable = false
|
||||||
|
omnipodPumpStatus.podNumber == omnipodPumpStatus.podSessionState.address.toString()
|
||||||
|
} else {
|
||||||
|
omnipodPumpStatus.podLotNumber = "" + omnipodPumpStatus.podSessionState.lot
|
||||||
|
omnipodPumpStatus.podAvailable = true
|
||||||
|
omnipod_pod_address.text = omnipodPumpStatus.podSessionState.address.toString()
|
||||||
|
omnipod_pod_expiry.text = omnipodPumpStatus.podSessionState.expiryDateAsString
|
||||||
|
omnipodPumpStatus.podNumber = omnipodPumpStatus.podSessionState.address.toString()
|
||||||
|
|
||||||
|
//pumpStatus.podSessionState = checkStatusSet(pumpStatus.podSessionState,
|
||||||
|
// OmnipodUtil.getPodSessionState()) as PodSessionState?
|
||||||
|
|
||||||
|
var podDeviceState = omnipodPumpStatus.podDeviceState
|
||||||
|
|
||||||
|
when (podDeviceState) {
|
||||||
|
null,
|
||||||
|
PodDeviceState.Sleeping -> omnipod_pod_status.text = "{fa-bed} " // + pumpStatus.pumpDeviceState.name());
|
||||||
|
PodDeviceState.NeverContacted,
|
||||||
|
PodDeviceState.WakingUp,
|
||||||
|
PodDeviceState.PumpUnreachable,
|
||||||
|
PodDeviceState.ErrorWhenCommunicating,
|
||||||
|
PodDeviceState.TimeoutWhenCommunicating,
|
||||||
|
PodDeviceState.InvalidConfiguration -> omnipod_pod_status.text = " " + resourceHelper.gs(podDeviceState.resourceId)
|
||||||
|
|
||||||
|
PodDeviceState.Active -> {
|
||||||
|
|
||||||
|
omnipod_pod_status.text = "Active";
|
||||||
|
// val cmd = OmnipodUtil.getCurrentCommand()
|
||||||
|
// if (cmd == null)
|
||||||
|
// omnipod_pod_status.text = " " + resourceHelper.gs(pumpStatus.pumpDeviceState.resourceId)
|
||||||
|
// else {
|
||||||
|
// aapsLogger.debug(LTag.PUMP,"Command: " + cmd)
|
||||||
|
// val cmdResourceId = cmd.resourceId
|
||||||
|
// if (cmd == MedtronicCommandType.GetHistoryData) {
|
||||||
|
// omnipod_pod_status.text = OmnipodUtil.frameNumber?.let {
|
||||||
|
// resourceHelper.gs(cmdResourceId, OmnipodUtil.pageNumber, OmnipodUtil.frameNumber)
|
||||||
|
// }
|
||||||
|
// ?: resourceHelper.gs(R.string.medtronic_cmd_desc_get_history_request, OmnipodUtil.pageNumber)
|
||||||
|
// } else {
|
||||||
|
// omnipod_pod_status.text = " " + (cmdResourceId?.let { resourceHelper.gs(it) }
|
||||||
|
// ?: cmd.getCommandDescription())
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
|
||||||
|
else -> aapsLogger.warn(LTag.PUMP, "Unknown pump state: " + omnipodPumpStatus.podDeviceState)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// pumpStatus.pumpDeviceState = checkStatusSet(pumpStatus.pumpDeviceState,
|
||||||
|
// OmnipodUtil.getPumpDeviceState()) as PumpDeviceState?
|
||||||
|
//
|
||||||
|
// when (pumpStatus.pumpDeviceState) {
|
||||||
|
// null,
|
||||||
|
// PumpDeviceState.Sleeping -> omnipod_pod_status.text = "{fa-bed} " // + pumpStatus.pumpDeviceState.name());
|
||||||
|
// PumpDeviceState.NeverContacted,
|
||||||
|
// PumpDeviceState.WakingUp,
|
||||||
|
// PumpDeviceState.PumpUnreachable,
|
||||||
|
// PumpDeviceState.ErrorWhenCommunicating,
|
||||||
|
// PumpDeviceState.TimeoutWhenCommunicating,
|
||||||
|
// PumpDeviceState.InvalidConfiguration -> omnipod_pod_status.text = " " + resourceHelper.gs(pumpStatus.pumpDeviceState.resourceId)
|
||||||
|
// PumpDeviceState.Active -> {
|
||||||
|
// val cmd = OmnipodUtil.getCurrentCommand()
|
||||||
|
// if (cmd == null)
|
||||||
|
// omnipod_pod_status.text = " " + resourceHelper.gs(pumpStatus.pumpDeviceState.resourceId)
|
||||||
|
// else {
|
||||||
|
// aapsLogger.debug(LTag.PUMP,"Command: " + cmd)
|
||||||
|
// val cmdResourceId = cmd.resourceId
|
||||||
|
// if (cmd == MedtronicCommandType.GetHistoryData) {
|
||||||
|
// omnipod_pod_status.text = OmnipodUtil.frameNumber?.let {
|
||||||
|
// resourceHelper.gs(cmdResourceId, OmnipodUtil.pageNumber, OmnipodUtil.frameNumber)
|
||||||
|
// }
|
||||||
|
// ?: resourceHelper.gs(R.string.medtronic_cmd_desc_get_history_request, OmnipodUtil.pageNumber)
|
||||||
|
// } else {
|
||||||
|
// omnipod_pod_status.text = " " + (cmdResourceId?.let { resourceHelper.gs(it) }
|
||||||
|
// ?: cmd.getCommandDescription())
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// else -> aapsLogger.warn(LTag.PUMP,"Unknown pump state: " + pumpStatus.pumpDeviceState)
|
||||||
|
// }
|
||||||
|
|
||||||
|
val status = commandQueue.spannedStatus()
|
||||||
|
if (status.toString() == "") {
|
||||||
|
omnipod_queue.visibility = View.GONE
|
||||||
|
} else {
|
||||||
|
omnipod_queue.visibility = View.VISIBLE
|
||||||
|
omnipod_queue.text = status
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun checkStatusSet(object1: Any?, object2: Any?): Any? {
|
||||||
|
return if (object1 == null) {
|
||||||
|
object2
|
||||||
|
} else {
|
||||||
|
if (object1 != object2) {
|
||||||
|
object2
|
||||||
|
} else
|
||||||
|
object1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// GUI functions
|
||||||
|
fun updateGUI() {
|
||||||
|
val plugin = omnipodPumpPlugin
|
||||||
|
//val omnipodPumpStatus = OmnipodUtil.getPumpStatus()
|
||||||
|
var pumpType = omnipodPumpStatus.pumpType
|
||||||
|
|
||||||
|
if (pumpType == null) {
|
||||||
|
aapsLogger.warn(LTag.PUMP, "PumpType was not set, reseting to Omnipod.")
|
||||||
|
pumpType = PumpType.Insulet_Omnipod;
|
||||||
|
}
|
||||||
|
|
||||||
|
setDeviceStatus()
|
||||||
|
|
||||||
|
if (omnipodPumpStatus.podAvailable) {
|
||||||
|
// last connection
|
||||||
|
if (omnipodPumpStatus.lastConnection != 0L) {
|
||||||
|
//val minAgo = DateUtil.minAgo(pumpStatus.lastConnection)
|
||||||
|
val min = (System.currentTimeMillis() - omnipodPumpStatus.lastConnection) / 1000 / 60
|
||||||
|
if (omnipodPumpStatus.lastConnection + 60 * 1000 > System.currentTimeMillis()) {
|
||||||
|
omnipod_lastconnection.setText(R.string.combo_pump_connected_now)
|
||||||
|
//omnipod_lastconnection.setTextColor(Color.WHITE)
|
||||||
|
} else { //if (pumpStatus.lastConnection + 30 * 60 * 1000 < System.currentTimeMillis()) {
|
||||||
|
|
||||||
|
if (min < 60) {
|
||||||
|
omnipod_lastconnection.text = resourceHelper.gs(R.string.minago, min)
|
||||||
|
} else if (min < 1440) {
|
||||||
|
val h = (min / 60).toInt()
|
||||||
|
omnipod_lastconnection.text = (resourceHelper.gq(R.plurals.objective_hours, h, h) + " "
|
||||||
|
+ resourceHelper.gs(R.string.ago))
|
||||||
|
} else {
|
||||||
|
val h = (min / 60).toInt()
|
||||||
|
val d = h / 24
|
||||||
|
// h = h - (d * 24);
|
||||||
|
omnipod_lastconnection.text = (resourceHelper.gq(R.plurals.objective_days, d, d) + " "
|
||||||
|
+ resourceHelper.gs(R.string.ago))
|
||||||
|
}
|
||||||
|
//omnipod_lastconnection.setTextColor(Color.RED)
|
||||||
|
}
|
||||||
|
// } else {
|
||||||
|
// omnipod_lastconnection.text = minAgo
|
||||||
|
// //omnipod_lastconnection.setTextColor(Color.WHITE)
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
|
||||||
|
// last bolus
|
||||||
|
val bolus = omnipodPumpStatus.lastBolusAmount
|
||||||
|
val bolusTime = omnipodPumpStatus.lastBolusTime
|
||||||
|
if (bolus != null && bolusTime != null && omnipodPumpStatus.podAvailable) {
|
||||||
|
val agoMsc = System.currentTimeMillis() - omnipodPumpStatus.lastBolusTime.time
|
||||||
|
val bolusMinAgo = agoMsc.toDouble() / 60.0 / 1000.0
|
||||||
|
val unit = resourceHelper.gs(R.string.insulin_unit_shortname)
|
||||||
|
val ago: String
|
||||||
|
if (agoMsc < 60 * 1000) {
|
||||||
|
ago = resourceHelper.gs(R.string.combo_pump_connected_now)
|
||||||
|
} else if (bolusMinAgo < 60) {
|
||||||
|
ago = DateUtil.minAgo(resourceHelper, omnipodPumpStatus.lastBolusTime.time)
|
||||||
|
} else {
|
||||||
|
ago = DateUtil.hourAgo(omnipodPumpStatus.lastBolusTime.time, resourceHelper)
|
||||||
|
}
|
||||||
|
omnipod_lastbolus.text = resourceHelper.gs(R.string.omnipod_last_bolus, pumpType.determineCorrectBolusSize(bolus), unit, ago)
|
||||||
|
} else {
|
||||||
|
omnipod_lastbolus.text = ""
|
||||||
|
}
|
||||||
|
|
||||||
|
// base basal rate
|
||||||
|
omnipod_basabasalrate.text = resourceHelper.gs(R.string.pump_basebasalrate, pumpType.determineCorrectBasalSize(plugin.baseBasalRate))
|
||||||
|
|
||||||
|
omnipod_tempbasal.text = activePlugin.activeTreatments
|
||||||
|
.getTempBasalFromHistory(System.currentTimeMillis())?.toStringFull() ?: ""
|
||||||
|
|
||||||
|
// reservoir
|
||||||
|
if (Round.isSame(omnipodPumpStatus.reservoirRemainingUnits, 75.0)) {
|
||||||
|
omnipod_reservoir.text = resourceHelper.gs(R.string.omnipod_reservoir_over50)
|
||||||
|
} else {
|
||||||
|
omnipod_reservoir.text = resourceHelper.gs(R.string.omnipod_reservoir_left, omnipodPumpStatus.reservoirRemainingUnits)
|
||||||
|
}
|
||||||
|
warnColors.setColorInverse(omnipod_reservoir, omnipodPumpStatus.reservoirRemainingUnits, 50.0, 20.0)
|
||||||
|
|
||||||
|
} else {
|
||||||
|
omnipod_basabasalrate.text = ""
|
||||||
|
omnipod_reservoir.text = ""
|
||||||
|
omnipod_tempbasal.text = ""
|
||||||
|
omnipod_lastbolus.text = ""
|
||||||
|
omnipod_lastconnection.text = ""
|
||||||
|
omnipod_lastconnection.setTextColor(Color.WHITE)
|
||||||
|
}
|
||||||
|
|
||||||
|
omnipod_errors.text = omnipodPumpStatus.errorInfo
|
||||||
|
|
||||||
|
updateAcknowledgeAlerts()
|
||||||
|
|
||||||
|
omnipod_refresh.isEnabled = omnipodPumpStatus.podAvailable
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun updateAcknowledgeAlerts() {
|
||||||
|
omnipod_pod_active_alerts_ack.isEnabled = omnipodPumpStatus.ackAlertsAvailable
|
||||||
|
omnipod_pod_active_alerts.text = omnipodPumpStatus.ackAlertsText
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
File diff suppressed because it is too large
Load diff
|
@ -0,0 +1,7 @@
|
||||||
|
package info.nightscout.androidaps.plugins.pump.omnipod.comm;
|
||||||
|
|
||||||
|
// TODO replace with Consumer when our min API level >= 24
|
||||||
|
@FunctionalInterface
|
||||||
|
public interface BolusProgressIndicationConsumer {
|
||||||
|
void accept(double estimatedUnitsDelivered, int percentage);
|
||||||
|
}
|
|
@ -0,0 +1,345 @@
|
||||||
|
package info.nightscout.androidaps.plugins.pump.omnipod.comm;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import javax.inject.Inject;
|
||||||
|
|
||||||
|
import dagger.android.HasAndroidInjector;
|
||||||
|
import info.nightscout.androidaps.logging.AAPSLogger;
|
||||||
|
import info.nightscout.androidaps.logging.LTag;
|
||||||
|
import info.nightscout.androidaps.plugins.pump.common.data.PumpStatus;
|
||||||
|
import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.RileyLinkCommunicationManager;
|
||||||
|
import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.RileyLinkConst;
|
||||||
|
import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.ble.RFSpy;
|
||||||
|
import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.ble.RileyLinkCommunicationException;
|
||||||
|
import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.ble.data.RLMessage;
|
||||||
|
import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.ble.defs.RLMessageType;
|
||||||
|
import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.ble.defs.RileyLinkBLEError;
|
||||||
|
import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.service.RileyLinkServiceData;
|
||||||
|
import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.service.tasks.ServiceTaskExecutor;
|
||||||
|
import info.nightscout.androidaps.plugins.pump.common.utils.ByteUtil;
|
||||||
|
import info.nightscout.androidaps.plugins.pump.medtronic.defs.PumpDeviceState;
|
||||||
|
import info.nightscout.androidaps.plugins.pump.omnipod.OmnipodPumpPlugin;
|
||||||
|
import info.nightscout.androidaps.plugins.pump.omnipod.comm.action.OmnipodAction;
|
||||||
|
import info.nightscout.androidaps.plugins.pump.omnipod.comm.exception.CommunicationException;
|
||||||
|
import info.nightscout.androidaps.plugins.pump.omnipod.comm.exception.IllegalPacketTypeException;
|
||||||
|
import info.nightscout.androidaps.plugins.pump.omnipod.comm.exception.IllegalResponseException;
|
||||||
|
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.MessageBlock;
|
||||||
|
import info.nightscout.androidaps.plugins.pump.omnipod.comm.message.OmnipodMessage;
|
||||||
|
import info.nightscout.androidaps.plugins.pump.omnipod.comm.message.OmnipodPacket;
|
||||||
|
import info.nightscout.androidaps.plugins.pump.omnipod.comm.message.command.DeactivatePodCommand;
|
||||||
|
import info.nightscout.androidaps.plugins.pump.omnipod.comm.message.response.ErrorResponse;
|
||||||
|
import info.nightscout.androidaps.plugins.pump.omnipod.comm.message.response.StatusResponse;
|
||||||
|
import info.nightscout.androidaps.plugins.pump.omnipod.comm.message.response.podinfo.PodInfoFaultEvent;
|
||||||
|
import info.nightscout.androidaps.plugins.pump.omnipod.comm.message.response.podinfo.PodInfoResponse;
|
||||||
|
import info.nightscout.androidaps.plugins.pump.omnipod.defs.ErrorResponseType;
|
||||||
|
import info.nightscout.androidaps.plugins.pump.omnipod.defs.MessageBlockType;
|
||||||
|
import info.nightscout.androidaps.plugins.pump.omnipod.defs.PacketType;
|
||||||
|
import info.nightscout.androidaps.plugins.pump.omnipod.defs.PodInfoType;
|
||||||
|
import info.nightscout.androidaps.plugins.pump.omnipod.defs.state.PodState;
|
||||||
|
import info.nightscout.androidaps.plugins.pump.omnipod.driver.OmnipodPumpStatus;
|
||||||
|
import info.nightscout.androidaps.plugins.pump.omnipod.exception.OmnipodException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by andy on 6/29/18.
|
||||||
|
*/
|
||||||
|
public class OmnipodCommunicationManager extends RileyLinkCommunicationManager {
|
||||||
|
|
||||||
|
@Inject public AAPSLogger aapsLogger;
|
||||||
|
@Inject OmnipodPumpStatus omnipodPumpStatus;
|
||||||
|
@Inject OmnipodPumpPlugin omnipodPumpPlugin;
|
||||||
|
@Inject RileyLinkServiceData rileyLinkServiceData;
|
||||||
|
@Inject ServiceTaskExecutor serviceTaskExecutor;
|
||||||
|
|
||||||
|
public OmnipodCommunicationManager(HasAndroidInjector injector, RFSpy rfspy) {
|
||||||
|
super(injector, rfspy);
|
||||||
|
omnipodPumpStatus.previousConnection = sp.getLong(
|
||||||
|
RileyLinkConst.Prefs.LastGoodDeviceCommunicationTime, 0L);
|
||||||
|
}
|
||||||
|
|
||||||
|
// @Override
|
||||||
|
// protected void configurePumpSpecificSettings() {
|
||||||
|
// }
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean tryToConnectToDevice() {
|
||||||
|
// TODO
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public byte[] createPumpMessageContent(RLMessageType type) {
|
||||||
|
return new byte[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override public PumpStatus getPumpStatus() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override public boolean isDeviceReachable() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean hasTunning() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public <E extends RLMessage> E createResponseMessage(byte[] payload, Class<E> clazz) {
|
||||||
|
return (E) new OmnipodPacket(payload);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setPumpDeviceState(PumpDeviceState pumpDeviceState) {
|
||||||
|
this.omnipodPumpStatus.setPumpDeviceState(pumpDeviceState);
|
||||||
|
}
|
||||||
|
|
||||||
|
public <T extends MessageBlock> T sendCommand(Class<T> responseClass, PodState podState, MessageBlock command) {
|
||||||
|
return sendCommand(responseClass, podState, command, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public <T extends MessageBlock> T sendCommand(Class<T> responseClass, PodState podState, MessageBlock command, boolean automaticallyResyncNone) {
|
||||||
|
OmnipodMessage message = new OmnipodMessage(podState.getAddress(), Collections.singletonList(command), podState.getMessageNumber());
|
||||||
|
return exchangeMessages(responseClass, podState, message, automaticallyResyncNone);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convenience method
|
||||||
|
public <T> T executeAction(OmnipodAction<T> action) {
|
||||||
|
return action.execute(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public <T extends MessageBlock> T exchangeMessages(Class<T> responseClass, PodState podState, OmnipodMessage message) {
|
||||||
|
return exchangeMessages(responseClass, podState, message, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public <T extends MessageBlock> T exchangeMessages(Class<T> responseClass, PodState podState, OmnipodMessage message, boolean automaticallyResyncNonce) {
|
||||||
|
return exchangeMessages(responseClass, podState, message, null, null, automaticallyResyncNonce);
|
||||||
|
}
|
||||||
|
|
||||||
|
public synchronized <T extends MessageBlock> T exchangeMessages(Class<T> responseClass, PodState podState, OmnipodMessage message, Integer addressOverride, Integer ackAddressOverride) {
|
||||||
|
return exchangeMessages(responseClass, podState, message, addressOverride, ackAddressOverride, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public synchronized <T extends MessageBlock> T exchangeMessages(Class<T> responseClass, PodState podState, OmnipodMessage message, Integer addressOverride, Integer ackAddressOverride, boolean automaticallyResyncNonce) {
|
||||||
|
|
||||||
|
aapsLogger.debug(LTag.PUMPCOMM, "Exchanging OmnipodMessage [responseClass={}, podState={}, message={}, addressOverride={}, ackAddressOverride={}, automaticallyResyncNonce={}]: {}", //
|
||||||
|
responseClass.getSimpleName(), podState, message, addressOverride, ackAddressOverride, automaticallyResyncNonce, message);
|
||||||
|
|
||||||
|
for (int i = 0; 2 > i; i++) {
|
||||||
|
|
||||||
|
if (podState.hasNonceState() && message.isNonceResyncable()) {
|
||||||
|
podState.advanceToNextNonce();
|
||||||
|
}
|
||||||
|
|
||||||
|
MessageBlock responseMessageBlock = transportMessages(podState, message, addressOverride, ackAddressOverride);
|
||||||
|
|
||||||
|
if (responseMessageBlock instanceof StatusResponse) {
|
||||||
|
podState.updateFromStatusResponse((StatusResponse) responseMessageBlock);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (responseClass.isInstance(responseMessageBlock)) {
|
||||||
|
return (T) responseMessageBlock;
|
||||||
|
} else {
|
||||||
|
if (responseMessageBlock.getType() == MessageBlockType.ERROR_RESPONSE) {
|
||||||
|
ErrorResponse error = (ErrorResponse) responseMessageBlock;
|
||||||
|
if (error.getErrorResponseType() == ErrorResponseType.BAD_NONCE) {
|
||||||
|
podState.resyncNonce(error.getNonceSearchKey(), message.getSentNonce(), message.getSequenceNumber());
|
||||||
|
if (automaticallyResyncNonce) {
|
||||||
|
message.resyncNonce(podState.getCurrentNonce());
|
||||||
|
} else {
|
||||||
|
throw new NonceOutOfSyncException();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
throw new PodReturnedErrorResponseException((ErrorResponse) responseMessageBlock);
|
||||||
|
}
|
||||||
|
} else if (responseMessageBlock.getType() == MessageBlockType.POD_INFO_RESPONSE && ((PodInfoResponse) responseMessageBlock).getSubType() == PodInfoType.FAULT_EVENT) {
|
||||||
|
PodInfoFaultEvent faultEvent = ((PodInfoResponse) responseMessageBlock).getPodInfo();
|
||||||
|
podState.setFaultEvent(faultEvent);
|
||||||
|
throw new PodFaultException(faultEvent);
|
||||||
|
} else {
|
||||||
|
throw new IllegalResponseException(responseClass.getSimpleName(), responseMessageBlock.getType());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new NonceResyncException();
|
||||||
|
}
|
||||||
|
|
||||||
|
private MessageBlock transportMessages(PodState podState, OmnipodMessage message, Integer addressOverride, Integer ackAddressOverride) {
|
||||||
|
int packetAddress = podState.getAddress();
|
||||||
|
if (addressOverride != null) {
|
||||||
|
packetAddress = addressOverride;
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean firstPacket = true;
|
||||||
|
byte[] encodedMessage;
|
||||||
|
// this does not work well with the deactivate pod command, we somehow either
|
||||||
|
// receive an ACK instead of a normal response, or a partial response and a communication timeout
|
||||||
|
if (message.isNonceResyncable() && !message.containsBlock(DeactivatePodCommand.class)) {
|
||||||
|
OmnipodMessage paddedMessage = new OmnipodMessage(message);
|
||||||
|
// If messages are nonce resyncable, we want do distinguish between certain and uncertain failures for verification purposes
|
||||||
|
// However, some commands (e.g. cancel delivery) are single packet command by nature. When we get a timeout with a single packet,
|
||||||
|
// we are unsure whether or not the command was received by the pod
|
||||||
|
// However, if we send > 1 packet, we know that the command wasn't received if we never send the subsequent packets,
|
||||||
|
// because the last packet contains the CRC.
|
||||||
|
// So we pad the message with get status commands to make it > packet
|
||||||
|
paddedMessage.padWithGetStatusCommands(PacketType.PDM.getMaxBodyLength()); // First packet is of type PDM
|
||||||
|
encodedMessage = paddedMessage.getEncoded();
|
||||||
|
} else {
|
||||||
|
encodedMessage = message.getEncoded();
|
||||||
|
}
|
||||||
|
|
||||||
|
OmnipodPacket response = null;
|
||||||
|
while (encodedMessage.length > 0) {
|
||||||
|
PacketType packetType = firstPacket ? PacketType.PDM : PacketType.CON;
|
||||||
|
OmnipodPacket packet = new OmnipodPacket(packetAddress, packetType, podState.getPacketNumber(), encodedMessage);
|
||||||
|
byte[] encodedMessageInPacket = packet.getEncodedMessage();
|
||||||
|
|
||||||
|
// getting the data remaining to be sent
|
||||||
|
encodedMessage = ByteUtil.substring(encodedMessage, encodedMessageInPacket.length, encodedMessage.length - encodedMessageInPacket.length);
|
||||||
|
firstPacket = false;
|
||||||
|
|
||||||
|
try {
|
||||||
|
// We actually ignore previous (ack) responses if it was not last packet to send
|
||||||
|
response = exchangePackets(podState, packet);
|
||||||
|
} catch (Exception ex) {
|
||||||
|
OmnipodException newException;
|
||||||
|
if (ex instanceof OmnipodException) {
|
||||||
|
newException = (OmnipodException) ex;
|
||||||
|
} else {
|
||||||
|
newException = new CommunicationException(CommunicationException.Type.UNEXPECTED_EXCEPTION, ex);
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean lastPacket = encodedMessage.length == 0;
|
||||||
|
|
||||||
|
// If this is not the last packet, the message wasn't fully sent,
|
||||||
|
// so it's impossible for the pod to have received the message
|
||||||
|
newException.setCertainFailure(!lastPacket);
|
||||||
|
|
||||||
|
aapsLogger.debug(LTag.PUMPCOMM, "Caught exception in transportMessages. Set certainFailure to {} because encodedMessage.length={}", newException.isCertainFailure(), encodedMessage.length);
|
||||||
|
|
||||||
|
throw newException;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (response.getPacketType() == PacketType.ACK) {
|
||||||
|
podState.increasePacketNumber(1);
|
||||||
|
throw new IllegalPacketTypeException(null, PacketType.ACK);
|
||||||
|
}
|
||||||
|
|
||||||
|
OmnipodMessage receivedMessage = null;
|
||||||
|
byte[] receivedMessageData = response.getEncodedMessage();
|
||||||
|
while (receivedMessage == null) {
|
||||||
|
try {
|
||||||
|
receivedMessage = OmnipodMessage.decodeMessage(receivedMessageData);
|
||||||
|
} catch (NotEnoughDataException ex) {
|
||||||
|
// Message is (probably) not complete yet
|
||||||
|
OmnipodPacket ackForCon = createAckPacket(podState, packetAddress, ackAddressOverride);
|
||||||
|
|
||||||
|
try {
|
||||||
|
OmnipodPacket conPacket = exchangePackets(podState, ackForCon, 3, 40);
|
||||||
|
if (conPacket.getPacketType() != PacketType.CON) {
|
||||||
|
throw new IllegalPacketTypeException(PacketType.CON, conPacket.getPacketType());
|
||||||
|
}
|
||||||
|
receivedMessageData = ByteUtil.concat(receivedMessageData, conPacket.getEncodedMessage());
|
||||||
|
} catch (OmnipodException ex2) {
|
||||||
|
throw ex2;
|
||||||
|
} catch (Exception ex2) {
|
||||||
|
throw new CommunicationException(CommunicationException.Type.UNEXPECTED_EXCEPTION, ex2);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
podState.increaseMessageNumber(2);
|
||||||
|
|
||||||
|
ackUntilQuiet(podState, packetAddress, ackAddressOverride);
|
||||||
|
|
||||||
|
List<MessageBlock> messageBlocks = receivedMessage.getMessageBlocks();
|
||||||
|
|
||||||
|
if (messageBlocks.size() == 0) {
|
||||||
|
throw new NotEnoughDataException(receivedMessageData);
|
||||||
|
} else if (messageBlocks.size() > 1) {
|
||||||
|
// BS: don't expect this to happen
|
||||||
|
aapsLogger.error(LTag.PUMPBTCOMM, "Received more than one message block: {}", messageBlocks.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
return messageBlocks.get(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
private OmnipodPacket createAckPacket(PodState podState, Integer packetAddress, Integer messageAddress) {
|
||||||
|
int pktAddress = podState.getAddress();
|
||||||
|
int msgAddress = podState.getAddress();
|
||||||
|
if (packetAddress != null) {
|
||||||
|
pktAddress = packetAddress;
|
||||||
|
}
|
||||||
|
if (messageAddress != null) {
|
||||||
|
msgAddress = messageAddress;
|
||||||
|
}
|
||||||
|
return new OmnipodPacket(pktAddress, PacketType.ACK, podState.getPacketNumber(), ByteUtil.getBytesFromInt(msgAddress));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ackUntilQuiet(PodState podState, Integer packetAddress, Integer messageAddress) {
|
||||||
|
OmnipodPacket ack = createAckPacket(podState, packetAddress, messageAddress);
|
||||||
|
boolean quiet = false;
|
||||||
|
while (!quiet) try {
|
||||||
|
sendAndListen(ack, 300, 1, 0, 40, OmnipodPacket.class);
|
||||||
|
} catch (RileyLinkCommunicationException ex) {
|
||||||
|
if (RileyLinkBLEError.Timeout.equals(ex.getErrorCode())) {
|
||||||
|
quiet = true;
|
||||||
|
} else {
|
||||||
|
aapsLogger.debug(LTag.PUMPBTCOMM, "Ignoring exception in ackUntilQuiet", ex);
|
||||||
|
}
|
||||||
|
} catch (OmnipodException ex) {
|
||||||
|
aapsLogger.debug(LTag.PUMPBTCOMM, "Ignoring exception in ackUntilQuiet", ex);
|
||||||
|
} catch (Exception ex) {
|
||||||
|
throw new CommunicationException(CommunicationException.Type.UNEXPECTED_EXCEPTION, ex);
|
||||||
|
}
|
||||||
|
|
||||||
|
podState.increasePacketNumber(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
private OmnipodPacket exchangePackets(PodState podState, OmnipodPacket packet) {
|
||||||
|
return exchangePackets(podState, packet, 0, 333, 9000, 127);
|
||||||
|
}
|
||||||
|
|
||||||
|
private OmnipodPacket exchangePackets(PodState podState, OmnipodPacket packet, int repeatCount, int preambleExtensionMilliseconds) {
|
||||||
|
return exchangePackets(podState, packet, repeatCount, 333, 9000, preambleExtensionMilliseconds);
|
||||||
|
}
|
||||||
|
|
||||||
|
private OmnipodPacket exchangePackets(PodState podState, OmnipodPacket packet, int repeatCount, int responseTimeoutMilliseconds, int exchangeTimeoutMilliseconds, int preambleExtensionMilliseconds) {
|
||||||
|
long timeoutTime = System.currentTimeMillis() + exchangeTimeoutMilliseconds;
|
||||||
|
|
||||||
|
while (System.currentTimeMillis() < timeoutTime) {
|
||||||
|
OmnipodPacket response = null;
|
||||||
|
try {
|
||||||
|
response = sendAndListen(packet, responseTimeoutMilliseconds, repeatCount, 9, preambleExtensionMilliseconds, OmnipodPacket.class);
|
||||||
|
} catch (RileyLinkCommunicationException | OmnipodException ex) {
|
||||||
|
aapsLogger.debug(LTag.PUMPBTCOMM, "Ignoring exception in exchangePackets", ex);
|
||||||
|
} catch (Exception ex) {
|
||||||
|
throw new CommunicationException(CommunicationException.Type.UNEXPECTED_EXCEPTION, ex);
|
||||||
|
}
|
||||||
|
if (response == null || !response.isValid()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (response.getAddress() != packet.getAddress()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (response.getSequenceNumber() != ((podState.getPacketNumber() + 1) & 0b11111)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
podState.increasePacketNumber(2);
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
throw new CommunicationException(CommunicationException.Type.TIMEOUT);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,664 @@
|
||||||
|
package info.nightscout.androidaps.plugins.pump.omnipod.comm;
|
||||||
|
|
||||||
|
import org.joda.time.DateTime;
|
||||||
|
import org.joda.time.DateTimeZone;
|
||||||
|
import org.joda.time.Duration;
|
||||||
|
|
||||||
|
import java.util.EnumSet;
|
||||||
|
import java.util.TimeZone;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
import info.nightscout.androidaps.logging.AAPSLogger;
|
||||||
|
import info.nightscout.androidaps.logging.LTag;
|
||||||
|
import info.nightscout.androidaps.plugins.pump.omnipod.comm.action.AcknowledgeAlertsAction;
|
||||||
|
import info.nightscout.androidaps.plugins.pump.omnipod.comm.action.AssignAddressAction;
|
||||||
|
import info.nightscout.androidaps.plugins.pump.omnipod.comm.action.BolusAction;
|
||||||
|
import info.nightscout.androidaps.plugins.pump.omnipod.comm.action.CancelDeliveryAction;
|
||||||
|
import info.nightscout.androidaps.plugins.pump.omnipod.comm.action.ConfigurePodAction;
|
||||||
|
import info.nightscout.androidaps.plugins.pump.omnipod.comm.action.DeactivatePodAction;
|
||||||
|
import info.nightscout.androidaps.plugins.pump.omnipod.comm.action.GetPodInfoAction;
|
||||||
|
import info.nightscout.androidaps.plugins.pump.omnipod.comm.action.GetStatusAction;
|
||||||
|
import info.nightscout.androidaps.plugins.pump.omnipod.comm.action.InsertCannulaAction;
|
||||||
|
import info.nightscout.androidaps.plugins.pump.omnipod.comm.action.PrimeAction;
|
||||||
|
import info.nightscout.androidaps.plugins.pump.omnipod.comm.action.SetBasalScheduleAction;
|
||||||
|
import info.nightscout.androidaps.plugins.pump.omnipod.comm.action.SetTempBasalAction;
|
||||||
|
import info.nightscout.androidaps.plugins.pump.omnipod.comm.action.service.InsertCannulaService;
|
||||||
|
import info.nightscout.androidaps.plugins.pump.omnipod.comm.action.service.PrimeService;
|
||||||
|
import info.nightscout.androidaps.plugins.pump.omnipod.comm.exception.CommunicationException;
|
||||||
|
import info.nightscout.androidaps.plugins.pump.omnipod.comm.exception.IllegalDeliveryStatusException;
|
||||||
|
import info.nightscout.androidaps.plugins.pump.omnipod.comm.exception.IllegalSetupProgressException;
|
||||||
|
import info.nightscout.androidaps.plugins.pump.omnipod.comm.exception.NonceOutOfSyncException;
|
||||||
|
import info.nightscout.androidaps.plugins.pump.omnipod.comm.exception.PodFaultException;
|
||||||
|
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.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.BeepType;
|
||||||
|
import info.nightscout.androidaps.plugins.pump.omnipod.defs.DeliveryStatus;
|
||||||
|
import info.nightscout.androidaps.plugins.pump.omnipod.defs.DeliveryType;
|
||||||
|
import info.nightscout.androidaps.plugins.pump.omnipod.defs.PodInfoType;
|
||||||
|
import info.nightscout.androidaps.plugins.pump.omnipod.defs.SetupProgress;
|
||||||
|
import info.nightscout.androidaps.plugins.pump.omnipod.defs.schedule.BasalSchedule;
|
||||||
|
import info.nightscout.androidaps.plugins.pump.omnipod.defs.state.PodSessionState;
|
||||||
|
import info.nightscout.androidaps.plugins.pump.omnipod.defs.state.PodStateChangedHandler;
|
||||||
|
import info.nightscout.androidaps.plugins.pump.omnipod.exception.OmnipodException;
|
||||||
|
import info.nightscout.androidaps.plugins.pump.omnipod.util.OmnipodConst;
|
||||||
|
import info.nightscout.androidaps.utils.sharedPreferences.SP;
|
||||||
|
import io.reactivex.Completable;
|
||||||
|
import io.reactivex.Flowable;
|
||||||
|
import io.reactivex.Single;
|
||||||
|
import io.reactivex.disposables.CompositeDisposable;
|
||||||
|
import io.reactivex.schedulers.Schedulers;
|
||||||
|
import io.reactivex.subjects.SingleSubject;
|
||||||
|
|
||||||
|
public class OmnipodManager {
|
||||||
|
private static final int ACTION_VERIFICATION_TRIES = 3;
|
||||||
|
|
||||||
|
protected final OmnipodCommunicationManager communicationService;
|
||||||
|
private final PodStateChangedHandler podStateChangedHandler;
|
||||||
|
protected PodSessionState podState;
|
||||||
|
|
||||||
|
private ActiveBolusData activeBolusData;
|
||||||
|
private final Object bolusDataMutex = new Object();
|
||||||
|
|
||||||
|
//private HasAndroidInjector injector;
|
||||||
|
AAPSLogger aapsLogger;
|
||||||
|
SP sp;
|
||||||
|
|
||||||
|
public OmnipodManager(//HasAndroidInjector injector,
|
||||||
|
AAPSLogger aapsLogger,
|
||||||
|
SP sp,
|
||||||
|
OmnipodCommunicationManager communicationService,
|
||||||
|
PodSessionState podState,
|
||||||
|
PodStateChangedHandler podStateChangedHandler) {
|
||||||
|
// this.injector = injector;
|
||||||
|
// this.injector.androidInjector().inject(this);
|
||||||
|
if (communicationService == null) {
|
||||||
|
throw new IllegalArgumentException("Communication service cannot be null");
|
||||||
|
}
|
||||||
|
this.aapsLogger = aapsLogger;
|
||||||
|
this.sp = sp;
|
||||||
|
this.communicationService = communicationService;
|
||||||
|
if (podState != null) {
|
||||||
|
podState.setStateChangedHandler(podStateChangedHandler);
|
||||||
|
}
|
||||||
|
this.podState = podState;
|
||||||
|
this.podStateChangedHandler = podStateChangedHandler;
|
||||||
|
}
|
||||||
|
|
||||||
|
// public OmnipodManager(HasAndroidInjector injector,
|
||||||
|
// OmnipodCommunicationManager communicationService,
|
||||||
|
// PodSessionState podState) {
|
||||||
|
// this(injector, communicationService, podState, null);
|
||||||
|
// }
|
||||||
|
|
||||||
|
public synchronized Single<SetupActionResult> pairAndPrime() {
|
||||||
|
logStartingCommandExecution("pairAndPrime");
|
||||||
|
|
||||||
|
try {
|
||||||
|
if (podState == null) {
|
||||||
|
podState = communicationService.executeAction(
|
||||||
|
new AssignAddressAction(podStateChangedHandler));
|
||||||
|
} else if (SetupProgress.PRIMING.isBefore(podState.getSetupProgress())) {
|
||||||
|
throw new IllegalSetupProgressException(SetupProgress.ADDRESS_ASSIGNED, podState.getSetupProgress());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (SetupProgress.ADDRESS_ASSIGNED.equals(podState.getSetupProgress())) {
|
||||||
|
communicationService.executeAction(new ConfigurePodAction(podState));
|
||||||
|
}
|
||||||
|
|
||||||
|
communicationService.executeAction(new PrimeAction(new PrimeService(), podState));
|
||||||
|
} finally {
|
||||||
|
logCommandExecutionFinished("pairAndPrime");
|
||||||
|
}
|
||||||
|
|
||||||
|
long delayInSeconds = calculateBolusDuration(OmnipodConst.POD_PRIME_BOLUS_UNITS, OmnipodConst.POD_PRIMING_DELIVERY_RATE).getStandardSeconds();
|
||||||
|
|
||||||
|
return Single.timer(delayInSeconds, TimeUnit.SECONDS) //
|
||||||
|
.map(o -> verifySetupAction(statusResponse ->
|
||||||
|
PrimeAction.updatePrimingStatus(podState, statusResponse, aapsLogger), SetupProgress.PRIMING_FINISHED)) //
|
||||||
|
.observeOn(Schedulers.io());
|
||||||
|
}
|
||||||
|
|
||||||
|
public synchronized Single<SetupActionResult> insertCannula(BasalSchedule basalSchedule) {
|
||||||
|
if (podState == null || podState.getSetupProgress().isBefore(SetupProgress.PRIMING_FINISHED)) {
|
||||||
|
throw new IllegalSetupProgressException(SetupProgress.PRIMING_FINISHED, podState == null ? null : podState.getSetupProgress());
|
||||||
|
} else if (podState.getSetupProgress().isAfter(SetupProgress.CANNULA_INSERTING)) {
|
||||||
|
throw new IllegalSetupProgressException(SetupProgress.CANNULA_INSERTING, podState.getSetupProgress());
|
||||||
|
}
|
||||||
|
|
||||||
|
logStartingCommandExecution("insertCannula [basalSchedule=" + basalSchedule + "]");
|
||||||
|
|
||||||
|
try {
|
||||||
|
communicationService.executeAction(new InsertCannulaAction(new InsertCannulaService(), podState, basalSchedule));
|
||||||
|
} finally {
|
||||||
|
logCommandExecutionFinished("insertCannula");
|
||||||
|
}
|
||||||
|
|
||||||
|
long delayInSeconds = calculateBolusDuration(OmnipodConst.POD_CANNULA_INSERTION_BOLUS_UNITS, OmnipodConst.POD_CANNULA_INSERTION_DELIVERY_RATE).getStandardSeconds();
|
||||||
|
|
||||||
|
return Single.timer(delayInSeconds, TimeUnit.SECONDS) //
|
||||||
|
.map(o -> verifySetupAction(statusResponse ->
|
||||||
|
InsertCannulaAction.updateCannulaInsertionStatus(podState, statusResponse, aapsLogger), SetupProgress.COMPLETED)) //
|
||||||
|
.observeOn(Schedulers.io());
|
||||||
|
}
|
||||||
|
|
||||||
|
public synchronized StatusResponse getPodStatus() {
|
||||||
|
if (podState == null) {
|
||||||
|
throw new IllegalSetupProgressException(SetupProgress.PRIMING_FINISHED, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
logStartingCommandExecution("getPodStatus");
|
||||||
|
|
||||||
|
try {
|
||||||
|
return communicationService.executeAction(new GetStatusAction(podState));
|
||||||
|
} finally {
|
||||||
|
logCommandExecutionFinished("getPodStatus");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public synchronized PodInfoResponse getPodInfo(PodInfoType podInfoType) {
|
||||||
|
assertReadyForDelivery();
|
||||||
|
|
||||||
|
logStartingCommandExecution("getPodInfo");
|
||||||
|
|
||||||
|
try {
|
||||||
|
return communicationService.executeAction(new GetPodInfoAction(podState, podInfoType));
|
||||||
|
} finally {
|
||||||
|
logCommandExecutionFinished("getPodInfo");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public synchronized StatusResponse acknowledgeAlerts() {
|
||||||
|
assertReadyForDelivery();
|
||||||
|
|
||||||
|
logStartingCommandExecution("acknowledgeAlerts");
|
||||||
|
|
||||||
|
try {
|
||||||
|
return executeAndVerify(() -> communicationService.executeAction(new AcknowledgeAlertsAction(podState, podState.getActiveAlerts())));
|
||||||
|
} finally {
|
||||||
|
logCommandExecutionFinished("acknowledgeAlerts");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// CAUTION: cancels all delivery
|
||||||
|
// CAUTION: suspends and then resumes delivery. An OmnipodException[certainFailure=false] indicates that the pod is or might be suspended
|
||||||
|
public synchronized StatusResponse setBasalSchedule(BasalSchedule schedule, boolean acknowledgementBeep) {
|
||||||
|
assertReadyForDelivery();
|
||||||
|
|
||||||
|
logStartingCommandExecution("setBasalSchedule [basalSchedule=" + schedule + ", acknowledgementBeep=" + acknowledgementBeep + "]");
|
||||||
|
|
||||||
|
try {
|
||||||
|
cancelDelivery(EnumSet.allOf(DeliveryType.class), acknowledgementBeep);
|
||||||
|
} catch (Exception ex) {
|
||||||
|
logCommandExecutionFinished("setBasalSchedule");
|
||||||
|
throw ex;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
try {
|
||||||
|
return executeAndVerify(() -> communicationService.executeAction(new SetBasalScheduleAction(podState, schedule,
|
||||||
|
false, podState.getScheduleOffset(), acknowledgementBeep)));
|
||||||
|
} catch (OmnipodException ex) {
|
||||||
|
// Treat all exceptions as uncertain failures, because all delivery has been suspended here.
|
||||||
|
// Setting this to an uncertain failure will enable for the user to get an appropriate warning
|
||||||
|
ex.setCertainFailure(false);
|
||||||
|
throw ex;
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
logCommandExecutionFinished("setBasalSchedule");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// CAUTION: cancels temp basal and then sets new temp basal. An OmnipodException[certainFailure=false] indicates that the pod might have cancelled the previous temp basal, but did not set a new temp basal
|
||||||
|
public synchronized StatusResponse setTemporaryBasal(double rate, Duration duration, boolean acknowledgementBeep, boolean completionBeep) {
|
||||||
|
assertReadyForDelivery();
|
||||||
|
|
||||||
|
logStartingCommandExecution("setTemporaryBasal [rate=" + rate + ", duration=" + duration + ", acknowledgementBeep=" + acknowledgementBeep + ", completionBeep=" + completionBeep + "]");
|
||||||
|
|
||||||
|
try {
|
||||||
|
cancelDelivery(EnumSet.of(DeliveryType.TEMP_BASAL), acknowledgementBeep);
|
||||||
|
} catch (Exception ex) {
|
||||||
|
logCommandExecutionFinished("setTemporaryBasal");
|
||||||
|
throw ex;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
return executeAndVerify(() -> communicationService.executeAction(new SetTempBasalAction(
|
||||||
|
podState, rate, duration,
|
||||||
|
acknowledgementBeep, completionBeep)));
|
||||||
|
} catch (OmnipodException ex) {
|
||||||
|
// Treat all exceptions as uncertain failures, because all delivery has been suspended here.
|
||||||
|
// Setting this to an uncertain failure will enable for the user to get an appropriate warning
|
||||||
|
ex.setCertainFailure(false);
|
||||||
|
throw ex;
|
||||||
|
} finally {
|
||||||
|
logCommandExecutionFinished("setTemporaryBasal");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public synchronized void cancelTemporaryBasal(boolean acknowledgementBeep) {
|
||||||
|
cancelDelivery(EnumSet.of(DeliveryType.TEMP_BASAL), acknowledgementBeep);
|
||||||
|
}
|
||||||
|
|
||||||
|
private synchronized StatusResponse cancelDelivery(EnumSet<DeliveryType> deliveryTypes, boolean acknowledgementBeep) {
|
||||||
|
assertReadyForDelivery();
|
||||||
|
|
||||||
|
logStartingCommandExecution("cancelDelivery [deliveryTypes=" + deliveryTypes + ", acknowledgementBeep=" + acknowledgementBeep + "]");
|
||||||
|
|
||||||
|
try {
|
||||||
|
return executeAndVerify(() -> {
|
||||||
|
StatusResponse statusResponse = communicationService.executeAction(new CancelDeliveryAction(podState, deliveryTypes, acknowledgementBeep));
|
||||||
|
aapsLogger.info(LTag.PUMPBTCOMM, "Status response after cancel delivery[types={}]: {}", deliveryTypes.toString(), statusResponse.toString());
|
||||||
|
return statusResponse;
|
||||||
|
});
|
||||||
|
} finally {
|
||||||
|
logCommandExecutionFinished("cancelDelivery");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns a SingleSubject that returns when the bolus has finished.
|
||||||
|
// When a bolus is cancelled, it will return after cancellation and report the estimated units delivered
|
||||||
|
// Only throws OmnipodException[certainFailure=false]
|
||||||
|
public synchronized BolusCommandResult bolus(Double units, boolean acknowledgementBeep, boolean completionBeep, BolusProgressIndicationConsumer progressIndicationConsumer) {
|
||||||
|
assertReadyForDelivery();
|
||||||
|
|
||||||
|
logStartingCommandExecution("bolus [units=" + units + ", acknowledgementBeep=" + acknowledgementBeep + ", completionBeep=" + completionBeep + "]");
|
||||||
|
|
||||||
|
CommandDeliveryStatus commandDeliveryStatus = CommandDeliveryStatus.SUCCESS;
|
||||||
|
|
||||||
|
try {
|
||||||
|
executeAndVerify(() -> communicationService.executeAction(new BolusAction(podState, units, acknowledgementBeep, completionBeep)));
|
||||||
|
} catch (OmnipodException ex) {
|
||||||
|
if (ex.isCertainFailure()) {
|
||||||
|
throw ex;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Catch uncertain exceptions as we still want to report bolus progress indication
|
||||||
|
aapsLogger.error(LTag.PUMPBTCOMM, "Caught exception[certainFailure=false] in bolus", ex);
|
||||||
|
commandDeliveryStatus = CommandDeliveryStatus.UNCERTAIN_FAILURE;
|
||||||
|
} finally {
|
||||||
|
logCommandExecutionFinished("bolus");
|
||||||
|
}
|
||||||
|
|
||||||
|
DateTime startDate = DateTime.now().minus(OmnipodConst.AVERAGE_BOLUS_COMMAND_COMMUNICATION_DURATION);
|
||||||
|
|
||||||
|
CompositeDisposable disposables = new CompositeDisposable();
|
||||||
|
Duration bolusDuration = calculateBolusDuration(units, OmnipodConst.POD_BOLUS_DELIVERY_RATE);
|
||||||
|
Duration estimatedRemainingBolusDuration = bolusDuration.minus(OmnipodConst.AVERAGE_BOLUS_COMMAND_COMMUNICATION_DURATION);
|
||||||
|
|
||||||
|
if (progressIndicationConsumer != null) {
|
||||||
|
int numberOfProgressReports = Math.max(20, Math.min(100, (int) Math.ceil(units) * 10));
|
||||||
|
long progressReportInterval = estimatedRemainingBolusDuration.getMillis() / numberOfProgressReports;
|
||||||
|
|
||||||
|
disposables.add(Flowable.intervalRange(0, numberOfProgressReports + 1, 0, progressReportInterval, TimeUnit.MILLISECONDS) //
|
||||||
|
.observeOn(Schedulers.io()) //
|
||||||
|
.subscribe(count -> {
|
||||||
|
int percentage = (int) ((double) count / numberOfProgressReports * 100);
|
||||||
|
double estimatedUnitsDelivered = activeBolusData == null ? 0 : activeBolusData.estimateUnitsDelivered();
|
||||||
|
progressIndicationConsumer.accept(estimatedUnitsDelivered, percentage);
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
SingleSubject<BolusDeliveryResult> bolusCompletionSubject = SingleSubject.create();
|
||||||
|
|
||||||
|
synchronized (bolusDataMutex) {
|
||||||
|
activeBolusData = new ActiveBolusData(units, startDate, bolusCompletionSubject, disposables);
|
||||||
|
}
|
||||||
|
|
||||||
|
disposables.add(Completable.complete() //
|
||||||
|
.delay(estimatedRemainingBolusDuration.getMillis() + 250, TimeUnit.MILLISECONDS) //
|
||||||
|
.observeOn(Schedulers.io()) //
|
||||||
|
.doOnComplete(() -> {
|
||||||
|
synchronized (bolusDataMutex) {
|
||||||
|
double unitsNotDelivered = 0.0d;
|
||||||
|
|
||||||
|
for (int i = 0; i < ACTION_VERIFICATION_TRIES; i++) {
|
||||||
|
try {
|
||||||
|
// Retrieve a status response in order to update the pod state
|
||||||
|
StatusResponse statusResponse = getPodStatus();
|
||||||
|
if (statusResponse.getDeliveryStatus().isBolusing()) {
|
||||||
|
throw new IllegalDeliveryStatusException(DeliveryStatus.NORMAL, statusResponse.getDeliveryStatus());
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} catch (PodFaultException ex) {
|
||||||
|
// Substract units not delivered in case of a Pod failure
|
||||||
|
unitsNotDelivered = ex.getFaultEvent().getInsulinNotDelivered();
|
||||||
|
|
||||||
|
aapsLogger.debug(LTag.PUMPBTCOMM, "Caught PodFaultException in bolus completion verification", ex);
|
||||||
|
break;
|
||||||
|
} catch (Exception ex) {
|
||||||
|
aapsLogger.debug(LTag.PUMPBTCOMM, "Ignoring exception in bolus completion verification", ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hasActiveBolus()) {
|
||||||
|
activeBolusData.bolusCompletionSubject.onSuccess(new BolusDeliveryResult(units - unitsNotDelivered));
|
||||||
|
activeBolusData = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.subscribe());
|
||||||
|
|
||||||
|
return new BolusCommandResult(commandDeliveryStatus, bolusCompletionSubject);
|
||||||
|
}
|
||||||
|
|
||||||
|
public synchronized void cancelBolus(boolean acknowledgementBeep) {
|
||||||
|
assertReadyForDelivery();
|
||||||
|
|
||||||
|
synchronized (bolusDataMutex) {
|
||||||
|
if (activeBolusData == null) {
|
||||||
|
throw new IllegalDeliveryStatusException(DeliveryStatus.BOLUS_IN_PROGRESS, podState.getLastDeliveryStatus());
|
||||||
|
}
|
||||||
|
|
||||||
|
logStartingCommandExecution("cancelBolus [acknowledgementBeep=" + acknowledgementBeep + "]");
|
||||||
|
|
||||||
|
try {
|
||||||
|
StatusResponse statusResponse = cancelDelivery(EnumSet.of(DeliveryType.BOLUS), acknowledgementBeep);
|
||||||
|
discardActiveBolusData(statusResponse.getInsulinNotDelivered());
|
||||||
|
} catch (PodFaultException ex) {
|
||||||
|
discardActiveBolusData(ex.getFaultEvent().getInsulinNotDelivered());
|
||||||
|
throw ex;
|
||||||
|
} finally {
|
||||||
|
logCommandExecutionFinished("cancelBolus");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void discardActiveBolusData(double unitsNotDelivered) {
|
||||||
|
synchronized (bolusDataMutex) {
|
||||||
|
activeBolusData.getDisposables().dispose();
|
||||||
|
activeBolusData.getBolusCompletionSubject().onSuccess(new BolusDeliveryResult(activeBolusData.getUnits() - unitsNotDelivered));
|
||||||
|
activeBolusData = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public synchronized void suspendDelivery(boolean acknowledgementBeep) {
|
||||||
|
cancelDelivery(EnumSet.allOf(DeliveryType.class), acknowledgementBeep);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Same as setting basal schedule, but without suspending delivery first
|
||||||
|
public synchronized StatusResponse resumeDelivery(boolean acknowledgementBeep) {
|
||||||
|
assertReadyForDelivery();
|
||||||
|
logStartingCommandExecution("resumeDelivery");
|
||||||
|
|
||||||
|
try {
|
||||||
|
return executeAndVerify(() -> communicationService.executeAction(new SetBasalScheduleAction(podState, podState.getBasalSchedule(),
|
||||||
|
false, podState.getScheduleOffset(), acknowledgementBeep)));
|
||||||
|
} finally {
|
||||||
|
logCommandExecutionFinished("resumeDelivery");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// CAUTION: cancels all delivery
|
||||||
|
// CAUTION: suspends and then resumes delivery. An OmnipodException[certainFailure=false] indicates that the pod is or might be suspended
|
||||||
|
public synchronized void setTime(boolean acknowledgementBeeps) {
|
||||||
|
assertReadyForDelivery();
|
||||||
|
|
||||||
|
logStartingCommandExecution("setTime [acknowledgementBeeps=" + acknowledgementBeeps + "]");
|
||||||
|
|
||||||
|
try {
|
||||||
|
cancelDelivery(EnumSet.allOf(DeliveryType.class), acknowledgementBeeps);
|
||||||
|
} catch (Exception ex) {
|
||||||
|
logCommandExecutionFinished("setTime");
|
||||||
|
throw ex;
|
||||||
|
}
|
||||||
|
|
||||||
|
DateTimeZone oldTimeZone = podState.getTimeZone();
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Joda seems to cache the default time zone, so we use the JVM's
|
||||||
|
DateTimeZone.setDefault(DateTimeZone.forTimeZone(TimeZone.getDefault()));
|
||||||
|
podState.setTimeZone(DateTimeZone.getDefault());
|
||||||
|
|
||||||
|
setBasalSchedule(podState.getBasalSchedule(), acknowledgementBeeps);
|
||||||
|
} catch (OmnipodException ex) {
|
||||||
|
// Treat all exceptions as uncertain failures, because all delivery has been suspended here.
|
||||||
|
// Setting this to an uncertain failure will enable for the user to get an appropriate warning
|
||||||
|
podState.setTimeZone(oldTimeZone);
|
||||||
|
ex.setCertainFailure(false);
|
||||||
|
throw ex;
|
||||||
|
} finally {
|
||||||
|
logCommandExecutionFinished("setTime");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public synchronized void deactivatePod() {
|
||||||
|
if (podState == null) {
|
||||||
|
throw new IllegalSetupProgressException(SetupProgress.ADDRESS_ASSIGNED, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
logStartingCommandExecution("deactivatePod");
|
||||||
|
|
||||||
|
// Try to get pulse log for diagnostics
|
||||||
|
// FIXME replace by storing to file
|
||||||
|
try {
|
||||||
|
PodInfoResponse podInfoResponse = communicationService.executeAction(new GetPodInfoAction(podState, PodInfoType.RECENT_PULSE_LOG));
|
||||||
|
PodInfoRecentPulseLog pulseLogInfo = podInfoResponse.getPodInfo();
|
||||||
|
aapsLogger.info(LTag.PUMPBTCOMM, "Retrieved pulse log from the pod: {}", pulseLogInfo.toString());
|
||||||
|
} catch (Exception ex) {
|
||||||
|
aapsLogger.warn(LTag.PUMPBTCOMM, "Failed to retrieve pulse log from the pod", ex);
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Always send acknowledgement beeps here. Matches the PDM's behavior
|
||||||
|
communicationService.executeAction(new DeactivatePodAction(podState, true));
|
||||||
|
} catch (PodFaultException ex) {
|
||||||
|
aapsLogger.info(LTag.PUMPBTCOMM, "Ignoring PodFaultException in deactivatePod", ex);
|
||||||
|
} finally {
|
||||||
|
logCommandExecutionFinished("deactivatePod");
|
||||||
|
}
|
||||||
|
|
||||||
|
resetPodState(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void resetPodState(boolean forcedByUser) {
|
||||||
|
aapsLogger.warn(LTag.PUMPBTCOMM, "resetPodState has been called. forcedByUser={}", forcedByUser);
|
||||||
|
podState = null;
|
||||||
|
sp.remove(OmnipodConst.Prefs.PodState);
|
||||||
|
}
|
||||||
|
|
||||||
|
public OmnipodCommunicationManager getCommunicationService() {
|
||||||
|
return communicationService;
|
||||||
|
}
|
||||||
|
|
||||||
|
public DateTime getTime() {
|
||||||
|
return podState.getTime();
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isReadyForDelivery() {
|
||||||
|
return podState != null && podState.getSetupProgress() == SetupProgress.COMPLETED;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean hasActiveBolus() {
|
||||||
|
synchronized (bolusDataMutex) {
|
||||||
|
return activeBolusData != null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// FIXME this is dirty, we should not expose the original pod state
|
||||||
|
public PodSessionState getPodState() {
|
||||||
|
return this.podState;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getPodStateAsString() {
|
||||||
|
return podState == null ? "null" : podState.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Only works for commands with nonce resyncable message blocks
|
||||||
|
// FIXME method is too big, needs refactoring
|
||||||
|
private StatusResponse executeAndVerify(VerifiableAction runnable) {
|
||||||
|
try {
|
||||||
|
return runnable.run();
|
||||||
|
} catch (Exception originalException) {
|
||||||
|
if (isCertainFailure(originalException)) {
|
||||||
|
throw originalException;
|
||||||
|
} else {
|
||||||
|
aapsLogger.warn(LTag.PUMPBTCOMM, "Caught exception in executeAndVerify. Verifying command by using cancel none command to verify nonce", originalException);
|
||||||
|
|
||||||
|
try {
|
||||||
|
logStartingCommandExecution("verifyCommand");
|
||||||
|
StatusResponse statusResponse = communicationService.sendCommand(StatusResponse.class, podState,
|
||||||
|
new CancelDeliveryCommand(podState.getCurrentNonce(), BeepType.NO_BEEP, DeliveryType.NONE), false);
|
||||||
|
aapsLogger.info(LTag.PUMPBTCOMM, "Command status resolved to SUCCESS. Status response after cancelDelivery[types=DeliveryType.NONE]: {}", statusResponse);
|
||||||
|
|
||||||
|
return statusResponse;
|
||||||
|
} catch (NonceOutOfSyncException verificationException) {
|
||||||
|
aapsLogger.error(LTag.PUMPBTCOMM, "Command resolved to FAILURE (CERTAIN_FAILURE)", verificationException);
|
||||||
|
|
||||||
|
if (originalException instanceof OmnipodException) {
|
||||||
|
((OmnipodException) originalException).setCertainFailure(true);
|
||||||
|
throw originalException;
|
||||||
|
} else {
|
||||||
|
OmnipodException newException = new CommunicationException(CommunicationException.Type.UNEXPECTED_EXCEPTION, originalException);
|
||||||
|
newException.setCertainFailure(true);
|
||||||
|
throw newException;
|
||||||
|
}
|
||||||
|
} catch (Exception verificationException) {
|
||||||
|
aapsLogger.error(LTag.PUMPBTCOMM, "Command unresolved (UNCERTAIN_FAILURE)", verificationException);
|
||||||
|
throw originalException;
|
||||||
|
} finally {
|
||||||
|
logCommandExecutionFinished("verifyCommand");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void assertReadyForDelivery() {
|
||||||
|
if (!isReadyForDelivery()) {
|
||||||
|
throw new IllegalSetupProgressException(SetupProgress.COMPLETED, podState == null ? null : podState.getSetupProgress());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private SetupActionResult verifySetupAction(StatusResponseConsumer setupActionResponseHandler, SetupProgress expectedSetupProgress) {
|
||||||
|
SetupActionResult result = null;
|
||||||
|
for (int i = 0; ACTION_VERIFICATION_TRIES > i; i++) {
|
||||||
|
try {
|
||||||
|
StatusResponse delayedStatusResponse = communicationService.executeAction(new GetStatusAction(podState));
|
||||||
|
setupActionResponseHandler.accept(delayedStatusResponse);
|
||||||
|
|
||||||
|
if (podState.getSetupProgress().equals(expectedSetupProgress)) {
|
||||||
|
result = new SetupActionResult(SetupActionResult.ResultType.SUCCESS);
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
result = new SetupActionResult(SetupActionResult.ResultType.FAILURE) //
|
||||||
|
.setupProgress(podState.getSetupProgress());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} catch (Exception ex) {
|
||||||
|
result = new SetupActionResult(SetupActionResult.ResultType.VERIFICATION_FAILURE) //
|
||||||
|
.exception(ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void logStartingCommandExecution(String action) {
|
||||||
|
aapsLogger.debug(LTag.PUMPBTCOMM, "Starting command execution for action: " + action);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void logCommandExecutionFinished(String action) {
|
||||||
|
aapsLogger.debug(LTag.PUMPBTCOMM, "Command execution finished for action: " + action);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Duration calculateBolusDuration(double units, double deliveryRate) {
|
||||||
|
return Duration.standardSeconds((long) Math.ceil(units / deliveryRate));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Duration calculateBolusDuration(double units) {
|
||||||
|
return calculateBolusDuration(units, OmnipodConst.POD_BOLUS_DELIVERY_RATE);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean isCertainFailure(Exception ex) {
|
||||||
|
return ex instanceof OmnipodException && ((OmnipodException) ex).isCertainFailure();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class BolusCommandResult {
|
||||||
|
private final CommandDeliveryStatus commandDeliveryStatus;
|
||||||
|
private final SingleSubject<BolusDeliveryResult> deliveryResultSubject;
|
||||||
|
|
||||||
|
public BolusCommandResult(CommandDeliveryStatus commandDeliveryStatus, SingleSubject<BolusDeliveryResult> deliveryResultSubject) {
|
||||||
|
this.commandDeliveryStatus = commandDeliveryStatus;
|
||||||
|
this.deliveryResultSubject = deliveryResultSubject;
|
||||||
|
}
|
||||||
|
|
||||||
|
public CommandDeliveryStatus getCommandDeliveryStatus() {
|
||||||
|
return commandDeliveryStatus;
|
||||||
|
}
|
||||||
|
|
||||||
|
public SingleSubject<BolusDeliveryResult> getDeliveryResultSubject() {
|
||||||
|
return deliveryResultSubject;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class BolusDeliveryResult {
|
||||||
|
private final double unitsDelivered;
|
||||||
|
|
||||||
|
public BolusDeliveryResult(double unitsDelivered) {
|
||||||
|
this.unitsDelivered = unitsDelivered;
|
||||||
|
}
|
||||||
|
|
||||||
|
public double getUnitsDelivered() {
|
||||||
|
return unitsDelivered;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum CommandDeliveryStatus {
|
||||||
|
SUCCESS,
|
||||||
|
CERTAIN_FAILURE,
|
||||||
|
UNCERTAIN_FAILURE
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO replace with Consumer when our min API level >= 24
|
||||||
|
@FunctionalInterface
|
||||||
|
private interface StatusResponseConsumer {
|
||||||
|
void accept(StatusResponse statusResponse);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class ActiveBolusData {
|
||||||
|
private final double units;
|
||||||
|
private volatile DateTime startDate;
|
||||||
|
private volatile SingleSubject<BolusDeliveryResult> bolusCompletionSubject;
|
||||||
|
private volatile CompositeDisposable disposables;
|
||||||
|
|
||||||
|
private ActiveBolusData(double units, DateTime startDate, SingleSubject<BolusDeliveryResult> bolusCompletionSubject, CompositeDisposable disposables) {
|
||||||
|
this.units = units;
|
||||||
|
this.startDate = startDate;
|
||||||
|
this.bolusCompletionSubject = bolusCompletionSubject;
|
||||||
|
this.disposables = disposables;
|
||||||
|
}
|
||||||
|
|
||||||
|
public double getUnits() {
|
||||||
|
return units;
|
||||||
|
}
|
||||||
|
|
||||||
|
public DateTime getStartDate() {
|
||||||
|
return startDate;
|
||||||
|
}
|
||||||
|
|
||||||
|
public CompositeDisposable getDisposables() {
|
||||||
|
return disposables;
|
||||||
|
}
|
||||||
|
|
||||||
|
public SingleSubject<BolusDeliveryResult> getBolusCompletionSubject() {
|
||||||
|
return bolusCompletionSubject;
|
||||||
|
}
|
||||||
|
|
||||||
|
public double estimateUnitsDelivered() {
|
||||||
|
long elapsedMillis = new Duration(startDate, DateTime.now()).getMillis();
|
||||||
|
long totalDurationMillis = (long) (units / OmnipodConst.POD_BOLUS_DELIVERY_RATE * 1000);
|
||||||
|
double factor = (double) elapsedMillis / totalDurationMillis;
|
||||||
|
double estimatedUnits = Math.min(1D, factor) * units;
|
||||||
|
|
||||||
|
int roundingDivisor = (int) (1 / OmnipodConst.POD_PULSE_SIZE);
|
||||||
|
return (double) Math.round(estimatedUnits * roundingDivisor) / roundingDivisor;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Could be replaced with Supplier<StatusResponse> when min API level >= 24
|
||||||
|
@FunctionalInterface
|
||||||
|
private interface VerifiableAction {
|
||||||
|
StatusResponse run();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,61 @@
|
||||||
|
package info.nightscout.androidaps.plugins.pump.omnipod.comm;
|
||||||
|
|
||||||
|
import info.nightscout.androidaps.plugins.pump.omnipod.defs.SetupProgress;
|
||||||
|
|
||||||
|
public class SetupActionResult {
|
||||||
|
private final ResultType resultType;
|
||||||
|
private String message;
|
||||||
|
private Exception exception;
|
||||||
|
private SetupProgress setupProgress;
|
||||||
|
|
||||||
|
public SetupActionResult(ResultType resultType) {
|
||||||
|
this.resultType = resultType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public SetupActionResult message(String message) {
|
||||||
|
this.message = message;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public SetupActionResult exception(Exception ex) {
|
||||||
|
exception = ex;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public SetupActionResult setupProgress(SetupProgress setupProgress) {
|
||||||
|
this.setupProgress = setupProgress;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ResultType getResultType() {
|
||||||
|
return resultType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getMessage() {
|
||||||
|
return message;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Exception getException() {
|
||||||
|
return exception;
|
||||||
|
}
|
||||||
|
|
||||||
|
public SetupProgress getSetupProgress() {
|
||||||
|
return setupProgress;
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum ResultType {
|
||||||
|
SUCCESS(true),
|
||||||
|
VERIFICATION_FAILURE(false),
|
||||||
|
FAILURE(false);
|
||||||
|
|
||||||
|
private final boolean success;
|
||||||
|
|
||||||
|
ResultType(boolean success) {
|
||||||
|
this.success = success;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isSuccess() {
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,39 @@
|
||||||
|
package info.nightscout.androidaps.plugins.pump.omnipod.comm.action;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
|
|
||||||
|
import info.nightscout.androidaps.plugins.pump.omnipod.comm.OmnipodCommunicationManager;
|
||||||
|
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.PodSessionState;
|
||||||
|
import info.nightscout.androidaps.plugins.pump.omnipod.comm.exception.ActionInitializationException;
|
||||||
|
|
||||||
|
public class AcknowledgeAlertsAction implements OmnipodAction<StatusResponse> {
|
||||||
|
private final PodSessionState podState;
|
||||||
|
private final AlertSet alerts;
|
||||||
|
|
||||||
|
public AcknowledgeAlertsAction(PodSessionState podState, AlertSet alerts) {
|
||||||
|
if (podState == null) {
|
||||||
|
throw new ActionInitializationException("Pod state cannot be null");
|
||||||
|
}
|
||||||
|
if (alerts == null) {
|
||||||
|
throw new ActionInitializationException("Alert set can not be null");
|
||||||
|
} else if (alerts.size() == 0) {
|
||||||
|
throw new ActionInitializationException("Alert set can not be empty");
|
||||||
|
}
|
||||||
|
this.podState = podState;
|
||||||
|
this.alerts = alerts;
|
||||||
|
}
|
||||||
|
|
||||||
|
public AcknowledgeAlertsAction(PodSessionState podState, AlertSlot alertSlot) {
|
||||||
|
this(podState, new AlertSet(Collections.singletonList(alertSlot)));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public StatusResponse execute(OmnipodCommunicationManager communicationService) {
|
||||||
|
return communicationService.sendCommand(StatusResponse.class, podState,
|
||||||
|
new AcknowledgeAlertsCommand(podState.getCurrentNonce(), alerts));
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,50 @@
|
||||||
|
package info.nightscout.androidaps.plugins.pump.omnipod.comm.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.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.state.PodSessionState;
|
||||||
|
import info.nightscout.androidaps.plugins.pump.omnipod.defs.state.PodSetupState;
|
||||||
|
import info.nightscout.androidaps.plugins.pump.omnipod.defs.state.PodStateChangedHandler;
|
||||||
|
import info.nightscout.androidaps.plugins.pump.omnipod.util.OmnipodConst;
|
||||||
|
|
||||||
|
public class AssignAddressAction implements OmnipodAction<PodSessionState> {
|
||||||
|
private final int address;
|
||||||
|
private final PodStateChangedHandler podStateChangedHandler;
|
||||||
|
|
||||||
|
public AssignAddressAction(PodStateChangedHandler podStateChangedHandler) {
|
||||||
|
this.address = generateRandomAddress();
|
||||||
|
this.podStateChangedHandler = podStateChangedHandler;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int generateRandomAddress() {
|
||||||
|
return 0x1f000000 | (new Random().nextInt() & 0x000fffff);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public PodSessionState execute(OmnipodCommunicationManager communicationService) {
|
||||||
|
PodSetupState setupState = new PodSetupState(address, 0x00, 0x00);
|
||||||
|
|
||||||
|
AssignAddressCommand assignAddress = new AssignAddressCommand(setupState.getAddress());
|
||||||
|
OmnipodMessage assignAddressMessage = new OmnipodMessage(OmnipodConst.DEFAULT_ADDRESS,
|
||||||
|
Collections.singletonList(assignAddress), setupState.getMessageNumber());
|
||||||
|
|
||||||
|
VersionResponse assignAddressResponse = communicationService.exchangeMessages(VersionResponse.class, setupState, assignAddressMessage,
|
||||||
|
OmnipodConst.DEFAULT_ADDRESS, setupState.getAddress());
|
||||||
|
|
||||||
|
DateTimeZone timeZone = DateTimeZone.getDefault();
|
||||||
|
|
||||||
|
PodSessionState podState = new PodSessionState(timeZone, address, assignAddressResponse.getPiVersion(),
|
||||||
|
assignAddressResponse.getPmVersion(), assignAddressResponse.getLot(), assignAddressResponse.getTid(),
|
||||||
|
setupState.getPacketNumber(), 0x00, communicationService.injector); // At this point, for an unknown reason, the pod starts counting messages from 0 again
|
||||||
|
|
||||||
|
podState.setStateChangedHandler(podStateChangedHandler);
|
||||||
|
return podState;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,53 @@
|
||||||
|
package info.nightscout.androidaps.plugins.pump.omnipod.comm.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.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.PodSessionState;
|
||||||
|
import info.nightscout.androidaps.plugins.pump.omnipod.comm.exception.ActionInitializationException;
|
||||||
|
|
||||||
|
public class BolusAction implements OmnipodAction<StatusResponse> {
|
||||||
|
private final PodSessionState podState;
|
||||||
|
private final double units;
|
||||||
|
private final Duration timeBetweenPulses;
|
||||||
|
private final boolean acknowledgementBeep;
|
||||||
|
private final boolean completionBeep;
|
||||||
|
|
||||||
|
public BolusAction(PodSessionState podState, double units, Duration timeBetweenPulses,
|
||||||
|
boolean acknowledgementBeep, boolean completionBeep) {
|
||||||
|
if (podState == null) {
|
||||||
|
throw new ActionInitializationException("Pod state cannot be null");
|
||||||
|
}
|
||||||
|
if (timeBetweenPulses == null) {
|
||||||
|
throw new ActionInitializationException("Time between pulses cannot be null");
|
||||||
|
}
|
||||||
|
this.podState = podState;
|
||||||
|
this.units = units;
|
||||||
|
this.timeBetweenPulses = timeBetweenPulses;
|
||||||
|
this.acknowledgementBeep = acknowledgementBeep;
|
||||||
|
this.completionBeep = completionBeep;
|
||||||
|
}
|
||||||
|
|
||||||
|
public BolusAction(PodSessionState podState, double units, boolean acknowledgementBeep, boolean completionBeep) {
|
||||||
|
this(podState, units, Duration.standardSeconds(2), acknowledgementBeep, completionBeep);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public StatusResponse execute(OmnipodCommunicationManager communicationService) {
|
||||||
|
BolusDeliverySchedule bolusDeliverySchedule = new BolusDeliverySchedule(units, timeBetweenPulses);
|
||||||
|
SetInsulinScheduleCommand setInsulinScheduleCommand = new SetInsulinScheduleCommand(
|
||||||
|
podState.getCurrentNonce(), bolusDeliverySchedule);
|
||||||
|
BolusExtraCommand bolusExtraCommand = new BolusExtraCommand(units, timeBetweenPulses,
|
||||||
|
acknowledgementBeep, completionBeep);
|
||||||
|
OmnipodMessage primeBolusMessage = new OmnipodMessage(podState.getAddress(),
|
||||||
|
Arrays.asList(setInsulinScheduleCommand, bolusExtraCommand), podState.getMessageNumber());
|
||||||
|
return communicationService.exchangeMessages(StatusResponse.class, podState, primeBolusMessage);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,56 @@
|
||||||
|
package info.nightscout.androidaps.plugins.pump.omnipod.comm.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.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.PodSessionState;
|
||||||
|
import info.nightscout.androidaps.plugins.pump.omnipod.comm.exception.ActionInitializationException;
|
||||||
|
|
||||||
|
public class CancelDeliveryAction implements OmnipodAction<StatusResponse> {
|
||||||
|
private final PodSessionState podState;
|
||||||
|
private final EnumSet<DeliveryType> deliveryTypes;
|
||||||
|
private final boolean acknowledgementBeep;
|
||||||
|
|
||||||
|
public CancelDeliveryAction(PodSessionState podState, EnumSet<DeliveryType> deliveryTypes,
|
||||||
|
boolean acknowledgementBeep) {
|
||||||
|
if (podState == null) {
|
||||||
|
throw new ActionInitializationException("Pod state cannot be null");
|
||||||
|
}
|
||||||
|
if (deliveryTypes == null) {
|
||||||
|
throw new ActionInitializationException("Delivery types cannot be null");
|
||||||
|
}
|
||||||
|
this.podState = podState;
|
||||||
|
this.deliveryTypes = deliveryTypes;
|
||||||
|
this.acknowledgementBeep = acknowledgementBeep;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public StatusResponse execute(OmnipodCommunicationManager communicationService) {
|
||||||
|
List<MessageBlock> messageBlocks = new ArrayList<>();
|
||||||
|
|
||||||
|
if (acknowledgementBeep && deliveryTypes.size() > 1) {
|
||||||
|
// Workaround for strange beep behaviour when cancelling multiple delivery types
|
||||||
|
List<DeliveryType> deliveryTypeList = new ArrayList<>(deliveryTypes);
|
||||||
|
|
||||||
|
EnumSet<DeliveryType> deliveryTypeWithBeep = EnumSet.of(deliveryTypeList.remove(deliveryTypeList.size() - 1));
|
||||||
|
EnumSet<DeliveryType> deliveryTypesWithoutBeep = EnumSet.copyOf(deliveryTypeList);
|
||||||
|
|
||||||
|
messageBlocks.add(new CancelDeliveryCommand(podState.getCurrentNonce(), BeepType.NO_BEEP, deliveryTypesWithoutBeep));
|
||||||
|
messageBlocks.add(new CancelDeliveryCommand(podState.getCurrentNonce(), BeepType.BEEP, deliveryTypeWithBeep));
|
||||||
|
} else {
|
||||||
|
messageBlocks.add(new CancelDeliveryCommand(podState.getCurrentNonce(),
|
||||||
|
acknowledgementBeep && deliveryTypes.size() == 1 ? BeepType.BEEP : BeepType.NO_BEEP, deliveryTypes));
|
||||||
|
}
|
||||||
|
|
||||||
|
return communicationService.exchangeMessages(StatusResponse.class, podState,
|
||||||
|
new OmnipodMessage(podState.getAddress(), messageBlocks, podState.getMessageNumber()));
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,36 @@
|
||||||
|
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.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.PodSessionState;
|
||||||
|
import info.nightscout.androidaps.plugins.pump.omnipod.comm.exception.ActionInitializationException;
|
||||||
|
|
||||||
|
public class ConfigureAlertsAction implements OmnipodAction<StatusResponse> {
|
||||||
|
private final PodSessionState podState;
|
||||||
|
private final List<AlertConfiguration> alertConfigurations;
|
||||||
|
|
||||||
|
public ConfigureAlertsAction(PodSessionState podState, List<AlertConfiguration> alertConfigurations) {
|
||||||
|
if (podState == null) {
|
||||||
|
throw new ActionInitializationException("Pod state cannot be null");
|
||||||
|
}
|
||||||
|
if (alertConfigurations == null) {
|
||||||
|
throw new ActionInitializationException("Alert configurations cannot be null");
|
||||||
|
}
|
||||||
|
this.podState = podState;
|
||||||
|
this.alertConfigurations = alertConfigurations;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public StatusResponse execute(OmnipodCommunicationManager communicationService) {
|
||||||
|
ConfigureAlertsCommand configureAlertsCommand = new ConfigureAlertsCommand(podState.getCurrentNonce(), alertConfigurations);
|
||||||
|
StatusResponse statusResponse = communicationService.sendCommand(StatusResponse.class, podState, configureAlertsCommand);
|
||||||
|
for (AlertConfiguration alertConfiguration : alertConfigurations) {
|
||||||
|
podState.putConfiguredAlert(alertConfiguration.getAlertSlot(), alertConfiguration.getAlertType());
|
||||||
|
}
|
||||||
|
return statusResponse;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,59 @@
|
||||||
|
package info.nightscout.androidaps.plugins.pump.omnipod.comm.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.message.OmnipodMessage;
|
||||||
|
import info.nightscout.androidaps.plugins.pump.omnipod.comm.message.command.ConfigurePodCommand;
|
||||||
|
import info.nightscout.androidaps.plugins.pump.omnipod.comm.message.response.VersionResponse;
|
||||||
|
import info.nightscout.androidaps.plugins.pump.omnipod.defs.PacketType;
|
||||||
|
import info.nightscout.androidaps.plugins.pump.omnipod.defs.PodProgressStatus;
|
||||||
|
import info.nightscout.androidaps.plugins.pump.omnipod.defs.SetupProgress;
|
||||||
|
import info.nightscout.androidaps.plugins.pump.omnipod.defs.state.PodSessionState;
|
||||||
|
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.IllegalSetupProgressException;
|
||||||
|
import info.nightscout.androidaps.plugins.pump.omnipod.util.OmnipodConst;
|
||||||
|
|
||||||
|
public class ConfigurePodAction implements OmnipodAction<VersionResponse> {
|
||||||
|
private final PodSessionState podState;
|
||||||
|
|
||||||
|
public ConfigurePodAction(PodSessionState podState) {
|
||||||
|
this.podState = podState;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public VersionResponse execute(OmnipodCommunicationManager communicationService) {
|
||||||
|
if (!podState.getSetupProgress().equals(SetupProgress.ADDRESS_ASSIGNED)) {
|
||||||
|
throw new IllegalSetupProgressException(SetupProgress.ADDRESS_ASSIGNED, podState.getSetupProgress());
|
||||||
|
}
|
||||||
|
DateTime activationDate = DateTime.now(podState.getTimeZone());
|
||||||
|
|
||||||
|
ConfigurePodCommand configurePodCommand = new ConfigurePodCommand(podState.getAddress(), activationDate,
|
||||||
|
podState.getLot(), podState.getTid());
|
||||||
|
OmnipodMessage message = new OmnipodMessage(OmnipodConst.DEFAULT_ADDRESS,
|
||||||
|
Collections.singletonList(configurePodCommand), podState.getMessageNumber());
|
||||||
|
VersionResponse configurePodResponse;
|
||||||
|
try {
|
||||||
|
configurePodResponse = communicationService.exchangeMessages(VersionResponse.class, podState,
|
||||||
|
message, OmnipodConst.DEFAULT_ADDRESS, podState.getAddress());
|
||||||
|
} catch (IllegalPacketTypeException ex) {
|
||||||
|
if (PacketType.ACK.equals(ex.getActual())) {
|
||||||
|
// Pod is already configured
|
||||||
|
podState.setSetupProgress(SetupProgress.POD_CONFIGURED);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
throw ex;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (configurePodResponse.getPodProgressStatus() != PodProgressStatus.PAIRING_SUCCESS) {
|
||||||
|
throw new IllegalPodProgressException(PodProgressStatus.PAIRING_SUCCESS, configurePodResponse.getPodProgressStatus());
|
||||||
|
}
|
||||||
|
|
||||||
|
podState.setSetupProgress(SetupProgress.POD_CONFIGURED);
|
||||||
|
|
||||||
|
return configurePodResponse;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,38 @@
|
||||||
|
package info.nightscout.androidaps.plugins.pump.omnipod.comm.action;
|
||||||
|
|
||||||
|
import java.util.EnumSet;
|
||||||
|
|
||||||
|
import info.nightscout.androidaps.plugins.pump.omnipod.comm.OmnipodCommunicationManager;
|
||||||
|
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.PodSessionState;
|
||||||
|
import info.nightscout.androidaps.plugins.pump.omnipod.comm.exception.ActionInitializationException;
|
||||||
|
import info.nightscout.androidaps.plugins.pump.omnipod.comm.exception.PodFaultException;
|
||||||
|
|
||||||
|
public class DeactivatePodAction implements OmnipodAction<StatusResponse> {
|
||||||
|
private final PodSessionState podState;
|
||||||
|
private final boolean acknowledgementBeep;
|
||||||
|
|
||||||
|
public DeactivatePodAction(PodSessionState podState, boolean acknowledgementBeep) {
|
||||||
|
if (podState == null) {
|
||||||
|
throw new ActionInitializationException("Pod state cannot be null");
|
||||||
|
}
|
||||||
|
this.podState = podState;
|
||||||
|
this.acknowledgementBeep = acknowledgementBeep;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public StatusResponse execute(OmnipodCommunicationManager communicationService) {
|
||||||
|
if (!podState.isSuspended() && !podState.hasFaultEvent()) {
|
||||||
|
try {
|
||||||
|
communicationService.executeAction(new CancelDeliveryAction(podState,
|
||||||
|
EnumSet.allOf(DeliveryType.class), acknowledgementBeep));
|
||||||
|
} catch(PodFaultException ex) {
|
||||||
|
// Ignore
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return communicationService.sendCommand(StatusResponse.class, podState, new DeactivatePodCommand(podState.getCurrentNonce()));
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,29 @@
|
||||||
|
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.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.PodSessionState;
|
||||||
|
import info.nightscout.androidaps.plugins.pump.omnipod.comm.exception.ActionInitializationException;
|
||||||
|
|
||||||
|
public class GetPodInfoAction implements OmnipodAction<PodInfoResponse> {
|
||||||
|
private final PodSessionState podState;
|
||||||
|
private final PodInfoType podInfoType;
|
||||||
|
|
||||||
|
public GetPodInfoAction(PodSessionState podState, PodInfoType podInfoType) {
|
||||||
|
if (podState == null) {
|
||||||
|
throw new ActionInitializationException("Pod state cannot be null");
|
||||||
|
}
|
||||||
|
if (podInfoType == null) {
|
||||||
|
throw new ActionInitializationException("Pod info type cannot be null");
|
||||||
|
}
|
||||||
|
this.podState = podState;
|
||||||
|
this.podInfoType = podInfoType;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public PodInfoResponse execute(OmnipodCommunicationManager communicationService) {
|
||||||
|
return communicationService.sendCommand(PodInfoResponse.class, podState, new GetStatusCommand(podInfoType));
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,24 @@
|
||||||
|
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.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.PodSessionState;
|
||||||
|
import info.nightscout.androidaps.plugins.pump.omnipod.comm.exception.ActionInitializationException;
|
||||||
|
|
||||||
|
public class GetStatusAction implements OmnipodAction<StatusResponse> {
|
||||||
|
private final PodSessionState podState;
|
||||||
|
|
||||||
|
public GetStatusAction(PodSessionState podState) {
|
||||||
|
if (podState == null) {
|
||||||
|
throw new ActionInitializationException("Pod state cannot be null");
|
||||||
|
}
|
||||||
|
this.podState = podState;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public StatusResponse execute(OmnipodCommunicationManager communicationService) {
|
||||||
|
return communicationService.sendCommand(StatusResponse.class, podState, new GetStatusCommand(PodInfoType.NORMAL));
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,71 @@
|
||||||
|
package info.nightscout.androidaps.plugins.pump.omnipod.comm.action;
|
||||||
|
|
||||||
|
import info.nightscout.androidaps.logging.AAPSLogger;
|
||||||
|
import info.nightscout.androidaps.logging.LTag;
|
||||||
|
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.IllegalSetupProgressException;
|
||||||
|
import info.nightscout.androidaps.plugins.pump.omnipod.comm.message.response.StatusResponse;
|
||||||
|
import info.nightscout.androidaps.plugins.pump.omnipod.defs.SetupProgress;
|
||||||
|
import info.nightscout.androidaps.plugins.pump.omnipod.defs.schedule.BasalSchedule;
|
||||||
|
import info.nightscout.androidaps.plugins.pump.omnipod.defs.state.PodSessionState;
|
||||||
|
|
||||||
|
public class InsertCannulaAction implements OmnipodAction<StatusResponse> {
|
||||||
|
|
||||||
|
private final PodSessionState podState;
|
||||||
|
private final InsertCannulaService service;
|
||||||
|
private final BasalSchedule initialBasalSchedule;
|
||||||
|
|
||||||
|
public InsertCannulaAction(InsertCannulaService insertCannulaService, PodSessionState podState, BasalSchedule initialBasalSchedule) {
|
||||||
|
if (insertCannulaService == null) {
|
||||||
|
throw new ActionInitializationException("Insert cannula service cannot be null");
|
||||||
|
}
|
||||||
|
if (podState == null) {
|
||||||
|
throw new ActionInitializationException("Pod state cannot be null");
|
||||||
|
}
|
||||||
|
if (initialBasalSchedule == null) {
|
||||||
|
throw new ActionInitializationException("Initial basal schedule cannot be null");
|
||||||
|
}
|
||||||
|
this.service = insertCannulaService;
|
||||||
|
this.podState = podState;
|
||||||
|
this.initialBasalSchedule = initialBasalSchedule;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void updateCannulaInsertionStatus(PodSessionState podState, StatusResponse statusResponse, AAPSLogger aapsLogger) {
|
||||||
|
if (podState.getSetupProgress().equals(SetupProgress.CANNULA_INSERTING) &&
|
||||||
|
statusResponse.getPodProgressStatus().isReadyForDelivery()) {
|
||||||
|
aapsLogger.debug(LTag.PUMPBTCOMM, "Updating SetupProgress from CANNULA_INSERTING to COMPLETED");
|
||||||
|
podState.setSetupProgress(SetupProgress.COMPLETED);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public StatusResponse execute(OmnipodCommunicationManager communicationService) {
|
||||||
|
if (podState.getSetupProgress().isBefore(SetupProgress.PRIMING_FINISHED)) {
|
||||||
|
throw new IllegalSetupProgressException(SetupProgress.PRIMING_FINISHED, podState.getSetupProgress());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (podState.getSetupProgress().isBefore(SetupProgress.INITIAL_BASAL_SCHEDULE_SET)) {
|
||||||
|
service.programInitialBasalSchedule(communicationService, podState, initialBasalSchedule);
|
||||||
|
podState.setSetupProgress(SetupProgress.INITIAL_BASAL_SCHEDULE_SET);
|
||||||
|
}
|
||||||
|
if (podState.getSetupProgress().isBefore(SetupProgress.STARTING_INSERT_CANNULA)) {
|
||||||
|
service.executeExpirationRemindersAlertCommand(communicationService, podState);
|
||||||
|
podState.setSetupProgress(SetupProgress.STARTING_INSERT_CANNULA);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (podState.getSetupProgress().isBefore(SetupProgress.CANNULA_INSERTING)) {
|
||||||
|
StatusResponse statusResponse = service.executeInsertionBolusCommand(communicationService, podState);
|
||||||
|
podState.setSetupProgress(SetupProgress.CANNULA_INSERTING);
|
||||||
|
return statusResponse;
|
||||||
|
} else if (podState.getSetupProgress().equals(SetupProgress.CANNULA_INSERTING)) {
|
||||||
|
// Check status
|
||||||
|
StatusResponse statusResponse = communicationService.executeAction(new GetStatusAction(podState));
|
||||||
|
updateCannulaInsertionStatus(podState, statusResponse, communicationService.aapsLogger);
|
||||||
|
return statusResponse;
|
||||||
|
} else {
|
||||||
|
throw new IllegalSetupProgressException(null, podState.getSetupProgress());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,7 @@
|
||||||
|
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);
|
||||||
|
}
|
|
@ -0,0 +1,61 @@
|
||||||
|
package info.nightscout.androidaps.plugins.pump.omnipod.comm.action;
|
||||||
|
|
||||||
|
import info.nightscout.androidaps.logging.AAPSLogger;
|
||||||
|
import info.nightscout.androidaps.logging.LTag;
|
||||||
|
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.IllegalSetupProgressException;
|
||||||
|
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.SetupProgress;
|
||||||
|
import info.nightscout.androidaps.plugins.pump.omnipod.defs.state.PodSessionState;
|
||||||
|
|
||||||
|
public class PrimeAction implements OmnipodAction<StatusResponse> {
|
||||||
|
|
||||||
|
private final PrimeService service;
|
||||||
|
private final PodSessionState podState;
|
||||||
|
|
||||||
|
public PrimeAction(PrimeService primeService, PodSessionState podState) {
|
||||||
|
if (primeService == null) {
|
||||||
|
throw new ActionInitializationException("Prime service cannot be null");
|
||||||
|
}
|
||||||
|
if (podState == null) {
|
||||||
|
throw new ActionInitializationException("Pod state cannot be null");
|
||||||
|
}
|
||||||
|
this.service = primeService;
|
||||||
|
this.podState = podState;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void updatePrimingStatus(PodSessionState podState, StatusResponse statusResponse, AAPSLogger aapsLogger) {
|
||||||
|
if (podState.getSetupProgress().equals(SetupProgress.PRIMING) && statusResponse.getPodProgressStatus().equals(PodProgressStatus.READY_FOR_BASAL_SCHEDULE)) {
|
||||||
|
aapsLogger.debug(LTag.PUMPBTCOMM, "Updating SetupProgress from PRIMING to PRIMING_FINISHED");
|
||||||
|
podState.setSetupProgress(SetupProgress.PRIMING_FINISHED);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public StatusResponse execute(OmnipodCommunicationManager communicationService) {
|
||||||
|
if (podState.getSetupProgress().isBefore(SetupProgress.POD_CONFIGURED)) {
|
||||||
|
throw new IllegalSetupProgressException(SetupProgress.POD_CONFIGURED, podState.getSetupProgress());
|
||||||
|
}
|
||||||
|
if (podState.getSetupProgress().isBefore(SetupProgress.STARTING_PRIME)) {
|
||||||
|
service.executeDisableTab5Sub16FaultConfigCommand(communicationService, podState);
|
||||||
|
service.executeFinishSetupReminderAlertCommand(communicationService, podState);
|
||||||
|
podState.setSetupProgress(SetupProgress.STARTING_PRIME);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (podState.getSetupProgress().isBefore(SetupProgress.PRIMING)) {
|
||||||
|
StatusResponse statusResponse = service.executePrimeBolusCommand(communicationService, podState);
|
||||||
|
podState.setSetupProgress(SetupProgress.PRIMING);
|
||||||
|
return statusResponse;
|
||||||
|
} else if (podState.getSetupProgress().equals(SetupProgress.PRIMING)) {
|
||||||
|
// Check status
|
||||||
|
StatusResponse statusResponse = communicationService.executeAction(new GetStatusAction(podState));
|
||||||
|
updatePrimingStatus(podState, statusResponse, communicationService.aapsLogger);
|
||||||
|
return statusResponse;
|
||||||
|
} else {
|
||||||
|
throw new IllegalSetupProgressException(null, podState.getSetupProgress());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,53 @@
|
||||||
|
package info.nightscout.androidaps.plugins.pump.omnipod.comm.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.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.PodSessionState;
|
||||||
|
import info.nightscout.androidaps.plugins.pump.omnipod.comm.exception.ActionInitializationException;
|
||||||
|
|
||||||
|
public class SetBasalScheduleAction implements OmnipodAction<StatusResponse> {
|
||||||
|
private final PodSessionState podState;
|
||||||
|
private final BasalSchedule basalSchedule;
|
||||||
|
private final boolean confidenceReminder;
|
||||||
|
private final Duration scheduleOffset;
|
||||||
|
private final boolean acknowledgementBeep;
|
||||||
|
|
||||||
|
public SetBasalScheduleAction(PodSessionState podState, BasalSchedule basalSchedule,
|
||||||
|
boolean confidenceReminder, Duration scheduleOffset, boolean acknowledgementBeep) {
|
||||||
|
if (podState == null) {
|
||||||
|
throw new ActionInitializationException("Pod state cannot be null");
|
||||||
|
}
|
||||||
|
if (basalSchedule == null) {
|
||||||
|
throw new ActionInitializationException("Basal schedule cannot be null");
|
||||||
|
}
|
||||||
|
if (scheduleOffset == null) {
|
||||||
|
throw new ActionInitializationException("Schedule offset cannot be null");
|
||||||
|
}
|
||||||
|
this.podState = podState;
|
||||||
|
this.basalSchedule = basalSchedule;
|
||||||
|
this.confidenceReminder = confidenceReminder;
|
||||||
|
this.scheduleOffset = scheduleOffset;
|
||||||
|
this.acknowledgementBeep = acknowledgementBeep;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public StatusResponse execute(OmnipodCommunicationManager communicationService) {
|
||||||
|
SetInsulinScheduleCommand setBasal = new SetInsulinScheduleCommand(podState.getCurrentNonce(), basalSchedule, scheduleOffset);
|
||||||
|
BasalScheduleExtraCommand extraCommand = new BasalScheduleExtraCommand(basalSchedule, scheduleOffset,
|
||||||
|
acknowledgementBeep, confidenceReminder, Duration.ZERO);
|
||||||
|
OmnipodMessage basalMessage = new OmnipodMessage(podState.getAddress(), Arrays.asList(setBasal, extraCommand),
|
||||||
|
podState.getMessageNumber());
|
||||||
|
|
||||||
|
StatusResponse statusResponse = communicationService.exchangeMessages(StatusResponse.class, podState, basalMessage);
|
||||||
|
podState.setBasalSchedule(basalSchedule);
|
||||||
|
return statusResponse;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,48 @@
|
||||||
|
package info.nightscout.androidaps.plugins.pump.omnipod.comm.action;
|
||||||
|
|
||||||
|
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.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.PodSessionState;
|
||||||
|
import info.nightscout.androidaps.plugins.pump.omnipod.comm.exception.ActionInitializationException;
|
||||||
|
|
||||||
|
public class SetTempBasalAction implements OmnipodAction<StatusResponse> {
|
||||||
|
private final PodSessionState podState;
|
||||||
|
private final double rate;
|
||||||
|
private final Duration duration;
|
||||||
|
private final boolean acknowledgementBeep;
|
||||||
|
private final boolean completionBeep;
|
||||||
|
|
||||||
|
public SetTempBasalAction(PodSessionState podState, double rate, Duration duration,
|
||||||
|
boolean acknowledgementBeep, boolean completionBeep) {
|
||||||
|
if (podState == null) {
|
||||||
|
throw new ActionInitializationException("Pod state cannot be null");
|
||||||
|
}
|
||||||
|
if (duration == null) {
|
||||||
|
throw new ActionInitializationException("Duration cannot be null");
|
||||||
|
}
|
||||||
|
this.podState = podState;
|
||||||
|
this.rate = rate;
|
||||||
|
this.duration = duration;
|
||||||
|
this.acknowledgementBeep = acknowledgementBeep;
|
||||||
|
this.completionBeep = completionBeep;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public StatusResponse execute(OmnipodCommunicationManager communicationService) {
|
||||||
|
List<MessageBlock> messageBlocks = Arrays.asList( //
|
||||||
|
new SetInsulinScheduleCommand(podState.getCurrentNonce(), rate, duration),
|
||||||
|
new TempBasalExtraCommand(rate, duration, acknowledgementBeep, completionBeep, Duration.ZERO));
|
||||||
|
|
||||||
|
OmnipodMessage message = new OmnipodMessage(podState.getAddress(), messageBlocks, podState.getMessageNumber());
|
||||||
|
return communicationService.exchangeMessages(StatusResponse.class, podState, message);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,59 @@
|
||||||
|
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.PodSessionState;
|
||||||
|
import info.nightscout.androidaps.plugins.pump.omnipod.util.OmnipodConst;
|
||||||
|
|
||||||
|
public class InsertCannulaService {
|
||||||
|
public StatusResponse programInitialBasalSchedule(OmnipodCommunicationManager communicationService,
|
||||||
|
PodSessionState podState, BasalSchedule basalSchedule) {
|
||||||
|
return communicationService.executeAction(new SetBasalScheduleAction(podState, basalSchedule,
|
||||||
|
true, podState.getScheduleOffset(), false));
|
||||||
|
}
|
||||||
|
|
||||||
|
public StatusResponse executeExpirationRemindersAlertCommand(OmnipodCommunicationManager communicationService,
|
||||||
|
PodSessionState podState) {
|
||||||
|
AlertConfiguration lowReservoirAlertConfiguration = AlertConfigurationFactory.createLowReservoirAlertConfiguration(OmnipodConst.LOW_RESERVOIR_ALERT);
|
||||||
|
|
||||||
|
DateTime endOfServiceTime = podState.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 new ConfigureAlertsAction(podState, alertConfigurations).execute(communicationService);
|
||||||
|
}
|
||||||
|
|
||||||
|
public StatusResponse executeInsertionBolusCommand(OmnipodCommunicationManager communicationService, PodSessionState podState) {
|
||||||
|
return communicationService.executeAction(new BolusAction(podState, OmnipodConst.POD_CANNULA_INSERTION_BOLUS_UNITS,
|
||||||
|
Duration.standardSeconds(1), false, false));
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,37 @@
|
||||||
|
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.PodSessionState;
|
||||||
|
import info.nightscout.androidaps.plugins.pump.omnipod.util.OmnipodConst;
|
||||||
|
|
||||||
|
public class PrimeService {
|
||||||
|
|
||||||
|
public StatusResponse executeDisableTab5Sub16FaultConfigCommand(OmnipodCommunicationManager communicationService, PodSessionState podState) {
|
||||||
|
FaultConfigCommand faultConfigCommand = new FaultConfigCommand(podState.getCurrentNonce(), (byte) 0x00, (byte) 0x00);
|
||||||
|
OmnipodMessage faultConfigMessage = new OmnipodMessage(podState.getAddress(),
|
||||||
|
Collections.singletonList(faultConfigCommand), podState.getMessageNumber());
|
||||||
|
return communicationService.exchangeMessages(StatusResponse.class, podState, faultConfigMessage);
|
||||||
|
}
|
||||||
|
|
||||||
|
public StatusResponse executeFinishSetupReminderAlertCommand(OmnipodCommunicationManager communicationService, PodSessionState podState) {
|
||||||
|
AlertConfiguration finishSetupReminderAlertConfiguration = AlertConfigurationFactory.createFinishSetupReminderAlertConfiguration();
|
||||||
|
return communicationService.executeAction(new ConfigureAlertsAction(podState,
|
||||||
|
Collections.singletonList(finishSetupReminderAlertConfiguration)));
|
||||||
|
}
|
||||||
|
|
||||||
|
public StatusResponse executePrimeBolusCommand(OmnipodCommunicationManager communicationService, PodSessionState podState) {
|
||||||
|
return communicationService.executeAction(new BolusAction(podState, OmnipodConst.POD_PRIME_BOLUS_UNITS,
|
||||||
|
Duration.standardSeconds(1), false, false));
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,9 @@
|
||||||
|
package info.nightscout.androidaps.plugins.pump.omnipod.comm.exception;
|
||||||
|
|
||||||
|
import info.nightscout.androidaps.plugins.pump.omnipod.exception.OmnipodException;
|
||||||
|
|
||||||
|
public class ActionInitializationException extends OmnipodException {
|
||||||
|
public ActionInitializationException(String message) {
|
||||||
|
super(message, true);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,13 @@
|
||||||
|
package info.nightscout.androidaps.plugins.pump.omnipod.comm.exception;
|
||||||
|
|
||||||
|
import info.nightscout.androidaps.plugins.pump.omnipod.exception.OmnipodException;
|
||||||
|
|
||||||
|
public class CommandInitializationException extends OmnipodException {
|
||||||
|
public CommandInitializationException(String message) {
|
||||||
|
super(message, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public CommandInitializationException(String message, Throwable cause) {
|
||||||
|
super(message, cause, true);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,36 @@
|
||||||
|
package info.nightscout.androidaps.plugins.pump.omnipod.comm.exception;
|
||||||
|
|
||||||
|
import info.nightscout.androidaps.plugins.pump.omnipod.exception.OmnipodException;
|
||||||
|
|
||||||
|
public class CommunicationException extends OmnipodException {
|
||||||
|
private final Type type;
|
||||||
|
|
||||||
|
public CommunicationException(Type type) {
|
||||||
|
super(type.getDescription(), false);
|
||||||
|
this.type = type;
|
||||||
|
}
|
||||||
|
|
||||||
|
public CommunicationException(Type type, Throwable cause) {
|
||||||
|
super(type.getDescription() + ": "+ cause, cause, false);
|
||||||
|
this.type = type;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Type getType() {
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum Type {
|
||||||
|
TIMEOUT("Communication timeout"),
|
||||||
|
UNEXPECTED_EXCEPTION("Caught an unexpected Exception");
|
||||||
|
|
||||||
|
private final String description;
|
||||||
|
|
||||||
|
Type(String description) {
|
||||||
|
this.description = description;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getDescription() {
|
||||||
|
return description;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,24 @@
|
||||||
|
package info.nightscout.androidaps.plugins.pump.omnipod.comm.exception;
|
||||||
|
|
||||||
|
import java.util.Locale;
|
||||||
|
|
||||||
|
import info.nightscout.androidaps.plugins.pump.omnipod.exception.OmnipodException;
|
||||||
|
|
||||||
|
public class CrcMismatchException extends OmnipodException {
|
||||||
|
private final int expected;
|
||||||
|
private final int actual;
|
||||||
|
|
||||||
|
public CrcMismatchException(int expected, int actual) {
|
||||||
|
super(String.format(Locale.getDefault(), "CRC mismatch: expected %d, got %d", expected, actual), false);
|
||||||
|
this.expected = expected;
|
||||||
|
this.actual = actual;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getExpected() {
|
||||||
|
return expected;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getActual() {
|
||||||
|
return actual;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,26 @@
|
||||||
|
package info.nightscout.androidaps.plugins.pump.omnipod.comm.exception;
|
||||||
|
|
||||||
|
import java.util.Locale;
|
||||||
|
|
||||||
|
import info.nightscout.androidaps.plugins.pump.omnipod.defs.DeliveryStatus;
|
||||||
|
import info.nightscout.androidaps.plugins.pump.omnipod.defs.PodProgressStatus;
|
||||||
|
import info.nightscout.androidaps.plugins.pump.omnipod.exception.OmnipodException;
|
||||||
|
|
||||||
|
public class IllegalDeliveryStatusException extends OmnipodException {
|
||||||
|
private final DeliveryStatus expected;
|
||||||
|
private final DeliveryStatus actual;
|
||||||
|
|
||||||
|
public IllegalDeliveryStatusException(DeliveryStatus expected, DeliveryStatus actual) {
|
||||||
|
super(String.format(Locale.getDefault(), "Illegal delivery status: %s, expected: %s", actual, expected), true);
|
||||||
|
this.expected = expected;
|
||||||
|
this.actual = actual;
|
||||||
|
}
|
||||||
|
|
||||||
|
public DeliveryStatus getExpected() {
|
||||||
|
return expected;
|
||||||
|
}
|
||||||
|
|
||||||
|
public DeliveryStatus getActual() {
|
||||||
|
return actual;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,27 @@
|
||||||
|
package info.nightscout.androidaps.plugins.pump.omnipod.comm.exception;
|
||||||
|
|
||||||
|
import java.util.Locale;
|
||||||
|
|
||||||
|
import info.nightscout.androidaps.plugins.pump.omnipod.defs.PacketType;
|
||||||
|
import info.nightscout.androidaps.plugins.pump.omnipod.exception.OmnipodException;
|
||||||
|
|
||||||
|
public class IllegalPacketTypeException extends OmnipodException {
|
||||||
|
private final PacketType expected;
|
||||||
|
private final PacketType actual;
|
||||||
|
|
||||||
|
public IllegalPacketTypeException(PacketType expected, PacketType actual) {
|
||||||
|
super(String.format(Locale.getDefault(), "Illegal packet type: %s, expected %s",
|
||||||
|
actual, expected), false);
|
||||||
|
this.expected = expected;
|
||||||
|
this.actual = actual;
|
||||||
|
}
|
||||||
|
|
||||||
|
public PacketType getExpected() {
|
||||||
|
return expected;
|
||||||
|
}
|
||||||
|
|
||||||
|
public PacketType getActual() {
|
||||||
|
return actual;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,25 @@
|
||||||
|
package info.nightscout.androidaps.plugins.pump.omnipod.comm.exception;
|
||||||
|
|
||||||
|
import java.util.Locale;
|
||||||
|
|
||||||
|
import info.nightscout.androidaps.plugins.pump.omnipod.defs.PodProgressStatus;
|
||||||
|
import info.nightscout.androidaps.plugins.pump.omnipod.exception.OmnipodException;
|
||||||
|
|
||||||
|
public class IllegalPodProgressException extends OmnipodException {
|
||||||
|
private final PodProgressStatus expected;
|
||||||
|
private final PodProgressStatus actual;
|
||||||
|
|
||||||
|
public IllegalPodProgressException(PodProgressStatus expected, PodProgressStatus actual) {
|
||||||
|
super(String.format(Locale.getDefault(), "Illegal setup state: %s, expected: %s", actual, expected), true);
|
||||||
|
this.expected = expected;
|
||||||
|
this.actual = actual;
|
||||||
|
}
|
||||||
|
|
||||||
|
public PodProgressStatus getExpected() {
|
||||||
|
return expected;
|
||||||
|
}
|
||||||
|
|
||||||
|
public PodProgressStatus getActual() {
|
||||||
|
return actual;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,26 @@
|
||||||
|
package info.nightscout.androidaps.plugins.pump.omnipod.comm.exception;
|
||||||
|
|
||||||
|
import java.util.Locale;
|
||||||
|
|
||||||
|
import info.nightscout.androidaps.plugins.pump.omnipod.defs.MessageBlockType;
|
||||||
|
import info.nightscout.androidaps.plugins.pump.omnipod.exception.OmnipodException;
|
||||||
|
|
||||||
|
public class IllegalResponseException extends OmnipodException {
|
||||||
|
private final String actualClass;
|
||||||
|
private final MessageBlockType expectedType;
|
||||||
|
|
||||||
|
public IllegalResponseException(String actualClass, MessageBlockType expectedType) {
|
||||||
|
super(String.format(Locale.getDefault(), "Illegal response type: got class of type %s " +
|
||||||
|
"for message block type %s", actualClass, expectedType), false);
|
||||||
|
this.actualClass = actualClass;
|
||||||
|
this.expectedType = expectedType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getActualClass() {
|
||||||
|
return actualClass;
|
||||||
|
}
|
||||||
|
|
||||||
|
public MessageBlockType getExpectedType() {
|
||||||
|
return expectedType;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,26 @@
|
||||||
|
package info.nightscout.androidaps.plugins.pump.omnipod.comm.exception;
|
||||||
|
|
||||||
|
import java.util.Locale;
|
||||||
|
|
||||||
|
import info.nightscout.androidaps.plugins.pump.omnipod.defs.SetupProgress;
|
||||||
|
import info.nightscout.androidaps.plugins.pump.omnipod.exception.OmnipodException;
|
||||||
|
|
||||||
|
public class IllegalSetupProgressException extends OmnipodException {
|
||||||
|
private final SetupProgress expected;
|
||||||
|
private final SetupProgress actual;
|
||||||
|
|
||||||
|
public IllegalSetupProgressException(SetupProgress expected, SetupProgress actual) {
|
||||||
|
super(String.format(Locale.getDefault(), "Illegal setup progress: %s, expected: %s", actual, expected), true);
|
||||||
|
this.expected = expected;
|
||||||
|
this.actual = actual;
|
||||||
|
}
|
||||||
|
|
||||||
|
public SetupProgress getExpected() {
|
||||||
|
return expected;
|
||||||
|
}
|
||||||
|
|
||||||
|
public SetupProgress getActual() {
|
||||||
|
return actual;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,13 @@
|
||||||
|
package info.nightscout.androidaps.plugins.pump.omnipod.comm.exception;
|
||||||
|
|
||||||
|
import info.nightscout.androidaps.plugins.pump.omnipod.exception.OmnipodException;
|
||||||
|
|
||||||
|
public class MessageDecodingException extends OmnipodException {
|
||||||
|
public MessageDecodingException(String message) {
|
||||||
|
super(message, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public MessageDecodingException(String message, Throwable cause) {
|
||||||
|
super(message, cause, false);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,9 @@
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,9 @@
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,17 @@
|
||||||
|
package info.nightscout.androidaps.plugins.pump.omnipod.comm.exception;
|
||||||
|
|
||||||
|
import info.nightscout.androidaps.plugins.pump.common.utils.ByteUtil;
|
||||||
|
import info.nightscout.androidaps.plugins.pump.omnipod.exception.OmnipodException;
|
||||||
|
|
||||||
|
public class NotEnoughDataException extends OmnipodException {
|
||||||
|
private final byte[] data;
|
||||||
|
|
||||||
|
public NotEnoughDataException(byte[] data) {
|
||||||
|
super("Not enough data: " + ByteUtil.shortHexString(data), false);
|
||||||
|
this.data = data;
|
||||||
|
}
|
||||||
|
|
||||||
|
public byte[] getData() {
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,17 @@
|
||||||
|
package info.nightscout.androidaps.plugins.pump.omnipod.comm.exception;
|
||||||
|
|
||||||
|
import info.nightscout.androidaps.plugins.pump.omnipod.comm.message.response.podinfo.PodInfoFaultEvent;
|
||||||
|
import info.nightscout.androidaps.plugins.pump.omnipod.exception.OmnipodException;
|
||||||
|
|
||||||
|
public class PodFaultException extends OmnipodException {
|
||||||
|
private final PodInfoFaultEvent faultEvent;
|
||||||
|
|
||||||
|
public PodFaultException(PodInfoFaultEvent faultEvent) {
|
||||||
|
super(faultEvent.getFaultEventType().toString(), true);
|
||||||
|
this.faultEvent = faultEvent;
|
||||||
|
}
|
||||||
|
|
||||||
|
public PodInfoFaultEvent getFaultEvent() {
|
||||||
|
return faultEvent;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,17 @@
|
||||||
|
package info.nightscout.androidaps.plugins.pump.omnipod.comm.exception;
|
||||||
|
|
||||||
|
import info.nightscout.androidaps.plugins.pump.omnipod.comm.message.response.ErrorResponse;
|
||||||
|
import info.nightscout.androidaps.plugins.pump.omnipod.exception.OmnipodException;
|
||||||
|
|
||||||
|
public class PodReturnedErrorResponseException extends OmnipodException {
|
||||||
|
private final ErrorResponse errorResponse;
|
||||||
|
|
||||||
|
public PodReturnedErrorResponseException(ErrorResponse errorResponse) {
|
||||||
|
super("Pod returned error response: " + errorResponse.getErrorResponseType(), true);
|
||||||
|
this.errorResponse = errorResponse;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ErrorResponse getErrorResponse() {
|
||||||
|
return errorResponse;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,5 @@
|
||||||
|
package info.nightscout.androidaps.plugins.pump.omnipod.comm.message;
|
||||||
|
|
||||||
|
public interface IRawRepresentable {
|
||||||
|
byte[] getRawData();
|
||||||
|
}
|
|
@ -0,0 +1,31 @@
|
||||||
|
package info.nightscout.androidaps.plugins.pump.omnipod.comm.message;
|
||||||
|
|
||||||
|
import java.io.ByteArrayOutputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
import info.nightscout.androidaps.plugins.pump.omnipod.defs.MessageBlockType;
|
||||||
|
|
||||||
|
public abstract class MessageBlock {
|
||||||
|
protected byte[] encodedData = new byte[0];
|
||||||
|
|
||||||
|
public MessageBlock() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract MessageBlockType getType();
|
||||||
|
|
||||||
|
//This method returns raw message representation
|
||||||
|
//It should be rewritten in a derived class if raw representation of a concrete message
|
||||||
|
//is something else than just message type concatenated with message data
|
||||||
|
public byte[] getRawData() {
|
||||||
|
ByteArrayOutputStream stream = new ByteArrayOutputStream();
|
||||||
|
try {
|
||||||
|
stream.write(this.getType().getValue());
|
||||||
|
stream.write((byte) encodedData.length);
|
||||||
|
stream.write(encodedData);
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return stream.toByteArray();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,7 @@
|
||||||
|
package info.nightscout.androidaps.plugins.pump.omnipod.comm.message;
|
||||||
|
|
||||||
|
public abstract class NonceResyncableMessageBlock extends MessageBlock {
|
||||||
|
public abstract int getNonce();
|
||||||
|
|
||||||
|
public abstract void setNonce(int nonce);
|
||||||
|
}
|
|
@ -0,0 +1,148 @@
|
||||||
|
package info.nightscout.androidaps.plugins.pump.omnipod.comm.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.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.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.util.OmniCRC;
|
||||||
|
|
||||||
|
public class OmnipodMessage {
|
||||||
|
|
||||||
|
private final int address;
|
||||||
|
private final List<MessageBlock> messageBlocks;
|
||||||
|
private final int sequenceNumber;
|
||||||
|
|
||||||
|
public OmnipodMessage(OmnipodMessage other) {
|
||||||
|
address = other.address;
|
||||||
|
messageBlocks = new ArrayList<>(other.messageBlocks);
|
||||||
|
sequenceNumber = other.sequenceNumber;
|
||||||
|
}
|
||||||
|
|
||||||
|
public OmnipodMessage(int address, List<MessageBlock> messageBlocks, int sequenceNumber) {
|
||||||
|
this.address = address;
|
||||||
|
this.messageBlocks = messageBlocks;
|
||||||
|
this.sequenceNumber = sequenceNumber;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static OmnipodMessage decodeMessage(byte[] data) {
|
||||||
|
if (data.length < 10) {
|
||||||
|
throw new NotEnoughDataException(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
int address = ByteUtil.toInt((int) data[0], (int) data[1], (int) data[2],
|
||||||
|
(int) data[3], ByteUtil.BitConversion.BIG_ENDIAN);
|
||||||
|
byte b9 = data[4];
|
||||||
|
int bodyLength = ByteUtil.convertUnsignedByteToInt(data[5]);
|
||||||
|
if (data.length - 8 < bodyLength) {
|
||||||
|
throw new NotEnoughDataException(data);
|
||||||
|
}
|
||||||
|
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));
|
||||||
|
if (crc != calculatedCrc) {
|
||||||
|
throw new CrcMismatchException(calculatedCrc, crc);
|
||||||
|
}
|
||||||
|
List<MessageBlock> blocks = decodeBlocks(ByteUtil.substring(data, 6, data.length - 6 - 2));
|
||||||
|
if (blocks == null || blocks.size() == 0) {
|
||||||
|
throw new MessageDecodingException("No blocks decoded");
|
||||||
|
}
|
||||||
|
|
||||||
|
return new OmnipodMessage(address, blocks, sequenceNumber);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static List<MessageBlock> decodeBlocks(byte[] data) {
|
||||||
|
List<MessageBlock> blocks = new ArrayList<>();
|
||||||
|
int index = 0;
|
||||||
|
while (index < data.length) {
|
||||||
|
try {
|
||||||
|
MessageBlockType blockType = MessageBlockType.fromByte(data[index]);
|
||||||
|
MessageBlock block = blockType.decode(ByteUtil.substring(data, index));
|
||||||
|
blocks.add(block);
|
||||||
|
int blockLength = block.getRawData().length;
|
||||||
|
index += blockLength;
|
||||||
|
} catch (Exception ex) {
|
||||||
|
throw new MessageDecodingException("Failed to decode blocks", ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return blocks;
|
||||||
|
}
|
||||||
|
|
||||||
|
public byte[] getEncoded() {
|
||||||
|
byte[] encodedData = new byte[0];
|
||||||
|
for (MessageBlock messageBlock : messageBlocks) {
|
||||||
|
encodedData = ByteUtil.concat(encodedData, messageBlock.getRawData());
|
||||||
|
}
|
||||||
|
|
||||||
|
byte[] header = new byte[0];
|
||||||
|
//right before the message blocks we have 6 bits of seqNum and 10 bits of length
|
||||||
|
header = ByteUtil.concat(header, ByteUtil.getBytesFromInt(address));
|
||||||
|
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);
|
||||||
|
encodedData = ByteUtil.concat(encodedData, ByteUtil.substring(ByteUtil.getBytesFromInt(crc), 2, 2));
|
||||||
|
return encodedData;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void padWithGetStatusCommands(int packetSize) {
|
||||||
|
while (getEncoded().length < packetSize) {
|
||||||
|
messageBlocks.add(new GetStatusCommand(PodInfoType.NORMAL));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<MessageBlock> getMessageBlocks() {
|
||||||
|
return messageBlocks;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getSequenceNumber() {
|
||||||
|
return sequenceNumber;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isNonceResyncable() {
|
||||||
|
return containsBlock(NonceResyncableMessageBlock.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getSentNonce() {
|
||||||
|
for (MessageBlock messageBlock : messageBlocks) {
|
||||||
|
if (messageBlock instanceof NonceResyncableMessageBlock) {
|
||||||
|
return ((NonceResyncableMessageBlock) messageBlock).getNonce();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
throw new UnsupportedOperationException("Message is not nonce resyncable");
|
||||||
|
}
|
||||||
|
|
||||||
|
public void resyncNonce(int nonce) {
|
||||||
|
for (MessageBlock messageBlock : messageBlocks) {
|
||||||
|
if (messageBlock instanceof NonceResyncableMessageBlock) {
|
||||||
|
((NonceResyncableMessageBlock) messageBlock).setNonce(nonce);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean containsBlock(Class<? extends MessageBlock> blockType) {
|
||||||
|
for (MessageBlock messageBlock : messageBlocks) {
|
||||||
|
if (blockType.isInstance(messageBlock)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "OmnipodMessage{" +
|
||||||
|
"address=" + address +
|
||||||
|
", messageBlocks=" + messageBlocks +
|
||||||
|
", encoded=" + ByteUtil.shortHexStringWithoutSpaces(getEncoded()) +
|
||||||
|
", sequenceNumber=" + sequenceNumber +
|
||||||
|
'}';
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,82 @@
|
||||||
|
package info.nightscout.androidaps.plugins.pump.omnipod.comm.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.defs.PacketType;
|
||||||
|
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.util.OmniCRC;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by andy on 6/1/18.
|
||||||
|
*/
|
||||||
|
public class OmnipodPacket implements RLMessage {
|
||||||
|
private int packetAddress = 0;
|
||||||
|
private PacketType packetType = PacketType.INVALID;
|
||||||
|
private int sequenceNumber = 0;
|
||||||
|
private byte[] encodedMessage = null;
|
||||||
|
private boolean valid = false;
|
||||||
|
|
||||||
|
public OmnipodPacket(byte[] encoded) {
|
||||||
|
if (encoded.length < 7) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.packetAddress = ByteUtil.toInt((int) encoded[0], (int) encoded[1],
|
||||||
|
(int) encoded[2], (int) encoded[3], ByteUtil.BitConversion.BIG_ENDIAN);
|
||||||
|
try {
|
||||||
|
this.packetType = PacketType.fromByte((byte) (((int) encoded[4] & 0xFF) >> 5));
|
||||||
|
} catch (IllegalArgumentException ex) {
|
||||||
|
throw new IllegalPacketTypeException(null, null);
|
||||||
|
}
|
||||||
|
this.sequenceNumber = (encoded[4] & 0b11111);
|
||||||
|
byte crc = OmniCRC.crc8(ByteUtil.substring(encoded, 0, encoded.length - 1));
|
||||||
|
if (crc != encoded[encoded.length - 1]) {
|
||||||
|
throw new CrcMismatchException(crc, encoded[encoded.length - 1]);
|
||||||
|
}
|
||||||
|
this.encodedMessage = ByteUtil.substring(encoded, 5, encoded.length - 1 - 5);
|
||||||
|
valid = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public OmnipodPacket(int packetAddress, PacketType packetType, int packetNumber, byte[] encodedMessage) {
|
||||||
|
this.packetAddress = packetAddress;
|
||||||
|
this.packetType = packetType;
|
||||||
|
this.sequenceNumber = packetNumber;
|
||||||
|
this.encodedMessage = encodedMessage;
|
||||||
|
if (encodedMessage.length > packetType.getMaxBodyLength()) {
|
||||||
|
this.encodedMessage = ByteUtil.substring(encodedMessage, 0, packetType.getMaxBodyLength());
|
||||||
|
}
|
||||||
|
this.valid = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public PacketType getPacketType() {
|
||||||
|
return packetType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getAddress() {
|
||||||
|
return packetAddress;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getSequenceNumber() {
|
||||||
|
return sequenceNumber;
|
||||||
|
}
|
||||||
|
|
||||||
|
public byte[] getEncodedMessage() {
|
||||||
|
return encodedMessage;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public byte[] getTxData() {
|
||||||
|
byte[] output = new byte[0];
|
||||||
|
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));
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isValid() {
|
||||||
|
return valid;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,54 @@
|
||||||
|
package info.nightscout.androidaps.plugins.pump.omnipod.comm.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;
|
||||||
|
|
||||||
|
public class AcknowledgeAlertsCommand extends NonceResyncableMessageBlock {
|
||||||
|
|
||||||
|
private final AlertSet alerts;
|
||||||
|
private int nonce;
|
||||||
|
|
||||||
|
public AcknowledgeAlertsCommand(int nonce, AlertSet alerts) {
|
||||||
|
this.nonce = nonce;
|
||||||
|
this.alerts = alerts;
|
||||||
|
encode();
|
||||||
|
}
|
||||||
|
|
||||||
|
public AcknowledgeAlertsCommand(int nonce, AlertSlot alertSlot) {
|
||||||
|
this(nonce, new AlertSet(Collections.singletonList(alertSlot)));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public MessageBlockType getType() {
|
||||||
|
return MessageBlockType.ACKNOWLEDGE_ALERT;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void encode() {
|
||||||
|
encodedData = ByteUtil.getBytesFromInt(nonce);
|
||||||
|
encodedData = ByteUtil.concat(encodedData, alerts.getRawValue());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getNonce() {
|
||||||
|
return nonce;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setNonce(int nonce) {
|
||||||
|
this.nonce = nonce;
|
||||||
|
encode();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "AcknowledgeAlertsCommand{" +
|
||||||
|
"alerts=" + alerts +
|
||||||
|
", nonce=" + nonce +
|
||||||
|
'}';
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,31 @@
|
||||||
|
package info.nightscout.androidaps.plugins.pump.omnipod.comm.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;
|
||||||
|
|
||||||
|
public class AssignAddressCommand extends MessageBlock {
|
||||||
|
private final int address;
|
||||||
|
|
||||||
|
public AssignAddressCommand(int address) {
|
||||||
|
this.address = address;
|
||||||
|
encodedData = ByteBuffer.allocate(4).putInt(this.address).array();
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getAddress() {
|
||||||
|
return address;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public MessageBlockType getType() {
|
||||||
|
return MessageBlockType.ASSIGN_ADDRESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "AssignAddressCommand{" +
|
||||||
|
"address=" + address +
|
||||||
|
'}';
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,127 @@
|
||||||
|
package info.nightscout.androidaps.plugins.pump.omnipod.comm.message.command;
|
||||||
|
|
||||||
|
import org.joda.time.Duration;
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
public class BasalScheduleExtraCommand extends MessageBlock {
|
||||||
|
private final boolean acknowledgementBeep;
|
||||||
|
private final boolean completionBeep;
|
||||||
|
private final Duration programReminderInterval;
|
||||||
|
private final byte currentEntryIndex;
|
||||||
|
private final double remainingPulses;
|
||||||
|
// We use a double for the delay between pulses because the Joda time API lacks precision for our calculations
|
||||||
|
private final double delayUntilNextTenthOfPulseInSeconds;
|
||||||
|
private final List<RateEntry> rateEntries;
|
||||||
|
|
||||||
|
public BasalScheduleExtraCommand(boolean acknowledgementBeep, boolean completionBeep,
|
||||||
|
Duration programReminderInterval, byte currentEntryIndex,
|
||||||
|
double remainingPulses, double delayUntilNextTenthOfPulseInSeconds, List<RateEntry> rateEntries) {
|
||||||
|
|
||||||
|
this.acknowledgementBeep = acknowledgementBeep;
|
||||||
|
this.completionBeep = completionBeep;
|
||||||
|
this.programReminderInterval = programReminderInterval;
|
||||||
|
this.currentEntryIndex = currentEntryIndex;
|
||||||
|
this.remainingPulses = remainingPulses;
|
||||||
|
this.delayUntilNextTenthOfPulseInSeconds = delayUntilNextTenthOfPulseInSeconds;
|
||||||
|
this.rateEntries = rateEntries;
|
||||||
|
encode();
|
||||||
|
}
|
||||||
|
|
||||||
|
public BasalScheduleExtraCommand(BasalSchedule schedule, Duration scheduleOffset,
|
||||||
|
boolean acknowledgementBeep, boolean completionBeep, Duration programReminderInterval) {
|
||||||
|
rateEntries = new ArrayList<>();
|
||||||
|
this.acknowledgementBeep = acknowledgementBeep;
|
||||||
|
this.completionBeep = completionBeep;
|
||||||
|
this.programReminderInterval = programReminderInterval;
|
||||||
|
Duration scheduleOffsetNearestSecond = Duration.standardSeconds(Math.round(scheduleOffset.getMillis() / 1000.0));
|
||||||
|
|
||||||
|
BasalSchedule mergedSchedule = new BasalSchedule(schedule.adjacentEqualRatesMergedEntries());
|
||||||
|
List<BasalSchedule.BasalScheduleDurationEntry> durations = mergedSchedule.getDurations();
|
||||||
|
|
||||||
|
for (BasalSchedule.BasalScheduleDurationEntry entry : durations) {
|
||||||
|
rateEntries.addAll(RateEntry.createEntries(entry.getRate(), entry.getDuration()));
|
||||||
|
}
|
||||||
|
|
||||||
|
BasalSchedule.BasalScheduleLookupResult entryLookupResult = mergedSchedule.lookup(scheduleOffsetNearestSecond);
|
||||||
|
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);
|
||||||
|
double timeBetweenPulses = 3600.0 / pulsesPerHour;
|
||||||
|
delayUntilNextTenthOfPulseInSeconds = (timeRemainingInEntryInSeconds % (timeBetweenPulses / 10.0));
|
||||||
|
remainingPulses = pulsesPerHour * (timeRemainingInEntryInSeconds - delayUntilNextTenthOfPulseInSeconds) / 3600.0 + 0.1;
|
||||||
|
|
||||||
|
encode();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void encode() {
|
||||||
|
byte beepOptions = (byte) ((programReminderInterval.getStandardMinutes() & 0x3f) + (completionBeep ? 1 << 6 : 0) + (acknowledgementBeep ? 1 << 7 : 0));
|
||||||
|
|
||||||
|
encodedData = new byte[]{
|
||||||
|
beepOptions,
|
||||||
|
currentEntryIndex
|
||||||
|
};
|
||||||
|
|
||||||
|
encodedData = ByteUtil.concat(encodedData, ByteUtil.getBytesFromInt16((int) Math.round(remainingPulses * 10)));
|
||||||
|
encodedData = ByteUtil.concat(encodedData, ByteUtil.getBytesFromInt((int) Math.round(delayUntilNextTenthOfPulseInSeconds * 1000 * 1000)));
|
||||||
|
|
||||||
|
for (RateEntry entry : rateEntries) {
|
||||||
|
encodedData = ByteUtil.concat(encodedData, entry.getRawData());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public MessageBlockType getType() {
|
||||||
|
return MessageBlockType.BASAL_SCHEDULE_EXTRA;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isAcknowledgementBeep() {
|
||||||
|
return acknowledgementBeep;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isCompletionBeep() {
|
||||||
|
return completionBeep;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Duration getProgramReminderInterval() {
|
||||||
|
return programReminderInterval;
|
||||||
|
}
|
||||||
|
|
||||||
|
public byte getCurrentEntryIndex() {
|
||||||
|
return currentEntryIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
public double getRemainingPulses() {
|
||||||
|
return remainingPulses;
|
||||||
|
}
|
||||||
|
|
||||||
|
public double getDelayUntilNextTenthOfPulseInSeconds() {
|
||||||
|
return delayUntilNextTenthOfPulseInSeconds;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<RateEntry> getRateEntries() {
|
||||||
|
return new ArrayList<>(rateEntries);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "BasalScheduleExtraCommand{" +
|
||||||
|
"acknowledgementBeep=" + acknowledgementBeep +
|
||||||
|
", completionBeep=" + completionBeep +
|
||||||
|
", programReminderInterval=" + programReminderInterval +
|
||||||
|
", currentEntryIndex=" + currentEntryIndex +
|
||||||
|
", remainingPulses=" + remainingPulses +
|
||||||
|
", delayUntilNextTenthOfPulseInSeconds=" + delayUntilNextTenthOfPulseInSeconds +
|
||||||
|
", rateEntries=" + rateEntries +
|
||||||
|
'}';
|
||||||
|
}
|
||||||
|
}
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue