Merge pull request #634 from MilosKozak/dev

1.58
This commit is contained in:
Milos Kozak 2018-02-01 09:55:48 +01:00 committed by GitHub
commit b9b99917d9
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
284 changed files with 13669 additions and 6024 deletions

View file

@ -7,12 +7,18 @@ android:
components: components:
- platform-tools - platform-tools
- tools - tools
- build-tools-25.0.2 - build-tools-27.0.2
- android-23 - android-23
- extra-google-m2repository - extra-google-m2repository
- extra-android-m2repository - extra-android-m2repository
- extra-google-google_play_services - extra-google-google_play_services
before_install:
- yes | sdkmanager "platforms;android-27"
script: script:
# Unit Test # Unit Test
- ./gradlew test - ./gradlew test jacocoTestReport
after_success:
- bash <(curl -s https://codecov.io/bash)

10
ISSUE_TEMPLATE.md Normal file
View file

@ -0,0 +1,10 @@
Reporting bugs
--------------
- Note the precise time the problem occurred and describe the circumstances and steps that caused
the problem
- Note the Build version (found in the About dialog in the app, when pressing the three dots in the
upper-right corner).
- Obtain the app's log files, which can be found on the phone in
_/storage/emulated/0/Android/data/info.nightscout.androidaps/_
See https://github.com/MilosKozak/AndroidAPS/wiki/Accessing-logfiles
- Open an issue at https://github.com/MilosKozak/AndroidAPS/issues/new

View file

@ -5,3 +5,5 @@
[![Gitter](https://badges.gitter.im/MilosKozak/AndroidAPS.svg)](https://gitter.im/MilosKozak/AndroidAPS?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) [![Gitter](https://badges.gitter.im/MilosKozak/AndroidAPS.svg)](https://gitter.im/MilosKozak/AndroidAPS?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
[![Build status](https://travis-ci.org/MilosKozak/AndroidAPS.svg?branch=master)](https://travis-ci.org/MilosKozak/AndroidAPS) [![Build status](https://travis-ci.org/MilosKozak/AndroidAPS.svg?branch=master)](https://travis-ci.org/MilosKozak/AndroidAPS)
[![codecov](https://codecov.io/gh/MilosKozak/AndroidAPS/branch/master/graph/badge.svg)](https://codecov.io/gh/MilosKozak/AndroidAPS)
dev: [![codecov](https://codecov.io/gh/MilosKozak/AndroidAPS/branch/dev/graph/badge.svg)](https://codecov.io/gh/MilosKozak/AndroidAPS)

View file

@ -0,0 +1,7 @@
Follow this link to get the source PSD file for the Steampunk graphics. The file could not be included in the repository as it exceeds Github's 25 mb limit.
Note, the source image size is 1600x1600. The image size should be reduced to 400x400 prior to export of final PNG.
https://drive.google.com/drive/folders/1MrdgnQz3wOniDvRSMhAsqHBYb2WmE5i0
Graphics created by (Github): andrew-warrington

View file

@ -1,14 +1,26 @@
buildscript { buildscript {
repositories { repositories {
maven { url 'https://maven.fabric.io/public' } maven { url 'https://maven.fabric.io/public' }
jcenter()
} }
dependencies { dependencies {
classpath 'io.fabric.tools:gradle:1.+' classpath 'io.fabric.tools:gradle:1.+'
classpath 'com.dicedmelon.gradle:jacoco-android:0.1.2'
} }
} }
apply plugin: 'com.android.application' apply plugin: "com.android.application"
apply plugin: 'io.fabric' apply plugin: "io.fabric"
apply plugin: "jacoco-android"
apply plugin: 'com.jakewharton.butterknife'
ext {
supportLibraryVersion = "27.0.2"
ormLiteVersion = "4.46"
powermockVersion = "1.7.3"
dexmakerVersion = "1.2"
}
repositories { repositories {
maven { url 'https://maven.fabric.io/public' } maven { url 'https://maven.fabric.io/public' }
@ -36,8 +48,8 @@ def generateGitBuild = { ->
} }
android { android {
compileSdkVersion 23 compileSdkVersion 27
buildToolsVersion "25.0.2" buildToolsVersion "${supportLibraryVersion}"
defaultConfig { defaultConfig {
applicationId "info.nightscout.androidaps" applicationId "info.nightscout.androidaps"
@ -45,7 +57,7 @@ android {
targetSdkVersion 23 targetSdkVersion 23
multiDexEnabled true multiDexEnabled true
versionCode 1500 versionCode 1500
version "1.55" version "1.58"
buildConfigField "String", "VERSION", '"' + version + '"' buildConfigField "String", "VERSION", '"' + version + '"'
buildConfigField "String", "BUILDVERSION", generateGitBuild() buildConfigField "String", "BUILDVERSION", generateGitBuild()
@ -54,13 +66,24 @@ android {
} }
} }
lintOptions { lintOptions {
// TODO remove once wear dependency com.google.android.gms:play-services-wearable:7.3.0
// has been upgraded (requiring significant code changes), which currently fails release
// build with a deprecation warning
//abortOnError false
// (disabled entirely to avoid reports on the error, which would still be displayed
// and it's easy to overlook that it's ignored)
checkReleaseBuilds false
disable 'MissingTranslation' disable 'MissingTranslation'
disable 'ExtraTranslation'
} }
buildTypes { buildTypes {
release { release {
minifyEnabled false minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
} }
debug {
testCoverageEnabled true
}
} }
productFlavors { productFlavors {
flavorDimensions "standard" flavorDimensions "standard"
@ -75,6 +98,8 @@ android {
buildConfigField "boolean", "PUMPDRIVERS", "true" buildConfigField "boolean", "PUMPDRIVERS", "true"
buildConfigField "boolean", "NSCLIENTOLNY", "false" buildConfigField "boolean", "NSCLIENTOLNY", "false"
buildConfigField "boolean", "CLOSEDLOOP", "true" buildConfigField "boolean", "CLOSEDLOOP", "true"
buildConfigField "boolean", "G5UPLOADER", "false"
buildConfigField "boolean", "PUMPCONTROL", "false"
} }
openloop { openloop {
dimension "standard" dimension "standard"
@ -87,6 +112,8 @@ android {
buildConfigField "boolean", "PUMPDRIVERS", "true" buildConfigField "boolean", "PUMPDRIVERS", "true"
buildConfigField "boolean", "NSCLIENTOLNY", "false" buildConfigField "boolean", "NSCLIENTOLNY", "false"
buildConfigField "boolean", "CLOSEDLOOP", "false" buildConfigField "boolean", "CLOSEDLOOP", "false"
buildConfigField "boolean", "G5UPLOADER", "false"
buildConfigField "boolean", "PUMPCONTROL", "false"
} }
pumpcontrol { pumpcontrol {
dimension "standard" dimension "standard"
@ -99,6 +126,8 @@ android {
buildConfigField "boolean", "PUMPDRIVERS", "true" buildConfigField "boolean", "PUMPDRIVERS", "true"
buildConfigField "boolean", "NSCLIENTOLNY", "false" buildConfigField "boolean", "NSCLIENTOLNY", "false"
buildConfigField "boolean", "CLOSEDLOOP", "false" buildConfigField "boolean", "CLOSEDLOOP", "false"
buildConfigField "boolean", "G5UPLOADER", "false"
buildConfigField "boolean", "PUMPCONTROL", "true"
} }
nsclient { nsclient {
dimension "standard" dimension "standard"
@ -111,6 +140,22 @@ android {
buildConfigField "boolean", "PUMPDRIVERS", "false" buildConfigField "boolean", "PUMPDRIVERS", "false"
buildConfigField "boolean", "NSCLIENTOLNY", "true" buildConfigField "boolean", "NSCLIENTOLNY", "true"
buildConfigField "boolean", "CLOSEDLOOP", "false" buildConfigField "boolean", "CLOSEDLOOP", "false"
buildConfigField "boolean", "G5UPLOADER", "false"
buildConfigField "boolean", "PUMPCONTROL", "false"
}
g5uploader {
dimension "standard"
resValue "string", "app_name", "NSClient"
versionName version + "-nsclient"
manifestPlaceholders = [
appIcon: "@mipmap/yellowowl"
]
buildConfigField "boolean", "APS", "false"
buildConfigField "boolean", "PUMPDRIVERS", "false"
buildConfigField "boolean", "NSCLIENTOLNY", "false"
buildConfigField "boolean", "CLOSEDLOOP", "false"
buildConfigField "boolean", "G5UPLOADER", "true"
buildConfigField "boolean", "PUMPCONTROL", "false"
} }
} }
} }
@ -128,47 +173,58 @@ dependencies {
wearApp project(':wear') wearApp project(':wear')
compile fileTree(include: ['*.jar'], dir: 'libs') compile fileTree(include: ['*.jar'], dir: 'libs')
compile('com.crashlytics.sdk.android:crashlytics:2.6.7@aar') { compile("com.crashlytics.sdk.android:crashlytics:2.6.7@aar") {
transitive = true; transitive = true;
} }
compile('com.crashlytics.sdk.android:answers:1.3.12@aar') { compile("com.crashlytics.sdk.android:answers:1.3.12@aar") {
transitive = true; transitive = true;
} }
compile 'com.android.support:appcompat-v7:23.4.0' compile "com.android.support:appcompat-v7:${supportLibraryVersion}"
compile 'com.android.support:support-v4:23.4.0' compile "com.android.support:support-v4:${supportLibraryVersion}"
compile 'com.android.support:cardview-v7:23.4.0' compile "com.android.support:cardview-v7:${supportLibraryVersion}"
compile 'com.android.support:recyclerview-v7:23.4.0' compile "com.android.support:recyclerview-v7:${supportLibraryVersion}"
compile 'com.android.support:gridlayout-v7:23.4.0' compile "com.android.support:gridlayout-v7:${supportLibraryVersion}"
compile "com.android.support:design:23.4.0" compile "com.android.support:design:${supportLibraryVersion}"
compile "com.android.support:percent:23.4.0" compile "com.android.support:percent:${supportLibraryVersion}"
compile 'com.wdullaer:materialdatetimepicker:2.3.0' compile "com.wdullaer:materialdatetimepicker:2.3.0"
compile 'com.squareup:otto:1.3.7' compile "com.squareup:otto:1.3.7"
compile 'com.j256.ormlite:ormlite-core:4.46' compile "com.j256.ormlite:ormlite-core:${ormLiteVersion}"
compile 'com.j256.ormlite:ormlite-android:4.46' compile "com.j256.ormlite:ormlite-android:${ormLiteVersion}"
compile('com.github.tony19:logback-android-classic:1.1.1-6') { compile("com.github.tony19:logback-android-classic:1.1.1-6") {
exclude group: 'com.google.android', module: 'android' exclude group: "com.google.android", module: "android"
} }
compile 'org.apache.commons:commons-lang3:3.6' compile "org.apache.commons:commons-lang3:3.6"
compile 'org.slf4j:slf4j-api:1.7.12' compile "org.slf4j:slf4j-api:1.7.12"
compile 'com.jjoe64:graphview:4.0.1' compile "com.jjoe64:graphview:4.0.1"
compile 'com.joanzapata.iconify:android-iconify-fontawesome:2.1.1' compile "com.joanzapata.iconify:android-iconify-fontawesome:2.1.1"
compile 'com.google.android.gms:play-services-wearable:7.5.0' compile "com.google.android.gms:play-services-wearable:7.5.0"
compile 'junit:junit:4.12' compile(name: "android-edittext-validator-v1.3.4-mod", ext: "aar")
testCompile 'org.json:json:20140107' compile("com.google.android:flexbox:0.3.0") {
testCompile 'org.mockito:mockito-core:2.7.22' exclude group: "com.android.support"
androidTestCompile 'org.mockito:mockito-core:2.7.22'
androidTestCompile 'com.google.dexmaker:dexmaker:1.2'
androidTestCompile 'com.google.dexmaker:dexmaker-mockito:1.2'
compile(name: 'android-edittext-validator-v1.3.4-mod', ext: 'aar')
compile ('com.google.android:flexbox:0.3.0') {
exclude group: 'com.android.support'
} }
compile('io.socket:socket.io-client:0.8.3') { compile("io.socket:socket.io-client:0.8.3") {
// excluding org.json which is provided by Android // excluding org.json which is provided by Android
exclude group: 'org.json', module: 'json' exclude group: "org.json", module: "json"
} }
compile 'com.google.code.gson:gson:2.7' compile "com.google.code.gson:gson:2.7"
compile 'com.google.guava:guava:20.0' compile "com.google.guava:guava:20.0"
compile "net.danlew:android.joda:2.9.9.1"
api "com.jakewharton:butterknife:8.8.1"
annotationProcessor "com.jakewharton:butterknife-compiler:8.8.1"
testCompile "junit:junit:4.12"
testCompile "org.json:json:20140107"
testCompile "org.mockito:mockito-core:2.7.22"
testCompile "org.powermock:powermock-api-mockito2:${powermockVersion}"
testCompile "org.powermock:powermock-module-junit4-rule-agent:${powermockVersion}"
testCompile "org.powermock:powermock-module-junit4-rule:${powermockVersion}"
testCompile "org.powermock:powermock-module-junit4:${powermockVersion}"
testCompile "joda-time:joda-time:2.9.4.2"
androidTestCompile "org.mockito:mockito-core:2.7.22"
androidTestCompile "com.google.dexmaker:dexmaker:${dexmakerVersion}"
androidTestCompile "com.google.dexmaker:dexmaker-mockito:${dexmakerVersion}"
} }

View file

@ -42,6 +42,9 @@
<activity <activity
android:name=".plugins.Overview.Dialogs.BolusProgressHelperActivity" android:name=".plugins.Overview.Dialogs.BolusProgressHelperActivity"
android:theme="@style/Theme.AppCompat.Translucent" /> android:theme="@style/Theme.AppCompat.Translucent" />
<activity
android:name=".plugins.Overview.Dialogs.ErrorHelperActivity"
android:theme="@style/Theme.AppCompat.Translucent" />
<activity android:name=".AgreementActivity" /> <activity android:name=".AgreementActivity" />
<activity android:name=".plugins.PumpDanaR.activities.DanaRHistoryActivity" /> <activity android:name=".plugins.PumpDanaR.activities.DanaRHistoryActivity" />
<activity android:name=".plugins.PumpDanaR.activities.DanaRStatsActivity" /> <activity android:name=".plugins.PumpDanaR.activities.DanaRStatsActivity" />
@ -72,6 +75,8 @@
<action android:name="com.eveningoutpost.dexdrip.NS_EMULATOR" /> <action android:name="com.eveningoutpost.dexdrip.NS_EMULATOR" />
<!-- Receiver from glimp --> <!-- Receiver from glimp -->
<action android:name="it.ct.glicemia.ACTION_GLUCOSE_MEASURED" /> <action android:name="it.ct.glicemia.ACTION_GLUCOSE_MEASURED" />
<!-- Receiver from DexcomG5 -->
<action android:name="com.dexcom.cgm.DATA" />
</intent-filter> </intent-filter>
</receiver> </receiver>
<!-- Receiver keepalive, scheduled every 30 min --> <!-- Receiver keepalive, scheduled every 30 min -->
@ -140,6 +145,9 @@
android:name=".Services.AlarmSoundService" android:name=".Services.AlarmSoundService"
android:enabled="true" android:enabled="true"
android:exported="true" /> android:exported="true" />
<service
android:name=".plugins.Overview.notifications.DismissNotificationService"
android:exported="false"></service>
<meta-data <meta-data
android:name="io.fabric.ApiKey" android:name="io.fabric.ApiKey"

View file

@ -15,7 +15,7 @@
<maxHistory>120</maxHistory> <maxHistory>120</maxHistory>
</rollingPolicy> </rollingPolicy>
<encoder> <encoder>
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level [%file:%line]: %msg%n</pattern> <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level [%class:%line]: %msg%n</pattern>
</encoder> </encoder>
</appender> </appender>
@ -24,7 +24,7 @@
<pattern>%logger{0}</pattern> <pattern>%logger{0}</pattern>
</tagEncoder> </tagEncoder>
<encoder> <encoder>
<pattern>[%thread] %-5level [%file:%line]: %msg%n</pattern> <pattern>[%thread] %-5level [%class:%line]: %msg%n</pattern>
</encoder> </encoder>
</appender> </appender>

View file

@ -4,22 +4,24 @@ package info.nightscout.androidaps;
* Created by mike on 07.06.2016. * Created by mike on 07.06.2016.
*/ */
public class Config { public class Config {
public static int SUPPORTEDNSVERSION = 1000; // 0.10.00 public static int SUPPORTEDNSVERSION = 1002; // 0.10.00
// MAIN FUCTIONALITY // MAIN FUCTIONALITY
public static final boolean APS = BuildConfig.APS; public static final boolean APS = BuildConfig.APS;
// PLUGINS // PLUGINS
public static final boolean NSCLIENT = BuildConfig.NSCLIENTOLNY; public static final boolean NSCLIENT = BuildConfig.NSCLIENTOLNY;
public static final boolean G5UPLOADER = BuildConfig.G5UPLOADER;
public static final boolean PUMPCONTROL = BuildConfig.PUMPCONTROL;
public static final boolean DANAR = true && BuildConfig.PUMPDRIVERS; public static final boolean DANAR = BuildConfig.PUMPDRIVERS;
public static final boolean ACTION = !BuildConfig.NSCLIENTOLNY; public static final boolean ACTION = !BuildConfig.NSCLIENTOLNY && !BuildConfig.G5UPLOADER;
public static final boolean VIRTUALPUMP = !BuildConfig.NSCLIENTOLNY; public static final boolean VIRTUALPUMP = !BuildConfig.NSCLIENTOLNY && !BuildConfig.G5UPLOADER;
public static final boolean MDI = !BuildConfig.NSCLIENTOLNY; public static final boolean MDI = !BuildConfig.NSCLIENTOLNY && !BuildConfig.G5UPLOADER;
public static final boolean OTHERPROFILES = !BuildConfig.NSCLIENTOLNY; public static final boolean OTHERPROFILES = !BuildConfig.NSCLIENTOLNY && !BuildConfig.G5UPLOADER;
public static final boolean SAFETY = !BuildConfig.NSCLIENTOLNY; public static final boolean SAFETY = !BuildConfig.NSCLIENTOLNY && !BuildConfig.G5UPLOADER;
public static final boolean SMSCOMMUNICATORENABLED = !BuildConfig.NSCLIENTOLNY; public static final boolean SMSCOMMUNICATORENABLED = !BuildConfig.NSCLIENTOLNY && !BuildConfig.G5UPLOADER;
public static final boolean detailedLog = true; public static final boolean detailedLog = true;

View file

@ -54,8 +54,12 @@ public class Constants {
//Screen: Threshold for width/height to go into small width/height layout //Screen: Threshold for width/height to go into small width/height layout
public static final int SMALL_WIDTH = 320; public static final int SMALL_WIDTH = 320;
public static final int SMALL_HEIGHT = 320; public static final int SMALL_HEIGHT = 480;
//Autosens //Autosens
public static final double DEVIATION_TO_BE_EQUAL = 2.0; public static final double DEVIATION_TO_BE_EQUAL = 2.0;
// Pump
public static final int PUMP_MAX_CONNECTION_TIME_IN_SECONDS = 120 - 1;
public static final int MIN_WATCHDOG_INTERVAL_IN_SECONDS = 12 * 60;
} }

View file

@ -82,7 +82,7 @@ public class MainActivity extends AppCompatActivity implements View.OnClickListe
Manifest.permission.WRITE_EXTERNAL_STORAGE}, CASE_STORAGE); Manifest.permission.WRITE_EXTERNAL_STORAGE}, CASE_STORAGE);
} }
askForBatteryOptimizationPermission(); askForBatteryOptimizationPermission();
checkUpgradeToProfileTarget(); doMigrations();
if (Config.logFunctionCalls) if (Config.logFunctionCalls)
log.debug("onCreate"); log.debug("onCreate");
@ -112,12 +112,16 @@ public class MainActivity extends AppCompatActivity implements View.OnClickListe
runOnUiThread(new Runnable() { runOnUiThread(new Runnable() {
@Override @Override
public void run() { public void run() {
recreate(); if(ev.recreate) {
try { // activity may be destroyed recreate();
setUpTabs(true); }else {
} catch (IllegalStateException e) { try { // activity may be destroyed
log.error("Unhandled exception", e); setUpTabs(true);
} catch (IllegalStateException e) {
log.error("Unhandled exception", e);
}
} }
boolean lockScreen = BuildConfig.NSCLIENTOLNY && SP.getBoolean("lockscreen", false); boolean lockScreen = BuildConfig.NSCLIENTOLNY && SP.getBoolean("lockscreen", false);
if (lockScreen) if (lockScreen)
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
@ -159,6 +163,19 @@ public class MainActivity extends AppCompatActivity implements View.OnClickListe
} }
} }
private void doMigrations() {
checkUpgradeToProfileTarget();
// guarantee that the unreachable threshold is at least 30 and of type String
// Added in 1.57 at 21.01.2018
Integer unreachable_threshold = SP.getInt(R.string.key_pump_unreachable_threshold, 30);
SP.remove(R.string.key_pump_unreachable_threshold);
if(unreachable_threshold < 30) unreachable_threshold = 30;
SP.putString(R.string.key_pump_unreachable_threshold, unreachable_threshold.toString());
}
private void checkUpgradeToProfileTarget() { // TODO: can be removed in the future private void checkUpgradeToProfileTarget() { // TODO: can be removed in the future
boolean oldKeyExists = SP.contains("openapsma_min_bg"); boolean oldKeyExists = SP.contains("openapsma_min_bg");
if (oldKeyExists) { if (oldKeyExists) {
@ -369,7 +386,7 @@ public class MainActivity extends AppCompatActivity implements View.OnClickListe
case R.id.nav_about: case R.id.nav_about:
AlertDialog.Builder builder = new AlertDialog.Builder(v.getContext()); AlertDialog.Builder builder = new AlertDialog.Builder(v.getContext());
builder.setTitle(getString(R.string.app_name) + " " + BuildConfig.VERSION); builder.setTitle(getString(R.string.app_name) + " " + BuildConfig.VERSION);
if (Config.NSCLIENT) if (Config.NSCLIENT|| Config.G5UPLOADER)
builder.setIcon(R.mipmap.yellowowl); builder.setIcon(R.mipmap.yellowowl);
else else
builder.setIcon(R.mipmap.blueowl); builder.setIcon(R.mipmap.blueowl);

View file

@ -1,7 +1,6 @@
package info.nightscout.androidaps; package info.nightscout.androidaps;
import android.app.Application; import android.app.Application;
import android.content.Intent;
import android.content.IntentFilter; import android.content.IntentFilter;
import android.content.res.Resources; import android.content.res.Resources;
import android.os.SystemClock; import android.os.SystemClock;
@ -16,6 +15,8 @@ import com.squareup.otto.Bus;
import com.squareup.otto.LoggingBus; import com.squareup.otto.LoggingBus;
import com.squareup.otto.ThreadEnforcer; import com.squareup.otto.ThreadEnforcer;
import net.danlew.android.joda.JodaTimeAndroid;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
@ -25,7 +26,6 @@ import info.nightscout.androidaps.Services.Intents;
import info.nightscout.androidaps.db.DatabaseHelper; import info.nightscout.androidaps.db.DatabaseHelper;
import info.nightscout.androidaps.interfaces.InsulinInterface; import info.nightscout.androidaps.interfaces.InsulinInterface;
import info.nightscout.androidaps.interfaces.PluginBase; import info.nightscout.androidaps.interfaces.PluginBase;
import info.nightscout.androidaps.interfaces.PumpInterface;
import info.nightscout.androidaps.plugins.Actions.ActionsFragment; import info.nightscout.androidaps.plugins.Actions.ActionsFragment;
import info.nightscout.androidaps.plugins.Careportal.CareportalPlugin; import info.nightscout.androidaps.plugins.Careportal.CareportalPlugin;
import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderFragment; import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderFragment;
@ -47,23 +47,20 @@ import info.nightscout.androidaps.plugins.OpenAPSMA.OpenAPSMAPlugin;
import info.nightscout.androidaps.plugins.Overview.OverviewPlugin; import info.nightscout.androidaps.plugins.Overview.OverviewPlugin;
import info.nightscout.androidaps.plugins.Persistentnotification.PersistentNotificationPlugin; import info.nightscout.androidaps.plugins.Persistentnotification.PersistentNotificationPlugin;
import info.nightscout.androidaps.plugins.ProfileCircadianPercentage.CircadianPercentageProfileFragment; import info.nightscout.androidaps.plugins.ProfileCircadianPercentage.CircadianPercentageProfileFragment;
import info.nightscout.androidaps.plugins.ProfileLocal.LocalProfileFragment; import info.nightscout.androidaps.plugins.ProfileLocal.LocalProfilePlugin;
import info.nightscout.androidaps.plugins.ProfileNS.NSProfilePlugin; import info.nightscout.androidaps.plugins.ProfileNS.NSProfilePlugin;
import info.nightscout.androidaps.plugins.ProfileSimple.SimpleProfilePlugin; import info.nightscout.androidaps.plugins.ProfileSimple.SimpleProfilePlugin;
import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPlugin; import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPlugin;
import info.nightscout.androidaps.plugins.PumpDanaR.services.DanaRExecutionService;
import info.nightscout.androidaps.plugins.PumpDanaRKorean.DanaRKoreanPlugin; import info.nightscout.androidaps.plugins.PumpDanaRKorean.DanaRKoreanPlugin;
import info.nightscout.androidaps.plugins.PumpDanaRKorean.services.DanaRKoreanExecutionService;
import info.nightscout.androidaps.plugins.PumpDanaRS.DanaRSPlugin; import info.nightscout.androidaps.plugins.PumpDanaRS.DanaRSPlugin;
import info.nightscout.androidaps.plugins.PumpDanaRS.services.DanaRSService;
import info.nightscout.androidaps.plugins.PumpDanaRv2.DanaRv2Plugin; import info.nightscout.androidaps.plugins.PumpDanaRv2.DanaRv2Plugin;
import info.nightscout.androidaps.plugins.PumpDanaRv2.services.DanaRv2ExecutionService;
import info.nightscout.androidaps.plugins.PumpMDI.MDIPlugin; import info.nightscout.androidaps.plugins.PumpMDI.MDIPlugin;
import info.nightscout.androidaps.plugins.PumpVirtual.VirtualPumpPlugin; import info.nightscout.androidaps.plugins.PumpVirtual.VirtualPumpPlugin;
import info.nightscout.androidaps.plugins.SensitivityAAPS.SensitivityAAPSPlugin; import info.nightscout.androidaps.plugins.SensitivityAAPS.SensitivityAAPSPlugin;
import info.nightscout.androidaps.plugins.SensitivityOref0.SensitivityOref0Plugin; import info.nightscout.androidaps.plugins.SensitivityOref0.SensitivityOref0Plugin;
import info.nightscout.androidaps.plugins.SensitivityWeightedAverage.SensitivityWeightedAveragePlugin; import info.nightscout.androidaps.plugins.SensitivityWeightedAverage.SensitivityWeightedAveragePlugin;
import info.nightscout.androidaps.plugins.SmsCommunicator.SmsCommunicatorPlugin; import info.nightscout.androidaps.plugins.SmsCommunicator.SmsCommunicatorPlugin;
import info.nightscout.androidaps.plugins.SourceDexcomG5.SourceDexcomG5Plugin;
import info.nightscout.androidaps.plugins.SourceGlimp.SourceGlimpPlugin; import info.nightscout.androidaps.plugins.SourceGlimp.SourceGlimpPlugin;
import info.nightscout.androidaps.plugins.SourceMM640g.SourceMM640gPlugin; import info.nightscout.androidaps.plugins.SourceMM640g.SourceMM640gPlugin;
import info.nightscout.androidaps.plugins.SourceNSClient.SourceNSClientPlugin; import info.nightscout.androidaps.plugins.SourceNSClient.SourceNSClientPlugin;
@ -101,6 +98,7 @@ public class MainApp extends Application {
super.onCreate(); super.onCreate();
Fabric.with(this, new Crashlytics()); Fabric.with(this, new Crashlytics());
Fabric.with(this, new Answers()); Fabric.with(this, new Answers());
JodaTimeAndroid.init(this);
Crashlytics.setString("BUILDVERSION", BuildConfig.BUILDVERSION); Crashlytics.setString("BUILDVERSION", BuildConfig.BUILDVERSION);
log.info("Version: " + BuildConfig.VERSION_NAME); log.info("Version: " + BuildConfig.VERSION_NAME);
log.info("BuildVersion: " + BuildConfig.BUILDVERSION); log.info("BuildVersion: " + BuildConfig.BUILDVERSION);
@ -129,7 +127,7 @@ public class MainApp extends Application {
if (Config.DANAR) pluginsList.add(DanaRPlugin.getPlugin()); if (Config.DANAR) pluginsList.add(DanaRPlugin.getPlugin());
if (Config.DANAR) pluginsList.add(DanaRKoreanPlugin.getPlugin()); if (Config.DANAR) pluginsList.add(DanaRKoreanPlugin.getPlugin());
if (Config.DANAR) pluginsList.add(DanaRv2Plugin.getPlugin()); if (Config.DANAR) pluginsList.add(DanaRv2Plugin.getPlugin());
//if (Config.DANAR) pluginsList.add(DanaRSPlugin.getPlugin()); if (Config.DANAR) pluginsList.add(DanaRSPlugin.getPlugin());
pluginsList.add(CareportalPlugin.getPlugin()); pluginsList.add(CareportalPlugin.getPlugin());
if (Config.MDI) pluginsList.add(MDIPlugin.getPlugin()); if (Config.MDI) pluginsList.add(MDIPlugin.getPlugin());
if (Config.VIRTUALPUMP) pluginsList.add(VirtualPumpPlugin.getPlugin()); if (Config.VIRTUALPUMP) pluginsList.add(VirtualPumpPlugin.getPlugin());
@ -138,19 +136,22 @@ public class MainApp extends Application {
if (Config.APS) pluginsList.add(OpenAPSAMAPlugin.getPlugin()); if (Config.APS) pluginsList.add(OpenAPSAMAPlugin.getPlugin());
pluginsList.add(NSProfilePlugin.getPlugin()); pluginsList.add(NSProfilePlugin.getPlugin());
if (Config.OTHERPROFILES) pluginsList.add(SimpleProfilePlugin.getPlugin()); if (Config.OTHERPROFILES) pluginsList.add(SimpleProfilePlugin.getPlugin());
if (Config.OTHERPROFILES) pluginsList.add(LocalProfileFragment.getPlugin()); if (Config.OTHERPROFILES) pluginsList.add(LocalProfilePlugin.getPlugin());
if (Config.OTHERPROFILES) if (Config.OTHERPROFILES)
pluginsList.add(CircadianPercentageProfileFragment.getPlugin()); pluginsList.add(CircadianPercentageProfileFragment.getPlugin());
pluginsList.add(TreatmentsPlugin.getPlugin()); pluginsList.add(TreatmentsPlugin.getPlugin());
if (Config.SAFETY) pluginsList.add(SafetyPlugin.getPlugin()); if (Config.SAFETY) pluginsList.add(SafetyPlugin.getPlugin());
if (Config.APS) pluginsList.add(ObjectivesPlugin.getPlugin()); if (Config.APS) pluginsList.add(ObjectivesPlugin.getPlugin());
if (!Config.NSCLIENT) if (!Config.NSCLIENT && !Config.G5UPLOADER)
pluginsList.add(SourceXdripPlugin.getPlugin()); pluginsList.add(SourceXdripPlugin.getPlugin());
pluginsList.add(SourceNSClientPlugin.getPlugin()); if (!Config.G5UPLOADER)
if (!Config.NSCLIENT) pluginsList.add(SourceNSClientPlugin.getPlugin());
if (!Config.NSCLIENT && !Config.G5UPLOADER)
pluginsList.add(SourceMM640gPlugin.getPlugin()); pluginsList.add(SourceMM640gPlugin.getPlugin());
if (!Config.NSCLIENT) if (!Config.NSCLIENT && !Config.G5UPLOADER)
pluginsList.add(SourceGlimpPlugin.getPlugin()); pluginsList.add(SourceGlimpPlugin.getPlugin());
if (!Config.NSCLIENT)
pluginsList.add(SourceDexcomG5Plugin.getPlugin());
if (Config.SMSCOMMUNICATORENABLED) pluginsList.add(SmsCommunicatorPlugin.getPlugin()); if (Config.SMSCOMMUNICATORENABLED) pluginsList.add(SmsCommunicatorPlugin.getPlugin());
pluginsList.add(FoodPlugin.getPlugin()); pluginsList.add(FoodPlugin.getPlugin());
@ -164,22 +165,25 @@ public class MainApp extends Application {
MainApp.getConfigBuilder().initialize(); MainApp.getConfigBuilder().initialize();
} }
NSUpload.uploadAppStart(); NSUpload.uploadAppStart();
if (MainApp.getConfigBuilder().isClosedModeEnabled()) if (Config.NSCLIENT)
Answers.getInstance().logCustom(new CustomEvent("AppStart-NSClient"));
else if (Config.G5UPLOADER)
Answers.getInstance().logCustom(new CustomEvent("AppStart-G5Uploader"));
else if (Config.PUMPCONTROL)
Answers.getInstance().logCustom(new CustomEvent("AppStart-PumpControl"));
else if (MainApp.getConfigBuilder().isClosedModeEnabled())
Answers.getInstance().logCustom(new CustomEvent("AppStart-ClosedLoop")); Answers.getInstance().logCustom(new CustomEvent("AppStart-ClosedLoop"));
else else
Answers.getInstance().logCustom(new CustomEvent("AppStart")); Answers.getInstance().logCustom(new CustomEvent("AppStart-OpenLoop"));
Thread t = new Thread(new Runnable() { new Thread(new Runnable() {
@Override @Override
public void run() { public void run() {
SystemClock.sleep(5000); SystemClock.sleep(5000);
PumpInterface pump = MainApp.getConfigBuilder(); ConfigBuilderPlugin.getCommandQueue().readStatus("Initialization", null);
if (pump != null)
pump.refreshDataFromPump("Initialization");
startKeepAliveService(); startKeepAliveService();
} }
}, "pump-initialization"); }).start();
t.start();
} }
@ -218,13 +222,21 @@ public class MainApp extends Application {
public void stopKeepAliveService() { public void stopKeepAliveService() {
if (keepAliveReceiver != null) if (keepAliveReceiver != null)
keepAliveReceiver.cancelAlarm(this); KeepAliveReceiver.cancelAlarm(this);
} }
public static Bus bus() { public static Bus bus() {
return sBus; return sBus;
} }
public static String gs(int id) {
return sResources.getString(id);
}
public static String gs(int id, Object... args) {
return sResources.getString(id, args);
}
public static MainApp instance() { public static MainApp instance() {
return sInstance; return sInstance;
} }

View file

@ -1,5 +1,6 @@
package info.nightscout.androidaps; package info.nightscout.androidaps;
import android.content.Intent;
import android.content.SharedPreferences; import android.content.SharedPreferences;
import android.os.Bundle; import android.os.Bundle;
import android.preference.EditTextPreference; import android.preference.EditTextPreference;
@ -31,6 +32,7 @@ import info.nightscout.androidaps.plugins.SensitivityAAPS.SensitivityAAPSPlugin;
import info.nightscout.androidaps.plugins.SensitivityOref0.SensitivityOref0Plugin; import info.nightscout.androidaps.plugins.SensitivityOref0.SensitivityOref0Plugin;
import info.nightscout.androidaps.plugins.SensitivityWeightedAverage.SensitivityWeightedAveragePlugin; import info.nightscout.androidaps.plugins.SensitivityWeightedAverage.SensitivityWeightedAveragePlugin;
import info.nightscout.androidaps.plugins.SmsCommunicator.SmsCommunicatorPlugin; import info.nightscout.androidaps.plugins.SmsCommunicator.SmsCommunicatorPlugin;
import info.nightscout.androidaps.plugins.SourceDexcomG5.SourceDexcomG5Plugin;
import info.nightscout.androidaps.plugins.Wear.WearPlugin; import info.nightscout.androidaps.plugins.Wear.WearPlugin;
import info.nightscout.androidaps.plugins.XDripStatusline.StatuslinePlugin; import info.nightscout.androidaps.plugins.XDripStatusline.StatuslinePlugin;
import info.nightscout.utils.LocaleHelper; import info.nightscout.utils.LocaleHelper;
@ -57,8 +59,9 @@ public class PreferencesActivity extends PreferenceActivity implements SharedPre
if (key.equals("language")) { if (key.equals("language")) {
String lang = sharedPreferences.getString("language", "en"); String lang = sharedPreferences.getString("language", "en");
LocaleHelper.setLocale(getApplicationContext(), lang); LocaleHelper.setLocale(getApplicationContext(), lang);
recreate(); MainApp.bus().post(new EventRefreshGui(true));
MainApp.bus().post(new EventRefreshGui()); //recreate() does not update language so better close settings
finish();
} }
if (key.equals("short_tabtitles")) { if (key.equals("short_tabtitles")) {
MainApp.bus().post(new EventRefreshGui()); MainApp.bus().post(new EventRefreshGui());
@ -126,15 +129,16 @@ public class PreferencesActivity extends PreferenceActivity implements SharedPre
addPreferencesFromResource(id); addPreferencesFromResource(id);
addPreferencesFromResource(R.xml.pref_advanced); addPreferencesFromResource(R.xml.pref_advanced);
} else { } else {
if (!Config.NSCLIENT) { if (!Config.NSCLIENT && !Config.G5UPLOADER) {
addPreferencesFromResource(R.xml.pref_password); addPreferencesFromResource(R.xml.pref_password);
} }
addPreferencesFromResource(R.xml.pref_age); addPreferencesFromResource(R.xml.pref_age);
addPreferencesFromResource(R.xml.pref_language); addPreferencesFromResource(R.xml.pref_language);
if (!Config.NSCLIENT) { if (!Config.NSCLIENT && !Config.G5UPLOADER) {
addPreferencesFromResource(R.xml.pref_quickwizard); addPreferencesFromResource(R.xml.pref_quickwizard);
} }
addPreferencesFromResourceIfEnabled(SourceDexcomG5Plugin.getPlugin(), PluginBase.BGSOURCE);
addPreferencesFromResourceIfEnabled(CareportalPlugin.getPlugin(), PluginBase.GENERAL); addPreferencesFromResourceIfEnabled(CareportalPlugin.getPlugin(), PluginBase.GENERAL);
addPreferencesFromResourceIfEnabled(SafetyPlugin.getPlugin(), PluginBase.CONSTRAINTS); addPreferencesFromResourceIfEnabled(SafetyPlugin.getPlugin(), PluginBase.CONSTRAINTS);
if (Config.APS) { if (Config.APS) {
@ -147,10 +151,6 @@ public class PreferencesActivity extends PreferenceActivity implements SharedPre
addPreferencesFromResourceIfEnabled(SensitivityWeightedAveragePlugin.getPlugin(), PluginBase.SENSITIVITY); addPreferencesFromResourceIfEnabled(SensitivityWeightedAveragePlugin.getPlugin(), PluginBase.SENSITIVITY);
addPreferencesFromResourceIfEnabled(SensitivityOref0Plugin.getPlugin(), PluginBase.SENSITIVITY); addPreferencesFromResourceIfEnabled(SensitivityOref0Plugin.getPlugin(), PluginBase.SENSITIVITY);
if (!Config.NSCLIENT) {
addPreferencesFromResource(R.xml.pref_profile);
}
if (Config.DANAR) { if (Config.DANAR) {
addPreferencesFromResourceIfEnabled(DanaRPlugin.getPlugin(), PluginBase.PUMP); addPreferencesFromResourceIfEnabled(DanaRPlugin.getPlugin(), PluginBase.PUMP);
addPreferencesFromResourceIfEnabled(DanaRKoreanPlugin.getPlugin(), PluginBase.PUMP); addPreferencesFromResourceIfEnabled(DanaRKoreanPlugin.getPlugin(), PluginBase.PUMP);
@ -165,14 +165,16 @@ public class PreferencesActivity extends PreferenceActivity implements SharedPre
} }
} }
addPreferencesFromResourceIfEnabled(VirtualPumpPlugin.getPlugin(), PluginBase.PUMP); if (!Config.NSCLIENT && !Config.G5UPLOADER) {
addPreferencesFromResourceIfEnabled(VirtualPumpPlugin.getPlugin(), PluginBase.PUMP);
}
addPreferencesFromResourceIfEnabled(InsulinOrefFreePeakPlugin.getPlugin(), PluginBase.INSULIN); addPreferencesFromResourceIfEnabled(InsulinOrefFreePeakPlugin.getPlugin(), PluginBase.INSULIN);
addPreferencesFromResourceIfEnabled(NSClientInternalPlugin.getPlugin(), PluginBase.GENERAL); addPreferencesFromResourceIfEnabled(NSClientInternalPlugin.getPlugin(), PluginBase.GENERAL);
addPreferencesFromResourceIfEnabled(SmsCommunicatorPlugin.getPlugin(), PluginBase.GENERAL); addPreferencesFromResourceIfEnabled(SmsCommunicatorPlugin.getPlugin(), PluginBase.GENERAL);
if (!Config.NSCLIENT) { if (!Config.NSCLIENT && !Config.G5UPLOADER) {
addPreferencesFromResource(R.xml.pref_others); addPreferencesFromResource(R.xml.pref_others);
} }
addPreferencesFromResource(R.xml.pref_advanced); addPreferencesFromResource(R.xml.pref_advanced);

View file

@ -15,29 +15,32 @@ import org.slf4j.LoggerFactory;
import info.nightscout.androidaps.Config; import info.nightscout.androidaps.Config;
import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.R; import info.nightscout.androidaps.R;
import info.nightscout.androidaps.data.ProfileStore;
import info.nightscout.androidaps.db.BgReading; import info.nightscout.androidaps.db.BgReading;
import info.nightscout.androidaps.db.CareportalEvent; import info.nightscout.androidaps.db.CareportalEvent;
import info.nightscout.androidaps.events.EventNewBasalProfile; import info.nightscout.androidaps.events.EventNewBasalProfile;
import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin; import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin;
import info.nightscout.androidaps.plugins.ConstraintsObjectives.ObjectivesPlugin; import info.nightscout.androidaps.plugins.ConstraintsObjectives.ObjectivesPlugin;
import info.nightscout.androidaps.plugins.NSClientInternal.data.NSDeviceStatus;
import info.nightscout.androidaps.plugins.NSClientInternal.data.NSMbg; import info.nightscout.androidaps.plugins.NSClientInternal.data.NSMbg;
import info.nightscout.androidaps.plugins.NSClientInternal.data.NSSgv;
import info.nightscout.androidaps.data.ProfileStore;
import info.nightscout.androidaps.plugins.NSClientInternal.data.NSSettingsStatus; import info.nightscout.androidaps.plugins.NSClientInternal.data.NSSettingsStatus;
import info.nightscout.androidaps.plugins.Overview.Notification; import info.nightscout.androidaps.plugins.NSClientInternal.data.NSSgv;
import info.nightscout.androidaps.plugins.Overview.OverviewPlugin; import info.nightscout.androidaps.plugins.Overview.OverviewPlugin;
import info.nightscout.androidaps.plugins.Overview.events.EventDismissNotification; import info.nightscout.androidaps.plugins.Overview.events.EventDismissNotification;
import info.nightscout.androidaps.plugins.Overview.events.EventNewNotification; import info.nightscout.androidaps.plugins.Overview.events.EventNewNotification;
import info.nightscout.androidaps.plugins.Overview.notifications.Notification;
import info.nightscout.androidaps.plugins.ProfileNS.NSProfilePlugin; import info.nightscout.androidaps.plugins.ProfileNS.NSProfilePlugin;
import info.nightscout.androidaps.plugins.ProfileNS.events.EventNSProfileUpdateGUI;
import info.nightscout.androidaps.plugins.PumpDanaR.activities.DanaRNSHistorySync; import info.nightscout.androidaps.plugins.PumpDanaR.activities.DanaRNSHistorySync;
import info.nightscout.androidaps.plugins.SmsCommunicator.events.EventNewSMS; import info.nightscout.androidaps.plugins.SmsCommunicator.events.EventNewSMS;
import info.nightscout.androidaps.plugins.SourceDexcomG5.SourceDexcomG5Plugin;
import info.nightscout.androidaps.plugins.SourceGlimp.SourceGlimpPlugin; import info.nightscout.androidaps.plugins.SourceGlimp.SourceGlimpPlugin;
import info.nightscout.androidaps.plugins.SourceMM640g.SourceMM640gPlugin; import info.nightscout.androidaps.plugins.SourceMM640g.SourceMM640gPlugin;
import info.nightscout.androidaps.plugins.SourceNSClient.SourceNSClientPlugin; import info.nightscout.androidaps.plugins.SourceNSClient.SourceNSClientPlugin;
import info.nightscout.androidaps.plugins.SourceXdrip.SourceXdripPlugin; import info.nightscout.androidaps.plugins.SourceXdrip.SourceXdripPlugin;
import info.nightscout.androidaps.receivers.DataReceiver; import info.nightscout.androidaps.receivers.DataReceiver;
import info.nightscout.androidaps.plugins.NSClientInternal.data.NSDeviceStatus;
import info.nightscout.utils.BundleLogger; import info.nightscout.utils.BundleLogger;
import info.nightscout.utils.NSUpload;
import info.nightscout.utils.SP; import info.nightscout.utils.SP;
@ -48,6 +51,7 @@ public class DataService extends IntentService {
boolean nsClientEnabled = true; boolean nsClientEnabled = true;
boolean mm640gEnabled = false; boolean mm640gEnabled = false;
boolean glimpEnabled = false; boolean glimpEnabled = false;
boolean dexcomG5Enabled = false;
public DataService() { public DataService() {
super("DataService"); super("DataService");
@ -64,26 +68,41 @@ public class DataService extends IntentService {
nsClientEnabled = false; nsClientEnabled = false;
mm640gEnabled = false; mm640gEnabled = false;
glimpEnabled = false; glimpEnabled = false;
dexcomG5Enabled = false;
} else if (ConfigBuilderPlugin.getActiveBgSource().getClass().equals(SourceNSClientPlugin.class)) { } else if (ConfigBuilderPlugin.getActiveBgSource().getClass().equals(SourceNSClientPlugin.class)) {
xDripEnabled = false; xDripEnabled = false;
nsClientEnabled = true; nsClientEnabled = true;
mm640gEnabled = false; mm640gEnabled = false;
glimpEnabled = false; glimpEnabled = false;
dexcomG5Enabled = false;
} else if (ConfigBuilderPlugin.getActiveBgSource().getClass().equals(SourceMM640gPlugin.class)) { } else if (ConfigBuilderPlugin.getActiveBgSource().getClass().equals(SourceMM640gPlugin.class)) {
xDripEnabled = false; xDripEnabled = false;
nsClientEnabled = false; nsClientEnabled = false;
mm640gEnabled = true; mm640gEnabled = true;
glimpEnabled = false; glimpEnabled = false;
dexcomG5Enabled = false;
} else if (ConfigBuilderPlugin.getActiveBgSource().getClass().equals(SourceGlimpPlugin.class)) { } else if (ConfigBuilderPlugin.getActiveBgSource().getClass().equals(SourceGlimpPlugin.class)) {
xDripEnabled = false; xDripEnabled = false;
nsClientEnabled = false; nsClientEnabled = false;
mm640gEnabled = false; mm640gEnabled = false;
glimpEnabled = true; glimpEnabled = true;
dexcomG5Enabled = false;
} else if (ConfigBuilderPlugin.getActiveBgSource().getClass().equals(SourceDexcomG5Plugin.class)) {
xDripEnabled = false;
nsClientEnabled = false;
mm640gEnabled = false;
glimpEnabled = false;
dexcomG5Enabled = true;
} }
boolean isNSProfile = ConfigBuilderPlugin.getActiveProfileInterface().getClass().equals(NSProfilePlugin.class); boolean isNSProfile = ConfigBuilderPlugin.getActiveProfileInterface().getClass().equals(NSProfilePlugin.class);
boolean nsUploadOnly = SP.getBoolean(R.string.key_ns_upload_only, false); boolean acceptNSData = !SP.getBoolean(R.string.key_ns_upload_only, false);
Bundle bundles = intent.getExtras();
if (bundles != null && bundles.containsKey("islocal")) {
acceptNSData = acceptNSData || bundles.getBoolean("islocal");
}
if (intent != null) { if (intent != null) {
final String action = intent.getAction(); final String action = intent.getAction();
@ -99,18 +118,20 @@ public class DataService extends IntentService {
if (glimpEnabled) { if (glimpEnabled) {
handleNewDataFromGlimp(intent); handleNewDataFromGlimp(intent);
} }
} else if (Intents.ACTION_NEW_SGV.equals(action)) { } else if (Intents.DEXCOMG5_BG.equals(action)) {
// always handle SGV if NS-Client is the source if (dexcomG5Enabled) {
if (nsClientEnabled) { handleNewDataFromDexcomG5(intent);
handleNewDataFromNSClient(intent);
} }
} else if (Intents.ACTION_NEW_SGV.equals(action)) {
// always backfill SGV from NS
handleNewDataFromNSClient(intent);
// Objectives 0 // Objectives 0
ObjectivesPlugin.bgIsAvailableInNS = true; ObjectivesPlugin.bgIsAvailableInNS = true;
ObjectivesPlugin.saveProgress(); ObjectivesPlugin.saveProgress();
} else if (isNSProfile && Intents.ACTION_NEW_PROFILE.equals(action) || Intents.ACTION_NEW_DEVICESTATUS.equals(action)) { } else if (isNSProfile && Intents.ACTION_NEW_PROFILE.equals(action) || Intents.ACTION_NEW_DEVICESTATUS.equals(action)) {
// always handle Profile if NSProfile is enabled without looking at nsUploadOnly // always handle Profile if NSProfile is enabled without looking at nsUploadOnly
handleNewDataFromNSClient(intent); handleNewDataFromNSClient(intent);
} else if (!nsUploadOnly && } else if (acceptNSData &&
(Intents.ACTION_NEW_TREATMENT.equals(action) || (Intents.ACTION_NEW_TREATMENT.equals(action) ||
Intents.ACTION_CHANGED_TREATMENT.equals(action) || Intents.ACTION_CHANGED_TREATMENT.equals(action) ||
Intents.ACTION_REMOVED_TREATMENT.equals(action) || Intents.ACTION_REMOVED_TREATMENT.equals(action) ||
@ -187,6 +208,40 @@ public class DataService extends IntentService {
MainApp.getDbHelper().createIfNotExists(bgReading, "GLIMP"); MainApp.getDbHelper().createIfNotExists(bgReading, "GLIMP");
} }
private void handleNewDataFromDexcomG5(Intent intent) {
// onHandleIntent Bundle{ data => [{"m_time":1511939180,"m_trend":"NotComputable","m_value":335}]; android.support.content.wakelockid => 95; }Bundle
Bundle bundle = intent.getExtras();
if (bundle == null) return;
BgReading bgReading = new BgReading();
String data = bundle.getString("data");
log.debug("Received Dexcom Data", data);
try {
JSONArray jsonArray = new JSONArray(data);
log.debug("Received Dexcom Data size:" + jsonArray.length());
for(int i = 0; i < jsonArray.length(); i++) {
JSONObject json = jsonArray.getJSONObject(i);
bgReading.value = json.getInt("m_value");
bgReading.direction = json.getString("m_trend");
bgReading.date = json.getLong("m_time") * 1000L;
bgReading.raw = 0;
boolean isNew = MainApp.getDbHelper().createIfNotExists(bgReading, "DexcomG5");
if (isNew && SP.getBoolean(R.string.key_dexcomg5_nsupload, false)) {
NSUpload.uploadBg(bgReading);
}
if (isNew && SP.getBoolean(R.string.key_dexcomg5_xdripupload, false)) {
NSUpload.sendToXdrip(bgReading);
}
}
} catch (JSONException e) {
e.printStackTrace();
}
}
private void handleNewDataFromMM640g(Intent intent) { private void handleNewDataFromMM640g(Intent intent) {
Bundle bundle = intent.getExtras(); Bundle bundle = intent.getExtras();
if (bundle == null) return; if (bundle == null) return;
@ -250,7 +305,7 @@ public class DataService extends IntentService {
log.error("Unhandled exception", e); log.error("Unhandled exception", e);
} }
if (ConfigBuilderPlugin.nightscoutVersionCode < Config.SUPPORTEDNSVERSION) { if (ConfigBuilderPlugin.nightscoutVersionCode < Config.SUPPORTEDNSVERSION) {
Notification notification = new Notification(Notification.OLD_NS, MainApp.sResources.getString(R.string.unsupportednsversion), Notification.URGENT); Notification notification = new Notification(Notification.OLD_NS, MainApp.sResources.getString(R.string.unsupportednsversion), Notification.NORMAL);
MainApp.bus().post(new EventNewNotification(notification)); MainApp.bus().post(new EventNewNotification(notification));
} else { } else {
MainApp.bus().post(new EventDismissNotification(Notification.OLD_NS)); MainApp.bus().post(new EventDismissNotification(Notification.OLD_NS));
@ -311,8 +366,10 @@ public class DataService extends IntentService {
String profile = bundles.getString("profile"); String profile = bundles.getString("profile");
ProfileStore profileStore = new ProfileStore(new JSONObject(profile)); ProfileStore profileStore = new ProfileStore(new JSONObject(profile));
NSProfilePlugin.storeNewProfile(profileStore); NSProfilePlugin.storeNewProfile(profileStore);
MainApp.bus().post(new EventNewBasalProfile()); MainApp.bus().post(new EventNSProfileUpdateGUI());
// if there are no profile switches this should lead to profile update
if (MainApp.getConfigBuilder().getProfileSwitchesFromHistory().size() == 0)
MainApp.bus().post(new EventNewBasalProfile());
if (Config.logIncommingData) if (Config.logIncommingData)
log.debug("Received profileStore: " + activeProfile + " " + profile); log.debug("Received profileStore: " + activeProfile + " " + profile);
} catch (JSONException e) { } catch (JSONException e) {

View file

@ -45,4 +45,6 @@ public interface Intents {
String ACTION_REMOTE_CALIBRATION = "com.eveningoutpost.dexdrip.NewCalibration"; String ACTION_REMOTE_CALIBRATION = "com.eveningoutpost.dexdrip.NewCalibration";
String GLIMP_BG = "it.ct.glicemia.ACTION_GLUCOSE_MEASURED"; String GLIMP_BG = "it.ct.glicemia.ACTION_GLUCOSE_MEASURED";
String DEXCOMG5_BG = "com.dexcom.cgm.DATA";
} }

View file

@ -64,14 +64,21 @@ public class GlucoseStatus {
return this; return this;
} }
@Nullable @Nullable
public static GlucoseStatus getGlucoseStatusData() { public static GlucoseStatus getGlucoseStatusData(){
return getGlucoseStatusData(false);
}
@Nullable
public static GlucoseStatus getGlucoseStatusData(boolean allowOldData) {
// load 45min // load 45min
long fromtime = (long) (System.currentTimeMillis() - 60 * 1000L * 45); long fromtime = (long) (System.currentTimeMillis() - 60 * 1000L * 45);
List<BgReading> data = MainApp.getDbHelper().getBgreadingsDataFromTime(fromtime, false); List<BgReading> data = MainApp.getDbHelper().getBgreadingsDataFromTime(fromtime, false);
int sizeRecords = data.size(); int sizeRecords = data.size();
if (sizeRecords < 1 || data.get(0).date < System.currentTimeMillis() - 7 * 60 * 1000L) { if (sizeRecords < 1 || (data.get(0).date < System.currentTimeMillis() - 7 * 60 * 1000L && !allowOldData)) {
return null; return null;
} }

View file

@ -12,4 +12,26 @@ public class Iob {
activityContrib += iob.activityContrib; activityContrib += iob.activityContrib;
return this; return this;
} }
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Iob iob = (Iob) o;
if (Double.compare(iob.iobContrib, iobContrib) != 0) return false;
return Double.compare(iob.activityContrib, activityContrib) == 0;
}
@Override
public int hashCode() {
int result;
long temp;
temp = Double.doubleToLongBits(iobContrib);
result = (int) (temp ^ (temp >>> 32));
temp = Double.doubleToLongBits(activityContrib);
result = 31 * result + (int) (temp ^ (temp >>> 32));
return result;
}
} }

View file

@ -12,17 +12,19 @@ import org.slf4j.LoggerFactory;
import java.text.DecimalFormat; import java.text.DecimalFormat;
import java.util.Calendar; import java.util.Calendar;
import java.util.Date;
import java.util.TimeZone; import java.util.TimeZone;
import info.nightscout.androidaps.Constants; import info.nightscout.androidaps.Constants;
import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.R; import info.nightscout.androidaps.R;
import info.nightscout.androidaps.plugins.Overview.Notification; import info.nightscout.androidaps.interfaces.PumpDescription;
import info.nightscout.androidaps.interfaces.PumpInterface;
import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin;
import info.nightscout.androidaps.plugins.Overview.events.EventDismissNotification; import info.nightscout.androidaps.plugins.Overview.events.EventDismissNotification;
import info.nightscout.androidaps.plugins.Overview.events.EventNewNotification; import info.nightscout.androidaps.plugins.Overview.events.EventNewNotification;
import info.nightscout.androidaps.plugins.Overview.notifications.Notification;
import info.nightscout.utils.DateUtil;
import info.nightscout.utils.DecimalFormatter; import info.nightscout.utils.DecimalFormatter;
import info.nightscout.utils.SafeParse;
import info.nightscout.utils.ToastUtils; import info.nightscout.utils.ToastUtils;
public class Profile { public class Profile {
@ -46,6 +48,9 @@ public class Profile {
private int percentage = 100; private int percentage = 100;
private int timeshift = 0; private int timeshift = 0;
private boolean isValid = true;
private boolean isValidated = false;
public Profile(JSONObject json, String units) { public Profile(JSONObject json, String units) {
this(json, 100, 0); this(json, 100, 0);
if (this.units == null) { if (this.units == null) {
@ -118,7 +123,9 @@ public class Profile {
} }
} catch (JSONException e) { } catch (JSONException e) {
log.error("Unhandled exception", e); log.error("Unhandled exception", e);
ToastUtils.showToastInUiThread(MainApp.instance().getApplicationContext(), MainApp.sResources.getString(R.string.invalidprofile)); ToastUtils.showToastInUiThread(MainApp.instance().getApplicationContext(), MainApp.gs(R.string.invalidprofile));
isValid = false;
isValidated = true;
} }
} }
@ -161,12 +168,20 @@ public class Profile {
LongSparseArray<Double> sparse = new LongSparseArray<>(); LongSparseArray<Double> sparse = new LongSparseArray<>();
for (Integer index = 0; index < array.length(); index++) { for (Integer index = 0; index < array.length(); index++) {
try { try {
JSONObject o = array.getJSONObject(index); final JSONObject o = array.getJSONObject(index);
long tas = getShitfTimeSecs((int) o.getLong("timeAsSeconds")); long tas = 0;
Double value = o.getDouble("value") * multiplier; try {
tas = getShitfTimeSecs((int) o.getLong("timeAsSeconds"));
} catch (JSONException e) {
String time = o.getString("time");
tas = getShitfTimeSecs(DateUtil.toSeconds(time));
//log.debug(">>>>>>>>>>>> Used recalculated timeAsSecons: " + time + " " + tas);
}
double value = o.getDouble("value") * multiplier;
sparse.put(tas, value); sparse.put(tas, value);
} catch (JSONException e) { } catch (JSONException e) {
log.error("Unhandled exception", e); log.error("Unhandled exception", e);
log.error(json.toString());
} }
} }
@ -178,6 +193,72 @@ public class Profile {
return sparse; return sparse;
} }
public synchronized boolean isValid(String from) {
if (!isValid)
return false;
if (!isValidated) {
if (basal_v == null)
basal_v = convertToSparseArray(basal);
validate(basal_v);
if (isf_v == null)
isf_v = convertToSparseArray(isf);
validate(isf_v);
if (ic_v == null)
ic_v = convertToSparseArray(ic);
validate(ic_v);
if (targetLow_v == null)
targetLow_v = convertToSparseArray(targetLow);
validate(targetLow_v);
if (targetHigh_v == null)
targetHigh_v = convertToSparseArray(targetHigh);
validate(targetHigh_v);
isValidated = true;
}
if (isValid) {
// Check for hours alignment
for (int index = 0; index < basal_v.size(); index++) {
long secondsFromMidnight = basal_v.keyAt(index);
if (secondsFromMidnight % 3600 != 0) {
Notification notification = new Notification(Notification.BASAL_PROFILE_NOT_ALIGNED_TO_HOURS, String.format(MainApp.gs(R.string.basalprofilenotaligned), from), Notification.NORMAL);
MainApp.bus().post(new EventNewNotification(notification));
}
}
// Check for minimal basal value
PumpInterface pump = ConfigBuilderPlugin.getActivePump();
if (pump != null) {
PumpDescription description = pump.getPumpDescription();
for (int i = 0; i < basal_v.size(); i++) {
if (basal_v.valueAt(i) < description.basalMinimumRate) {
basal_v.setValueAt(i, description.basalMinimumRate);
MainApp.bus().post(new EventNewNotification(new Notification(Notification.MINIMAL_BASAL_VALUE_REPLACED, String.format(MainApp.gs(R.string.minimalbasalvaluereplaced), from), Notification.NORMAL)));
}
}
} else {
// if pump not available (at start)
// do not store converted array
basal_v = null;
isValidated = false;
}
}
return isValid;
}
private void validate(LongSparseArray array) {
if (array.size() == 0) {
isValid = false;
return;
}
for (int index = 0; index < array.size(); index++) {
if (array.valueAt(index).equals(0d)) {
isValid = false;
return;
}
}
}
private Double getValueToTime(JSONArray array, Integer timeAsSeconds) { private Double getValueToTime(JSONArray array, Integer timeAsSeconds) {
Double lastValue = null; Double lastValue = null;
@ -324,9 +405,10 @@ public class Profile {
return getBasal(secondsFromMidnight(time)); return getBasal(secondsFromMidnight(time));
} }
public Double getBasal(Integer timeAsSeconds) { public synchronized Double getBasal(Integer timeAsSeconds) {
if (basal_v == null) if (basal_v == null) {
basal_v = convertToSparseArray(basal); basal_v = convertToSparseArray(basal);
}
return getValueToTime(basal_v, timeAsSeconds); return getValueToTime(basal_v, timeAsSeconds);
} }
@ -344,7 +426,9 @@ public class Profile {
public Double value; public Double value;
} }
public BasalValue[] getBasalValues() { public synchronized BasalValue[] getBasalValues() {
if (basal_v == null)
basal_v = convertToSparseArray(basal);
BasalValue[] ret = new BasalValue[basal_v.size()]; BasalValue[] ret = new BasalValue[basal_v.size()];
for (Integer index = 0; index < basal_v.size(); index++) { for (Integer index = 0; index < basal_v.size(); index++) {

View file

@ -31,7 +31,8 @@ public class ProfileIntervals<T extends Interval> {
public synchronized void add(List<T> list) { public synchronized void add(List<T> list) {
for (T interval : list) { for (T interval : list) {
rawData.put(interval.start(), interval); if (interval.isValid())
rawData.put(interval.start(), interval);
} }
merge(); merge();
} }
@ -62,7 +63,7 @@ public class ProfileIntervals<T extends Interval> {
public synchronized List<T> getReversedList() { public synchronized List<T> getReversedList() {
List<T> list = new ArrayList<>(); List<T> list = new ArrayList<>();
for (int i = rawData.size() -1; i>=0; i--) for (int i = rawData.size() - 1; i >= 0; i--)
list.add(rawData.valueAt(i)); list.add(rawData.valueAt(i));
return list; return list;
} }

View file

@ -1,4 +1,4 @@
package info.nightscout.androidaps.plugins.Overview; package info.nightscout.androidaps.data;
import android.content.SharedPreferences; import android.content.SharedPreferences;
import android.preference.PreferenceManager; import android.preference.PreferenceManager;
@ -9,11 +9,7 @@ import org.json.JSONObject;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import java.util.Date;
import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.data.Profile;
import info.nightscout.utils.DateUtil;
/** /**
* Created by mike on 12.10.2016. * Created by mike on 12.10.2016.
@ -22,84 +18,7 @@ import info.nightscout.utils.DateUtil;
public class QuickWizard { public class QuickWizard {
private static Logger log = LoggerFactory.getLogger(QuickWizard.class); private static Logger log = LoggerFactory.getLogger(QuickWizard.class);
public class QuickWizardEntry { private JSONArray storage = new JSONArray();
public JSONObject storage;
public int position;
/*
{
buttonText: "Meal",
carbs: 36,
validFrom: 8 * 60 * 60, // seconds from midnight
validTo: 9 * 60 * 60, // seconds from midnight
}
*/
public QuickWizardEntry() {
String emptyData = "{\"buttonText\":\"\",\"carbs\":0,\"validFrom\":0,\"validTo\":86340}";
try {
storage = new JSONObject(emptyData);
} catch (JSONException e) {
log.error("Unhandled exception", e);
}
position = -1;
}
public QuickWizardEntry(JSONObject entry, int position) {
storage = entry;
this.position = position;
}
public Boolean isActive() {
return Profile.secondsFromMidnight() >= validFrom() && Profile.secondsFromMidnight() <= validTo();
}
public String buttonText() {
try {
return storage.getString("buttonText");
} catch (JSONException e) {
log.error("Unhandled exception", e);
}
return "";
}
public Integer carbs() {
try {
return storage.getInt("carbs");
} catch (JSONException e) {
log.error("Unhandled exception", e);
}
return 0;
}
public Date validFromDate() {
return DateUtil.toDate(validFrom());
}
public Date validToDate() {
return DateUtil.toDate(validTo());
}
public Integer validFrom() {
try {
return storage.getInt("validFrom");
} catch (JSONException e) {
log.error("Unhandled exception", e);
}
return 0;
}
public Integer validTo() {
try {
return storage.getInt("validTo");
} catch (JSONException e) {
log.error("Unhandled exception", e);
}
return 0;
}
}
JSONArray storage = new JSONArray();
public void setData(JSONArray newData) { public void setData(JSONArray newData) {
storage = newData; storage = newData;

View file

@ -0,0 +1,247 @@
package info.nightscout.androidaps.data;
import org.json.JSONException;
import org.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.Date;
import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.R;
import info.nightscout.androidaps.db.BgReading;
import info.nightscout.androidaps.db.TempTarget;
import info.nightscout.androidaps.interfaces.TreatmentsInterface;
import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin;
import info.nightscout.androidaps.plugins.IobCobCalculator.AutosensData;
import info.nightscout.androidaps.plugins.IobCobCalculator.IobCobCalculatorPlugin;
import info.nightscout.androidaps.plugins.Loop.LoopPlugin;
import info.nightscout.utils.BolusWizard;
import info.nightscout.utils.DateUtil;
import info.nightscout.utils.SP;
/**
* Created by mike on 25.12.2017.
*/
public class QuickWizardEntry {
private static Logger log = LoggerFactory.getLogger(QuickWizardEntry.class);
public JSONObject storage;
public int position;
public static final int YES = 0;
public static final int NO = 1;
public static final int POSITIVE_ONLY = 2;
public static final int NEGATIVE_ONLY = 3;
/*
{
buttonText: "Meal",
carbs: 36,
validFrom: 8 * 60 * 60, // seconds from midnight
validTo: 9 * 60 * 60, // seconds from midnight
useBG: 0,
useCOB: 0,
useBolusIOB: 0,
useBasalIOB: 0,
useTrend: 0,
useSuperBolus: 0,
useTemptarget: 0
}
*/
public QuickWizardEntry() {
String emptyData = "{\"buttonText\":\"\",\"carbs\":0,\"validFrom\":0,\"validTo\":86340}";
try {
storage = new JSONObject(emptyData);
} catch (JSONException e) {
log.error("Unhandled exception", e);
}
position = -1;
}
public QuickWizardEntry(JSONObject entry, int position) {
storage = entry;
this.position = position;
}
public Boolean isActive() {
return Profile.secondsFromMidnight() >= validFrom() && Profile.secondsFromMidnight() <= validTo();
}
public BolusWizard doCalc(Profile profile, TempTarget tempTarget, BgReading lastBG, boolean _synchronized) {
BolusWizard wizard = new BolusWizard();
//BG
double bg = 0;
if (lastBG != null && useBG() == YES) {
bg = lastBG.valueToUnits(profile.getUnits());
}
// COB
double cob = 0d;
AutosensData autosensData;
if (_synchronized)
autosensData = IobCobCalculatorPlugin.getLastAutosensDataSynchronized("QuickWizard COB");
else
autosensData = IobCobCalculatorPlugin.getLastAutosensData("QuickWizard COB");
if (autosensData != null && useCOB() == YES) {
cob = autosensData.cob;
}
// Temp target
if (useTempTarget() == NO) {
tempTarget = null;
}
// Bolus IOB
boolean bolusIOB = false;
if (useBolusIOB() == YES) {
bolusIOB = true;
}
// Basal IOB
TreatmentsInterface treatments = MainApp.getConfigBuilder();
treatments.updateTotalIOBTempBasals();
IobTotal basalIob = treatments.getLastCalculationTempBasals().round();
boolean basalIOB = false;
if (useBasalIOB() == YES) {
basalIOB = true;
} else if (useBasalIOB() == POSITIVE_ONLY && basalIob.iob > 0) {
basalIOB = true;
} else if (useBasalIOB() == NEGATIVE_ONLY && basalIob.iob < 0) {
basalIOB = true;
}
// SuperBolus
boolean superBolus = false;
if (useSuperBolus() == YES && SP.getBoolean(R.string.key_usesuperbolus, false)) {
superBolus = true;
}
final LoopPlugin activeloop = ConfigBuilderPlugin.getActiveLoop();
if (activeloop != null && activeloop.isEnabled(activeloop.getType()) && activeloop.isSuperBolus())
superBolus = false;
// Trend
GlucoseStatus glucoseStatus = GlucoseStatus.getGlucoseStatusData();
boolean trend = false;
if (useTrend() == YES) {
trend = true;
} else if (useTrend() == POSITIVE_ONLY && glucoseStatus != null && glucoseStatus.short_avgdelta > 0) {
trend = true;
} else if (useTrend() == NEGATIVE_ONLY && glucoseStatus != null && glucoseStatus.short_avgdelta < 0) {
trend = true;
}
wizard.doCalc(profile, tempTarget, carbs(), cob, bg, 0d, bolusIOB, basalIOB, superBolus, trend);
return wizard;
}
public String buttonText() {
try {
return storage.getString("buttonText");
} catch (JSONException e) {
log.error("Unhandled exception", e);
}
return "";
}
public Integer carbs() {
try {
return storage.getInt("carbs");
} catch (JSONException e) {
log.error("Unhandled exception", e);
}
return 0;
}
public Date validFromDate() {
return DateUtil.toDate(validFrom());
}
public Date validToDate() {
return DateUtil.toDate(validTo());
}
public Integer validFrom() {
try {
return storage.getInt("validFrom");
} catch (JSONException e) {
log.error("Unhandled exception", e);
}
return 0;
}
public Integer validTo() {
try {
return storage.getInt("validTo");
} catch (JSONException e) {
log.error("Unhandled exception", e);
}
return 0;
}
public int useBG() {
try {
return storage.getInt("useBG");
} catch (JSONException e) {
//log.error("Unhandled exception", e);
}
return YES;
}
public int useCOB() {
try {
return storage.getInt("useCOB");
} catch (JSONException e) {
//log.error("Unhandled exception", e);
}
return NO;
}
public int useBolusIOB() {
try {
return storage.getInt("useBolusIOB");
} catch (JSONException e) {
//log.error("Unhandled exception", e);
}
return YES;
}
public int useBasalIOB() {
try {
return storage.getInt("useBasalIOB");
} catch (JSONException e) {
//log.error("Unhandled exception", e);
}
return YES;
}
public int useTrend() {
try {
return storage.getInt("useTrend");
} catch (JSONException e) {
//log.error("Unhandled exception", e);
}
return NO;
}
public int useSuperBolus() {
try {
return storage.getInt("useSuperBolus");
} catch (JSONException e) {
//log.error("Unhandled exception", e);
}
return NO;
}
public int useTempTarget() {
try {
return storage.getInt("useTempTarget");
} catch (JSONException e) {
//log.error("Unhandled exception", e);
}
return NO;
}
}

View file

@ -53,6 +53,7 @@ public class BgReading implements DataPointWithLabelInterface {
value = sgv.getMgdl(); value = sgv.getMgdl();
raw = sgv.getFiltered() != null ? sgv.getFiltered() : value; raw = sgv.getFiltered() != null ? sgv.getFiltered() : value;
direction = sgv.getDirection(); direction = sgv.getDirection();
_id = sgv.getId();
} }
public Double valueToUnits(String units) { public Double valueToUnits(String units) {
@ -96,7 +97,9 @@ public class BgReading implements DataPointWithLabelInterface {
direction.compareTo("NOT COMPUTABLE") == 0 || direction.compareTo("NOT COMPUTABLE") == 0 ||
direction.compareTo("OUT_OF_RANGE") == 0 || direction.compareTo("OUT_OF_RANGE") == 0 ||
direction.compareTo("OUT OF RANGE") == 0 || direction.compareTo("OUT OF RANGE") == 0 ||
direction.compareTo("NONE") == 0) { direction.compareTo("NONE") == 0 ||
direction.compareTo("NotComputable") == 0
) {
return true; return true;
} else { } else {
return false; return false;

View file

@ -191,6 +191,17 @@ public class CareportalEvent implements DataPointWithLabelInterface {
return Translator.translate(eventType); return Translator.translate(eventType);
} }
public String getNotes() {
try {
JSONObject object = new JSONObject(json);
if (object.has("notes"))
return object.getString("notes");
} catch (JSONException e) {
log.error("Unhandled exception", e);
}
return "";
}
@Override @Override
public long getDuration() { public long getDuration() {
try { try {

View file

@ -30,7 +30,9 @@ import java.util.concurrent.TimeUnit;
import info.nightscout.androidaps.Config; import info.nightscout.androidaps.Config;
import info.nightscout.androidaps.Constants; import info.nightscout.androidaps.Constants;
import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.R;
import info.nightscout.androidaps.data.Profile; import info.nightscout.androidaps.data.Profile;
import info.nightscout.androidaps.data.ProfileStore;
import info.nightscout.androidaps.events.EventCareportalEventChange; import info.nightscout.androidaps.events.EventCareportalEventChange;
import info.nightscout.androidaps.events.EventExtendedBolusChange; import info.nightscout.androidaps.events.EventExtendedBolusChange;
import info.nightscout.androidaps.events.EventFoodDatabaseChanged; import info.nightscout.androidaps.events.EventFoodDatabaseChanged;
@ -43,9 +45,15 @@ import info.nightscout.androidaps.events.EventReloadTreatmentData;
import info.nightscout.androidaps.events.EventTempBasalChange; import info.nightscout.androidaps.events.EventTempBasalChange;
import info.nightscout.androidaps.events.EventTempTargetChange; import info.nightscout.androidaps.events.EventTempTargetChange;
import info.nightscout.androidaps.events.EventTreatmentChange; import info.nightscout.androidaps.events.EventTreatmentChange;
import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin;
import info.nightscout.androidaps.plugins.IobCobCalculator.events.EventNewHistoryData; import info.nightscout.androidaps.plugins.IobCobCalculator.events.EventNewHistoryData;
import info.nightscout.androidaps.plugins.Overview.events.EventNewNotification;
import info.nightscout.androidaps.plugins.Overview.notifications.Notification;
import info.nightscout.androidaps.plugins.PumpDanaR.activities.DanaRNSHistorySync; import info.nightscout.androidaps.plugins.PumpDanaR.activities.DanaRNSHistorySync;
import info.nightscout.androidaps.plugins.PumpVirtual.VirtualPumpPlugin; import info.nightscout.androidaps.plugins.PumpVirtual.VirtualPumpPlugin;
import info.nightscout.utils.DateUtil;
import info.nightscout.utils.NSUpload;
import info.nightscout.utils.PercentageSplitter;
public class DatabaseHelper extends OrmLiteSqliteOpenHelper { public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
private static Logger log = LoggerFactory.getLogger(DatabaseHelper.class); private static Logger log = LoggerFactory.getLogger(DatabaseHelper.class);
@ -343,7 +351,7 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
} }
// ------------------- BgReading handling ----------------------- // ------------------- BgReading handling -----------------------
public void createIfNotExists(BgReading bgReading, String from) { public boolean createIfNotExists(BgReading bgReading, String from) {
try { try {
bgReading.date = roundDateToSec(bgReading.date); bgReading.date = roundDateToSec(bgReading.date);
BgReading old = getDaoBgReadings().queryForId(bgReading.date); BgReading old = getDaoBgReadings().queryForId(bgReading.date);
@ -351,18 +359,29 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
getDaoBgReadings().create(bgReading); getDaoBgReadings().create(bgReading);
log.debug("BG: New record from: " + from + " " + bgReading.toString()); log.debug("BG: New record from: " + from + " " + bgReading.toString());
scheduleBgChange(); scheduleBgChange();
return; return true;
} }
if (!old.isEqual(bgReading)) { if (!old.isEqual(bgReading)) {
log.debug("BG: Similiar found: " + old.toString());
old.copyFrom(bgReading); old.copyFrom(bgReading);
getDaoBgReadings().update(old); getDaoBgReadings().update(old);
log.debug("BG: Updating record from: " + from + " " + old.toString()); log.debug("BG: Updating record from: " + from + " New data: " + old.toString());
scheduleBgChange(); scheduleBgChange();
return; return false;
} }
} catch (SQLException e) { } catch (SQLException e) {
log.error("Unhandled exception", e); log.error("Unhandled exception", e);
} }
return false;
}
public void update(BgReading bgReading) {
bgReading.date = roundDateToSec(bgReading.date);
try {
getDaoBgReadings().update(bgReading);
} catch (SQLException e) {
e.printStackTrace();
}
} }
private static void scheduleBgChange() { private static void scheduleBgChange() {
@ -395,7 +414,7 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
QueryBuilder<BgReading, Long> queryBuilder = daoBgReadings.queryBuilder(); QueryBuilder<BgReading, Long> queryBuilder = daoBgReadings.queryBuilder();
queryBuilder.orderBy("date", false); queryBuilder.orderBy("date", false);
queryBuilder.limit(1L); queryBuilder.limit(1L);
queryBuilder.where().gt("value", 38); queryBuilder.where().gt("value", 38).and().eq("isValid", true);
PreparedQuery<BgReading> preparedQuery = queryBuilder.prepare(); PreparedQuery<BgReading> preparedQuery = queryBuilder.prepare();
bgList = daoBgReadings.query(preparedQuery); bgList = daoBgReadings.query(preparedQuery);
@ -433,7 +452,24 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
QueryBuilder<BgReading, Long> queryBuilder = daoBgreadings.queryBuilder(); QueryBuilder<BgReading, Long> queryBuilder = daoBgreadings.queryBuilder();
queryBuilder.orderBy("date", ascending); queryBuilder.orderBy("date", ascending);
Where where = queryBuilder.where(); Where where = queryBuilder.where();
where.ge("date", mills).and().gt("value", 38); where.ge("date", mills).and().gt("value", 38).and().eq("isValid", true);
PreparedQuery<BgReading> preparedQuery = queryBuilder.prepare();
bgReadings = daoBgreadings.query(preparedQuery);
return bgReadings;
} catch (SQLException e) {
log.error("Unhandled exception", e);
}
return new ArrayList<BgReading>();
}
public List<BgReading> getAllBgreadingsDataFromTime(long mills, boolean ascending) {
try {
Dao<BgReading, Long> daoBgreadings = getDaoBgReadings();
List<BgReading> bgReadings;
QueryBuilder<BgReading, Long> queryBuilder = daoBgreadings.queryBuilder();
queryBuilder.orderBy("date", ascending);
Where where = queryBuilder.where();
where.ge("date", mills);
PreparedQuery<BgReading> preparedQuery = queryBuilder.prepare(); PreparedQuery<BgReading> preparedQuery = queryBuilder.prepare();
bgReadings = daoBgreadings.query(preparedQuery); bgReadings = daoBgreadings.query(preparedQuery);
return bgReadings; return bgReadings;
@ -471,7 +507,7 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
return 0; return 0;
} }
public int deleteDbRequestbyMongoId(String action, String id) { public void deleteDbRequestbyMongoId(String action, String id) {
try { try {
QueryBuilder<DbRequest, String> queryBuilder = getDaoDbRequest().queryBuilder(); QueryBuilder<DbRequest, String> queryBuilder = getDaoDbRequest().queryBuilder();
Where where = queryBuilder.where(); Where where = queryBuilder.where();
@ -479,16 +515,13 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
queryBuilder.limit(10L); queryBuilder.limit(10L);
PreparedQuery<DbRequest> preparedQuery = queryBuilder.prepare(); PreparedQuery<DbRequest> preparedQuery = queryBuilder.prepare();
List<DbRequest> dbList = getDaoDbRequest().query(preparedQuery); List<DbRequest> dbList = getDaoDbRequest().query(preparedQuery);
if (dbList.size() != 1) { log.error("deleteDbRequestbyMongoId query size: " + dbList.size());
log.error("deleteDbRequestbyMongoId query size: " + dbList.size()); for (DbRequest r : dbList) {
} else { delete(r);
//log.debug("Treatment findTreatmentById found: " + trList.get(0).log());
return delete(dbList.get(0));
} }
} catch (SQLException e) { } catch (SQLException e) {
log.error("Unhandled exception", e); log.error("Unhandled exception", e);
} }
return 0;
} }
public void deleteAllDbRequests() { public void deleteAllDbRequests() {
@ -1351,7 +1384,7 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
return; return;
} }
extendedBolus.date = trJson.getLong("mills"); extendedBolus.date = trJson.getLong("mills");
extendedBolus.durationInMinutes = trJson.getInt("duration"); extendedBolus.durationInMinutes = trJson.has("duration") ? trJson.getInt("duration") : 0;
extendedBolus.insulin = trJson.getDouble("relative"); extendedBolus.insulin = trJson.getDouble("relative");
extendedBolus._id = trJson.getString("_id"); extendedBolus._id = trJson.getString("_id");
createOrUpdate(extendedBolus); createOrUpdate(extendedBolus);
@ -1437,7 +1470,21 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
} catch (SQLException e) { } catch (SQLException e) {
log.error("Unhandled exception", e); log.error("Unhandled exception", e);
} }
return new ArrayList<CareportalEvent>(); return new ArrayList<>();
}
public List<CareportalEvent> getCareportalEventsFromTime(boolean ascending) {
try {
List<CareportalEvent> careportalEvents;
QueryBuilder<CareportalEvent, Long> queryBuilder = getDaoCareportalEvents().queryBuilder();
queryBuilder.orderBy("date", ascending);
PreparedQuery<CareportalEvent> preparedQuery = queryBuilder.prepare();
careportalEvents = getDaoCareportalEvents().query(preparedQuery);
return careportalEvents;
} catch (SQLException e) {
log.error("Unhandled exception", e);
}
return new ArrayList<>();
} }
public void deleteCareportalEventById(String _id) { public void deleteCareportalEventById(String _id) {
@ -1570,6 +1617,8 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
} }
} }
} }
// look for already added percentage from NS
profileSwitch.profileName = PercentageSplitter.pureName(profileSwitch.profileName);
getDaoProfileSwitch().create(profileSwitch); getDaoProfileSwitch().create(profileSwitch);
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();
@ -1643,6 +1692,19 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
profileSwitch.percentage = trJson.getInt("percentage"); profileSwitch.percentage = trJson.getInt("percentage");
if (trJson.has("profileJson")) if (trJson.has("profileJson"))
profileSwitch.profileJson = trJson.getString("profileJson"); profileSwitch.profileJson = trJson.getString("profileJson");
else {
ProfileStore store = ConfigBuilderPlugin.getActiveProfileInterface().getProfile();
Profile profile = store.getSpecificProfile(profileSwitch.profileName);
if (profile != null) {
profileSwitch.profileJson = profile.getData().toString();
log.debug("Profile switch prefilled with JSON from local store");
// Update data in NS
NSUpload.updateProfileSwitch(profileSwitch);
} else {
log.debug("JSON for profile switch doesn't exist. Ignoring: " + trJson.toString());
return;
}
}
if (trJson.has("profilePlugin")) if (trJson.has("profilePlugin"))
profileSwitch.profilePlugin = trJson.getString("profilePlugin"); profileSwitch.profilePlugin = trJson.getString("profilePlugin");
createOrUpdate(profileSwitch); createOrUpdate(profileSwitch);

View file

@ -147,6 +147,11 @@ public class ExtendedBolus implements Interval, DataPointWithLabelInterface {
return durationInMinutes == 0; return durationInMinutes == 0;
} }
@Override
public boolean isValid() {
return true;
}
// -------- Interval interface end --------- // -------- Interval interface end ---------
public String log() { public String log() {

View file

@ -70,7 +70,7 @@ public class FoodHelper {
public boolean createOrUpdate(Food food) { public boolean createOrUpdate(Food food) {
try { try {
// find by NS _id // find by NS _id
if (food._id != null) { if (food._id != null && !food._id.equals("")) {
Food old; Food old;
QueryBuilder<Food, Long> queryBuilder = getDaoFood().queryBuilder(); QueryBuilder<Food, Long> queryBuilder = getDaoFood().queryBuilder();
@ -90,12 +90,13 @@ public class FoodHelper {
} else { } else {
return false; return false;
} }
} else {
getDaoFood().createOrUpdate(food);
log.debug("FOOD: New record: " + food.toString());
scheduleFoodChange();
return true;
} }
} }
getDaoFood().createOrUpdate(food);
log.debug("FOOD: New record: " + food.toString());
scheduleFoodChange();
return true;
} catch (SQLException e) { } catch (SQLException e) {
log.error("Unhandled exception", e); log.error("Unhandled exception", e);
} }

View file

@ -1,6 +1,7 @@
package info.nightscout.androidaps.db; package info.nightscout.androidaps.db;
import android.graphics.Color; import android.graphics.Color;
import android.support.annotation.Nullable;
import com.j256.ormlite.field.DatabaseField; import com.j256.ormlite.field.DatabaseField;
import com.j256.ormlite.table.DatabaseTable; import com.j256.ormlite.table.DatabaseTable;
@ -12,10 +13,14 @@ import org.slf4j.LoggerFactory;
import java.util.Objects; import java.util.Objects;
import info.nightscout.androidaps.MainApp;
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.plugins.Overview.events.EventNewNotification;
import info.nightscout.androidaps.plugins.Overview.graphExtensions.DataPointWithLabelInterface; import info.nightscout.androidaps.plugins.Overview.graphExtensions.DataPointWithLabelInterface;
import info.nightscout.androidaps.plugins.Overview.graphExtensions.PointsWithLabelGraphSeries; import info.nightscout.androidaps.plugins.Overview.graphExtensions.PointsWithLabelGraphSeries;
import info.nightscout.androidaps.plugins.Overview.notifications.Notification;
import info.nightscout.androidaps.plugins.ProfileLocal.LocalProfilePlugin; import info.nightscout.androidaps.plugins.ProfileLocal.LocalProfilePlugin;
import info.nightscout.utils.DateUtil; import info.nightscout.utils.DateUtil;
import info.nightscout.utils.DecimalFormatter; import info.nightscout.utils.DecimalFormatter;
@ -56,12 +61,14 @@ public class ProfileSwitch implements Interval, DataPointWithLabelInterface {
private Profile profile = null; private Profile profile = null;
@Nullable
public Profile getProfileObject() { public Profile getProfileObject() {
if (profile == null) if (profile == null)
try { try {
profile = new Profile(new JSONObject(profileJson), percentage, timeshift); profile = new Profile(new JSONObject(profileJson), percentage, timeshift);
} catch (JSONException e) { } catch (Exception e) {
log.error("Unhandled exception", e); log.error("Unhandled exception", e);
log.error("Unhandled exception", profileJson);
} }
return profile; return profile;
} }
@ -171,6 +178,20 @@ public class ProfileSwitch implements Interval, DataPointWithLabelInterface {
return durationInMinutes == 0; return durationInMinutes == 0;
} }
@Override
public boolean isValid() {
boolean isValid = getProfileObject() != null && getProfileObject().isValid(DateUtil.dateAndTimeString(date));
if (!isValid)
createNotificationInvalidProfile(DateUtil.dateAndTimeString(date));
return isValid;
}
public void createNotificationInvalidProfile(String detail) {
Notification notification = new Notification(Notification.ZERO_VALUE_IN_PROFILE, String.format(MainApp.gs(R.string.zerovalueinprofile), detail), Notification.LOW, 5);
MainApp.bus().post(new EventNewNotification(notification));
}
// -------- Interval interface end --------- // -------- Interval interface end ---------
// ----------------- DataPointInterface -------------------- // ----------------- DataPointInterface --------------------

View file

@ -123,6 +123,11 @@ public class TempTarget implements Interval {
return durationInMinutes == 0; return durationInMinutes == 0;
} }
@Override
public boolean isValid() {
return true;
}
// -------- Interval interface end --------- // -------- Interval interface end ---------
public String lowValueToUnitsToString(String units) { public String lowValueToUnitsToString(String units) {

View file

@ -182,6 +182,11 @@ public class TemporaryBasal implements Interval {
return durationInMinutes == 0; return durationInMinutes == 0;
} }
@Override
public boolean isValid() {
return true;
}
// -------- Interval interface end --------- // -------- Interval interface end ---------
public IobTotal iobCalc(long time) { public IobTotal iobCalc(long time) {

View file

@ -0,0 +1,8 @@
package info.nightscout.androidaps.events;
/**
* Created by mike on 23.01.2018.
*/
public class EventAppInitialized extends Event {
}

View file

@ -4,4 +4,11 @@ package info.nightscout.androidaps.events;
* Created by mike on 13.06.2016. * Created by mike on 13.06.2016.
*/ */
public class EventRefreshGui extends Event { public class EventRefreshGui extends Event {
public boolean recreate = false;
public EventRefreshGui(boolean recreate) {
this.recreate = recreate;
}
public EventRefreshGui(){
this(false);
}
} }

View file

@ -15,6 +15,8 @@ public interface ConstraintsInterface {
boolean isAMAModeEnabled(); boolean isAMAModeEnabled();
boolean isSMBModeEnabled();
Double applyBasalConstraints(Double absoluteRate); Double applyBasalConstraints(Double absoluteRate);
Integer applyBasalConstraints(Integer percentRate); Integer applyBasalConstraints(Integer percentRate);

View file

@ -1,9 +1,12 @@
package info.nightscout.androidaps.interfaces; package info.nightscout.androidaps.interfaces;
import info.nightscout.androidaps.data.PumpEnactResult;
/** /**
* Created by mike on 12.06.2017. * Created by mike on 12.06.2017.
*/ */
public interface DanaRInterface { public interface DanaRInterface {
boolean loadHistory(byte type); PumpEnactResult loadHistory(byte type); // for history browser
PumpEnactResult loadEvents(); // events history to build treatments from
} }

View file

@ -21,5 +21,5 @@ public interface InsulinInterface {
String getFriendlyName(); String getFriendlyName();
String getComment(); String getComment();
double getDia(); double getDia();
public Iob iobCalcForTreatment(Treatment treatment, long time, Double dia); public Iob iobCalcForTreatment(Treatment treatment, long time, double dia);
} }

View file

@ -21,4 +21,6 @@ public interface Interval {
boolean isInProgress(); boolean isInProgress();
boolean isEndingEvent(); boolean isEndingEvent();
boolean isValid();
} }

View file

@ -35,4 +35,6 @@ public class PumpDescription {
public double basalMinimumRate = 0.04d; public double basalMinimumRate = 0.04d;
public boolean isRefillingCapable = false; public boolean isRefillingCapable = false;
public boolean storesCarbInfo = true;
} }

View file

@ -16,27 +16,31 @@ public interface PumpInterface {
boolean isInitialized(); boolean isInitialized();
boolean isSuspended(); boolean isSuspended();
boolean isBusy(); boolean isBusy();
boolean isConnected();
boolean isConnecting();
void connect(String reason);
void disconnect(String reason);
void stopConnecting();
void getPumpStatus();
// Upload to pump new basal profile // Upload to pump new basal profile
int SUCCESS = 0; PumpEnactResult setNewBasalProfile(Profile profile);
int FAILED = 1;
int NOT_NEEDED = 2;
int setNewBasalProfile(Profile profile);
boolean isThisProfileSet(Profile profile); boolean isThisProfileSet(Profile profile);
Date lastDataTime(); Date lastDataTime();
void refreshDataFromPump(String reason);
double getBaseBasalRate(); // base basal rate, not temp basal double getBaseBasalRate(); // base basal rate, not temp basal
PumpEnactResult deliverTreatment(DetailedBolusInfo detailedBolusInfo); PumpEnactResult deliverTreatment(DetailedBolusInfo detailedBolusInfo);
void stopBolusDelivering(); void stopBolusDelivering();
PumpEnactResult setTempBasalAbsolute(Double absoluteRate, Integer durationInMinutes, boolean enforceNew); PumpEnactResult setTempBasalAbsolute(Double absoluteRate, Integer durationInMinutes, boolean enforceNew);
PumpEnactResult setTempBasalPercent(Integer percent, Integer durationInMinutes); PumpEnactResult setTempBasalPercent(Integer percent, Integer durationInMinutes, boolean enforceNew);
PumpEnactResult setExtendedBolus(Double insulin, Integer durationInMinutes); PumpEnactResult setExtendedBolus(Double insulin, Integer durationInMinutes);
//some pumps might set a very short temp close to 100% as cancelling a temp can be noisy //some pumps might set a very short temp close to 100% as cancelling a temp can be noisy
//when the cancel request is requested by the user (forced), the pump should always do a real cancel //when the cancel request is requested by the user (forced), the pump should always do a real cancel
PumpEnactResult cancelTempBasal(boolean force); PumpEnactResult cancelTempBasal(boolean enforceNew);
PumpEnactResult cancelExtendedBolus(); PumpEnactResult cancelExtendedBolus();
// Status to be passed to NS // Status to be passed to NS

View file

@ -3,14 +3,11 @@ package info.nightscout.androidaps.plugins.Actions;
import android.app.Activity; import android.app.Activity;
import android.os.Bundle; import android.os.Bundle;
import android.os.Handler;
import android.os.HandlerThread;
import android.support.v4.app.Fragment; import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager; import android.support.v4.app.FragmentManager;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.widget.Button;
import com.crashlytics.android.Crashlytics; import com.crashlytics.android.Crashlytics;
import com.crashlytics.android.answers.Answers; import com.crashlytics.android.answers.Answers;
@ -34,6 +31,8 @@ import info.nightscout.androidaps.plugins.Careportal.CareportalFragment;
import info.nightscout.androidaps.plugins.Careportal.Dialogs.NewNSTreatmentDialog; import info.nightscout.androidaps.plugins.Careportal.Dialogs.NewNSTreatmentDialog;
import info.nightscout.androidaps.plugins.Careportal.OptionsToShow; import info.nightscout.androidaps.plugins.Careportal.OptionsToShow;
import info.nightscout.androidaps.plugins.Common.SubscriberFragment; import info.nightscout.androidaps.plugins.Common.SubscriberFragment;
import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin;
import info.nightscout.utils.SingleClickButton;
/** /**
* A simple {@link Fragment} subclass. * A simple {@link Fragment} subclass.
@ -46,24 +45,16 @@ public class ActionsFragment extends SubscriberFragment implements View.OnClickL
return actionsPlugin; return actionsPlugin;
} }
Button profileSwitch; SingleClickButton profileSwitch;
Button tempTarget; SingleClickButton tempTarget;
Button extendedBolus; SingleClickButton extendedBolus;
Button extendedBolusCancel; SingleClickButton extendedBolusCancel;
Button tempBasal; SingleClickButton tempBasal;
Button tempBasalCancel; SingleClickButton tempBasalCancel;
Button fill; SingleClickButton fill;
private static Handler sHandler;
private static HandlerThread sHandlerThread;
public ActionsFragment() { public ActionsFragment() {
super(); super();
if (sHandlerThread == null) {
sHandlerThread = new HandlerThread(ActionsFragment.class.getSimpleName());
sHandlerThread.start();
sHandler = new Handler(sHandlerThread.getLooper());
}
} }
@ -73,13 +64,13 @@ public class ActionsFragment extends SubscriberFragment implements View.OnClickL
try { try {
View view = inflater.inflate(R.layout.actions_fragment, container, false); View view = inflater.inflate(R.layout.actions_fragment, container, false);
profileSwitch = (Button) view.findViewById(R.id.actions_profileswitch); profileSwitch = (SingleClickButton) view.findViewById(R.id.actions_profileswitch);
tempTarget = (Button) view.findViewById(R.id.actions_temptarget); tempTarget = (SingleClickButton) view.findViewById(R.id.actions_temptarget);
extendedBolus = (Button) view.findViewById(R.id.actions_extendedbolus); extendedBolus = (SingleClickButton) view.findViewById(R.id.actions_extendedbolus);
extendedBolusCancel = (Button) view.findViewById(R.id.actions_extendedbolus_cancel); extendedBolusCancel = (SingleClickButton) view.findViewById(R.id.actions_extendedbolus_cancel);
tempBasal = (Button) view.findViewById(R.id.actions_settempbasal); tempBasal = (SingleClickButton) view.findViewById(R.id.actions_settempbasal);
tempBasalCancel = (Button) view.findViewById(R.id.actions_canceltempbasal); tempBasalCancel = (SingleClickButton) view.findViewById(R.id.actions_canceltempbasal);
fill = (Button) view.findViewById(R.id.actions_fill); fill = (SingleClickButton) view.findViewById(R.id.actions_fill);
profileSwitch.setOnClickListener(this); profileSwitch.setOnClickListener(this);
tempTarget.setOnClickListener(this); tempTarget.setOnClickListener(this);
@ -135,14 +126,14 @@ public class ActionsFragment extends SubscriberFragment implements View.OnClickL
fill.setVisibility(View.GONE); fill.setVisibility(View.GONE);
return; return;
} }
boolean allowProfileSwitch = MainApp.getConfigBuilder().getActiveProfileInterface().getProfile().getProfileList().size() > 1; final PumpInterface pump = ConfigBuilderPlugin.getActivePump();
if (!MainApp.getConfigBuilder().getPumpDescription().isSetBasalProfileCapable || !MainApp.getConfigBuilder().isInitialized() || MainApp.getConfigBuilder().isSuspended() || !allowProfileSwitch) if (!pump.getPumpDescription().isSetBasalProfileCapable || !pump.isInitialized() || pump.isSuspended())
profileSwitch.setVisibility(View.GONE); profileSwitch.setVisibility(View.GONE);
else else
profileSwitch.setVisibility(View.VISIBLE); profileSwitch.setVisibility(View.VISIBLE);
if (!MainApp.getConfigBuilder().getPumpDescription().isExtendedBolusCapable || !MainApp.getConfigBuilder().isInitialized() || MainApp.getConfigBuilder().isSuspended() || MainApp.getConfigBuilder().isFakingTempsByExtendedBoluses()) { if (!pump.getPumpDescription().isExtendedBolusCapable || !pump.isInitialized() || pump.isSuspended() || pump.isFakingTempsByExtendedBoluses()) {
extendedBolus.setVisibility(View.GONE); extendedBolus.setVisibility(View.GONE);
extendedBolusCancel.setVisibility(View.GONE); extendedBolusCancel.setVisibility(View.GONE);
} else { } else {
@ -158,7 +149,7 @@ public class ActionsFragment extends SubscriberFragment implements View.OnClickL
} }
if (!MainApp.getConfigBuilder().getPumpDescription().isTempBasalCapable || !MainApp.getConfigBuilder().isInitialized() || MainApp.getConfigBuilder().isSuspended()) { if (!pump.getPumpDescription().isTempBasalCapable || !pump.isInitialized() || pump.isSuspended()) {
tempBasal.setVisibility(View.GONE); tempBasal.setVisibility(View.GONE);
tempBasalCancel.setVisibility(View.GONE); tempBasalCancel.setVisibility(View.GONE);
} else { } else {
@ -173,7 +164,7 @@ public class ActionsFragment extends SubscriberFragment implements View.OnClickL
} }
} }
if (!MainApp.getConfigBuilder().getPumpDescription().isRefillingCapable || !MainApp.getConfigBuilder().isInitialized() || MainApp.getConfigBuilder().isSuspended()) if (!pump.getPumpDescription().isRefillingCapable || !pump.isInitialized() || pump.isSuspended())
fill.setVisibility(View.GONE); fill.setVisibility(View.GONE);
else else
fill.setVisibility(View.VISIBLE); fill.setVisibility(View.VISIBLE);
@ -190,7 +181,6 @@ public class ActionsFragment extends SubscriberFragment implements View.OnClickL
@Override @Override
public void onClick(View view) { public void onClick(View view) {
FragmentManager manager = getFragmentManager(); FragmentManager manager = getFragmentManager();
final PumpInterface pump = MainApp.getConfigBuilder();
switch (view.getId()) { switch (view.getId()) {
case R.id.actions_profileswitch: case R.id.actions_profileswitch:
NewNSTreatmentDialog newDialog = new NewNSTreatmentDialog(); NewNSTreatmentDialog newDialog = new NewNSTreatmentDialog();
@ -212,24 +202,14 @@ public class ActionsFragment extends SubscriberFragment implements View.OnClickL
break; break;
case R.id.actions_extendedbolus_cancel: case R.id.actions_extendedbolus_cancel:
if (MainApp.getConfigBuilder().isInHistoryExtendedBoluslInProgress()) { if (MainApp.getConfigBuilder().isInHistoryExtendedBoluslInProgress()) {
sHandler.post(new Runnable() { ConfigBuilderPlugin.getCommandQueue().cancelExtended(null);
@Override Answers.getInstance().logCustom(new CustomEvent("CancelExtended"));
public void run() {
pump.cancelExtendedBolus();
Answers.getInstance().logCustom(new CustomEvent("CancelExtended"));
}
});
} }
break; break;
case R.id.actions_canceltempbasal: case R.id.actions_canceltempbasal:
if (MainApp.getConfigBuilder().isTempBasalInProgress()) { if (MainApp.getConfigBuilder().isTempBasalInProgress()) {
sHandler.post(new Runnable() { ConfigBuilderPlugin.getCommandQueue().cancelTempBasal(true, null);
@Override Answers.getInstance().logCustom(new CustomEvent("CancelTemp"));
public void run() {
pump.cancelTempBasal(true);
Answers.getInstance().logCustom(new CustomEvent("CancelTemp"));
}
});
} }
break; break;
case R.id.actions_settempbasal: case R.id.actions_settempbasal:

View file

@ -2,9 +2,8 @@ package info.nightscout.androidaps.plugins.Actions.dialogs;
import android.content.Context; import android.content.Context;
import android.content.DialogInterface; import android.content.DialogInterface;
import android.content.Intent;
import android.os.Bundle; import android.os.Bundle;
import android.os.Handler;
import android.os.HandlerThread;
import android.support.v4.app.DialogFragment; import android.support.v4.app.DialogFragment;
import android.support.v7.app.AlertDialog; import android.support.v7.app.AlertDialog;
import android.view.LayoutInflater; import android.view.LayoutInflater;
@ -27,11 +26,10 @@ import info.nightscout.androidaps.Constants;
import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.R; import info.nightscout.androidaps.R;
import info.nightscout.androidaps.data.DetailedBolusInfo; import info.nightscout.androidaps.data.DetailedBolusInfo;
import info.nightscout.androidaps.data.PumpEnactResult;
import info.nightscout.androidaps.db.Source; import info.nightscout.androidaps.db.Source;
import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin; import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin;
import info.nightscout.androidaps.plugins.Overview.Notification; import info.nightscout.androidaps.plugins.Overview.Dialogs.ErrorHelperActivity;
import info.nightscout.androidaps.plugins.Overview.events.EventNewNotification; import info.nightscout.androidaps.queue.Callback;
import info.nightscout.utils.DecimalFormatter; import info.nightscout.utils.DecimalFormatter;
import info.nightscout.utils.NumberPicker; import info.nightscout.utils.NumberPicker;
import info.nightscout.utils.SP; import info.nightscout.utils.SP;
@ -48,13 +46,7 @@ public class FillDialog extends DialogFragment implements OnClickListener {
NumberPicker editInsulin; NumberPicker editInsulin;
Handler mHandler;
public static HandlerThread mHandlerThread;
public FillDialog() { public FillDialog() {
mHandlerThread = new HandlerThread(FillDialog.class.getSimpleName());
mHandlerThread.start();
this.mHandler = new Handler(mHandlerThread.getLooper());
} }
@Override @Override
@ -69,7 +61,7 @@ public class FillDialog extends DialogFragment implements OnClickListener {
getDialog().getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN); getDialog().getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN);
Double maxInsulin = MainApp.getConfigBuilder().applyBolusConstraints(Constants.bolusOnlyForCheckLimit); Double maxInsulin = MainApp.getConfigBuilder().applyBolusConstraints(Constants.bolusOnlyForCheckLimit);
double bolusstep = MainApp.getConfigBuilder().getPumpDescription().bolusStep; double bolusstep = ConfigBuilderPlugin.getActivePump().getPumpDescription().bolusStep;
editInsulin = (NumberPicker) view.findViewById(R.id.treatments_newtreatment_insulinamount); editInsulin = (NumberPicker) view.findViewById(R.id.treatments_newtreatment_insulinamount);
editInsulin.setParams(0d, 0d, maxInsulin, bolusstep, new DecimalFormat("0.00"), false); editInsulin.setParams(0d, 0d, maxInsulin, bolusstep, new DecimalFormat("0.00"), false);
@ -108,6 +100,9 @@ public class FillDialog extends DialogFragment implements OnClickListener {
if (button1.getVisibility() == View.GONE && button2.getVisibility() == View.GONE && button3.getVisibility() == View.GONE) { if (button1.getVisibility() == View.GONE && button2.getVisibility() == View.GONE && button3.getVisibility() == View.GONE) {
divider.setVisibility(View.GONE); divider.setVisibility(View.GONE);
} }
setCancelable(true);
getDialog().setCanceledOnTouchOutside(false);
return view; return view;
} }
@ -158,28 +153,21 @@ public class FillDialog extends DialogFragment implements OnClickListener {
builder.setPositiveButton(getString(R.string.primefill), new DialogInterface.OnClickListener() { builder.setPositiveButton(getString(R.string.primefill), new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) { public void onClick(DialogInterface dialog, int id) {
if (finalInsulinAfterConstraints > 0) { if (finalInsulinAfterConstraints > 0) {
final ConfigBuilderPlugin pump = MainApp.getConfigBuilder(); DetailedBolusInfo detailedBolusInfo = new DetailedBolusInfo();
mHandler.post(new Runnable() { detailedBolusInfo.insulin = finalInsulinAfterConstraints;
detailedBolusInfo.context = context;
detailedBolusInfo.source = Source.USER;
detailedBolusInfo.isValid = false; // do not count it in IOB (for pump history)
ConfigBuilderPlugin.getCommandQueue().bolus(detailedBolusInfo, new Callback() {
@Override @Override
public void run() { public void run() {
DetailedBolusInfo detailedBolusInfo = new DetailedBolusInfo();
detailedBolusInfo.insulin = finalInsulinAfterConstraints;
detailedBolusInfo.context = context;
detailedBolusInfo.source = Source.USER;
detailedBolusInfo.isValid = false; // do not count it in IOB (for pump history)
PumpEnactResult result = pump.deliverTreatment(detailedBolusInfo);
if (!result.success) { if (!result.success) {
try { Intent i = new Intent(MainApp.instance(), ErrorHelperActivity.class);
AlertDialog.Builder builder = new AlertDialog.Builder(context); i.putExtra("soundid", R.raw.boluserror);
builder.setTitle(MainApp.sResources.getString(R.string.treatmentdeliveryerror)); i.putExtra("status", result.comment);
builder.setMessage(result.comment); i.putExtra("title", MainApp.sResources.getString(R.string.treatmentdeliveryerror));
builder.setPositiveButton(MainApp.sResources.getString(R.string.ok), null); i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
builder.show(); MainApp.instance().startActivity(i);
} catch (WindowManager.BadTokenException | NullPointerException e) {
// window has been destroyed
Notification notification = new Notification(Notification.BOLUS_DELIVERY_ERROR, MainApp.sResources.getString(R.string.treatmentdeliveryerror), Notification.URGENT);
MainApp.bus().post(new EventNewNotification(notification));
}
} }
} }
}); });

View file

@ -2,15 +2,13 @@ package info.nightscout.androidaps.plugins.Actions.dialogs;
import android.content.Context; import android.content.Context;
import android.content.DialogInterface; import android.content.DialogInterface;
import android.content.Intent;
import android.os.Bundle; import android.os.Bundle;
import android.os.Handler;
import android.os.HandlerThread;
import android.support.v4.app.DialogFragment; import android.support.v4.app.DialogFragment;
import android.support.v7.app.AlertDialog; import android.support.v7.app.AlertDialog;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.view.WindowManager;
import com.crashlytics.android.answers.Answers; import com.crashlytics.android.answers.Answers;
import com.crashlytics.android.answers.CustomEvent; import com.crashlytics.android.answers.CustomEvent;
@ -23,10 +21,9 @@ import java.text.DecimalFormat;
import info.nightscout.androidaps.Constants; import info.nightscout.androidaps.Constants;
import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.R; import info.nightscout.androidaps.R;
import info.nightscout.androidaps.data.PumpEnactResult; import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin;
import info.nightscout.androidaps.interfaces.PumpInterface; import info.nightscout.androidaps.plugins.Overview.Dialogs.ErrorHelperActivity;
import info.nightscout.androidaps.plugins.Overview.Notification; import info.nightscout.androidaps.queue.Callback;
import info.nightscout.androidaps.plugins.Overview.events.EventNewNotification;
import info.nightscout.utils.NumberPicker; import info.nightscout.utils.NumberPicker;
import info.nightscout.utils.SafeParse; import info.nightscout.utils.SafeParse;
@ -36,13 +33,7 @@ public class NewExtendedBolusDialog extends DialogFragment implements View.OnCli
NumberPicker editInsulin; NumberPicker editInsulin;
NumberPicker editDuration; NumberPicker editDuration;
Handler mHandler;
public static HandlerThread mHandlerThread;
public NewExtendedBolusDialog() { public NewExtendedBolusDialog() {
mHandlerThread = new HandlerThread(NewExtendedBolusDialog.class.getSimpleName());
mHandlerThread.start();
this.mHandler = new Handler(mHandlerThread.getLooper());
} }
@Override @Override
@ -56,21 +47,17 @@ public class NewExtendedBolusDialog extends DialogFragment implements View.OnCli
editInsulin = (NumberPicker) view.findViewById(R.id.overview_newextendedbolus_insulin); editInsulin = (NumberPicker) view.findViewById(R.id.overview_newextendedbolus_insulin);
editInsulin.setParams(0d, 0d, maxInsulin, 0.1d, new DecimalFormat("0.00"), false); editInsulin.setParams(0d, 0d, maxInsulin, 0.1d, new DecimalFormat("0.00"), false);
double extendedDurationStep = MainApp.getConfigBuilder().getPumpDescription().extendedBolusDurationStep; double extendedDurationStep = ConfigBuilderPlugin.getActivePump().getPumpDescription().extendedBolusDurationStep;
double extendedMaxDuration = MainApp.getConfigBuilder().getPumpDescription().extendedBolusMaxDuration; double extendedMaxDuration = ConfigBuilderPlugin.getActivePump().getPumpDescription().extendedBolusMaxDuration;
editDuration = (NumberPicker) view.findViewById(R.id.overview_newextendedbolus_duration); editDuration = (NumberPicker) view.findViewById(R.id.overview_newextendedbolus_duration);
editDuration.setParams(extendedDurationStep, extendedDurationStep, extendedMaxDuration, extendedDurationStep, new DecimalFormat("0"), false); editDuration.setParams(extendedDurationStep, extendedDurationStep, extendedMaxDuration, extendedDurationStep, new DecimalFormat("0"), false);
view.findViewById(R.id.ok).setOnClickListener(this); view.findViewById(R.id.ok).setOnClickListener(this);
view.findViewById(R.id.cancel).setOnClickListener(this); view.findViewById(R.id.cancel).setOnClickListener(this);
return view;
}
@Override setCancelable(true);
public void onResume() { getDialog().setCanceledOnTouchOutside(false);
super.onResume(); return view;
if (getDialog() != null)
getDialog().getWindow().setLayout(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
} }
@Override @Override
@ -99,23 +86,16 @@ public class NewExtendedBolusDialog extends DialogFragment implements View.OnCli
builder.setMessage(confirmMessage); builder.setMessage(confirmMessage);
builder.setPositiveButton(getString(R.string.ok), new DialogInterface.OnClickListener() { builder.setPositiveButton(getString(R.string.ok), new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) { public void onClick(DialogInterface dialog, int id) {
final PumpInterface pump = MainApp.getConfigBuilder(); ConfigBuilderPlugin.getCommandQueue().extendedBolus(finalInsulin, finalDurationInMinutes, new Callback() {
mHandler.post(new Runnable() {
@Override @Override
public void run() { public void run() {
PumpEnactResult result = pump.setExtendedBolus(finalInsulin, finalDurationInMinutes);
if (!result.success) { if (!result.success) {
try { Intent i = new Intent(MainApp.instance(), ErrorHelperActivity.class);
AlertDialog.Builder builder = new AlertDialog.Builder(context); i.putExtra("soundid", R.raw.boluserror);
builder.setTitle(context.getString(R.string.treatmentdeliveryerror)); i.putExtra("status", result.comment);
builder.setMessage(result.comment); i.putExtra("title", MainApp.sResources.getString(R.string.treatmentdeliveryerror));
builder.setPositiveButton(context.getString(R.string.ok), null); i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
builder.show(); MainApp.instance().startActivity(i);
} catch (WindowManager.BadTokenException | NullPointerException e) {
// window has been destroyed
Notification notification = new Notification(Notification.BOLUS_DELIVERY_ERROR, MainApp.sResources.getString(R.string.treatmentdeliveryerror), Notification.URGENT);
MainApp.bus().post(new EventNewNotification(notification));
}
} }
} }
}); });

View file

@ -1,11 +1,9 @@
package info.nightscout.androidaps.plugins.Actions.dialogs; package info.nightscout.androidaps.plugins.Actions.dialogs;
import android.app.Activity;
import android.content.Context; import android.content.Context;
import android.content.DialogInterface; import android.content.DialogInterface;
import android.content.Intent;
import android.os.Bundle; import android.os.Bundle;
import android.os.Handler;
import android.os.HandlerThread;
import android.support.v4.app.DialogFragment; import android.support.v4.app.DialogFragment;
import android.support.v7.app.AlertDialog; import android.support.v7.app.AlertDialog;
import android.view.LayoutInflater; import android.view.LayoutInflater;
@ -26,9 +24,10 @@ import java.text.DecimalFormat;
import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.R; import info.nightscout.androidaps.R;
import info.nightscout.androidaps.data.Profile; import info.nightscout.androidaps.data.Profile;
import info.nightscout.androidaps.data.PumpEnactResult;
import info.nightscout.androidaps.interfaces.PumpDescription; import info.nightscout.androidaps.interfaces.PumpDescription;
import info.nightscout.androidaps.interfaces.PumpInterface; import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin;
import info.nightscout.androidaps.plugins.Overview.Dialogs.ErrorHelperActivity;
import info.nightscout.androidaps.queue.Callback;
import info.nightscout.utils.NumberPicker; import info.nightscout.utils.NumberPicker;
import info.nightscout.utils.SafeParse; import info.nightscout.utils.SafeParse;
@ -47,13 +46,7 @@ public class NewTempBasalDialog extends DialogFragment implements View.OnClickLi
NumberPicker basalAbsolute; NumberPicker basalAbsolute;
NumberPicker duration; NumberPicker duration;
Handler mHandler;
public static HandlerThread mHandlerThread;
public NewTempBasalDialog() { public NewTempBasalDialog() {
mHandlerThread = new HandlerThread(NewTempBasalDialog.class.getSimpleName());
mHandlerThread.start();
this.mHandler = new Handler(mHandlerThread.getLooper());
} }
@Override @Override
@ -70,7 +63,7 @@ public class NewTempBasalDialog extends DialogFragment implements View.OnClickLi
absoluteRadio = (RadioButton) view.findViewById(R.id.overview_newtempbasal_absolute_radio); absoluteRadio = (RadioButton) view.findViewById(R.id.overview_newtempbasal_absolute_radio);
typeSelectorLayout = (LinearLayout) view.findViewById(R.id.overview_newtempbasal_typeselector_layout); typeSelectorLayout = (LinearLayout) view.findViewById(R.id.overview_newtempbasal_typeselector_layout);
PumpDescription pumpDescription = MainApp.getConfigBuilder().getPumpDescription(); PumpDescription pumpDescription = ConfigBuilderPlugin.getActivePump().getPumpDescription();
basalPercent = (NumberPicker) view.findViewById(R.id.overview_newtempbasal_basalpercentinput); basalPercent = (NumberPicker) view.findViewById(R.id.overview_newtempbasal_basalpercentinput);
double maxTempPercent = pumpDescription.maxTempPercent; double maxTempPercent = pumpDescription.maxTempPercent;
@ -109,6 +102,9 @@ public class NewTempBasalDialog extends DialogFragment implements View.OnClickLi
view.findViewById(R.id.ok).setOnClickListener(this); view.findViewById(R.id.ok).setOnClickListener(this);
view.findViewById(R.id.cancel).setOnClickListener(this); view.findViewById(R.id.cancel).setOnClickListener(this);
basalTypeRadioGroup.setOnCheckedChangeListener(this); basalTypeRadioGroup.setOnCheckedChangeListener(this);
setCancelable(true);
getDialog().setCanceledOnTouchOutside(false);
return view; return view;
} }
@ -143,37 +139,29 @@ public class NewTempBasalDialog extends DialogFragment implements View.OnClickLi
final Double finalBasal = absolute; final Double finalBasal = absolute;
final int finalDurationInMinutes = durationInMinutes; final int finalDurationInMinutes = durationInMinutes;
final Context context = getContext(); AlertDialog.Builder builder = new AlertDialog.Builder(getContext());
AlertDialog.Builder builder = new AlertDialog.Builder(context);
builder.setTitle(this.getContext().getString(R.string.confirmation)); builder.setTitle(this.getContext().getString(R.string.confirmation));
builder.setMessage(confirmMessage); builder.setMessage(confirmMessage);
builder.setPositiveButton(getString(R.string.ok), new DialogInterface.OnClickListener() { builder.setPositiveButton(getString(R.string.ok), new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) { public void onClick(DialogInterface dialog, int id) {
final PumpInterface pump = MainApp.getConfigBuilder(); Callback callback = new Callback() {
mHandler.post(new Runnable() {
@Override @Override
public void run() { public void run() {
PumpEnactResult result;
if (setAsPercent) {
result = pump.setTempBasalPercent(finalBasalPercent, finalDurationInMinutes);
} else {
result = pump.setTempBasalAbsolute(finalBasal, finalDurationInMinutes, true);
}
if (!result.success) { if (!result.success) {
if (context instanceof Activity) { Intent i = new Intent(MainApp.instance(), ErrorHelperActivity.class);
Activity activity = (Activity) context; i.putExtra("soundid", R.raw.boluserror);
if (activity.isFinishing()) { i.putExtra("status", result.comment);
return; i.putExtra("title", MainApp.sResources.getString(R.string.tempbasaldeliveryerror));
} i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
} MainApp.instance().startActivity(i);
AlertDialog.Builder builder = new AlertDialog.Builder(context);
builder.setTitle(MainApp.sResources.getString(R.string.tempbasaldeliveryerror));
builder.setMessage(result.comment);
builder.setPositiveButton(MainApp.sResources.getString(R.string.ok), null);
builder.show();
} }
} }
}); };
if (setAsPercent) {
ConfigBuilderPlugin.getCommandQueue().tempBasalPercent(finalBasalPercent, finalDurationInMinutes, true, callback);
} else {
ConfigBuilderPlugin.getCommandQueue().tempBasalAbsolute(finalBasal, finalDurationInMinutes, true, callback);
}
Answers.getInstance().logCustom(new CustomEvent("TempBasal")); Answers.getInstance().logCustom(new CustomEvent("TempBasal"));
} }
}); });

View file

@ -14,6 +14,7 @@ import com.crashlytics.android.Crashlytics;
import com.squareup.otto.Subscribe; import com.squareup.otto.Subscribe;
import info.nightscout.androidaps.BuildConfig; import info.nightscout.androidaps.BuildConfig;
import info.nightscout.androidaps.Config;
import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.R; import info.nightscout.androidaps.R;
import info.nightscout.androidaps.data.ProfileStore; import info.nightscout.androidaps.data.ProfileStore;
@ -104,7 +105,7 @@ public class CareportalFragment extends SubscriberFragment implements View.OnCli
butonsLayout.setVisibility(View.VISIBLE); butonsLayout.setVisibility(View.VISIBLE);
} }
if (BuildConfig.NSCLIENTOLNY) if (Config.NSCLIENT || Config.G5UPLOADER)
statsLayout.setVisibility(View.GONE); // visible on overview statsLayout.setVisibility(View.GONE); // visible on overview
updateGUI(); updateGUI();

View file

@ -67,7 +67,7 @@ public class CareportalPlugin implements PluginBase {
@Override @Override
public boolean showInList(int type) { public boolean showInList(int type) {
return !Config.NSCLIENT; return !Config.NSCLIENT && !Config.G5UPLOADER;
} }
@Override @Override

View file

@ -3,9 +3,8 @@ package info.nightscout.androidaps.plugins.Careportal.Dialogs;
import android.app.Activity; import android.app.Activity;
import android.content.DialogInterface; import android.content.DialogInterface;
import android.content.Intent;
import android.os.Bundle; import android.os.Bundle;
import android.os.Handler;
import android.os.HandlerThread;
import android.support.v4.app.DialogFragment; import android.support.v4.app.DialogFragment;
import android.support.v7.app.AlertDialog; import android.support.v7.app.AlertDialog;
import android.text.Editable; import android.text.Editable;
@ -51,9 +50,10 @@ import info.nightscout.androidaps.db.ProfileSwitch;
import info.nightscout.androidaps.db.Source; import info.nightscout.androidaps.db.Source;
import info.nightscout.androidaps.db.TempTarget; import info.nightscout.androidaps.db.TempTarget;
import info.nightscout.androidaps.events.EventNewBasalProfile; import info.nightscout.androidaps.events.EventNewBasalProfile;
import info.nightscout.androidaps.interfaces.PumpInterface;
import info.nightscout.androidaps.plugins.Careportal.OptionsToShow; import info.nightscout.androidaps.plugins.Careportal.OptionsToShow;
import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin; import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin;
import info.nightscout.androidaps.plugins.Overview.Dialogs.ErrorHelperActivity;
import info.nightscout.androidaps.queue.Callback;
import info.nightscout.utils.DateUtil; import info.nightscout.utils.DateUtil;
import info.nightscout.utils.NSUpload; import info.nightscout.utils.NSUpload;
import info.nightscout.utils.NumberPicker; import info.nightscout.utils.NumberPicker;
@ -105,10 +105,6 @@ public class NewNSTreatmentDialog extends DialogFragment implements View.OnClick
Date eventTime; Date eventTime;
private static Handler sHandler;
private static HandlerThread sHandlerThread;
public void setOptions(OptionsToShow options, int event) { public void setOptions(OptionsToShow options, int event) {
this.options = options; this.options = options;
this.event = MainApp.sResources.getString(event); this.event = MainApp.sResources.getString(event);
@ -116,11 +112,6 @@ public class NewNSTreatmentDialog extends DialogFragment implements View.OnClick
public NewNSTreatmentDialog() { public NewNSTreatmentDialog() {
super(); super();
if (sHandlerThread == null) {
sHandlerThread = new HandlerThread(NewNSTreatmentDialog.class.getSimpleName());
sHandlerThread.start();
sHandler = new Handler(sHandlerThread.getLooper());
}
} }
@Override @Override
@ -138,7 +129,7 @@ public class NewNSTreatmentDialog extends DialogFragment implements View.OnClick
@Override @Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) { Bundle savedInstanceState) {
if (options==null) return null; if (options == null) return null;
getDialog().setTitle(getString(options.eventName)); getDialog().setTitle(getString(options.eventName));
setStyle(DialogFragment.STYLE_NORMAL, getTheme()); setStyle(DialogFragment.STYLE_NORMAL, getTheme());
View view = inflater.inflate(R.layout.careportal_newnstreatment_dialog, container, false); View view = inflater.inflate(R.layout.careportal_newnstreatment_dialog, container, false);
@ -184,7 +175,7 @@ public class NewNSTreatmentDialog extends DialogFragment implements View.OnClick
profileSpinner.setAdapter(adapter); profileSpinner.setAdapter(adapter);
// set selected to actual profile // set selected to actual profile
for (int p = 0; p < profileList.size(); p++) { for (int p = 0; p < profileList.size(); p++) {
if (profileList.get(p).equals(MainApp.getConfigBuilder().getProfileName())) if (profileList.get(p).equals(MainApp.getConfigBuilder().getProfileName(false)))
profileSpinner.setSelection(p); profileSpinner.setSelection(p);
} }
@ -203,27 +194,30 @@ public class NewNSTreatmentDialog extends DialogFragment implements View.OnClick
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) { public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
double defaultDuration = 0; double defaultDuration = 0;
double defaultTarget = 0; double defaultTarget = 0;
if(profile!=null){ if (profile != null) {
defaultTarget = bg.doubleValue(); defaultTarget = bg.doubleValue();
} }
boolean erase = false; boolean erase = false;
if(MainApp.sResources.getString(R.string.eatingsoon).equals(reasonList.get(position))){ if (MainApp.sResources.getString(R.string.eatingsoon).equals(reasonList.get(position))) {
defaultDuration = SP.getDouble(R.string.key_eatingsoon_duration, 0d); defaultDuration = SP.getDouble(R.string.key_eatingsoon_duration, 0d);
defaultTarget = SP.getDouble(R.string.key_eatingsoon_target, 0d);; defaultTarget = SP.getDouble(R.string.key_eatingsoon_target, 0d);
} else if (MainApp.sResources.getString(R.string.activity).equals(reasonList.get(position))){ ;
defaultDuration = SP.getDouble(R.string.key_activity_duration, 0d);; } else if (MainApp.sResources.getString(R.string.activity).equals(reasonList.get(position))) {
defaultTarget = SP.getDouble(R.string.key_activity_target, 0d);; defaultDuration = SP.getDouble(R.string.key_activity_duration, 0d);
;
defaultTarget = SP.getDouble(R.string.key_activity_target, 0d);
;
} else { } else {
defaultDuration = 0; defaultDuration = 0;
erase = true; erase = true;
} }
if(defaultTarget != 0 || erase){ if (defaultTarget != 0 || erase) {
editTemptarget.setValue(defaultTarget); editTemptarget.setValue(defaultTarget);
} }
if(defaultDuration != 0){ if (defaultDuration != 0) {
editDuration.setValue(defaultDuration); editDuration.setValue(defaultDuration);
} else if (erase){ } else if (erase) {
editDuration.setValue(0d); editDuration.setValue(0d);
} }
} }
@ -237,7 +231,7 @@ public class NewNSTreatmentDialog extends DialogFragment implements View.OnClick
// bg // bg
bgUnitsView.setText(units); bgUnitsView.setText(units);
TextWatcher bgTextWatcher = new TextWatcher() { TextWatcher bgTextWatcher = new TextWatcher() {
public void afterTextChanged(Editable s) { public void afterTextChanged(Editable s) {
} }
@ -337,15 +331,15 @@ public class NewNSTreatmentDialog extends DialogFragment implements View.OnClick
editTimeshift.setParams(0d, (double) Constants.CPP_MIN_TIMESHIFT, (double) Constants.CPP_MAX_TIMESHIFT, 1d, new DecimalFormat("0"), false); editTimeshift.setParams(0d, (double) Constants.CPP_MIN_TIMESHIFT, (double) Constants.CPP_MAX_TIMESHIFT, 1d, new DecimalFormat("0"), false);
ProfileSwitch ps = MainApp.getConfigBuilder().getProfileSwitchFromHistory(System.currentTimeMillis()); ProfileSwitch ps = MainApp.getConfigBuilder().getProfileSwitchFromHistory(System.currentTimeMillis());
if(ps!=null && ps.isCPP){ if (ps != null && ps.isCPP) {
final int percentage = ps.percentage; final int percentage = ps.percentage;
final int timeshift = ps.timeshift; final int timeshift = ps.timeshift;
reuseButton.setText(reuseButton.getText() + " " + percentage + "% " + timeshift +"h"); reuseButton.setText(reuseButton.getText() + " " + percentage + "% " + timeshift + "h");
reuseButton.setOnClickListener(new View.OnClickListener() { reuseButton.setOnClickListener(new View.OnClickListener() {
@Override @Override
public void onClick(View v) { public void onClick(View v) {
editPercentage.setValue((double)percentage); editPercentage.setValue((double) percentage);
editTimeshift.setValue((double)timeshift); editTimeshift.setValue((double) timeshift);
} }
}); });
} }
@ -363,9 +357,11 @@ public class NewNSTreatmentDialog extends DialogFragment implements View.OnClick
showOrHide((ViewGroup) view.findViewById(R.id.careportal_newnstreatment_profile_layout), options.profile); showOrHide((ViewGroup) view.findViewById(R.id.careportal_newnstreatment_profile_layout), options.profile);
showOrHide((ViewGroup) view.findViewById(R.id.careportal_newnstreatment_percentage_layout), options.profile); showOrHide((ViewGroup) view.findViewById(R.id.careportal_newnstreatment_percentage_layout), options.profile);
showOrHide((ViewGroup) view.findViewById(R.id.careportal_newnstreatment_timeshift_layout), options.profile); showOrHide((ViewGroup) view.findViewById(R.id.careportal_newnstreatment_timeshift_layout), options.profile);
showOrHide((ViewGroup) view.findViewById(R.id.careportal_newnstreatment_reuse_layout), options.profile && ps!=null && ps.isCPP); showOrHide((ViewGroup) view.findViewById(R.id.careportal_newnstreatment_reuse_layout), options.profile && ps != null && ps.isCPP);
showOrHide((ViewGroup) view.findViewById(R.id.careportal_newnstreatment_temptarget_layout), options.tempTarget); showOrHide((ViewGroup) view.findViewById(R.id.careportal_newnstreatment_temptarget_layout), options.tempTarget);
setCancelable(true);
getDialog().setCanceledOnTouchOutside(false);
return view; return view;
} }
@ -538,7 +534,7 @@ public class NewNSTreatmentDialog extends DialogFragment implements View.OnClick
if (options.eventType == R.id.careportal_combobolus) { if (options.eventType == R.id.careportal_combobolus) {
Double enteredInsulin = SafeParse.stringToDouble(editInsulin.getText()); Double enteredInsulin = SafeParse.stringToDouble(editInsulin.getText());
data.put("enteredinsulin", enteredInsulin); data.put("enteredinsulin", enteredInsulin);
data.put("insulin", enteredInsulin * SafeParse.stringToDouble(editInsulin.getText()) / 100); data.put("insulin", enteredInsulin * SafeParse.stringToDouble(editSplit.getText()) / 100);
data.put("relative", enteredInsulin * (100 - SafeParse.stringToDouble(editSplit.getText())) / 100 / SafeParse.stringToDouble(editDuration.getText()) * 60); data.put("relative", enteredInsulin * (100 - SafeParse.stringToDouble(editSplit.getText())) / 100 / SafeParse.stringToDouble(editDuration.getText()) * 60);
} }
} catch (JSONException e) { } catch (JSONException e) {
@ -674,31 +670,22 @@ public class NewNSTreatmentDialog extends DialogFragment implements View.OnClick
} else if (options.executeTempTarget) { } else if (options.executeTempTarget) {
try { try {
if ((data.has("targetBottom") && data.has("targetTop")) || (data.has("duration") && data.getInt("duration") == 0)) { if ((data.has("targetBottom") && data.has("targetTop")) || (data.has("duration") && data.getInt("duration") == 0)) {
sHandler.post(new Runnable() { TempTarget tempTarget = new TempTarget();
@Override tempTarget.date = eventTime.getTime();
public void run() { tempTarget.durationInMinutes = data.getInt("duration");
try { tempTarget.reason = data.getString("reason");
TempTarget tempTarget = new TempTarget(); tempTarget.source = Source.USER;
tempTarget.date = eventTime.getTime(); if (tempTarget.durationInMinutes != 0) {
tempTarget.durationInMinutes = data.getInt("duration"); tempTarget.low = Profile.toMgdl(data.getDouble("targetBottom"), profile.getUnits());
tempTarget.reason = data.getString("reason"); tempTarget.high = Profile.toMgdl(data.getDouble("targetTop"), profile.getUnits());
tempTarget.source = Source.USER; } else {
if (tempTarget.durationInMinutes != 0) { tempTarget.low = 0;
tempTarget.low = Profile.toMgdl(data.getDouble("targetBottom"), profile.getUnits()); tempTarget.high = 0;
tempTarget.high = Profile.toMgdl(data.getDouble("targetTop"), profile.getUnits()); }
} else { log.debug("Creating new TempTarget db record: " + tempTarget.toString());
tempTarget.low = 0; MainApp.getDbHelper().createOrUpdate(tempTarget);
tempTarget.high = 0; NSUpload.uploadCareportalEntryToNS(data);
} Answers.getInstance().logCustom(new CustomEvent("TempTarget"));
log.debug("Creating new TempTarget db record: " + tempTarget.toString());
MainApp.getDbHelper().createOrUpdate(tempTarget);
NSUpload.uploadCareportalEntryToNS(data);
Answers.getInstance().logCustom(new CustomEvent("TempTarget"));
} catch (JSONException e) {
log.error("Unhandled exception", e);
}
}
});
} }
} catch (JSONException e) { } catch (JSONException e) {
log.error("Unhandled exception", e); log.error("Unhandled exception", e);
@ -714,64 +701,68 @@ public class NewNSTreatmentDialog extends DialogFragment implements View.OnClick
} }
public static void doProfileSwitch(final ProfileStore profileStore, final String profileName, final int duration, final int percentage, final int timeshift) { public static void doProfileSwitch(final ProfileStore profileStore, final String profileName, final int duration, final int percentage, final int timeshift) {
sHandler.post(new Runnable() { ProfileSwitch profileSwitch = new ProfileSwitch();
profileSwitch.date = System.currentTimeMillis();
profileSwitch.source = Source.USER;
profileSwitch.profileName = profileName;
profileSwitch.profileJson = profileStore.getSpecificProfile(profileName).getData().toString();
profileSwitch.profilePlugin = ConfigBuilderPlugin.getActiveProfileInterface().getClass().getName();
profileSwitch.durationInMinutes = duration;
profileSwitch.isCPP = percentage != 100 || timeshift != 0;
profileSwitch.timeshift = timeshift;
profileSwitch.percentage = percentage;
MainApp.getConfigBuilder().addToHistoryProfileSwitch(profileSwitch);
ConfigBuilderPlugin.getCommandQueue().setProfile(profileSwitch.getProfileObject(), new Callback() {
@Override @Override
public void run() { public void run() {
ProfileSwitch profileSwitch = new ProfileSwitch(); if (!result.success) {
profileSwitch.date = System.currentTimeMillis(); Intent i = new Intent(MainApp.instance(), ErrorHelperActivity.class);
profileSwitch.source = Source.USER; i.putExtra("soundid", R.raw.boluserror);
profileSwitch.profileName = profileName; i.putExtra("status", result.comment);
profileSwitch.profileJson = profileStore.getSpecificProfile(profileName).getData().toString(); i.putExtra("title", MainApp.sResources.getString(R.string.failedupdatebasalprofile));
profileSwitch.profilePlugin = ConfigBuilderPlugin.getActiveProfileInterface().getClass().getName(); i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
profileSwitch.durationInMinutes = duration; MainApp.instance().startActivity(i);
profileSwitch.isCPP = percentage != 100 || timeshift != 0;
profileSwitch.timeshift = timeshift;
profileSwitch.percentage = percentage;
MainApp.getConfigBuilder().addToHistoryProfileSwitch(profileSwitch);
PumpInterface pump = MainApp.getConfigBuilder();
if (pump != null) {
pump.setNewBasalProfile(profileSwitch.getProfileObject());
MainApp.bus().post(new EventNewBasalProfile());
} else {
log.error("No active pump selected");
} }
Answers.getInstance().logCustom(new CustomEvent("ProfileSwitch")); MainApp.bus().post(new EventNewBasalProfile());
} }
}); });
Answers.getInstance().logCustom(new CustomEvent("ProfileSwitch"));
} }
public static void doProfileSwitch(final int duration, final int percentage, final int timeshift) { public static void doProfileSwitch(final int duration, final int percentage, final int timeshift) {
sHandler.post(new Runnable() { ProfileSwitch profileSwitch = MainApp.getConfigBuilder().getProfileSwitchFromHistory(System.currentTimeMillis());
@Override if (profileSwitch != null) {
public void run() { profileSwitch = new ProfileSwitch();
ProfileSwitch profileSwitch = MainApp.getConfigBuilder().getProfileSwitchFromHistory(System.currentTimeMillis()); profileSwitch.date = System.currentTimeMillis();
if (profileSwitch != null) { profileSwitch.source = Source.USER;
profileSwitch = new ProfileSwitch(); profileSwitch.profileName = MainApp.getConfigBuilder().getProfileName(System.currentTimeMillis(), false);
profileSwitch.date = System.currentTimeMillis(); profileSwitch.profileJson = MainApp.getConfigBuilder().getProfile().getData().toString();
profileSwitch.source = Source.USER; profileSwitch.profilePlugin = ConfigBuilderPlugin.getActiveProfileInterface().getClass().getName();
profileSwitch.profileName = MainApp.getConfigBuilder().getProfileName(System.currentTimeMillis(), false); profileSwitch.durationInMinutes = duration;
profileSwitch.profileJson = MainApp.getConfigBuilder().getProfile().getData().toString(); profileSwitch.isCPP = percentage != 100 || timeshift != 0;
profileSwitch.profilePlugin = ConfigBuilderPlugin.getActiveProfileInterface().getClass().getName(); profileSwitch.timeshift = timeshift;
profileSwitch.durationInMinutes = duration; profileSwitch.percentage = percentage;
profileSwitch.isCPP = percentage != 100 || timeshift != 0; MainApp.getConfigBuilder().addToHistoryProfileSwitch(profileSwitch);
profileSwitch.timeshift = timeshift;
profileSwitch.percentage = percentage;
MainApp.getConfigBuilder().addToHistoryProfileSwitch(profileSwitch);
PumpInterface pump = MainApp.getConfigBuilder(); ConfigBuilderPlugin.getCommandQueue().setProfile(profileSwitch.getProfileObject(), new Callback() {
if (pump != null) { @Override
pump.setNewBasalProfile(profileSwitch.getProfileObject()); public void run() {
MainApp.bus().post(new EventNewBasalProfile()); if (!result.success) {
} else { Intent i = new Intent(MainApp.instance(), ErrorHelperActivity.class);
log.error("No active pump selected"); i.putExtra("soundid", R.raw.boluserror);
i.putExtra("status", result.comment);
i.putExtra("title", MainApp.sResources.getString(R.string.failedupdatebasalprofile));
i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
MainApp.instance().startActivity(i);
} }
Answers.getInstance().logCustom(new CustomEvent("ProfileSwitch")); MainApp.bus().post(new EventNewBasalProfile());
} else {
log.error("No profile switch existing");
} }
} });
}); Answers.getInstance().logCustom(new CustomEvent("ProfileSwitch"));
} else {
log.error("No profile switch existing");
}
} }
} }

View file

@ -2,9 +2,12 @@ package info.nightscout.androidaps.plugins.Common;
import android.support.v4.app.Fragment; import android.support.v4.app.Fragment;
import butterknife.Unbinder;
import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.MainApp;
abstract public class SubscriberFragment extends Fragment { abstract public class SubscriberFragment extends Fragment {
protected Unbinder unbinder;
@Override @Override
public void onPause() { public void onPause() {
super.onPause(); super.onPause();
@ -18,5 +21,12 @@ abstract public class SubscriberFragment extends Fragment {
updateGUI(); updateGUI();
} }
@Override public void onDestroyView() {
super.onDestroyView();
if (unbinder != null)
unbinder.unbind();
}
protected abstract void updateGUI(); protected abstract void updateGUI();
} }

View file

@ -1,12 +1,8 @@
package info.nightscout.androidaps.plugins.ConfigBuilder; package info.nightscout.androidaps.plugins.ConfigBuilder;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences; import android.content.SharedPreferences;
import android.os.PowerManager;
import android.preference.PreferenceManager; import android.preference.PreferenceManager;
import android.support.annotation.Nullable; import android.support.annotation.Nullable;
import android.support.v7.app.AppCompatActivity;
import org.json.JSONException; import org.json.JSONException;
import org.json.JSONObject; import org.json.JSONObject;
@ -14,16 +10,16 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Date;
import java.util.List; import java.util.List;
import info.nightscout.androidaps.Config; import info.nightscout.androidaps.Config;
import info.nightscout.androidaps.Constants;
import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.R; import info.nightscout.androidaps.R;
import info.nightscout.androidaps.data.DetailedBolusInfo; import info.nightscout.androidaps.data.DetailedBolusInfo;
import info.nightscout.androidaps.data.Intervals;
import info.nightscout.androidaps.data.IobTotal; import info.nightscout.androidaps.data.IobTotal;
import info.nightscout.androidaps.data.MealData; import info.nightscout.androidaps.data.MealData;
import info.nightscout.androidaps.data.Intervals;
import info.nightscout.androidaps.data.Profile; import info.nightscout.androidaps.data.Profile;
import info.nightscout.androidaps.data.ProfileIntervals; import info.nightscout.androidaps.data.ProfileIntervals;
import info.nightscout.androidaps.data.PumpEnactResult; import info.nightscout.androidaps.data.PumpEnactResult;
@ -32,33 +28,30 @@ import info.nightscout.androidaps.db.ProfileSwitch;
import info.nightscout.androidaps.db.TempTarget; import info.nightscout.androidaps.db.TempTarget;
import info.nightscout.androidaps.db.TemporaryBasal; import info.nightscout.androidaps.db.TemporaryBasal;
import info.nightscout.androidaps.db.Treatment; import info.nightscout.androidaps.db.Treatment;
import info.nightscout.androidaps.events.EventBolusRequested; import info.nightscout.androidaps.events.EventAppInitialized;
import info.nightscout.androidaps.interfaces.APSInterface; import info.nightscout.androidaps.interfaces.APSInterface;
import info.nightscout.androidaps.interfaces.BgSourceInterface; import info.nightscout.androidaps.interfaces.BgSourceInterface;
import info.nightscout.androidaps.interfaces.ConstraintsInterface; import info.nightscout.androidaps.interfaces.ConstraintsInterface;
import info.nightscout.androidaps.interfaces.InsulinInterface; import info.nightscout.androidaps.interfaces.InsulinInterface;
import info.nightscout.androidaps.interfaces.PluginBase; import info.nightscout.androidaps.interfaces.PluginBase;
import info.nightscout.androidaps.interfaces.ProfileInterface; import info.nightscout.androidaps.interfaces.ProfileInterface;
import info.nightscout.androidaps.interfaces.PumpDescription;
import info.nightscout.androidaps.interfaces.PumpInterface; import info.nightscout.androidaps.interfaces.PumpInterface;
import info.nightscout.androidaps.interfaces.SensitivityInterface; import info.nightscout.androidaps.interfaces.SensitivityInterface;
import info.nightscout.androidaps.interfaces.TreatmentsInterface; import info.nightscout.androidaps.interfaces.TreatmentsInterface;
import info.nightscout.androidaps.plugins.Loop.APSResult; import info.nightscout.androidaps.plugins.Loop.APSResult;
import info.nightscout.androidaps.plugins.Loop.LoopPlugin; import info.nightscout.androidaps.plugins.Loop.LoopPlugin;
import info.nightscout.androidaps.plugins.Overview.Dialogs.BolusProgressDialog;
import info.nightscout.androidaps.plugins.Overview.Dialogs.BolusProgressHelperActivity;
import info.nightscout.androidaps.plugins.Overview.Notification;
import info.nightscout.androidaps.plugins.Overview.events.EventDismissBolusprogressIfRunning;
import info.nightscout.androidaps.plugins.Overview.events.EventDismissNotification;
import info.nightscout.androidaps.plugins.Overview.events.EventNewNotification; import info.nightscout.androidaps.plugins.Overview.events.EventNewNotification;
import info.nightscout.androidaps.plugins.Overview.notifications.Notification;
import info.nightscout.androidaps.plugins.PumpVirtual.VirtualPumpPlugin; import info.nightscout.androidaps.plugins.PumpVirtual.VirtualPumpPlugin;
import info.nightscout.androidaps.queue.Callback;
import info.nightscout.androidaps.queue.CommandQueue;
import info.nightscout.utils.NSUpload; import info.nightscout.utils.NSUpload;
import info.nightscout.utils.SP; import info.nightscout.utils.SP;
/** /**
* Created by mike on 05.08.2016. * Created by mike on 05.08.2016.
*/ */
public class ConfigBuilderPlugin implements PluginBase, PumpInterface, ConstraintsInterface, TreatmentsInterface { public class ConfigBuilderPlugin implements PluginBase, ConstraintsInterface, TreatmentsInterface {
private static Logger log = LoggerFactory.getLogger(ConfigBuilderPlugin.class); private static Logger log = LoggerFactory.getLogger(ConfigBuilderPlugin.class);
private static BgSourceInterface activeBgSource; private static BgSourceInterface activeBgSource;
@ -77,12 +70,10 @@ public class ConfigBuilderPlugin implements PluginBase, PumpInterface, Constrain
private static ArrayList<PluginBase> pluginList; private static ArrayList<PluginBase> pluginList;
private PowerManager.WakeLock mWakeLock; private static CommandQueue commandQueue = new CommandQueue();
public ConfigBuilderPlugin() { public ConfigBuilderPlugin() {
MainApp.bus().register(this); MainApp.bus().register(this);
PowerManager powerManager = (PowerManager) MainApp.instance().getApplicationContext().getSystemService(Context.POWER_SERVICE);
mWakeLock = powerManager.newWakeLock(PowerManager.SCREEN_DIM_WAKE_LOCK, "ConfigBuilderPlugin");
} }
@Override @Override
@ -154,6 +145,7 @@ public class ConfigBuilderPlugin implements PluginBase, PumpInterface, Constrain
public void initialize() { public void initialize() {
pluginList = MainApp.getPluginsList(); pluginList = MainApp.getPluginsList();
loadSettings(); loadSettings();
MainApp.bus().post(new EventAppInitialized());
} }
public void storeSettings() { public void storeSettings() {
@ -197,6 +189,10 @@ public class ConfigBuilderPlugin implements PluginBase, PumpInterface, Constrain
verifySelectionInCategories(); verifySelectionInCategories();
} }
public static CommandQueue getCommandQueue() {
return commandQueue;
}
public static BgSourceInterface getActiveBgSource() { public static BgSourceInterface getActiveBgSource() {
return activeBgSource; return activeBgSource;
} }
@ -358,294 +354,75 @@ public class ConfigBuilderPlugin implements PluginBase, PumpInterface, Constrain
} }
/* /*
* Pump interface * Ex Pump interface
* *
* Config builder return itself as a pump and check constraints before it passes command to pump driver * Config builder return itself as a pump and check constraints before it passes command to pump driver
*/ */
@Override
public boolean isInitialized() {
if (activePump != null)
return activePump.isInitialized();
else return true;
}
@Override
public boolean isSuspended() {
if (activePump != null)
return activePump.isSuspended();
else return false;
}
@Override
public boolean isBusy() {
if (activePump != null)
return activePump.isBusy();
else return false;
}
@Override
public int setNewBasalProfile(Profile profile) {
// Compare with pump limits
Profile.BasalValue[] basalValues = profile.getBasalValues();
for (int index = 0; index < basalValues.length; index++) {
if (basalValues[index].value < getPumpDescription().basalMinimumRate) {
Notification notification = new Notification(Notification.BASAL_VALUE_BELOW_MINIMUM, MainApp.sResources.getString(R.string.basalvaluebelowminimum), Notification.URGENT);
MainApp.bus().post(new EventNewNotification(notification));
return FAILED;
}
}
MainApp.bus().post(new EventDismissNotification(Notification.BASAL_VALUE_BELOW_MINIMUM));
if (isThisProfileSet(profile)) {
log.debug("Correct profile already set");
return NOT_NEEDED;
} else if (activePump != null) {
return activePump.setNewBasalProfile(profile);
} else
return SUCCESS;
}
@Override
public boolean isThisProfileSet(Profile profile) {
if (activePump != null) {
boolean result = activePump.isThisProfileSet(profile);
if (result == false) {
log.debug("Current profile: " + getProfile().getData().toString());
log.debug("New profile: " + profile.getData().toString());
}
return result;
} else return true;
}
@Override
public Date lastDataTime() {
if (activePump != null)
return activePump.lastDataTime();
else return new Date();
}
@Override
public void refreshDataFromPump(String reason) {
if (activePump != null)
activePump.refreshDataFromPump(reason);
}
@Override
public double getBaseBasalRate() {
if (activePump != null)
return activePump.getBaseBasalRate();
else
return 0d;
}
@Override
public PumpEnactResult deliverTreatment(DetailedBolusInfo detailedBolusInfo) {
mWakeLock.acquire();
PumpEnactResult result;
detailedBolusInfo.insulin = applyBolusConstraints(detailedBolusInfo.insulin);
detailedBolusInfo.carbs = applyCarbsConstraints((int) detailedBolusInfo.carbs);
BolusProgressDialog bolusProgressDialog = null;
if (detailedBolusInfo.context != null) {
bolusProgressDialog = new BolusProgressDialog();
bolusProgressDialog.setInsulin(detailedBolusInfo.insulin);
bolusProgressDialog.show(((AppCompatActivity) detailedBolusInfo.context).getSupportFragmentManager(), "BolusProgress");
} else {
Intent i = new Intent();
i.putExtra("insulin", detailedBolusInfo.insulin);
i.setClass(MainApp.instance(), BolusProgressHelperActivity.class);
i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
MainApp.instance().startActivity(i);
}
MainApp.bus().post(new EventBolusRequested(detailedBolusInfo.insulin));
result = activePump.deliverTreatment(detailedBolusInfo);
BolusProgressDialog.bolusEnded = true;
MainApp.bus().post(new EventDismissBolusprogressIfRunning(result));
mWakeLock.release();
return result;
}
@Override
public void stopBolusDelivering() {
activePump.stopBolusDelivering();
}
/**
* apply constraints, set temp based on absolute valus and expecting absolute result
*
* @param absoluteRate
* @param durationInMinutes
* @return
*/
@Override
public PumpEnactResult setTempBasalAbsolute(Double absoluteRate, Integer durationInMinutes, boolean force) {
Double rateAfterConstraints = applyBasalConstraints(absoluteRate);
PumpEnactResult result = activePump.setTempBasalAbsolute(rateAfterConstraints, durationInMinutes, force);
if (Config.logCongigBuilderActions)
log.debug("setTempBasalAbsolute rate: " + rateAfterConstraints + " durationInMinutes: " + durationInMinutes + " success: " + result.success + " enacted: " + result.enacted);
return result;
}
public PumpEnactResult setTempBasalAbsolute(Double absoluteRate, Integer durationInMinutes) {
return setTempBasalAbsolute(absoluteRate, durationInMinutes, false);
}
/**
* apply constraints, set temp based on percent and expecting result in percent
*
* @param percent 0 ... 100 ...
* @param durationInMinutes
* @return result
*/
@Override
public PumpEnactResult setTempBasalPercent(Integer percent, Integer durationInMinutes) {
Integer percentAfterConstraints = applyBasalConstraints(percent);
PumpEnactResult result = activePump.setTempBasalPercent(percentAfterConstraints, durationInMinutes);
if (Config.logCongigBuilderActions)
log.debug("setTempBasalPercent percent: " + percentAfterConstraints + " durationInMinutes: " + durationInMinutes + " success: " + result.success + " enacted: " + result.enacted);
return result;
}
@Override
public PumpEnactResult setExtendedBolus(Double insulin, Integer durationInMinutes) {
Double rateAfterConstraints = applyBolusConstraints(insulin);
PumpEnactResult result = activePump.setExtendedBolus(rateAfterConstraints, durationInMinutes);
if (Config.logCongigBuilderActions)
log.debug("setExtendedBolus rate: " + rateAfterConstraints + " durationInMinutes: " + durationInMinutes + " success: " + result.success + " enacted: " + result.enacted);
return result;
}
@Override
public PumpEnactResult cancelTempBasal(boolean force) {
PumpEnactResult result = activePump.cancelTempBasal(force);
if (Config.logCongigBuilderActions)
log.debug("cancelTempBasal success: " + result.success + " enacted: " + result.enacted);
return result;
}
@Override
public PumpEnactResult cancelExtendedBolus() {
PumpEnactResult result = activePump.cancelExtendedBolus();
if (Config.logCongigBuilderActions)
log.debug("cancelExtendedBolus success: " + result.success + " enacted: " + result.enacted);
return result;
}
/** /**
* expect absolute request and allow both absolute and percent response based on pump capabilities * expect absolute request and allow both absolute and percent response based on pump capabilities
* *
* @param request * @param request
* @return * @return
* true if command is going to be executed
* false if error
*/ */
public PumpEnactResult applyAPSRequest(APSResult request) { public boolean applyAPSRequest(APSResult request, Callback callback) {
PumpInterface pump = getActivePump();
request.rate = applyBasalConstraints(request.rate); request.rate = applyBasalConstraints(request.rate);
PumpEnactResult result; PumpEnactResult result;
if (!isInitialized()) { if (!pump.isInitialized()) {
result = new PumpEnactResult();
result.comment = MainApp.sResources.getString(R.string.pumpNotInitialized);
result.enacted = false;
result.success = false;
log.debug("applyAPSRequest: " + MainApp.sResources.getString(R.string.pumpNotInitialized)); log.debug("applyAPSRequest: " + MainApp.sResources.getString(R.string.pumpNotInitialized));
return result; if (callback != null) {
callback.result(new PumpEnactResult().comment(MainApp.sResources.getString(R.string.pumpNotInitialized)).enacted(false).success(false)).run();
}
return false;
} }
if (isSuspended()) { if (pump.isSuspended()) {
result = new PumpEnactResult();
result.comment = MainApp.sResources.getString(R.string.pumpsuspended);
result.enacted = false;
result.success = false;
log.debug("applyAPSRequest: " + MainApp.sResources.getString(R.string.pumpsuspended)); log.debug("applyAPSRequest: " + MainApp.sResources.getString(R.string.pumpsuspended));
return result; if (callback != null) {
callback.result(new PumpEnactResult().comment(MainApp.sResources.getString(R.string.pumpsuspended)).enacted(false).success(false)).run();
}
return false;
} }
if (Config.logCongigBuilderActions) if (Config.logCongigBuilderActions)
log.debug("applyAPSRequest: " + request.toString()); log.debug("applyAPSRequest: " + request.toString());
if ((request.rate == 0 && request.duration == 0) || Math.abs(request.rate - getBaseBasalRate()) < getPumpDescription().basalStep) { if ((request.rate == 0 && request.duration == 0) || Math.abs(request.rate - pump.getBaseBasalRate()) < pump.getPumpDescription().basalStep) {
if (isTempBasalInProgress()) { if (isTempBasalInProgress()) {
if (Config.logCongigBuilderActions) if (Config.logCongigBuilderActions)
log.debug("applyAPSRequest: cancelTempBasal()"); log.debug("applyAPSRequest: cancelTempBasal()");
result = cancelTempBasal(false); getCommandQueue().cancelTempBasal(false, callback);
return true;
} else { } else {
result = new PumpEnactResult();
result.absolute = request.rate;
result.duration = 0;
result.enacted = false;
result.comment = "Basal set correctly";
result.success = true;
if (Config.logCongigBuilderActions) if (Config.logCongigBuilderActions)
log.debug("applyAPSRequest: Basal set correctly"); log.debug("applyAPSRequest: Basal set correctly");
if (callback != null) {
callback.result(new PumpEnactResult().absolute(request.rate).duration(0).enacted(false).success(true).comment("Basal set correctly")).run();
}
return false;
} }
} else if (isTempBasalInProgress() } else if (isTempBasalInProgress()
&& getTempBasalRemainingMinutesFromHistory() > 5 && getTempBasalRemainingMinutesFromHistory() > 5
&& Math.abs(request.rate - getTempBasalAbsoluteRateHistory()) < getPumpDescription().basalStep) { && Math.abs(request.rate - getTempBasalAbsoluteRateHistory()) < pump.getPumpDescription().basalStep) {
result = new PumpEnactResult();
result.absolute = getTempBasalAbsoluteRateHistory();
result.duration = getTempBasalFromHistory(System.currentTimeMillis()).getPlannedRemainingMinutes();
result.enacted = false;
result.comment = "Temp basal set correctly";
result.success = true;
if (Config.logCongigBuilderActions) if (Config.logCongigBuilderActions)
log.debug("applyAPSRequest: Temp basal set correctly"); log.debug("applyAPSRequest: Temp basal set correctly");
if (callback != null) {
callback.result(new PumpEnactResult().absolute(getTempBasalAbsoluteRateHistory()).duration(getTempBasalFromHistory(System.currentTimeMillis()).getPlannedRemainingMinutes()).enacted(false).success(true).comment("Temp basal set correctly")).run();
}
return false;
} else { } else {
if (Config.logCongigBuilderActions) if (Config.logCongigBuilderActions)
log.debug("applyAPSRequest: setTempBasalAbsolute()"); log.debug("applyAPSRequest: setTempBasalAbsolute()");
result = setTempBasalAbsolute(request.rate, request.duration); getCommandQueue().tempBasalAbsolute(request.rate, request.duration, false, callback);
} return true;
return result;
}
@Nullable
@Override
public JSONObject getJSONStatus() {
if (activePump != null)
return activePump.getJSONStatus();
else return null;
}
@Override
public String deviceID() {
if (activePump != null)
return activePump.deviceID();
else return "No Pump active!";
}
@Override
public PumpDescription getPumpDescription() {
if (activePump != null)
return activePump.getPumpDescription();
else {
PumpDescription emptyDescription = new PumpDescription();
emptyDescription.isBolusCapable = false;
emptyDescription.isExtendedBolusCapable = false;
emptyDescription.isSetBasalProfileCapable = false;
emptyDescription.isTempBasalCapable = true; // needs to be true before real driver is selected
emptyDescription.isRefillingCapable = false;
return emptyDescription;
} }
} }
@Override
public String shortStatus(boolean veryShort) {
if (activePump != null) {
return activePump.shortStatus(veryShort);
} else {
return "No Pump active!";
}
}
@Override
public boolean isFakingTempsByExtendedBoluses() {
return activePump.isFakingTempsByExtendedBoluses();
}
/** /**
* Constraints interface * Constraints interface
@ -691,8 +468,7 @@ public class ConfigBuilderPlugin implements PluginBase, PumpInterface, Constrain
@Override @Override
public boolean isAMAModeEnabled() { public boolean isAMAModeEnabled() {
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(MainApp.instance().getApplicationContext()); boolean result = SP.getBoolean("openapsama_useautosens", false);
boolean result = preferences.getBoolean("openapsama_useautosens", false);
ArrayList<PluginBase> constraintsPlugins = MainApp.getSpecificPluginsListByInterface(ConstraintsInterface.class); ArrayList<PluginBase> constraintsPlugins = MainApp.getSpecificPluginsListByInterface(ConstraintsInterface.class);
for (PluginBase p : constraintsPlugins) { for (PluginBase p : constraintsPlugins) {
@ -703,6 +479,19 @@ public class ConfigBuilderPlugin implements PluginBase, PumpInterface, Constrain
return result; return result;
} }
@Override
public boolean isSMBModeEnabled() {
boolean result = true; // TODO update for SMB // SP.getBoolean("openapsama_useautosens", false);
ArrayList<PluginBase> constraintsPlugins = MainApp.getSpecificPluginsListByInterface(ConstraintsInterface.class);
for (PluginBase p : constraintsPlugins) {
ConstraintsInterface constrain = (ConstraintsInterface) p;
if (!p.isEnabled(PluginBase.CONSTRAINTS)) continue;
result = result && constrain.isSMBModeEnabled();
}
return result;
}
@Override @Override
public Double applyBasalConstraints(Double absoluteRate) { public Double applyBasalConstraints(Double absoluteRate) {
Double rateAfterConstrain = absoluteRate; Double rateAfterConstrain = absoluteRate;
@ -822,13 +611,13 @@ public class ConfigBuilderPlugin implements PluginBase, PumpInterface, Constrain
@Override @Override
public boolean isTempBasalInProgress() { public boolean isTempBasalInProgress() {
return activeTreatments.isTempBasalInProgress(); return activeTreatments != null && activeTreatments.isTempBasalInProgress();
} }
@Override @Override
@Nullable @Nullable
public TemporaryBasal getTempBasalFromHistory(long time) { public TemporaryBasal getTempBasalFromHistory(long time) {
return activeTreatments.getTempBasalFromHistory(time); return activeTreatments != null ? activeTreatments.getTempBasalFromHistory(time) : null;
} }
@Override @Override
@ -945,6 +734,10 @@ public class ConfigBuilderPlugin implements PluginBase, PumpInterface, Constrain
return getProfileName(System.currentTimeMillis()); return getProfileName(System.currentTimeMillis());
} }
public String getProfileName(boolean customized) {
return getProfileName(System.currentTimeMillis(), customized);
}
public String getProfileName(long time) { public String getProfileName(long time) {
return getProfileName(time, true); return getProfileName(time, true);
} }
@ -968,14 +761,17 @@ public class ConfigBuilderPlugin implements PluginBase, PumpInterface, Constrain
return "Default"; return "Default";
} }
@Nullable
public Profile getProfile() { public Profile getProfile() {
return getProfile(System.currentTimeMillis()); return getProfile(System.currentTimeMillis());
} }
public String getProfileUnits() { public String getProfileUnits() {
return getProfile().getUnits(); Profile profile = getProfile();
return profile != null ? profile.getUnits() : Constants.MGDL;
} }
@Nullable
public Profile getProfile(long time) { public Profile getProfile(long time) {
if (activeTreatments == null) if (activeTreatments == null)
return null; //app not initialized return null; //app not initialized

View file

@ -197,6 +197,7 @@ public class ObjectivesFragment extends Fragment {
ObjectivesPlugin.objectives.get(4).objective = MainApp.sResources.getString(R.string.objectives_4_objective); ObjectivesPlugin.objectives.get(4).objective = MainApp.sResources.getString(R.string.objectives_4_objective);
ObjectivesPlugin.objectives.get(5).objective = MainApp.sResources.getString(R.string.objectives_5_objective); ObjectivesPlugin.objectives.get(5).objective = MainApp.sResources.getString(R.string.objectives_5_objective);
ObjectivesPlugin.objectives.get(6).objective = MainApp.sResources.getString(R.string.objectives_6_objective); ObjectivesPlugin.objectives.get(6).objective = MainApp.sResources.getString(R.string.objectives_6_objective);
ObjectivesPlugin.objectives.get(7).objective = MainApp.sResources.getString(R.string.objectives_7_objective);
ObjectivesPlugin.objectives.get(0).gate = MainApp.sResources.getString(R.string.objectives_0_gate); ObjectivesPlugin.objectives.get(0).gate = MainApp.sResources.getString(R.string.objectives_0_gate);
ObjectivesPlugin.objectives.get(1).gate = MainApp.sResources.getString(R.string.objectives_1_gate); ObjectivesPlugin.objectives.get(1).gate = MainApp.sResources.getString(R.string.objectives_1_gate);
ObjectivesPlugin.objectives.get(2).gate = MainApp.sResources.getString(R.string.objectives_2_gate); ObjectivesPlugin.objectives.get(2).gate = MainApp.sResources.getString(R.string.objectives_2_gate);

View file

@ -14,9 +14,15 @@ import info.nightscout.androidaps.BuildConfig;
import info.nightscout.androidaps.Config; import info.nightscout.androidaps.Config;
import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.R; import info.nightscout.androidaps.R;
import info.nightscout.androidaps.db.DatabaseHelper;
import info.nightscout.androidaps.interfaces.APSInterface;
import info.nightscout.androidaps.interfaces.ConstraintsInterface; import info.nightscout.androidaps.interfaces.ConstraintsInterface;
import info.nightscout.androidaps.interfaces.PluginBase; import info.nightscout.androidaps.interfaces.PluginBase;
import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin;
import info.nightscout.androidaps.plugins.ConstraintsSafety.SafetyPlugin;
import info.nightscout.androidaps.plugins.Loop.LoopPlugin; import info.nightscout.androidaps.plugins.Loop.LoopPlugin;
import info.nightscout.androidaps.plugins.NSClientInternal.NSClientInternalPlugin;
import info.nightscout.androidaps.plugins.PumpVirtual.VirtualPumpPlugin;
import info.nightscout.utils.SP; import info.nightscout.utils.SP;
/** /**
@ -62,7 +68,7 @@ public class ObjectivesPlugin implements PluginBase, ConstraintsInterface {
@Override @Override
public String getNameShort() { public String getNameShort() {
String name = MainApp.sResources.getString(R.string.objectives_shortname); String name = MainApp.sResources.getString(R.string.objectives_shortname);
if (!name.trim().isEmpty()){ if (!name.trim().isEmpty()) {
//only if translation exists //only if translation exists
return name; return name;
} }
@ -72,12 +78,12 @@ public class ObjectivesPlugin implements PluginBase, ConstraintsInterface {
@Override @Override
public boolean isEnabled(int type) { public boolean isEnabled(int type) {
return type == CONSTRAINTS && MainApp.getConfigBuilder().getPumpDescription().isTempBasalCapable; return type == CONSTRAINTS && ConfigBuilderPlugin.getActivePump().getPumpDescription().isTempBasalCapable;
} }
@Override @Override
public boolean isVisibleInTabs(int type) { public boolean isVisibleInTabs(int type) {
return type == CONSTRAINTS && fragmentVisible && !BuildConfig.NSCLIENTOLNY; return type == CONSTRAINTS && fragmentVisible && !Config.NSCLIENT && !Config.G5UPLOADER;
} }
@Override @Override
@ -152,14 +158,37 @@ public class ObjectivesPlugin implements PluginBase, ConstraintsInterface {
RequirementResult requirementsMet(Integer objNum) { RequirementResult requirementsMet(Integer objNum) {
switch (objNum) { switch (objNum) {
case 0: case 0:
return new RequirementResult(bgIsAvailableInNS && pumpStatusIsAvailableInNS, boolean isVirtualPump = VirtualPumpPlugin.getPlugin().isEnabled(PluginBase.PUMP);
boolean vpUploadEnabled = SP.getBoolean("virtualpump_uploadstatus", false);
boolean vpUploadNeeded = !isVirtualPump || vpUploadEnabled;
boolean hasBGData = DatabaseHelper.lastBg() != null;
boolean apsEnabled = false;
APSInterface usedAPS = ConfigBuilderPlugin.getActiveAPS();
if (usedAPS != null && ((PluginBase) usedAPS).isEnabled(PluginBase.APS))
apsEnabled = true;
return new RequirementResult(hasBGData && bgIsAvailableInNS && pumpStatusIsAvailableInNS && NSClientInternalPlugin.getPlugin().hasWritePermission() && LoopPlugin.getPlugin().isEnabled(PluginBase.LOOP) && apsEnabled && vpUploadNeeded,
MainApp.sResources.getString(R.string.objectives_bgavailableinns) + ": " + yesOrNo(bgIsAvailableInNS) MainApp.sResources.getString(R.string.objectives_bgavailableinns) + ": " + yesOrNo(bgIsAvailableInNS)
+ " " + MainApp.sResources.getString(R.string.objectives_pumpstatusavailableinns) + ": " + yesOrNo(pumpStatusIsAvailableInNS)); + "\n" + MainApp.sResources.getString(R.string.nsclienthaswritepermission) + ": " + yesOrNo(NSClientInternalPlugin.getPlugin().hasWritePermission())
+ (isVirtualPump ? "\n" + MainApp.sResources.getString(R.string.virtualpump_uploadstatus_title) + ": " + yesOrNo(vpUploadEnabled) : "")
+ "\n" + MainApp.sResources.getString(R.string.objectives_pumpstatusavailableinns) + ": " + yesOrNo(pumpStatusIsAvailableInNS)
+ "\n" + MainApp.sResources.getString(R.string.hasbgdata) + ": " + yesOrNo(hasBGData)
+ "\n" + MainApp.sResources.getString(R.string.loopenabled) + ": " + yesOrNo(LoopPlugin.getPlugin().isEnabled(PluginBase.LOOP))
+ "\n" + MainApp.sResources.getString(R.string.apsselected) + ": " + yesOrNo(apsEnabled)
);
case 1: case 1:
return new RequirementResult(manualEnacts >= manualEnactsNeeded, return new RequirementResult(manualEnacts >= manualEnactsNeeded,
MainApp.sResources.getString(R.string.objectives_manualenacts) + ": " + manualEnacts + "/" + manualEnactsNeeded); MainApp.sResources.getString(R.string.objectives_manualenacts) + ": " + manualEnacts + "/" + manualEnactsNeeded);
case 2: case 2:
return new RequirementResult(true, ""); return new RequirementResult(true, "");
case 3:
boolean closedModeEnabled = SafetyPlugin.getPlugin().isClosedModeEnabled();
return new RequirementResult(closedModeEnabled, MainApp.sResources.getString(R.string.closedmodeenabled) + ": " + yesOrNo(closedModeEnabled));
case 4:
double maxIOB = MainApp.getConfigBuilder().applyMaxIOBConstraints(1000d);
boolean maxIobSet = maxIOB > 0;
return new RequirementResult(maxIobSet, MainApp.sResources.getString(R.string.maxiobset) + ": " + yesOrNo(maxIobSet));
default: default:
return new RequirementResult(true, ""); return new RequirementResult(true, "");
} }
@ -212,7 +241,13 @@ public class ObjectivesPlugin implements PluginBase, ConstraintsInterface {
MainApp.sResources.getString(R.string.objectives_6_objective), MainApp.sResources.getString(R.string.objectives_6_objective),
"", "",
new Date(0), new Date(0),
14, 28,
new Date(0)));
objectives.add(new Objective(7,
MainApp.sResources.getString(R.string.objectives_7_objective),
"",
new Date(0),
28,
new Date(0))); new Date(0)));
} }
@ -260,7 +295,7 @@ public class ObjectivesPlugin implements PluginBase, ConstraintsInterface {
**/ **/
@Override @Override
public boolean isLoopEnabled() { public boolean isLoopEnabled() {
return objectives.get(1).started.getTime() > 0; return objectives.get(0).started.getTime() > 0;
} }
@Override @Override
@ -278,14 +313,19 @@ public class ObjectivesPlugin implements PluginBase, ConstraintsInterface {
return objectives.get(6).started.getTime() > 0; return objectives.get(6).started.getTime() > 0;
} }
@Override
public boolean isSMBModeEnabled() {
return objectives.get(7).started.getTime() > 0;
}
@Override @Override
public Double applyMaxIOBConstraints(Double maxIob) { public Double applyMaxIOBConstraints(Double maxIob) {
if (objectives.get(4).started.getTime() > 0 || objectives.get(2).accomplished.getTime() == 0) if (objectives.get(3).started.getTime() > 0 && objectives.get(3).accomplished.getTime() == 0) {
return maxIob;
else {
if (Config.logConstraintsChanges) if (Config.logConstraintsChanges)
log.debug("Limiting maxIOB " + maxIob + " to " + 0 + "U"); log.debug("Limiting maxIOB " + maxIob + " to " + 0 + "U");
return 0d; return 0d;
} else {
return maxIob;
} }
} }

View file

@ -10,9 +10,10 @@ import info.nightscout.androidaps.Config;
import info.nightscout.androidaps.Constants; import info.nightscout.androidaps.Constants;
import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.R; import info.nightscout.androidaps.R;
import info.nightscout.androidaps.data.Profile;
import info.nightscout.androidaps.interfaces.ConstraintsInterface; import info.nightscout.androidaps.interfaces.ConstraintsInterface;
import info.nightscout.androidaps.interfaces.PluginBase; import info.nightscout.androidaps.interfaces.PluginBase;
import info.nightscout.androidaps.data.Profile; import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin;
import info.nightscout.utils.HardLimits; import info.nightscout.utils.HardLimits;
import info.nightscout.utils.Round; import info.nightscout.utils.Round;
import info.nightscout.utils.SP; import info.nightscout.utils.SP;
@ -93,7 +94,7 @@ public class SafetyPlugin implements PluginBase, ConstraintsInterface {
@Override @Override
public boolean isLoopEnabled() { public boolean isLoopEnabled() {
return MainApp.getConfigBuilder().getPumpDescription().isTempBasalCapable; return ConfigBuilderPlugin.getActivePump().getPumpDescription().isTempBasalCapable;
} }
/** /**
@ -115,6 +116,11 @@ public class SafetyPlugin implements PluginBase, ConstraintsInterface {
return true; return true;
} }
@Override
public boolean isSMBModeEnabled() {
return true;
}
@Override @Override
public Double applyBasalConstraints(Double absoluteRate) { public Double applyBasalConstraints(Double absoluteRate) {
Double origAbsoluteRate = absoluteRate; Double origAbsoluteRate = absoluteRate;

View file

@ -61,7 +61,6 @@ public class FoodFragment extends SubscriberFragment {
Bundle savedInstanceState) { Bundle savedInstanceState) {
try { try {
View view = inflater.inflate(R.layout.food_fragment, container, false); View view = inflater.inflate(R.layout.food_fragment, container, false);
filter = (EditText) view.findViewById(R.id.food_filter); filter = (EditText) view.findViewById(R.id.food_filter);
clearFilter = (ImageView) view.findViewById(R.id.food_clearfilter); clearFilter = (ImageView) view.findViewById(R.id.food_clearfilter);
category = new SpinnerHelper(view.findViewById(R.id.food_category)); category = new SpinnerHelper(view.findViewById(R.id.food_category));

View file

@ -107,7 +107,7 @@ public class InsulinFastactingPlugin implements PluginBase, InsulinInterface {
} }
@Override @Override
public Iob iobCalcForTreatment(Treatment treatment, long time, Double dia) { public Iob iobCalcForTreatment(Treatment treatment, long time, double dia) {
Iob result = new Iob(); Iob result = new Iob();
double scaleFactor = 3.0 / dia; double scaleFactor = 3.0 / dia;

View file

@ -107,7 +107,7 @@ public class InsulinFastactingProlongedPlugin implements PluginBase, InsulinInte
} }
@Override @Override
public Iob iobCalcForTreatment(Treatment treatment, long time, Double dia) { public Iob iobCalcForTreatment(Treatment treatment, long time, double dia) {
Iob result = new Iob(); Iob result = new Iob();
//Double scaleFactor = 3.0 / dia; //Double scaleFactor = 3.0 / dia;

View file

@ -1,13 +1,14 @@
package info.nightscout.androidaps.plugins.Insulin; package info.nightscout.androidaps.plugins.Insulin;
import info.nightscout.androidaps.Constants; import com.squareup.otto.Bus;
import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.R; import info.nightscout.androidaps.R;
import info.nightscout.androidaps.data.Iob; import info.nightscout.androidaps.data.Iob;
import info.nightscout.androidaps.db.Treatment; import info.nightscout.androidaps.db.Treatment;
import info.nightscout.androidaps.interfaces.InsulinInterface; import info.nightscout.androidaps.interfaces.InsulinInterface;
import info.nightscout.androidaps.interfaces.PluginBase; import info.nightscout.androidaps.interfaces.PluginBase;
import info.nightscout.androidaps.plugins.Overview.Notification; import info.nightscout.androidaps.plugins.Overview.notifications.Notification;
import info.nightscout.androidaps.plugins.Overview.events.EventNewNotification; import info.nightscout.androidaps.plugins.Overview.events.EventNewNotification;
/** /**
@ -45,38 +46,53 @@ public abstract class InsulinOrefBasePlugin implements PluginBase, InsulinInterf
return true; return true;
} }
public Bus getBus() {
return MainApp.bus();
}
@Override @Override
public double getDia() { public double getDia() {
double dia = getUserDefinedDia(); double dia = getUserDefinedDia();
if(dia >= MIN_DIA){ if(dia >= MIN_DIA){
return dia; return dia;
} else { } else {
if((System.currentTimeMillis() - lastWarned) > 60*1000) { sendShortDiaNotification(dia);
lastWarned = System.currentTimeMillis();
Notification notification = new Notification(Notification.SHORT_DIA, String.format(MainApp.sResources.getString(R.string.dia_too_short), dia, MIN_DIA), Notification.URGENT);
MainApp.bus().post(new EventNewNotification(notification));
}
return MIN_DIA; return MIN_DIA;
} }
} }
void sendShortDiaNotification(double dia) {
if((System.currentTimeMillis() - lastWarned) > 60*1000) {
lastWarned = System.currentTimeMillis();
Notification notification = new Notification(Notification.SHORT_DIA, String.format(this.getNotificationPattern(), dia, MIN_DIA), Notification.URGENT);
this.getBus().post(new EventNewNotification(notification));
}
}
public String getNotificationPattern() {
return MainApp.sResources.getString(R.string.dia_too_short);
}
public double getUserDefinedDia() { public double getUserDefinedDia() {
return MainApp.getConfigBuilder().getProfile() != null ? MainApp.getConfigBuilder().getProfile().getDia() : MIN_DIA; return MainApp.getConfigBuilder().getProfile() != null ? MainApp.getConfigBuilder().getProfile().getDia() : MIN_DIA;
} }
public Iob iobCalcForTreatment(Treatment treatment, long time) {
return this.iobCalcForTreatment(treatment, time, 0d);
}
@Override @Override
public Iob iobCalcForTreatment(Treatment treatment, long time, Double dia) { public Iob iobCalcForTreatment(Treatment treatment, long time, double dia) {
Iob result = new Iob(); Iob result = new Iob();
int peak = getPeak(); int peak = getPeak();
if (treatment.insulin != 0d) { if (treatment.insulin != 0d) {
long bolusTime = treatment.date; long bolusTime = treatment.date;
double t = (time - bolusTime) / 1000d / 60d; double t = (time - bolusTime) / 1000d / 60d;
double td = getDia()*60; //getDIA() always > 5 double td = getDia()*60; //getDIA() always >= MIN_DIA
double tp = peak; double tp = peak;
// force the IOB to 0 if over DIA hours have passed // force the IOB to 0 if over DIA hours have passed

View file

@ -1,4 +1,4 @@
package info.nightscout.androidaps.plugins.IobCobCalculator.events; package info.nightscout.androidaps.plugins.IobCobCalculator;
/** /**
* Created by mike on 10.06.2017. * Created by mike on 10.06.2017.

View file

@ -1,7 +1,6 @@
package info.nightscout.androidaps.plugins.IobCobCalculator; package info.nightscout.androidaps.plugins.IobCobCalculator;
import android.os.Handler; import android.os.SystemClock;
import android.os.HandlerThread;
import android.support.annotation.Nullable; import android.support.annotation.Nullable;
import android.support.v4.util.LongSparseArray; import android.support.v4.util.LongSparseArray;
@ -23,16 +22,15 @@ import info.nightscout.androidaps.data.IobTotal;
import info.nightscout.androidaps.data.Profile; import info.nightscout.androidaps.data.Profile;
import info.nightscout.androidaps.db.BgReading; import info.nightscout.androidaps.db.BgReading;
import info.nightscout.androidaps.db.TemporaryBasal; import info.nightscout.androidaps.db.TemporaryBasal;
import info.nightscout.androidaps.db.Treatment; import info.nightscout.androidaps.events.EventAppInitialized;
import info.nightscout.androidaps.events.EventConfigBuilderChange; import info.nightscout.androidaps.events.EventConfigBuilderChange;
import info.nightscout.androidaps.events.EventNewBG; import info.nightscout.androidaps.events.EventNewBG;
import info.nightscout.androidaps.events.EventNewBasalProfile; import info.nightscout.androidaps.events.EventNewBasalProfile;
import info.nightscout.androidaps.events.EventPreferenceChange; import info.nightscout.androidaps.events.EventPreferenceChange;
import info.nightscout.androidaps.interfaces.PluginBase; import info.nightscout.androidaps.interfaces.PluginBase;
import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin; import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin;
import info.nightscout.androidaps.plugins.IobCobCalculator.events.BasalData;
import info.nightscout.androidaps.plugins.IobCobCalculator.events.EventAutosensCalculationFinished;
import info.nightscout.androidaps.plugins.IobCobCalculator.events.EventNewHistoryData; import info.nightscout.androidaps.plugins.IobCobCalculator.events.EventNewHistoryData;
import info.nightscout.utils.DateUtil;
/** /**
* Created by mike on 24.04.2017. * Created by mike on 24.04.2017.
@ -50,10 +48,10 @@ public class IobCobCalculatorPlugin implements PluginBase {
private static double dia = Constants.defaultDIA; private static double dia = Constants.defaultDIA;
private static Handler sHandler = null; static final Object dataLock = new Object();
private static HandlerThread sHandlerThread = null;
private static final Object dataLock = new Object(); boolean stopCalculationTrigger = false;
IobCobThread thread = null;
private static IobCobCalculatorPlugin plugin = null; private static IobCobCalculatorPlugin plugin = null;
@ -133,12 +131,6 @@ public class IobCobCalculatorPlugin implements PluginBase {
IobCobCalculatorPlugin() { IobCobCalculatorPlugin() {
MainApp.bus().register(this); MainApp.bus().register(this);
if (sHandlerThread == null) {
sHandlerThread = new HandlerThread(IobCobCalculatorPlugin.class.getSimpleName());
sHandlerThread.start();
sHandler = new Handler(sHandlerThread.getLooper());
}
onNewBg(new EventNewBG());
} }
@Nullable @Nullable
@ -175,14 +167,9 @@ public class IobCobCalculatorPlugin implements PluginBase {
return rouded; return rouded;
} }
private void loadBgData() { void loadBgData() {
//log.debug("Locking loadBgData"); bgReadings = MainApp.getDbHelper().getBgreadingsDataFromTime((long) (System.currentTimeMillis() - 60 * 60 * 1000L * (24 + dia)), false);
synchronized (dataLock) { log.debug("BG data loaded. Size: " + bgReadings.size());
onNewProfile(null);
bgReadings = MainApp.getDbHelper().getBgreadingsDataFromTime((long) (System.currentTimeMillis() - 60 * 60 * 1000L * (24 + dia)), false);
log.debug("BG data loaded. Size: " + bgReadings.size());
}
//log.debug("Releasing loadBgData");
} }
private boolean isAbout5minData() { private boolean isAbout5minData() {
@ -209,7 +196,7 @@ public class IobCobCalculatorPlugin implements PluginBase {
} }
} }
private void createBucketedData() { void createBucketedData() {
if (isAbout5minData()) if (isAbout5minData())
createBucketedData5min(); createBucketedData5min();
else else
@ -232,7 +219,7 @@ public class IobCobCalculatorPlugin implements PluginBase {
private BgReading findOlder(long time) { private BgReading findOlder(long time) {
BgReading lastFound = bgReadings.get(bgReadings.size() - 1); BgReading lastFound = bgReadings.get(bgReadings.size() - 1);
if (lastFound.date > time) return null; if (lastFound.date > time) return null;
for (int i = bgReadings.size() - 2; i >=0 ; --i) { for (int i = bgReadings.size() - 2; i >= 0; --i) {
if (bgReadings.get(i).date < time) continue; if (bgReadings.get(i).date < time) continue;
lastFound = bgReadings.get(i); lastFound = bgReadings.get(i);
if (bgReadings.get(i).date > time) break; if (bgReadings.get(i).date > time) break;
@ -241,221 +228,97 @@ public class IobCobCalculatorPlugin implements PluginBase {
} }
private void createBucketedDataRecalculated() { private void createBucketedDataRecalculated() {
synchronized (dataLock) { if (bgReadings == null || bgReadings.size() < 3) {
if (bgReadings == null || bgReadings.size() < 3) { bucketed_data = null;
bucketed_data = null; return;
return; }
}
bucketed_data = new ArrayList<>(); bucketed_data = new ArrayList<>();
long currentTime = bgReadings.get(0).date + 5 * 60 * 1000 - bgReadings.get(0).date % (5 * 60 * 1000) - 5 * 60 * 1000L; long currentTime = bgReadings.get(0).date + 5 * 60 * 1000 - bgReadings.get(0).date % (5 * 60 * 1000) - 5 * 60 * 1000L;
//log.debug("First reading: " + new Date(currentTime).toLocaleString()); //log.debug("First reading: " + new Date(currentTime).toLocaleString());
while (true) { while (true) {
// test if current value is older than current time // test if current value is older than current time
BgReading newer = findNewer(currentTime); BgReading newer = findNewer(currentTime);
BgReading older = findOlder(currentTime); BgReading older = findOlder(currentTime);
if (newer == null || older == null) if (newer == null || older == null)
break; break;
double bgDelta = newer.value - older.value; double bgDelta = newer.value - older.value;
long timeDiffToNew = newer.date - currentTime; long timeDiffToNew = newer.date - currentTime;
double currentBg = newer.value - (double) timeDiffToNew / (newer.date - older.date) * bgDelta; double currentBg = newer.value - (double) timeDiffToNew / (newer.date - older.date) * bgDelta;
BgReading newBgreading = new BgReading(); BgReading newBgreading = new BgReading();
newBgreading.date = currentTime; newBgreading.date = currentTime;
newBgreading.value = Math.round(currentBg); newBgreading.value = Math.round(currentBg);
bucketed_data.add(newBgreading); bucketed_data.add(newBgreading);
//log.debug("BG: " + newBgreading.value + " (" + new Date(newBgreading.date).toLocaleString() + ") Prev: " + older.value + " (" + new Date(older.date).toLocaleString() + ") Newer: " + newer.value + " (" + new Date(newer.date).toLocaleString() + ")"); //log.debug("BG: " + newBgreading.value + " (" + new Date(newBgreading.date).toLocaleString() + ") Prev: " + older.value + " (" + new Date(older.date).toLocaleString() + ") Newer: " + newer.value + " (" + new Date(newer.date).toLocaleString() + ")");
currentTime -= 5 * 60 * 1000L; currentTime -= 5 * 60 * 1000L;
}
} }
} }
public void createBucketedData5min() { public void createBucketedData5min() {
//log.debug("Locking createBucketedData"); if (bgReadings == null || bgReadings.size() < 3) {
synchronized (dataLock) { bucketed_data = null;
if (bgReadings == null || bgReadings.size() < 3) { return;
bucketed_data = null; }
return;
bucketed_data = new ArrayList<>();
bucketed_data.add(bgReadings.get(0));
int j = 0;
for (int i = 1; i < bgReadings.size(); ++i) {
long bgTime = bgReadings.get(i).date;
long lastbgTime = bgReadings.get(i - 1).date;
//log.error("Processing " + i + ": " + new Date(bgTime).toString() + " " + bgReadings.get(i).value + " Previous: " + new Date(lastbgTime).toString() + " " + bgReadings.get(i - 1).value);
if (bgReadings.get(i).value < 39 || bgReadings.get(i - 1).value < 39) {
continue;
} }
bucketed_data = new ArrayList<>(); long elapsed_minutes = (bgTime - lastbgTime) / (60 * 1000);
bucketed_data.add(bgReadings.get(0)); if (Math.abs(elapsed_minutes) > 8) {
int j = 0; // interpolate missing data points
for (int i = 1; i < bgReadings.size(); ++i) { double lastbg = bgReadings.get(i - 1).value;
long bgTime = bgReadings.get(i).date; elapsed_minutes = Math.abs(elapsed_minutes);
long lastbgTime = bgReadings.get(i - 1).date; //console.error(elapsed_minutes);
//log.error("Processing " + i + ": " + new Date(bgTime).toString() + " " + bgReadings.get(i).value + " Previous: " + new Date(lastbgTime).toString() + " " + bgReadings.get(i - 1).value); long nextbgTime;
if (bgReadings.get(i).value < 39 || bgReadings.get(i - 1).value < 39) { while (elapsed_minutes > 5) {
continue; nextbgTime = lastbgTime - 5 * 60 * 1000;
}
long elapsed_minutes = (bgTime - lastbgTime) / (60 * 1000);
if (Math.abs(elapsed_minutes) > 8) {
// interpolate missing data points
double lastbg = bgReadings.get(i - 1).value;
elapsed_minutes = Math.abs(elapsed_minutes);
//console.error(elapsed_minutes);
long nextbgTime;
while (elapsed_minutes > 5) {
nextbgTime = lastbgTime - 5 * 60 * 1000;
j++;
BgReading newBgreading = new BgReading();
newBgreading.date = nextbgTime;
double gapDelta = bgReadings.get(i).value - lastbg;
//console.error(gapDelta, lastbg, elapsed_minutes);
double nextbg = lastbg + (5d / elapsed_minutes * gapDelta);
newBgreading.value = Math.round(nextbg);
//console.error("Interpolated", bucketed_data[j]);
bucketed_data.add(newBgreading);
//log.error("******************************************************************************************************* Adding:" + new Date(newBgreading.date).toString() + " " + newBgreading.value);
elapsed_minutes = elapsed_minutes - 5;
lastbg = nextbg;
lastbgTime = nextbgTime;
}
j++; j++;
BgReading newBgreading = new BgReading(); BgReading newBgreading = new BgReading();
newBgreading.value = bgReadings.get(i).value; newBgreading.date = nextbgTime;
newBgreading.date = bgTime; double gapDelta = bgReadings.get(i).value - lastbg;
//console.error(gapDelta, lastbg, elapsed_minutes);
double nextbg = lastbg + (5d / elapsed_minutes * gapDelta);
newBgreading.value = Math.round(nextbg);
//console.error("Interpolated", bucketed_data[j]);
bucketed_data.add(newBgreading); bucketed_data.add(newBgreading);
//log.error("******************************************************************************************************* Copying:" + new Date(newBgreading.date).toString() + " " + newBgreading.value); //log.error("******************************************************************************************************* Adding:" + new Date(newBgreading.date).toString() + " " + newBgreading.value);
} else if (Math.abs(elapsed_minutes) > 2) {
j++; elapsed_minutes = elapsed_minutes - 5;
BgReading newBgreading = new BgReading(); lastbg = nextbg;
newBgreading.value = bgReadings.get(i).value; lastbgTime = nextbgTime;
newBgreading.date = bgTime;
bucketed_data.add(newBgreading);
//log.error("******************************************************************************************************* Copying:" + new Date(newBgreading.date).toString() + " " + newBgreading.value);
} else {
bucketed_data.get(j).value = (bucketed_data.get(j).value + bgReadings.get(i).value) / 2;
//log.error("***** Average");
} }
} j++;
log.debug("Bucketed data created. Size: " + bucketed_data.size()); BgReading newBgreading = new BgReading();
} newBgreading.value = bgReadings.get(i).value;
//log.debug("Releasing createBucketedData"); newBgreading.date = bgTime;
} bucketed_data.add(newBgreading);
//log.error("******************************************************************************************************* Copying:" + new Date(newBgreading.date).toString() + " " + newBgreading.value);
private void calculateSensitivityData() { } else if (Math.abs(elapsed_minutes) > 2) {
if (MainApp.getConfigBuilder() == null) j++;
return; // app still initializing BgReading newBgreading = new BgReading();
if (MainApp.getConfigBuilder().getProfile() == null) newBgreading.value = bgReadings.get(i).value;
return; // app still initializing newBgreading.date = bgTime;
//log.debug("Locking calculateSensitivityData"); bucketed_data.add(newBgreading);
long oldestTimeWithData = oldestDataAvailable(); //log.error("******************************************************************************************************* Copying:" + new Date(newBgreading.date).toString() + " " + newBgreading.value);
} else {
synchronized (dataLock) { bucketed_data.get(j).value = (bucketed_data.get(j).value + bgReadings.get(i).value) / 2;
//log.error("***** Average");
if (bucketed_data == null || bucketed_data.size() < 3) {
log.debug("calculateSensitivityData: No bucketed data available");
return;
}
long prevDataTime = roundUpTime(bucketed_data.get(bucketed_data.size() - 3).date);
log.debug("Prev data time: " + new Date(prevDataTime).toLocaleString());
AutosensData previous = autosensDataTable.get(prevDataTime);
// start from oldest to be able sub cob
for (int i = bucketed_data.size() - 4; i >= 0; i--) {
// check if data already exists
long bgTime = bucketed_data.get(i).date;
bgTime = roundUpTime(bgTime);
Profile profile = MainApp.getConfigBuilder().getProfile(bgTime);
AutosensData existing;
if ((existing = autosensDataTable.get(bgTime)) != null) {
previous = existing;
continue;
}
if (profile.getIsf(bgTime) == null)
return; // profile not set yet
double sens = Profile.toMgdl(profile.getIsf(bgTime), profile.getUnits());
AutosensData autosensData = new AutosensData();
autosensData.time = bgTime;
if (previous != null)
autosensData.activeCarbsList = new ArrayList<>(previous.activeCarbsList);
else
autosensData.activeCarbsList = new ArrayList<>();
//console.error(bgTime , bucketed_data[i].glucose);
double bg;
double avgDelta;
double delta;
bg = bucketed_data.get(i).value;
if (bg < 39 || bucketed_data.get(i + 3).value < 39) {
log.error("! value < 39");
continue;
}
delta = (bg - bucketed_data.get(i + 1).value);
IobTotal iob = calculateFromTreatmentsAndTemps(bgTime);
double bgi = -iob.activity * sens * 5;
double deviation = delta - bgi;
List<Treatment> recentTreatments = MainApp.getConfigBuilder().getTreatments5MinBackFromHistory(bgTime);
for (int ir = 0; ir < recentTreatments.size(); ir++) {
autosensData.carbsFromBolus += recentTreatments.get(ir).carbs;
autosensData.activeCarbsList.add(new AutosensData.CarbsInPast(recentTreatments.get(ir)));
}
// if we are absorbing carbs
if (previous != null && previous.cob > 0) {
// calculate sum of min carb impact from all active treatments
double totalMinCarbsImpact = 0d;
for (int ii = 0; ii < autosensData.activeCarbsList.size(); ++ii) {
AutosensData.CarbsInPast c = autosensData.activeCarbsList.get(ii);
totalMinCarbsImpact += c.min5minCarbImpact;
}
// figure out how many carbs that represents
// but always assume at least 3mg/dL/5m (default) absorption per active treatment
double ci = Math.max(deviation, totalMinCarbsImpact);
autosensData.absorbed = ci * profile.getIc(bgTime) / sens;
// and add that to the running total carbsAbsorbed
autosensData.cob = Math.max(previous.cob - autosensData.absorbed, 0d);
autosensData.substractAbosorbedCarbs();
}
autosensData.removeOldCarbs(bgTime);
autosensData.cob += autosensData.carbsFromBolus;
autosensData.deviation = deviation;
autosensData.bgi = bgi;
autosensData.delta = delta;
// calculate autosens only without COB
if (autosensData.cob <= 0) {
if (Math.abs(deviation) < Constants.DEVIATION_TO_BE_EQUAL) {
autosensData.pastSensitivity += "=";
autosensData.nonEqualDeviation = true;
} else if (deviation > 0) {
autosensData.pastSensitivity += "+";
autosensData.nonEqualDeviation = true;
} else {
autosensData.pastSensitivity += "-";
autosensData.nonEqualDeviation = true;
}
autosensData.nonCarbsDeviation = true;
} else {
autosensData.pastSensitivity += "C";
}
//log.debug("TIME: " + new Date(bgTime).toString() + " BG: " + bg + " SENS: " + sens + " DELTA: " + delta + " AVGDELTA: " + avgDelta + " IOB: " + iob.iob + " ACTIVITY: " + iob.activity + " BGI: " + bgi + " DEVIATION: " + deviation);
previous = autosensData;
autosensDataTable.put(bgTime, autosensData);
autosensData.autosensRatio = detectSensitivity(oldestTimeWithData, bgTime).ratio;
if (Config.logAutosensData)
log.debug(autosensData.log(bgTime));
} }
} }
MainApp.bus().post(new EventAutosensCalculationFinished()); log.debug("Bucketed data created. Size: " + bucketed_data.size());
//log.debug("Releasing calculateSensitivityData");
} }
public static long oldestDataAvailable() { public static long oldestDataAvailable() {
@ -543,6 +406,10 @@ public class IobCobCalculatorPlugin implements PluginBase {
//log.debug(">>> getAutosensData Cache hit " + data.log(time)); //log.debug(">>> getAutosensData Cache hit " + data.log(time));
return data; return data;
} else { } else {
if (time > now) {
// data may not be calculated yet, use last data
return getLastAutosensData("getAutosensData");
}
//log.debug(">>> getAutosensData Cache miss " + new Date(time).toLocaleString()); //log.debug(">>> getAutosensData Cache miss " + new Date(time).toLocaleString());
return null; return null;
} }
@ -550,13 +417,35 @@ public class IobCobCalculatorPlugin implements PluginBase {
} }
@Nullable @Nullable
public static AutosensData getLastAutosensData() { public static AutosensData getLastAutosensDataSynchronized(String reason) {
if (autosensDataTable.size() < 1) synchronized (dataLock) {
return getLastAutosensData(reason);
}
}
@Nullable
public static AutosensData getLastAutosensData(String reason) {
if (autosensDataTable.size() < 1) {
log.debug("AUTOSENSDATA null: autosensDataTable empty (" + reason + ")");
return null; return null;
AutosensData data = autosensDataTable.valueAt(autosensDataTable.size() - 1); }
if (data.time < System.currentTimeMillis() - 5 * 60 * 1000) { AutosensData data = null;
try {
data = autosensDataTable.valueAt(autosensDataTable.size() - 1);
} catch (Exception e) {
// data can be processed on the background
// in this rare case better return null and do not block UI
// APS plugin should use getLastAutosensDataSynchronized where the blocking is not an issue
log.debug("AUTOSENSDATA null: Exception catched (" + reason + ")");
return null;
}
if (data.time < System.currentTimeMillis() - 11 * 60 * 1000) {
log.debug("AUTOSENSDATA null: data is old (" + reason + ") size()=" + autosensDataTable.size() + " lastdata=" + DateUtil.dateAndTimeString(data.time));
return null; return null;
} else { } else {
if (data == null)
log.debug("AUTOSENSDATA null: data == null (" + " " + reason + ") size()=" + autosensDataTable.size() + " lastdata=" + DateUtil.dateAndTimeString(data.time));
return data; return data;
} }
} }
@ -584,7 +473,7 @@ public class IobCobCalculatorPlugin implements PluginBase {
} }
} }
private static AutosensResult detectSensitivity(long fromTime, long toTime) { static AutosensResult detectSensitivity(long fromTime, long toTime) {
return ConfigBuilderPlugin.getActiveSensitivity().detectSensitivity(fromTime, toTime); return ConfigBuilderPlugin.getActiveSensitivity().detectSensitivity(fromTime, toTime);
} }
@ -597,15 +486,33 @@ public class IobCobCalculatorPlugin implements PluginBase {
} }
@Subscribe @Subscribe
public void onNewBg(EventNewBG ev) { public void onEventAppInitialized(EventAppInitialized ev) {
sHandler.post(new Runnable() { runCalculation("onEventAppInitialized", true);
@Override }
public void run() {
loadBgData(); @Subscribe
createBucketedData(); public void onEventNewBG(EventNewBG ev) {
calculateSensitivityData(); stopCalculation("onEventNewBG");
runCalculation("onEventNewBG", true);
}
private void stopCalculation(String from) {
if (thread != null && thread.getState() != Thread.State.TERMINATED) {
stopCalculationTrigger = true;
log.debug("Stopping calculation thread: " + from);
while (thread.getState() != Thread.State.TERMINATED) {
SystemClock.sleep(100);
} }
}); log.debug("Calculation thread stopped: " + from);
}
}
private void runCalculation(String from, boolean bgDataReload) {
log.debug("Starting calculation thread: " + from);
if (thread == null || thread.getState() == Thread.State.TERMINATED) {
thread = new IobCobThread(this, from, bgDataReload);
thread.start();
}
} }
@Subscribe @Subscribe
@ -619,64 +526,53 @@ public class IobCobCalculatorPlugin implements PluginBase {
if (ev == null) { // on init no need of reset if (ev == null) { // on init no need of reset
return; return;
} }
stopCalculation("onNewProfile");
synchronized (dataLock) { synchronized (dataLock) {
log.debug("Invalidating cached data because of new profile. IOB: " + iobTable.size() + " Autosens: " + autosensDataTable.size() + " records"); log.debug("Invalidating cached data because of new profile. IOB: " + iobTable.size() + " Autosens: " + autosensDataTable.size() + " records");
iobTable = new LongSparseArray<>(); iobTable = new LongSparseArray<>();
autosensDataTable = new LongSparseArray<>(); autosensDataTable = new LongSparseArray<>();
} }
sHandler.post(new Runnable() { runCalculation("onNewProfile", false);
@Override
public void run() {
calculateSensitivityData();
}
});
} }
@Subscribe @Subscribe
public void onStatusEvent(EventPreferenceChange ev) { public void onEventPreferenceChange(EventPreferenceChange ev) {
if (ev.isChanged(R.string.key_openapsama_autosens_period) || if (ev.isChanged(R.string.key_openapsama_autosens_period) ||
ev.isChanged(R.string.key_age) || ev.isChanged(R.string.key_age) ||
ev.isChanged(R.string.key_absorption_maxtime) ev.isChanged(R.string.key_absorption_maxtime)
) { ) {
stopCalculation("onEventPreferenceChange");
synchronized (dataLock) { synchronized (dataLock) {
log.debug("Invalidating cached data because of preference change. IOB: " + iobTable.size() + " Autosens: " + autosensDataTable.size() + " records"); log.debug("Invalidating cached data because of preference change. IOB: " + iobTable.size() + " Autosens: " + autosensDataTable.size() + " records");
iobTable = new LongSparseArray<>(); iobTable = new LongSparseArray<>();
autosensDataTable = new LongSparseArray<>(); autosensDataTable = new LongSparseArray<>();
} }
sHandler.post(new Runnable() { runCalculation("onEventPreferenceChange", false);
@Override
public void run() {
calculateSensitivityData();
}
});
} }
} }
@Subscribe @Subscribe
public void onStatusEvent(EventConfigBuilderChange ev) { public void onEventConfigBuilderChange(EventConfigBuilderChange ev) {
stopCalculation("onEventConfigBuilderChange");
synchronized (dataLock) { synchronized (dataLock) {
log.debug("Invalidating cached data because of configuration change. IOB: " + iobTable.size() + " Autosens: " + autosensDataTable.size() + " records"); log.debug("Invalidating cached data because of configuration change. IOB: " + iobTable.size() + " Autosens: " + autosensDataTable.size() + " records");
iobTable = new LongSparseArray<>(); iobTable = new LongSparseArray<>();
autosensDataTable = new LongSparseArray<>(); autosensDataTable = new LongSparseArray<>();
} }
sHandler.post(new Runnable() { runCalculation("onEventConfigBuilderChange", false);
@Override
public void run() {
calculateSensitivityData();
}
});
} }
// When historical data is changed (comming from NS etc) finished calculations after this date must be invalidated // When historical data is changed (comming from NS etc) finished calculations after this date must be invalidated
@Subscribe @Subscribe
public void onNewHistoryData(EventNewHistoryData ev) { public void onEventNewHistoryData(EventNewHistoryData ev) {
//log.debug("Locking onNewHistoryData"); //log.debug("Locking onNewHistoryData");
stopCalculation("onEventNewHistoryData");
synchronized (dataLock) { synchronized (dataLock) {
long time = ev.time; // clear up 5 min back for proper COB calculation
long time = ev.time - 5 * 60 * 1000L;
log.debug("Invalidating cached data to: " + new Date(time).toLocaleString()); log.debug("Invalidating cached data to: " + new Date(time).toLocaleString());
for (int index = iobTable.size() - 1; index >= 0; index--) { for (int index = iobTable.size() - 1; index >= 0; index--) {
if (iobTable.keyAt(index) > time) { if (iobTable.keyAt(index) > time) {
if (Config.logAutosensData)
if (Config.logAutosensData) if (Config.logAutosensData)
log.debug("Removing from iobTable: " + new Date(iobTable.keyAt(index)).toLocaleString()); log.debug("Removing from iobTable: " + new Date(iobTable.keyAt(index)).toLocaleString());
iobTable.removeAt(index); iobTable.removeAt(index);
@ -703,12 +599,7 @@ public class IobCobCalculatorPlugin implements PluginBase {
} }
} }
} }
sHandler.post(new Runnable() { runCalculation("onEventNewHistoryData", false);
@Override
public void run() {
calculateSensitivityData();
}
});
//log.debug("Releasing onNewHistoryData"); //log.debug("Releasing onNewHistoryData");
} }

View file

@ -0,0 +1,206 @@
package info.nightscout.androidaps.plugins.IobCobCalculator;
import android.content.Context;
import android.os.PowerManager;
import android.support.v4.util.LongSparseArray;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import info.nightscout.androidaps.Config;
import info.nightscout.androidaps.Constants;
import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.data.IobTotal;
import info.nightscout.androidaps.data.Profile;
import info.nightscout.androidaps.db.BgReading;
import info.nightscout.androidaps.db.Treatment;
import info.nightscout.androidaps.plugins.IobCobCalculator.events.EventAutosensCalculationFinished;
import info.nightscout.androidaps.queue.QueueThread;
import static info.nightscout.androidaps.plugins.IobCobCalculator.IobCobCalculatorPlugin.getBucketedData;
import static info.nightscout.androidaps.plugins.IobCobCalculator.IobCobCalculatorPlugin.oldestDataAvailable;
import static info.nightscout.androidaps.plugins.IobCobCalculator.IobCobCalculatorPlugin.roundUpTime;
/**
* Created by mike on 23.01.2018.
*/
public class IobCobThread extends Thread {
private static Logger log = LoggerFactory.getLogger(QueueThread.class);
private IobCobCalculatorPlugin iobCobCalculatorPlugin;
private boolean bgDataReload;
private String from;
private PowerManager.WakeLock mWakeLock;
public IobCobThread(IobCobCalculatorPlugin plugin, String from, boolean bgDataReload) {
super();
this.iobCobCalculatorPlugin = plugin;
this.bgDataReload = bgDataReload;
this.from = from;
PowerManager powerManager = (PowerManager) MainApp.instance().getApplicationContext().getSystemService(Context.POWER_SERVICE);
mWakeLock = powerManager.newWakeLock(PowerManager.SCREEN_DIM_WAKE_LOCK, "iobCobThread");
}
@Override
public final void run() {
mWakeLock.acquire();
try {
if (MainApp.getConfigBuilder() == null) {
log.debug("Aborting calculation thread (ConfigBuilder not ready): " + from);
return; // app still initializing
}
if (MainApp.getConfigBuilder().getProfile() == null) {
log.debug("Aborting calculation thread (No profile): " + from);
return; // app still initializing
}
//log.debug("Locking calculateSensitivityData");
Object dataLock = iobCobCalculatorPlugin.dataLock;
long oldestTimeWithData = oldestDataAvailable();
synchronized (dataLock) {
if (bgDataReload) {
iobCobCalculatorPlugin.loadBgData();
iobCobCalculatorPlugin.createBucketedData();
}
List<BgReading> bucketed_data = getBucketedData();
LongSparseArray<AutosensData> autosensDataTable = iobCobCalculatorPlugin.getAutosensDataTable();
if (bucketed_data == null || bucketed_data.size() < 3) {
log.debug("Aborting calculation thread (No bucketed data available): " + from);
return;
}
long prevDataTime = roundUpTime(bucketed_data.get(bucketed_data.size() - 3).date);
log.debug("Prev data time: " + new Date(prevDataTime).toLocaleString());
AutosensData previous = autosensDataTable.get(prevDataTime);
// start from oldest to be able sub cob
for (int i = bucketed_data.size() - 4; i >= 0; i--) {
if (iobCobCalculatorPlugin.stopCalculationTrigger) {
iobCobCalculatorPlugin.stopCalculationTrigger = false;
log.debug("Aborting calculation thread (trigger): " + from);
return;
}
// check if data already exists
long bgTime = bucketed_data.get(i).date;
bgTime = roundUpTime(bgTime);
if (bgTime > System.currentTimeMillis())
continue;
Profile profile = MainApp.getConfigBuilder().getProfile(bgTime);
AutosensData existing;
if ((existing = autosensDataTable.get(bgTime)) != null) {
previous = existing;
continue;
}
if (profile == null) {
log.debug("Aborting calculation thread (no profile): " + from);
return; // profile not set yet
}
if (profile.getIsf(bgTime) == null) {
log.debug("Aborting calculation thread (no ISF): " + from);
return; // profile not set yet
}
if (Config.logAutosensData)
log.debug("Processing calculation thread: " + from + " (" + i + "/" + bucketed_data.size() + ")");
double sens = Profile.toMgdl(profile.getIsf(bgTime), profile.getUnits());
AutosensData autosensData = new AutosensData();
autosensData.time = bgTime;
if (previous != null)
autosensData.activeCarbsList = new ArrayList<>(previous.activeCarbsList);
else
autosensData.activeCarbsList = new ArrayList<>();
//console.error(bgTime , bucketed_data[i].glucose);
double bg;
double avgDelta;
double delta;
bg = bucketed_data.get(i).value;
if (bg < 39 || bucketed_data.get(i + 3).value < 39) {
log.error("! value < 39");
continue;
}
delta = (bg - bucketed_data.get(i + 1).value);
IobTotal iob = iobCobCalculatorPlugin.calculateFromTreatmentsAndTemps(bgTime);
double bgi = -iob.activity * sens * 5;
double deviation = delta - bgi;
List<Treatment> recentTreatments = MainApp.getConfigBuilder().getTreatments5MinBackFromHistory(bgTime);
for (int ir = 0; ir < recentTreatments.size(); ir++) {
autosensData.carbsFromBolus += recentTreatments.get(ir).carbs;
autosensData.activeCarbsList.add(new AutosensData.CarbsInPast(recentTreatments.get(ir)));
}
// if we are absorbing carbs
if (previous != null && previous.cob > 0) {
// calculate sum of min carb impact from all active treatments
double totalMinCarbsImpact = 0d;
for (int ii = 0; ii < autosensData.activeCarbsList.size(); ++ii) {
AutosensData.CarbsInPast c = autosensData.activeCarbsList.get(ii);
totalMinCarbsImpact += c.min5minCarbImpact;
}
// figure out how many carbs that represents
// but always assume at least 3mg/dL/5m (default) absorption per active treatment
double ci = Math.max(deviation, totalMinCarbsImpact);
autosensData.absorbed = ci * profile.getIc(bgTime) / sens;
// and add that to the running total carbsAbsorbed
autosensData.cob = Math.max(previous.cob - autosensData.absorbed, 0d);
autosensData.substractAbosorbedCarbs();
}
autosensData.removeOldCarbs(bgTime);
autosensData.cob += autosensData.carbsFromBolus;
autosensData.deviation = deviation;
autosensData.bgi = bgi;
autosensData.delta = delta;
// calculate autosens only without COB
if (autosensData.cob <= 0) {
if (Math.abs(deviation) < Constants.DEVIATION_TO_BE_EQUAL) {
autosensData.pastSensitivity += "=";
autosensData.nonEqualDeviation = true;
} else if (deviation > 0) {
autosensData.pastSensitivity += "+";
autosensData.nonEqualDeviation = true;
} else {
autosensData.pastSensitivity += "-";
autosensData.nonEqualDeviation = true;
}
autosensData.nonCarbsDeviation = true;
} else {
autosensData.pastSensitivity += "C";
}
//log.debug("TIME: " + new Date(bgTime).toString() + " BG: " + bg + " SENS: " + sens + " DELTA: " + delta + " AVGDELTA: " + avgDelta + " IOB: " + iob.iob + " ACTIVITY: " + iob.activity + " BGI: " + bgi + " DEVIATION: " + deviation);
previous = autosensData;
autosensDataTable.put(bgTime, autosensData);
autosensData.autosensRatio = iobCobCalculatorPlugin.detectSensitivity(oldestTimeWithData, bgTime).ratio;
if (Config.logAutosensData)
log.debug(autosensData.log(bgTime));
}
}
MainApp.bus().post(new EventAutosensCalculationFinished());
log.debug("Finishing calculation thread: " + from);
} finally {
mWakeLock.release();
}
}
}

View file

@ -12,6 +12,7 @@ import org.slf4j.LoggerFactory;
import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.R; import info.nightscout.androidaps.R;
import info.nightscout.androidaps.interfaces.PumpInterface;
import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin; import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin;
import info.nightscout.utils.DecimalFormatter; import info.nightscout.utils.DecimalFormatter;
@ -25,15 +26,16 @@ public class APSResult {
public double rate; public double rate;
public int duration; public int duration;
public boolean changeRequested = false; public boolean changeRequested = false;
@Override @Override
public String toString() { public String toString() {
final ConfigBuilderPlugin configBuilder = MainApp.getConfigBuilder(); final PumpInterface pump = ConfigBuilderPlugin.getActivePump();
if (changeRequested) { if (changeRequested) {
if (rate == 0 && duration == 0) if (rate == 0 && duration == 0)
return MainApp.sResources.getString(R.string.canceltemp); return MainApp.sResources.getString(R.string.canceltemp);
else else
return MainApp.sResources.getString(R.string.rate) + ": " + DecimalFormatter.to2Decimal(rate) + " U/h " + return MainApp.sResources.getString(R.string.rate) + ": " + DecimalFormatter.to2Decimal(rate) + " U/h " +
"(" + DecimalFormatter.to2Decimal(rate/configBuilder.getBaseBasalRate() *100) + "%)\n" + "(" + DecimalFormatter.to2Decimal(rate / pump.getBaseBasalRate() * 100) + "%)\n" +
MainApp.sResources.getString(R.string.duration) + ": " + DecimalFormatter.to0Decimal(duration) + " min\n" + MainApp.sResources.getString(R.string.duration) + ": " + DecimalFormatter.to0Decimal(duration) + " min\n" +
MainApp.sResources.getString(R.string.reason) + ": " + reason; MainApp.sResources.getString(R.string.reason) + ": " + reason;
} else } else
@ -41,13 +43,13 @@ public class APSResult {
} }
public Spanned toSpanned() { public Spanned toSpanned() {
final ConfigBuilderPlugin configBuilder = MainApp.getConfigBuilder(); final PumpInterface pump = ConfigBuilderPlugin.getActivePump();
if (changeRequested) { if (changeRequested) {
String ret = ""; String ret = "";
if (rate == 0 && duration == 0) ret = MainApp.sResources.getString(R.string.canceltemp); if (rate == 0 && duration == 0) ret = MainApp.sResources.getString(R.string.canceltemp);
else else
ret = "<b>" + MainApp.sResources.getString(R.string.rate) + "</b>: " + DecimalFormatter.to2Decimal(rate) + " U/h " + ret = "<b>" + MainApp.sResources.getString(R.string.rate) + "</b>: " + DecimalFormatter.to2Decimal(rate) + " U/h " +
"(" + DecimalFormatter.to2Decimal(rate/configBuilder.getBaseBasalRate() *100) + "%) <br>" + "(" + DecimalFormatter.to2Decimal(rate / pump.getBaseBasalRate() * 100) + "%) <br>" +
"<b>" + MainApp.sResources.getString(R.string.duration) + "</b>: " + DecimalFormatter.to2Decimal(duration) + " min<br>" + "<b>" + MainApp.sResources.getString(R.string.duration) + "</b>: " + DecimalFormatter.to2Decimal(duration) + " min<br>" +
"<b>" + MainApp.sResources.getString(R.string.reason) + "</b>: " + reason.replace("<", "&lt;").replace(">", "&gt;"); "<b>" + MainApp.sResources.getString(R.string.reason) + "</b>: " + reason.replace("<", "&lt;").replace(">", "&gt;");
return Html.fromHtml(ret); return Html.fromHtml(ret);

View file

@ -6,15 +6,12 @@ import android.app.PendingIntent;
import android.app.TaskStackBuilder; import android.app.TaskStackBuilder;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.os.Handler; import android.support.v4.app.NotificationCompat;
import android.os.HandlerThread;
import android.support.v7.app.NotificationCompat;
import com.crashlytics.android.answers.Answers; import com.crashlytics.android.answers.Answers;
import com.crashlytics.android.answers.CustomEvent; import com.crashlytics.android.answers.CustomEvent;
import com.squareup.otto.Subscribe; import com.squareup.otto.Subscribe;
import org.json.JSONException;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
@ -31,14 +28,14 @@ import info.nightscout.androidaps.events.EventTreatmentChange;
import info.nightscout.androidaps.interfaces.APSInterface; import info.nightscout.androidaps.interfaces.APSInterface;
import info.nightscout.androidaps.interfaces.ConstraintsInterface; import info.nightscout.androidaps.interfaces.ConstraintsInterface;
import info.nightscout.androidaps.interfaces.PluginBase; import info.nightscout.androidaps.interfaces.PluginBase;
import info.nightscout.androidaps.interfaces.PumpInterface;
import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin; import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin;
import info.nightscout.androidaps.plugins.Loop.events.EventLoopSetLastRunGui; import info.nightscout.androidaps.plugins.Loop.events.EventLoopSetLastRunGui;
import info.nightscout.androidaps.plugins.Loop.events.EventLoopUpdateGui; import info.nightscout.androidaps.plugins.Loop.events.EventLoopUpdateGui;
import info.nightscout.androidaps.plugins.Loop.events.EventNewOpenLoopNotification; import info.nightscout.androidaps.plugins.Loop.events.EventNewOpenLoopNotification;
import info.nightscout.androidaps.plugins.OpenAPSAMA.OpenAPSAMAPlugin; import info.nightscout.androidaps.queue.Callback;
import info.nightscout.utils.NSUpload; import info.nightscout.utils.NSUpload;
import info.nightscout.utils.SP; import info.nightscout.utils.SP;
import info.nightscout.utils.SafeParse;
/** /**
* Created by mike on 05.08.2016. * Created by mike on 05.08.2016.
@ -55,14 +52,12 @@ public class LoopPlugin implements PluginBase {
return loopPlugin; return loopPlugin;
} }
private static Handler sHandler;
private static HandlerThread sHandlerThread;
private boolean fragmentEnabled = false; private boolean fragmentEnabled = false;
private boolean fragmentVisible = false; private boolean fragmentVisible = false;
private long loopSuspendedTill = 0L; // end of manual loop suspend private long loopSuspendedTill = 0L; // end of manual loop suspend
private boolean isSuperBolus = false; private boolean isSuperBolus = false;
private boolean isDisconnected = false;
public class LastRun { public class LastRun {
public APSResult request = null; public APSResult request = null;
@ -77,14 +72,10 @@ public class LoopPlugin implements PluginBase {
static public LastRun lastRun = null; static public LastRun lastRun = null;
public LoopPlugin() { public LoopPlugin() {
if (sHandlerThread == null) {
sHandlerThread = new HandlerThread(LoopPlugin.class.getSimpleName());
sHandlerThread.start();
sHandler = new Handler(sHandlerThread.getLooper());
}
MainApp.bus().register(this); MainApp.bus().register(this);
loopSuspendedTill = SP.getLong("loopSuspendedTill", 0L); loopSuspendedTill = SP.getLong("loopSuspendedTill", 0L);
isSuperBolus = SP.getBoolean("isSuperBolus", false); isSuperBolus = SP.getBoolean("isSuperBolus", false);
isDisconnected = SP.getBoolean("isDisconnected", false);
} }
@Override @Override
@ -105,7 +96,7 @@ public class LoopPlugin implements PluginBase {
@Override @Override
public String getNameShort() { public String getNameShort() {
String name = MainApp.sResources.getString(R.string.loop_shortname); String name = MainApp.sResources.getString(R.string.loop_shortname);
if (!name.trim().isEmpty()){ if (!name.trim().isEmpty()) {
//only if translation exists //only if translation exists
return name; return name;
} }
@ -115,12 +106,14 @@ public class LoopPlugin implements PluginBase {
@Override @Override
public boolean isEnabled(int type) { public boolean isEnabled(int type) {
return type == LOOP && fragmentEnabled && MainApp.getConfigBuilder().getPumpDescription().isTempBasalCapable; boolean pumpCapable = ConfigBuilderPlugin.getActivePump() == null || ConfigBuilderPlugin.getActivePump().getPumpDescription().isTempBasalCapable;
return type == LOOP && fragmentEnabled && pumpCapable;
} }
@Override @Override
public boolean isVisibleInTabs(int type) { public boolean isVisibleInTabs(int type) {
return type == LOOP && fragmentVisible && MainApp.getConfigBuilder().getPumpDescription().isTempBasalCapable; boolean pumpCapable = ConfigBuilderPlugin.getActivePump() == null || ConfigBuilderPlugin.getActivePump().getPumpDescription().isTempBasalCapable;
return type == LOOP && fragmentVisible && pumpCapable;
} }
@Override @Override
@ -170,13 +163,28 @@ public class LoopPlugin implements PluginBase {
public void suspendTo(long endTime) { public void suspendTo(long endTime) {
loopSuspendedTill = endTime; loopSuspendedTill = endTime;
isSuperBolus = false; isSuperBolus = false;
isDisconnected = false;
SP.putLong("loopSuspendedTill", loopSuspendedTill); SP.putLong("loopSuspendedTill", loopSuspendedTill);
SP.putBoolean("isSuperBolus", isSuperBolus);
SP.putBoolean("isDisconnected", isDisconnected);
} }
public void superBolusTo(long endTime) { public void superBolusTo(long endTime) {
loopSuspendedTill = endTime; loopSuspendedTill = endTime;
isSuperBolus = true; isSuperBolus = true;
isDisconnected = false;
SP.putLong("loopSuspendedTill", loopSuspendedTill); SP.putLong("loopSuspendedTill", loopSuspendedTill);
SP.putBoolean("isSuperBolus", isSuperBolus);
SP.putBoolean("isDisconnected", isDisconnected);
}
public void disconnectTo(long endTime) {
loopSuspendedTill = endTime;
isSuperBolus = false;
isDisconnected = true;
SP.putLong("loopSuspendedTill", loopSuspendedTill);
SP.putBoolean("isSuperBolus", isSuperBolus);
SP.putBoolean("isDisconnected", isDisconnected);
} }
public int minutesToEndOfSuspend() { public int minutesToEndOfSuspend() {
@ -208,7 +216,7 @@ public class LoopPlugin implements PluginBase {
return true; return true;
} }
public boolean isSuperBolus() { public boolean isSuperBolus() {
if (loopSuspendedTill == 0) if (loopSuspendedTill == 0)
return false; return false;
@ -222,6 +230,19 @@ public class LoopPlugin implements PluginBase {
return isSuperBolus; return isSuperBolus;
} }
public boolean isDisconnected() {
if (loopSuspendedTill == 0)
return false;
long now = System.currentTimeMillis();
if (loopSuspendedTill <= now) { // time exceeded
suspendTo(0L);
return false;
}
return isDisconnected;
}
public void invoke(String initiator, boolean allowNotification) { public void invoke(String initiator, boolean allowNotification) {
try { try {
if (Config.logFunctionCalls) if (Config.logFunctionCalls)
@ -232,34 +253,22 @@ public class LoopPlugin implements PluginBase {
MainApp.bus().post(new EventLoopSetLastRunGui(MainApp.sResources.getString(R.string.loopdisabled))); MainApp.bus().post(new EventLoopSetLastRunGui(MainApp.sResources.getString(R.string.loopdisabled)));
return; return;
} }
final ConfigBuilderPlugin configBuilder = MainApp.getConfigBuilder(); final PumpInterface pump = ConfigBuilderPlugin.getActivePump();
APSResult result = null; APSResult result = null;
if (configBuilder == null || !isEnabled(PluginBase.LOOP)) if (!isEnabled(PluginBase.LOOP))
return; return;
if (isSuspended()) { if (MainApp.getConfigBuilder().getProfile() == null) {
log.debug(MainApp.sResources.getString(R.string.loopsuspended));
MainApp.bus().post(new EventLoopSetLastRunGui(MainApp.sResources.getString(R.string.loopsuspended)));
return;
}
if (configBuilder.isSuspended()) {
log.debug(MainApp.sResources.getString(R.string.pumpsuspended));
MainApp.bus().post(new EventLoopSetLastRunGui(MainApp.sResources.getString(R.string.pumpsuspended)));
return;
}
if (configBuilder.getProfile() == null) {
log.debug(MainApp.sResources.getString(R.string.noprofileselected)); log.debug(MainApp.sResources.getString(R.string.noprofileselected));
MainApp.bus().post(new EventLoopSetLastRunGui(MainApp.sResources.getString(R.string.noprofileselected))); MainApp.bus().post(new EventLoopSetLastRunGui(MainApp.sResources.getString(R.string.noprofileselected)));
return; return;
} }
// Check if pump info is loaded // Check if pump info is loaded
if (configBuilder.getBaseBasalRate() < 0.01d) return; if (pump.getBaseBasalRate() < 0.01d) return;
APSInterface usedAPS = configBuilder.getActiveAPS(); APSInterface usedAPS = ConfigBuilderPlugin.getActiveAPS();
if (usedAPS != null && ((PluginBase) usedAPS).isEnabled(PluginBase.APS)) { if (usedAPS != null && ((PluginBase) usedAPS).isEnabled(PluginBase.APS)) {
usedAPS.invoke(initiator); usedAPS.invoke(initiator);
result = usedAPS.getLastAPSResult(); result = usedAPS.getLastAPSResult();
@ -282,20 +291,33 @@ public class LoopPlugin implements PluginBase {
lastRun.source = ((PluginBase) usedAPS).getName(); lastRun.source = ((PluginBase) usedAPS).getName();
lastRun.setByPump = null; lastRun.setByPump = null;
if (constraintsInterface.isClosedModeEnabled()) { NSUpload.uploadDeviceStatus();
if (isSuspended()) {
log.debug(MainApp.sResources.getString(R.string.loopsuspended));
MainApp.bus().post(new EventLoopSetLastRunGui(MainApp.sResources.getString(R.string.loopsuspended)));
return;
}
if (pump.isSuspended()) {
log.debug(MainApp.sResources.getString(R.string.pumpsuspended));
MainApp.bus().post(new EventLoopSetLastRunGui(MainApp.sResources.getString(R.string.pumpsuspended)));
return;
}
if (constraintsInterface.isClosedModeEnabled()) {
if (result.changeRequested) { if (result.changeRequested) {
final PumpEnactResult waiting = new PumpEnactResult(); final PumpEnactResult waiting = new PumpEnactResult();
final PumpEnactResult previousResult = lastRun.setByPump; final PumpEnactResult previousResult = lastRun.setByPump;
waiting.queued = true; waiting.queued = true;
lastRun.setByPump = waiting; lastRun.setByPump = waiting;
MainApp.bus().post(new EventLoopUpdateGui()); MainApp.bus().post(new EventLoopUpdateGui());
sHandler.post(new Runnable() { MainApp.getConfigBuilder().applyAPSRequest(resultAfterConstraints, new Callback() {
@Override @Override
public void run() { public void run() {
final PumpEnactResult applyResult = configBuilder.applyAPSRequest(resultAfterConstraints);
Answers.getInstance().logCustom(new CustomEvent("APSRequest")); Answers.getInstance().logCustom(new CustomEvent("APSRequest"));
if (applyResult.enacted || applyResult.success) { if (result.enacted || result.success) {
lastRun.setByPump = applyResult; lastRun.setByPump = result;
lastRun.lastEnact = lastRun.lastAPSRun; lastRun.lastEnact = lastRun.lastAPSRun;
} else { } else {
lastRun.setByPump = previousResult; lastRun.setByPump = previousResult;
@ -343,7 +365,6 @@ public class LoopPlugin implements PluginBase {
} }
MainApp.bus().post(new EventLoopUpdateGui()); MainApp.bus().post(new EventLoopUpdateGui());
NSUpload.uploadDeviceStatus();
} finally { } finally {
if (Config.logFunctionCalls) if (Config.logFunctionCalls)
log.debug("invoke end"); log.debug("invoke end");

View file

@ -122,7 +122,7 @@ public class NSClientInternalPlugin implements PluginBase {
@Override @Override
public boolean showInList(int type) { public boolean showInList(int type) {
return !Config.NSCLIENT; return !Config.NSCLIENT && !Config.G5UPLOADER;
} }
@Override @Override
@ -222,4 +222,8 @@ public class NSClientInternalPlugin implements PluginBase {
public String url() { public String url() {
return NSClientService.nsURL; return NSClientService.nsURL;
} }
public boolean hasWritePermission() {
return nsClientService.hasWriteAuth;
}
} }

View file

@ -96,6 +96,8 @@ public class UploadQueue {
} }
public static void removeID(final String action, final String _id) { public static void removeID(final String action, final String _id) {
if (_id == null || _id.equals(""))
return;
startService(); startService();
if (NSClientService.handler != null) { if (NSClientService.handler != null) {
NSClientService.handler.post(new Runnable() { NSClientService.handler.post(new Runnable() {

View file

@ -1,10 +1,7 @@
package info.nightscout.androidaps.plugins.NSClientInternal.broadcasts; package info.nightscout.androidaps.plugins.NSClientInternal.broadcasts;
import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.content.pm.ResolveInfo;
import android.os.Bundle; import android.os.Bundle;
import android.os.TransactionTooLargeException;
import android.support.v4.content.LocalBroadcastManager; import android.support.v4.content.LocalBroadcastManager;
import org.json.JSONArray; import org.json.JSONArray;
@ -19,9 +16,7 @@ import java.util.List;
import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.R; import info.nightscout.androidaps.R;
import info.nightscout.androidaps.Services.Intents; import info.nightscout.androidaps.Services.Intents;
import info.nightscout.androidaps.plugins.NSClientInternal.data.NSTreatment;
import info.nightscout.utils.SP; import info.nightscout.utils.SP;
import info.nightscout.utils.ToastUtils;
/** /**
* Created by mike on 20.02.2016. * Created by mike on 20.02.2016.
@ -29,31 +24,32 @@ import info.nightscout.utils.ToastUtils;
public class BroadcastTreatment { public class BroadcastTreatment {
private static Logger log = LoggerFactory.getLogger(BroadcastTreatment.class); private static Logger log = LoggerFactory.getLogger(BroadcastTreatment.class);
public static void handleNewTreatment(NSTreatment treatment, Context context, boolean isDelta) { public static void handleNewTreatment(JSONObject treatment, boolean isDelta, boolean isLocalBypass) {
Bundle bundle = new Bundle(); Bundle bundle = new Bundle();
bundle.putString("treatment", treatment.getData().toString()); bundle.putString("treatment", treatment.toString());
bundle.putBoolean("delta", isDelta); bundle.putBoolean("delta", isDelta);
bundle.putBoolean("islocal", isLocalBypass);
Intent intent = new Intent(Intents.ACTION_NEW_TREATMENT); Intent intent = new Intent(Intents.ACTION_NEW_TREATMENT);
intent.putExtras(bundle); intent.putExtras(bundle);
intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES); intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES);
LocalBroadcastManager.getInstance(MainApp.instance()).sendBroadcast(intent); LocalBroadcastManager.getInstance(MainApp.instance()).sendBroadcast(intent);
if(SP.getBoolean(R.string.key_nsclient_localbroadcasts, true)) { if (SP.getBoolean(R.string.key_nsclient_localbroadcasts, true)) {
bundle = new Bundle(); bundle = new Bundle();
bundle.putString("treatment", treatment.getData().toString()); bundle.putString("treatment", treatment.toString());
bundle.putBoolean("delta", isDelta); bundle.putBoolean("delta", isDelta);
intent = new Intent(Intents.ACTION_NEW_TREATMENT); intent = new Intent(Intents.ACTION_NEW_TREATMENT);
intent.putExtras(bundle); intent.putExtras(bundle);
intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES); intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES);
context.sendBroadcast(intent); MainApp.instance().getApplicationContext().sendBroadcast(intent);
} }
} }
public static void handleNewTreatment(JSONArray treatments, Context context, boolean isDelta) { public static void handleNewTreatment(JSONArray treatments, boolean isDelta) {
List<JSONArray> splitted = splitArray(treatments); List<JSONArray> splitted = splitArray(treatments);
for (JSONArray part: splitted) { for (JSONArray part : splitted) {
Bundle bundle = new Bundle(); Bundle bundle = new Bundle();
bundle.putString("treatments", part.toString()); bundle.putString("treatments", part.toString());
bundle.putBoolean("delta", isDelta); bundle.putBoolean("delta", isDelta);
@ -63,21 +59,21 @@ public class BroadcastTreatment {
LocalBroadcastManager.getInstance(MainApp.instance()).sendBroadcast(intent); LocalBroadcastManager.getInstance(MainApp.instance()).sendBroadcast(intent);
} }
if(SP.getBoolean(R.string.key_nsclient_localbroadcasts, true)){ if (SP.getBoolean(R.string.key_nsclient_localbroadcasts, true)) {
splitted = splitArray(treatments); splitted = splitArray(treatments);
for (JSONArray part: splitted) { for (JSONArray part : splitted) {
Bundle bundle = new Bundle(); Bundle bundle = new Bundle();
bundle.putString("treatments", part.toString()); bundle.putString("treatments", part.toString());
bundle.putBoolean("delta", isDelta); bundle.putBoolean("delta", isDelta);
Intent intent = new Intent(Intents.ACTION_NEW_TREATMENT); Intent intent = new Intent(Intents.ACTION_NEW_TREATMENT);
intent.putExtras(bundle); intent.putExtras(bundle);
intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES); intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES);
context.sendBroadcast(intent); MainApp.instance().getApplicationContext().sendBroadcast(intent);
} }
} }
} }
public void handleChangedTreatment(JSONObject treatment, Context context, boolean isDelta) { public void handleChangedTreatment(JSONObject treatment, boolean isDelta) {
Bundle bundle = new Bundle(); Bundle bundle = new Bundle();
bundle.putString("treatment", treatment.toString()); bundle.putString("treatment", treatment.toString());
@ -88,18 +84,18 @@ public class BroadcastTreatment {
LocalBroadcastManager.getInstance(MainApp.instance()).sendBroadcast(intent); LocalBroadcastManager.getInstance(MainApp.instance()).sendBroadcast(intent);
if(SP.getBoolean(R.string.key_nsclient_localbroadcasts, true)) { if (SP.getBoolean(R.string.key_nsclient_localbroadcasts, true)) {
bundle = new Bundle(); bundle = new Bundle();
bundle.putString("treatment", treatment.toString()); bundle.putString("treatment", treatment.toString());
bundle.putBoolean("delta", isDelta); bundle.putBoolean("delta", isDelta);
intent = new Intent(Intents.ACTION_CHANGED_TREATMENT); intent = new Intent(Intents.ACTION_CHANGED_TREATMENT);
intent.putExtras(bundle); intent.putExtras(bundle);
intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES); intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES);
context.sendBroadcast(intent); MainApp.instance().getApplicationContext().sendBroadcast(intent);
} }
} }
public static void handleChangedTreatment(JSONArray treatments, Context context, boolean isDelta) { public static void handleChangedTreatment(JSONArray treatments, boolean isDelta) {
List<JSONArray> splitted = splitArray(treatments); List<JSONArray> splitted = splitArray(treatments);
for (JSONArray part : splitted) { for (JSONArray part : splitted) {
@ -112,7 +108,7 @@ public class BroadcastTreatment {
LocalBroadcastManager.getInstance(MainApp.instance()).sendBroadcast(intent); LocalBroadcastManager.getInstance(MainApp.instance()).sendBroadcast(intent);
} }
if(SP.getBoolean(R.string.key_nsclient_localbroadcasts, true)) { if (SP.getBoolean(R.string.key_nsclient_localbroadcasts, true)) {
splitted = splitArray(treatments); splitted = splitArray(treatments);
for (JSONArray part : splitted) { for (JSONArray part : splitted) {
Bundle bundle = new Bundle(); Bundle bundle = new Bundle();
@ -121,12 +117,12 @@ public class BroadcastTreatment {
Intent intent = new Intent(Intents.ACTION_CHANGED_TREATMENT); Intent intent = new Intent(Intents.ACTION_CHANGED_TREATMENT);
intent.putExtras(bundle); intent.putExtras(bundle);
intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES); intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES);
context.sendBroadcast(intent); MainApp.instance().getApplicationContext().sendBroadcast(intent);
} }
} }
} }
public static void handleRemovedTreatment(JSONObject treatment, Context context, boolean isDelta) { public static void handleRemovedTreatment(JSONObject treatment, boolean isDelta) {
Bundle bundle = new Bundle(); Bundle bundle = new Bundle();
bundle.putString("treatment", treatment.toString()); bundle.putString("treatment", treatment.toString());
@ -137,18 +133,18 @@ public class BroadcastTreatment {
LocalBroadcastManager.getInstance(MainApp.instance()).sendBroadcast(intent); LocalBroadcastManager.getInstance(MainApp.instance()).sendBroadcast(intent);
if(SP.getBoolean(R.string.key_nsclient_localbroadcasts, true)) { if (SP.getBoolean(R.string.key_nsclient_localbroadcasts, true)) {
bundle = new Bundle(); bundle = new Bundle();
bundle.putString("treatment", treatment.toString()); bundle.putString("treatment", treatment.toString());
bundle.putBoolean("delta", isDelta); bundle.putBoolean("delta", isDelta);
intent = new Intent(Intents.ACTION_REMOVED_TREATMENT); intent = new Intent(Intents.ACTION_REMOVED_TREATMENT);
intent.putExtras(bundle); intent.putExtras(bundle);
intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES); intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES);
context.sendBroadcast(intent); MainApp.instance().getApplicationContext().sendBroadcast(intent);
} }
} }
public static void handleRemovedTreatment(JSONArray treatments, Context context, boolean isDelta) { public static void handleRemovedTreatment(JSONArray treatments, boolean isDelta) {
Bundle bundle = new Bundle(); Bundle bundle = new Bundle();
bundle.putString("treatments", treatments.toString()); bundle.putString("treatments", treatments.toString());
@ -159,14 +155,14 @@ public class BroadcastTreatment {
LocalBroadcastManager.getInstance(MainApp.instance()).sendBroadcast(intent); LocalBroadcastManager.getInstance(MainApp.instance()).sendBroadcast(intent);
if(SP.getBoolean(R.string.key_nsclient_localbroadcasts, true)) { if (SP.getBoolean(R.string.key_nsclient_localbroadcasts, true)) {
bundle = new Bundle(); bundle = new Bundle();
bundle.putString("treatments", treatments.toString()); bundle.putString("treatments", treatments.toString());
bundle.putBoolean("delta", isDelta); bundle.putBoolean("delta", isDelta);
intent = new Intent(Intents.ACTION_REMOVED_TREATMENT); intent = new Intent(Intents.ACTION_REMOVED_TREATMENT);
intent.putExtras(bundle); intent.putExtras(bundle);
intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES); intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES);
context.sendBroadcast(intent); MainApp.instance().getApplicationContext().sendBroadcast(intent);
} }
} }

View file

@ -308,6 +308,15 @@ public class NSDeviceStatus {
return Html.fromHtml(string.toString()); return Html.fromHtml(string.toString());
} }
public static long getOpenApsTimestamp() {
if (deviceStatusOpenAPSData.clockSuggested != 0) {
return deviceStatusOpenAPSData.clockSuggested;
} else {
return -1;
}
}
public Spanned getExtendedOpenApsStatus() { public Spanned getExtendedOpenApsStatus() {
StringBuilder string = new StringBuilder(); StringBuilder string = new StringBuilder();

View file

@ -63,5 +63,6 @@ public class NSSgv {
public Long getMills () { return getLongOrNull("mills"); } public Long getMills () { return getLongOrNull("mills"); }
public String getDevice () { return getStringOrNull("device"); } public String getDevice () { return getStringOrNull("device"); }
public String getDirection () { return getStringOrNull("direction"); } public String getDirection () { return getStringOrNull("direction"); }
public String getId () { return getStringOrNull("_id"); }
} }

View file

@ -11,16 +11,14 @@ import org.json.JSONObject;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import java.util.Date;
import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.R; import info.nightscout.androidaps.R;
import info.nightscout.androidaps.db.DbRequest;
import info.nightscout.androidaps.interfaces.PluginBase; import info.nightscout.androidaps.interfaces.PluginBase;
import info.nightscout.androidaps.plugins.NSClientInternal.NSClientInternalPlugin; import info.nightscout.androidaps.plugins.NSClientInternal.NSClientInternalPlugin;
import info.nightscout.androidaps.plugins.NSClientInternal.UploadQueue; import info.nightscout.androidaps.plugins.NSClientInternal.UploadQueue;
import info.nightscout.androidaps.db.DbRequest; import info.nightscout.androidaps.plugins.NSClientInternal.broadcasts.BroadcastTreatment;
import info.nightscout.androidaps.plugins.NSClientInternal.data.AlarmAck; import info.nightscout.utils.DateUtil;
import info.nightscout.androidaps.plugins.NSClientInternal.services.NSClientService;
import info.nightscout.utils.SP; import info.nightscout.utils.SP;
public class DBAccessReceiver extends BroadcastReceiver { public class DBAccessReceiver extends BroadcastReceiver {
@ -32,14 +30,6 @@ public class DBAccessReceiver extends BroadcastReceiver {
PowerManager powerManager = (PowerManager) context.getSystemService(Context.POWER_SERVICE); PowerManager powerManager = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
PowerManager.WakeLock wakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, PowerManager.WakeLock wakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
DBAccessReceiver.class.getSimpleName()); DBAccessReceiver.class.getSimpleName());
NSClientInternalPlugin nsClientInternalPlugin = MainApp.getSpecificPlugin(NSClientInternalPlugin.class);
if (!nsClientInternalPlugin.isEnabled(PluginBase.GENERAL)) {
return;
}
if (SP.getBoolean(R.string.key_ns_noupload, false)) {
log.debug("Upload disabled. Message dropped");
return;
}
wakeLock.acquire(); wakeLock.acquire();
try { try {
Bundle bundles = intent.getExtras(); Bundle bundles = intent.getExtras();
@ -85,11 +75,27 @@ public class DBAccessReceiver extends BroadcastReceiver {
} }
if (action.equals("dbRemove")) { if (action.equals("dbRemove")) {
DbRequest dbr = new DbRequest(action, collection, nsclientid.toString(), _id); if (shouldUpload()) {
UploadQueue.add(dbr); DbRequest dbr = new DbRequest(action, collection, nsclientid.toString(), _id);
UploadQueue.add(dbr);
}
} else if (action.equals("dbUpdate")) {
if (shouldUpload()) {
DbRequest dbr = new DbRequest(action, collection, nsclientid.toString(), _id, data);
UploadQueue.add(dbr);
}
} else { } else {
DbRequest dbr = new DbRequest(action, collection, nsclientid.toString(), data); DbRequest dbr = new DbRequest(action, collection, nsclientid.toString(), data);
UploadQueue.add(dbr); // this is not used as mongo _id but only for searching in UploadQueue database
// if record has to be removed from queue before upload
dbr._id = nsclientid.toString();
if (shouldUpload()) {
UploadQueue.add(dbr);
}
if (collection.equals("treatments")) {
genereateTreatmentOfflineBroadcast(dbr);
}
} }
} finally { } finally {
@ -98,6 +104,24 @@ public class DBAccessReceiver extends BroadcastReceiver {
} }
public boolean shouldUpload() {
NSClientInternalPlugin nsClientInternalPlugin = MainApp.getSpecificPlugin(NSClientInternalPlugin.class);
return nsClientInternalPlugin.isEnabled(PluginBase.GENERAL) && !SP.getBoolean(R.string.key_ns_noupload, false);
}
public void genereateTreatmentOfflineBroadcast(DbRequest request) {
if (request.action.equals("dbAdd")) {
try {
JSONObject data = new JSONObject(request.data);
data.put("mills", DateUtil.fromISODateString(data.getString("created_at")).getTime());
data.put("_id", data.get("NSCLIENT_ID")); // this is only fake id
BroadcastTreatment.handleNewTreatment(data, false, true);
} catch (Exception e) {
log.error("Unhadled exception", e);
}
}
}
private boolean isAllowedCollection(String collection) { private boolean isAllowedCollection(String collection) {
// "treatments" || "entries" || "devicestatus" || "profile" || "food" // "treatments" || "entries" || "devicestatus" || "profile" || "food"
if (collection.equals("treatments")) return true; if (collection.equals("treatments")) return true;

View file

@ -52,15 +52,15 @@ import info.nightscout.androidaps.plugins.NSClientInternal.broadcasts.BroadcastS
import info.nightscout.androidaps.plugins.NSClientInternal.broadcasts.BroadcastTreatment; import info.nightscout.androidaps.plugins.NSClientInternal.broadcasts.BroadcastTreatment;
import info.nightscout.androidaps.plugins.NSClientInternal.broadcasts.BroadcastUrgentAlarm; import info.nightscout.androidaps.plugins.NSClientInternal.broadcasts.BroadcastUrgentAlarm;
import info.nightscout.androidaps.plugins.NSClientInternal.data.AlarmAck; import info.nightscout.androidaps.plugins.NSClientInternal.data.AlarmAck;
import info.nightscout.androidaps.plugins.NSClientInternal.data.NSSgv;
import info.nightscout.androidaps.plugins.NSClientInternal.data.NSSettingsStatus; import info.nightscout.androidaps.plugins.NSClientInternal.data.NSSettingsStatus;
import info.nightscout.androidaps.plugins.NSClientInternal.data.NSSgv;
import info.nightscout.androidaps.plugins.NSClientInternal.data.NSTreatment; import info.nightscout.androidaps.plugins.NSClientInternal.data.NSTreatment;
import info.nightscout.androidaps.plugins.NSClientInternal.events.EventNSClientNewLog; import info.nightscout.androidaps.plugins.NSClientInternal.events.EventNSClientNewLog;
import info.nightscout.androidaps.plugins.NSClientInternal.events.EventNSClientRestart; import info.nightscout.androidaps.plugins.NSClientInternal.events.EventNSClientRestart;
import info.nightscout.androidaps.plugins.NSClientInternal.events.EventNSClientStatus; import info.nightscout.androidaps.plugins.NSClientInternal.events.EventNSClientStatus;
import info.nightscout.androidaps.plugins.Overview.Notification;
import info.nightscout.androidaps.plugins.Overview.events.EventDismissNotification; import info.nightscout.androidaps.plugins.Overview.events.EventDismissNotification;
import info.nightscout.androidaps.plugins.Overview.events.EventNewNotification; import info.nightscout.androidaps.plugins.Overview.events.EventNewNotification;
import info.nightscout.androidaps.plugins.Overview.notifications.Notification;
import info.nightscout.utils.DateUtil; import info.nightscout.utils.DateUtil;
import info.nightscout.utils.SP; import info.nightscout.utils.SP;
import io.socket.client.IO; import io.socket.client.IO;
@ -114,6 +114,18 @@ public class NSClientService extends Service {
initialize(); initialize();
} }
@Override
public void onCreate() {
super.onCreate();
mWakeLock.acquire();
}
@Override
public void onDestroy() {
super.onDestroy();
mWakeLock.release();
}
public class LocalBinder extends Binder { public class LocalBinder extends Binder {
public NSClientService getServiceInstance() { public NSClientService getServiceInstance() {
return NSClientService.this; return NSClientService.this;
@ -182,8 +194,6 @@ public class NSClientService extends Service {
public void initialize() { public void initialize() {
dataCounter = 0; dataCounter = 0;
NSClientService.mWakeLock.acquire();
readPreferences(); readPreferences();
if (!nsAPISecret.equals("")) if (!nsAPISecret.equals(""))
@ -221,7 +231,6 @@ public class NSClientService extends Service {
MainApp.bus().post(new EventNSClientNewLog("NSCLIENT", "No NS URL specified")); MainApp.bus().post(new EventNSClientNewLog("NSCLIENT", "No NS URL specified"));
MainApp.bus().post(new EventNSClientStatus("Not configured")); MainApp.bus().post(new EventNSClientStatus("Not configured"));
} }
NSClientService.mWakeLock.release();
} }
private Emitter.Listener onConnect = new Emitter.Listener() { private Emitter.Listener onConnect = new Emitter.Listener() {
@ -242,6 +251,15 @@ public class NSClientService extends Service {
public void destroy() { public void destroy() {
if (mSocket != null) { if (mSocket != null) {
mSocket.off(Socket.EVENT_CONNECT);
mSocket.off(Socket.EVENT_DISCONNECT);
mSocket.off(Socket.EVENT_PING);
mSocket.off("dataUpdate");
mSocket.off("announcement");
mSocket.off("alarm");
mSocket.off("urgent_alarm");
mSocket.off("clear_alarm");
MainApp.bus().post(new EventNSClientNewLog("NSCLIENT", "destroy")); MainApp.bus().post(new EventNSClientNewLog("NSCLIENT", "destroy"));
isConnected = false; isConnected = false;
hasWriteAuth = false; hasWriteAuth = false;
@ -310,17 +328,17 @@ public class NSClientService extends Service {
}; };
private Emitter.Listener onAnnouncement = new Emitter.Listener() { private Emitter.Listener onAnnouncement = new Emitter.Listener() {
/* /*
{ {
"level":0, "level":0,
"title":"Announcement", "title":"Announcement",
"message":"test", "message":"test",
"plugin":{"name":"treatmentnotify","label":"Treatment Notifications","pluginType":"notification","enabled":true}, "plugin":{"name":"treatmentnotify","label":"Treatment Notifications","pluginType":"notification","enabled":true},
"group":"Announcement", "group":"Announcement",
"isAnnouncement":true, "isAnnouncement":true,
"key":"9ac46ad9a1dcda79dd87dae418fce0e7955c68da" "key":"9ac46ad9a1dcda79dd87dae418fce0e7955c68da"
} }
*/ */
@Override @Override
public void call(final Object... args) { public void call(final Object... args) {
JSONObject data; JSONObject data;
@ -342,19 +360,19 @@ public class NSClientService extends Service {
}; };
private Emitter.Listener onAlarm = new Emitter.Listener() { private Emitter.Listener onAlarm = new Emitter.Listener() {
/* /*
{ {
"level":1, "level":1,
"title":"Warning HIGH", "title":"Warning HIGH",
"message":"BG Now: 5 -0.2 → mmol\/L\nRaw BG: 4.8 mmol\/L Čistý\nBG 15m: 4.8 mmol\/L\nIOB: -0.02U\nCOB: 0g", "message":"BG Now: 5 -0.2 → mmol\/L\nRaw BG: 4.8 mmol\/L Čistý\nBG 15m: 4.8 mmol\/L\nIOB: -0.02U\nCOB: 0g",
"eventName":"high", "eventName":"high",
"plugin":{"name":"simplealarms","label":"Simple Alarms","pluginType":"notification","enabled":true}, "plugin":{"name":"simplealarms","label":"Simple Alarms","pluginType":"notification","enabled":true},
"pushoverSound":"climb", "pushoverSound":"climb",
"debug":{"lastSGV":5,"thresholds":{"bgHigh":180,"bgTargetTop":75,"bgTargetBottom":72,"bgLow":70}}, "debug":{"lastSGV":5,"thresholds":{"bgHigh":180,"bgTargetTop":75,"bgTargetBottom":72,"bgLow":70}},
"group":"default", "group":"default",
"key":"simplealarms_1" "key":"simplealarms_1"
} }
*/ */
@Override @Override
public void call(final Object... args) { public void call(final Object... args) {
if (Config.detailedLog) if (Config.detailedLog)
@ -372,19 +390,19 @@ public class NSClientService extends Service {
}; };
private Emitter.Listener onUrgentAlarm = new Emitter.Listener() { private Emitter.Listener onUrgentAlarm = new Emitter.Listener() {
/* /*
{ {
"level":2, "level":2,
"title":"Urgent HIGH", "title":"Urgent HIGH",
"message":"BG Now: 5.2 -0.1 → mmol\/L\nRaw BG: 5 mmol\/L Čistý\nBG 15m: 5 mmol\/L\nIOB: 0.00U\nCOB: 0g", "message":"BG Now: 5.2 -0.1 → mmol\/L\nRaw BG: 5 mmol\/L Čistý\nBG 15m: 5 mmol\/L\nIOB: 0.00U\nCOB: 0g",
"eventName":"high", "eventName":"high",
"plugin":{"name":"simplealarms","label":"Simple Alarms","pluginType":"notification","enabled":true}, "plugin":{"name":"simplealarms","label":"Simple Alarms","pluginType":"notification","enabled":true},
"pushoverSound":"persistent", "pushoverSound":"persistent",
"debug":{"lastSGV":5.2,"thresholds":{"bgHigh":80,"bgTargetTop":75,"bgTargetBottom":72,"bgLow":70}}, "debug":{"lastSGV":5.2,"thresholds":{"bgHigh":80,"bgTargetTop":75,"bgTargetBottom":72,"bgLow":70}},
"group":"default", "group":"default",
"key":"simplealarms_2" "key":"simplealarms_2"
} }
*/ */
@Override @Override
public void call(final Object... args) { public void call(final Object... args) {
JSONObject data; JSONObject data;
@ -402,14 +420,14 @@ public class NSClientService extends Service {
}; };
private Emitter.Listener onClearAlarm = new Emitter.Listener() { private Emitter.Listener onClearAlarm = new Emitter.Listener() {
/* /*
{ {
"clear":true, "clear":true,
"title":"All Clear", "title":"All Clear",
"message":"default - Urgent was ack'd", "message":"default - Urgent was ack'd",
"group":"default" "group":"default"
} }
*/ */
@Override @Override
public void call(final Object... args) { public void call(final Object... args) {
JSONObject data; JSONObject data;
@ -520,17 +538,17 @@ public class NSClientService extends Service {
updatedTreatments.put(jsonTreatment); updatedTreatments.put(jsonTreatment);
} else if (treatment.getAction().equals("remove")) { } else if (treatment.getAction().equals("remove")) {
if (treatment.getMills() != null && treatment.getMills() > System.currentTimeMillis() - 24 * 60 * 60 * 1000L) // handle 1 day old deletions only if (treatment.getMills() != null && treatment.getMills() > System.currentTimeMillis() - 24 * 60 * 60 * 1000L) // handle 1 day old deletions only
removedTreatments.put(jsonTreatment); removedTreatments.put(jsonTreatment);
} }
} }
if (removedTreatments.length() > 0) { if (removedTreatments.length() > 0) {
BroadcastTreatment.handleRemovedTreatment(removedTreatments, MainApp.instance().getApplicationContext(), isDelta); BroadcastTreatment.handleRemovedTreatment(removedTreatments, isDelta);
} }
if (updatedTreatments.length() > 0) { if (updatedTreatments.length() > 0) {
BroadcastTreatment.handleChangedTreatment(updatedTreatments, MainApp.instance().getApplicationContext(), isDelta); BroadcastTreatment.handleChangedTreatment(updatedTreatments, isDelta);
} }
if (addedTreatments.length() > 0) { if (addedTreatments.length() > 0) {
BroadcastTreatment.handleNewTreatment(addedTreatments, MainApp.instance().getApplicationContext(), isDelta); BroadcastTreatment.handleNewTreatment(addedTreatments, isDelta);
} }
} }
if (data.has("devicestatus")) { if (data.has("devicestatus")) {
@ -632,6 +650,13 @@ public class NSClientService extends Service {
if (sgv.getMills() > latestDateInReceivedData) if (sgv.getMills() > latestDateInReceivedData)
latestDateInReceivedData = sgv.getMills(); latestDateInReceivedData = sgv.getMills();
} }
// Was that sgv more less 15 mins ago ?
boolean lessThan15MinAgo = false;
if ((System.currentTimeMillis() - latestDateInReceivedData) / (60 * 1000L) < 15L)
lessThan15MinAgo = true;
if (Notification.isAlarmForStaleData() && lessThan15MinAgo) {
MainApp.bus().post(new EventDismissNotification(Notification.NSALARM));
}
BroadcastSgvs.handleNewSgv(sgvs, MainApp.instance().getApplicationContext(), isDelta); BroadcastSgvs.handleNewSgv(sgvs, MainApp.instance().getApplicationContext(), isDelta);
} }
MainApp.bus().post(new EventNSClientNewLog("LAST", DateUtil.dateAndTimeString(latestDateInReceivedData))); MainApp.bus().post(new EventNSClientNewLog("LAST", DateUtil.dateAndTimeString(latestDateInReceivedData)));
@ -750,7 +775,7 @@ public class NSClientService extends Service {
public void run() { public void run() {
if (mSocket == null || !mSocket.connected()) return; if (mSocket == null || !mSocket.connected()) return;
if (lastResendTime > System.currentTimeMillis() - 10 * 1000L) { if (lastResendTime > System.currentTimeMillis() - 10 * 1000L) {
log.debug("Skipping resend by lastResendTime: " + ((System.currentTimeMillis() - lastResendTime) / 1000L) + " sec"); log.debug("Skipping resend by lastResendTime: " + ((System.currentTimeMillis() - lastResendTime) / 1000L) + " sec");
return; return;
} }

View file

@ -17,7 +17,6 @@ import org.slf4j.LoggerFactory;
import java.io.IOException; import java.io.IOException;
import java.lang.reflect.InvocationTargetException; import java.lang.reflect.InvocationTargetException;
import java.util.Date;
import info.nightscout.androidaps.Config; import info.nightscout.androidaps.Config;
import info.nightscout.androidaps.Constants; import info.nightscout.androidaps.Constants;
@ -25,11 +24,10 @@ import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.data.GlucoseStatus; import info.nightscout.androidaps.data.GlucoseStatus;
import info.nightscout.androidaps.data.IobTotal; import info.nightscout.androidaps.data.IobTotal;
import info.nightscout.androidaps.data.MealData; import info.nightscout.androidaps.data.MealData;
import info.nightscout.androidaps.data.Profile;
import info.nightscout.androidaps.db.TemporaryBasal; import info.nightscout.androidaps.db.TemporaryBasal;
import info.nightscout.androidaps.interfaces.PumpInterface;
import info.nightscout.androidaps.plugins.IobCobCalculator.IobCobCalculatorPlugin; import info.nightscout.androidaps.plugins.IobCobCalculator.IobCobCalculatorPlugin;
import info.nightscout.androidaps.plugins.Loop.ScriptReader; import info.nightscout.androidaps.plugins.Loop.ScriptReader;
import info.nightscout.androidaps.data.Profile;
import info.nightscout.androidaps.plugins.OpenAPSMA.LoggerCallback; import info.nightscout.androidaps.plugins.OpenAPSMA.LoggerCallback;
import info.nightscout.utils.SP; import info.nightscout.utils.SP;
@ -186,7 +184,7 @@ public class DetermineBasalAdapterAMAJS {
double minBg, double minBg,
double maxBg, double maxBg,
double targetBg, double targetBg,
PumpInterface pump, double basalrate,
IobTotal[] iobArray, IobTotal[] iobArray,
GlucoseStatus glucoseStatus, GlucoseStatus glucoseStatus,
MealData mealData, MealData mealData,
@ -210,7 +208,7 @@ public class DetermineBasalAdapterAMAJS {
mProfile.put("max_daily_safety_multiplier", SP.getInt("openapsama_max_daily_safety_multiplier", 3)); mProfile.put("max_daily_safety_multiplier", SP.getInt("openapsama_max_daily_safety_multiplier", 3));
mProfile.put("current_basal_safety_multiplier", SP.getInt("openapsama_current_basal_safety_multiplier", 4)); mProfile.put("current_basal_safety_multiplier", SP.getInt("openapsama_current_basal_safety_multiplier", 4));
mProfile.put("skip_neutral_temps", true); mProfile.put("skip_neutral_temps", true);
mProfile.put("current_basal", pump.getBaseBasalRate()); mProfile.put("current_basal", basalrate);
mProfile.put("temptargetSet", tempTargetSet); mProfile.put("temptargetSet", tempTargetSet);
mProfile.put("autosens_adjust_targets", SP.getBoolean("openapsama_autosens_adjusttargets", true)); mProfile.put("autosens_adjust_targets", SP.getBoolean("openapsama_autosens_adjusttargets", true));
mProfile.put("min_5m_carbimpact", SP.getDouble("openapsama_min_5m_carbimpact", 3d)); mProfile.put("min_5m_carbimpact", SP.getDouble("openapsama_min_5m_carbimpact", 3d));

View file

@ -14,15 +14,15 @@ import info.nightscout.androidaps.R;
import info.nightscout.androidaps.data.GlucoseStatus; import info.nightscout.androidaps.data.GlucoseStatus;
import info.nightscout.androidaps.data.IobTotal; import info.nightscout.androidaps.data.IobTotal;
import info.nightscout.androidaps.data.MealData; import info.nightscout.androidaps.data.MealData;
import info.nightscout.androidaps.data.Profile;
import info.nightscout.androidaps.db.TempTarget; import info.nightscout.androidaps.db.TempTarget;
import info.nightscout.androidaps.interfaces.APSInterface; import info.nightscout.androidaps.interfaces.APSInterface;
import info.nightscout.androidaps.interfaces.PluginBase; import info.nightscout.androidaps.interfaces.PluginBase;
import info.nightscout.androidaps.interfaces.PumpInterface; import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin;
import info.nightscout.androidaps.plugins.IobCobCalculator.AutosensResult; import info.nightscout.androidaps.plugins.IobCobCalculator.AutosensResult;
import info.nightscout.androidaps.plugins.IobCobCalculator.IobCobCalculatorPlugin; import info.nightscout.androidaps.plugins.IobCobCalculator.IobCobCalculatorPlugin;
import info.nightscout.androidaps.plugins.Loop.APSResult; import info.nightscout.androidaps.plugins.Loop.APSResult;
import info.nightscout.androidaps.plugins.Loop.ScriptReader; import info.nightscout.androidaps.plugins.Loop.ScriptReader;
import info.nightscout.androidaps.data.Profile;
import info.nightscout.androidaps.plugins.OpenAPSMA.events.EventOpenAPSUpdateGui; import info.nightscout.androidaps.plugins.OpenAPSMA.events.EventOpenAPSUpdateGui;
import info.nightscout.androidaps.plugins.OpenAPSMA.events.EventOpenAPSUpdateResultGui; import info.nightscout.androidaps.plugins.OpenAPSMA.events.EventOpenAPSUpdateResultGui;
import info.nightscout.utils.DateUtil; import info.nightscout.utils.DateUtil;
@ -75,12 +75,14 @@ public class OpenAPSAMAPlugin implements PluginBase, APSInterface {
@Override @Override
public boolean isEnabled(int type) { public boolean isEnabled(int type) {
return type == APS && fragmentEnabled && MainApp.getConfigBuilder().getPumpDescription().isTempBasalCapable; boolean pumpCapable = ConfigBuilderPlugin.getActivePump() == null || ConfigBuilderPlugin.getActivePump().getPumpDescription().isTempBasalCapable;
return type == APS && fragmentEnabled && pumpCapable;
} }
@Override @Override
public boolean isVisibleInTabs(int type) { public boolean isVisibleInTabs(int type) {
return type == APS && fragmentVisible && MainApp.getConfigBuilder().getPumpDescription().isTempBasalCapable; boolean pumpCapable = ConfigBuilderPlugin.getActivePump() == null || ConfigBuilderPlugin.getActivePump().getPumpDescription().isTempBasalCapable;
return type == APS && fragmentVisible && pumpCapable;
} }
@Override @Override
@ -137,7 +139,7 @@ public class OpenAPSAMAPlugin implements PluginBase, APSInterface {
public void invoke(String initiator) { public void invoke(String initiator) {
log.debug("invoke from " + initiator); log.debug("invoke from " + initiator);
lastAPSResult = null; lastAPSResult = null;
DetermineBasalAdapterAMAJS determineBasalAdapterAMAJS = null; DetermineBasalAdapterAMAJS determineBasalAdapterAMAJS;
try { try {
determineBasalAdapterAMAJS = new DetermineBasalAdapterAMAJS(new ScriptReader(MainApp.instance().getBaseContext())); determineBasalAdapterAMAJS = new DetermineBasalAdapterAMAJS(new ScriptReader(MainApp.instance().getBaseContext()));
} catch (IOException e) { } catch (IOException e) {
@ -147,7 +149,6 @@ public class OpenAPSAMAPlugin implements PluginBase, APSInterface {
GlucoseStatus glucoseStatus = GlucoseStatus.getGlucoseStatusData(); GlucoseStatus glucoseStatus = GlucoseStatus.getGlucoseStatusData();
Profile profile = MainApp.getConfigBuilder().getProfile(); Profile profile = MainApp.getConfigBuilder().getProfile();
PumpInterface pump = MainApp.getConfigBuilder();
if (profile == null) { if (profile == null) {
MainApp.bus().post(new EventOpenAPSUpdateResultGui(MainApp.instance().getString(R.string.noprofileselected))); MainApp.bus().post(new EventOpenAPSUpdateResultGui(MainApp.instance().getString(R.string.noprofileselected)));
@ -215,7 +216,8 @@ public class OpenAPSAMAPlugin implements PluginBase, APSInterface {
if (!checkOnlyHardLimits(Profile.toMgdl(profile.getIsf(), units), "sens", 2, 900)) if (!checkOnlyHardLimits(Profile.toMgdl(profile.getIsf(), units), "sens", 2, 900))
return; return;
if (!checkOnlyHardLimits(profile.getMaxDailyBasal(), "max_daily_basal", 0.1, 10)) return; if (!checkOnlyHardLimits(profile.getMaxDailyBasal(), "max_daily_basal", 0.1, 10)) return;
if (!checkOnlyHardLimits(pump.getBaseBasalRate(), "current_basal", 0.01, 5)) return; if (!checkOnlyHardLimits(ConfigBuilderPlugin.getActivePump().getBaseBasalRate(), "current_basal", 0.01, 5))
return;
startPart = new Date(); startPart = new Date();
if (MainApp.getConfigBuilder().isAMAModeEnabled()) { if (MainApp.getConfigBuilder().isAMAModeEnabled()) {
@ -229,7 +231,7 @@ public class OpenAPSAMAPlugin implements PluginBase, APSInterface {
start = new Date(); start = new Date();
try { try {
determineBasalAdapterAMAJS.setData(profile, maxIob, maxBasal, minBg, maxBg, targetBg, pump, iobArray, glucoseStatus, mealData, determineBasalAdapterAMAJS.setData(profile, maxIob, maxBasal, minBg, maxBg, targetBg, ConfigBuilderPlugin.getActivePump().getBaseBasalRate(), iobArray, glucoseStatus, mealData,
lastAutosensResult.ratio, //autosensDataRatio lastAutosensResult.ratio, //autosensDataRatio
isTempTarget, isTempTarget,
SafeParse.stringToDouble(SP.getString("openapsama_min_5m_carbimpact", "3.0"))//min_5m_carbimpact SafeParse.stringToDouble(SP.getString("openapsama_min_5m_carbimpact", "3.0"))//min_5m_carbimpact
@ -246,9 +248,11 @@ public class OpenAPSAMAPlugin implements PluginBase, APSInterface {
determineBasalResultAMA.changeRequested = false; determineBasalResultAMA.changeRequested = false;
// limit requests on openloop mode // limit requests on openloop mode
if (!MainApp.getConfigBuilder().isClosedModeEnabled()) { if (!MainApp.getConfigBuilder().isClosedModeEnabled()) {
if (MainApp.getConfigBuilder().isTempBasalInProgress() && Math.abs(determineBasalResultAMA.rate - MainApp.getConfigBuilder().getTempBasalAbsoluteRateHistory()) < 0.1) if (MainApp.getConfigBuilder().isTempBasalInProgress() && determineBasalResultAMA.rate == 0 && determineBasalResultAMA.duration == 0) {
// going to cancel
} else if (MainApp.getConfigBuilder().isTempBasalInProgress() && Math.abs(determineBasalResultAMA.rate - MainApp.getConfigBuilder().getTempBasalAbsoluteRateHistory()) < 0.1) {
determineBasalResultAMA.changeRequested = false; determineBasalResultAMA.changeRequested = false;
if (!MainApp.getConfigBuilder().isTempBasalInProgress() && Math.abs(determineBasalResultAMA.rate - MainApp.getConfigBuilder().getBaseBasalRate()) < 0.1) } else if (!MainApp.getConfigBuilder().isTempBasalInProgress() && Math.abs(determineBasalResultAMA.rate - ConfigBuilderPlugin.getActivePump().getBaseBasalRate()) < 0.1)
determineBasalResultAMA.changeRequested = false; determineBasalResultAMA.changeRequested = false;
} }

View file

@ -22,9 +22,8 @@ import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.data.GlucoseStatus; import info.nightscout.androidaps.data.GlucoseStatus;
import info.nightscout.androidaps.data.IobTotal; import info.nightscout.androidaps.data.IobTotal;
import info.nightscout.androidaps.data.MealData; import info.nightscout.androidaps.data.MealData;
import info.nightscout.androidaps.interfaces.PumpInterface;
import info.nightscout.androidaps.plugins.Loop.ScriptReader;
import info.nightscout.androidaps.data.Profile; import info.nightscout.androidaps.data.Profile;
import info.nightscout.androidaps.plugins.Loop.ScriptReader;
import info.nightscout.utils.SP; import info.nightscout.utils.SP;
public class DetermineBasalAdapterMAJS { public class DetermineBasalAdapterMAJS {
@ -155,7 +154,7 @@ public class DetermineBasalAdapterMAJS {
double minBg, double minBg,
double maxBg, double maxBg,
double targetBg, double targetBg,
PumpInterface pump, double basalRate,
IobTotal iobData, IobTotal iobData,
GlucoseStatus glucoseStatus, GlucoseStatus glucoseStatus,
MealData mealData) throws JSONException { MealData mealData) throws JSONException {
@ -174,7 +173,7 @@ public class DetermineBasalAdapterMAJS {
mProfile.put("carb_ratio", profile.getIc()); mProfile.put("carb_ratio", profile.getIc());
mProfile.put("sens", Profile.toMgdl(profile.getIsf().doubleValue(), units)); mProfile.put("sens", Profile.toMgdl(profile.getIsf().doubleValue(), units));
mProfile.put("current_basal", pump.getBaseBasalRate()); mProfile.put("current_basal", basalRate);
if (units.equals(Constants.MMOL)) { if (units.equals(Constants.MMOL)) {
mProfile.put("out_units", "mmol/L"); mProfile.put("out_units", "mmol/L");

View file

@ -14,13 +14,13 @@ import info.nightscout.androidaps.R;
import info.nightscout.androidaps.data.GlucoseStatus; import info.nightscout.androidaps.data.GlucoseStatus;
import info.nightscout.androidaps.data.IobTotal; import info.nightscout.androidaps.data.IobTotal;
import info.nightscout.androidaps.data.MealData; import info.nightscout.androidaps.data.MealData;
import info.nightscout.androidaps.data.Profile;
import info.nightscout.androidaps.db.TempTarget; import info.nightscout.androidaps.db.TempTarget;
import info.nightscout.androidaps.interfaces.APSInterface; import info.nightscout.androidaps.interfaces.APSInterface;
import info.nightscout.androidaps.interfaces.PluginBase; import info.nightscout.androidaps.interfaces.PluginBase;
import info.nightscout.androidaps.interfaces.PumpInterface; import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin;
import info.nightscout.androidaps.plugins.Loop.APSResult; import info.nightscout.androidaps.plugins.Loop.APSResult;
import info.nightscout.androidaps.plugins.Loop.ScriptReader; import info.nightscout.androidaps.plugins.Loop.ScriptReader;
import info.nightscout.androidaps.data.Profile;
import info.nightscout.androidaps.plugins.OpenAPSMA.events.EventOpenAPSUpdateGui; import info.nightscout.androidaps.plugins.OpenAPSMA.events.EventOpenAPSUpdateGui;
import info.nightscout.androidaps.plugins.OpenAPSMA.events.EventOpenAPSUpdateResultGui; import info.nightscout.androidaps.plugins.OpenAPSMA.events.EventOpenAPSUpdateResultGui;
import info.nightscout.utils.DateUtil; import info.nightscout.utils.DateUtil;
@ -63,7 +63,7 @@ public class OpenAPSMAPlugin implements PluginBase, APSInterface {
@Override @Override
public String getNameShort() { public String getNameShort() {
String name = MainApp.sResources.getString(R.string.oaps_shortname); String name = MainApp.sResources.getString(R.string.oaps_shortname);
if (!name.trim().isEmpty()){ if (!name.trim().isEmpty()) {
//only if translation exists //only if translation exists
return name; return name;
} }
@ -73,12 +73,14 @@ public class OpenAPSMAPlugin implements PluginBase, APSInterface {
@Override @Override
public boolean isEnabled(int type) { public boolean isEnabled(int type) {
return type == APS && fragmentEnabled && MainApp.getConfigBuilder().getPumpDescription().isTempBasalCapable; boolean pumpCapable = ConfigBuilderPlugin.getActivePump() == null || ConfigBuilderPlugin.getActivePump().getPumpDescription().isTempBasalCapable;
return type == APS && fragmentEnabled && pumpCapable;
} }
@Override @Override
public boolean isVisibleInTabs(int type) { public boolean isVisibleInTabs(int type) {
return type == APS && fragmentVisible && MainApp.getConfigBuilder().getPumpDescription().isTempBasalCapable; boolean pumpCapable = ConfigBuilderPlugin.getActivePump() == null || ConfigBuilderPlugin.getActivePump().getPumpDescription().isTempBasalCapable;
return type == APS && fragmentVisible && pumpCapable;
} }
@Override @Override
@ -145,7 +147,6 @@ public class OpenAPSMAPlugin implements PluginBase, APSInterface {
GlucoseStatus glucoseStatus = GlucoseStatus.getGlucoseStatusData(); GlucoseStatus glucoseStatus = GlucoseStatus.getGlucoseStatusData();
Profile profile = MainApp.getConfigBuilder().getProfile(); Profile profile = MainApp.getConfigBuilder().getProfile();
PumpInterface pump = MainApp.getConfigBuilder();
if (profile == null) { if (profile == null) {
MainApp.bus().post(new EventOpenAPSUpdateResultGui(MainApp.instance().getString(R.string.noprofileselected))); MainApp.bus().post(new EventOpenAPSUpdateResultGui(MainApp.instance().getString(R.string.noprofileselected)));
@ -213,11 +214,12 @@ public class OpenAPSMAPlugin implements PluginBase, APSInterface {
if (!checkOnlyHardLimits(Profile.toMgdl(profile.getIsf(), units), "sens", 2, 900)) if (!checkOnlyHardLimits(Profile.toMgdl(profile.getIsf(), units), "sens", 2, 900))
return; return;
if (!checkOnlyHardLimits(profile.getMaxDailyBasal(), "max_daily_basal", 0.1, 10)) return; if (!checkOnlyHardLimits(profile.getMaxDailyBasal(), "max_daily_basal", 0.1, 10)) return;
if (!checkOnlyHardLimits(pump.getBaseBasalRate(), "current_basal", 0.01, 5)) return; if (!checkOnlyHardLimits(ConfigBuilderPlugin.getActivePump().getBaseBasalRate(), "current_basal", 0.01, 5))
return;
start = new Date(); start = new Date();
try { try {
determineBasalAdapterMAJS.setData(profile, maxIob, maxBasal, minBg, maxBg, targetBg, pump, iobTotal, glucoseStatus, mealData); determineBasalAdapterMAJS.setData(profile, maxIob, maxBasal, minBg, maxBg, targetBg, ConfigBuilderPlugin.getActivePump().getBaseBasalRate(), iobTotal, glucoseStatus, mealData);
} catch (JSONException e) { } catch (JSONException e) {
log.error("Unhandled exception", e); log.error("Unhandled exception", e);
} }
@ -230,9 +232,11 @@ public class OpenAPSMAPlugin implements PluginBase, APSInterface {
determineBasalResultMA.changeRequested = false; determineBasalResultMA.changeRequested = false;
// limit requests on openloop mode // limit requests on openloop mode
if (!MainApp.getConfigBuilder().isClosedModeEnabled()) { if (!MainApp.getConfigBuilder().isClosedModeEnabled()) {
if (MainApp.getConfigBuilder().isTempBasalInProgress() && Math.abs(determineBasalResultMA.rate - MainApp.getConfigBuilder().getTempBasalAbsoluteRateHistory()) < 0.1) if (MainApp.getConfigBuilder().isTempBasalInProgress() && determineBasalResultMA.rate == 0 && determineBasalResultMA.duration == 0) {
// going to cancel
} else if (MainApp.getConfigBuilder().isTempBasalInProgress() && Math.abs(determineBasalResultMA.rate - MainApp.getConfigBuilder().getTempBasalAbsoluteRateHistory()) < 0.1) {
determineBasalResultMA.changeRequested = false; determineBasalResultMA.changeRequested = false;
if (!MainApp.getConfigBuilder().isTempBasalInProgress() && Math.abs(determineBasalResultMA.rate - MainApp.getConfigBuilder().getBaseBasalRate()) < 0.1) } else if (!MainApp.getConfigBuilder().isTempBasalInProgress() && Math.abs(determineBasalResultMA.rate - ConfigBuilderPlugin.getActivePump().getBaseBasalRate()) < 0.1)
determineBasalResultMA.changeRequested = false; determineBasalResultMA.changeRequested = false;
} }

View file

@ -20,7 +20,7 @@ import org.slf4j.LoggerFactory;
import info.nightscout.androidaps.MainApp; 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.interfaces.PumpInterface; import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin;
import info.nightscout.androidaps.plugins.Overview.events.EventDismissBolusprogressIfRunning; import info.nightscout.androidaps.plugins.Overview.events.EventDismissBolusprogressIfRunning;
import info.nightscout.androidaps.plugins.Overview.events.EventOverviewBolusProgress; import info.nightscout.androidaps.plugins.Overview.events.EventOverviewBolusProgress;
@ -35,6 +35,7 @@ public class BolusProgressDialog extends DialogFragment implements View.OnClickL
static double amount; static double amount;
public static boolean bolusEnded = false; public static boolean bolusEnded = false;
public static boolean running = true; public static boolean running = true;
public static boolean stopPressed = false;
public BolusProgressDialog() { public BolusProgressDialog() {
super(); super();
@ -62,6 +63,7 @@ public class BolusProgressDialog extends DialogFragment implements View.OnClickL
progressBar.setMax(100); progressBar.setMax(100);
statusView.setText(MainApp.sResources.getString(R.string.waitingforpump)); statusView.setText(MainApp.sResources.getString(R.string.waitingforpump));
setCancelable(false); setCancelable(false);
stopPressed = false;
return view; return view;
} }
@ -95,10 +97,10 @@ public class BolusProgressDialog extends DialogFragment implements View.OnClickL
switch (view.getId()) { switch (view.getId()) {
case R.id.overview_bolusprogress_stop: case R.id.overview_bolusprogress_stop:
log.debug("Stop bolus delivery button pressed"); log.debug("Stop bolus delivery button pressed");
stopPressed = true;
stopPressedView.setVisibility(View.VISIBLE); stopPressedView.setVisibility(View.VISIBLE);
stopButton.setVisibility(View.INVISIBLE); stopButton.setVisibility(View.INVISIBLE);
PumpInterface pump = MainApp.getConfigBuilder(); ConfigBuilderPlugin.getActivePump().stopBolusDelivering();
pump.stopBolusDelivering();
break; break;
} }
} }
@ -124,7 +126,7 @@ public class BolusProgressDialog extends DialogFragment implements View.OnClickL
@Subscribe @Subscribe
public void onStatusEvent(final EventDismissBolusprogressIfRunning ev) { public void onStatusEvent(final EventDismissBolusprogressIfRunning ev) {
if(BolusProgressDialog.running){ if (BolusProgressDialog.running) {
dismiss(); dismiss();
} }
} }

View file

@ -76,6 +76,8 @@ public class CalibrationDialog extends DialogFragment implements View.OnClickLis
unitsView = (TextView) view.findViewById(R.id.overview_calibration_units); unitsView = (TextView) view.findViewById(R.id.overview_calibration_units);
unitsView.setText(units); unitsView.setText(units);
setCancelable(true);
getDialog().setCanceledOnTouchOutside(false);
return view; return view;
} }

View file

@ -9,7 +9,6 @@ import android.view.ViewGroup;
import android.view.Window; import android.view.Window;
import android.view.WindowManager; import android.view.WindowManager;
import android.widget.ArrayAdapter; import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.EditText; import android.widget.EditText;
import android.widget.Spinner; import android.widget.Spinner;
@ -17,13 +16,13 @@ import org.json.JSONException;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import java.text.SimpleDateFormat;
import java.util.ArrayList; import java.util.ArrayList;
import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.R; import info.nightscout.androidaps.R;
import info.nightscout.androidaps.data.QuickWizard;
import info.nightscout.androidaps.data.QuickWizardEntry;
import info.nightscout.androidaps.plugins.Overview.OverviewPlugin; import info.nightscout.androidaps.plugins.Overview.OverviewPlugin;
import info.nightscout.androidaps.plugins.Overview.QuickWizard;
import info.nightscout.androidaps.plugins.Overview.events.EventQuickWizardChange; import info.nightscout.androidaps.plugins.Overview.events.EventQuickWizardChange;
import info.nightscout.utils.DateUtil; import info.nightscout.utils.DateUtil;
import info.nightscout.utils.SafeParse; import info.nightscout.utils.SafeParse;
@ -31,19 +30,25 @@ import info.nightscout.utils.SafeParse;
public class EditQuickWizardDialog extends DialogFragment implements View.OnClickListener { public class EditQuickWizardDialog extends DialogFragment implements View.OnClickListener {
private static Logger log = LoggerFactory.getLogger(EditQuickWizardDialog.class); private static Logger log = LoggerFactory.getLogger(EditQuickWizardDialog.class);
QuickWizard.QuickWizardEntry entry = new QuickWizard().newEmptyItem(); QuickWizardEntry entry = new QuickWizard().newEmptyItem();
QuickWizard quickWizard = MainApp.getSpecificPlugin(OverviewPlugin.class).quickWizard; QuickWizard quickWizard = MainApp.getSpecificPlugin(OverviewPlugin.class).quickWizard;
EditText buttonEdit; EditText buttonEdit;
EditText carbsEdit; EditText carbsEdit;
Spinner fromSpinner; Spinner fromSpinner;
Spinner toSpinner; Spinner toSpinner;
Button okButton; Spinner useBGSpinner;
Spinner useCOBSpinner;
Spinner useBolusIOBSpinner;
Spinner useBasalIOBSpinner;
Spinner useTrendSpinner;
Spinner useSuperBolusSpinner;
Spinner useTempTargetSpinner;
public EditQuickWizardDialog() { public EditQuickWizardDialog() {
} }
public void setData(QuickWizard.QuickWizardEntry data) { public void setData(QuickWizardEntry data) {
entry = data; entry = data;
} }
@ -58,8 +63,16 @@ public class EditQuickWizardDialog extends DialogFragment implements View.OnClic
carbsEdit = (EditText) view.findViewById(R.id.overview_editquickwizard_carbs_edit); carbsEdit = (EditText) view.findViewById(R.id.overview_editquickwizard_carbs_edit);
fromSpinner = (Spinner) view.findViewById(R.id.overview_editquickwizard_from_spinner); fromSpinner = (Spinner) view.findViewById(R.id.overview_editquickwizard_from_spinner);
toSpinner = (Spinner) view.findViewById(R.id.overview_editquickwizard_to_spinner); toSpinner = (Spinner) view.findViewById(R.id.overview_editquickwizard_to_spinner);
okButton = (Button) view.findViewById(R.id.overview_editquickwizard_ok_button); useBGSpinner = (Spinner) view.findViewById(R.id.overview_editquickwizard_usebg_spinner);
okButton.setOnClickListener(this); useCOBSpinner = (Spinner) view.findViewById(R.id.overview_editquickwizard_usecob_spinner);
useBolusIOBSpinner = (Spinner) view.findViewById(R.id.overview_editquickwizard_usebolusiob_spinner);
useBasalIOBSpinner = (Spinner) view.findViewById(R.id.overview_editquickwizard_usebasaliob_spinner);
useTrendSpinner = (Spinner) view.findViewById(R.id.overview_editquickwizard_usetrend_spinner);
useSuperBolusSpinner = (Spinner) view.findViewById(R.id.overview_editquickwizard_usesuperbolus_spinner);
useTempTargetSpinner = (Spinner) view.findViewById(R.id.overview_editquickwizard_usetemptarget_spinner);
view.findViewById(R.id.ok).setOnClickListener(this);
view.findViewById(R.id.cancel).setOnClickListener(this);
int posFrom = 0; int posFrom = 0;
int posTo = 95; int posTo = 95;
@ -83,6 +96,14 @@ public class EditQuickWizardDialog extends DialogFragment implements View.OnClic
fromSpinner.setSelection(posFrom); fromSpinner.setSelection(posFrom);
toSpinner.setSelection(posTo); toSpinner.setSelection(posTo);
setSelection(useBGSpinner, entry.useBG());
setSelection(useCOBSpinner, entry.useCOB());
setSelection(useBolusIOBSpinner, entry.useBolusIOB());
setSelection(useBasalIOBSpinner, entry.useBasalIOB());
setSelection(useTrendSpinner, entry.useTrend());
setSelection(useSuperBolusSpinner, entry.useSuperBolus());
setSelection(useTempTargetSpinner, entry.useTempTarget());
return view; return view;
} }
@ -96,7 +117,7 @@ public class EditQuickWizardDialog extends DialogFragment implements View.OnClic
@Override @Override
public void onClick(View v) { public void onClick(View v) {
switch (v.getId()) { switch (v.getId()) {
case R.id.overview_editquickwizard_ok_button: case R.id.ok:
if (fromSpinner.getSelectedItem() == null) return; if (fromSpinner.getSelectedItem() == null) return;
if (toSpinner.getSelectedItem() == null) return; if (toSpinner.getSelectedItem() == null) return;
try { try {
@ -106,13 +127,64 @@ public class EditQuickWizardDialog extends DialogFragment implements View.OnClic
entry.storage.put("validFrom", validFromInt); entry.storage.put("validFrom", validFromInt);
int validToInt = DateUtil.toSeconds(toSpinner.getSelectedItem().toString()); int validToInt = DateUtil.toSeconds(toSpinner.getSelectedItem().toString());
entry.storage.put("validTo", validToInt); entry.storage.put("validTo", validToInt);
entry.storage.put("useBG", getSelection(useBGSpinner));
entry.storage.put("useCOB", getSelection(useCOBSpinner));
entry.storage.put("useBolusIOB", getSelection(useBolusIOBSpinner));
entry.storage.put("useBasalIOB", getSelection(useBasalIOBSpinner));
entry.storage.put("useTrend", getSelection(useTrendSpinner));
entry.storage.put("useSuperBolus", getSelection(useSuperBolusSpinner));
entry.storage.put("useTempTarget", getSelection(useTempTargetSpinner));
} catch (JSONException e) { } catch (JSONException e) {
log.error("Unhandled exception", e); log.error("Unhandled exception", e);
} }
quickWizard.addOrUpdate(entry); quickWizard.addOrUpdate(entry);
dismiss(); dismiss();
MainApp.bus().post(new EventQuickWizardChange()); MainApp.bus().post(new EventQuickWizardChange());
break; break;
case R.id.cancel:
dismiss();
break;
}
}
int getSelection(Spinner spinner) {
String value = spinner.getSelectedItem().toString();
if (value.equals(MainApp.sResources.getString(R.string.yes)))
return QuickWizardEntry.YES;
if (value.equals(MainApp.sResources.getString(R.string.no)))
return QuickWizardEntry.NO;
if (value.equals(MainApp.sResources.getString(R.string.positiveonly)))
return QuickWizardEntry.POSITIVE_ONLY;
if (value.equals(MainApp.sResources.getString(R.string.negativeonly)))
return QuickWizardEntry.NEGATIVE_ONLY;
return QuickWizardEntry.NO;
}
void setSelection(Spinner spinner, int value) {
String selection;
switch (value) {
case QuickWizardEntry.YES:
selection = MainApp.sResources.getString(R.string.yes);
break;
case QuickWizardEntry.NO:
selection = MainApp.sResources.getString(R.string.no);
break;
case QuickWizardEntry.POSITIVE_ONLY:
selection = MainApp.sResources.getString(R.string.positiveonly);
break;
case QuickWizardEntry.NEGATIVE_ONLY:
selection = MainApp.sResources.getString(R.string.negativeonly);
break;
default:
selection = MainApp.sResources.getString(R.string.no);
break;
}
for (int i = 0; i < spinner.getCount(); i++) {
if (spinner.getItemAtPosition(i).toString().equalsIgnoreCase(selection)) {
spinner.setSelection(i);
break;
}
} }
} }
} }

View file

@ -0,0 +1,94 @@
package info.nightscout.androidaps.plugins.Overview.Dialogs;
import android.content.Intent;
import android.os.Bundle;
import android.support.v4.app.DialogFragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.TextView;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.R;
import info.nightscout.androidaps.Services.AlarmSoundService;
public class ErrorDialog extends DialogFragment implements View.OnClickListener {
private static Logger log = LoggerFactory.getLogger(ErrorDialog.class);
Button okButton;
TextView statusView;
ErrorHelperActivity helperActivity;
static String status;
static String title;
static int soundId;
public ErrorDialog() {
super();
}
public void setStatus(String status) {
this.status = status;
}
public void setTitle(String title) {
this.title = title;
}
public void setSound(int soundId) {
this.soundId = soundId;
}
public void setHelperActivity(ErrorHelperActivity activity) {
this.helperActivity = activity;
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
getDialog().setTitle(title);
View view = inflater.inflate(R.layout.overview_error_dialog, container, false);
okButton = (Button) view.findViewById(R.id.overview_error_ok);
statusView = (TextView) view.findViewById(R.id.overview_error_status);
okButton.setOnClickListener(this);
setCancelable(false);
Intent alarm = new Intent(MainApp.instance().getApplicationContext(), AlarmSoundService.class);
alarm.putExtra("soundid", soundId);
MainApp.instance().startService(alarm);
return view;
}
@Override
public void onResume() {
super.onResume();
if (getDialog() != null)
getDialog().getWindow().setLayout(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
statusView.setText(status);
}
@Override
public void dismiss() {
super.dismiss();
if (helperActivity != null) {
helperActivity.finish();
}
Intent alarm = new Intent(MainApp.instance().getApplicationContext(), AlarmSoundService.class);
MainApp.instance().stopService(alarm);
}
@Override
public void onClick(View view) {
switch (view.getId()) {
case R.id.overview_error_ok:
log.debug("Error dialog ok button pressed");
dismiss();
break;
}
}
}

View file

@ -0,0 +1,21 @@
package info.nightscout.androidaps.plugins.Overview.Dialogs;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
public class ErrorHelperActivity extends AppCompatActivity {
public ErrorHelperActivity() {
super();
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ErrorDialog errorDialog = new ErrorDialog();
errorDialog.setHelperActivity(this);
errorDialog.setStatus(getIntent().getStringExtra("status"));
errorDialog.setSound(getIntent().getIntExtra("soundid", 0));
errorDialog.setTitle(getIntent().getStringExtra("title"));
errorDialog.show(this.getSupportFragmentManager(), "Error");
}
}

View file

@ -2,9 +2,8 @@ package info.nightscout.androidaps.plugins.Overview.Dialogs;
import android.content.Context; import android.content.Context;
import android.content.DialogInterface; import android.content.DialogInterface;
import android.content.Intent;
import android.os.Bundle; import android.os.Bundle;
import android.os.Handler;
import android.os.HandlerThread;
import android.support.v4.app.DialogFragment; import android.support.v4.app.DialogFragment;
import android.support.v7.app.AlertDialog; import android.support.v7.app.AlertDialog;
import android.text.Editable; import android.text.Editable;
@ -30,12 +29,11 @@ import info.nightscout.androidaps.Constants;
import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.R; import info.nightscout.androidaps.R;
import info.nightscout.androidaps.data.DetailedBolusInfo; import info.nightscout.androidaps.data.DetailedBolusInfo;
import info.nightscout.androidaps.data.PumpEnactResult;
import info.nightscout.androidaps.db.CareportalEvent; import info.nightscout.androidaps.db.CareportalEvent;
import info.nightscout.androidaps.db.Source; import info.nightscout.androidaps.db.Source;
import info.nightscout.androidaps.interfaces.PumpInterface; import info.nightscout.androidaps.interfaces.PumpInterface;
import info.nightscout.androidaps.plugins.Overview.Notification; import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin;
import info.nightscout.androidaps.plugins.Overview.events.EventNewNotification; import info.nightscout.androidaps.queue.Callback;
import info.nightscout.utils.NumberPicker; import info.nightscout.utils.NumberPicker;
import info.nightscout.utils.SafeParse; import info.nightscout.utils.SafeParse;
import info.nightscout.utils.ToastUtils; import info.nightscout.utils.ToastUtils;
@ -49,12 +47,11 @@ public class NewTreatmentDialog extends DialogFragment implements OnClickListene
private Integer maxCarbs; private Integer maxCarbs;
private Double maxInsulin; private Double maxInsulin;
private Handler mHandler; //one shot guards
private boolean accepted;
private boolean okClicked;
public NewTreatmentDialog() { public NewTreatmentDialog() {
HandlerThread mHandlerThread = new HandlerThread(NewTreatmentDialog.class.getSimpleName());
mHandlerThread.start();
this.mHandler = new Handler(mHandlerThread.getLooper());
} }
final private TextWatcher textWatcher = new TextWatcher() { final private TextWatcher textWatcher = new TextWatcher() {
@ -103,15 +100,23 @@ public class NewTreatmentDialog extends DialogFragment implements OnClickListene
editInsulin = (NumberPicker) view.findViewById(R.id.treatments_newtreatment_insulinamount); editInsulin = (NumberPicker) view.findViewById(R.id.treatments_newtreatment_insulinamount);
editCarbs.setParams(0d, 0d, (double) maxCarbs, 1d, new DecimalFormat("0"), false, textWatcher); editCarbs.setParams(0d, 0d, (double) maxCarbs, 1d, new DecimalFormat("0"), false, textWatcher);
editInsulin.setParams(0d, 0d, maxInsulin, MainApp.getConfigBuilder().getPumpDescription().bolusStep, new DecimalFormat("0.00"), false, textWatcher); editInsulin.setParams(0d, 0d, maxInsulin, ConfigBuilderPlugin.getActivePump().getPumpDescription().bolusStep, new DecimalFormat("0.00"), false, textWatcher);
setCancelable(true);
getDialog().setCanceledOnTouchOutside(false);
return view; return view;
} }
@Override @Override
public void onClick(View view) { public synchronized void onClick(View view) {
switch (view.getId()) { switch (view.getId()) {
case R.id.ok: case R.id.ok:
if (okClicked) {
log.debug("guarding: ok already clicked");
dismiss();
return;
}
okClicked = true;
try { try {
Double insulin = SafeParse.stringToDouble(editInsulin.getText()); Double insulin = SafeParse.stringToDouble(editInsulin.getText());
@ -132,48 +137,55 @@ public class NewTreatmentDialog extends DialogFragment implements OnClickListene
final int finalCarbsAfterConstraints = carbsAfterConstraints; final int finalCarbsAfterConstraints = carbsAfterConstraints;
final Context context = getContext(); final Context context = getContext();
AlertDialog.Builder builder = new AlertDialog.Builder(context); final AlertDialog.Builder builder = new AlertDialog.Builder(context);
builder.setTitle(this.getContext().getString(R.string.confirmation)); builder.setTitle(this.getContext().getString(R.string.confirmation));
builder.setMessage(Html.fromHtml(confirmMessage)); builder.setMessage(Html.fromHtml(confirmMessage));
builder.setPositiveButton(getString(R.string.ok), new DialogInterface.OnClickListener() { builder.setPositiveButton(getString(R.string.ok), new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) { public void onClick(DialogInterface dialog, int id) {
if (finalInsulinAfterConstraints > 0 || finalCarbsAfterConstraints > 0) { synchronized (builder) {
final PumpInterface pump = MainApp.getConfigBuilder(); if (accepted) {
mHandler.post(new Runnable() { log.debug("guarding: already accepted");
@Override return;
public void run() { }
DetailedBolusInfo detailedBolusInfo = new DetailedBolusInfo(); accepted = true;
if (finalInsulinAfterConstraints == 0) if (finalInsulinAfterConstraints > 0 || finalCarbsAfterConstraints > 0) {
detailedBolusInfo.eventType = CareportalEvent.CARBCORRECTION; DetailedBolusInfo detailedBolusInfo = new DetailedBolusInfo();
if (finalCarbsAfterConstraints == 0) if (finalInsulinAfterConstraints == 0)
detailedBolusInfo.eventType = CareportalEvent.CORRECTIONBOLUS; detailedBolusInfo.eventType = CareportalEvent.CARBCORRECTION;
detailedBolusInfo.insulin = finalInsulinAfterConstraints; if (finalCarbsAfterConstraints == 0)
detailedBolusInfo.carbs = finalCarbsAfterConstraints; detailedBolusInfo.eventType = CareportalEvent.CORRECTIONBOLUS;
detailedBolusInfo.context = context; detailedBolusInfo.insulin = finalInsulinAfterConstraints;
detailedBolusInfo.source = Source.USER; detailedBolusInfo.carbs = finalCarbsAfterConstraints;
PumpEnactResult result = pump.deliverTreatment(detailedBolusInfo); detailedBolusInfo.context = context;
if (!result.success) { detailedBolusInfo.source = Source.USER;
try { if (detailedBolusInfo.insulin > 0 || ConfigBuilderPlugin.getActivePump().getPumpDescription().storesCarbInfo) {
AlertDialog.Builder builder = new AlertDialog.Builder(context); ConfigBuilderPlugin.getCommandQueue().bolus(detailedBolusInfo, new Callback() {
builder.setTitle(MainApp.sResources.getString(R.string.treatmentdeliveryerror)); @Override
builder.setMessage(result.comment); public void run() {
builder.setPositiveButton(MainApp.sResources.getString(R.string.ok), null); if (!result.success) {
builder.show(); Intent i = new Intent(MainApp.instance(), ErrorHelperActivity.class);
} catch (WindowManager.BadTokenException | NullPointerException e) { i.putExtra("soundid", R.raw.boluserror);
// window has been destroyed i.putExtra("status", result.comment);
Notification notification = new Notification(Notification.BOLUS_DELIVERY_ERROR, MainApp.sResources.getString(R.string.treatmentdeliveryerror), Notification.URGENT); i.putExtra("title", MainApp.sResources.getString(R.string.treatmentdeliveryerror));
MainApp.bus().post(new EventNewNotification(notification)); i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
MainApp.instance().startActivity(i);
}
} }
} });
} else {
MainApp.getConfigBuilder().addToHistoryTreatment(detailedBolusInfo);
} }
}); Answers.getInstance().logCustom(new CustomEvent("Bolus"));
Answers.getInstance().logCustom(new CustomEvent("Bolus")); }
} }
} }
}); });
builder.setNegativeButton(getString(R.string.cancel), null); builder.setNegativeButton(
getString(R.string.cancel), null);
builder.show(); builder.show();
dismiss(); dismiss();
} catch (Exception e) { } catch (Exception e) {
log.error("Unhandled exception", e); log.error("Unhandled exception", e);

View file

@ -3,9 +3,8 @@ package info.nightscout.androidaps.plugins.Overview.Dialogs;
import android.app.Activity; import android.app.Activity;
import android.content.Context; import android.content.Context;
import android.content.DialogInterface; import android.content.DialogInterface;
import android.content.Intent;
import android.os.Bundle; import android.os.Bundle;
import android.os.Handler;
import android.os.HandlerThread;
import android.support.v4.app.DialogFragment; import android.support.v4.app.DialogFragment;
import android.support.v7.app.AlertDialog; import android.support.v7.app.AlertDialog;
import android.text.Editable; import android.text.Editable;
@ -32,7 +31,6 @@ import com.squareup.otto.Subscribe;
import org.json.JSONException; import org.json.JSONException;
import org.json.JSONObject; import org.json.JSONObject;
import org.mozilla.javascript.tools.debugger.Main;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
@ -47,7 +45,6 @@ import info.nightscout.androidaps.data.DetailedBolusInfo;
import info.nightscout.androidaps.data.IobTotal; import info.nightscout.androidaps.data.IobTotal;
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.db.BgReading; import info.nightscout.androidaps.db.BgReading;
import info.nightscout.androidaps.db.CareportalEvent; import info.nightscout.androidaps.db.CareportalEvent;
import info.nightscout.androidaps.db.DatabaseHelper; import info.nightscout.androidaps.db.DatabaseHelper;
@ -56,16 +53,17 @@ import info.nightscout.androidaps.db.TempTarget;
import info.nightscout.androidaps.events.EventNewBG; import info.nightscout.androidaps.events.EventNewBG;
import info.nightscout.androidaps.events.EventRefreshOverview; import info.nightscout.androidaps.events.EventRefreshOverview;
import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin; import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin;
import info.nightscout.androidaps.plugins.IobCobCalculator.AutosensData;
import info.nightscout.androidaps.plugins.IobCobCalculator.IobCobCalculatorPlugin;
import info.nightscout.androidaps.plugins.IobCobCalculator.events.EventAutosensCalculationFinished;
import info.nightscout.androidaps.plugins.Loop.LoopPlugin; import info.nightscout.androidaps.plugins.Loop.LoopPlugin;
import info.nightscout.androidaps.plugins.OpenAPSAMA.OpenAPSAMAPlugin; import info.nightscout.androidaps.plugins.OpenAPSAMA.OpenAPSAMAPlugin;
import info.nightscout.androidaps.plugins.OpenAPSMA.events.EventOpenAPSUpdateGui; import info.nightscout.androidaps.plugins.OpenAPSMA.events.EventOpenAPSUpdateGui;
import info.nightscout.androidaps.plugins.Overview.Notification; import info.nightscout.androidaps.queue.Callback;
import info.nightscout.androidaps.plugins.Overview.events.EventNewNotification;
import info.nightscout.utils.BolusWizard; import info.nightscout.utils.BolusWizard;
import info.nightscout.utils.DateUtil; import info.nightscout.utils.DateUtil;
import info.nightscout.utils.DecimalFormatter; import info.nightscout.utils.DecimalFormatter;
import info.nightscout.utils.NumberPicker; import info.nightscout.utils.NumberPicker;
import info.nightscout.utils.OKDialog;
import info.nightscout.utils.SP; import info.nightscout.utils.SP;
import info.nightscout.utils.SafeParse; import info.nightscout.utils.SafeParse;
import info.nightscout.utils.ToastUtils; import info.nightscout.utils.ToastUtils;
@ -107,18 +105,15 @@ public class WizardDialog extends DialogFragment implements OnClickListener, Com
Integer calculatedCarbs = 0; Integer calculatedCarbs = 0;
Double calculatedTotalInsulin = 0d; Double calculatedTotalInsulin = 0d;
JSONObject boluscalcJSON; JSONObject boluscalcJSON;
boolean cobAvailable = false;
Handler mHandler;
public static HandlerThread mHandlerThread;
Context context; Context context;
//one shot guards
private boolean accepted;
private boolean okClicked;
public WizardDialog() { public WizardDialog() {
super(); super();
mHandlerThread = new HandlerThread(WizardDialog.class.getSimpleName());
mHandlerThread.start();
mHandler = new Handler(mHandlerThread.getLooper());
} }
@Override @Override
@ -146,26 +141,19 @@ public class WizardDialog extends DialogFragment implements OnClickListener, Com
} }
@Subscribe @Subscribe
public void onStatusEvent(final EventOpenAPSUpdateGui e) { public void onStatusEvent(final EventNewBG e) {
Activity activity = getActivity(); Activity activity = getActivity();
if (activity != null) if (activity != null)
activity.runOnUiThread(new Runnable() { activity.runOnUiThread(new Runnable() {
@Override @Override
public void run() { public void run() {
if (ConfigBuilderPlugin.getActiveAPS() instanceof OpenAPSAMAPlugin && ConfigBuilderPlugin.getActiveAPS().getLastAPSResult() != null && ConfigBuilderPlugin.getActiveAPS().getLastAPSRun().after(new Date(System.currentTimeMillis() - 11 * 60 * 1000L))) {
cobLayout.setVisibility(View.VISIBLE);
cobAvailable = true;
} else {
cobLayout.setVisibility(View.GONE);
cobAvailable = false;
}
calculateInsulin(); calculateInsulin();
} }
}); });
} }
@Subscribe @Subscribe
public void onStatusEvent(final EventNewBG e) { public void onStatusEvent(final EventAutosensCalculationFinished e) {
Activity activity = getActivity(); Activity activity = getActivity();
if (activity != null) if (activity != null)
activity.runOnUiThread(new Runnable() { activity.runOnUiThread(new Runnable() {
@ -253,11 +241,13 @@ public class WizardDialog extends DialogFragment implements OnClickListener, Com
editBg.setParams(0d, 0d, 500d, 0.1d, new DecimalFormat("0.0"), false, textWatcher); editBg.setParams(0d, 0d, 500d, 0.1d, new DecimalFormat("0.0"), false, textWatcher);
editCarbs.setParams(0d, 0d, (double) maxCarbs, 1d, new DecimalFormat("0"), false, textWatcher); editCarbs.setParams(0d, 0d, (double) maxCarbs, 1d, new DecimalFormat("0"), false, textWatcher);
double bolusstep = MainApp.getConfigBuilder().getPumpDescription().bolusStep; double bolusstep = ConfigBuilderPlugin.getActivePump().getPumpDescription().bolusStep;
editCorr.setParams(0d, -maxCorrection, maxCorrection, bolusstep, new DecimalFormat("0.00"), false, textWatcher); editCorr.setParams(0d, -maxCorrection, maxCorrection, bolusstep, new DecimalFormat("0.00"), false, textWatcher);
editCarbTime.setParams(0d, -60d, 60d, 5d, new DecimalFormat("0"), false); editCarbTime.setParams(0d, -60d, 60d, 5d, new DecimalFormat("0"), false);
initDialog(); initDialog();
setCancelable(true);
getDialog().setCanceledOnTouchOutside(false);
return view; return view;
} }
@ -297,9 +287,15 @@ public class WizardDialog extends DialogFragment implements OnClickListener, Com
} }
@Override @Override
public void onClick(View view) { public synchronized void onClick(View view) {
switch (view.getId()) { switch (view.getId()) {
case R.id.ok: case R.id.ok:
if (okClicked) {
log.debug("guarding: ok already clicked");
dismiss();
return;
}
okClicked = true;
if (calculatedTotalInsulin > 0d || calculatedCarbs > 0d) { if (calculatedTotalInsulin > 0d || calculatedCarbs > 0d) {
DecimalFormat formatNumber2decimalplaces = new DecimalFormat("0.00"); DecimalFormat formatNumber2decimalplaces = new DecimalFormat("0.00");
@ -327,56 +323,67 @@ public class WizardDialog extends DialogFragment implements OnClickListener, Com
final int carbTime = SafeParse.stringToInt(editCarbTime.getText()); final int carbTime = SafeParse.stringToInt(editCarbTime.getText());
final boolean useSuperBolus = superbolusCheckbox.isChecked(); final boolean useSuperBolus = superbolusCheckbox.isChecked();
AlertDialog.Builder builder = new AlertDialog.Builder(context); final AlertDialog.Builder builder = new AlertDialog.Builder(context);
builder.setTitle(MainApp.sResources.getString(R.string.confirmation)); builder.setTitle(MainApp.sResources.getString(R.string.confirmation));
builder.setMessage(Html.fromHtml(confirmMessage)); builder.setMessage(Html.fromHtml(confirmMessage));
builder.setPositiveButton(getString(R.string.ok), new DialogInterface.OnClickListener() { builder.setPositiveButton(getString(R.string.ok), new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) { public void onClick(DialogInterface dialog, int id) {
if (finalInsulinAfterConstraints > 0 || finalCarbsAfterConstraints > 0) { synchronized (builder) {
final ConfigBuilderPlugin pump = MainApp.getConfigBuilder(); if (accepted) {
mHandler.post(new Runnable() { log.debug("guarding: already accepted");
@Override return;
public void run() { }
PumpEnactResult result; accepted = true;
if (useSuperBolus) { if (finalInsulinAfterConstraints > 0 || finalCarbsAfterConstraints > 0) {
final LoopPlugin activeloop = MainApp.getConfigBuilder().getActiveLoop(); if (useSuperBolus) {
if (activeloop != null) { final LoopPlugin activeloop = ConfigBuilderPlugin.getActiveLoop();
activeloop.superBolusTo(System.currentTimeMillis() + 2 * 60L * 60 * 1000); if (activeloop != null) {
MainApp.bus().post(new EventRefreshOverview("WizardDialog")); activeloop.superBolusTo(System.currentTimeMillis() + 2 * 60L * 60 * 1000);
} MainApp.bus().post(new EventRefreshOverview("WizardDialog"));
pump.cancelTempBasal(true);
result = pump.setTempBasalAbsolute(0d, 120, true);
if (!result.success) {
OKDialog.show(getActivity(), MainApp.sResources.getString(R.string.tempbasaldeliveryerror), result.comment, null);
}
} }
DetailedBolusInfo detailedBolusInfo = new DetailedBolusInfo(); ConfigBuilderPlugin.getCommandQueue().tempBasalPercent(0, 120, true, new Callback() {
detailedBolusInfo.eventType = CareportalEvent.BOLUSWIZARD; @Override
detailedBolusInfo.insulin = finalInsulinAfterConstraints; public void run() {
detailedBolusInfo.carbs = finalCarbsAfterConstraints; if (!result.success) {
detailedBolusInfo.context = context; Intent i = new Intent(MainApp.instance(), ErrorHelperActivity.class);
detailedBolusInfo.glucose = bg; i.putExtra("soundid", R.raw.boluserror);
detailedBolusInfo.glucoseType = "Manual"; i.putExtra("status", result.comment);
detailedBolusInfo.carbTime = carbTime; i.putExtra("title", MainApp.sResources.getString(R.string.tempbasaldeliveryerror));
detailedBolusInfo.boluscalc = boluscalcJSON; i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
detailedBolusInfo.source = Source.USER; MainApp.instance().startActivity(i);
result = pump.deliverTreatment(detailedBolusInfo); }
if (!result.success) {
try {
AlertDialog.Builder builder = new AlertDialog.Builder(context);
builder.setTitle(MainApp.sResources.getString(R.string.treatmentdeliveryerror));
builder.setMessage(result.comment);
builder.setPositiveButton(MainApp.sResources.getString(R.string.ok), null);
builder.show();
} catch (WindowManager.BadTokenException | NullPointerException e) {
// window has been destroyed
Notification notification = new Notification(Notification.BOLUS_DELIVERY_ERROR, MainApp.sResources.getString(R.string.treatmentdeliveryerror), Notification.URGENT);
MainApp.bus().post(new EventNewNotification(notification));
} }
} });
} }
}); DetailedBolusInfo detailedBolusInfo = new DetailedBolusInfo();
Answers.getInstance().logCustom(new CustomEvent("Wizard")); detailedBolusInfo.eventType = CareportalEvent.BOLUSWIZARD;
detailedBolusInfo.insulin = finalInsulinAfterConstraints;
detailedBolusInfo.carbs = finalCarbsAfterConstraints;
detailedBolusInfo.context = context;
detailedBolusInfo.glucose = bg;
detailedBolusInfo.glucoseType = "Manual";
detailedBolusInfo.carbTime = carbTime;
detailedBolusInfo.boluscalc = boluscalcJSON;
detailedBolusInfo.source = Source.USER;
if (detailedBolusInfo.insulin > 0 || ConfigBuilderPlugin.getActivePump().getPumpDescription().storesCarbInfo) {
ConfigBuilderPlugin.getCommandQueue().bolus(detailedBolusInfo, new Callback() {
@Override
public void run() {
if (!result.success) {
Intent i = new Intent(MainApp.instance(), ErrorHelperActivity.class);
i.putExtra("soundid", R.raw.boluserror);
i.putExtra("status", result.comment);
i.putExtra("title", MainApp.sResources.getString(R.string.treatmentdeliveryerror));
i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
MainApp.instance().startActivity(i);
}
}
});
} else {
MainApp.getConfigBuilder().addToHistoryTreatment(detailedBolusInfo);
}
Answers.getInstance().logCustom(new CustomEvent("Wizard"));
}
} }
} }
}); });
@ -393,7 +400,7 @@ public class WizardDialog extends DialogFragment implements OnClickListener, Com
private void initDialog() { private void initDialog() {
Profile profile = MainApp.getConfigBuilder().getProfile(); Profile profile = MainApp.getConfigBuilder().getProfile();
ProfileStore profileStore = MainApp.getConfigBuilder().getActiveProfileInterface().getProfile(); ProfileStore profileStore = ConfigBuilderPlugin.getActiveProfileInterface().getProfile();
if (profile == null) { if (profile == null) {
ToastUtils.showToastInUiThread(MainApp.instance().getApplicationContext(), MainApp.sResources.getString(R.string.noprofile)); ToastUtils.showToastInUiThread(MainApp.instance().getApplicationContext(), MainApp.sResources.getString(R.string.noprofile));
@ -403,7 +410,7 @@ public class WizardDialog extends DialogFragment implements OnClickListener, Com
ArrayList<CharSequence> profileList; ArrayList<CharSequence> profileList;
profileList = profileStore.getProfileList(); profileList = profileStore.getProfileList();
profileList.add(0, MainApp.sResources.getString(R.string.active)); profileList.add(0, MainApp.sResources.getString(R.string.active));
ArrayAdapter<CharSequence> adapter = new ArrayAdapter<CharSequence>(getContext(), ArrayAdapter<CharSequence> adapter = new ArrayAdapter<>(getContext(),
R.layout.spinner_centered, profileList); R.layout.spinner_centered, profileList);
profileSpinner.setAdapter(adapter); profileSpinner.setAdapter(adapter);
@ -432,19 +439,11 @@ public class WizardDialog extends DialogFragment implements OnClickListener, Com
bolusIobInsulin.setText(DecimalFormatter.to2Decimal(-bolusIob.iob) + "U"); bolusIobInsulin.setText(DecimalFormatter.to2Decimal(-bolusIob.iob) + "U");
basalIobInsulin.setText(DecimalFormatter.to2Decimal(-basalIob.basaliob) + "U"); basalIobInsulin.setText(DecimalFormatter.to2Decimal(-basalIob.basaliob) + "U");
// COB only if AMA is selected
if (ConfigBuilderPlugin.getActiveAPS() instanceof OpenAPSAMAPlugin && ConfigBuilderPlugin.getActiveAPS().getLastAPSResult() != null && ConfigBuilderPlugin.getActiveAPS().getLastAPSRun().after(new Date(System.currentTimeMillis() - 11 * 60 * 1000L))) {
cobLayout.setVisibility(View.VISIBLE);
cobAvailable = true;
} else {
cobLayout.setVisibility(View.GONE);
cobAvailable = false;
}
calculateInsulin(); calculateInsulin();
} }
private void calculateInsulin() { private void calculateInsulin() {
ProfileStore profile = MainApp.getConfigBuilder().getActiveProfileInterface().getProfile(); ProfileStore profile = ConfigBuilderPlugin.getActiveProfileInterface().getProfile();
if (profileSpinner == null || profileSpinner.getSelectedItem() == null) if (profileSpinner == null || profileSpinner.getSelectedItem() == null)
return; // not initialized yet return; // not initialized yet
String selectedAlternativeProfile = profileSpinner.getSelectedItem().toString(); String selectedAlternativeProfile = profileSpinner.getSelectedItem().toString();
@ -476,13 +475,11 @@ public class WizardDialog extends DialogFragment implements OnClickListener, Com
// COB // COB
Double c_cob = 0d; Double c_cob = 0d;
if (cobAvailable && cobCheckbox.isChecked()) { if (cobCheckbox.isChecked()) {
if (ConfigBuilderPlugin.getActiveAPS().getLastAPSResult() != null && ConfigBuilderPlugin.getActiveAPS().getLastAPSRun().after(new Date(System.currentTimeMillis() - 11 * 60 * 1000L))) { AutosensData autosensData = IobCobCalculatorPlugin.getLastAutosensData("Wizard COB");
try {
c_cob = SafeParse.stringToDouble(ConfigBuilderPlugin.getActiveAPS().getLastAPSResult().json().getString("COB")); if(autosensData != null) {
} catch (JSONException e) { c_cob = autosensData.cob;
log.error("Unhandled exception", e);
}
} }
} }
@ -524,7 +521,7 @@ public class WizardDialog extends DialogFragment implements OnClickListener, Com
bgTrendInsulin.setText(DecimalFormatter.to2Decimal(wizard.insulinFromTrend) + "U"); bgTrendInsulin.setText(DecimalFormatter.to2Decimal(wizard.insulinFromTrend) + "U");
// COB // COB
if (cobAvailable && cobCheckbox.isChecked()) { if (cobCheckbox.isChecked()) {
cob.setText(DecimalFormatter.to2Decimal(c_cob) + "g IC: " + DecimalFormatter.to1Decimal(wizard.ic)); cob.setText(DecimalFormatter.to2Decimal(c_cob) + "g IC: " + DecimalFormatter.to1Decimal(wizard.ic));
cobInsulin.setText(DecimalFormatter.to2Decimal(wizard.insulinFromCOB) + "U"); cobInsulin.setText(DecimalFormatter.to2Decimal(wizard.insulinFromCOB) + "U");
} else { } else {
@ -535,12 +532,12 @@ public class WizardDialog extends DialogFragment implements OnClickListener, Com
if (calculatedTotalInsulin > 0d || calculatedCarbs > 0d) { if (calculatedTotalInsulin > 0d || calculatedCarbs > 0d) {
String insulinText = calculatedTotalInsulin > 0d ? (DecimalFormatter.to2Decimal(calculatedTotalInsulin) + "U") : ""; String insulinText = calculatedTotalInsulin > 0d ? (DecimalFormatter.to2Decimal(calculatedTotalInsulin) + "U") : "";
String carbsText = calculatedCarbs > 0d ? (DecimalFormatter.to0Decimal(calculatedCarbs) + "g") : ""; String carbsText = calculatedCarbs > 0d ? (DecimalFormatter.to0Decimal(calculatedCarbs) + "g") : "";
total.setText(getString(R.string.result) + ": " + insulinText + " " + carbsText); total.setText(MainApp.gs(R.string.result) + ": " + insulinText + " " + carbsText);
okButton.setVisibility(View.VISIBLE); okButton.setVisibility(View.VISIBLE);
} else { } else {
// TODO this should also be run when loading the dialog as the OK button is initially visible // TODO this should also be run when loading the dialog as the OK button is initially visible
// but does nothing if neither carbs nor insulin is > 0 // but does nothing if neither carbs nor insulin is > 0
total.setText(getString(R.string.missing) + " " + DecimalFormatter.to0Decimal(wizard.carbsEquivalent) + "g"); total.setText(MainApp.gs(R.string.missing) + " " + DecimalFormatter.to0Decimal(wizard.carbsEquivalent) + "g");
okButton.setVisibility(View.INVISIBLE); okButton.setVisibility(View.INVISIBLE);
} }

View file

@ -9,10 +9,12 @@ import org.slf4j.LoggerFactory;
import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.R; import info.nightscout.androidaps.R;
import info.nightscout.androidaps.data.QuickWizard;
import info.nightscout.androidaps.events.EventRefreshOverview; import info.nightscout.androidaps.events.EventRefreshOverview;
import info.nightscout.androidaps.interfaces.PluginBase; import info.nightscout.androidaps.interfaces.PluginBase;
import info.nightscout.androidaps.plugins.Overview.events.EventDismissNotification; import info.nightscout.androidaps.plugins.Overview.events.EventDismissNotification;
import info.nightscout.androidaps.plugins.Overview.events.EventNewNotification; import info.nightscout.androidaps.plugins.Overview.events.EventNewNotification;
import info.nightscout.androidaps.plugins.Overview.notifications.NotificationStore;
import info.nightscout.utils.SP; import info.nightscout.utils.SP;
/** /**

View file

@ -1,9 +1,9 @@
package info.nightscout.androidaps.plugins.Overview.activities; package info.nightscout.androidaps.plugins.Overview.activities;
import android.app.Activity; import android.app.Activity;
import android.os.Bundle;
import android.support.v4.app.FragmentManager; import android.support.v4.app.FragmentManager;
import android.support.v7.app.AppCompatActivity; import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.support.v7.widget.CardView; import android.support.v7.widget.CardView;
import android.support.v7.widget.LinearLayoutManager; import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView; import android.support.v7.widget.RecyclerView;
@ -15,13 +15,11 @@ import android.widget.TextView;
import com.squareup.otto.Subscribe; import com.squareup.otto.Subscribe;
import java.text.SimpleDateFormat;
import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.R; import info.nightscout.androidaps.R;
import info.nightscout.androidaps.data.QuickWizard;
import info.nightscout.androidaps.plugins.Overview.Dialogs.EditQuickWizardDialog; import info.nightscout.androidaps.plugins.Overview.Dialogs.EditQuickWizardDialog;
import info.nightscout.androidaps.plugins.Overview.OverviewPlugin; import info.nightscout.androidaps.plugins.Overview.OverviewPlugin;
import info.nightscout.androidaps.plugins.Overview.QuickWizard;
import info.nightscout.androidaps.plugins.Overview.events.EventQuickWizardChange; import info.nightscout.androidaps.plugins.Overview.events.EventQuickWizardChange;
import info.nightscout.utils.DateUtil; import info.nightscout.utils.DateUtil;
import info.nightscout.utils.DecimalFormatter; import info.nightscout.utils.DecimalFormatter;
@ -153,6 +151,7 @@ public class QuickWizardListActivity extends AppCompatActivity implements View.O
break; break;
} }
} }
@Subscribe @Subscribe
public void onStatusEvent(final EventQuickWizardChange ev) { public void onStatusEvent(final EventQuickWizardChange ev) {
updateGUI(); updateGUI();

View file

@ -1,7 +1,7 @@
package info.nightscout.androidaps.plugins.Overview.events; package info.nightscout.androidaps.plugins.Overview.events;
import info.nightscout.androidaps.events.Event; import info.nightscout.androidaps.events.Event;
import info.nightscout.androidaps.plugins.Overview.Notification; import info.nightscout.androidaps.plugins.Overview.notifications.Notification;
/** /**
* Created by mike on 03.12.2016. * Created by mike on 03.12.2016.

View file

@ -24,9 +24,10 @@ import info.nightscout.androidaps.db.CareportalEvent;
import info.nightscout.androidaps.db.ExtendedBolus; import info.nightscout.androidaps.db.ExtendedBolus;
import info.nightscout.androidaps.db.ProfileSwitch; import info.nightscout.androidaps.db.ProfileSwitch;
import info.nightscout.androidaps.db.Treatment; import info.nightscout.androidaps.db.Treatment;
import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin;
import info.nightscout.androidaps.plugins.IobCobCalculator.AutosensData; import info.nightscout.androidaps.plugins.IobCobCalculator.AutosensData;
import info.nightscout.androidaps.plugins.IobCobCalculator.IobCobCalculatorPlugin; import info.nightscout.androidaps.plugins.IobCobCalculator.IobCobCalculatorPlugin;
import info.nightscout.androidaps.plugins.IobCobCalculator.events.BasalData; import info.nightscout.androidaps.plugins.IobCobCalculator.BasalData;
import info.nightscout.androidaps.plugins.OpenAPSAMA.DetermineBasalResultAMA; import info.nightscout.androidaps.plugins.OpenAPSAMA.DetermineBasalResultAMA;
import info.nightscout.androidaps.plugins.Overview.graphExtensions.AreaGraphSeries; import info.nightscout.androidaps.plugins.Overview.graphExtensions.AreaGraphSeries;
import info.nightscout.androidaps.plugins.Overview.graphExtensions.DataPointWithLabelInterface; import info.nightscout.androidaps.plugins.Overview.graphExtensions.DataPointWithLabelInterface;
@ -44,15 +45,18 @@ import info.nightscout.utils.Round;
public class GraphData { public class GraphData {
public GraphData() { private GraphView graph;
units = MainApp.getConfigBuilder().getProfileUnits();
}
public double maxY = 0; public double maxY = 0;
private List<BgReading> bgReadingsArray; private List<BgReading> bgReadingsArray;
private String units; private String units;
private List<Series> series = new ArrayList<>();
public void addBgReadings(GraphView bgGraph, long fromTime, long toTime, double lowLine, double highLine, DetermineBasalResultAMA amaResult) { public GraphData(GraphView graph) {
units = MainApp.getConfigBuilder().getProfileUnits();
this.graph = graph;
}
public void addBgReadings(long fromTime, long toTime, double lowLine, double highLine, DetermineBasalResultAMA amaResult) {
double maxBgValue = 0d; double maxBgValue = 0d;
bgReadingsArray = MainApp.getDbHelper().getBgreadingsDataFromTime(fromTime, true); bgReadingsArray = MainApp.getDbHelper().getBgreadingsDataFromTime(fromTime, true);
List<DataPointWithLabelInterface> bgListArray = new ArrayList<>(); List<DataPointWithLabelInterface> bgListArray = new ArrayList<>();
@ -80,20 +84,18 @@ public class GraphData {
DataPointWithLabelInterface[] bg = new DataPointWithLabelInterface[bgListArray.size()]; DataPointWithLabelInterface[] bg = new DataPointWithLabelInterface[bgListArray.size()];
bg = bgListArray.toArray(bg); bg = bgListArray.toArray(bg);
if (bg.length > 0) {
addSeriesWithoutInvalidate(bgGraph, new PointsWithLabelGraphSeries<>(bg));
}
maxY = maxBgValue; maxY = maxBgValue;
// set manual y bounds to have nice steps // set manual y bounds to have nice steps
bgGraph.getViewport().setMaxY(maxY); graph.getViewport().setMaxY(maxY);
bgGraph.getViewport().setMinY(0); graph.getViewport().setMinY(0);
bgGraph.getViewport().setYAxisBoundsManual(true); graph.getViewport().setYAxisBoundsManual(true);
bgGraph.getGridLabelRenderer().setNumVerticalLabels(numOfVertLines); graph.getGridLabelRenderer().setNumVerticalLabels(numOfVertLines);
addSeries(new PointsWithLabelGraphSeries<>(bg));
} }
public void addInRangeArea(GraphView bgGraph, long fromTime, long toTime, double lowLine, double highLine) { public void addInRangeArea(long fromTime, long toTime, double lowLine, double highLine) {
AreaGraphSeries<DoubleDataPoint> inRangeAreaSeries; AreaGraphSeries<DoubleDataPoint> inRangeAreaSeries;
DoubleDataPoint[] inRangeAreaDataPoints = new DoubleDataPoint[]{ DoubleDataPoint[] inRangeAreaDataPoints = new DoubleDataPoint[]{
@ -101,14 +103,15 @@ public class GraphData {
new DoubleDataPoint(toTime, lowLine, highLine) new DoubleDataPoint(toTime, lowLine, highLine)
}; };
inRangeAreaSeries = new AreaGraphSeries<>(inRangeAreaDataPoints); inRangeAreaSeries = new AreaGraphSeries<>(inRangeAreaDataPoints);
addSeriesWithoutInvalidate(bgGraph, inRangeAreaSeries);
inRangeAreaSeries.setColor(0); inRangeAreaSeries.setColor(0);
inRangeAreaSeries.setDrawBackground(true); inRangeAreaSeries.setDrawBackground(true);
inRangeAreaSeries.setBackgroundColor(MainApp.sResources.getColor(R.color.inrangebackground)); inRangeAreaSeries.setBackgroundColor(MainApp.sResources.getColor(R.color.inrangebackground));
addSeries(inRangeAreaSeries);
} }
// scale in % of vertical size (like 0.3) // scale in % of vertical size (like 0.3)
public void addBasals(GraphView bgGraph, long fromTime, long toTime, double scale) { public void addBasals(long fromTime, long toTime, double scale) {
LineGraphSeries<ScaledDataPoint> basalsLineSeries; LineGraphSeries<ScaledDataPoint> basalsLineSeries;
LineGraphSeries<ScaledDataPoint> absoluteBasalsLineSeries; LineGraphSeries<ScaledDataPoint> absoluteBasalsLineSeries;
LineGraphSeries<ScaledDataPoint> baseBasalsSeries; LineGraphSeries<ScaledDataPoint> baseBasalsSeries;
@ -193,7 +196,7 @@ public class GraphData {
basalsLineSeries = new LineGraphSeries<>(basalLine); basalsLineSeries = new LineGraphSeries<>(basalLine);
Paint paint = new Paint(); Paint paint = new Paint();
paint.setStyle(Paint.Style.STROKE); paint.setStyle(Paint.Style.STROKE);
paint.setStrokeWidth(2); paint.setStrokeWidth(MainApp.instance().getApplicationContext().getResources().getDisplayMetrics().scaledDensity * 2);
paint.setPathEffect(new DashPathEffect(new float[]{2, 4}, 0)); paint.setPathEffect(new DashPathEffect(new float[]{2, 4}, 0));
paint.setColor(MainApp.sResources.getColor(R.color.basal)); paint.setColor(MainApp.sResources.getColor(R.color.basal));
basalsLineSeries.setCustomPaint(paint); basalsLineSeries.setCustomPaint(paint);
@ -203,19 +206,19 @@ public class GraphData {
absoluteBasalsLineSeries = new LineGraphSeries<>(absoluteBasalLine); absoluteBasalsLineSeries = new LineGraphSeries<>(absoluteBasalLine);
Paint absolutePaint = new Paint(); Paint absolutePaint = new Paint();
absolutePaint.setStyle(Paint.Style.STROKE); absolutePaint.setStyle(Paint.Style.STROKE);
absolutePaint.setStrokeWidth(4); absolutePaint.setStrokeWidth(MainApp.instance().getApplicationContext().getResources().getDisplayMetrics().scaledDensity * 2);
absolutePaint.setColor(MainApp.sResources.getColor(R.color.basal)); absolutePaint.setColor(MainApp.sResources.getColor(R.color.basal));
absoluteBasalsLineSeries.setCustomPaint(absolutePaint); absoluteBasalsLineSeries.setCustomPaint(absolutePaint);
basalScale.setMultiplier(maxY * scale / maxBasalValueFound); basalScale.setMultiplier(maxY * scale / maxBasalValueFound);
addSeriesWithoutInvalidate(bgGraph, baseBasalsSeries); addSeries(baseBasalsSeries);
addSeriesWithoutInvalidate(bgGraph, tempBasalsSeries); addSeries(tempBasalsSeries);
addSeriesWithoutInvalidate(bgGraph, basalsLineSeries); addSeries(basalsLineSeries);
addSeriesWithoutInvalidate(bgGraph, absoluteBasalsLineSeries); addSeries(absoluteBasalsLineSeries);
} }
public void addTreatments(GraphView bgGraph, long fromTime, long endTime) { public void addTreatments(long fromTime, long endTime) {
List<DataPointWithLabelInterface> filteredTreatments = new ArrayList<>(); List<DataPointWithLabelInterface> filteredTreatments = new ArrayList<>();
List<Treatment> treatments = MainApp.getConfigBuilder().getTreatmentsFromHistory(); List<Treatment> treatments = MainApp.getConfigBuilder().getTreatmentsFromHistory();
@ -237,7 +240,7 @@ public class GraphData {
} }
// Extended bolus // Extended bolus
if (!MainApp.getConfigBuilder().isFakingTempsByExtendedBoluses()) { if (!ConfigBuilderPlugin.getActivePump().isFakingTempsByExtendedBoluses()) {
List<ExtendedBolus> extendedBoluses = MainApp.getConfigBuilder().getExtendedBolusesFromHistory().getList(); List<ExtendedBolus> extendedBoluses = MainApp.getConfigBuilder().getExtendedBolusesFromHistory().getList();
for (int tx = 0; tx < extendedBoluses.size(); tx++) { for (int tx = 0; tx < extendedBoluses.size(); tx++) {
@ -250,7 +253,7 @@ public class GraphData {
} }
// Careportal // Careportal
List<CareportalEvent> careportalEvents = MainApp.getDbHelper().getCareportalEventsFromTime(fromTime, true); List<CareportalEvent> careportalEvents = MainApp.getDbHelper().getCareportalEventsFromTime(fromTime - 6 * 60 * 60 * 1000, true);
for (int tx = 0; tx < careportalEvents.size(); tx++) { for (int tx = 0; tx < careportalEvents.size(); tx++) {
DataPointWithLabelInterface t = careportalEvents.get(tx); DataPointWithLabelInterface t = careportalEvents.get(tx);
@ -261,9 +264,7 @@ public class GraphData {
DataPointWithLabelInterface[] treatmentsArray = new DataPointWithLabelInterface[filteredTreatments.size()]; DataPointWithLabelInterface[] treatmentsArray = new DataPointWithLabelInterface[filteredTreatments.size()];
treatmentsArray = filteredTreatments.toArray(treatmentsArray); treatmentsArray = filteredTreatments.toArray(treatmentsArray);
if (treatmentsArray.length > 0) { addSeries(new PointsWithLabelGraphSeries<>(treatmentsArray));
addSeriesWithoutInvalidate(bgGraph, new PointsWithLabelGraphSeries<>(treatmentsArray));
}
} }
double getNearestBg(long date) { double getNearestBg(long date) {
@ -278,7 +279,7 @@ public class GraphData {
} }
// scale in % of vertical size (like 0.3) // scale in % of vertical size (like 0.3)
public void addIob(GraphView graph, long fromTime, long toTime, boolean useForScale, double scale) { public void addIob(long fromTime, long toTime, boolean useForScale, double scale) {
FixedLineGraphSeries<ScaledDataPoint> iobSeries; FixedLineGraphSeries<ScaledDataPoint> iobSeries;
List<ScaledDataPoint> iobArray = new ArrayList<>(); List<ScaledDataPoint> iobArray = new ArrayList<>();
Double maxIobValueFound = 0d; Double maxIobValueFound = 0d;
@ -309,11 +310,11 @@ public class GraphData {
iobScale.setMultiplier(maxY * scale / maxIobValueFound); iobScale.setMultiplier(maxY * scale / maxIobValueFound);
addSeriesWithoutInvalidate(graph, iobSeries); addSeries(iobSeries);
} }
// scale in % of vertical size (like 0.3) // scale in % of vertical size (like 0.3)
public void addCob(GraphView graph, long fromTime, long toTime, boolean useForScale, double scale) { public void addCob(long fromTime, long toTime, boolean useForScale, double scale) {
FixedLineGraphSeries<ScaledDataPoint> cobSeries; FixedLineGraphSeries<ScaledDataPoint> cobSeries;
List<ScaledDataPoint> cobArray = new ArrayList<>(); List<ScaledDataPoint> cobArray = new ArrayList<>();
Double maxCobValueFound = 0d; Double maxCobValueFound = 0d;
@ -348,11 +349,11 @@ public class GraphData {
cobScale.setMultiplier(maxY * scale / maxCobValueFound); cobScale.setMultiplier(maxY * scale / maxCobValueFound);
addSeriesWithoutInvalidate(graph, cobSeries); addSeries(cobSeries);
} }
// scale in % of vertical size (like 0.3) // scale in % of vertical size (like 0.3)
public void addDeviations(GraphView graph, long fromTime, long toTime, boolean useForScale, double scale) { public void addDeviations(long fromTime, long toTime, boolean useForScale, double scale) {
class DeviationDataPoint extends ScaledDataPoint { class DeviationDataPoint extends ScaledDataPoint {
public int color; public int color;
@ -395,11 +396,11 @@ public class GraphData {
devScale.setMultiplier(maxY * scale / maxDevValueFound); devScale.setMultiplier(maxY * scale / maxDevValueFound);
addSeriesWithoutInvalidate(graph, devSeries); addSeries(devSeries);
} }
// scale in % of vertical size (like 0.3) // scale in % of vertical size (like 0.3)
public void addRatio(GraphView graph, long fromTime, long toTime, boolean useForScale, double scale) { public void addRatio(long fromTime, long toTime, boolean useForScale, double scale) {
LineGraphSeries<DataPoint> ratioSeries; LineGraphSeries<DataPoint> ratioSeries;
List<DataPoint> ratioArray = new ArrayList<>(); List<DataPoint> ratioArray = new ArrayList<>();
Double maxRatioValueFound = 0d; Double maxRatioValueFound = 0d;
@ -425,11 +426,11 @@ public class GraphData {
ratioScale.setMultiplier(maxY * scale / maxRatioValueFound); ratioScale.setMultiplier(maxY * scale / maxRatioValueFound);
addSeriesWithoutInvalidate(graph, ratioSeries); addSeries(ratioSeries);
} }
// scale in % of vertical size (like 0.3) // scale in % of vertical size (like 0.3)
public void addNowLine(GraphView graph, long now) { public void addNowLine(long now) {
LineGraphSeries<DataPoint> seriesNow; LineGraphSeries<DataPoint> seriesNow;
DataPoint[] nowPoints = new DataPoint[]{ DataPoint[] nowPoints = new DataPoint[]{
new DataPoint(now, 0), new DataPoint(now, 0),
@ -446,10 +447,10 @@ public class GraphData {
paint.setColor(Color.WHITE); paint.setColor(Color.WHITE);
seriesNow.setCustomPaint(paint); seriesNow.setCustomPaint(paint);
addSeriesWithoutInvalidate(graph, seriesNow); addSeries(seriesNow);
} }
public void formatAxis(GraphView graph, long fromTime, long endTime) { public void formatAxis(long fromTime, long endTime) {
graph.getViewport().setMaxX(endTime); graph.getViewport().setMaxX(endTime);
graph.getViewport().setMinX(fromTime); graph.getViewport().setMinX(fromTime);
graph.getViewport().setXAxisBoundsManual(true); graph.getViewport().setXAxisBoundsManual(true);
@ -457,11 +458,23 @@ public class GraphData {
graph.getGridLabelRenderer().setNumHorizontalLabels(7); // only 7 because of the space graph.getGridLabelRenderer().setNumHorizontalLabels(7); // only 7 because of the space
} }
private void addSeriesWithoutInvalidate(GraphView bgGraph, Series s) { private void addSeries(Series s) {
if (!s.isEmpty()) { series.add(s);
s.onGraphViewAttached(bgGraph);
bgGraph.getSeries().add(s);
}
} }
public void performUpdate() {
// clear old data
graph.getSeries().clear();
// add precalculated series
for (Series s: series) {
if (!s.isEmpty()) {
s.onGraphViewAttached(graph);
graph.getSeries().add(s);
}
}
// draw it
graph.onDataChanged(false, false);
}
} }

View file

@ -30,7 +30,10 @@ import android.graphics.Path;
import android.graphics.Point; import android.graphics.Point;
import android.graphics.Rect; import android.graphics.Rect;
import android.graphics.Typeface; import android.graphics.Typeface;
import android.util.TypedValue;
// Added by Rumen for scalable text
import android.content.Context;
import info.nightscout.androidaps.MainApp;
import com.jjoe64.graphview.GraphView; import com.jjoe64.graphview.GraphView;
import com.jjoe64.graphview.series.BaseSeries; import com.jjoe64.graphview.series.BaseSeries;
@ -44,6 +47,13 @@ import java.util.Iterator;
* @author jjoe64 * @author jjoe64
*/ */
public class PointsWithLabelGraphSeries<E extends DataPointWithLabelInterface> extends BaseSeries<E> { public class PointsWithLabelGraphSeries<E extends DataPointWithLabelInterface> extends BaseSeries<E> {
// Default spSize
int spSize = 12;
// Convert the sp to pixels
Context context = MainApp.instance().getApplicationContext();
float scaledTextSize = spSize * context.getResources().getDisplayMetrics().scaledDensity;
float scaledPxSize = context.getResources().getDisplayMetrics().scaledDensity * 1.5f;
/** /**
* choose a predefined shape to render for * choose a predefined shape to render for
* each data point. * each data point.
@ -131,9 +141,6 @@ public class PointsWithLabelGraphSeries<E extends DataPointWithLabelInterface> e
Iterator<E> values = getValues(minX, maxX); Iterator<E> values = getValues(minX, maxX);
// draw background // draw background
double lastEndY = 0;
double lastEndX = 0;
// draw data // draw data
double diffY = maxY - minY; double diffY = maxY - minY;
@ -144,9 +151,8 @@ public class PointsWithLabelGraphSeries<E extends DataPointWithLabelInterface> e
float graphLeft = graphView.getGraphContentLeft(); float graphLeft = graphView.getGraphContentLeft();
float graphTop = graphView.getGraphContentTop(); float graphTop = graphView.getGraphContentTop();
lastEndY = 0; float scaleX = (float) (graphWidth / diffX);
lastEndX = 0;
float firstX = 0;
int i=0; int i=0;
while (values.hasNext()) { while (values.hasNext()) {
E value = values.next(); E value = values.next();
@ -161,9 +167,6 @@ public class PointsWithLabelGraphSeries<E extends DataPointWithLabelInterface> e
double ratX = valX / diffX; double ratX = valX / diffX;
double x = graphWidth * ratX; double x = graphWidth * ratX;
double orgX = x;
double orgY = y;
// overdraw // overdraw
boolean overdraw = false; boolean overdraw = false;
if (x > graphWidth) { // end right if (x > graphWidth) { // end right
@ -175,6 +178,14 @@ public class PointsWithLabelGraphSeries<E extends DataPointWithLabelInterface> e
if (y > graphHeight) { // end top if (y > graphHeight) { // end top
overdraw = true; overdraw = true;
} }
long duration = value.getDuration();
float endWithDuration = (float) (x + duration * scaleX + graphLeft + 1);
// cut off to graph start if needed
if (x < 0 && endWithDuration > 0) {
x = 0;
}
/* Fix a bug that continue to show the DOT after Y axis */ /* Fix a bug that continue to show the DOT after Y axis */
if(x < 0) { if(x < 0) {
overdraw = true; overdraw = true;
@ -185,30 +196,30 @@ public class PointsWithLabelGraphSeries<E extends DataPointWithLabelInterface> e
registerDataPoint(endX, endY, value); registerDataPoint(endX, endY, value);
float xpluslength = 0; float xpluslength = 0;
if (value.getDuration() > 0) { if (duration > 0) {
xpluslength = endX + Math.min((float) (value.getDuration() * graphWidth / diffX), graphLeft + graphWidth); xpluslength = Math.min(endWithDuration, graphLeft + graphWidth);
} }
// draw data point // draw data point
if (!overdraw) { if (!overdraw) {
if (value.getShape() == Shape.POINT) { if (value.getShape() == Shape.POINT) {
mPaint.setStrokeWidth(0); mPaint.setStrokeWidth(0);
canvas.drawCircle(endX, endY, value.getSize(), mPaint); canvas.drawCircle(endX, endY, scaledPxSize, mPaint);
} else if (value.getShape() == Shape.RECTANGLE) { } else if (value.getShape() == Shape.RECTANGLE) {
canvas.drawRect(endX-value.getSize(), endY-value.getSize(), endX+value.getSize(), endY+value.getSize(), mPaint); canvas.drawRect(endX-scaledPxSize, endY-scaledPxSize, endX+scaledPxSize, endY+scaledPxSize, mPaint);
} else if (value.getShape() == Shape.TRIANGLE) { } else if (value.getShape() == Shape.TRIANGLE) {
mPaint.setStrokeWidth(0); mPaint.setStrokeWidth(0);
Point[] points = new Point[3]; Point[] points = new Point[3];
points[0] = new Point((int)endX, (int)(endY-value.getSize())); points[0] = new Point((int)endX, (int)(endY-scaledPxSize));
points[1] = new Point((int)(endX+value.getSize()), (int)(endY+value.getSize()*0.67)); points[1] = new Point((int)(endX+scaledPxSize), (int)(endY+scaledPxSize*0.67));
points[2] = new Point((int)(endX-value.getSize()), (int)(endY+value.getSize()*0.67)); points[2] = new Point((int)(endX-scaledPxSize), (int)(endY+scaledPxSize*0.67));
drawArrows(points, canvas, mPaint); drawArrows(points, canvas, mPaint);
} else if (value.getShape() == Shape.BOLUS) { } else if (value.getShape() == Shape.BOLUS) {
mPaint.setStrokeWidth(0); mPaint.setStrokeWidth(0);
Point[] points = new Point[3]; Point[] points = new Point[3];
points[0] = new Point((int)endX, (int)(endY-value.getSize())); points[0] = new Point((int)endX, (int)(endY-scaledPxSize));
points[1] = new Point((int)(endX+value.getSize()), (int)(endY+value.getSize()*0.67)); points[1] = new Point((int)(endX+scaledPxSize), (int)(endY+scaledPxSize*0.67));
points[2] = new Point((int)(endX-value.getSize()), (int)(endY+value.getSize()*0.67)); points[2] = new Point((int)(endX-scaledPxSize), (int)(endY+scaledPxSize*0.67));
mPaint.setStyle(Paint.Style.FILL_AND_STROKE); mPaint.setStyle(Paint.Style.FILL_AND_STROKE);
drawArrows(points, canvas, mPaint); drawArrows(points, canvas, mPaint);
if (value.getLabel() != null) { if (value.getLabel() != null) {
@ -220,7 +231,7 @@ public class PointsWithLabelGraphSeries<E extends DataPointWithLabelInterface> e
Rect bounds = new Rect((int)endX, (int)endY + 3, (int) (xpluslength), (int) endY + 8); Rect bounds = new Rect((int)endX, (int)endY + 3, (int) (xpluslength), (int) endY + 8);
mPaint.setStyle(Paint.Style.FILL_AND_STROKE); mPaint.setStyle(Paint.Style.FILL_AND_STROKE);
canvas.drawRect(bounds, mPaint); canvas.drawRect(bounds, mPaint);
mPaint.setTextSize((int) (value.getSize() * 2.5)); mPaint.setTextSize((float) (scaledTextSize));
mPaint.setTypeface(Typeface.create(Typeface.DEFAULT, Typeface.NORMAL)); mPaint.setTypeface(Typeface.create(Typeface.DEFAULT, Typeface.NORMAL));
mPaint.setFakeBoldText(true); mPaint.setFakeBoldText(true);
canvas.drawText(value.getLabel(), endX, endY, mPaint); canvas.drawText(value.getLabel(), endX, endY, mPaint);
@ -228,7 +239,8 @@ public class PointsWithLabelGraphSeries<E extends DataPointWithLabelInterface> e
} else if (value.getShape() == Shape.PROFILE) { } else if (value.getShape() == Shape.PROFILE) {
mPaint.setStrokeWidth(0); mPaint.setStrokeWidth(0);
if (value.getLabel() != null) { if (value.getLabel() != null) {
mPaint.setTextSize((int) (value.getSize() * 3)); //mPaint.setTextSize((int) (scaledPxSize * 3));
mPaint.setTextSize((float) (scaledTextSize*1.2));
mPaint.setTypeface(Typeface.create(Typeface.DEFAULT, Typeface.BOLD)); mPaint.setTypeface(Typeface.create(Typeface.DEFAULT, Typeface.BOLD));
Rect bounds = new Rect(); Rect bounds = new Rect();
mPaint.getTextBounds(value.getLabel(), 0, value.getLabel().length(), bounds); mPaint.getTextBounds(value.getLabel(), 0, value.getLabel().length(), bounds);
@ -245,25 +257,25 @@ public class PointsWithLabelGraphSeries<E extends DataPointWithLabelInterface> e
mPaint.setStyle(Paint.Style.STROKE); mPaint.setStyle(Paint.Style.STROKE);
mPaint.setStrokeWidth(5); mPaint.setStrokeWidth(5);
float w = mPaint.getStrokeWidth(); float w = mPaint.getStrokeWidth();
canvas.drawCircle(endX, endY, value.getSize(), mPaint); canvas.drawCircle(endX, endY, scaledPxSize, mPaint);
} else if (value.getShape() == Shape.BGCHECK) { } else if (value.getShape() == Shape.BGCHECK) {
mPaint.setStyle(Paint.Style.FILL_AND_STROKE); mPaint.setStyle(Paint.Style.FILL_AND_STROKE);
mPaint.setStrokeWidth(0); mPaint.setStrokeWidth(0);
canvas.drawCircle(endX, endY, value.getSize(), mPaint); canvas.drawCircle(endX, endY, scaledPxSize, mPaint);
if (value.getLabel() != null) { if (value.getLabel() != null) {
drawLabel45(endX, endY, value, canvas); drawLabel45(endX, endY, value, canvas);
} }
} else if (value.getShape() == Shape.ANNOUNCEMENT) { } else if (value.getShape() == Shape.ANNOUNCEMENT) {
mPaint.setStyle(Paint.Style.FILL_AND_STROKE); mPaint.setStyle(Paint.Style.FILL_AND_STROKE);
mPaint.setStrokeWidth(0); mPaint.setStrokeWidth(0);
canvas.drawCircle(endX, endY, value.getSize(), mPaint); canvas.drawCircle(endX, endY, scaledPxSize, mPaint);
if (value.getLabel() != null) { if (value.getLabel() != null) {
drawLabel45(endX, endY, value, canvas); drawLabel45(endX, endY, value, canvas);
} }
} else if (value.getShape() == Shape.GENERAL) { } else if (value.getShape() == Shape.GENERAL) {
mPaint.setStyle(Paint.Style.FILL_AND_STROKE); mPaint.setStyle(Paint.Style.FILL_AND_STROKE);
mPaint.setStrokeWidth(0); mPaint.setStrokeWidth(0);
canvas.drawCircle(endX, endY, value.getSize(), mPaint); canvas.drawCircle(endX, endY, scaledPxSize, mPaint);
if (value.getLabel() != null) { if (value.getLabel() != null) {
drawLabel45(endX, endY, value, canvas); drawLabel45(endX, endY, value, canvas);
} }
@ -271,7 +283,7 @@ public class PointsWithLabelGraphSeries<E extends DataPointWithLabelInterface> e
mPaint.setStrokeWidth(0); mPaint.setStrokeWidth(0);
if (value.getLabel() != null) { if (value.getLabel() != null) {
mPaint.setStrokeWidth(0); mPaint.setStrokeWidth(0);
mPaint.setTextSize((int) (value.getSize() * 3)); mPaint.setTextSize((float) (scaledTextSize * 1.2));
mPaint.setTypeface(Typeface.create(Typeface.DEFAULT, Typeface.BOLD)); mPaint.setTypeface(Typeface.create(Typeface.DEFAULT, Typeface.BOLD));
Rect bounds = new Rect(); Rect bounds = new Rect();
mPaint.getTextBounds(value.getLabel(), 0, value.getLabel().length(), bounds); mPaint.getTextBounds(value.getLabel(), 0, value.getLabel().length(), bounds);
@ -286,7 +298,7 @@ public class PointsWithLabelGraphSeries<E extends DataPointWithLabelInterface> e
mPaint.setStrokeWidth(0); mPaint.setStrokeWidth(0);
if (value.getLabel() != null) { if (value.getLabel() != null) {
mPaint.setStrokeWidth(0); mPaint.setStrokeWidth(0);
mPaint.setTextSize((int) (value.getSize() * 3)); mPaint.setTextSize(scaledTextSize);
mPaint.setTypeface(Typeface.create(Typeface.DEFAULT, Typeface.BOLD)); mPaint.setTypeface(Typeface.create(Typeface.DEFAULT, Typeface.BOLD));
Rect bounds = new Rect(); Rect bounds = new Rect();
mPaint.getTextBounds(value.getLabel(), 0, value.getLabel().length(), bounds); mPaint.getTextBounds(value.getLabel(), 0, value.getLabel().length(), bounds);
@ -301,7 +313,7 @@ public class PointsWithLabelGraphSeries<E extends DataPointWithLabelInterface> e
mPaint.setStrokeWidth(0); mPaint.setStrokeWidth(0);
if (value.getLabel() != null) { if (value.getLabel() != null) {
mPaint.setStrokeWidth(0); mPaint.setStrokeWidth(0);
mPaint.setTextSize((int) (value.getSize() * 3)); mPaint.setTextSize((float) (scaledTextSize * 1.5));
mPaint.setTypeface(Typeface.create(Typeface.DEFAULT, Typeface.BOLD)); mPaint.setTypeface(Typeface.create(Typeface.DEFAULT, Typeface.BOLD));
Rect bounds = new Rect(); Rect bounds = new Rect();
mPaint.getTextBounds(value.getLabel(), 0, value.getLabel().length(), bounds); mPaint.getTextBounds(value.getLabel(), 0, value.getLabel().length(), bounds);
@ -352,26 +364,26 @@ public class PointsWithLabelGraphSeries<E extends DataPointWithLabelInterface> e
void drawLabel45(float endX, float endY, E value, Canvas canvas) { void drawLabel45(float endX, float endY, E value, Canvas canvas) {
if (value.getLabel().startsWith("~")) { if (value.getLabel().startsWith("~")) {
float px = endX; float px = endX;
float py = endY + value.getSize(); float py = endY + scaledPxSize;
canvas.save(); canvas.save();
canvas.rotate(-45, px, py); canvas.rotate(-45, px, py);
mPaint.setTextSize((int) (value.getSize() * 2.5)); mPaint.setTextSize((float) (scaledTextSize*0.8));
mPaint.setTypeface(Typeface.create(Typeface.DEFAULT, Typeface.NORMAL)); mPaint.setTypeface(Typeface.create(Typeface.DEFAULT, Typeface.NORMAL));
mPaint.setFakeBoldText(true); mPaint.setFakeBoldText(true);
mPaint.setTextAlign(Paint.Align.RIGHT); mPaint.setTextAlign(Paint.Align.RIGHT);
canvas.drawText(value.getLabel().substring(1), px - value.getSize(), py, mPaint); canvas.drawText(value.getLabel().substring(1), px - scaledPxSize, py, mPaint);
mPaint.setTextAlign(Paint.Align.LEFT); mPaint.setTextAlign(Paint.Align.LEFT);
canvas.restore(); canvas.restore();
} else { } else {
float px = endX; float px = endX;
float py = endY - value.getSize(); float py = endY - scaledPxSize;
canvas.save(); canvas.save();
canvas.rotate(-45, px, py); canvas.rotate(-45, px, py);
mPaint.setTextSize((int) (value.getSize() * 2.5)); mPaint.setTextSize((float) (scaledTextSize*0.8));
mPaint.setTypeface(Typeface.create(Typeface.DEFAULT, Typeface.NORMAL)); mPaint.setTypeface(Typeface.create(Typeface.DEFAULT, Typeface.NORMAL));
mPaint.setFakeBoldText(true); mPaint.setFakeBoldText(true);
canvas.drawText(value.getLabel(), px + value.getSize(), py, mPaint); canvas.drawText(value.getLabel(), px + scaledPxSize, py, mPaint);
canvas.restore(); canvas.restore();
} }
} }
} }

View file

@ -0,0 +1,36 @@
package info.nightscout.androidaps.plugins.Overview.notifications;
import android.app.IntentService;
import android.app.PendingIntent;
import android.content.Intent;
import android.support.annotation.Nullable;
import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.plugins.Overview.events.EventDismissNotification;
public class DismissNotificationService extends IntentService {
/**
* Creates an IntentService. Invoked by your subclass's constructor.
*
* @param name Used to name the worker thread, important only for debugging.
*/
public DismissNotificationService(String name) {
super(name);
}
public DismissNotificationService(){
super("DismissNotificationService");
};
@Override
protected void onHandleIntent(@Nullable Intent intent) {
MainApp.bus().post(new EventDismissNotification(intent.getIntExtra("alertID", -1)));
}
public static PendingIntent deleteIntent(int id){
Intent intent = new Intent(MainApp.instance(), DismissNotificationService.class);
intent.putExtra("alertID", id);
return PendingIntent.getService(MainApp.instance(), id, intent, PendingIntent.FLAG_UPDATE_CURRENT);
}
}

View file

@ -1,5 +1,8 @@
package info.nightscout.androidaps.plugins.Overview; package info.nightscout.androidaps.plugins.Overview.notifications;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.Date; import java.util.Date;
@ -11,15 +14,14 @@ import info.nightscout.androidaps.plugins.NSClientInternal.data.NSSettingsStatus
import info.nightscout.utils.SP; import info.nightscout.utils.SP;
// Added by Rumen for debugging // Added by Rumen for debugging
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/** /**
* Created by mike on 03.12.2016. * Created by mike on 03.12.2016.
*/ */
public class Notification { public class Notification {
private static Logger log = LoggerFactory.getLogger(Notification.class); private static Logger log = LoggerFactory.getLogger(Notification.class);
public static final int URGENT = 0; public static final int URGENT = 0;
public static final int NORMAL = 1; public static final int NORMAL = 1;
public static final int LOW = 2; public static final int LOW = 2;
@ -50,7 +52,13 @@ public class Notification {
public static final int SHORT_DIA = 21; public static final int SHORT_DIA = 21;
public static final int TOAST_ALARM = 22; public static final int TOAST_ALARM = 22;
public static final int WRONGBASALSTEP = 23; public static final int WRONGBASALSTEP = 23;
public static final int BOLUS_DELIVERY_ERROR = 24; public static final int WRONG_DRIVER = 24;
public static final int PUMP_UNREACHABLE = 26;
public static final int BG_READINGS_MISSED = 27;
public static final int UNSUPPORTED_FIRMWARE = 28;
public static final int MINIMAL_BASAL_VALUE_REPLACED = 29;
public static final int BASAL_PROFILE_NOT_ALIGNED_TO_HOURS = 30;
public static final int ZERO_VALUE_IN_PROFILE = 31;
public int id; public int id;
public Date date; public Date date;
@ -60,7 +68,6 @@ public class Notification {
public NSAlarm nsAlarm = null; public NSAlarm nsAlarm = null;
public Integer soundId = null; public Integer soundId = null;
public Notification() { public Notification() {
} }
@ -88,6 +95,27 @@ public class Notification {
this.validTo = new Date(0); this.validTo = new Date(0);
} }
public Notification(int id) {
this.id = id;
this.date = new Date();
this.validTo = new Date(0);
}
public Notification text(String text) {
this.text = text;
return this;
}
public Notification level(int level) {
this.level = level;
return this;
}
public Notification sound(int soundId) {
this.soundId = soundId;
return this;
}
public Notification(NSAlarm nsAlarm) { public Notification(NSAlarm nsAlarm) {
this.date = new Date(); this.date = new Date();
this.validTo = new Date(0); this.validTo = new Date(0);
@ -103,7 +131,7 @@ public class Notification {
this.id = NSALARM; this.id = NSALARM;
this.level = NORMAL; this.level = NORMAL;
this.text = nsAlarm.getTile(); this.text = nsAlarm.getTile();
if (isAlarmForLow() && SP.getBoolean(R.string.key_nsalarm_low, false) || isAlarmForHigh() && SP.getBoolean(R.string.key_nsalarm_high, false) || isAlarmForStaleData() && SP.getBoolean(R.string.key_nsalarm_staledata,false)) if (isAlarmForLow() && SP.getBoolean(R.string.key_nsalarm_low, false) || isAlarmForHigh() && SP.getBoolean(R.string.key_nsalarm_high, false) || isAlarmForStaleData() && SP.getBoolean(R.string.key_nsalarm_staledata, false))
this.soundId = R.raw.alarm; this.soundId = R.raw.alarm;
break; break;
case 2: case 2:
@ -121,8 +149,7 @@ public class Notification {
return true; return true;
if (level == ANNOUNCEMENT) if (level == ANNOUNCEMENT)
return true; return true;
if (level == NORMAL && isAlarmForLow() && SP.getBoolean(R.string.key_nsalarm_low, false) || isAlarmForHigh() && SP.getBoolean(R.string.key_nsalarm_high, false) || isAlarmForStaleData() && SP.getBoolean(R.string.key_nsalarm_staledata, false)) if (level == NORMAL && isAlarmForLow() && SP.getBoolean(R.string.key_nsalarm_low, false) || isAlarmForHigh() && SP.getBoolean(R.string.key_nsalarm_high, false) || isAlarmForStaleData() && SP.getBoolean(R.string.key_nsalarm_staledata, false)) {
{
return true; return true;
} }
if (level == URGENT && isAlarmForLow() && SP.getBoolean(R.string.key_nsalarm_urgent_low, false) || isAlarmForHigh() && SP.getBoolean(R.string.key_nsalarm_urgent_high, false) || isAlarmForStaleData() && SP.getBoolean(R.string.key_nsalarm_urgent_staledata, false)) if (level == URGENT && isAlarmForLow() && SP.getBoolean(R.string.key_nsalarm_urgent_low, false) || isAlarmForHigh() && SP.getBoolean(R.string.key_nsalarm_urgent_high, false) || isAlarmForStaleData() && SP.getBoolean(R.string.key_nsalarm_urgent_staledata, false))
@ -153,35 +180,37 @@ public class Notification {
return true; return true;
return false; return false;
} }
static boolean isAlarmForStaleData(){ public static boolean isAlarmForStaleData(){
if(SP.getLong("snoozedTo", 0L) != 0L){ long snoozedTo = SP.getLong("snoozedTo", 0L);
if(snoozedTo != 0L){
if(System.currentTimeMillis() < SP.getLong("snoozedTo", 0L)) { if(System.currentTimeMillis() < SP.getLong("snoozedTo", 0L)) {
//log.debug("Alarm is snoozed for next "+(SP.getLong("snoozedTo", 0L)-System.currentTimeMillis())/1000+" seconds"); //log.debug("Alarm is snoozed for next "+(SP.getLong("snoozedTo", 0L)-System.currentTimeMillis())/1000+" seconds");
return false; return false;
} }
} }
BgReading bgReading = MainApp.getDbHelper().lastBg(); BgReading bgReading = MainApp.getDbHelper().lastBg();
if (bgReading == null) if (bgReading == null)
return false; return false;
long bgReadingAgo = System.currentTimeMillis() - bgReading.date; long bgReadingAgo = System.currentTimeMillis() - bgReading.date;
int bgReadingAgoMin = (int) (bgReadingAgo / (1000 * 60)); int bgReadingAgoMin = (int) (bgReadingAgo / (1000 * 60));
// Added for testing // Added for testing
//bgReadingAgoMin = 20; // bgReadingAgoMin = 20;
log.debug("bgReadingAgoMin value is:"+bgReadingAgoMin); boolean openAPSEnabledAlerts = NSSettingsStatus.getInstance().openAPSEnabledAlerts();
//log.debug("bgReadingAgoMin value is:"+bgReadingAgoMin);
//log.debug("Stale alarm snoozed to: "+(System.currentTimeMillis() - snoozedTo)/60000L);
Double threshold = NSSettingsStatus.getInstance().getThreshold("alarmTimeagoWarnMins"); Double threshold = NSSettingsStatus.getInstance().getThreshold("alarmTimeagoWarnMins");
boolean openAPSEnabledAlerts = NSSettingsStatus.getInstance().openAPSEnabledAlerts(); //log.debug("OpenAPS Alerts enabled: "+openAPSEnabledAlerts);
log.debug("OpenAPS Alerts enabled: "+openAPSEnabledAlerts); // if no thresshold from Ns get it loccally
// if no thresshold from Ns get it loccally
if(threshold == null) threshold = SP.getDouble(R.string.key_nsalarm_staledatavalue,15D); if(threshold == null) threshold = SP.getDouble(R.string.key_nsalarm_staledatavalue,15D);
// No threshold of OpenAPS Alarm so using the one for BG // No threshold of OpenAPS Alarm so using the one for BG
// Added OpenAPSEnabledAlerts to alarm check // Added OpenAPSEnabledAlerts to alarm check
if((bgReadingAgoMin > threshold && SP.getBoolean(R.string.key_nsalarm_staledata, false))||(bgReadingAgoMin > threshold && openAPSEnabledAlerts)){ if((bgReadingAgoMin > threshold && SP.getBoolean(R.string.key_nsalarm_staledata, false))||(bgReadingAgoMin > threshold && openAPSEnabledAlerts)){
return true; return true;
} }
//snoozing for threshold //snoozing for threshold
SP.putLong("snoozedTo", (long) (bgReading.date+(threshold*1000*60L))); SP.putLong("snoozedTo", (long) (bgReading.date + (threshold * 1000 * 60L)));
//log.debug("New bg data is available Alarm is snoozed for next "+threshold*1000*60+" seconds"); //log.debug("New bg data is available Alarm is snoozed for next "+threshold*1000*60+" seconds");
return false; return false;
} }
} }

View file

@ -1,6 +1,14 @@
package info.nightscout.androidaps.plugins.Overview; package info.nightscout.androidaps.plugins.Overview.notifications;
import android.app.NotificationManager;
import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.media.AudioAttributes;
import android.media.RingtoneManager;
import android.net.Uri;
import android.support.v4.app.NotificationCompat;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
@ -8,7 +16,6 @@ import org.slf4j.LoggerFactory;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.Comparator; import java.util.Comparator;
import java.util.Date;
import java.util.List; import java.util.List;
import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.MainApp;
@ -26,6 +33,7 @@ public class NotificationStore {
private static Logger log = LoggerFactory.getLogger(NotificationStore.class); private static Logger log = LoggerFactory.getLogger(NotificationStore.class);
public List<Notification> store = new ArrayList<Notification>(); public List<Notification> store = new ArrayList<Notification>();
public long snoozedUntil = 0L; public long snoozedUntil = 0L;
public NotificationStore() { public NotificationStore() {
} }
@ -49,21 +57,45 @@ public class NotificationStore {
return; return;
} }
} }
if (n.soundId != null) {
Intent alarm = new Intent(MainApp.instance().getApplicationContext(), AlarmSoundService.class);
alarm.putExtra("soundid", n.soundId);
MainApp.instance().startService(alarm);
}
store.add(n); store.add(n);
WearPlugin wearPlugin = MainApp.getSpecificPlugin(WearPlugin.class); if (SP.getBoolean(MainApp.sResources.getString(R.string.key_raise_notifications_as_android_notifications), false)) {
if(wearPlugin!= null && wearPlugin.isEnabled()) { raiseSystemNotification(n);
wearPlugin.overviewNotification(n.id, "OverviewNotification:\n" + n.text); } else {
if (n.soundId != null) {
Intent alarm = new Intent(MainApp.instance().getApplicationContext(), AlarmSoundService.class);
alarm.putExtra("soundid", n.soundId);
MainApp.instance().startService(alarm);
}
} }
Collections.sort(store, new NotificationComparator()); Collections.sort(store, new NotificationComparator());
} }
private void raiseSystemNotification(Notification n) {
Context context = MainApp.instance().getApplicationContext();
NotificationManager mgr = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
Bitmap largeIcon = BitmapFactory.decodeResource(context.getResources(), R.mipmap.blueowl);
Uri sound = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_ALARM);
NotificationCompat.Builder notificationBuilder =
new NotificationCompat.Builder(context)
.setSmallIcon(R.drawable.ic_notification)
.setLargeIcon(largeIcon)
.setContentText(n.text)
.setPriority(NotificationCompat.PRIORITY_MAX)
.setDeleteIntent(DismissNotificationService.deleteIntent(n.id));
if (n.level == Notification.URGENT) {
notificationBuilder.setVibrate(new long[]{1000, 1000, 1000, 1000})
.setContentTitle(MainApp.sResources.getString(R.string.urgent_alarm))
.setSound(sound, AudioAttributes.USAGE_ALARM);
} else {
notificationBuilder.setVibrate(new long[]{0, 100, 50, 100, 50})
.setContentTitle(MainApp.sResources.getString(R.string.info))
;
}
mgr.notify(n.id, notificationBuilder.build());
}
public boolean remove(int id) { public boolean remove(int id) {
for (int i = 0; i < store.size(); i++) { for (int i = 0; i < store.size(); i++) {
if (get(i).id == id) { if (get(i).id == id) {
@ -87,14 +119,14 @@ public class NotificationStore {
} }
} }
} }
public void snoozeTo(long timeToSnooze){ public void snoozeTo(long timeToSnooze) {
log.debug("Snoozing alarm until: "+timeToSnooze); log.debug("Snoozing alarm until: " + timeToSnooze);
SP.putLong("snoozedTo", timeToSnooze); SP.putLong("snoozedTo", timeToSnooze);
} }
public void unSnooze(){ public void unSnooze() {
if(Notification.isAlarmForStaleData()){ if (Notification.isAlarmForStaleData()) {
Notification notification = new Notification(Notification.NSALARM, MainApp.sResources.getString(R.string.nsalarm_staledata), Notification.URGENT); Notification notification = new Notification(Notification.NSALARM, MainApp.sResources.getString(R.string.nsalarm_staledata), Notification.URGENT);
SP.putLong("snoozedTo", System.currentTimeMillis()); SP.putLong("snoozedTo", System.currentTimeMillis());
add(notification); add(notification);

View file

@ -7,7 +7,7 @@ import android.content.Intent;
import android.graphics.Bitmap; import android.graphics.Bitmap;
import android.graphics.BitmapFactory; import android.graphics.BitmapFactory;
import android.support.v4.app.TaskStackBuilder; import android.support.v4.app.TaskStackBuilder;
import android.support.v7.app.NotificationCompat; import android.support.v4.app.NotificationCompat;
import com.squareup.otto.Subscribe; import com.squareup.otto.Subscribe;
@ -29,7 +29,7 @@ import info.nightscout.androidaps.events.EventRefreshOverview;
import info.nightscout.androidaps.events.EventTempBasalChange; import info.nightscout.androidaps.events.EventTempBasalChange;
import info.nightscout.androidaps.events.EventTreatmentChange; import info.nightscout.androidaps.events.EventTreatmentChange;
import info.nightscout.androidaps.interfaces.PluginBase; import info.nightscout.androidaps.interfaces.PluginBase;
import info.nightscout.androidaps.interfaces.PumpInterface; import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin;
import info.nightscout.utils.DecimalFormatter; import info.nightscout.utils.DecimalFormatter;
/** /**
@ -139,10 +139,8 @@ public class PersistentNotificationPlugin implements PluginBase {
} }
} }
PumpInterface pump = MainApp.getConfigBuilder(); TemporaryBasal activeTemp = MainApp.getConfigBuilder().getTempBasalFromHistory(System.currentTimeMillis());
if (activeTemp != null) {
if (MainApp.getConfigBuilder().isTempBasalInProgress()) {
TemporaryBasal activeTemp = MainApp.getConfigBuilder().getTempBasalFromHistory(System.currentTimeMillis());
line1 += " " + activeTemp.toStringShort(); line1 += " " + activeTemp.toStringShort();
} }
@ -157,7 +155,7 @@ public class PersistentNotificationPlugin implements PluginBase {
+ ctx.getString(R.string.basal) + ": " + DecimalFormatter.to2Decimal(basalIob.basaliob) + "U)"; + ctx.getString(R.string.basal) + ": " + DecimalFormatter.to2Decimal(basalIob.basaliob) + "U)";
String line3 = DecimalFormatter.to2Decimal(pump.getBaseBasalRate()) + " U/h"; String line3 = DecimalFormatter.to2Decimal(ConfigBuilderPlugin.getActivePump().getBaseBasalRate()) + " U/h";
line3 += " - " + MainApp.getConfigBuilder().getProfileName(); line3 += " - " + MainApp.getConfigBuilder().getProfileName();

View file

@ -35,11 +35,11 @@ import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.R; import info.nightscout.androidaps.R;
import info.nightscout.androidaps.events.EventInitializationChanged; import info.nightscout.androidaps.events.EventInitializationChanged;
import info.nightscout.androidaps.events.EventProfileSwitchChange; import info.nightscout.androidaps.events.EventProfileSwitchChange;
import info.nightscout.androidaps.interfaces.PumpInterface;
import info.nightscout.androidaps.plugins.Careportal.CareportalFragment; import info.nightscout.androidaps.plugins.Careportal.CareportalFragment;
import info.nightscout.androidaps.plugins.Careportal.Dialogs.NewNSTreatmentDialog; import info.nightscout.androidaps.plugins.Careportal.Dialogs.NewNSTreatmentDialog;
import info.nightscout.androidaps.plugins.Careportal.OptionsToShow; import info.nightscout.androidaps.plugins.Careportal.OptionsToShow;
import info.nightscout.androidaps.plugins.Common.SubscriberFragment; import info.nightscout.androidaps.plugins.Common.SubscriberFragment;
import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin;
import info.nightscout.utils.DecimalFormatter; import info.nightscout.utils.DecimalFormatter;
import info.nightscout.utils.SafeParse; import info.nightscout.utils.SafeParse;
@ -151,8 +151,7 @@ public class CircadianPercentageProfileFragment extends SubscriberFragment {
iceditIcon = (ImageView) layout.findViewById(R.id.circadianpercentageprofile_icedit); iceditIcon = (ImageView) layout.findViewById(R.id.circadianpercentageprofile_icedit);
isfeditIcon = (ImageView) layout.findViewById(R.id.circadianpercentageprofile_isfedit); isfeditIcon = (ImageView) layout.findViewById(R.id.circadianpercentageprofile_isfedit);
PumpInterface pump = MainApp.getConfigBuilder(); if (!ConfigBuilderPlugin.getActivePump().getPumpDescription().isTempBasalCapable) {
if (!pump.getPumpDescription().isTempBasalCapable) {
layout.findViewById(R.id.circadianpercentageprofile_baseprofilebasal_layout).setVisibility(View.GONE); layout.findViewById(R.id.circadianpercentageprofile_baseprofilebasal_layout).setVisibility(View.GONE);
} }
@ -334,7 +333,8 @@ public class CircadianPercentageProfileFragment extends SubscriberFragment {
adb.setPositiveButton("MIGRATE", new DialogInterface.OnClickListener() { adb.setPositiveButton("MIGRATE", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) { public void onClick(DialogInterface dialog, int which) {
CircadianPercentageProfilePlugin.migrateToLP(); CircadianPercentageProfilePlugin.migrateToLP();
} }); }
});
adb.setNegativeButton("Cancel", null); adb.setNegativeButton("Cancel", null);
adb.show(); adb.show();
} }
@ -366,7 +366,7 @@ public class CircadianPercentageProfileFragment extends SubscriberFragment {
} }
private void customSnackbar(View view, final String Msg, Object snackbarCaller) { private void customSnackbar(View view, final String Msg, Object snackbarCaller) {
if(mSnackBar!= null) mSnackBar.dismiss(); if (mSnackBar != null) mSnackBar.dismiss();
this.snackbarCaller = snackbarCaller; this.snackbarCaller = snackbarCaller;
if (timeshiftViewHint || percentageViewHint) { if (timeshiftViewHint || percentageViewHint) {
@ -522,7 +522,7 @@ public class CircadianPercentageProfileFragment extends SubscriberFragment {
activity.runOnUiThread(new Runnable() { activity.runOnUiThread(new Runnable() {
@Override @Override
public void run() { public void run() {
if (!MainApp.getConfigBuilder().isInitialized() || MainApp.getConfigBuilder().isSuspended()) { if (!ConfigBuilderPlugin.getActivePump().isInitialized() || ConfigBuilderPlugin.getActivePump().isSuspended()) {
profileswitchButton.setVisibility(View.GONE); profileswitchButton.setVisibility(View.GONE);
} else { } else {
profileswitchButton.setVisibility(View.VISIBLE); profileswitchButton.setVisibility(View.VISIBLE);

View file

@ -16,12 +16,10 @@ import info.nightscout.androidaps.Constants;
import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.R; import info.nightscout.androidaps.R;
import info.nightscout.androidaps.data.Profile; import info.nightscout.androidaps.data.Profile;
import info.nightscout.androidaps.data.ProfileStore;
import info.nightscout.androidaps.interfaces.PluginBase; import info.nightscout.androidaps.interfaces.PluginBase;
import info.nightscout.androidaps.interfaces.ProfileInterface; import info.nightscout.androidaps.interfaces.ProfileInterface;
import info.nightscout.androidaps.data.ProfileStore;
import info.nightscout.androidaps.interfaces.PumpInterface;
import info.nightscout.androidaps.plugins.Careportal.Dialogs.NewNSTreatmentDialog; import info.nightscout.androidaps.plugins.Careportal.Dialogs.NewNSTreatmentDialog;
import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin;
import info.nightscout.androidaps.plugins.ProfileLocal.LocalProfilePlugin; import info.nightscout.androidaps.plugins.ProfileLocal.LocalProfilePlugin;
import info.nightscout.utils.DecimalFormatter; import info.nightscout.utils.DecimalFormatter;
import info.nightscout.utils.NSUpload; import info.nightscout.utils.NSUpload;
@ -164,43 +162,36 @@ public class CircadianPercentageProfilePlugin implements PluginBase, ProfileInte
baseic[i] = SP.getDouble(SETTINGS_PREFIX + "baseic" + i, baseic[i]); baseic[i] = SP.getDouble(SETTINGS_PREFIX + "baseic" + i, baseic[i]);
baseisf[i] = SP.getDouble(SETTINGS_PREFIX + "baseisf" + i, baseisf[i]); baseisf[i] = SP.getDouble(SETTINGS_PREFIX + "baseisf" + i, baseisf[i]);
} }
createConvertedProfile();
} }
public String externallySetParameters(int timeshift, int percentage) { public String externallySetParameters(int timeshift, int percentage) {
String msg = ""; String msg = "";
if (!fragmentEnabled){ if (!fragmentEnabled) {
msg+= "NO CPP!" + "\n"; msg += "NO CPP!" + "\n";
} }
//check for validity //check for validity
if (percentage < Constants.CPP_MIN_PERCENTAGE || percentage > Constants.CPP_MAX_PERCENTAGE) { if (percentage < Constants.CPP_MIN_PERCENTAGE || percentage > Constants.CPP_MAX_PERCENTAGE) {
msg+= String.format(MainApp.sResources.getString(R.string.openapsma_valueoutofrange), "Profile-Percentage") + "\n"; msg += String.format(MainApp.sResources.getString(R.string.openapsma_valueoutofrange), "Profile-Percentage") + "\n";
} }
if (timeshift < 0 || timeshift > 23) { if (timeshift < 0 || timeshift > 23) {
msg+= String.format(MainApp.sResources.getString(R.string.openapsma_valueoutofrange), "Profile-Timeshift") + "\n"; msg += String.format(MainApp.sResources.getString(R.string.openapsma_valueoutofrange), "Profile-Timeshift") + "\n";
} }
if(!SP.getBoolean("syncprofiletopump", false)){
msg+= MainApp.sResources.getString(R.string.syncprofiletopump_title) + " " + MainApp.sResources.getString(R.string.cpp_sync_setting_missing) + "\n";
}
final PumpInterface pump = MainApp.getConfigBuilder();
final Profile profile = MainApp.getConfigBuilder().getProfile(); final Profile profile = MainApp.getConfigBuilder().getProfile();
if (pump == null || profile == null || profile.getBasal() == null){ if (profile == null || profile.getBasal() == null) {
msg+= MainApp.sResources.getString(R.string.cpp_notloadedplugins) + "\n"; msg += MainApp.sResources.getString(R.string.cpp_notloadedplugins) + "\n";
} }
if(!"".equals(msg)) { if (!"".equals(msg)) {
msg += MainApp.sResources.getString(R.string.cpp_valuesnotstored); msg += MainApp.sResources.getString(R.string.cpp_valuesnotstored);
return msg; return msg;
} }
//store profile //store profile
this.timeshift= timeshift; this.timeshift = timeshift;
this.percentage = percentage; this.percentage = percentage;
storeSettings(); storeSettings();
@ -218,7 +209,7 @@ public class CircadianPercentageProfilePlugin implements PluginBase, ProfileInte
return msg; return msg;
} }
public static void migrateToLP(){ public static void migrateToLP() {
SharedPreferences settings = PreferenceManager.getDefaultSharedPreferences(MainApp.instance().getApplicationContext()); SharedPreferences settings = PreferenceManager.getDefaultSharedPreferences(MainApp.instance().getApplicationContext());
SharedPreferences.Editor editor = settings.edit(); SharedPreferences.Editor editor = settings.edit();
editor.putBoolean("LocalProfile" + "mmol", SP.getBoolean(SETTINGS_PREFIX + "mmol", false)); editor.putBoolean("LocalProfile" + "mmol", SP.getBoolean(SETTINGS_PREFIX + "mmol", false));
@ -232,7 +223,7 @@ public class CircadianPercentageProfilePlugin implements PluginBase, ProfileInte
JSONArray targetHigh = new JSONArray().put(new JSONObject().put("time", "00:00").put("timeAsSeconds", 0).put("value", SP.getDouble(SETTINGS_PREFIX + "targethigh", 120d))); JSONArray targetHigh = new JSONArray().put(new JSONObject().put("time", "00:00").put("timeAsSeconds", 0).put("value", SP.getDouble(SETTINGS_PREFIX + "targethigh", 120d)));
editor.putString("LocalProfile" + "targetlow", targetLow.toString()); editor.putString("LocalProfile" + "targetlow", targetLow.toString());
editor.putString("LocalProfile" + "targethigh", targetHigh.toString()); editor.putString("LocalProfile" + "targethigh", targetHigh.toString());
} catch (JSONException e) { } catch (JSONException e) {
e.printStackTrace(); e.printStackTrace();
} }
editor.commit(); editor.commit();
@ -247,19 +238,19 @@ public class CircadianPercentageProfilePlugin implements PluginBase, ProfileInte
} }
public static String getLPisf(){ public static String getLPisf() {
return getLPConversion("baseisf", 35d); return getLPConversion("baseisf", 35d);
} }
public static String getLPic(){ public static String getLPic() {
return getLPConversion("baseic", 4); return getLPConversion("baseic", 4);
} }
public static String getLPbasal(){ public static String getLPbasal() {
return getLPConversion("basebasal", 1); return getLPConversion("basebasal", 1);
} }
public static String getLPConversion(String type, double defaultValue){ public static String getLPConversion(String type, double defaultValue) {
try { try {
JSONArray jsonArray = new JSONArray(); JSONArray jsonArray = new JSONArray();
double last = -1d; double last = -1d;
@ -269,10 +260,10 @@ public class CircadianPercentageProfilePlugin implements PluginBase, ProfileInte
String time; String time;
DecimalFormat df = new DecimalFormat("00"); DecimalFormat df = new DecimalFormat("00");
time = df.format(i) + ":00"; time = df.format(i) + ":00";
if(last != value) { if (last != value) {
jsonArray.put(new JSONObject().put("time", time).put("timeAsSeconds", i * 60 * 60).put("value", value)); jsonArray.put(new JSONObject().put("time", time).put("timeAsSeconds", i * 60 * 60).put("value", value));
} }
last = value; last = value;
} }
return jsonArray.toString(); return jsonArray.toString();
} catch (JSONException e) { } catch (JSONException e) {
@ -353,6 +344,9 @@ public class CircadianPercentageProfilePlugin implements PluginBase, ProfileInte
@Override @Override
public ProfileStore getProfile() { public ProfileStore getProfile() {
if (convertedProfile == null)
createConvertedProfile();
performLimitCheck(); performLimitCheck();
return convertedProfile; return convertedProfile;
} }
@ -364,6 +358,9 @@ public class CircadianPercentageProfilePlugin implements PluginBase, ProfileInte
@Override @Override
public String getProfileName() { public String getProfileName() {
if (convertedProfile == null)
createConvertedProfile();
performLimitCheck(); performLimitCheck();
return convertedProfileName; return convertedProfileName;
} }

View file

@ -11,6 +11,7 @@ import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.widget.Button; import android.widget.Button;
import android.widget.RadioButton; import android.widget.RadioButton;
import android.widget.TextView;
import com.crashlytics.android.Crashlytics; import com.crashlytics.android.Crashlytics;
import com.squareup.otto.Subscribe; import com.squareup.otto.Subscribe;
@ -22,12 +23,15 @@ import java.text.DecimalFormat;
import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.R; import info.nightscout.androidaps.R;
import info.nightscout.androidaps.data.Profile;
import info.nightscout.androidaps.data.ProfileStore;
import info.nightscout.androidaps.events.EventInitializationChanged; import info.nightscout.androidaps.events.EventInitializationChanged;
import info.nightscout.androidaps.interfaces.PumpInterface; import info.nightscout.androidaps.interfaces.PumpDescription;
import info.nightscout.androidaps.plugins.Careportal.CareportalFragment; import info.nightscout.androidaps.plugins.Careportal.CareportalFragment;
import info.nightscout.androidaps.plugins.Careportal.Dialogs.NewNSTreatmentDialog; import info.nightscout.androidaps.plugins.Careportal.Dialogs.NewNSTreatmentDialog;
import info.nightscout.androidaps.plugins.Careportal.OptionsToShow; import info.nightscout.androidaps.plugins.Careportal.OptionsToShow;
import info.nightscout.androidaps.plugins.Common.SubscriberFragment; import info.nightscout.androidaps.plugins.Common.SubscriberFragment;
import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin;
import info.nightscout.utils.DecimalFormatter; import info.nightscout.utils.DecimalFormatter;
import info.nightscout.utils.NumberPicker; import info.nightscout.utils.NumberPicker;
import info.nightscout.utils.SafeParse; import info.nightscout.utils.SafeParse;
@ -36,12 +40,6 @@ import info.nightscout.utils.TimeListEdit;
public class LocalProfileFragment extends SubscriberFragment { public class LocalProfileFragment extends SubscriberFragment {
private static Logger log = LoggerFactory.getLogger(LocalProfileFragment.class); private static Logger log = LoggerFactory.getLogger(LocalProfileFragment.class);
private static LocalProfilePlugin localProfilePlugin = new LocalProfilePlugin();
public static LocalProfilePlugin getPlugin() {
return localProfilePlugin;
}
NumberPicker diaView; NumberPicker diaView;
RadioButton mgdlView; RadioButton mgdlView;
RadioButton mmolView; RadioButton mmolView;
@ -50,6 +48,7 @@ public class LocalProfileFragment extends SubscriberFragment {
TimeListEdit basalView; TimeListEdit basalView;
TimeListEdit targetView; TimeListEdit targetView;
Button profileswitchButton; Button profileswitchButton;
TextView invalidProfile;
@Override @Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, public View onCreateView(LayoutInflater inflater, ViewGroup container,
@ -58,10 +57,11 @@ public class LocalProfileFragment extends SubscriberFragment {
Runnable save = new Runnable() { Runnable save = new Runnable() {
@Override @Override
public void run() { public void run() {
localProfilePlugin.storeSettings(); LocalProfilePlugin.getPlugin().storeSettings();
if(basalView!=null){ if (basalView != null) {
basalView.updateLabel(MainApp.sResources.getString(R.string.nsprofileview_basal_label)+ ": "+ getSumLabel()); basalView.updateLabel(MainApp.sResources.getString(R.string.nsprofileview_basal_label) + ": " + getSumLabel());
} }
updateGUI();
} }
}; };
@ -79,48 +79,49 @@ public class LocalProfileFragment extends SubscriberFragment {
@Override @Override
public void onTextChanged(CharSequence s, int start, public void onTextChanged(CharSequence s, int start,
int before, int count) { int before, int count) {
localProfilePlugin.dia = SafeParse.stringToDouble(diaView.getText().toString()); LocalProfilePlugin.getPlugin().dia = SafeParse.stringToDouble(diaView.getText().toString());
localProfilePlugin.storeSettings(); LocalProfilePlugin.getPlugin().storeSettings();
updateGUI();
} }
}; };
PumpDescription pumpDescription = ConfigBuilderPlugin.getActivePump().getPumpDescription();
View layout = inflater.inflate(R.layout.localprofile_fragment, container, false); View layout = inflater.inflate(R.layout.localprofile_fragment, container, false);
diaView = (NumberPicker) layout.findViewById(R.id.localprofile_dia); diaView = (NumberPicker) layout.findViewById(R.id.localprofile_dia);
diaView.setParams(localProfilePlugin.dia, 2d, 48d, 0.1d, new DecimalFormat("0.0"), false, textWatch); diaView.setParams(LocalProfilePlugin.getPlugin().dia, 2d, 48d, 0.1d, new DecimalFormat("0.0"), false, textWatch);
mgdlView = (RadioButton) layout.findViewById(R.id.localprofile_mgdl); mgdlView = (RadioButton) layout.findViewById(R.id.localprofile_mgdl);
mmolView = (RadioButton) layout.findViewById(R.id.localprofile_mmol); mmolView = (RadioButton) layout.findViewById(R.id.localprofile_mmol);
icView = new TimeListEdit(getContext(), layout, R.id.localprofile_ic, MainApp.sResources.getString(R.string.nsprofileview_ic_label) + ":", getPlugin().ic, null, 0.1d, new DecimalFormat("0.0"), save); icView = new TimeListEdit(getContext(), layout, R.id.localprofile_ic, MainApp.sResources.getString(R.string.nsprofileview_ic_label) + ":", LocalProfilePlugin.getPlugin().ic, null, 0.5, 50d, 0.1d, new DecimalFormat("0.0"), save);
isfView = new TimeListEdit(getContext(), layout, R.id.localprofile_isf, MainApp.sResources.getString(R.string.nsprofileview_isf_label) + ":", getPlugin().isf, null, 0.1d, new DecimalFormat("0.0"), save); isfView = new TimeListEdit(getContext(), layout, R.id.localprofile_isf, MainApp.sResources.getString(R.string.nsprofileview_isf_label) + ":", LocalProfilePlugin.getPlugin().isf, null, 0.5, 500d, 0.1d, new DecimalFormat("0.0"), save);
basalView = new TimeListEdit(getContext(), layout, R.id.localprofile_basal, MainApp.sResources.getString(R.string.nsprofileview_basal_label)+ ": " + getSumLabel(), getPlugin().basal, null, 0.01d, new DecimalFormat("0.00"), save); basalView = new TimeListEdit(getContext(), layout, R.id.localprofile_basal, MainApp.sResources.getString(R.string.nsprofileview_basal_label) + ": " + getSumLabel(), LocalProfilePlugin.getPlugin().basal, null, pumpDescription.basalMinimumRate, 10, 0.01d, new DecimalFormat("0.00"), save);
targetView = new TimeListEdit(getContext(), layout, R.id.localprofile_target, MainApp.sResources.getString(R.string.nsprofileview_target_label)+ ":", getPlugin().targetLow, getPlugin().targetHigh, 0.1d, new DecimalFormat("0.0"), save); targetView = new TimeListEdit(getContext(), layout, R.id.localprofile_target, MainApp.sResources.getString(R.string.nsprofileview_target_label) + ":", LocalProfilePlugin.getPlugin().targetLow, LocalProfilePlugin.getPlugin().targetHigh, 3d, 200, 0.1d, new DecimalFormat("0.0"), save);
profileswitchButton = (Button) layout.findViewById(R.id.localprofile_profileswitch); profileswitchButton = (Button) layout.findViewById(R.id.localprofile_profileswitch);
invalidProfile = (TextView) layout.findViewById(R.id.invalidprofile);
PumpInterface pump = MainApp.getConfigBuilder(); if (!ConfigBuilderPlugin.getActivePump().getPumpDescription().isTempBasalCapable) {
if (!pump.getPumpDescription().isTempBasalCapable) {
layout.findViewById(R.id.localprofile_basal).setVisibility(View.GONE); layout.findViewById(R.id.localprofile_basal).setVisibility(View.GONE);
} }
updateGUI(); mgdlView.setChecked(LocalProfilePlugin.getPlugin().mgdl);
mmolView.setChecked(LocalProfilePlugin.getPlugin().mmol);
mgdlView.setChecked(localProfilePlugin.mgdl);
mmolView.setChecked(localProfilePlugin.mmol);
mgdlView.setOnClickListener(new View.OnClickListener() { mgdlView.setOnClickListener(new View.OnClickListener() {
@Override @Override
public void onClick(View v) { public void onClick(View v) {
localProfilePlugin.mgdl = mgdlView.isChecked(); LocalProfilePlugin.getPlugin().mgdl = mgdlView.isChecked();
localProfilePlugin.mmol = !localProfilePlugin.mgdl; LocalProfilePlugin.getPlugin().mmol = !LocalProfilePlugin.getPlugin().mgdl;
mmolView.setChecked(localProfilePlugin.mmol); mmolView.setChecked(LocalProfilePlugin.getPlugin().mmol);
localProfilePlugin.storeSettings(); LocalProfilePlugin.getPlugin().storeSettings();
} }
}); });
mmolView.setOnClickListener(new View.OnClickListener() { mmolView.setOnClickListener(new View.OnClickListener() {
@Override @Override
public void onClick(View v) { public void onClick(View v) {
localProfilePlugin.mmol = mmolView.isChecked(); LocalProfilePlugin.getPlugin().mmol = mmolView.isChecked();
localProfilePlugin.mgdl = !localProfilePlugin.mmol; LocalProfilePlugin.getPlugin().mgdl = !LocalProfilePlugin.getPlugin().mmol;
mgdlView.setChecked(localProfilePlugin.mgdl); mgdlView.setChecked(LocalProfilePlugin.getPlugin().mgdl);
localProfilePlugin.storeSettings(); LocalProfilePlugin.getPlugin().storeSettings();
} }
}); });
@ -136,7 +137,6 @@ public class LocalProfileFragment extends SubscriberFragment {
}); });
updateGUI();
return layout; return layout;
} catch (Exception e) { } catch (Exception e) {
log.error("Unhandled exception: ", e); log.error("Unhandled exception: ", e);
@ -148,7 +148,11 @@ public class LocalProfileFragment extends SubscriberFragment {
@NonNull @NonNull
public String getSumLabel() { public String getSumLabel() {
return "" + DecimalFormatter.to2Decimal(localProfilePlugin.getProfile().getDefaultProfile().baseBasalSum()) +"U"; ProfileStore profile = LocalProfilePlugin.getPlugin().getProfile();
if (profile != null)
return "" + DecimalFormatter.to2Decimal(profile.getDefaultProfile().baseBasalSum()) + "U";
else
return MainApp.gs(R.string.localprofile);
} }
@Subscribe @Subscribe
@ -163,11 +167,16 @@ public class LocalProfileFragment extends SubscriberFragment {
activity.runOnUiThread(new Runnable() { activity.runOnUiThread(new Runnable() {
@Override @Override
public void run() { public void run() {
if (!MainApp.getConfigBuilder().isInitialized() || MainApp.getConfigBuilder().isSuspended()) { boolean isValid = LocalProfilePlugin.getPlugin().getProfile() != null && LocalProfilePlugin.getPlugin().getProfile().getDefaultProfile().isValid(MainApp.gs(R.string.localprofile));
if (!ConfigBuilderPlugin.getActivePump().isInitialized() || ConfigBuilderPlugin.getActivePump().isSuspended() || !isValid) {
profileswitchButton.setVisibility(View.GONE); profileswitchButton.setVisibility(View.GONE);
} else { } else {
profileswitchButton.setVisibility(View.VISIBLE); profileswitchButton.setVisibility(View.VISIBLE);
} }
if (isValid)
invalidProfile.setVisibility(View.GONE);
else
invalidProfile.setVisibility(View.VISIBLE);
} }
}); });
} }

View file

@ -13,9 +13,9 @@ import info.nightscout.androidaps.Config;
import info.nightscout.androidaps.Constants; import info.nightscout.androidaps.Constants;
import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.R; import info.nightscout.androidaps.R;
import info.nightscout.androidaps.data.ProfileStore;
import info.nightscout.androidaps.interfaces.PluginBase; import info.nightscout.androidaps.interfaces.PluginBase;
import info.nightscout.androidaps.interfaces.ProfileInterface; import info.nightscout.androidaps.interfaces.ProfileInterface;
import info.nightscout.androidaps.data.ProfileStore;
import info.nightscout.utils.DecimalFormatter; import info.nightscout.utils.DecimalFormatter;
import info.nightscout.utils.SP; import info.nightscout.utils.SP;
@ -26,6 +26,14 @@ public class LocalProfilePlugin implements PluginBase, ProfileInterface {
public static final String LOCAL_PROFILE = "LocalProfile"; public static final String LOCAL_PROFILE = "LocalProfile";
private static Logger log = LoggerFactory.getLogger(LocalProfilePlugin.class); private static Logger log = LoggerFactory.getLogger(LocalProfilePlugin.class);
private static LocalProfilePlugin localProfilePlugin;
public static LocalProfilePlugin getPlugin() {
if (localProfilePlugin == null)
localProfilePlugin = new LocalProfilePlugin();
return localProfilePlugin;
}
private boolean fragmentEnabled = false; private boolean fragmentEnabled = false;
private boolean fragmentVisible = false; private boolean fragmentVisible = false;
@ -128,7 +136,7 @@ public class LocalProfilePlugin implements PluginBase, ProfileInterface {
editor.apply(); editor.apply();
createConvertedProfile(); createConvertedProfile();
if (Config.logPrefsChange) if (Config.logPrefsChange)
log.debug("Storing settings: " + getProfile().getData().toString()); log.debug("Storing settings: " + getRawProfile().getData().toString());
} }
public void loadSettings() { public void loadSettings() {
@ -178,7 +186,6 @@ public class LocalProfilePlugin implements PluginBase, ProfileInterface {
} catch (JSONException ignored) { } catch (JSONException ignored) {
} }
} }
createConvertedProfile();
} }
/* /*
@ -244,6 +251,16 @@ public class LocalProfilePlugin implements PluginBase, ProfileInterface {
@Override @Override
public ProfileStore getProfile() { public ProfileStore getProfile() {
if (convertedProfile == null)
createConvertedProfile();
if (!convertedProfile.getDefaultProfile().isValid(MainApp.gs(R.string.localprofile)))
return null;
return convertedProfile;
}
public ProfileStore getRawProfile() {
if (convertedProfile == null)
createConvertedProfile();
return convertedProfile; return convertedProfile;
} }
@ -254,6 +271,8 @@ public class LocalProfilePlugin implements PluginBase, ProfileInterface {
@Override @Override
public String getProfileName() { public String getProfileName() {
if (convertedProfile == null)
createConvertedProfile();
return DecimalFormatter.to2Decimal(convertedProfile.getDefaultProfile().percentageBasalSum()) + "U "; return DecimalFormatter.to2Decimal(convertedProfile.getDefaultProfile().percentageBasalSum()) + "U ";
} }

View file

@ -84,30 +84,36 @@ public class NSProfileFragment extends SubscriberFragment implements AdapterView
} }
ProfileStore profileStore = NSProfilePlugin.getPlugin().getProfile(); ProfileStore profileStore = NSProfilePlugin.getPlugin().getProfile();
ArrayList<CharSequence> profileList = profileStore.getProfileList(); if (profileStore != null) {
ArrayAdapter<CharSequence> adapter = new ArrayAdapter<>(getContext(), ArrayList<CharSequence> profileList = profileStore.getProfileList();
R.layout.spinner_centered, profileList); ArrayAdapter<CharSequence> adapter = new ArrayAdapter<>(getContext(),
profileSpinner.setAdapter(adapter); R.layout.spinner_centered, profileList);
// set selected to actual profile profileSpinner.setAdapter(adapter);
for (int p = 0; p < profileList.size(); p++) { // set selected to actual profile
if (profileList.get(p).equals(MainApp.getConfigBuilder().getProfileName())) for (int p = 0; p < profileList.size(); p++) {
profileSpinner.setSelection(p); if (profileList.get(p).equals(MainApp.getConfigBuilder().getProfileName()))
profileSpinner.setSelection(p);
}
} }
} }
@Override @Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) { public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
String name = parent.getItemAtPosition(position).toString(); String name = parent.getItemAtPosition(position).toString();
Profile profile = NSProfilePlugin.getPlugin().getProfile().getSpecificProfile(name); ProfileStore store = NSProfilePlugin.getPlugin().getProfile();
units.setText(profile.getUnits()); if (store != null) {
dia.setText(DecimalFormatter.to2Decimal(profile.getDia()) + " h"); Profile profile = store.getSpecificProfile(name);
activeProfile.setText(name); if (profile != null) {
ic.setText(profile.getIcList()); units.setText(profile.getUnits());
isf.setText(profile.getIsfList()); dia.setText(DecimalFormatter.to2Decimal(profile.getDia()) + " h");
basal.setText(profile.getBasalList()); activeProfile.setText(name);
target.setText(profile.getTargetList()); ic.setText(profile.getIcList());
isf.setText(profile.getIsfList());
basal.setText(profile.getBasalList());
target.setText(profile.getTargetList());
}
}
} }
@Override @Override

View file

@ -18,9 +18,10 @@ import info.nightscout.androidaps.Services.Intents;
import info.nightscout.androidaps.data.ProfileStore; import info.nightscout.androidaps.data.ProfileStore;
import info.nightscout.androidaps.interfaces.PluginBase; import info.nightscout.androidaps.interfaces.PluginBase;
import info.nightscout.androidaps.interfaces.ProfileInterface; import info.nightscout.androidaps.interfaces.ProfileInterface;
import info.nightscout.androidaps.interfaces.PumpInterface; import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin;
import info.nightscout.androidaps.plugins.ProfileNS.events.EventNSProfileUpdateGUI; import info.nightscout.androidaps.plugins.ProfileNS.events.EventNSProfileUpdateGUI;
import info.nightscout.androidaps.plugins.SmsCommunicator.SmsCommunicatorPlugin; import info.nightscout.androidaps.plugins.SmsCommunicator.SmsCommunicatorPlugin;
import info.nightscout.androidaps.queue.Callback;
import info.nightscout.utils.SP; import info.nightscout.utils.SP;
/** /**
@ -71,12 +72,12 @@ public class NSProfilePlugin implements PluginBase, ProfileInterface {
@Override @Override
public boolean isEnabled(int type) { public boolean isEnabled(int type) {
return type == PROFILE && (Config.NSCLIENT || fragmentEnabled); return type == PROFILE && (Config.NSCLIENT || Config.G5UPLOADER|| fragmentEnabled);
} }
@Override @Override
public boolean isVisibleInTabs(int type) { public boolean isVisibleInTabs(int type) {
return type == PROFILE && (Config.NSCLIENT ||fragmentVisible); return type == PROFILE && (Config.NSCLIENT || Config.G5UPLOADER|| fragmentVisible);
} }
@Override @Override
@ -91,7 +92,7 @@ public class NSProfilePlugin implements PluginBase, ProfileInterface {
@Override @Override
public boolean showInList(int type) { public boolean showInList(int type) {
return !Config.NSCLIENT; return !Config.NSCLIENT && !Config.G5UPLOADER;
} }
@Override @Override
@ -119,16 +120,17 @@ public class NSProfilePlugin implements PluginBase, ProfileInterface {
profile = new ProfileStore(newProfile.getData()); profile = new ProfileStore(newProfile.getData());
storeNSProfile(); storeNSProfile();
MainApp.bus().post(new EventNSProfileUpdateGUI()); MainApp.bus().post(new EventNSProfileUpdateGUI());
PumpInterface pump = MainApp.getConfigBuilder(); ConfigBuilderPlugin.getCommandQueue().setProfile(MainApp.getConfigBuilder().getProfile(), new Callback() {
if (SP.getBoolean("syncprofiletopump", false)) { @Override
if (pump.setNewBasalProfile(MainApp.getConfigBuilder().getProfile()) == PumpInterface.SUCCESS) { public void run() {
SmsCommunicatorPlugin smsCommunicatorPlugin = MainApp.getSpecificPlugin(SmsCommunicatorPlugin.class); if (result.enacted) {
if (smsCommunicatorPlugin != null && smsCommunicatorPlugin.isEnabled(PluginBase.GENERAL)) { SmsCommunicatorPlugin smsCommunicatorPlugin = MainApp.getSpecificPlugin(SmsCommunicatorPlugin.class);
smsCommunicatorPlugin.sendNotificationToAllNumbers(MainApp.sResources.getString(R.string.profile_set_ok)); if (smsCommunicatorPlugin != null && smsCommunicatorPlugin.isEnabled(PluginBase.GENERAL)) {
smsCommunicatorPlugin.sendNotificationToAllNumbers(MainApp.sResources.getString(R.string.profile_set_ok));
}
} }
} }
} });
} }
private static void storeNSProfile() { private static void storeNSProfile() {

View file

@ -11,6 +11,7 @@ import android.view.ViewGroup;
import android.widget.Button; import android.widget.Button;
import android.widget.EditText; import android.widget.EditText;
import android.widget.RadioButton; import android.widget.RadioButton;
import android.widget.TextView;
import com.crashlytics.android.Crashlytics; import com.crashlytics.android.Crashlytics;
import com.squareup.otto.Subscribe; import com.squareup.otto.Subscribe;
@ -21,11 +22,11 @@ import org.slf4j.LoggerFactory;
import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.R; import info.nightscout.androidaps.R;
import info.nightscout.androidaps.events.EventInitializationChanged; import info.nightscout.androidaps.events.EventInitializationChanged;
import info.nightscout.androidaps.interfaces.PumpInterface;
import info.nightscout.androidaps.plugins.Careportal.CareportalFragment; import info.nightscout.androidaps.plugins.Careportal.CareportalFragment;
import info.nightscout.androidaps.plugins.Careportal.Dialogs.NewNSTreatmentDialog; import info.nightscout.androidaps.plugins.Careportal.Dialogs.NewNSTreatmentDialog;
import info.nightscout.androidaps.plugins.Careportal.OptionsToShow; import info.nightscout.androidaps.plugins.Careportal.OptionsToShow;
import info.nightscout.androidaps.plugins.Common.SubscriberFragment; import info.nightscout.androidaps.plugins.Common.SubscriberFragment;
import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin;
import info.nightscout.utils.SafeParse; import info.nightscout.utils.SafeParse;
public class SimpleProfileFragment extends SubscriberFragment { public class SimpleProfileFragment extends SubscriberFragment {
@ -40,6 +41,7 @@ public class SimpleProfileFragment extends SubscriberFragment {
EditText targetlowView; EditText targetlowView;
EditText targethighView; EditText targethighView;
Button profileswitchButton; Button profileswitchButton;
TextView invalidProfile;
@Override @Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, public View onCreateView(LayoutInflater inflater, ViewGroup container,
@ -55,15 +57,13 @@ public class SimpleProfileFragment extends SubscriberFragment {
targetlowView = (EditText) layout.findViewById(R.id.simpleprofile_targetlow); targetlowView = (EditText) layout.findViewById(R.id.simpleprofile_targetlow);
targethighView = (EditText) layout.findViewById(R.id.simpleprofile_targethigh); targethighView = (EditText) layout.findViewById(R.id.simpleprofile_targethigh);
profileswitchButton = (Button) layout.findViewById(R.id.simpleprofile_profileswitch); profileswitchButton = (Button) layout.findViewById(R.id.simpleprofile_profileswitch);
invalidProfile = (TextView) layout.findViewById(R.id.invalidprofile);
PumpInterface pump = MainApp.getConfigBuilder(); if (!ConfigBuilderPlugin.getActivePump().getPumpDescription().isTempBasalCapable) {
if (!pump.getPumpDescription().isTempBasalCapable) {
layout.findViewById(R.id.simpleprofile_basalrate).setVisibility(View.GONE); layout.findViewById(R.id.simpleprofile_basalrate).setVisibility(View.GONE);
layout.findViewById(R.id.simpleprofile_basalrate_label).setVisibility(View.GONE); layout.findViewById(R.id.simpleprofile_basalrate_label).setVisibility(View.GONE);
} }
updateGUI();
mgdlView.setChecked(SimpleProfilePlugin.getPlugin().mgdl); mgdlView.setChecked(SimpleProfilePlugin.getPlugin().mgdl);
mmolView.setChecked(SimpleProfilePlugin.getPlugin().mmol); mmolView.setChecked(SimpleProfilePlugin.getPlugin().mmol);
diaView.setText(SimpleProfilePlugin.getPlugin().dia.toString()); diaView.setText(SimpleProfilePlugin.getPlugin().dia.toString());
@ -124,6 +124,7 @@ public class SimpleProfileFragment extends SubscriberFragment {
SimpleProfilePlugin.getPlugin().targetLow = SafeParse.stringToDouble(targetlowView.getText().toString()); SimpleProfilePlugin.getPlugin().targetLow = SafeParse.stringToDouble(targetlowView.getText().toString());
SimpleProfilePlugin.getPlugin().targetHigh = SafeParse.stringToDouble(targethighView.getText().toString()); SimpleProfilePlugin.getPlugin().targetHigh = SafeParse.stringToDouble(targethighView.getText().toString());
SimpleProfilePlugin.getPlugin().storeSettings(); SimpleProfilePlugin.getPlugin().storeSettings();
updateGUI();
} }
}; };
@ -134,8 +135,6 @@ public class SimpleProfileFragment extends SubscriberFragment {
targetlowView.addTextChangedListener(textWatch); targetlowView.addTextChangedListener(textWatch);
targethighView.addTextChangedListener(textWatch); targethighView.addTextChangedListener(textWatch);
updateGUI();
return layout; return layout;
} catch (Exception e) { } catch (Exception e) {
Crashlytics.logException(e); Crashlytics.logException(e);
@ -156,11 +155,16 @@ public class SimpleProfileFragment extends SubscriberFragment {
activity.runOnUiThread(new Runnable() { activity.runOnUiThread(new Runnable() {
@Override @Override
public void run() { public void run() {
if (!MainApp.getConfigBuilder().isInitialized() || MainApp.getConfigBuilder().isSuspended()) { boolean isValid = SimpleProfilePlugin.getPlugin().getProfile() != null && SimpleProfilePlugin.getPlugin().getProfile().getDefaultProfile().isValid(MainApp.gs(R.string.simpleprofile));
if (!ConfigBuilderPlugin.getActivePump().isInitialized() || ConfigBuilderPlugin.getActivePump().isSuspended() || !isValid) {
profileswitchButton.setVisibility(View.GONE); profileswitchButton.setVisibility(View.GONE);
} else { } else {
profileswitchButton.setVisibility(View.VISIBLE); profileswitchButton.setVisibility(View.VISIBLE);
} }
if (isValid)
invalidProfile.setVisibility(View.GONE);
else
invalidProfile.setVisibility(View.VISIBLE);
} }
}); });
} }

View file

@ -13,9 +13,9 @@ import info.nightscout.androidaps.Config;
import info.nightscout.androidaps.Constants; import info.nightscout.androidaps.Constants;
import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.R; import info.nightscout.androidaps.R;
import info.nightscout.androidaps.data.ProfileStore;
import info.nightscout.androidaps.interfaces.PluginBase; import info.nightscout.androidaps.interfaces.PluginBase;
import info.nightscout.androidaps.interfaces.ProfileInterface; import info.nightscout.androidaps.interfaces.ProfileInterface;
import info.nightscout.androidaps.data.ProfileStore;
import info.nightscout.utils.SP; import info.nightscout.utils.SP;
/** /**
@ -28,7 +28,7 @@ public class SimpleProfilePlugin implements PluginBase, ProfileInterface {
public static SimpleProfilePlugin getPlugin() { public static SimpleProfilePlugin getPlugin() {
if (simpleProfilePlugin == null) if (simpleProfilePlugin == null)
simpleProfilePlugin = new SimpleProfilePlugin(); simpleProfilePlugin = new SimpleProfilePlugin();
return simpleProfilePlugin; return simpleProfilePlugin;
} }
@ -132,6 +132,8 @@ public class SimpleProfilePlugin implements PluginBase, ProfileInterface {
editor.apply(); editor.apply();
createConvertedProfile(); createConvertedProfile();
if (Config.logPrefsChange)
log.debug("Storing settings: " + getRawProfile().getData().toString());
} }
private void loadSettings() { private void loadSettings() {
@ -141,12 +143,11 @@ public class SimpleProfilePlugin implements PluginBase, ProfileInterface {
mgdl = SP.getBoolean("SimpleProfile" + "mgdl", true); mgdl = SP.getBoolean("SimpleProfile" + "mgdl", true);
mmol = SP.getBoolean("SimpleProfile" + "mmol", false); mmol = SP.getBoolean("SimpleProfile" + "mmol", false);
dia = SP.getDouble("SimpleProfile" + "dia", Constants.defaultDIA); dia = SP.getDouble("SimpleProfile" + "dia", Constants.defaultDIA);
ic = SP.getDouble("SimpleProfile" + "ic", 20d); ic = SP.getDouble("SimpleProfile" + "ic", 0d);
isf = SP.getDouble("SimpleProfile" + "isf", 200d); isf = SP.getDouble("SimpleProfile" + "isf", 0d);
basal = SP.getDouble("SimpleProfile" + "basal", 1d); basal = SP.getDouble("SimpleProfile" + "basal", 0d);
targetLow = SP.getDouble("SimpleProfile" + "targetlow", 80d); targetLow = SP.getDouble("SimpleProfile" + "targetlow", 0d);
targetHigh = SP.getDouble("SimpleProfile" + "targethigh", 120d); targetHigh = SP.getDouble("SimpleProfile" + "targethigh", 0d);
createConvertedProfile();
} }
/* /*
@ -211,6 +212,16 @@ public class SimpleProfilePlugin implements PluginBase, ProfileInterface {
@Override @Override
public ProfileStore getProfile() { public ProfileStore getProfile() {
if (convertedProfile == null)
createConvertedProfile();
if (!convertedProfile.getDefaultProfile().isValid(MainApp.gs(R.string.simpleprofile)))
return null;
return convertedProfile;
}
public ProfileStore getRawProfile() {
if (convertedProfile == null)
createConvertedProfile();
return convertedProfile; return convertedProfile;
} }

View file

@ -0,0 +1,557 @@
package info.nightscout.androidaps.plugins.PumpDanaR;
import android.support.annotation.Nullable;
import org.json.JSONException;
import org.json.JSONObject;
import org.slf4j.Logger;
import java.util.Date;
import java.util.Objects;
import info.nightscout.androidaps.BuildConfig;
import info.nightscout.androidaps.Config;
import info.nightscout.androidaps.Constants;
import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.R;
import info.nightscout.androidaps.data.Profile;
import info.nightscout.androidaps.data.ProfileStore;
import info.nightscout.androidaps.data.PumpEnactResult;
import info.nightscout.androidaps.db.ExtendedBolus;
import info.nightscout.androidaps.db.TemporaryBasal;
import info.nightscout.androidaps.interfaces.ConstraintsInterface;
import info.nightscout.androidaps.interfaces.DanaRInterface;
import info.nightscout.androidaps.interfaces.PluginBase;
import info.nightscout.androidaps.interfaces.ProfileInterface;
import info.nightscout.androidaps.interfaces.PumpDescription;
import info.nightscout.androidaps.interfaces.PumpInterface;
import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin;
import info.nightscout.androidaps.plugins.Overview.events.EventDismissNotification;
import info.nightscout.androidaps.plugins.Overview.events.EventNewNotification;
import info.nightscout.androidaps.plugins.Overview.notifications.Notification;
import info.nightscout.androidaps.plugins.ProfileNS.NSProfilePlugin;
import info.nightscout.androidaps.plugins.PumpDanaR.services.AbstractDanaRExecutionService;
import info.nightscout.utils.DateUtil;
import info.nightscout.utils.DecimalFormatter;
import info.nightscout.utils.Round;
/**
* Created by mike on 28.01.2018.
*/
public abstract class AbstractDanaRPlugin implements PluginBase, PumpInterface, DanaRInterface, ConstraintsInterface, ProfileInterface {
protected Logger log;
protected boolean mPluginPumpEnabled = false;
protected boolean mPluginProfileEnabled = false;
protected boolean mFragmentPumpVisible = true;
protected AbstractDanaRExecutionService sExecutionService;
protected DanaRPump pump = DanaRPump.getInstance();
protected boolean useExtendedBoluses = false;
public PumpDescription pumpDescription = new PumpDescription();
@Override
public String getFragmentClass() {
return DanaRFragment.class.getName();
}
// Plugin base interface
@Override
public int getType() {
return PluginBase.PUMP;
}
@Override
public String getNameShort() {
String name = MainApp.sResources.getString(R.string.danarpump_shortname);
if (!name.trim().isEmpty()) {
//only if translation exists
return name;
}
// use long name as fallback
return getName();
}
@Override
public boolean isEnabled(int type) {
if (type == PluginBase.PROFILE) return mPluginProfileEnabled && mPluginPumpEnabled;
else if (type == PluginBase.PUMP) return mPluginPumpEnabled;
else if (type == PluginBase.CONSTRAINTS) return mPluginPumpEnabled;
return false;
}
@Override
public boolean isVisibleInTabs(int type) {
if (type == PluginBase.PROFILE || type == PluginBase.CONSTRAINTS) return false;
else if (type == PluginBase.PUMP) return mFragmentPumpVisible;
return false;
}
@Override
public boolean canBeHidden(int type) {
return true;
}
@Override
public boolean hasFragment() {
return true;
}
@Override
public boolean showInList(int type) {
return type == PUMP;
}
@Override
public void setFragmentEnabled(int type, boolean fragmentEnabled) {
if (type == PluginBase.PROFILE)
mPluginProfileEnabled = fragmentEnabled;
else if (type == PluginBase.PUMP)
mPluginPumpEnabled = fragmentEnabled;
// if pump profile was enabled need to switch to another too
if (type == PluginBase.PUMP && !fragmentEnabled && mPluginProfileEnabled) {
setFragmentEnabled(PluginBase.PROFILE, false);
setFragmentVisible(PluginBase.PROFILE, false);
NSProfilePlugin.getPlugin().setFragmentEnabled(PluginBase.PROFILE, true);
NSProfilePlugin.getPlugin().setFragmentVisible(PluginBase.PROFILE, true);
}
}
@Override
public void setFragmentVisible(int type, boolean fragmentVisible) {
if (type == PluginBase.PUMP)
mFragmentPumpVisible = fragmentVisible;
}
@Override
public boolean isSuspended() {
return pump.pumpSuspended;
}
@Override
public boolean isBusy() {
if (sExecutionService == null) return false;
return sExecutionService.isConnected() || sExecutionService.isConnecting();
}
// Pump interface
@Override
public PumpEnactResult setNewBasalProfile(Profile profile) {
PumpEnactResult result = new PumpEnactResult();
if (sExecutionService == null) {
log.error("setNewBasalProfile sExecutionService is null");
result.comment = "setNewBasalProfile sExecutionService is null";
return result;
}
if (!isInitialized()) {
log.error("setNewBasalProfile not initialized");
Notification notification = new Notification(Notification.PROFILE_NOT_SET_NOT_INITIALIZED, MainApp.sResources.getString(R.string.pumpNotInitializedProfileNotSet), Notification.URGENT);
MainApp.bus().post(new EventNewNotification(notification));
result.comment = MainApp.sResources.getString(R.string.pumpNotInitializedProfileNotSet);
return result;
} else {
MainApp.bus().post(new EventDismissNotification(Notification.PROFILE_NOT_SET_NOT_INITIALIZED));
}
if (!sExecutionService.updateBasalsInPump(profile)) {
Notification notification = new Notification(Notification.FAILED_UDPATE_PROFILE, MainApp.sResources.getString(R.string.failedupdatebasalprofile), Notification.URGENT);
MainApp.bus().post(new EventNewNotification(notification));
result.comment = MainApp.sResources.getString(R.string.failedupdatebasalprofile);
return result;
} else {
MainApp.bus().post(new EventDismissNotification(Notification.PROFILE_NOT_SET_NOT_INITIALIZED));
MainApp.bus().post(new EventDismissNotification(Notification.FAILED_UDPATE_PROFILE));
Notification notification = new Notification(Notification.PROFILE_SET_OK, MainApp.sResources.getString(R.string.profile_set_ok), Notification.INFO, 60);
MainApp.bus().post(new EventNewNotification(notification));
result.success = true;
result.enacted = true;
result.comment = "OK";
return result;
}
}
@Override
public boolean isThisProfileSet(Profile profile) {
if (!isInitialized())
return true; // TODO: not sure what's better. so far TRUE to prevent too many SMS
if (pump.pumpProfiles == null)
return true; // TODO: not sure what's better. so far TRUE to prevent too many SMS
int basalValues = pump.basal48Enable ? 48 : 24;
int basalIncrement = pump.basal48Enable ? 30 * 60 : 60 * 60;
for (int h = 0; h < basalValues; h++) {
Double pumpValue = pump.pumpProfiles[pump.activeProfile][h];
Double profileValue = profile.getBasal((Integer) (h * basalIncrement));
if (profileValue == null) return true;
if (Math.abs(pumpValue - profileValue) > getPumpDescription().basalStep) {
log.debug("Diff found. Hour: " + h + " Pump: " + pumpValue + " Profile: " + profileValue);
return false;
}
}
return true;
}
@Override
public Date lastDataTime() {
return new Date(pump.lastConnection);
}
@Override
public double getBaseBasalRate() {
return pump.currentBasal;
}
@Override
public void stopBolusDelivering() {
if (sExecutionService == null) {
log.error("stopBolusDelivering sExecutionService is null");
return;
}
sExecutionService.bolusStop();
}
@Override
public PumpEnactResult setTempBasalPercent(Integer percent, Integer durationInMinutes, boolean enforceNew) {
PumpEnactResult result = new PumpEnactResult();
ConfigBuilderPlugin configBuilderPlugin = MainApp.getConfigBuilder();
percent = configBuilderPlugin.applyBasalConstraints(percent);
if (percent < 0) {
result.isTempCancel = false;
result.enacted = false;
result.success = false;
result.comment = MainApp.instance().getString(R.string.danar_invalidinput);
log.error("setTempBasalPercent: Invalid input");
return result;
}
if (percent > getPumpDescription().maxTempPercent)
percent = getPumpDescription().maxTempPercent;
TemporaryBasal runningTB = MainApp.getConfigBuilder().getRealTempBasalFromHistory(System.currentTimeMillis());
if (runningTB != null && runningTB.percentRate == percent && !enforceNew) {
result.enacted = false;
result.success = true;
result.isTempCancel = false;
result.comment = MainApp.instance().getString(R.string.virtualpump_resultok);
result.duration = pump.tempBasalRemainingMin;
result.percent = pump.tempBasalPercent;
result.absolute = MainApp.getConfigBuilder().getTempBasalAbsoluteRateHistory();
result.isPercent = true;
if (Config.logPumpActions)
log.debug("setTempBasalPercent: Correct value already set");
return result;
}
int durationInHours = Math.max(durationInMinutes / 60, 1);
boolean connectionOK = sExecutionService.tempBasal(percent, durationInHours);
if (connectionOK && pump.isTempBasalInProgress && pump.tempBasalPercent == percent) {
result.enacted = true;
result.success = true;
result.comment = MainApp.instance().getString(R.string.virtualpump_resultok);
result.isTempCancel = false;
result.duration = pump.tempBasalRemainingMin;
result.percent = pump.tempBasalPercent;
result.absolute = MainApp.getConfigBuilder().getTempBasalAbsoluteRateHistory();
result.isPercent = true;
if (Config.logPumpActions)
log.debug("setTempBasalPercent: OK");
return result;
}
result.enacted = false;
result.success = false;
result.comment = MainApp.instance().getString(R.string.tempbasaldeliveryerror);
log.error("setTempBasalPercent: Failed to set temp basal");
return result;
}
@Override
public PumpEnactResult setExtendedBolus(Double insulin, Integer durationInMinutes) {
ConfigBuilderPlugin configBuilderPlugin = MainApp.getConfigBuilder();
insulin = configBuilderPlugin.applyBolusConstraints(insulin);
// needs to be rounded
int durationInHalfHours = Math.max(durationInMinutes / 30, 1);
insulin = Round.roundTo(insulin, getPumpDescription().extendedBolusStep);
PumpEnactResult result = new PumpEnactResult();
ExtendedBolus runningEB = MainApp.getConfigBuilder().getExtendedBolusFromHistory(System.currentTimeMillis());
if (runningEB != null && Math.abs(runningEB.insulin - insulin) < getPumpDescription().extendedBolusStep) {
result.enacted = false;
result.success = true;
result.comment = MainApp.instance().getString(R.string.virtualpump_resultok);
result.duration = pump.extendedBolusRemainingMinutes;
result.absolute = pump.extendedBolusAbsoluteRate;
result.isPercent = false;
result.isTempCancel = false;
if (Config.logPumpActions)
log.debug("setExtendedBolus: Correct extended bolus already set. Current: " + pump.extendedBolusAmount + " Asked: " + insulin);
return result;
}
boolean connectionOK = sExecutionService.extendedBolus(insulin, durationInHalfHours);
if (connectionOK && pump.isExtendedInProgress && Math.abs(pump.extendedBolusAmount - insulin) < getPumpDescription().extendedBolusStep) {
result.enacted = true;
result.success = true;
result.comment = MainApp.instance().getString(R.string.virtualpump_resultok);
result.isTempCancel = false;
result.duration = pump.extendedBolusRemainingMinutes;
result.absolute = pump.extendedBolusAbsoluteRate;
result.bolusDelivered = pump.extendedBolusAmount;
result.isPercent = false;
if (Config.logPumpActions)
log.debug("setExtendedBolus: OK");
return result;
}
result.enacted = false;
result.success = false;
result.comment = MainApp.instance().getString(R.string.danar_valuenotsetproperly);
log.error("setExtendedBolus: Failed to extended bolus");
return result;
}
@Override
public PumpEnactResult cancelExtendedBolus() {
PumpEnactResult result = new PumpEnactResult();
ExtendedBolus runningEB = MainApp.getConfigBuilder().getExtendedBolusFromHistory(System.currentTimeMillis());
if (runningEB != null) {
sExecutionService.extendedBolusStop();
result.enacted = true;
result.isTempCancel = true;
}
if (!pump.isExtendedInProgress) {
result.success = true;
result.comment = MainApp.instance().getString(R.string.virtualpump_resultok);
if (Config.logPumpActions)
log.debug("cancelExtendedBolus: OK");
return result;
} else {
result.success = false;
result.comment = MainApp.instance().getString(R.string.danar_valuenotsetproperly);
log.error("cancelExtendedBolus: Failed to cancel extended bolus");
return result;
}
}
@Override
public void connect(String from) {
if (sExecutionService != null) {
sExecutionService.connect();
pumpDescription.basalStep = pump.basalStep;
pumpDescription.bolusStep = pump.bolusStep;
}
}
@Override
public boolean isConnected() {
return sExecutionService != null && sExecutionService.isConnected();
}
@Override
public boolean isConnecting() {
return sExecutionService != null && sExecutionService.isConnecting();
}
@Override
public void disconnect(String from) {
if (sExecutionService != null) sExecutionService.disconnect(from);
}
@Override
public void stopConnecting() {
if (sExecutionService != null) sExecutionService.stopConnecting();
}
@Override
public void getPumpStatus() {
if (sExecutionService != null) sExecutionService.getPumpStatus();
}
@Override
public JSONObject getJSONStatus() {
if (pump.lastConnection + 5 * 60 * 1000L < System.currentTimeMillis()) {
return null;
}
JSONObject pumpjson = new JSONObject();
JSONObject battery = new JSONObject();
JSONObject status = new JSONObject();
JSONObject extended = new JSONObject();
try {
battery.put("percent", pump.batteryRemaining);
status.put("status", pump.pumpSuspended ? "suspended" : "normal");
status.put("timestamp", DateUtil.toISOString(pump.lastConnection));
extended.put("Version", BuildConfig.VERSION_NAME + "-" + BuildConfig.BUILDVERSION);
extended.put("PumpIOB", pump.iob);
if (pump.lastBolusTime.getTime() != 0) {
extended.put("LastBolus", pump.lastBolusTime.toLocaleString());
extended.put("LastBolusAmount", pump.lastBolusAmount);
}
TemporaryBasal tb = MainApp.getConfigBuilder().getRealTempBasalFromHistory(System.currentTimeMillis());
if (tb != null) {
extended.put("TempBasalAbsoluteRate", tb.tempBasalConvertedToAbsolute(System.currentTimeMillis()));
extended.put("TempBasalStart", DateUtil.dateAndTimeString(tb.date));
extended.put("TempBasalRemaining", tb.getPlannedRemainingMinutes());
}
ExtendedBolus eb = MainApp.getConfigBuilder().getExtendedBolusFromHistory(System.currentTimeMillis());
if (eb != null) {
extended.put("ExtendedBolusAbsoluteRate", eb.absoluteRate());
extended.put("ExtendedBolusStart", DateUtil.dateAndTimeString(eb.date));
extended.put("ExtendedBolusRemaining", eb.getPlannedRemainingMinutes());
}
extended.put("BaseBasalRate", getBaseBasalRate());
try {
extended.put("ActiveProfile", MainApp.getConfigBuilder().getProfileName());
} catch (Exception e) {
}
pumpjson.put("battery", battery);
pumpjson.put("status", status);
pumpjson.put("extended", extended);
pumpjson.put("reservoir", (int) pump.reservoirRemainingUnits);
pumpjson.put("clock", DateUtil.toISOString(new Date()));
} catch (JSONException e) {
log.error("Unhandled exception", e);
}
return pumpjson;
}
@Override
public String deviceID() {
return pump.serialNumber;
}
@Override
public PumpDescription getPumpDescription() {
return pumpDescription;
}
/**
* DanaR interface
*/
@Override
public PumpEnactResult loadHistory(byte type) {
return sExecutionService.loadHistory(type);
}
/**
* Constraint interface
*/
@Override
public boolean isLoopEnabled() {
return true;
}
@Override
public boolean isClosedModeEnabled() {
return true;
}
@Override
public boolean isAutosensModeEnabled() {
return true;
}
@Override
public boolean isAMAModeEnabled() {
return true;
}
@Override
public boolean isSMBModeEnabled() {
return true;
}
@SuppressWarnings("PointlessBooleanExpression")
@Override
public Double applyBasalConstraints(Double absoluteRate) {
double origAbsoluteRate = absoluteRate;
if (pump != null) {
if (absoluteRate > pump.maxBasal) {
absoluteRate = pump.maxBasal;
if (Config.logConstraintsChanges && origAbsoluteRate != Constants.basalAbsoluteOnlyForCheckLimit)
log.debug("Limiting rate " + origAbsoluteRate + "U/h by pump constraint to " + absoluteRate + "U/h");
}
}
return absoluteRate;
}
@SuppressWarnings("PointlessBooleanExpression")
@Override
public Integer applyBasalConstraints(Integer percentRate) {
Integer origPercentRate = percentRate;
if (percentRate < 0) percentRate = 0;
if (percentRate > getPumpDescription().maxTempPercent)
percentRate = getPumpDescription().maxTempPercent;
if (!Objects.equals(percentRate, origPercentRate) && Config.logConstraintsChanges && !Objects.equals(origPercentRate, Constants.basalPercentOnlyForCheckLimit))
log.debug("Limiting percent rate " + origPercentRate + "% to " + percentRate + "%");
return percentRate;
}
@SuppressWarnings("PointlessBooleanExpression")
@Override
public Double applyBolusConstraints(Double insulin) {
double origInsulin = insulin;
if (pump != null) {
if (insulin > pump.maxBolus) {
insulin = pump.maxBolus;
if (Config.logConstraintsChanges && origInsulin != Constants.bolusOnlyForCheckLimit)
log.debug("Limiting bolus " + origInsulin + "U by pump constraint to " + insulin + "U");
}
}
return insulin;
}
@Override
public Integer applyCarbsConstraints(Integer carbs) {
return carbs;
}
@Override
public Double applyMaxIOBConstraints(Double maxIob) {
return maxIob;
}
@Nullable
@Override
public ProfileStore getProfile() {
if (pump.lastSettingsRead == 0)
return null; // no info now
return pump.createConvertedProfile();
}
@Override
public String getUnits() {
return pump.getUnits();
}
@Override
public String getProfileName() {
return pump.createConvertedProfileName();
}
// Reply for sms communicator
public String shortStatus(boolean veryShort) {
String ret = "";
if (pump.lastConnection != 0) {
Long agoMsec = System.currentTimeMillis() - pump.lastConnection;
int agoMin = (int) (agoMsec / 60d / 1000d);
ret += "LastConn: " + agoMin + " minago\n";
}
if (pump.lastBolusTime.getTime() != 0) {
ret += "LastBolus: " + DecimalFormatter.to2Decimal(pump.lastBolusAmount) + "U @" + android.text.format.DateFormat.format("HH:mm", pump.lastBolusTime) + "\n";
}
if (MainApp.getConfigBuilder().isInHistoryRealTempBasalInProgress()) {
ret += "Temp: " + MainApp.getConfigBuilder().getRealTempBasalFromHistory(System.currentTimeMillis()).toStringFull() + "\n";
}
if (MainApp.getConfigBuilder().isInHistoryExtendedBoluslInProgress()) {
ret += "Extended: " + MainApp.getConfigBuilder().getExtendedBolusFromHistory(System.currentTimeMillis()).toString() + "\n";
}
if (!veryShort) {
ret += "TDD: " + DecimalFormatter.to0Decimal(pump.dailyTotalUnits) + " / " + pump.maxDailyTotalUnits + " U\n";
}
ret += "IOB: " + pump.iob + "U\n";
ret += "Reserv: " + DecimalFormatter.to0Decimal(pump.reservoirRemainingUnits) + "U\n";
ret += "Batt: " + pump.batteryRemaining + "\n";
return ret;
}
// TODO: daily total constraint
}

View file

@ -6,6 +6,7 @@ import android.preference.ListPreference;
import android.util.AttributeSet; import android.util.AttributeSet;
import java.util.Set; import java.util.Set;
import java.util.Vector;
public class BluetoothDevicePreference extends ListPreference { public class BluetoothDevicePreference extends ListPreference {
@ -13,25 +14,22 @@ public class BluetoothDevicePreference extends ListPreference {
super(context, attrs); super(context, attrs);
BluetoothAdapter bta = BluetoothAdapter.getDefaultAdapter(); BluetoothAdapter bta = BluetoothAdapter.getDefaultAdapter();
Integer size = 0; Vector<CharSequence> entries = new Vector<CharSequence>();
if (bta != null) {
size += bta.getBondedDevices().size();
}
CharSequence[] entries = new CharSequence[size];
int i = 0;
if (bta != null) { if (bta != null) {
Set<BluetoothDevice> pairedDevices = bta.getBondedDevices(); Set<BluetoothDevice> pairedDevices = bta.getBondedDevices();
for (BluetoothDevice dev : pairedDevices) { for (BluetoothDevice dev : pairedDevices) {
entries[i] = dev.getName(); String name = dev.getName();
i++; if(name != null) {
entries.add(name);
}
} }
} }
setEntries(entries); setEntries(entries.toArray(new CharSequence[0]));
setEntryValues(entries); setEntryValues(entries.toArray(new CharSequence[0]));
} }
public BluetoothDevicePreference(Context context) { public BluetoothDevicePreference(Context context) {
this(context, null); this(context, null);
} }
} }

View file

@ -6,8 +6,8 @@ import android.app.Activity;
import android.content.Intent; import android.content.Intent;
import android.os.Bundle; import android.os.Bundle;
import android.os.Handler; import android.os.Handler;
import android.os.HandlerThread;
import android.support.v4.app.FragmentManager; import android.support.v4.app.FragmentManager;
import android.text.Spanned;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
@ -21,16 +21,24 @@ import com.squareup.otto.Subscribe;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import java.util.Date;
import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.OnClick;
import butterknife.Unbinder;
import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.R; import info.nightscout.androidaps.R;
import info.nightscout.androidaps.events.EventExtendedBolusChange; import info.nightscout.androidaps.events.EventExtendedBolusChange;
import info.nightscout.androidaps.events.EventPumpStatusChanged; import info.nightscout.androidaps.events.EventPumpStatusChanged;
import info.nightscout.androidaps.events.EventTempBasalChange; import info.nightscout.androidaps.events.EventTempBasalChange;
import info.nightscout.androidaps.plugins.Common.SubscriberFragment; import info.nightscout.androidaps.plugins.Common.SubscriberFragment;
import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin;
import info.nightscout.androidaps.plugins.PumpDanaR.Dialogs.ProfileViewDialog; import info.nightscout.androidaps.plugins.PumpDanaR.Dialogs.ProfileViewDialog;
import info.nightscout.androidaps.plugins.PumpDanaR.activities.DanaRHistoryActivity; import info.nightscout.androidaps.plugins.PumpDanaR.activities.DanaRHistoryActivity;
import info.nightscout.androidaps.plugins.PumpDanaR.activities.DanaRStatsActivity; import info.nightscout.androidaps.plugins.PumpDanaR.activities.DanaRStatsActivity;
import info.nightscout.androidaps.plugins.PumpDanaR.events.EventDanaRNewStatus; import info.nightscout.androidaps.plugins.PumpDanaR.events.EventDanaRNewStatus;
import info.nightscout.androidaps.queue.events.EventQueueChanged;
import info.nightscout.utils.DateUtil; import info.nightscout.utils.DateUtil;
import info.nightscout.utils.DecimalFormatter; import info.nightscout.utils.DecimalFormatter;
import info.nightscout.utils.SetWarnColor; import info.nightscout.utils.SetWarnColor;
@ -38,62 +46,47 @@ import info.nightscout.utils.SetWarnColor;
public class DanaRFragment extends SubscriberFragment { public class DanaRFragment extends SubscriberFragment {
private static Logger log = LoggerFactory.getLogger(DanaRFragment.class); private static Logger log = LoggerFactory.getLogger(DanaRFragment.class);
private static Handler sHandler;
private static HandlerThread sHandlerThread;
private Handler loopHandler = new Handler(); private Handler loopHandler = new Handler();
private Runnable refreshLoop = null; private Runnable refreshLoop = new Runnable() {
TextView lastConnectionView;
TextView btConnectionView;
TextView lastBolusView;
TextView dailyUnitsView;
TextView basaBasalRateView;
TextView tempBasalView;
TextView extendedBolusView;
TextView batteryView;
TextView reservoirView;
TextView iobView;
TextView firmwareView;
TextView basalStepView;
TextView bolusStepView;
TextView serialNumberView;
Button viewProfileButton;
Button historyButton;
Button statsButton;
LinearLayout pumpStatusLayout;
TextView pumpStatusView;
static Runnable connectRunnable = new Runnable() {
@Override @Override
public void run() { public void run() {
MainApp.getConfigBuilder().refreshDataFromPump("Connect request from GUI"); updateGUI();
loopHandler.postDelayed(refreshLoop, 60 * 1000L);
} }
}; };
@BindView(R.id.danar_lastconnection) TextView lastConnectionView;
@BindView(R.id.danar_btconnection) TextView btConnectionView;
@BindView(R.id.danar_lastbolus) TextView lastBolusView;
@BindView(R.id.danar_dailyunits) TextView dailyUnitsView;
@BindView(R.id.danar_basabasalrate) TextView basaBasalRateView;
@BindView(R.id.danar_tempbasal) TextView tempBasalView;
@BindView(R.id.danar_extendedbolus) TextView extendedBolusView;
@BindView(R.id.danar_battery) TextView batteryView;
@BindView(R.id.danar_reservoir) TextView reservoirView;
@BindView(R.id.danar_iob) TextView iobView;
@BindView(R.id.danar_firmware) TextView firmwareView;
@BindView(R.id.danar_basalstep) TextView basalStepView;
@BindView(R.id.danar_bolusstep) TextView bolusStepView;
@BindView(R.id.danar_serialnumber) TextView serialNumberView;
@BindView(R.id.danar_queue) TextView queueView;
@BindView(R.id.overview_pumpstatuslayout) LinearLayout pumpStatusLayout;
@BindView(R.id.overview_pumpstatus) TextView pumpStatusView;
public DanaRFragment() { public DanaRFragment() {
if (sHandlerThread == null) {
sHandlerThread = new HandlerThread(DanaRFragment.class.getSimpleName());
sHandlerThread.start();
sHandler = new Handler(sHandlerThread.getLooper());
}
} }
@Override @Override
public void onCreate(Bundle savedInstanceState) { public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
if (refreshLoop == null) { loopHandler.postDelayed(refreshLoop, 60 * 1000L);
refreshLoop = new Runnable() { }
@Override
public void run() { @Override
updateGUI(); public void onDestroy() {
loopHandler.postDelayed(refreshLoop, 60 * 1000L); super.onDestroy();
} loopHandler.removeCallbacks(refreshLoop);
};
loopHandler.postDelayed(refreshLoop, 60 * 1000L);
}
} }
@Override @Override
@ -101,60 +94,10 @@ public class DanaRFragment extends SubscriberFragment {
Bundle savedInstanceState) { Bundle savedInstanceState) {
try { try {
View view = inflater.inflate(R.layout.danar_fragment, container, false); View view = inflater.inflate(R.layout.danar_fragment, container, false);
btConnectionView = (TextView) view.findViewById(R.id.danar_btconnection); unbinder = ButterKnife.bind(this, view);
lastConnectionView = (TextView) view.findViewById(R.id.danar_lastconnection);
lastBolusView = (TextView) view.findViewById(R.id.danar_lastbolus);
dailyUnitsView = (TextView) view.findViewById(R.id.danar_dailyunits);
basaBasalRateView = (TextView) view.findViewById(R.id.danar_basabasalrate);
tempBasalView = (TextView) view.findViewById(R.id.danar_tempbasal);
extendedBolusView = (TextView) view.findViewById(R.id.danar_extendedbolus);
batteryView = (TextView) view.findViewById(R.id.danar_battery);
reservoirView = (TextView) view.findViewById(R.id.danar_reservoir);
iobView = (TextView) view.findViewById(R.id.danar_iob);
firmwareView = (TextView) view.findViewById(R.id.danar_firmware);
viewProfileButton = (Button) view.findViewById(R.id.danar_viewprofile);
historyButton = (Button) view.findViewById(R.id.danar_history);
statsButton = (Button) view.findViewById(R.id.danar_stats);
basalStepView = (TextView) view.findViewById(R.id.danar_basalstep);
bolusStepView = (TextView) view.findViewById(R.id.danar_bolusstep);
serialNumberView = (TextView) view.findViewById(R.id.danar_serialnumber);
pumpStatusView = (TextView) view.findViewById(R.id.overview_pumpstatus);
pumpStatusView.setBackgroundColor(MainApp.sResources.getColor(R.color.colorInitializingBorder)); pumpStatusView.setBackgroundColor(MainApp.sResources.getColor(R.color.colorInitializingBorder));
pumpStatusLayout = (LinearLayout) view.findViewById(R.id.overview_pumpstatuslayout);
viewProfileButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
FragmentManager manager = getFragmentManager();
ProfileViewDialog profileViewDialog = new ProfileViewDialog();
profileViewDialog.show(manager, "ProfileViewDialog");
}
});
historyButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
startActivity(new Intent(getContext(), DanaRHistoryActivity.class));
}
});
statsButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
startActivity(new Intent(getContext(), DanaRStatsActivity.class));
}
});
btConnectionView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
log.debug("Clicked connect to pump");
sHandler.post(connectRunnable);
}
});
updateGUI();
return view; return view;
} catch (Exception e) { } catch (Exception e) {
Crashlytics.logException(e); Crashlytics.logException(e);
@ -163,6 +106,26 @@ public class DanaRFragment extends SubscriberFragment {
return null; return null;
} }
@OnClick(R.id.danar_history) void onHistoryClick() {
startActivity(new Intent(getContext(), DanaRHistoryActivity.class));
}
@OnClick(R.id.danar_viewprofile) void onViewProfileClick() {
FragmentManager manager = getFragmentManager();
ProfileViewDialog profileViewDialog = new ProfileViewDialog();
profileViewDialog.show(manager, "ProfileViewDialog");
}
@OnClick(R.id.danar_stats) void onStatsClick() {
startActivity(new Intent(getContext(), DanaRStatsActivity.class));
}
@OnClick(R.id.danar_btconnection) void onBtConnectionClick() {
log.debug("Clicked connect to pump");
DanaRPump.getInstance().lastConnection = 0;
ConfigBuilderPlugin.getCommandQueue().readStatus("Clicked connect to pump", null);
}
@Subscribe @Subscribe
public void onStatusEvent(final EventPumpStatusChanged c) { public void onStatusEvent(final EventPumpStatusChanged c) {
Activity activity = getActivity(); Activity activity = getActivity();
@ -206,6 +169,11 @@ public class DanaRFragment extends SubscriberFragment {
updateGUI(); updateGUI();
} }
@Subscribe
public void onStatusEvent(final EventQueueChanged s) {
updateGUI();
}
// GUI functions // GUI functions
@Override @Override
protected void updateGUI() { protected void updateGUI() {
@ -216,8 +184,8 @@ public class DanaRFragment extends SubscriberFragment {
@Override @Override
public void run() { public void run() {
DanaRPump pump = DanaRPump.getInstance(); DanaRPump pump = DanaRPump.getInstance();
if (pump.lastConnection.getTime() != 0) { if (pump.lastConnection != 0) {
Long agoMsec = System.currentTimeMillis() - pump.lastConnection.getTime(); Long agoMsec = System.currentTimeMillis() - pump.lastConnection;
int agoMin = (int) (agoMsec / 60d / 1000d); int agoMin = (int) (agoMsec / 60d / 1000d);
lastConnectionView.setText(DateUtil.timeString(pump.lastConnection) + " (" + String.format(MainApp.sResources.getString(R.string.minago), agoMin) + ")"); lastConnectionView.setText(DateUtil.timeString(pump.lastConnection) + " (" + String.format(MainApp.sResources.getString(R.string.minago), agoMin) + ")");
SetWarnColor.setColor(lastConnectionView, agoMin, 16d, 31d); SetWarnColor.setColor(lastConnectionView, agoMin, 16d, 31d);
@ -226,15 +194,15 @@ public class DanaRFragment extends SubscriberFragment {
Long agoMsec = System.currentTimeMillis() - pump.lastBolusTime.getTime(); Long agoMsec = System.currentTimeMillis() - pump.lastBolusTime.getTime();
double agoHours = agoMsec / 60d / 60d / 1000d; double agoHours = agoMsec / 60d / 60d / 1000d;
if (agoHours < 6) // max 6h back if (agoHours < 6) // max 6h back
lastBolusView.setText(DateUtil.timeString(pump.lastBolusTime) + " " + DateUtil.sinceString(pump.lastBolusTime.getTime()) + " " + DecimalFormatter.to2Decimal(DanaRPump.getInstance().lastBolusAmount) + " U"); lastBolusView.setText(DateUtil.timeString(pump.lastBolusTime) + " " + DateUtil.sinceString(pump.lastBolusTime.getTime()) + " " + DecimalFormatter.to2Decimal(DanaRPump.getInstance().lastBolusAmount) + " U");
else lastBolusView.setText(""); else lastBolusView.setText("");
} }
dailyUnitsView.setText(DecimalFormatter.to0Decimal(pump.dailyTotalUnits) + " / " + pump.maxDailyTotalUnits + " U"); dailyUnitsView.setText(DecimalFormatter.to0Decimal(pump.dailyTotalUnits) + " / " + pump.maxDailyTotalUnits + " U");
SetWarnColor.setColor(dailyUnitsView, pump.dailyTotalUnits, pump.maxDailyTotalUnits * 0.75d, pump.maxDailyTotalUnits * 0.9d); SetWarnColor.setColor(dailyUnitsView, pump.dailyTotalUnits, pump.maxDailyTotalUnits * 0.75d, pump.maxDailyTotalUnits * 0.9d);
basaBasalRateView.setText("( " + (pump.activeProfile + 1) + " ) " + DecimalFormatter.to2Decimal(MainApp.getConfigBuilder().getBaseBasalRate()) + " U/h"); basaBasalRateView.setText("( " + (pump.activeProfile + 1) + " ) " + DecimalFormatter.to2Decimal(ConfigBuilderPlugin.getActivePump().getBaseBasalRate()) + " U/h");
// DanaRPlugin, DanaRKoreanPlugin // DanaRPlugin, DanaRKoreanPlugin
if (MainApp.getConfigBuilder().isFakingTempsByExtendedBoluses()) { if (ConfigBuilderPlugin.getActivePump().isFakingTempsByExtendedBoluses()) {
if (MainApp.getConfigBuilder().isInHistoryRealTempBasalInProgress()) { if (MainApp.getConfigBuilder().isInHistoryRealTempBasalInProgress()) {
tempBasalView.setText(MainApp.getConfigBuilder().getRealTempBasalFromHistory(System.currentTimeMillis()).toStringFull()); tempBasalView.setText(MainApp.getConfigBuilder().getRealTempBasalFromHistory(System.currentTimeMillis()).toStringFull());
} else { } else {
@ -266,10 +234,17 @@ public class DanaRFragment extends SubscriberFragment {
basalStepView.setText("" + pump.basalStep); basalStepView.setText("" + pump.basalStep);
bolusStepView.setText("" + pump.bolusStep); bolusStepView.setText("" + pump.bolusStep);
serialNumberView.setText("" + pump.serialNumber); serialNumberView.setText("" + pump.serialNumber);
if (queueView != null) {
Spanned status = ConfigBuilderPlugin.getCommandQueue().spannedStatus();
if (status.toString().equals("")) {
queueView.setVisibility(View.GONE);
} else {
queueView.setVisibility(View.VISIBLE);
queueView.setText(status);
}
}
} }
}); });
} }
} }

View file

@ -5,69 +5,30 @@ import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.content.ServiceConnection; import android.content.ServiceConnection;
import android.os.IBinder; import android.os.IBinder;
import android.support.annotation.Nullable;
import com.squareup.otto.Subscribe; import com.squareup.otto.Subscribe;
import org.json.JSONException;
import org.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import java.util.Date;
import java.util.Objects;
import info.nightscout.androidaps.BuildConfig;
import info.nightscout.androidaps.Config; import info.nightscout.androidaps.Config;
import info.nightscout.androidaps.Constants;
import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.R; import info.nightscout.androidaps.R;
import info.nightscout.androidaps.data.DetailedBolusInfo; import info.nightscout.androidaps.data.DetailedBolusInfo;
import info.nightscout.androidaps.data.PumpEnactResult; import info.nightscout.androidaps.data.PumpEnactResult;
import info.nightscout.androidaps.db.ExtendedBolus;
import info.nightscout.androidaps.db.TemporaryBasal; import info.nightscout.androidaps.db.TemporaryBasal;
import info.nightscout.androidaps.db.Treatment; import info.nightscout.androidaps.db.Treatment;
import info.nightscout.androidaps.events.EventAppExit; import info.nightscout.androidaps.events.EventAppExit;
import info.nightscout.androidaps.events.EventPreferenceChange; import info.nightscout.androidaps.events.EventPreferenceChange;
import info.nightscout.androidaps.interfaces.ConstraintsInterface;
import info.nightscout.androidaps.interfaces.DanaRInterface;
import info.nightscout.androidaps.interfaces.PluginBase;
import info.nightscout.androidaps.interfaces.ProfileInterface;
import info.nightscout.androidaps.interfaces.PumpDescription; import info.nightscout.androidaps.interfaces.PumpDescription;
import info.nightscout.androidaps.interfaces.PumpInterface;
import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin; import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin;
import info.nightscout.androidaps.data.Profile;
import info.nightscout.androidaps.data.ProfileStore;
import info.nightscout.androidaps.plugins.Overview.Notification;
import info.nightscout.androidaps.plugins.Overview.events.EventDismissNotification;
import info.nightscout.androidaps.plugins.Overview.events.EventNewNotification;
import info.nightscout.androidaps.plugins.ProfileNS.NSProfilePlugin;
import info.nightscout.androidaps.plugins.PumpDanaR.services.DanaRExecutionService; import info.nightscout.androidaps.plugins.PumpDanaR.services.DanaRExecutionService;
import info.nightscout.utils.DateUtil;
import info.nightscout.utils.DecimalFormatter;
import info.nightscout.utils.Round; import info.nightscout.utils.Round;
import info.nightscout.utils.SP; import info.nightscout.utils.SP;
/** /**
* Created by mike on 05.08.2016. * Created by mike on 05.08.2016.
*/ */
public class DanaRPlugin implements PluginBase, PumpInterface, DanaRInterface, ConstraintsInterface, ProfileInterface { public class DanaRPlugin extends AbstractDanaRPlugin {
private static Logger log = LoggerFactory.getLogger(DanaRPlugin.class);
@Override
public String getFragmentClass() {
return DanaRFragment.class.getName();
}
private static boolean fragmentPumpEnabled = false;
private static boolean fragmentProfileEnabled = false;
private static boolean fragmentPumpVisible = true;
private static DanaRExecutionService sExecutionService;
private static DanaRPump pump = DanaRPump.getInstance();
private static boolean useExtendedBoluses = false;
private static DanaRPlugin plugin = null; private static DanaRPlugin plugin = null;
@ -77,9 +38,8 @@ public class DanaRPlugin implements PluginBase, PumpInterface, DanaRInterface, C
return plugin; return plugin;
} }
public static PumpDescription pumpDescription = new PumpDescription();
public DanaRPlugin() { public DanaRPlugin() {
log = LoggerFactory.getLogger(DanaRPlugin.class);
useExtendedBoluses = SP.getBoolean("danar_useextended", false); useExtendedBoluses = SP.getBoolean("danar_useextended", false);
Context context = MainApp.instance().getApplicationContext(); Context context = MainApp.instance().getApplicationContext();
@ -110,6 +70,8 @@ public class DanaRPlugin implements PluginBase, PumpInterface, DanaRInterface, C
pumpDescription.basalMinimumRate = 0.04d; pumpDescription.basalMinimumRate = 0.04d;
pumpDescription.isRefillingCapable = true; pumpDescription.isRefillingCapable = true;
pumpDescription.storesCarbInfo = true;
} }
private ServiceConnection mConnection = new ServiceConnection() { private ServiceConnection mConnection = new ServiceConnection() {
@ -145,83 +107,17 @@ public class DanaRPlugin implements PluginBase, PumpInterface, DanaRInterface, C
} }
// Plugin base interface // Plugin base interface
@Override
public int getType() {
return PluginBase.PUMP;
}
@Override @Override
public String getName() { public String getName() {
return MainApp.instance().getString(R.string.danarpump); return MainApp.instance().getString(R.string.danarpump);
} }
@Override
public String getNameShort() {
String name = MainApp.sResources.getString(R.string.danarpump_shortname);
if (!name.trim().isEmpty()) {
//only if translation exists
return name;
}
// use long name as fallback
return getName();
}
@Override
public boolean isEnabled(int type) {
if (type == PluginBase.PROFILE) return fragmentProfileEnabled && fragmentPumpEnabled;
else if (type == PluginBase.PUMP) return fragmentPumpEnabled;
else if (type == PluginBase.CONSTRAINTS) return fragmentPumpEnabled;
return false;
}
@Override
public boolean isVisibleInTabs(int type) {
if (type == PluginBase.PROFILE || type == PluginBase.CONSTRAINTS) return false;
else if (type == PluginBase.PUMP) return fragmentPumpVisible;
return false;
}
@Override
public boolean canBeHidden(int type) {
return true;
}
@Override
public boolean hasFragment() {
return true;
}
@Override
public boolean showInList(int type) {
return type == PUMP;
}
@Override
public void setFragmentEnabled(int type, boolean fragmentEnabled) {
if (type == PluginBase.PROFILE)
fragmentProfileEnabled = fragmentEnabled;
else if (type == PluginBase.PUMP)
fragmentPumpEnabled = fragmentEnabled;
// if pump profile was enabled need to switch to another too
if (type == PluginBase.PUMP && !fragmentEnabled && fragmentProfileEnabled) {
setFragmentEnabled(PluginBase.PROFILE, false);
setFragmentVisible(PluginBase.PROFILE, false);
NSProfilePlugin.getPlugin().setFragmentEnabled(PluginBase.PROFILE, true);
NSProfilePlugin.getPlugin().setFragmentVisible(PluginBase.PROFILE, true);
}
}
@Override
public void setFragmentVisible(int type, boolean fragmentVisible) {
if (type == PluginBase.PUMP)
fragmentPumpVisible = fragmentVisible;
}
@Override @Override
public int getPreferencesId() { public int getPreferencesId() {
return R.xml.pref_danar; return R.xml.pref_danar;
} }
// Pump interface
@Override @Override
public boolean isFakingTempsByExtendedBoluses() { public boolean isFakingTempsByExtendedBoluses() {
return useExtendedBoluses; return useExtendedBoluses;
@ -229,81 +125,7 @@ public class DanaRPlugin implements PluginBase, PumpInterface, DanaRInterface, C
@Override @Override
public boolean isInitialized() { public boolean isInitialized() {
return pump.lastConnection.getTime() > 0 && pump.isExtendedBolusEnabled; return pump.lastConnection > 0 && pump.isExtendedBolusEnabled && pump.maxBasal > 0;
}
@Override
public boolean isSuspended() {
return pump.pumpSuspended;
}
@Override
public boolean isBusy() {
if (sExecutionService == null) return false;
return sExecutionService.isConnected() || sExecutionService.isConnecting();
}
// Pump interface
@Override
public int setNewBasalProfile(Profile profile) {
if (sExecutionService == null) {
log.error("setNewBasalProfile sExecutionService is null");
return FAILED;
}
if (!isInitialized()) {
log.error("setNewBasalProfile not initialized");
Notification notification = new Notification(Notification.PROFILE_NOT_SET_NOT_INITIALIZED, MainApp.sResources.getString(R.string.pumpNotInitializedProfileNotSet), Notification.URGENT);
MainApp.bus().post(new EventNewNotification(notification));
return FAILED;
} else {
MainApp.bus().post(new EventDismissNotification(Notification.PROFILE_NOT_SET_NOT_INITIALIZED));
}
if (!sExecutionService.updateBasalsInPump(profile)) {
Notification notification = new Notification(Notification.FAILED_UDPATE_PROFILE, MainApp.sResources.getString(R.string.failedupdatebasalprofile), Notification.URGENT);
MainApp.bus().post(new EventNewNotification(notification));
return FAILED;
} else {
MainApp.bus().post(new EventDismissNotification(Notification.PROFILE_NOT_SET_NOT_INITIALIZED));
MainApp.bus().post(new EventDismissNotification(Notification.FAILED_UDPATE_PROFILE));
return SUCCESS;
}
}
@Override
public boolean isThisProfileSet(Profile profile) {
if (!isInitialized())
return true; // TODO: not sure what's better. so far TRUE to prevent too many SMS
if (pump.pumpProfiles == null)
return true; // TODO: not sure what's better. so far TRUE to prevent too many SMS
int basalValues = pump.basal48Enable ? 48 : 24;
int basalIncrement = pump.basal48Enable ? 30 * 60 : 60 * 60;
for (int h = 0; h < basalValues; h++) {
Double pumpValue = pump.pumpProfiles[pump.activeProfile][h];
Double profileValue = profile.getBasal((Integer) (h * basalIncrement));
if (profileValue == null) return true;
if (Math.abs(pumpValue - profileValue) > getPumpDescription().basalStep) {
log.debug("Diff found. Hour: " + h + " Pump: " + pumpValue + " Profile: " + profileValue);
return false;
}
}
return true;
}
@Override
public Date lastDataTime() {
return pump.lastConnection;
}
@Override
public void refreshDataFromPump(String reason) {
if (!isConnected() && !isConnecting()) {
doConnect(reason);
}
}
@Override
public double getBaseBasalRate() {
return pump.currentBasal;
} }
@Override @Override
@ -313,7 +135,7 @@ public class DanaRPlugin implements PluginBase, PumpInterface, DanaRInterface, C
if (detailedBolusInfo.insulin > 0 || detailedBolusInfo.carbs > 0) { if (detailedBolusInfo.insulin > 0 || detailedBolusInfo.carbs > 0) {
Treatment t = new Treatment(); Treatment t = new Treatment();
boolean connectionOK = false; boolean connectionOK = false;
if (detailedBolusInfo.insulin > 0 || detailedBolusInfo.carbs > 0) connectionOK = sExecutionService.bolus(detailedBolusInfo.insulin, (int) detailedBolusInfo.carbs, t); if (detailedBolusInfo.insulin > 0 || detailedBolusInfo.carbs > 0) connectionOK = sExecutionService.bolus(detailedBolusInfo.insulin, (int) detailedBolusInfo.carbs, detailedBolusInfo.carbTime, t);
PumpEnactResult result = new PumpEnactResult(); PumpEnactResult result = new PumpEnactResult();
result.success = connectionOK; result.success = connectionOK;
result.bolusDelivered = t.insulin; result.bolusDelivered = t.insulin;
@ -336,22 +158,14 @@ public class DanaRPlugin implements PluginBase, PumpInterface, DanaRInterface, C
} }
} }
@Override
public void stopBolusDelivering() {
if (sExecutionService == null) {
log.error("stopBolusDelivering sExecutionService is null");
return;
}
sExecutionService.bolusStop();
}
// This is called from APS // This is called from APS
@Override @Override
public PumpEnactResult setTempBasalAbsolute(Double absoluteRate, Integer durationInMinutes, boolean enforceNew) { public PumpEnactResult setTempBasalAbsolute(Double absoluteRate, Integer durationInMinutes, boolean enforceNew) {
// Recheck pump status if older than 30 min // Recheck pump status if older than 30 min
if (pump.lastConnection.getTime() + 30 * 60 * 1000L < System.currentTimeMillis()) { //This should not be needed while using queue because connection should be done before calling this
doConnect("setTempBasalAbsolute old data"); //if (pump.lastConnection.getTime() + 30 * 60 * 1000L < System.currentTimeMillis()) {
} // connect("setTempBasalAbsolute old data");
//}
PumpEnactResult result = new PumpEnactResult(); PumpEnactResult result = new PumpEnactResult();
@ -414,7 +228,7 @@ public class DanaRPlugin implements PluginBase, PumpInterface, DanaRInterface, C
log.debug("setTempBasalAbsolute: currently running: " + running.toString()); log.debug("setTempBasalAbsolute: currently running: " + running.toString());
if (running.percentRate == percentRate) { if (running.percentRate == percentRate) {
if (enforceNew) { if (enforceNew) {
cancelTempBasal(true); cancelTempBasal(true);
} else { } else {
result.success = true; result.success = true;
result.percent = percentRate; result.percent = percentRate;
@ -432,7 +246,7 @@ public class DanaRPlugin implements PluginBase, PumpInterface, DanaRInterface, C
// Convert duration from minutes to hours // Convert duration from minutes to hours
if (Config.logPumpActions) if (Config.logPumpActions)
log.debug("setTempBasalAbsolute: Setting temp basal " + percentRate + "% for " + durationInMinutes + " mins (doLowTemp || doHighTemp)"); log.debug("setTempBasalAbsolute: Setting temp basal " + percentRate + "% for " + durationInMinutes + " mins (doLowTemp || doHighTemp)");
return setTempBasalPercent(percentRate, durationInMinutes); return setTempBasalPercent(percentRate, durationInMinutes, false);
} }
if (doExtendedTemp) { if (doExtendedTemp) {
// Check if some temp is already in progress // Check if some temp is already in progress
@ -496,100 +310,6 @@ public class DanaRPlugin implements PluginBase, PumpInterface, DanaRInterface, C
return result; return result;
} }
@Override
public PumpEnactResult setTempBasalPercent(Integer percent, Integer durationInMinutes) {
PumpEnactResult result = new PumpEnactResult();
ConfigBuilderPlugin configBuilderPlugin = MainApp.getConfigBuilder();
percent = configBuilderPlugin.applyBasalConstraints(percent);
if (percent < 0) {
result.isTempCancel = false;
result.enacted = false;
result.success = false;
result.comment = MainApp.instance().getString(R.string.danar_invalidinput);
log.error("setTempBasalPercent: Invalid input");
return result;
}
if (percent > getPumpDescription().maxTempPercent)
percent = getPumpDescription().maxTempPercent;
TemporaryBasal runningTB = MainApp.getConfigBuilder().getRealTempBasalFromHistory(System.currentTimeMillis());
if (runningTB != null && runningTB.percentRate == percent) {
result.enacted = false;
result.success = true;
result.isTempCancel = false;
result.comment = MainApp.instance().getString(R.string.virtualpump_resultok);
result.duration = pump.tempBasalRemainingMin;
result.percent = pump.tempBasalPercent;
result.absolute = MainApp.getConfigBuilder().getTempBasalAbsoluteRateHistory();
result.isPercent = true;
if (Config.logPumpActions)
log.debug("setTempBasalPercent: Correct value already set");
return result;
}
int durationInHours = Math.max(durationInMinutes / 60, 1);
boolean connectionOK = sExecutionService.tempBasal(percent, durationInHours);
if (connectionOK && pump.isTempBasalInProgress && pump.tempBasalPercent == percent) {
result.enacted = true;
result.success = true;
result.comment = MainApp.instance().getString(R.string.virtualpump_resultok);
result.isTempCancel = false;
result.duration = pump.tempBasalRemainingMin;
result.percent = pump.tempBasalPercent;
result.absolute = MainApp.getConfigBuilder().getTempBasalAbsoluteRateHistory();
result.isPercent = true;
if (Config.logPumpActions)
log.debug("setTempBasalPercent: OK");
return result;
}
result.enacted = false;
result.success = false;
result.comment = MainApp.instance().getString(R.string.danar_valuenotsetproperly);
log.error("setTempBasalPercent: Failed to set temp basal");
return result;
}
@Override
public PumpEnactResult setExtendedBolus(Double insulin, Integer durationInMinutes) {
ConfigBuilderPlugin configBuilderPlugin = MainApp.getConfigBuilder();
insulin = configBuilderPlugin.applyBolusConstraints(insulin);
// needs to be rounded
int durationInHalfHours = Math.max(durationInMinutes / 30, 1);
insulin = Round.roundTo(insulin, getPumpDescription().extendedBolusStep);
PumpEnactResult result = new PumpEnactResult();
ExtendedBolus runningEB = MainApp.getConfigBuilder().getExtendedBolusFromHistory(System.currentTimeMillis());
if (runningEB != null && Math.abs(runningEB.insulin - insulin) < getPumpDescription().extendedBolusStep) {
result.enacted = false;
result.success = true;
result.comment = MainApp.instance().getString(R.string.virtualpump_resultok);
result.duration = pump.extendedBolusRemainingMinutes;
result.absolute = pump.extendedBolusAbsoluteRate;
result.isPercent = false;
result.isTempCancel = false;
if (Config.logPumpActions)
log.debug("setExtendedBolus: Correct extended bolus already set. Current: " + pump.extendedBolusAmount + " Asked: " + insulin);
return result;
}
boolean connectionOK = sExecutionService.extendedBolus(insulin, durationInHalfHours);
if (connectionOK && pump.isExtendedInProgress && Math.abs(pump.extendedBolusAmount - insulin) < getPumpDescription().extendedBolusStep) {
result.enacted = true;
result.success = true;
result.comment = MainApp.instance().getString(R.string.virtualpump_resultok);
result.isTempCancel = false;
result.duration = pump.extendedBolusRemainingMinutes;
result.absolute = pump.extendedBolusAbsoluteRate;
result.bolusDelivered = pump.extendedBolusAmount;
result.isPercent = false;
if (Config.logPumpActions)
log.debug("setExtendedBolus: OK");
return result;
}
result.enacted = false;
result.success = false;
result.comment = MainApp.instance().getString(R.string.danar_valuenotsetproperly);
log.error("setExtendedBolus: Failed to extended bolus");
return result;
}
@Override @Override
public PumpEnactResult cancelTempBasal(boolean force) { public PumpEnactResult cancelTempBasal(boolean force) {
if (MainApp.getConfigBuilder().isInHistoryRealTempBasalInProgress()) if (MainApp.getConfigBuilder().isInHistoryRealTempBasalInProgress())
@ -631,232 +351,7 @@ public class DanaRPlugin implements PluginBase, PumpInterface, DanaRInterface, C
} }
@Override @Override
public PumpEnactResult cancelExtendedBolus() { public PumpEnactResult loadEvents() {
PumpEnactResult result = new PumpEnactResult(); return null; // no history, not needed
ExtendedBolus runningEB = MainApp.getConfigBuilder().getExtendedBolusFromHistory(System.currentTimeMillis());
if (runningEB != null) {
sExecutionService.extendedBolusStop();
result.enacted = true;
result.isTempCancel = true;
}
if (!pump.isExtendedInProgress) {
result.success = true;
result.comment = MainApp.instance().getString(R.string.virtualpump_resultok);
if (Config.logPumpActions)
log.debug("cancelExtendedBolus: OK");
return result;
} else {
result.success = false;
result.comment = MainApp.instance().getString(R.string.danar_valuenotsetproperly);
log.error("cancelExtendedBolus: Failed to cancel extended bolus");
return result;
}
} }
public static void doConnect(String from) {
if (sExecutionService != null) {
sExecutionService.connect(from);
pumpDescription.basalStep = pump.basalStep;
pumpDescription.bolusStep = pump.bolusStep;
}
}
public static boolean isConnected() {
return sExecutionService != null && sExecutionService.isConnected();
}
public static boolean isConnecting() {
return sExecutionService != null && sExecutionService.isConnecting();
}
public static void doDisconnect(String from) {
if (sExecutionService != null) sExecutionService.disconnect(from);
}
@Override
public JSONObject getJSONStatus() {
if (pump.lastConnection.getTime() + 5 * 60 * 1000L < System.currentTimeMillis()) {
return null;
}
JSONObject pumpjson = new JSONObject();
JSONObject battery = new JSONObject();
JSONObject status = new JSONObject();
JSONObject extended = new JSONObject();
try {
battery.put("percent", pump.batteryRemaining);
status.put("status", pump.pumpSuspended ? "suspended" : "normal");
status.put("timestamp", DateUtil.toISOString(pump.lastConnection));
extended.put("Version", BuildConfig.VERSION_NAME + "-" + BuildConfig.BUILDVERSION);
extended.put("PumpIOB", pump.iob);
if (pump.lastBolusTime.getTime() != 0) {
extended.put("LastBolus", pump.lastBolusTime.toLocaleString());
extended.put("LastBolusAmount", pump.lastBolusAmount);
}
TemporaryBasal tb = MainApp.getConfigBuilder().getRealTempBasalFromHistory(System.currentTimeMillis());
if (tb != null) {
extended.put("TempBasalAbsoluteRate", tb.tempBasalConvertedToAbsolute(System.currentTimeMillis()));
extended.put("TempBasalStart", DateUtil.dateAndTimeString(tb.date));
extended.put("TempBasalRemaining", tb.getPlannedRemainingMinutes());
}
ExtendedBolus eb = MainApp.getConfigBuilder().getExtendedBolusFromHistory(System.currentTimeMillis());
if (eb != null) {
extended.put("ExtendedBolusAbsoluteRate", eb.absoluteRate());
extended.put("ExtendedBolusStart", DateUtil.dateAndTimeString(eb.date));
extended.put("ExtendedBolusRemaining", eb.getPlannedRemainingMinutes());
}
extended.put("BaseBasalRate", getBaseBasalRate());
try {
extended.put("ActiveProfile", MainApp.getConfigBuilder().getProfileName());
} catch (Exception e) {
}
pumpjson.put("battery", battery);
pumpjson.put("status", status);
pumpjson.put("extended", extended);
pumpjson.put("reservoir", (int) pump.reservoirRemainingUnits);
pumpjson.put("clock", DateUtil.toISOString(new Date()));
} catch (JSONException e) {
log.error("Unhandled exception", e);
}
return pumpjson;
}
@Override
public String deviceID() {
return pump.serialNumber;
}
@Override
public PumpDescription getPumpDescription() {
return pumpDescription;
}
/**
* DanaR interface
*/
@Override
public boolean loadHistory(byte type) {
return sExecutionService.loadHistory(type);
}
/**
* Constraint interface
*/
@Override
public boolean isLoopEnabled() {
return true;
}
@Override
public boolean isClosedModeEnabled() {
return true;
}
@Override
public boolean isAutosensModeEnabled() {
return true;
}
@Override
public boolean isAMAModeEnabled() {
return true;
}
@SuppressWarnings("PointlessBooleanExpression")
@Override
public Double applyBasalConstraints(Double absoluteRate) {
double origAbsoluteRate = absoluteRate;
if (pump != null) {
if (absoluteRate > pump.maxBasal) {
absoluteRate = pump.maxBasal;
if (Config.logConstraintsChanges && origAbsoluteRate != Constants.basalAbsoluteOnlyForCheckLimit)
log.debug("Limiting rate " + origAbsoluteRate + "U/h by pump constraint to " + absoluteRate + "U/h");
}
}
return absoluteRate;
}
@SuppressWarnings("PointlessBooleanExpression")
@Override
public Integer applyBasalConstraints(Integer percentRate) {
Integer origPercentRate = percentRate;
if (percentRate < 0) percentRate = 0;
if (percentRate > getPumpDescription().maxTempPercent)
percentRate = getPumpDescription().maxTempPercent;
if (!Objects.equals(percentRate, origPercentRate) && Config.logConstraintsChanges && !Objects.equals(origPercentRate, Constants.basalPercentOnlyForCheckLimit))
log.debug("Limiting percent rate " + origPercentRate + "% to " + percentRate + "%");
return percentRate;
}
@SuppressWarnings("PointlessBooleanExpression")
@Override
public Double applyBolusConstraints(Double insulin) {
double origInsulin = insulin;
if (pump != null) {
if (insulin > pump.maxBolus) {
insulin = pump.maxBolus;
if (Config.logConstraintsChanges && origInsulin != Constants.bolusOnlyForCheckLimit)
log.debug("Limiting bolus " + origInsulin + "U by pump constraint to " + insulin + "U");
}
}
return insulin;
}
@Override
public Integer applyCarbsConstraints(Integer carbs) {
return carbs;
}
@Override
public Double applyMaxIOBConstraints(Double maxIob) {
return maxIob;
}
@Nullable
@Override
public ProfileStore getProfile() {
if (pump.lastSettingsRead.getTime() == 0)
return null; // no info now
return pump.createConvertedProfile();
}
@Override
public String getUnits() {
return pump.getUnits();
}
@Override
public String getProfileName() {
return pump.createConvertedProfileName();
}
// Reply for sms communicator
public String shortStatus(boolean veryShort) {
String ret = "";
if (pump.lastConnection.getTime() != 0) {
Long agoMsec = System.currentTimeMillis() - pump.lastConnection.getTime();
int agoMin = (int) (agoMsec / 60d / 1000d);
ret += "LastConn: " + agoMin + " minago\n";
}
if (pump.lastBolusTime.getTime() != 0) {
ret += "LastBolus: " + DecimalFormatter.to2Decimal(pump.lastBolusAmount) + "U @" + android.text.format.DateFormat.format("HH:mm", pump.lastBolusTime) + "\n";
}
if (MainApp.getConfigBuilder().isInHistoryRealTempBasalInProgress()) {
ret += "Temp: " + MainApp.getConfigBuilder().getRealTempBasalFromHistory(System.currentTimeMillis()).toStringFull() + "\n";
}
if (MainApp.getConfigBuilder().isInHistoryExtendedBoluslInProgress()) {
ret += "Extended: " + MainApp.getConfigBuilder().getExtendedBolusFromHistory(System.currentTimeMillis()).toString() + "\n";
}
if (!veryShort) {
ret += "TDD: " + DecimalFormatter.to0Decimal(pump.dailyTotalUnits) + " / " + pump.maxDailyTotalUnits + " U\n";
}
ret += "IOB: " + pump.iob + "U\n";
ret += "Reserv: " + DecimalFormatter.to0Decimal(pump.reservoirRemainingUnits) + "U\n";
ret += "Batt: " + pump.batteryRemaining + "\n";
return ret;
}
// TODO: daily total constraint
} }

View file

@ -56,8 +56,8 @@ public class DanaRPump {
public static final int CARBS = 14; public static final int CARBS = 14;
public static final int PRIMECANNULA = 15; public static final int PRIMECANNULA = 15;
public Date lastConnection = new Date(0); public long lastConnection = 0;
public Date lastSettingsRead = new Date(0); public long lastSettingsRead =0;
// Info // Info
public String serialNumber = ""; public String serialNumber = "";

View file

@ -21,6 +21,7 @@ import info.nightscout.androidaps.data.ProfileStore;
import info.nightscout.androidaps.interfaces.PluginBase; import info.nightscout.androidaps.interfaces.PluginBase;
import info.nightscout.androidaps.data.Profile; import info.nightscout.androidaps.data.Profile;
import info.nightscout.androidaps.interfaces.ProfileInterface; import info.nightscout.androidaps.interfaces.ProfileInterface;
import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin;
import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPlugin; import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPlugin;
import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPump; import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPump;
import info.nightscout.androidaps.plugins.PumpDanaRKorean.DanaRKoreanPlugin; import info.nightscout.androidaps.plugins.PumpDanaRKorean.DanaRKoreanPlugin;
@ -44,14 +45,7 @@ public class ProfileViewDialog extends DialogFragment {
private Button refreshButton; private Button refreshButton;
Handler mHandler;
static HandlerThread mHandlerThread;
public ProfileViewDialog() { public ProfileViewDialog() {
mHandlerThread = new HandlerThread(ProfileViewDialog.class.getSimpleName());
mHandlerThread.start();
mHandler = new Handler(mHandlerThread.getLooper());
} }
@Override @Override
@ -72,18 +66,7 @@ public class ProfileViewDialog extends DialogFragment {
refreshButton.setOnClickListener(new View.OnClickListener() { refreshButton.setOnClickListener(new View.OnClickListener() {
@Override @Override
public void onClick(View v) { public void onClick(View v) {
mHandler.post(new Runnable() { ConfigBuilderPlugin.getCommandQueue().readStatus("ProfileViewDialog", null);
@Override
public void run() {
DanaRPump.getInstance().lastSettingsRead = new Date(0);
if (MainApp.getSpecificPlugin(DanaRPlugin.class).isEnabled(PluginBase.PUMP))
DanaRPlugin.doConnect("ProfileViewDialog");
if (MainApp.getSpecificPlugin(DanaRKoreanPlugin.class).isEnabled(PluginBase.PUMP))
DanaRKoreanPlugin.doConnect("ProfileViewDialog");
if (MainApp.getSpecificPlugin(DanaRv2Plugin.class).isEnabled(PluginBase.PUMP))
DanaRv2Plugin.doConnect("ProfileViewDialog");
}
});
dismiss(); dismiss();
} }
}); });

View file

@ -9,36 +9,30 @@ 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 java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
import info.nightscout.androidaps.Config; import info.nightscout.androidaps.Config;
import info.nightscout.androidaps.plugins.PumpDanaR.comm.MessageBase; import info.nightscout.androidaps.plugins.PumpDanaR.comm.MessageBase;
import info.nightscout.androidaps.plugins.PumpDanaR.comm.MessageHashTable; import info.nightscout.androidaps.plugins.PumpDanaR.comm.MessageHashTable;
import info.nightscout.androidaps.plugins.PumpDanaR.services.AbstractSerialIOThread;
import info.nightscout.utils.CRC; import info.nightscout.utils.CRC;
/** /**
* Created by mike on 17.07.2016. * Created by mike on 17.07.2016.
*/ */
public class SerialIOThread extends Thread { public class SerialIOThread extends AbstractSerialIOThread {
private static Logger log = LoggerFactory.getLogger(SerialIOThread.class); private static Logger log = LoggerFactory.getLogger(SerialIOThread.class);
private InputStream mInputStream = null; private InputStream mInputStream = null;
private OutputStream mOutputStream = null; private OutputStream mOutputStream = null;
private BluetoothSocket mRfCommSocket; private BluetoothSocket mRfCommSocket;
private static final ScheduledExecutorService worker = Executors.newSingleThreadScheduledExecutor();
private static ScheduledFuture<?> scheduledDisconnection = null;
private boolean mKeepRunning = true; private boolean mKeepRunning = true;
private byte[] mReadBuff = new byte[0]; private byte[] mReadBuff = new byte[0];
MessageBase processedMessage; private MessageBase processedMessage;
public SerialIOThread(BluetoothSocket rfcommSocket) { public SerialIOThread(BluetoothSocket rfcommSocket) {
super(SerialIOThread.class.toString()); super();
mRfCommSocket = rfcommSocket; mRfCommSocket = rfcommSocket;
try { try {
@ -64,7 +58,8 @@ public class SerialIOThread extends Thread {
// process all messages we already got // process all messages we already got
while (mReadBuff.length > 3) { // 3rd byte is packet size. continue only if we an determine packet size while (mReadBuff.length > 3) { // 3rd byte is packet size. continue only if we an determine packet size
byte[] extractedBuff = cutMessageFromBuffer(); byte[] extractedBuff = cutMessageFromBuffer();
if (extractedBuff == null) break; // message is not complete in buffer (wrong packet calls disconnection) if (extractedBuff == null)
break; // message is not complete in buffer (wrong packet calls disconnection)
int command = (extractedBuff[5] & 0xFF) | ((extractedBuff[4] << 8) & 0xFF00); int command = (extractedBuff[5] & 0xFF) | ((extractedBuff[4] << 8) & 0xFF00);
@ -85,7 +80,6 @@ public class SerialIOThread extends Thread {
synchronized (message) { synchronized (message) {
message.notify(); message.notify();
} }
scheduleDisconnection();
} }
} }
} catch (Exception e) { } catch (Exception e) {
@ -144,6 +138,7 @@ public class SerialIOThread extends Thread {
} }
} }
@Override
public synchronized void sendMessage(MessageBase message) { public synchronized void sendMessage(MessageBase message) {
if (!mRfCommSocket.isConnected()) { if (!mRfCommSocket.isConnected()) {
log.error("Socket not connected on sendMessage"); log.error("Socket not connected on sendMessage");
@ -177,25 +172,9 @@ public class SerialIOThread extends Thread {
log.debug("Old firmware detected"); log.debug("Old firmware detected");
} }
} }
scheduleDisconnection();
}
public void scheduleDisconnection() {
class DisconnectRunnable implements Runnable {
public void run() {
disconnect("scheduleDisconnection");
scheduledDisconnection = null;
}
}
// prepare task for execution in 10 sec
// cancel waiting task to prevent sending multiple disconnections
if (scheduledDisconnection != null)
scheduledDisconnection.cancel(false);
Runnable task = new DisconnectRunnable();
final int sec = 10;
scheduledDisconnection = worker.schedule(task, sec, TimeUnit.SECONDS);
} }
@Override
public void disconnect(String reason) { public void disconnect(String reason) {
mKeepRunning = false; mKeepRunning = false;
try { try {

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