Merge pull request #1 from MilosKozak/master

get latest changes 17-4-2018
This commit is contained in:
Alessya 2018-04-17 14:47:04 +03:00 committed by GitHub
commit 383b26ab0c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
493 changed files with 27160 additions and 9432 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,7 @@
[![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)
[![Donate via PayPal](https://www.paypalobjects.com/en_US/i/btn/btn_donateCC_LG.gif)](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=Y4LHGJJESAVB8)

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,29 +48,45 @@ def generateGitBuild = { ->
} }
android { android {
compileSdkVersion 23 compileSdkVersion 27
buildToolsVersion "25.0.2" buildToolsVersion "${supportLibraryVersion}"
defaultConfig { defaultConfig {
applicationId "info.nightscout.androidaps" applicationId "info.nightscout.androidaps"
minSdkVersion 21 minSdkVersion 21
targetSdkVersion 23 targetSdkVersion 23
multiDexEnabled true
versionCode 1500 versionCode 1500
version "1.53" version "1.58"
buildConfigField "String", "VERSION", '"' + version + '"' buildConfigField "String", "VERSION", '"' + version + '"'
buildConfigField "String", "BUILDVERSION", generateGitBuild() buildConfigField "String", "BUILDVERSION", generateGitBuild()
ndk {
moduleName "BleCommandUtil"
}
} }
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", "wear" flavorDimensions "standard"
full { full {
dimension "standard" dimension "standard"
resValue "string", "app_name", "AndroidAPS" resValue "string", "app_name", "AndroidAPS"
@ -70,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"
@ -82,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"
@ -94,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"
@ -106,22 +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"
} }
wear { g5uploader {
dimension "wear" dimension "standard"
buildConfigField "boolean", "WEAR", "true" resValue "string", "app_name", "NSClient"
buildConfigField "boolean", "WEAR_CONTROL", "false" versionName version + "-nsclient"
manifestPlaceholders = [
} appIcon: "@mipmap/yellowowl"
wearcontrol { ]
dimension "wear" buildConfigField "boolean", "APS", "false"
buildConfigField "boolean", "WEAR", "true" buildConfigField "boolean", "PUMPDRIVERS", "false"
buildConfigField "boolean", "WEAR_CONTROL", "true" buildConfigField "boolean", "NSCLIENTOLNY", "false"
} buildConfigField "boolean", "CLOSEDLOOP", "false"
nowear { buildConfigField "boolean", "G5UPLOADER", "true"
dimension "wear" buildConfigField "boolean", "PUMPCONTROL", "false"
buildConfigField "boolean", "WEAR", "false"
buildConfigField "boolean", "WEAR_CONTROL", "false"
} }
} }
} }
@ -136,51 +170,61 @@ allprojects {
} }
dependencies { dependencies {
wearWearApp project(path: ':wear', configuration: 'restrictedRelease') wearApp project(':wear')
wearcontrolWearApp project(path: ':wear', configuration: 'fullRelease')
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.slf4j:slf4j-api:1.7.12' compile "org.apache.commons:commons-lang3:3.6"
compile 'com.jjoe64:graphview:4.0.1' compile "org.slf4j:slf4j-api:1.7.12"
compile 'com.eclipsesource.j2v8:j2v8:3.1.6@aar' 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}"
} }

BIN
app/libs/rhino-1.7.7.2.jar Normal file

Binary file not shown.

View file

@ -17,6 +17,7 @@
<uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="com.google.android.permission.PROVIDE_BACKGROUND" /> <uses-permission android:name="com.google.android.permission.PROVIDE_BACKGROUND" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission-sdk-23 android:name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS" /> <uses-permission-sdk-23 android:name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS" />
@ -41,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" />
@ -50,6 +54,13 @@
<category android:name="android.intent.category.DEFAULT" /> <category android:name="android.intent.category.DEFAULT" />
</intent-filter> </intent-filter>
</activity> </activity>
<activity android:name=".plugins.PumpDanaRS.activities.BLEScanActivity">
<intent-filter>
<action android:name="info.nightscout.androidaps.plugins.PumpDanaRS.activities.BLEScanActivity" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
<activity android:name=".plugins.PumpDanaRS.activities.PairingHelperActivity" />
<receiver <receiver
android:name=".receivers.DataReceiver" android:name=".receivers.DataReceiver"
@ -64,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 -->
@ -113,6 +126,10 @@
android:name=".plugins.PumpDanaRv2.services.DanaRv2ExecutionService" android:name=".plugins.PumpDanaRv2.services.DanaRv2ExecutionService"
android:enabled="true" android:enabled="true"
android:exported="false" /> android:exported="false" />
<service
android:name=".plugins.PumpDanaRS.services.DanaRSService"
android:enabled="true"
android:exported="true"></service>
<service <service
android:name=".plugins.Wear.wearintegration.WatchUpdaterService" android:name=".plugins.Wear.wearintegration.WatchUpdaterService"
android:exported="true"> android:exported="true">
@ -128,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

@ -0,0 +1,12 @@
var console = { };
console.error = function error(){
for (var i = 0, len = arguments.length; i < len; i++) {
console2.log(arguments[i]);
}
};
console.log = function log(){
for (var i = 0, len = arguments.length; i < len; i++) {
console2.log(arguments[i]);
}
};

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

@ -0,0 +1,120 @@
package com.cozmo.danar.util;
import android.content.Context;
import info.nightscout.androidaps.MainApp;
public class BleCommandUtil {
public static final int DANAR_PACKET__TYPE_ENCRYPTION_REQUEST = 0x01;
public static final int DANAR_PACKET__TYPE_ENCRYPTION_RESPONSE = 0x02;
public static final int DANAR_PACKET__TYPE_COMMAND = 0xA1;
public static final int DANAR_PACKET__TYPE_RESPONSE = 0xB2;
public static final int DANAR_PACKET__TYPE_NOTIFY = 0xC3;
public static final int DANAR_PACKET__OPCODE_ENCRYPTION__PUMP_CHECK = 0x00;
public static final int DANAR_PACKET__OPCODE_ENCRYPTION__CHECK_PASSKEY = 0xD0;
public static final int DANAR_PACKET__OPCODE_ENCRYPTION__PASSKEY_REQUEST = 0xD1;
public static final int DANAR_PACKET__OPCODE_ENCRYPTION__PASSKEY_RETURN = 0xD2;
public static final int DANAR_PACKET__OPCODE_ENCRYPTION__TIME_INFORMATION = 0x01;
public static final int DANAR_PACKET__OPCODE_NOTIFY__DELIVERY_COMPLETE = 0x01;
public static final int DANAR_PACKET__OPCODE_NOTIFY__DELIVERY_RATE_DISPLAY = 0x02;
public static final int DANAR_PACKET__OPCODE_NOTIFY__ALARM = 0x03;
public static final int DANAR_PACKET__OPCODE_NOTIFY__MISSED_BOLUS_ALARM = 0x04;
public static final int DANAR_PACKET__OPCODE_REVIEW__INITIAL_SCREEN_INFORMATION = 0x02;
public static final int DANAR_PACKET__OPCODE_REVIEW__DELIVERY_STATUS = 0x03;
public static final int DANAR_PACKET__OPCODE_REVIEW__GET_PASSWORD = 0x04;
public static final int DANAR_PACKET__OPCODE_REVIEW__BOLUS_AVG = 0x10;
public static final int DANAR_PACKET__OPCODE_REVIEW__BOLUS = 0x11;
public static final int DANAR_PACKET__OPCODE_REVIEW__DAILY = 0x12;
public static final int DANAR_PACKET__OPCODE_REVIEW__PRIME = 0x13;
public static final int DANAR_PACKET__OPCODE_REVIEW__REFILL = 0x14;
public static final int DANAR_PACKET__OPCODE_REVIEW__BLOOD_GLUCOSE = 0x15;
public static final int DANAR_PACKET__OPCODE_REVIEW__CARBOHYDRATE = 0x16;
public static final int DANAR_PACKET__OPCODE_REVIEW__TEMPORARY = 0x17;
public static final int DANAR_PACKET__OPCODE_REVIEW__SUSPEND = 0x18;
public static final int DANAR_PACKET__OPCODE_REVIEW__ALARM = 0x19;
public static final int DANAR_PACKET__OPCODE_REVIEW__BASAL = 0x1A;
public static final int DANAR_PACKET__OPCODE_REVIEW__ALL_HISTORY = 0x1F;
public static final int DANAR_PACKET__OPCODE_REVIEW__GET_SHIPPING_INFORMATION = 0x20;
public static final int DANAR_PACKET__OPCODE_REVIEW__GET_PUMP_CHECK = 0x21;
public static final int DANAR_PACKET__OPCODE_REVIEW__GET_USER_TIME_CHANGE_FLAG = 0x22;
public static final int DANAR_PACKET__OPCODE_REVIEW__SET_USER_TIME_CHANGE_FLAG_CLEAR = 0x23;
public static final int DANAR_PACKET__OPCODE_REVIEW__GET_MORE_INFORMATION = 0x24;
public static final int DANAR_PACKET__OPCODE_REVIEW__SET_HISTORY_UPLOAD_MODE = 0x25;
public static final int DANAR_PACKET__OPCODE_REVIEW__GET_TODAY_DELIVERY_TOTAL = 0x26;
public static final int DANAR_PACKET__OPCODE_BOLUS__GET_STEP_BOLUS_INFORMATION = 0x40;
public static final int DANAR_PACKET__OPCODE_BOLUS__GET_EXTENDED_BOLUS_STATE = 0x41;
public static final int DANAR_PACKET__OPCODE_BOLUS__GET_EXTENDED_BOLUS = 0x42;
public static final int DANAR_PACKET__OPCODE_BOLUS__GET_DUAL_BOLUS = 0x43;
public static final int DANAR_PACKET__OPCODE_BOLUS__SET_STEP_BOLUS_STOP = 0x44;
public static final int DANAR_PACKET__OPCODE_BOLUS__GET_CARBOHYDRATE_CALCULATION_INFORMATION = 0x45;
public static final int DANAR_PACKET__OPCODE_BOLUS__GET_EXTENDED_MENU_OPTION_STATE = 0x46;
public static final int DANAR_PACKET__OPCODE_BOLUS__SET_EXTENDED_BOLUS = 0x47;
public static final int DANAR_PACKET__OPCODE_BOLUS__SET_DUAL_BOLUS = 0x48;
public static final int DANAR_PACKET__OPCODE_BOLUS__SET_EXTENDED_BOLUS_CANCEL = 0x49;
public static final int DANAR_PACKET__OPCODE_BOLUS__SET_STEP_BOLUS_START = 0x4A;
public static final int DANAR_PACKET__OPCODE_BOLUS__GET_CALCULATION_INFORMATION = 0x4B;
public static final int DANAR_PACKET__OPCODE_BOLUS__GET_BOLUS_RATE = 0x4C;
public static final int DANAR_PACKET__OPCODE_BOLUS__SET_BOLUS_RATE = 0x4D;
public static final int DANAR_PACKET__OPCODE_BOLUS__GET_CIR_CF_ARRAY = 0x4E;
public static final int DANAR_PACKET__OPCODE_BOLUS__SET_CIR_CF_ARRAY = 0x4F;
public static final int DANAR_PACKET__OPCODE_BOLUS__GET_BOLUS_OPTION = 0x50;
public static final int DANAR_PACKET__OPCODE_BOLUS__SET_BOLUS_OPTION = 0x51;
public static final int DANAR_PACKET__OPCODE_BASAL__SET_TEMPORARY_BASAL = 0x60;
public static final int DANAR_PACKET__OPCODE_BASAL__TEMPORARY_BASAL_STATE = 0x61;
public static final int DANAR_PACKET__OPCODE_BASAL__CANCEL_TEMPORARY_BASAL = 0x62;
public static final int DANAR_PACKET__OPCODE_BASAL__GET_PROFILE_NUMBER = 0x63;
public static final int DANAR_PACKET__OPCODE_BASAL__SET_PROFILE_NUMBER = 0x64;
public static final int DANAR_PACKET__OPCODE_BASAL__GET_PROFILE_BASAL_RATE = 0x65;
public static final int DANAR_PACKET__OPCODE_BASAL__SET_PROFILE_BASAL_RATE = 0x66;
public static final int DANAR_PACKET__OPCODE_BASAL__GET_BASAL_RATE = 0x67;
public static final int DANAR_PACKET__OPCODE_BASAL__SET_BASAL_RATE = 0x68;
public static final int DANAR_PACKET__OPCODE_BASAL__SET_SUSPEND_ON = 0x69;
public static final int DANAR_PACKET__OPCODE_BASAL__SET_SUSPEND_OFF = 0x6A;
public static final int DANAR_PACKET__OPCODE_OPTION__GET_PUMP_TIME = 0x70;
public static final int DANAR_PACKET__OPCODE_OPTION__SET_PUMP_TIME = 0x71;
public static final int DANAR_PACKET__OPCODE_OPTION__GET_USER_OPTION = 0x72;
public static final int DANAR_PACKET__OPCODE_OPTION__SET_USER_OPTION = 0x73;
public static final int DANAR_PACKET__OPCODE_BASAL__APS_SET_TEMPORARY_BASAL = 0xC1;
public static final int DANAR_PACKET__OPCODE__APS_HISTORY_EVENTS = 0xC2;
public static final int DANAR_PACKET__OPCODE__APS_SET_EVENT_HISTORY = 0xC3;
public static final int DANAR_PACKET__OPCODE_ETC__SET_HISTORY_SAVE = 0xE0;
public static final int DANAR_PACKET__OPCODE_ETC__KEEP_CONNECTION = 0xFF;
static {
System.loadLibrary("BleCommandUtil");
}
private static native byte[] getEncryptedPacketJni(Object context, int opcode, byte[] bytes, String deviceName);
private static native byte[] getDecryptedPacketJni(Object context, byte[] bytes);
// ---------------------------------------------------------
private static BleCommandUtil mInstance = null;
public static BleCommandUtil getInstance() {
if (mInstance == null) {
mInstance = new BleCommandUtil();
}
return mInstance;
}
// ---------------------------------------------------------
public byte[] getEncryptedPacket(int opcode, byte[] bytes, String deviceName) {
return getEncryptedPacketJni(MainApp.instance().getApplicationContext(), opcode, bytes, deviceName);
}
public byte[] getDecryptedPacket(byte[] bytes) {
return getDecryptedPacketJni(MainApp.instance().getApplicationContext(), bytes);
}
}

View file

@ -0,0 +1,87 @@
package com.squareup.otto;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import info.nightscout.androidaps.events.Event;
/** Logs events has they're being posted to and dispatched from the event bus.
*
* A summary of event-receiver calls that occurred so far is logged
* after 10s (after startup) and then again every 60s.
* */
public class LoggingBus extends Bus {
private static Logger log = LoggerFactory.getLogger(LoggingBus.class);
private static long everyMinute = System.currentTimeMillis() + 10 * 1000;
private Map<String, Set<String>> event2Receiver = new HashMap<>();
public LoggingBus(ThreadEnforcer enforcer) {
super(enforcer);
}
@Override
public void post(Object event) {
if (event instanceof DeadEvent) {
log.debug("Event has no receiver: " + ((DeadEvent) event).event + ", source: " + ((DeadEvent) event).source);
return;
}
if (!(event instanceof Event)) {
log.error("Posted event not an event class: " + event.getClass());
}
log.debug("<<< " + event);
try {
StackTraceElement caller = new Throwable().getStackTrace()[1];
String className = caller.getClassName();
className = className.substring(className.lastIndexOf(".") + 1);
log.debug(" source: " + className + "." + caller.getMethodName() + ":" + caller.getLineNumber());
} catch (RuntimeException e) {
log.debug(" source: <unknown>");
}
super.post(event);
}
@Override
protected void dispatch(Object event, EventHandler wrapper) {
try {
log.debug(">>> " + event);
Field methodField = wrapper.getClass().getDeclaredField("method");
methodField.setAccessible(true);
Method targetMethod = (Method) methodField.get(wrapper);
String className = targetMethod.getDeclaringClass().getSimpleName();
String methodName = targetMethod.getName();
String receiverMethod = className + "." + methodName;
log.debug(" receiver: " + receiverMethod);
String key = event.getClass().getSimpleName();
if (!event2Receiver.containsKey(key)) event2Receiver.put(key, new HashSet<String>());
event2Receiver.get(key).add(receiverMethod);
} catch (ReflectiveOperationException e) {
log.debug(" receiver: <unknown>");
}
if (everyMinute < System.currentTimeMillis()) {
log.debug("***************** Event -> receiver pairings seen so far ****************");
for (Map.Entry<String, Set<String>> stringSetEntry : event2Receiver.entrySet()) {
log.debug(" " + stringSetEntry.getKey());
for (String s : stringSetEntry.getValue()) {
log.debug(" -> " + s);
}
}
log.debug("*************************************************************************");
everyMinute = System.currentTimeMillis() + 60 * 1000;
}
super.dispatch(event, wrapper);
}
}

View file

@ -4,31 +4,26 @@ 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 OPENAPSENABLED = APS;
public static final boolean LOOPENABLED = APS;
public static final boolean WEAR = BuildConfig.WEAR;
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 DANARv2 = true && 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 ALLPREFERENCES = !BuildConfig.NSCLIENTOLNY;
public static final boolean detailedLog = true; public static final boolean detailedLog = true;
public static final boolean logFunctionCalls = true; public static final boolean logFunctionCalls = true;
public static final boolean logIncommingData = true; public static final boolean logIncommingData = true;
@ -40,10 +35,11 @@ public class Config {
public static final boolean logNSUpload = true; public static final boolean logNSUpload = true;
public static final boolean logPumpActions = true; public static final boolean logPumpActions = true;
public static final boolean logCongigBuilderActions = true; public static final boolean logCongigBuilderActions = true;
public static final boolean logAutosensData = true; public static final boolean logAutosensData = false;
public static final boolean logEvents = false;
// DanaR specific // DanaR specific
public static final boolean logDanaBTComm = true; public static final boolean logDanaBTComm = true;
public static final boolean logDanaMessageDetail = true; public static boolean logDanaMessageDetail = true;
public static final boolean logDanaSerialEngine = true; public static final boolean logDanaSerialEngine = true;
} }

View file

@ -32,6 +32,8 @@ public class Constants {
// Circadian Percentage Profile // Circadian Percentage Profile
public static final int CPP_MIN_PERCENTAGE = 50; public static final int CPP_MIN_PERCENTAGE = 50;
public static final int CPP_MAX_PERCENTAGE = 200; public static final int CPP_MAX_PERCENTAGE = 200;
public static final int CPP_MIN_TIMESHIFT = -6;
public static final int CPP_MAX_TIMESHIFT = 23;
// Very Hard Limits Ranges // Very Hard Limits Ranges
// First value is the Lowest and second value is the Highest a Limit can define // First value is the Lowest and second value is the Highest a Limit can define
@ -52,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

@ -58,8 +58,10 @@ public class MainActivity extends AppCompatActivity implements View.OnClickListe
static final int CASE_STORAGE = 0x1; static final int CASE_STORAGE = 0x1;
static final int CASE_SMS = 0x2; static final int CASE_SMS = 0x2;
static final int CASE_LOCATION = 0x3;
private boolean askForSMS = false; private boolean askForSMS = false;
private boolean askForLocation = true;
ImageButton menuButton; ImageButton menuButton;
@ -80,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");
@ -110,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() {
if(ev.recreate) {
recreate(); recreate();
}else {
try { // activity may be destroyed try { // activity may be destroyed
setUpTabs(true); setUpTabs(true);
} catch (IllegalStateException e) { } catch (IllegalStateException e) {
log.error("Unhandled exception", 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);
@ -157,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) {
@ -202,6 +221,7 @@ public class MainActivity extends AppCompatActivity implements View.OnClickListe
protected void onResume() { protected void onResume() {
super.onResume(); super.onResume();
askForSMSPermissions(); askForSMSPermissions();
askForLocationPermissions();
} }
@Override @Override
@ -256,6 +276,17 @@ public class MainActivity extends AppCompatActivity implements View.OnClickListe
} }
} }
private synchronized void askForLocationPermissions() {
if (askForLocation) { //only when settings were changed an MainActivity resumes.
askForLocation = false;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
askForPermission(new String[]{Manifest.permission.ACCESS_FINE_LOCATION,
Manifest.permission.ACCESS_FINE_LOCATION,
Manifest.permission.ACCESS_FINE_LOCATION}, CASE_LOCATION);
}
}
}
private void askForPermission(String[] permission, Integer requestCode) { private void askForPermission(String[] permission, Integer requestCode) {
boolean test = false; boolean test = false;
for (int i = 0; i < permission.length; i++) { for (int i = 0; i < permission.length; i++) {
@ -279,6 +310,7 @@ public class MainActivity extends AppCompatActivity implements View.OnClickListe
alert.setPositiveButton(R.string.ok, null); alert.setPositiveButton(R.string.ok, null);
alert.show(); alert.show();
break; break;
case CASE_LOCATION:
case CASE_SMS: case CASE_SMS:
break; break;
} }
@ -321,6 +353,7 @@ public class MainActivity extends AppCompatActivity implements View.OnClickListe
@Override @Override
public void run() { public void run() {
Intent i = new Intent(v.getContext(), PreferencesActivity.class); Intent i = new Intent(v.getContext(), PreferencesActivity.class);
i.putExtra("id", -1);
startActivity(i); startActivity(i);
} }
}, null); }, null);
@ -353,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;
@ -13,8 +12,11 @@ import com.crashlytics.android.answers.Answers;
import com.crashlytics.android.answers.CustomEvent; import com.crashlytics.android.answers.CustomEvent;
import com.j256.ormlite.android.apptools.OpenHelperManager; import com.j256.ormlite.android.apptools.OpenHelperManager;
import com.squareup.otto.Bus; import com.squareup.otto.Bus;
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;
@ -24,48 +26,47 @@ 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.CareportalFragment; import info.nightscout.androidaps.plugins.Careportal.CareportalPlugin;
import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderFragment; import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderFragment;
import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin; import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin;
import info.nightscout.androidaps.plugins.ConstraintsObjectives.ObjectivesFragment; import info.nightscout.androidaps.plugins.ConstraintsObjectives.ObjectivesPlugin;
import info.nightscout.androidaps.plugins.ConstraintsSafety.SafetyPlugin; import info.nightscout.androidaps.plugins.ConstraintsSafety.SafetyPlugin;
import info.nightscout.androidaps.plugins.Food.FoodPlugin;
import info.nightscout.androidaps.plugins.Insulin.InsulinFastactingPlugin; import info.nightscout.androidaps.plugins.Insulin.InsulinFastactingPlugin;
import info.nightscout.androidaps.plugins.Insulin.InsulinFastactingProlongedPlugin; import info.nightscout.androidaps.plugins.Insulin.InsulinFastactingProlongedPlugin;
import info.nightscout.androidaps.plugins.Insulin.InsulinOrefFreePeakPlugin; import info.nightscout.androidaps.plugins.Insulin.InsulinOrefFreePeakPlugin;
import info.nightscout.androidaps.plugins.Insulin.InsulinOrefRapidActingPlugin; import info.nightscout.androidaps.plugins.Insulin.InsulinOrefRapidActingPlugin;
import info.nightscout.androidaps.plugins.Insulin.InsulinOrefUltraRapidActingPlugin; import info.nightscout.androidaps.plugins.Insulin.InsulinOrefUltraRapidActingPlugin;
import info.nightscout.androidaps.plugins.IobCobCalculator.IobCobCalculatorPlugin; import info.nightscout.androidaps.plugins.IobCobCalculator.IobCobCalculatorPlugin;
import info.nightscout.androidaps.plugins.Loop.LoopFragment; import info.nightscout.androidaps.plugins.Loop.LoopPlugin;
import info.nightscout.androidaps.plugins.NSClientInternal.NSClientInternalFragment; import info.nightscout.androidaps.plugins.NSClientInternal.NSClientInternalPlugin;
import info.nightscout.androidaps.plugins.NSClientInternal.receivers.AckAlarmReceiver; import info.nightscout.androidaps.plugins.NSClientInternal.receivers.AckAlarmReceiver;
import info.nightscout.androidaps.plugins.OpenAPSAMA.OpenAPSAMAFragment; import info.nightscout.androidaps.plugins.OpenAPSAMA.OpenAPSAMAPlugin;
import info.nightscout.androidaps.plugins.OpenAPSMA.OpenAPSMAFragment; import info.nightscout.androidaps.plugins.OpenAPSMA.OpenAPSMAPlugin;
import info.nightscout.androidaps.plugins.Overview.OverviewFragment; 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.NSProfileFragment; import info.nightscout.androidaps.plugins.ProfileNS.NSProfilePlugin;
import info.nightscout.androidaps.plugins.ProfileSimple.SimpleProfileFragment; 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.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.SmsCommunicatorFragment; 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;
import info.nightscout.androidaps.plugins.SourceXdrip.SourceXdripPlugin; import info.nightscout.androidaps.plugins.SourceXdrip.SourceXdripPlugin;
import info.nightscout.androidaps.plugins.Treatments.TreatmentsFragment; import info.nightscout.androidaps.plugins.Treatments.TreatmentsPlugin;
import info.nightscout.androidaps.plugins.Wear.WearFragment; import info.nightscout.androidaps.plugins.Wear.WearPlugin;
import info.nightscout.androidaps.plugins.XDripStatusline.StatuslinePlugin; import info.nightscout.androidaps.plugins.XDripStatusline.StatuslinePlugin;
import info.nightscout.androidaps.receivers.DataReceiver; import info.nightscout.androidaps.receivers.DataReceiver;
import info.nightscout.androidaps.receivers.KeepAliveReceiver; import info.nightscout.androidaps.receivers.KeepAliveReceiver;
@ -97,11 +98,13 @@ 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);
sBus = new Bus(ThreadEnforcer.ANY); sBus = Config.logEvents ? new LoggingBus(ThreadEnforcer.ANY) : new Bus(ThreadEnforcer.ANY);
sInstance = this; sInstance = this;
sResources = getResources(); sResources = getResources();
@ -110,7 +113,7 @@ public class MainApp extends Application {
if (pluginsList == null) { if (pluginsList == null) {
pluginsList = new ArrayList<>(); pluginsList = new ArrayList<>();
// Register all tabs in app here // Register all tabs in app here
pluginsList.add(OverviewFragment.getPlugin()); pluginsList.add(OverviewPlugin.getPlugin());
pluginsList.add(IobCobCalculatorPlugin.getPlugin()); pluginsList.add(IobCobCalculatorPlugin.getPlugin());
if (Config.ACTION) pluginsList.add(ActionsFragment.getPlugin()); if (Config.ACTION) pluginsList.add(ActionsFragment.getPlugin());
pluginsList.add(InsulinFastactingPlugin.getPlugin()); pluginsList.add(InsulinFastactingPlugin.getPlugin());
@ -123,58 +126,64 @@ public class MainApp extends Application {
pluginsList.add(SensitivityWeightedAveragePlugin.getPlugin()); pluginsList.add(SensitivityWeightedAveragePlugin.getPlugin());
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.DANARv2) pluginsList.add(DanaRv2Plugin.getPlugin()); if (Config.DANAR) pluginsList.add(DanaRv2Plugin.getPlugin());
pluginsList.add(CareportalFragment.getPlugin()); if (Config.DANAR) pluginsList.add(DanaRSPlugin.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.getInstance()); if (Config.VIRTUALPUMP) pluginsList.add(VirtualPumpPlugin.getPlugin());
if (Config.LOOPENABLED) pluginsList.add(LoopFragment.getPlugin()); if (Config.APS) pluginsList.add(LoopPlugin.getPlugin());
if (Config.OPENAPSENABLED) pluginsList.add(OpenAPSMAFragment.getPlugin()); if (Config.APS) pluginsList.add(OpenAPSMAPlugin.getPlugin());
if (Config.OPENAPSENABLED) pluginsList.add(OpenAPSAMAFragment.getPlugin()); if (Config.APS) pluginsList.add(OpenAPSAMAPlugin.getPlugin());
pluginsList.add(NSProfileFragment.getPlugin()); pluginsList.add(NSProfilePlugin.getPlugin());
if (Config.OTHERPROFILES) pluginsList.add(SimpleProfileFragment.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(TreatmentsFragment.getPlugin()); pluginsList.add(TreatmentsPlugin.getPlugin());
if (Config.SAFETY) pluginsList.add(SafetyPlugin.getPlugin()); if (Config.SAFETY) pluginsList.add(SafetyPlugin.getPlugin());
if (Config.APS) pluginsList.add(ObjectivesFragment.getPlugin()); if (Config.APS) pluginsList.add(ObjectivesPlugin.getPlugin());
if (!Config.NSCLIENT) if (!Config.NSCLIENT && !Config.G5UPLOADER)
pluginsList.add(SourceXdripPlugin.getPlugin()); pluginsList.add(SourceXdripPlugin.getPlugin());
if (!Config.G5UPLOADER)
pluginsList.add(SourceNSClientPlugin.getPlugin()); pluginsList.add(SourceNSClientPlugin.getPlugin());
if (!Config.NSCLIENT) 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.SMSCOMMUNICATORENABLED) pluginsList.add(SmsCommunicatorFragment.getPlugin()); if (!Config.NSCLIENT)
pluginsList.add(SourceDexcomG5Plugin.getPlugin());
if (Config.SMSCOMMUNICATORENABLED) pluginsList.add(SmsCommunicatorPlugin.getPlugin());
pluginsList.add(FoodPlugin.getPlugin());
if (Config.WEAR) pluginsList.add(WearFragment.getPlugin(this)); pluginsList.add(WearPlugin.initPlugin(this));
pluginsList.add(StatuslinePlugin.getPlugin(this)); pluginsList.add(StatuslinePlugin.initPlugin(this));
pluginsList.add(new PersistentNotificationPlugin(this)); pluginsList.add(new PersistentNotificationPlugin(this));
pluginsList.add(NSClientInternalFragment.getPlugin()); pluginsList.add(NSClientInternalPlugin.getPlugin());
pluginsList.add(sConfigBuilder = ConfigBuilderFragment.getPlugin()); pluginsList.add(sConfigBuilder = ConfigBuilderFragment.getPlugin());
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"));
new Thread(new Runnable() {
startKeepAliveService();
Thread t = 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) startKeepAliveService();
pump.refreshDataFromPump("Initialization");
} }
}); }).start();
t.start();
} }
@ -183,6 +192,9 @@ public class MainApp extends Application {
lbm.registerReceiver(dataReceiver, new IntentFilter(Intents.ACTION_NEW_TREATMENT)); lbm.registerReceiver(dataReceiver, new IntentFilter(Intents.ACTION_NEW_TREATMENT));
lbm.registerReceiver(dataReceiver, new IntentFilter(Intents.ACTION_CHANGED_TREATMENT)); lbm.registerReceiver(dataReceiver, new IntentFilter(Intents.ACTION_CHANGED_TREATMENT));
lbm.registerReceiver(dataReceiver, new IntentFilter(Intents.ACTION_REMOVED_TREATMENT)); lbm.registerReceiver(dataReceiver, new IntentFilter(Intents.ACTION_REMOVED_TREATMENT));
lbm.registerReceiver(dataReceiver, new IntentFilter(Intents.ACTION_NEW_FOOD));
lbm.registerReceiver(dataReceiver, new IntentFilter(Intents.ACTION_CHANGED_FOOD));
lbm.registerReceiver(dataReceiver, new IntentFilter(Intents.ACTION_REMOVED_FOOD));
lbm.registerReceiver(dataReceiver, new IntentFilter(Intents.ACTION_NEW_SGV)); lbm.registerReceiver(dataReceiver, new IntentFilter(Intents.ACTION_NEW_SGV));
lbm.registerReceiver(dataReceiver, new IntentFilter(Intents.ACTION_NEW_PROFILE)); lbm.registerReceiver(dataReceiver, new IntentFilter(Intents.ACTION_NEW_PROFILE));
lbm.registerReceiver(dataReceiver, new IntentFilter(Intents.ACTION_NEW_STATUS)); lbm.registerReceiver(dataReceiver, new IntentFilter(Intents.ACTION_NEW_STATUS));
@ -203,11 +215,6 @@ public class MainApp extends Application {
private void startKeepAliveService() { private void startKeepAliveService() {
if (keepAliveReceiver == null) { if (keepAliveReceiver == null) {
keepAliveReceiver = new KeepAliveReceiver(); keepAliveReceiver = new KeepAliveReceiver();
if (Config.DANAR) {
startService(new Intent(this, DanaRExecutionService.class));
startService(new Intent(this, DanaRKoreanExecutionService.class));
startService(new Intent(this, DanaRv2ExecutionService.class));
}
keepAliveReceiver.setAlarm(this); keepAliveReceiver.setAlarm(this);
} }
} }
@ -215,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;
@ -15,17 +16,23 @@ import android.text.TextUtils;
import info.nightscout.androidaps.events.EventPreferenceChange; import info.nightscout.androidaps.events.EventPreferenceChange;
import info.nightscout.androidaps.events.EventRefreshGui; import info.nightscout.androidaps.events.EventRefreshGui;
import info.nightscout.androidaps.interfaces.PluginBase; import info.nightscout.androidaps.interfaces.PluginBase;
import info.nightscout.androidaps.plugins.Careportal.CareportalPlugin;
import info.nightscout.androidaps.plugins.ConstraintsSafety.SafetyPlugin;
import info.nightscout.androidaps.plugins.Insulin.InsulinOrefFreePeakPlugin; import info.nightscout.androidaps.plugins.Insulin.InsulinOrefFreePeakPlugin;
import info.nightscout.androidaps.plugins.PumpDanaR.BluetoothDevicePreference; import info.nightscout.androidaps.plugins.Loop.LoopPlugin;
import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPlugin;
import info.nightscout.androidaps.plugins.PumpDanaRKorean.DanaRKoreanPlugin;
import info.nightscout.androidaps.plugins.NSClientInternal.NSClientInternalPlugin; import info.nightscout.androidaps.plugins.NSClientInternal.NSClientInternalPlugin;
import info.nightscout.androidaps.plugins.OpenAPSAMA.OpenAPSAMAPlugin; import info.nightscout.androidaps.plugins.OpenAPSAMA.OpenAPSAMAPlugin;
import info.nightscout.androidaps.plugins.OpenAPSMA.OpenAPSMAPlugin;
import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPlugin;
import info.nightscout.androidaps.plugins.PumpDanaRKorean.DanaRKoreanPlugin;
import info.nightscout.androidaps.plugins.PumpDanaRS.DanaRSPlugin;
import info.nightscout.androidaps.plugins.PumpDanaRv2.DanaRv2Plugin; import info.nightscout.androidaps.plugins.PumpDanaRv2.DanaRv2Plugin;
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.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;
@ -39,6 +46,9 @@ public class PreferencesActivity extends PreferenceActivity implements SharedPre
protected void onCreate(Bundle savedInstanceState) { protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
myPreferenceFragment = new MyPreferenceFragment(); myPreferenceFragment = new MyPreferenceFragment();
Bundle args = new Bundle();
args.putInt("id", getIntent().getIntExtra("id", -1));
myPreferenceFragment.setArguments(args);
getFragmentManager().beginTransaction().replace(android.R.id.content, myPreferenceFragment).commit(); getFragmentManager().beginTransaction().replace(android.R.id.content, myPreferenceFragment).commit();
PreferenceManager.getDefaultSharedPreferences(this).registerOnSharedPreferenceChangeListener(this); PreferenceManager.getDefaultSharedPreferences(this).registerOnSharedPreferenceChangeListener(this);
} }
@ -49,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());
@ -62,7 +73,7 @@ public class PreferencesActivity extends PreferenceActivity implements SharedPre
} }
private static void updatePrefSummary(Preference pref) { private static void updatePrefSummary(Preference pref) {
if (pref instanceof ListPreference || pref instanceof BluetoothDevicePreference) { if (pref instanceof ListPreference) {
ListPreference listPref = (ListPreference) pref; ListPreference listPref = (ListPreference) pref;
pref.setSummary(listPref.getEntry()); pref.setSummary(listPref.getEntry());
} }
@ -70,18 +81,15 @@ public class PreferencesActivity extends PreferenceActivity implements SharedPre
EditTextPreference editTextPref = (EditTextPreference) pref; EditTextPreference editTextPref = (EditTextPreference) pref;
if (pref.getKey().contains("password") || pref.getKey().contains("secret")) { if (pref.getKey().contains("password") || pref.getKey().contains("secret")) {
pref.setSummary("******"); pref.setSummary("******");
} else if (pref.getKey().equals(MainApp.sResources.getString(R.string.key_danars_name))) {
pref.setSummary(SP.getString(R.string.key_danars_name, ""));
} else if (editTextPref.getText() != null && !editTextPref.getText().equals("")) { } else if (editTextPref.getText() != null && !editTextPref.getText().equals("")) {
((EditTextPreference) pref).setDialogMessage(editTextPref.getDialogMessage()); ((EditTextPreference) pref).setDialogMessage(editTextPref.getDialogMessage());
pref.setSummary(editTextPref.getText()); pref.setSummary(editTextPref.getText());
} } else if (pref.getKey().contains("smscommunicator_allowednumbers") && TextUtils.isEmpty(editTextPref.getText().trim())) {
else if(pref.getKey().contains("smscommunicator_allowednumbers") && TextUtils.isEmpty(editTextPref.getText().toString().trim())){
pref.setSummary(MainApp.sResources.getString(R.string.smscommunicator_allowednumbers_summary)); pref.setSummary(MainApp.sResources.getString(R.string.smscommunicator_allowednumbers_summary));
} }
} }
if (pref instanceof MultiSelectListPreference) {
EditTextPreference editTextPref = (EditTextPreference) pref;
pref.setSummary(editTextPref.getText());
}
} }
public static void initSummary(Preference p) { public static void initSummary(Preference p) {
@ -96,85 +104,94 @@ public class PreferencesActivity extends PreferenceActivity implements SharedPre
} }
public static class MyPreferenceFragment extends PreferenceFragment { public static class MyPreferenceFragment extends PreferenceFragment {
private Integer id;
@Override
public void setArguments(Bundle args) {
super.setArguments(args);
id = args.getInt("id");
}
void addPreferencesFromResourceIfEnabled(PluginBase p, int type) {
if (p.isEnabled(type) && p.getPreferencesId() != -1)
addPreferencesFromResource(p.getPreferencesId());
}
@Override @Override
public void onCreate(final Bundle savedInstanceState) { public void onCreate(final Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
if (Config.ALLPREFERENCES) {
if (savedInstanceState != null && savedInstanceState.containsKey("id")) {
id = savedInstanceState.getInt("id");
}
if (id != -1) {
addPreferencesFromResource(id);
addPreferencesFromResource(R.xml.pref_advanced);
} else {
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.ALLPREFERENCES) {
if (!Config.NSCLIENT && !Config.G5UPLOADER) {
addPreferencesFromResource(R.xml.pref_quickwizard); addPreferencesFromResource(R.xml.pref_quickwizard);
} }
addPreferencesFromResource(R.xml.pref_careportal); addPreferencesFromResourceIfEnabled(SourceDexcomG5Plugin.getPlugin(), PluginBase.BGSOURCE);
if (Config.ALLPREFERENCES) { addPreferencesFromResourceIfEnabled(CareportalPlugin.getPlugin(), PluginBase.GENERAL);
addPreferencesFromResource(R.xml.pref_treatments); addPreferencesFromResourceIfEnabled(SafetyPlugin.getPlugin(), PluginBase.CONSTRAINTS);
} if (Config.APS) {
if (Config.APS) addPreferencesFromResourceIfEnabled(LoopPlugin.getPlugin(), PluginBase.LOOP);
addPreferencesFromResource(R.xml.pref_closedmode); addPreferencesFromResourceIfEnabled(OpenAPSMAPlugin.getPlugin(), PluginBase.APS);
if (Config.OPENAPSENABLED) { addPreferencesFromResourceIfEnabled(OpenAPSAMAPlugin.getPlugin(), PluginBase.APS);
addPreferencesFromResource(R.xml.pref_openapsma);
if (MainApp.getSpecificPlugin(OpenAPSAMAPlugin.class) != null && MainApp.getSpecificPlugin(OpenAPSAMAPlugin.class).isEnabled(PluginBase.APS))
addPreferencesFromResource(R.xml.pref_openapsama);
}
if (MainApp.getSpecificPlugin(SensitivityAAPSPlugin.class) != null && MainApp.getSpecificPlugin(SensitivityAAPSPlugin.class).isEnabled(PluginBase.SENSITIVITY)
|| MainApp.getSpecificPlugin(SensitivityWeightedAveragePlugin.class) != null && MainApp.getSpecificPlugin(SensitivityWeightedAveragePlugin.class).isEnabled(PluginBase.SENSITIVITY))
addPreferencesFromResource(R.xml.pref_absorption_aaps);
if (MainApp.getSpecificPlugin(SensitivityOref0Plugin.class) != null && MainApp.getSpecificPlugin(SensitivityOref0Plugin.class).isEnabled(PluginBase.SENSITIVITY))
addPreferencesFromResource(R.xml.pref_absorption_oref0);
if (Config.ALLPREFERENCES) {
addPreferencesFromResource(R.xml.pref_profile);
} }
addPreferencesFromResourceIfEnabled(SensitivityAAPSPlugin.getPlugin(), PluginBase.SENSITIVITY);
addPreferencesFromResourceIfEnabled(SensitivityWeightedAveragePlugin.getPlugin(), PluginBase.SENSITIVITY);
addPreferencesFromResourceIfEnabled(SensitivityOref0Plugin.getPlugin(), PluginBase.SENSITIVITY);
if (Config.DANAR) { if (Config.DANAR) {
DanaRPlugin danaRPlugin = MainApp.getSpecificPlugin(DanaRPlugin.class); addPreferencesFromResourceIfEnabled(DanaRPlugin.getPlugin(), PluginBase.PUMP);
DanaRKoreanPlugin danaRKoreanPlugin = MainApp.getSpecificPlugin(DanaRKoreanPlugin.class); addPreferencesFromResourceIfEnabled(DanaRKoreanPlugin.getPlugin(), PluginBase.PUMP);
DanaRv2Plugin danaRv2Plugin = MainApp.getSpecificPlugin(DanaRv2Plugin.class); addPreferencesFromResourceIfEnabled(DanaRv2Plugin.getPlugin(), PluginBase.PUMP);
if (danaRPlugin.isEnabled(PluginBase.PUMP) || danaRKoreanPlugin.isEnabled(PluginBase.PUMP)) { addPreferencesFromResourceIfEnabled(DanaRSPlugin.getPlugin(), PluginBase.PUMP);
addPreferencesFromResource(R.xml.pref_danar);
} if (DanaRPlugin.getPlugin().isEnabled(PluginBase.PROFILE)
if (danaRv2Plugin != null && danaRv2Plugin.isEnabled(PluginBase.PUMP)) { || DanaRKoreanPlugin.getPlugin().isEnabled(PluginBase.PROFILE)
addPreferencesFromResource(R.xml.pref_danarv2); || DanaRv2Plugin.getPlugin().isEnabled(PluginBase.PROFILE)
} || DanaRSPlugin.getPlugin().isEnabled(PluginBase.PROFILE)) {
if (danaRPlugin.isEnabled(PluginBase.PROFILE) || danaRKoreanPlugin.isEnabled(PluginBase.PROFILE) || danaRv2Plugin != null && danaRv2Plugin.isEnabled(PluginBase.PROFILE)) {
addPreferencesFromResource(R.xml.pref_danarprofile); addPreferencesFromResource(R.xml.pref_danarprofile);
} }
} }
VirtualPumpPlugin virtualPumpPlugin = MainApp.getSpecificPlugin(VirtualPumpPlugin.class);
if (virtualPumpPlugin != null && virtualPumpPlugin.isEnabled(PluginBase.PUMP)) { if (!Config.NSCLIENT && !Config.G5UPLOADER) {
addPreferencesFromResource(R.xml.pref_virtualpump); addPreferencesFromResourceIfEnabled(VirtualPumpPlugin.getPlugin(), PluginBase.PUMP);
}
InsulinOrefFreePeakPlugin insulinOrefFreePeakPlugin = MainApp.getSpecificPlugin(InsulinOrefFreePeakPlugin.class);
if(insulinOrefFreePeakPlugin.isEnabled(PluginBase.INSULIN)){
addPreferencesFromResource(R.xml.pref_insulinoreffreepeak);
} }
NSClientInternalPlugin nsClientInternalPlugin = MainApp.getSpecificPlugin(NSClientInternalPlugin.class); addPreferencesFromResourceIfEnabled(InsulinOrefFreePeakPlugin.getPlugin(), PluginBase.INSULIN);
if (nsClientInternalPlugin != null && nsClientInternalPlugin.isEnabled(PluginBase.GENERAL)) {
addPreferencesFromResource(R.xml.pref_nsclientinternal); addPreferencesFromResourceIfEnabled(NSClientInternalPlugin.getPlugin(), PluginBase.GENERAL);
} addPreferencesFromResourceIfEnabled(SmsCommunicatorPlugin.getPlugin(), PluginBase.GENERAL);
if (Config.SMSCOMMUNICATORENABLED)
addPreferencesFromResource(R.xml.pref_smscommunicator); if (!Config.NSCLIENT && !Config.G5UPLOADER) {
if (Config.ALLPREFERENCES) {
addPreferencesFromResource(R.xml.pref_others); addPreferencesFromResource(R.xml.pref_others);
} }
addPreferencesFromResource(R.xml.pref_advanced); addPreferencesFromResource(R.xml.pref_advanced);
if (Config.WEAR) { addPreferencesFromResourceIfEnabled(WearPlugin.getPlugin(), PluginBase.GENERAL);
WearPlugin wearPlugin = MainApp.getSpecificPlugin(WearPlugin.class); addPreferencesFromResourceIfEnabled(StatuslinePlugin.getPlugin(), PluginBase.GENERAL);
if (wearPlugin != null && wearPlugin.isEnabled(PluginBase.GENERAL)) {
addPreferencesFromResource(R.xml.pref_wear);
}
}
StatuslinePlugin statuslinePlugin = MainApp.getSpecificPlugin(StatuslinePlugin.class);
if (statuslinePlugin != null && statuslinePlugin.isEnabled(PluginBase.GENERAL)) {
addPreferencesFromResource(R.xml.pref_xdripstatus);
} }
initSummary(getPreferenceScreen()); initSummary(getPreferenceScreen());
} }
@Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putInt("id", id);
}
public Preference getPreference(String key) { public Preference getPreference(String key) {
return findPreference(key); return findPreference(key);
} }

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,23 +118,28 @@ 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) ||
Intents.ACTION_NEW_STATUS.equals(action) || Intents.ACTION_NEW_STATUS.equals(action) ||
Intents.ACTION_NEW_DEVICESTATUS.equals(action) || Intents.ACTION_NEW_DEVICESTATUS.equals(action) ||
Intents.ACTION_NEW_FOOD.equals(action) ||
Intents.ACTION_CHANGED_FOOD.equals(action) ||
Intents.ACTION_REMOVED_FOOD.equals(action) ||
Intents.ACTION_NEW_CAL.equals(action) || Intents.ACTION_NEW_CAL.equals(action) ||
Intents.ACTION_NEW_MBG.equals(action)) Intents.ACTION_NEW_MBG.equals(action))
) { ) {
@ -184,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;
@ -247,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));
@ -308,36 +366,18 @@ 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 EventNSProfileUpdateGUI());
// if there are no profile switches this should lead to profile update
if (MainApp.getConfigBuilder().getProfileSwitchesFromHistory().size() == 0)
MainApp.bus().post(new EventNewBasalProfile()); 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) {
log.error("Unhandled exception", e); log.error("Unhandled exception", e);
} }
} }
if (intent.getAction().equals(Intents.ACTION_NEW_TREATMENT)) {
try {
if (bundles.containsKey("treatment")) {
String trstring = bundles.getString("treatment");
handleAddChangeDataFromNS(trstring);
}
if (bundles.containsKey("treatments")) {
String trstring = bundles.getString("treatments");
JSONArray jsonArray = new JSONArray(trstring);
for (int i = 0; i < jsonArray.length(); i++) {
JSONObject trJson = jsonArray.getJSONObject(i);
String trstr = trJson.toString();
handleAddChangeDataFromNS(trstr);
}
}
} catch (Exception e) {
log.error("Unhandled exception", e);
}
} if (intent.getAction().equals(Intents.ACTION_NEW_TREATMENT) || intent.getAction().equals(Intents.ACTION_CHANGED_TREATMENT)) {
if (intent.getAction().equals(Intents.ACTION_CHANGED_TREATMENT)) {
try { try {
if (bundles.containsKey("treatment")) { if (bundles.containsKey("treatment")) {
String trstring = bundles.getString("treatment"); String trstring = bundles.getString("treatment");
@ -433,6 +473,56 @@ public class DataService extends IntentService {
log.error("Unhandled exception", e); log.error("Unhandled exception", e);
} }
} }
if (intent.getAction().equals(Intents.ACTION_NEW_FOOD) || intent.getAction().equals(Intents.ACTION_CHANGED_FOOD)) {
try {
if (bundles.containsKey("food")) {
String trstring = bundles.getString("food");
handleAddChangeFoodRecord(new JSONObject(trstring));
}
if (bundles.containsKey("foods")) {
String trstring = bundles.getString("foods");
JSONArray jsonArray = new JSONArray(trstring);
for (int i = 0; i < jsonArray.length(); i++) {
JSONObject trJson = jsonArray.getJSONObject(i);
handleAddChangeFoodRecord(trJson);
}
}
} catch (Exception e) {
log.error("Unhandled exception", e);
}
}
if (intent.getAction().equals(Intents.ACTION_REMOVED_FOOD)) {
try {
if (bundles.containsKey("food")) {
String trstring = bundles.getString("food");
JSONObject trJson = new JSONObject(trstring);
String _id = trJson.getString("_id");
handleRemovedFoodRecord(_id);
}
if (bundles.containsKey("foods")) {
String trstring = bundles.getString("foods");
JSONArray jsonArray = new JSONArray(trstring);
for (int i = 0; i < jsonArray.length(); i++) {
JSONObject trJson = jsonArray.getJSONObject(i);
String _id = trJson.getString("_id");
handleRemovedFoodRecord(_id);
}
}
} catch (Exception e) {
log.error("Unhandled exception", e);
}
}
}
private void handleRemovedFoodRecord(String _id) {
MainApp.getDbHelper().foodHelper.deleteFoodById(_id);
}
public void handleAddChangeFoodRecord(JSONObject trJson) throws JSONException {
MainApp.getDbHelper().foodHelper.createFoodFromJsonIfNotExists(trJson);
} }
private void handleRemovedRecordFromNS(String _id) { private void handleRemovedRecordFromNS(String _id) {

View file

@ -8,6 +8,9 @@ public interface Intents {
String ACTION_NEW_PROFILE = "info.nightscout.client.NEW_PROFILE"; String ACTION_NEW_PROFILE = "info.nightscout.client.NEW_PROFILE";
String ACTION_NEW_SGV = "info.nightscout.client.NEW_SGV"; String ACTION_NEW_SGV = "info.nightscout.client.NEW_SGV";
String ACTION_NEW_DEVICESTATUS = "info.nightscout.client.NEW_DEVICESTATUS"; String ACTION_NEW_DEVICESTATUS = "info.nightscout.client.NEW_DEVICESTATUS";
String ACTION_NEW_FOOD = "info.nightscout.client.NEW_FOOD";
String ACTION_CHANGED_FOOD = "info.nightscout.client.CHANGED_FOOD";
String ACTION_REMOVED_FOOD = "info.nightscout.client.REMOVED_FOOD";
String ACTION_NEW_MBG = "info.nightscout.client.NEW_MBG"; String ACTION_NEW_MBG = "info.nightscout.client.NEW_MBG";
String ACTION_NEW_CAL = "info.nightscout.client.NEW_CAL"; String ACTION_NEW_CAL = "info.nightscout.client.NEW_CAL";
String ACTION_NEW_STATUS = "info.nightscout.client.NEW_STATUS"; String ACTION_NEW_STATUS = "info.nightscout.client.NEW_STATUS";
@ -42,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

@ -29,4 +29,14 @@ public class DetailedBolusInfo {
public Context context = null; // context for progress dialog public Context context = null; // context for progress dialog
public long pumpId = 0; // id of record if comming from pump history (not a newly created treatment) public long pumpId = 0; // id of record if comming from pump history (not a newly created treatment)
public boolean isSMB = false; // is a Super-MicroBolus public boolean isSMB = false; // is a Super-MicroBolus
@Override
public String toString() {
return new Date(date).toLocaleString() +
" insulin: " + insulin +
" carbs: " + carbs +
" isValid: " + isValid +
" carbTime: " + carbTime +
" isSMB: " + isSMB;
}
} }

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,15 +12,18 @@ 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.ToastUtils; import info.nightscout.utils.ToastUtils;
@ -29,19 +32,27 @@ public class Profile {
private JSONObject json; private JSONObject json;
private String units = null; private String units = null;
double dia = Constants.defaultDIA; private double dia = Constants.defaultDIA;
TimeZone timeZone = TimeZone.getDefault(); private TimeZone timeZone = TimeZone.getDefault();
JSONArray isf; private JSONArray isf;
private LongSparseArray<Double> isf_v = null; // oldest at index 0 private LongSparseArray<Double> isf_v = null; // oldest at index 0
JSONArray ic; private JSONArray ic;
private LongSparseArray<Double> ic_v = null; // oldest at index 0 private LongSparseArray<Double> ic_v = null; // oldest at index 0
JSONArray basal; private JSONArray basal;
private LongSparseArray<Double> basal_v = null; // oldest at index 0 private LongSparseArray<Double> basal_v = null; // oldest at index 0
JSONArray targetLow; private JSONArray targetLow;
JSONArray targetHigh; private LongSparseArray<Double> targetLow_v = null; // oldest at index 0
private JSONArray targetHigh;
private LongSparseArray<Double> targetHigh_v = null; // oldest at index 0
private int percentage = 100;
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); this(json, 100, 0);
if (this.units == null) { if (this.units == null) {
if (units != null) if (units != null)
this.units = units; this.units = units;
@ -52,7 +63,9 @@ public class Profile {
} }
} }
public Profile(JSONObject json) { public Profile(JSONObject json, int percentage, int timeshift) {
this.percentage = percentage;
this.timeshift = timeshift;
this.json = json; this.json = json;
try { try {
if (json.has("units")) if (json.has("units"))
@ -110,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;
} }
} }
@ -148,20 +163,102 @@ public class Profile {
} }
private LongSparseArray<Double> convertToSparseArray(JSONArray array) { private LongSparseArray<Double> convertToSparseArray(JSONArray array) {
double multiplier = getMultiplier(array);
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 = o.getLong("timeAsSeconds"); long tas = 0;
Double value = o.getDouble("value"); 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());
} }
} }
// check if start is at 0 (midnight)
// and add last value before midnight if not
if (sparse.keyAt(0) != 0) {
sparse.put(0, sparse.valueAt(sparse.size() - 1));
}
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;
@ -182,7 +279,47 @@ public class Profile {
return lastValue; return lastValue;
} }
private Double getValueToTime(LongSparseArray<Double> array, long timeAsSeconds) { Integer getShitfTimeSecs(Integer originalTime) {
Integer shiftedTime = originalTime + timeshift * 60 * 60;
shiftedTime = (shiftedTime + 24 * 60 * 60) % (24 * 60 * 60);
if (timeshift != 0)
log.debug("(Sec) Original time: " + originalTime + " ShiftedTime: " + shiftedTime);
return shiftedTime;
}
private double getMultiplier(LongSparseArray<Double> array) {
double multiplier = 1d;
if (array == isf_v)
multiplier = 100d / percentage;
else if (array == ic_v)
multiplier = 100d / percentage;
else if (array == basal_v)
multiplier = percentage / 100d;
else
log.error("Unknown array type");
return multiplier;
}
private double getMultiplier(JSONArray array) {
double multiplier = 1d;
if (array == isf)
multiplier = 100d / percentage;
else if (array == ic)
multiplier = 100d / percentage;
else if (array == basal)
multiplier = percentage / 100d;
else if (array == targetLow)
multiplier = 1d;
else if (array == targetHigh)
multiplier = 1d;
else
log.error("Unknown array type");
return multiplier;
}
private Double getValueToTime(LongSparseArray<Double> array, Integer timeAsSeconds) {
Double lastValue = null; Double lastValue = null;
for (Integer index = 0; index < array.size(); index++) { for (Integer index = 0; index < array.size(); index++) {
@ -197,26 +334,29 @@ public class Profile {
return lastValue; return lastValue;
} }
private String getValuesList(JSONArray array, JSONArray array2, DecimalFormat format, String units) { private String format_HH_MM(Integer timeAsSeconds) {
String time;
int hour = timeAsSeconds / 60 / 60;
int minutes = (timeAsSeconds - hour * 60 * 60) / 60;
DecimalFormat df = new DecimalFormat("00");
time = df.format(hour) + ":" + df.format(minutes);
return time;
}
private String getValuesList(LongSparseArray<Double> array, LongSparseArray<Double> array2, DecimalFormat format, String units) {
String retValue = ""; String retValue = "";
for (Integer index = 0; index < array.length(); index++) { for (Integer index = 0; index < array.size(); index++) {
try { retValue += format_HH_MM((int) array.keyAt(index));
JSONObject o = array.getJSONObject(index);
retValue += o.getString("time");
retValue += " "; retValue += " ";
retValue += format.format(o.getDouble("value")); retValue += format.format(array.valueAt(index));
if (array2 != null) { if (array2 != null) {
JSONObject o2 = array2.getJSONObject(index);
retValue += " - "; retValue += " - ";
retValue += format.format(o2.getDouble("value")); retValue += format.format(array2.valueAt(index));
} }
retValue += " " + units; retValue += " " + units;
if (index + 1 < array.length()) if (index + 1 < array.size())
retValue += "\n"; retValue += "\n";
} catch (JSONException e) {
log.error("Unhandled exception", e);
}
} }
return retValue; return retValue;
} }
@ -236,7 +376,7 @@ public class Profile {
} }
public String getIsfList() { public String getIsfList() {
return getValuesList(isf, null, new DecimalFormat("0.0"), getUnits() + "/U"); return getValuesList(isf_v, null, new DecimalFormat("0.0"), getUnits() + "/U");
} }
public Double getIc() { public Double getIc() {
@ -254,7 +394,7 @@ public class Profile {
} }
public String getIcList() { public String getIcList() {
return getValuesList(ic, null, new DecimalFormat("0.0"), " g/U"); return getValuesList(ic_v, null, new DecimalFormat("0.0"), " g/U");
} }
public Double getBasal() { public Double getBasal() {
@ -265,14 +405,15 @@ 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);
} }
public String getBasalList() { public String getBasalList() {
return getValuesList(basal, null, new DecimalFormat("0.00"), "U"); return getValuesList(basal_v, null, new DecimalFormat("0.00"), "U");
} }
public class BasalValue { public class BasalValue {
@ -285,21 +426,17 @@ public class Profile {
public Double value; public Double value;
} }
public BasalValue[] getBasalValues() { public synchronized BasalValue[] getBasalValues() {
try { if (basal_v == null)
BasalValue[] ret = new BasalValue[basal.length()]; basal_v = convertToSparseArray(basal);
BasalValue[] ret = new BasalValue[basal_v.size()];
for (Integer index = 0; index < basal.length(); index++) { for (Integer index = 0; index < basal_v.size(); index++) {
JSONObject o = basal.getJSONObject(index); Integer tas = (int) basal_v.keyAt(index);
Integer tas = o.getInt("timeAsSeconds"); Double value = basal_v.valueAt(index);
Double value = o.getDouble("value");
ret[index] = new BasalValue(tas, value); ret[index] = new BasalValue(tas, value);
} }
return ret; return ret;
} catch (JSONException e) {
log.error("Unhandled exception", e);
}
return new BasalValue[0];
} }
public Double getTargetLow() { public Double getTargetLow() {
@ -311,7 +448,9 @@ public class Profile {
} }
public Double getTargetLow(Integer timeAsSeconds) { public Double getTargetLow(Integer timeAsSeconds) {
return getValueToTime(targetLow, timeAsSeconds); if (targetLow_v == null)
targetLow_v = convertToSparseArray(targetLow);
return getValueToTime(targetLow_v, timeAsSeconds);
} }
public Double getTargetHigh() { public Double getTargetHigh() {
@ -323,11 +462,13 @@ public class Profile {
} }
public Double getTargetHigh(Integer timeAsSeconds) { public Double getTargetHigh(Integer timeAsSeconds) {
return getValueToTime(targetHigh, timeAsSeconds); if (targetHigh_v == null)
targetHigh_v = convertToSparseArray(targetHigh);
return getValueToTime(targetHigh_v, timeAsSeconds);
} }
public String getTargetList() { public String getTargetList() {
return getValuesList(targetLow, targetHigh, new DecimalFormat("0.0"), getUnits()); return getValuesList(targetLow_v, targetHigh_v, new DecimalFormat("0.0"), getUnits());
} }
public double getMaxDailyBasal() { public double getMaxDailyBasal() {
@ -350,18 +491,6 @@ public class Profile {
return (int) (passed / 1000); return (int) (passed / 1000);
} }
public static Integer secondsFromMidnight(Date date) {
Calendar c = Calendar.getInstance();
long now = date.getTime();
c.setTime(date);
c.set(Calendar.HOUR_OF_DAY, 0);
c.set(Calendar.MINUTE, 0);
c.set(Calendar.SECOND, 0);
c.set(Calendar.MILLISECOND, 0);
long passed = now - c.getTimeInMillis();
return (int) (passed / 1000);
}
public static Integer secondsFromMidnight(long date) { public static Integer secondsFromMidnight(long date) {
Calendar c = Calendar.getInstance(); Calendar c = Calendar.getInstance();
c.setTimeInMillis(date); c.setTimeInMillis(date);
@ -410,4 +539,29 @@ public class Profile {
return toUnitsString(lowMgdl, lowMmol, units) + " - " + toUnitsString(highMgdl, highMmol, units); return toUnitsString(lowMgdl, lowMmol, units) + " - " + toUnitsString(highMgdl, highMmol, units);
} }
public double percentageBasalSum() {
double result = 0d;
for (int i = 0; i < 24; i++) {
result += getBasal((Integer) (i * 60 * 60));
}
return result;
}
public double baseBasalSum() {
double result = 0d;
for (int i = 0; i < 24; i++) {
result += getBasal((Integer) (i * 60 * 60)) / getMultiplier(basal_v);
}
return result;
}
public int getPercentage() {
return percentage;
}
public int getTimeshift() {
return timeshift;
}
} }

View file

@ -31,6 +31,7 @@ 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) {
if (interval.isValid())
rawData.put(interval.start(), interval); rawData.put(interval.start(), interval);
} }
merge(); merge();

View file

@ -32,6 +32,56 @@ public class PumpEnactResult extends Object {
public boolean queued = false; public boolean queued = false;
public PumpEnactResult success(boolean success) {
this.success = success;
return this;
}
public PumpEnactResult enacted(boolean enacted) {
this.enacted = enacted;
return this;
}
public PumpEnactResult comment(String comment) {
this.comment = comment;
return this;
}
public PumpEnactResult duration(Integer duration) {
this.duration = duration;
return this;
}
public PumpEnactResult absolute(Double absolute) {
this.absolute = absolute;
return this;
}
public PumpEnactResult isPercent(boolean isPercent) {
this.isPercent = isPercent;
return this;
}
public PumpEnactResult isTempCancel(boolean isTempCancel) {
this.isTempCancel = isTempCancel;
return this;
}
public PumpEnactResult bolusDelivered(Double bolusDelivered) {
this.bolusDelivered = bolusDelivered;
return this;
}
public PumpEnactResult carbsDelivered(Double carbsDelivered) {
this.carbsDelivered = carbsDelivered;
return this;
}
public PumpEnactResult queued(boolean queued) {
this.queued = queued;
return this;
}
public String log() { public String log() {
return "Success: " + success + " Enacted: " + enacted + " Comment: " + comment + " Duration: " + duration + " Absolute: " + absolute + " Percent: " + percent + " IsPercent: " + isPercent + " Queued: " + queued; return "Success: " + success + " Enacted: " + enacted + " Comment: " + comment + " Duration: " + duration + " Absolute: " + absolute + " Percent: " + percent + " IsPercent: " + isPercent + " Queued: " + queued;
} }

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,9 +30,12 @@ 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.EventNewBG; import info.nightscout.androidaps.events.EventNewBG;
import info.nightscout.androidaps.events.EventProfileSwitchChange; import info.nightscout.androidaps.events.EventProfileSwitchChange;
import info.nightscout.androidaps.events.EventRefreshOverview; import info.nightscout.androidaps.events.EventRefreshOverview;
@ -42,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);
@ -59,6 +68,7 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
public static final String DATABASE_DBREQUESTS = "DBRequests"; public static final String DATABASE_DBREQUESTS = "DBRequests";
public static final String DATABASE_CAREPORTALEVENTS = "CareportalEvents"; public static final String DATABASE_CAREPORTALEVENTS = "CareportalEvents";
public static final String DATABASE_PROFILESWITCHES = "ProfileSwitches"; public static final String DATABASE_PROFILESWITCHES = "ProfileSwitches";
public static final String DATABASE_FOODS = "Foods";
private static final int DATABASE_VERSION = 8; private static final int DATABASE_VERSION = 8;
@ -85,6 +95,8 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
private static final ScheduledExecutorService profileSwitchEventWorker = Executors.newSingleThreadScheduledExecutor(); private static final ScheduledExecutorService profileSwitchEventWorker = Executors.newSingleThreadScheduledExecutor();
private static ScheduledFuture<?> scheduledProfileSwitchEventPost = null; private static ScheduledFuture<?> scheduledProfileSwitchEventPost = null;
public FoodHelper foodHelper = new FoodHelper(this);
public DatabaseHelper(Context context) { public DatabaseHelper(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION); super(context, DATABASE_NAME, null, DATABASE_VERSION);
onCreate(getWritableDatabase(), getConnectionSource()); onCreate(getWritableDatabase(), getConnectionSource());
@ -104,6 +116,7 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
TableUtils.createTableIfNotExists(connectionSource, ExtendedBolus.class); TableUtils.createTableIfNotExists(connectionSource, ExtendedBolus.class);
TableUtils.createTableIfNotExists(connectionSource, CareportalEvent.class); TableUtils.createTableIfNotExists(connectionSource, CareportalEvent.class);
TableUtils.createTableIfNotExists(connectionSource, ProfileSwitch.class); TableUtils.createTableIfNotExists(connectionSource, ProfileSwitch.class);
TableUtils.createTableIfNotExists(connectionSource, Food.class);
} catch (SQLException e) { } catch (SQLException e) {
log.error("Can't create database", e); log.error("Can't create database", e);
throw new RuntimeException(e); throw new RuntimeException(e);
@ -128,6 +141,7 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
TableUtils.dropTable(connectionSource, ExtendedBolus.class, true); TableUtils.dropTable(connectionSource, ExtendedBolus.class, true);
TableUtils.dropTable(connectionSource, CareportalEvent.class, true); TableUtils.dropTable(connectionSource, CareportalEvent.class, true);
TableUtils.dropTable(connectionSource, ProfileSwitch.class, true); TableUtils.dropTable(connectionSource, ProfileSwitch.class, true);
TableUtils.dropTable(connectionSource, Food.class, true);
onCreate(database, connectionSource); onCreate(database, connectionSource);
} }
} catch (SQLException e) { } catch (SQLException e) {
@ -205,6 +219,7 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
TableUtils.createTableIfNotExists(connectionSource, ExtendedBolus.class); TableUtils.createTableIfNotExists(connectionSource, ExtendedBolus.class);
TableUtils.createTableIfNotExists(connectionSource, CareportalEvent.class); TableUtils.createTableIfNotExists(connectionSource, CareportalEvent.class);
TableUtils.createTableIfNotExists(connectionSource, ProfileSwitch.class); TableUtils.createTableIfNotExists(connectionSource, ProfileSwitch.class);
foodHelper.resetFood();
updateEarliestDataChange(0); updateEarliestDataChange(0);
} catch (SQLException e) { } catch (SQLException e) {
log.error("Unhandled exception", e); log.error("Unhandled exception", e);
@ -217,6 +232,7 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
scheduleTemporaryTargetChange(); scheduleTemporaryTargetChange();
scheduleCareportalEventChange(); scheduleCareportalEventChange();
scheduleProfileSwitchChange(); scheduleProfileSwitchChange();
foodHelper.scheduleFoodChange();
new java.util.Timer().schedule( new java.util.Timer().schedule(
new java.util.TimerTask() { new java.util.TimerTask() {
@Override @Override
@ -335,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);
@ -343,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() {
@ -387,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);
@ -425,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;
@ -463,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();
@ -471,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());
} else { for (DbRequest r : dbList) {
//log.debug("Treatment findTreatmentById found: " + trList.get(0).log()); delete(r);
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() {
@ -655,8 +696,7 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
class PostRunnable implements Runnable { class PostRunnable implements Runnable {
public void run() { public void run() {
log.debug("Firing EventTreatmentChange"); log.debug("Firing EventTreatmentChange");
MainApp.bus().post(new EventReloadTreatmentData()); MainApp.bus().post(new EventReloadTreatmentData(new EventTreatmentChange()));
MainApp.bus().post(new EventTreatmentChange());
if (earliestDataChange != null) if (earliestDataChange != null)
MainApp.bus().post(new EventNewHistoryData(earliestDataChange)); MainApp.bus().post(new EventNewHistoryData(earliestDataChange));
earliestDataChange = null; earliestDataChange = null;
@ -1344,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);
@ -1357,8 +1397,7 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
class PostRunnable implements Runnable { class PostRunnable implements Runnable {
public void run() { public void run() {
log.debug("Firing EventExtendedBolusChange"); log.debug("Firing EventExtendedBolusChange");
MainApp.bus().post(new EventReloadTreatmentData()); MainApp.bus().post(new EventReloadTreatmentData(new EventExtendedBolusChange()));
MainApp.bus().post(new EventExtendedBolusChange());
if (earliestDataChange != null) if (earliestDataChange != null)
MainApp.bus().post(new EventNewHistoryData(earliestDataChange)); MainApp.bus().post(new EventNewHistoryData(earliestDataChange));
earliestDataChange = null; earliestDataChange = null;
@ -1431,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) {
@ -1535,9 +1588,10 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
old = getDaoProfileSwitch().queryForId(profileSwitch.date); old = getDaoProfileSwitch().queryForId(profileSwitch.date);
if (old != null) { if (old != null) {
if (!old.isEqual(profileSwitch)) { if (!old.isEqual(profileSwitch)) {
profileSwitch.source = old.source;
profileSwitch.profileName = old.profileName; // preserver profileName to prevent multiple CPP extension
getDaoProfileSwitch().delete(old); // need to delete/create because date may change too getDaoProfileSwitch().delete(old); // need to delete/create because date may change too
old.copyFrom(profileSwitch); getDaoProfileSwitch().create(profileSwitch);
getDaoProfileSwitch().create(old);
log.debug("PROFILESWITCH: Updating record by date from: " + Source.getString(profileSwitch.source) + " " + old.toString()); log.debug("PROFILESWITCH: Updating record by date from: " + Source.getString(profileSwitch.source) + " " + old.toString());
scheduleProfileSwitchChange(); scheduleProfileSwitchChange();
return true; return true;
@ -1563,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();
@ -1636,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);
@ -1672,4 +1741,5 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
return null; return null;
} }
// ---------------- Food handling ---------------
} }

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

@ -0,0 +1,107 @@
package info.nightscout.androidaps.db;
import com.j256.ormlite.field.DatabaseField;
import com.j256.ormlite.table.DatabaseTable;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.Objects;
/**
* Created by mike on 20.09.2017.
*/
@DatabaseTable(tableName = DatabaseHelper.DATABASE_FOODS)
public class Food {
private static Logger log = LoggerFactory.getLogger(Food.class);
@DatabaseField(id = true)
public long key;
@DatabaseField
public boolean isValid = true;
@DatabaseField
public String _id; // NS _id
@DatabaseField
public String name;
@DatabaseField
public String category;
@DatabaseField
public String subcategory;
// Example:
// name="juice" portion=250 units="ml" carbs=12
// means 250ml of juice has 12g of carbs
@DatabaseField
public double portion; // common portion in "units"
@DatabaseField
public int carbs; // in grams
@DatabaseField
public int fat = 0; // in grams
@DatabaseField
public int protein = 0; // in grams
@DatabaseField
public int energy = 0; // in kJ
@DatabaseField
public String units = "g";
@DatabaseField
public int gi; // not used yet
public Food() {
key = System.currentTimeMillis();
}
public boolean isEqual(Food other) {
if (portion != other.portion)
return false;
if (carbs != other.carbs)
return false;
if (fat != other.fat)
return false;
if (protein != other.protein)
return false;
if (energy != other.energy)
return false;
if (gi != other.gi)
return false;
if (!Objects.equals(_id, other._id))
return false;
if (!Objects.equals(name, other.name))
return false;
if (!Objects.equals(category, other.category))
return false;
if (!Objects.equals(subcategory, other.subcategory))
return false;
if (!Objects.equals(units, other.units))
return false;
return true;
}
public void copyFrom(Food other) {
isValid = other.isValid;
_id = other._id;
name = other.name;
category = other.category;
subcategory = other.subcategory;
portion = other.portion;
carbs = other.carbs;
fat = other.fat;
protein = other.protein;
energy = other.energy;
units = other.units;
gi = other.gi;
}
}

View file

@ -0,0 +1,208 @@
package info.nightscout.androidaps.db;
import com.j256.ormlite.android.AndroidConnectionSource;
import com.j256.ormlite.dao.Dao;
import com.j256.ormlite.stmt.PreparedQuery;
import com.j256.ormlite.stmt.QueryBuilder;
import com.j256.ormlite.stmt.Where;
import com.j256.ormlite.table.TableUtils;
import org.json.JSONException;
import org.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.events.EventFoodDatabaseChanged;
/**
* Created by mike on 24.09.2017.
*/
public class FoodHelper {
private static Logger log = LoggerFactory.getLogger(FoodHelper.class);
DatabaseHelper databaseHelper;
private static final ScheduledExecutorService foodEventWorker = Executors.newSingleThreadScheduledExecutor();
private static ScheduledFuture<?> scheduledFoodEventPost = null;
public FoodHelper(DatabaseHelper databaseHelper) {
this.databaseHelper = databaseHelper;
}
private Dao<Food, Long> getDaoFood() throws SQLException {
return databaseHelper.getDao(Food.class);
}
public void resetFood() {
try {
TableUtils.dropTable(databaseHelper.getConnectionSource(), Food.class, true);
TableUtils.createTableIfNotExists(databaseHelper.getConnectionSource(), Food.class);
} catch (SQLException e) {
log.error("Unhandled exception", e);
}
scheduleFoodChange();
}
public List<Food> getFoodData() {
try {
Dao<Food, Long> daoFood = getDaoFood();
List<Food> foods;
QueryBuilder<Food, Long> queryBuilder = daoFood.queryBuilder();
PreparedQuery<Food> preparedQuery = queryBuilder.prepare();
foods = daoFood.query(preparedQuery);
return foods;
} catch (SQLException e) {
log.error("Unhandled exception", e);
}
return new ArrayList<>();
}
public boolean createOrUpdate(Food food) {
try {
// find by NS _id
if (food._id != null && !food._id.equals("")) {
Food old;
QueryBuilder<Food, Long> queryBuilder = getDaoFood().queryBuilder();
Where where = queryBuilder.where();
where.eq("_id", food._id);
PreparedQuery<Food> preparedQuery = queryBuilder.prepare();
List<Food> found = getDaoFood().query(preparedQuery);
if (found.size() > 0) {
old = found.get(0);
if (!old.isEqual(food)) {
getDaoFood().delete(old); // need to delete/create because date may change too
old.copyFrom(food);
getDaoFood().create(old);
log.debug("FOOD: Updating record by _id: " + old.toString());
scheduleFoodChange();
return true;
} else {
return false;
}
} else {
getDaoFood().createOrUpdate(food);
log.debug("FOOD: New record: " + food.toString());
scheduleFoodChange();
return true;
}
}
} catch (SQLException e) {
log.error("Unhandled exception", e);
}
return false;
}
public void delete(Food food) {
try {
getDaoFood().delete(food);
scheduleFoodChange();
} catch (SQLException e) {
log.error("Unhandled exception", e);
}
}
public static void scheduleFoodChange() {
class PostRunnable implements Runnable {
public void run() {
log.debug("Firing EventFoodChange");
MainApp.bus().post(new EventFoodDatabaseChanged());
scheduledFoodEventPost = null;
}
}
// prepare task for execution in 1 sec
// cancel waiting task to prevent sending multiple posts
if (scheduledFoodEventPost != null)
scheduledFoodEventPost.cancel(false);
Runnable task = new PostRunnable();
final int sec = 1;
scheduledFoodEventPost = foodEventWorker.schedule(task, sec, TimeUnit.SECONDS);
}
/*
{
"_id": "551ee3ad368e06e80856e6a9",
"type": "food",
"category": "Zakladni",
"subcategory": "Napoje",
"name": "Mleko",
"portion": 250,
"carbs": 12,
"gi": 1,
"created_at": "2015-04-14T06:59:16.500Z",
"unit": "ml"
}
*/
public void createFoodFromJsonIfNotExists(JSONObject trJson) {
try {
Food food = new Food();
if (trJson.has("type") && trJson.getString("type").equals("food")) {
if (trJson.has("_id"))
food._id = trJson.getString("_id");
if (trJson.has("category"))
food.category = trJson.getString("category");
if (trJson.has("subcategory"))
food.subcategory = trJson.getString("subcategory");
if (trJson.has("name"))
food.name = trJson.getString("name");
if (trJson.has("unit"))
food.units = trJson.getString("unit");
if (trJson.has("portion"))
food.portion = trJson.getDouble("portion");
if (trJson.has("carbs"))
food.carbs = trJson.getInt("carbs");
if (trJson.has("gi"))
food.gi = trJson.getInt("gi");
if (trJson.has("energy"))
food.energy = trJson.getInt("energy");
if (trJson.has("protein"))
food.protein = trJson.getInt("protein");
if (trJson.has("fat"))
food.fat = trJson.getInt("fat");
}
createOrUpdate(food);
} catch (JSONException e) {
log.error("Unhandled exception", e);
}
}
public void deleteFoodById(String _id) {
Food stored = findFoodById(_id);
if (stored != null) {
log.debug("FOOD: Removing Food record from database: " + stored.toString());
delete(stored);
scheduleFoodChange();
}
}
public Food findFoodById(String _id) {
try {
QueryBuilder<Food, Long> queryBuilder = getDaoFood().queryBuilder();
Where where = queryBuilder.where();
where.eq("_id", _id);
PreparedQuery<Food> preparedQuery = queryBuilder.prepare();
List<Food> list = getDaoFood().query(preparedQuery);
if (list.size() == 1) {
return list.get(0);
} else {
return null;
}
} catch (SQLException e) {
log.error("Unhandled exception", e);
}
return null;
}
}

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;
@ -10,14 +11,19 @@ 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 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.utils.DateUtil; import info.nightscout.utils.DateUtil;
import info.nightscout.utils.DecimalFormatter;
@DatabaseTable(tableName = DatabaseHelper.DATABASE_PROFILESWITCHES) @DatabaseTable(tableName = DatabaseHelper.DATABASE_PROFILESWITCHES)
public class ProfileSwitch implements Interval, DataPointWithLabelInterface { public class ProfileSwitch implements Interval, DataPointWithLabelInterface {
@ -55,16 +61,32 @@ 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)); 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;
} }
public String getCustomizedName() {
String name = profileName;
if(LocalProfilePlugin.LOCAL_PROFILE.equals(name)){
name = DecimalFormatter.to2Decimal(getProfileObject().percentageBasalSum()) + "U ";
}
if (isCPP) {
name += "(" + percentage + "%";
if (timeshift != 0)
name += "," + timeshift + "h";
name += ")";
}
return name;
}
public boolean isEqual(ProfileSwitch other) { public boolean isEqual(ProfileSwitch other) {
if (date != other.date) { if (date != other.date) {
return false; return false;
@ -156,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 --------------------
@ -179,7 +215,7 @@ public class ProfileSwitch implements Interval, DataPointWithLabelInterface {
@Override @Override
public String getLabel() { public String getLabel() {
return profileName; return getCustomizedName();
} }
@Override @Override

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,16 @@
package info.nightscout.androidaps.events;
import org.apache.commons.lang3.builder.ReflectionToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;
/** Base class for all events posted on the event bus. */
public abstract class Event {
static {
ReflectionToStringBuilder.setDefaultStyle(ToStringStyle.SHORT_PREFIX_STYLE);
}
@Override
public String toString() {
return ReflectionToStringBuilder.toString(this);
}
}

View file

@ -3,5 +3,5 @@ package info.nightscout.androidaps.events;
/** /**
* Created by mike on 07.07.2016. * Created by mike on 07.07.2016.
*/ */
public class EventAppExit { public class EventAppExit extends Event {
} }

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,7 +4,7 @@ package info.nightscout.androidaps.events;
* Created by adrian on 07/02/17. * Created by adrian on 07/02/17.
*/ */
public class EventBolusRequested { public class EventBolusRequested extends Event {
private double amount; private double amount;
public EventBolusRequested (double amount){ public EventBolusRequested (double amount){

View file

@ -4,5 +4,5 @@ package info.nightscout.androidaps.events;
* Created by mike on 25.05.2017. * Created by mike on 25.05.2017.
*/ */
public class EventCareportalEventChange { public class EventCareportalEventChange extends Event {
} }

View file

@ -4,5 +4,5 @@ package info.nightscout.androidaps.events;
* Created by mike on 17.02.2017. * Created by mike on 17.02.2017.
*/ */
public class EventConfigBuilderChange { public class EventConfigBuilderChange extends Event {
} }

View file

@ -4,5 +4,5 @@ package info.nightscout.androidaps.events;
* Created by mike on 15.05.2017. * Created by mike on 15.05.2017.
*/ */
public class EventExtendedBolusChange { public class EventExtendedBolusChange extends Event {
} }

View file

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

View file

@ -4,5 +4,5 @@ package info.nightscout.androidaps.events;
* Created by mike on 13.12.2016. * Created by mike on 13.12.2016.
*/ */
public class EventInitializationChanged { public class EventInitializationChanged extends Event {
} }

View file

@ -0,0 +1,5 @@
package info.nightscout.androidaps.events;
/** Supeclass for all events concerned with input or output into or from the LoopPlugin. */
public abstract class EventLoop extends Event {
}

View file

@ -3,5 +3,5 @@ package info.nightscout.androidaps.events;
/** /**
* Created by mike on 05.06.2016. * Created by mike on 05.06.2016.
*/ */
public class EventNewBG { public class EventNewBG extends EventLoop {
} }

View file

@ -3,5 +3,5 @@ package info.nightscout.androidaps.events;
/** /**
* Created by mike on 04.06.2016. * Created by mike on 04.06.2016.
*/ */
public class EventNewBasalProfile { public class EventNewBasalProfile extends Event {
} }

View file

@ -5,7 +5,7 @@ import info.nightscout.androidaps.MainApp;
/** /**
* Created by mike on 19.06.2016. * Created by mike on 19.06.2016.
*/ */
public class EventPreferenceChange { public class EventPreferenceChange extends Event {
public String changedKey; public String changedKey;
public EventPreferenceChange(String key) { public EventPreferenceChange(String key) {
changedKey = key; changedKey = key;

View file

@ -4,5 +4,5 @@ package info.nightscout.androidaps.events;
* Created by mike on 02.06.2017. * Created by mike on 02.06.2017.
*/ */
public class EventProfileSwitchChange { public class EventProfileSwitchChange extends Event {
} }

View file

@ -7,7 +7,7 @@ import info.nightscout.androidaps.R;
* Created by mike on 19.02.2017. * Created by mike on 19.02.2017.
*/ */
public class EventPumpStatusChanged { public class EventPumpStatusChanged extends Event {
public static final int CONNECTING = 0; public static final int CONNECTING = 0;
public static final int CONNECTED = 1; public static final int CONNECTED = 1;
public static final int PERFORMING = 2; public static final int PERFORMING = 2;
@ -18,14 +18,24 @@ public class EventPumpStatusChanged {
public int sSecondsElapsed = 0; public int sSecondsElapsed = 0;
public String sPerfomingAction = ""; public String sPerfomingAction = "";
public static String error = "";
public EventPumpStatusChanged(int status) { public EventPumpStatusChanged(int status) {
sStatus = status; sStatus = status;
sSecondsElapsed = 0; sSecondsElapsed = 0;
error = "";
} }
public EventPumpStatusChanged(int status, int secondsElapsed) { public EventPumpStatusChanged(int status, int secondsElapsed) {
sStatus = status; sStatus = status;
sSecondsElapsed = secondsElapsed; sSecondsElapsed = secondsElapsed;
error = "";
}
public EventPumpStatusChanged(int status, String error) {
sStatus = status;
sSecondsElapsed = 0;
this.error = error;
} }
public EventPumpStatusChanged(String action) { public EventPumpStatusChanged(String action) {

View file

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

View file

@ -4,7 +4,7 @@ package info.nightscout.androidaps.events;
* Created by mike on 16.06.2017. * Created by mike on 16.06.2017.
*/ */
public class EventRefreshOverview { public class EventRefreshOverview extends Event {
public String from; public String from;
public EventRefreshOverview(String from) { public EventRefreshOverview(String from) {

View file

@ -4,5 +4,5 @@ package info.nightscout.androidaps.events;
* Created by mike on 12.06.2017. * Created by mike on 12.06.2017.
*/ */
public class EventReloadProfileSwitchData { public class EventReloadProfileSwitchData extends Event {
} }

View file

@ -4,5 +4,5 @@ package info.nightscout.androidaps.events;
* Created by mike on 29.05.2017. * Created by mike on 29.05.2017.
*/ */
public class EventReloadTempBasalData { public class EventReloadTempBasalData extends Event {
} }

View file

@ -4,5 +4,10 @@ package info.nightscout.androidaps.events;
* Created by mike on 29.05.2017. * Created by mike on 29.05.2017.
*/ */
public class EventReloadTreatmentData { public class EventReloadTreatmentData extends Event {
public Object next;
public EventReloadTreatmentData(Object next) {
this.next = next;
}
} }

View file

@ -3,5 +3,5 @@ package info.nightscout.androidaps.events;
/** /**
* Created by mike on 05.06.2016. * Created by mike on 05.06.2016.
*/ */
public class EventTempBasalChange { public class EventTempBasalChange extends EventLoop {
} }

View file

@ -4,5 +4,5 @@ package info.nightscout.androidaps.events;
* Created by mike on 13.01.2017. * Created by mike on 13.01.2017.
*/ */
public class EventTempTargetChange { public class EventTempTargetChange extends Event {
} }

View file

@ -3,5 +3,5 @@ package info.nightscout.androidaps.events;
/** /**
* Created by mike on 04.06.2016. * Created by mike on 04.06.2016.
*/ */
public class EventTreatmentChange { public class EventTreatmentChange extends EventLoop {
} }

View file

@ -0,0 +1,5 @@
package info.nightscout.androidaps.events;
/** Base class for events to update the UI, mostly a specific tab. */
public abstract class EventUpdateGui extends Event {
}

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

@ -30,4 +30,5 @@ public interface PluginBase {
boolean showInList(int type); boolean showInList(int type);
void setFragmentEnabled(int type, boolean fragmentEnabled); void setFragmentEnabled(int type, boolean fragmentEnabled);
void setFragmentVisible(int type, boolean fragmentVisible); void setFragmentVisible(int type, boolean fragmentVisible);
int getPreferencesId();
} }

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 force); 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,15 +3,13 @@ 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.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;
@ -33,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.
@ -45,39 +45,32 @@ 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());
}
} }
@Override @Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) { Bundle savedInstanceState) {
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);
@ -89,6 +82,11 @@ public class ActionsFragment extends SubscriberFragment implements View.OnClickL
updateGUI(); updateGUI();
return view; return view;
} catch (Exception e) {
Crashlytics.logException(e);
}
return null;
} }
@Subscribe @Subscribe
@ -128,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 {
@ -151,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 {
@ -159,14 +157,14 @@ public class ActionsFragment extends SubscriberFragment implements View.OnClickL
tempBasal.setVisibility(View.GONE); tempBasal.setVisibility(View.GONE);
tempBasalCancel.setVisibility(View.VISIBLE); tempBasalCancel.setVisibility(View.VISIBLE);
final TemporaryBasal activeTemp = MainApp.getConfigBuilder().getTempBasalFromHistory(System.currentTimeMillis()); final TemporaryBasal activeTemp = MainApp.getConfigBuilder().getTempBasalFromHistory(System.currentTimeMillis());
tempBasalCancel.setText(MainApp.instance().getString(R.string.cancel) + "\n" + activeTemp.toStringShort()); tempBasalCancel.setText(MainApp.instance().getString(R.string.cancel) + " " + activeTemp.toStringShort());
} else { } else {
tempBasal.setVisibility(View.VISIBLE); tempBasal.setVisibility(View.VISIBLE);
tempBasalCancel.setVisibility(View.GONE); tempBasalCancel.setVisibility(View.GONE);
} }
} }
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);
@ -183,18 +181,17 @@ 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();
final OptionsToShow profileswitch = CareportalFragment.profileswitch; final OptionsToShow profileswitch = CareportalFragment.PROFILESWITCH;
profileswitch.executeProfileSwitch = true; profileswitch.executeProfileSwitch = true;
newDialog.setOptions(profileswitch, R.string.careportal_profileswitch); newDialog.setOptions(profileswitch, R.string.careportal_profileswitch);
newDialog.show(manager, "NewNSTreatmentDialog"); newDialog.show(manager, "NewNSTreatmentDialog");
break; break;
case R.id.actions_temptarget: case R.id.actions_temptarget:
NewNSTreatmentDialog newTTDialog = new NewNSTreatmentDialog(); NewNSTreatmentDialog newTTDialog = new NewNSTreatmentDialog();
final OptionsToShow temptarget = CareportalFragment.temptarget; final OptionsToShow temptarget = CareportalFragment.TEMPTARGET;
temptarget.executeTempTarget = true; temptarget.executeTempTarget = true;
newTTDialog.setOptions(temptarget, R.string.careportal_temporarytarget); newTTDialog.setOptions(temptarget, R.string.careportal_temporarytarget);
newTTDialog.show(manager, "NewNSTreatmentDialog"); newTTDialog.show(manager, "NewNSTreatmentDialog");
@ -205,25 +202,15 @@ 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
public void run() {
pump.cancelExtendedBolus();
Answers.getInstance().logCustom(new CustomEvent("CancelExtended")); 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
public void run() {
pump.cancelTempBasal(true);
Answers.getInstance().logCustom(new CustomEvent("CancelTemp")); Answers.getInstance().logCustom(new CustomEvent("CancelTemp"));
} }
});
}
break; break;
case R.id.actions_settempbasal: case R.id.actions_settempbasal:
NewTempBasalDialog newTempDialog = new NewTempBasalDialog(); NewTempBasalDialog newTempDialog = new NewTempBasalDialog();

View file

@ -10,8 +10,8 @@ import info.nightscout.androidaps.interfaces.PluginBase;
public class ActionsPlugin implements PluginBase { public class ActionsPlugin implements PluginBase {
boolean fragmentEnabled = true; private boolean fragmentEnabled = true;
boolean fragmentVisible = true; private boolean fragmentVisible = true;
@Override @Override
public int getType() { public int getType() {
@ -74,4 +74,9 @@ public class ActionsPlugin implements PluginBase {
if (type == GENERAL) this.fragmentVisible = fragmentVisible; if (type == GENERAL) this.fragmentVisible = fragmentVisible;
} }
@Override
public int getPreferencesId() {
return -1;
}
} }

View file

@ -2,11 +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.SharedPreferences; import android.content.Intent;
import android.os.Bundle; import android.os.Bundle;
import android.os.Handler;
import android.os.HandlerThread;
import android.preference.PreferenceManager;
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;
@ -16,7 +13,6 @@ import android.view.ViewGroup;
import android.view.Window; import android.view.Window;
import android.view.WindowManager; import android.view.WindowManager;
import android.widget.Button; import android.widget.Button;
import android.widget.TextView;
import com.crashlytics.android.answers.Answers; import com.crashlytics.android.answers.Answers;
import com.crashlytics.android.answers.CustomEvent; import com.crashlytics.android.answers.CustomEvent;
@ -30,14 +26,12 @@ 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.interfaces.PumpInterface;
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.PlusMinusEditText; import info.nightscout.utils.NumberPicker;
import info.nightscout.utils.SP; import info.nightscout.utils.SP;
import info.nightscout.utils.SafeParse; import info.nightscout.utils.SafeParse;
@ -45,21 +39,14 @@ public class FillDialog extends DialogFragment implements OnClickListener {
private static Logger log = LoggerFactory.getLogger(FillDialog.class); private static Logger log = LoggerFactory.getLogger(FillDialog.class);
Button deliverButton; Button deliverButton;
TextView insulin;
double amount1 = 0d; double amount1 = 0d;
double amount2 = 0d; double amount2 = 0d;
double amount3 = 0d; double amount3 = 0d;
PlusMinusEditText 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
@ -73,10 +60,10 @@ public class FillDialog extends DialogFragment implements OnClickListener {
getDialog().getWindow().requestFeature(Window.FEATURE_NO_TITLE); getDialog().getWindow().requestFeature(Window.FEATURE_NO_TITLE);
getDialog().getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN); getDialog().getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN);
insulin = (TextView) view.findViewById(R.id.treatments_newtreatment_insulinamount);
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 = new PlusMinusEditText(view, R.id.treatments_newtreatment_insulinamount, R.id.treatments_newtreatment_insulinamount_plus, R.id.treatments_newtreatment_insulinamount_minus, 0d, 0d, maxInsulin, bolusstep, new DecimalFormat("0.00"), false); editInsulin = (NumberPicker) view.findViewById(R.id.treatments_newtreatment_insulinamount);
editInsulin.setParams(0d, 0d, maxInsulin, bolusstep, new DecimalFormat("0.00"), false);
//setup preset buttons //setup preset buttons
Button button1 = (Button) view.findViewById(R.id.fill_preset_button1); Button button1 = (Button) view.findViewById(R.id.fill_preset_button1);
@ -113,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;
} }
@ -127,7 +117,7 @@ public class FillDialog extends DialogFragment implements OnClickListener {
public void onClick(View view) { public void onClick(View view) {
switch (view.getId()) { switch (view.getId()) {
case R.id.treatments_newtreatment_deliverbutton: case R.id.treatments_newtreatment_deliverbutton:
Double insulin = SafeParse.stringToDouble(this.insulin.getText().toString()); Double insulin = SafeParse.stringToDouble(editInsulin.getText().toString());
confirmAndDeliver(insulin); confirmAndDeliver(insulin);
break; break;
case R.id.fill_preset_button1: case R.id.fill_preset_button1:
@ -163,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();
mHandler.post(new Runnable() {
@Override
public void run() {
DetailedBolusInfo detailedBolusInfo = new DetailedBolusInfo(); DetailedBolusInfo detailedBolusInfo = new DetailedBolusInfo();
detailedBolusInfo.insulin = finalInsulinAfterConstraints; detailedBolusInfo.insulin = finalInsulinAfterConstraints;
detailedBolusInfo.context = context; detailedBolusInfo.context = context;
detailedBolusInfo.source = Source.USER; detailedBolusInfo.source = Source.USER;
detailedBolusInfo.isValid = false; // do not count it in IOB (for pump history) detailedBolusInfo.isValid = false; // do not count it in IOB (for pump history)
PumpEnactResult result = pump.deliverTreatment(detailedBolusInfo); ConfigBuilderPlugin.getCommandQueue().bolus(detailedBolusInfo, new Callback() {
@Override
public void run() {
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,18 +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 android.widget.Button;
import android.widget.EditText;
import android.widget.RadioButton;
import com.crashlytics.android.answers.Answers; import com.crashlytics.android.answers.Answers;
import com.crashlytics.android.answers.CustomEvent; import com.crashlytics.android.answers.CustomEvent;
@ -26,26 +21,19 @@ 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.PlusMinusEditText;
import info.nightscout.utils.SafeParse; import info.nightscout.utils.SafeParse;
public class NewExtendedBolusDialog extends DialogFragment implements View.OnClickListener { public class NewExtendedBolusDialog extends DialogFragment implements View.OnClickListener {
private static Logger log = LoggerFactory.getLogger(NewExtendedBolusDialog.class); private static Logger log = LoggerFactory.getLogger(NewExtendedBolusDialog.class);
PlusMinusEditText editInsulin; NumberPicker editInsulin;
PlusMinusEditText 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,22 +44,20 @@ public class NewExtendedBolusDialog extends DialogFragment implements View.OnCli
View view = inflater.inflate(R.layout.overview_newextendedbolus_dialog, container, false); View view = inflater.inflate(R.layout.overview_newextendedbolus_dialog, container, false);
Double maxInsulin = MainApp.getConfigBuilder().applyBolusConstraints(Constants.bolusOnlyForCheckLimit); Double maxInsulin = MainApp.getConfigBuilder().applyBolusConstraints(Constants.bolusOnlyForCheckLimit);
editInsulin = new PlusMinusEditText(view, R.id.overview_newextendedbolus_insulin, R.id.overview_newextendedbolus_insulin_plus, R.id.overview_newextendedbolus_insulin_minus, 0d, 0d, maxInsulin, 0.1d, new DecimalFormat("0.00"), false); editInsulin = (NumberPicker) view.findViewById(R.id.overview_newextendedbolus_insulin);
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 = new PlusMinusEditText(view, R.id.overview_newextendedbolus_duration, R.id.overview_newextendedbolus_duration_plus, R.id.overview_newextendedbolus_duration_minus, extendedDurationStep, extendedDurationStep, extendedMaxDuration, extendedDurationStep, new DecimalFormat("0"), false); editDuration = (NumberPicker) view.findViewById(R.id.overview_newextendedbolus_duration);
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
@ -100,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;
@ -14,7 +12,6 @@ import android.view.ViewGroup;
import android.widget.LinearLayout; import android.widget.LinearLayout;
import android.widget.RadioButton; import android.widget.RadioButton;
import android.widget.RadioGroup; import android.widget.RadioGroup;
import android.widget.RelativeLayout;
import com.crashlytics.android.answers.Answers; import com.crashlytics.android.answers.Answers;
import com.crashlytics.android.answers.CustomEvent; import com.crashlytics.android.answers.CustomEvent;
@ -26,12 +23,12 @@ 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.PumpEnactResult;
import info.nightscout.androidaps.interfaces.PumpDescription;
import info.nightscout.androidaps.interfaces.PumpInterface;
import info.nightscout.androidaps.data.Profile; import info.nightscout.androidaps.data.Profile;
import info.nightscout.androidaps.interfaces.PumpDescription;
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.PlusMinusEditText;
import info.nightscout.utils.SafeParse; import info.nightscout.utils.SafeParse;
public class NewTempBasalDialog extends DialogFragment implements View.OnClickListener, RadioGroup.OnCheckedChangeListener { public class NewTempBasalDialog extends DialogFragment implements View.OnClickListener, RadioGroup.OnCheckedChangeListener {
@ -49,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
@ -72,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;
@ -111,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;
} }
@ -145,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, false);
}
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)); if (setAsPercent) {
builder.setMessage(result.comment); ConfigBuilderPlugin.getCommandQueue().tempBasalPercent(finalBasalPercent, finalDurationInMinutes, true, callback);
builder.setPositiveButton(MainApp.sResources.getString(R.string.ok), null); } else {
builder.show(); ConfigBuilderPlugin.getCommandQueue().tempBasalAbsolute(finalBasal, finalDurationInMinutes, true, callback);
} }
}
});
Answers.getInstance().logCustom(new CustomEvent("TempBasal")); Answers.getInstance().logCustom(new CustomEvent("TempBasal"));
} }
}); });

View file

@ -3,21 +3,20 @@ package info.nightscout.androidaps.plugins.Careportal;
import android.app.Activity; import android.app.Activity;
import android.os.Bundle; import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager; import android.support.v4.app.FragmentManager;
import android.text.Layout;
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.LinearLayout; import android.widget.LinearLayout;
import android.widget.TextView; import android.widget.TextView;
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.Profile;
import info.nightscout.androidaps.data.ProfileStore; import info.nightscout.androidaps.data.ProfileStore;
import info.nightscout.androidaps.db.CareportalEvent; import info.nightscout.androidaps.db.CareportalEvent;
import info.nightscout.androidaps.events.EventCareportalEventChange; import info.nightscout.androidaps.events.EventCareportalEventChange;
@ -28,8 +27,6 @@ import info.nightscout.androidaps.plugins.Overview.OverviewFragment;
public class CareportalFragment extends SubscriberFragment implements View.OnClickListener { public class CareportalFragment extends SubscriberFragment implements View.OnClickListener {
static CareportalPlugin careportalPlugin;
TextView iage; TextView iage;
TextView cage; TextView cage;
TextView sage; TextView sage;
@ -39,38 +36,33 @@ public class CareportalFragment extends SubscriberFragment implements View.OnCli
LinearLayout butonsLayout; LinearLayout butonsLayout;
View noProfileView; View noProfileView;
static public CareportalPlugin getPlugin() { // date,bg,insulin,carbs,prebolus,duration,percent,absolute,profile,split,temptarget
if (careportalPlugin == null) { public static final OptionsToShow BGCHECK = new OptionsToShow(R.id.careportal_bgcheck, R.string.careportal_bgcheck).date().bg();
careportalPlugin = new CareportalPlugin(); public static final OptionsToShow SNACKBOLUS = new OptionsToShow(R.id.careportal_snackbolus, R.string.careportal_snackbolus).date().bg().insulin().carbs().prebolus();
} public static final OptionsToShow MEALBOLUS = new OptionsToShow(R.id.careportal_mealbolus, R.string.careportal_mealbolus).date().bg().insulin().carbs().prebolus();
return careportalPlugin; public static final OptionsToShow CORRECTIONBOLUS = new OptionsToShow(R.id.careportal_correctionbolus, R.string.careportal_correctionbolus).date().bg().insulin().carbs().prebolus();
} public static final OptionsToShow CARBCORRECTION = new OptionsToShow(R.id.careportal_carbscorrection, R.string.careportal_carbscorrection).date().bg().carbs();
public static final OptionsToShow COMBOBOLUS = new OptionsToShow(R.id.careportal_combobolus, R.string.careportal_combobolus).date().bg().insulin().carbs().prebolus().duration().split();
// bg,insulin,carbs,prebolus,duration,percent,absolute,profile,split,temptarget public static final OptionsToShow ANNOUNCEMENT = new OptionsToShow(R.id.careportal_announcement, R.string.careportal_announcement).date().bg();
public static final OptionsToShow bgcheck = new OptionsToShow(R.id.careportal_bgcheck, R.string.careportal_bgcheck, true, true, true, false, false, false, false, false, false, false); public static final OptionsToShow NOTE = new OptionsToShow(R.id.careportal_note, R.string.careportal_note).date().bg().duration();
public static final OptionsToShow snackbolus = new OptionsToShow(R.id.careportal_snackbolus, R.string.careportal_snackbolus, true, true, true, true, false, false, false, false, false, false); public static final OptionsToShow QUESTION = new OptionsToShow(R.id.careportal_question, R.string.careportal_question).date().bg();
public static final OptionsToShow mealbolus = new OptionsToShow(R.id.careportal_mealbolus, R.string.careportal_mealbolus, true, true, true, true, false, false, false, false, false, false); public static final OptionsToShow EXERCISE = new OptionsToShow(R.id.careportal_exercise, R.string.careportal_exercise).date().duration();
public static final OptionsToShow correctionbolus = new OptionsToShow(R.id.careportal_correctionbolus, R.string.careportal_correctionbolus, true, true, true, true, false, false, false, false, false, false); public static final OptionsToShow SITECHANGE = new OptionsToShow(R.id.careportal_pumpsitechange, R.string.careportal_pumpsitechange).date().bg();
public static final OptionsToShow carbcorrection = new OptionsToShow(R.id.careportal_carbscorrection, R.string.careportal_carbscorrection, true, false, true, false, false, false, false, false, false, false); public static final OptionsToShow SENSORSTART = new OptionsToShow(R.id.careportal_cgmsensorstart, R.string.careportal_cgmsensorstart).date().bg();
public static final OptionsToShow combobolus = new OptionsToShow(R.id.careportal_combobolus, R.string.careportal_combobolus, true, true, true, true, true, false, false, false, true, false); public static final OptionsToShow SENSORCHANGE = new OptionsToShow(R.id.careportal_cgmsensorinsert, R.string.careportal_cgmsensorinsert).date().bg();
public static final OptionsToShow announcement = new OptionsToShow(R.id.careportal_announcement, R.string.careportal_announcement, true, false, false, false, false, false, false, false, false, false); public static final OptionsToShow INSULINCHANGE = new OptionsToShow(R.id.careportal_insulincartridgechange, R.string.careportal_insulincartridgechange).date().bg();
public static final OptionsToShow note = new OptionsToShow(R.id.careportal_note, R.string.careportal_note, true, false, false, false, true, false, false, false, false, false); public static final OptionsToShow PUMPBATTERYCHANGE = new OptionsToShow(R.id.careportal_pumpbatterychange, R.string.careportal_pumpbatterychange).date().bg();
public static final OptionsToShow question = new OptionsToShow(R.id.careportal_question, R.string.careportal_question, true, false, false, false, false, false, false, false, false, false); public static final OptionsToShow TEMPBASALSTART = new OptionsToShow(R.id.careportal_tempbasalstart, R.string.careportal_tempbasalstart).date().bg().duration().percent().absolute();
public static final OptionsToShow exercise = new OptionsToShow(R.id.careportal_exercise, R.string.careportal_exercise, false, false, false, false, true, false, false, false, false, false); public static final OptionsToShow TEMPBASALEND = new OptionsToShow(R.id.careportal_tempbasalend, R.string.careportal_tempbasalend).date().bg();
public static final OptionsToShow sitechange = new OptionsToShow(R.id.careportal_pumpsitechange, R.string.careportal_pumpsitechange, true, true, false, false, false, false, false, false, false, false); public static final OptionsToShow PROFILESWITCH = new OptionsToShow(R.id.careportal_profileswitch, R.string.careportal_profileswitch).date().duration().profile();
public static final OptionsToShow sensorstart = new OptionsToShow(R.id.careportal_cgmsensorstart, R.string.careportal_cgmsensorstart, true, false, false, false, false, false, false, false, false, false); public static final OptionsToShow PROFILESWITCHDIRECT = new OptionsToShow(R.id.careportal_profileswitch, R.string.careportal_profileswitch).duration().profile();
public static final OptionsToShow sensorchange = new OptionsToShow(R.id.careportal_cgmsensorinsert, R.string.careportal_cgmsensorinsert, true, false, false, false, false, false, false, false, false, false); public static final OptionsToShow OPENAPSOFFLINE = new OptionsToShow(R.id.careportal_openapsoffline, R.string.careportal_openapsoffline).date().duration();
public static final OptionsToShow insulinchange = new OptionsToShow(R.id.careportal_insulincartridgechange, R.string.careportal_insulincartridgechange, true, false, false, false, false, false, false, false, false, false); public static final OptionsToShow TEMPTARGET = new OptionsToShow(R.id.careportal_temporarytarget, R.string.careportal_temporarytarget).date().duration().tempTarget();
public static final OptionsToShow pumpbatterychange = new OptionsToShow(R.id.careportal_pumpbatterychange, R.string.careportal_pumpbatterychange, true, false, false, false, false, false, false, false, false, false);
public static final OptionsToShow tempbasalstart = new OptionsToShow(R.id.careportal_tempbasalstart, R.string.careportal_tempbasalstart, true, false, false, false, true, true, true, false, false, false);
public static final OptionsToShow tempbasalend = new OptionsToShow(R.id.careportal_tempbasalend, R.string.careportal_tempbasalend, true, false, false, false, false, false, false, false, false, false);
public static final OptionsToShow profileswitch = new OptionsToShow(R.id.careportal_profileswitch, R.string.careportal_profileswitch, true, false, false, false, true, false, false, true, false, false);
public static final OptionsToShow openapsoffline = new OptionsToShow(R.id.careportal_openapsoffline, R.string.careportal_openapsoffline, false, false, false, false, true, false, false, false, false, false);
public static final OptionsToShow temptarget = new OptionsToShow(R.id.careportal_temporarytarget, R.string.careportal_temporarytarget, false, false, false, false, true, false, false, false, false, true);
@Override @Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) { Bundle savedInstanceState) {
try {
View view = inflater.inflate(R.layout.careportal_fragment, container, false); View view = inflater.inflate(R.layout.careportal_fragment, container, false);
view.findViewById(R.id.careportal_bgcheck).setOnClickListener(this); view.findViewById(R.id.careportal_bgcheck).setOnClickListener(this);
@ -99,9 +91,9 @@ public class CareportalFragment extends SubscriberFragment implements View.OnCli
sage = (TextView) view.findViewById(R.id.careportal_sensorage); sage = (TextView) view.findViewById(R.id.careportal_sensorage);
pbage = (TextView) view.findViewById(R.id.careportal_pbage); pbage = (TextView) view.findViewById(R.id.careportal_pbage);
statsLayout = (View) view.findViewById(R.id.careportal_stats); statsLayout = view.findViewById(R.id.careportal_stats);
noProfileView = (View) view.findViewById(R.id.profileview_noprofile); noProfileView = view.findViewById(R.id.profileview_noprofile);
butonsLayout = (LinearLayout) view.findViewById(R.id.careportal_buttons); butonsLayout = (LinearLayout) view.findViewById(R.id.careportal_buttons);
ProfileStore profileStore = ConfigBuilderPlugin.getActiveProfileInterface().getProfile(); ProfileStore profileStore = ConfigBuilderPlugin.getActiveProfileInterface().getProfile();
@ -113,11 +105,16 @@ 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();
return view; return view;
} catch (Exception e) {
Crashlytics.logException(e);
}
return null;
} }
@Override @Override
@ -129,66 +126,66 @@ public class CareportalFragment extends SubscriberFragment implements View.OnCli
NewNSTreatmentDialog newDialog = new NewNSTreatmentDialog(); NewNSTreatmentDialog newDialog = new NewNSTreatmentDialog();
switch (id) { switch (id) {
case R.id.careportal_bgcheck: case R.id.careportal_bgcheck:
newDialog.setOptions(bgcheck, R.string.careportal_bgcheck); newDialog.setOptions(BGCHECK, R.string.careportal_bgcheck);
break; break;
case R.id.careportal_announcement: case R.id.careportal_announcement:
newDialog.setOptions(announcement, R.string.careportal_announcement); newDialog.setOptions(ANNOUNCEMENT, R.string.careportal_announcement);
break; break;
case R.id.careportal_cgmsensorinsert: case R.id.careportal_cgmsensorinsert:
newDialog.setOptions(sensorchange, R.string.careportal_cgmsensorinsert); newDialog.setOptions(SENSORCHANGE, R.string.careportal_cgmsensorinsert);
break; break;
case R.id.careportal_cgmsensorstart: case R.id.careportal_cgmsensorstart:
newDialog.setOptions(sensorstart, R.string.careportal_cgmsensorstart); newDialog.setOptions(SENSORSTART, R.string.careportal_cgmsensorstart);
break; break;
case R.id.careportal_combobolus: case R.id.careportal_combobolus:
newDialog.setOptions(combobolus, R.string.careportal_combobolus); newDialog.setOptions(COMBOBOLUS, R.string.careportal_combobolus);
break; break;
case R.id.careportal_correctionbolus: case R.id.careportal_correctionbolus:
newDialog.setOptions(correctionbolus, R.string.careportal_correctionbolus); newDialog.setOptions(CORRECTIONBOLUS, R.string.careportal_correctionbolus);
break; break;
case R.id.careportal_carbscorrection: case R.id.careportal_carbscorrection:
newDialog.setOptions(carbcorrection, R.string.careportal_carbscorrection); newDialog.setOptions(CARBCORRECTION, R.string.careportal_carbscorrection);
break; break;
case R.id.careportal_exercise: case R.id.careportal_exercise:
newDialog.setOptions(exercise, R.string.careportal_exercise); newDialog.setOptions(EXERCISE, R.string.careportal_exercise);
break; break;
case R.id.careportal_insulincartridgechange: case R.id.careportal_insulincartridgechange:
newDialog.setOptions(insulinchange, R.string.careportal_insulincartridgechange); newDialog.setOptions(INSULINCHANGE, R.string.careportal_insulincartridgechange);
break; break;
case R.id.careportal_pumpbatterychange: case R.id.careportal_pumpbatterychange:
newDialog.setOptions(pumpbatterychange, R.string.careportal_pumpbatterychange); newDialog.setOptions(PUMPBATTERYCHANGE, R.string.careportal_pumpbatterychange);
break; break;
case R.id.careportal_mealbolus: case R.id.careportal_mealbolus:
newDialog.setOptions(mealbolus, R.string.careportal_mealbolus); newDialog.setOptions(MEALBOLUS, R.string.careportal_mealbolus);
break; break;
case R.id.careportal_note: case R.id.careportal_note:
newDialog.setOptions(note, R.string.careportal_note); newDialog.setOptions(NOTE, R.string.careportal_note);
break; break;
case R.id.careportal_profileswitch: case R.id.careportal_profileswitch:
profileswitch.executeProfileSwitch = false; PROFILESWITCH.executeProfileSwitch = false;
newDialog.setOptions(profileswitch, R.string.careportal_profileswitch); newDialog.setOptions(PROFILESWITCH, R.string.careportal_profileswitch);
break; break;
case R.id.careportal_pumpsitechange: case R.id.careportal_pumpsitechange:
newDialog.setOptions(sitechange, R.string.careportal_pumpsitechange); newDialog.setOptions(SITECHANGE, R.string.careportal_pumpsitechange);
break; break;
case R.id.careportal_question: case R.id.careportal_question:
newDialog.setOptions(question, R.string.careportal_question); newDialog.setOptions(QUESTION, R.string.careportal_question);
break; break;
case R.id.careportal_snackbolus: case R.id.careportal_snackbolus:
newDialog.setOptions(snackbolus, R.string.careportal_snackbolus); newDialog.setOptions(SNACKBOLUS, R.string.careportal_snackbolus);
break; break;
case R.id.careportal_tempbasalstart: case R.id.careportal_tempbasalstart:
newDialog.setOptions(tempbasalstart, R.string.careportal_tempbasalstart); newDialog.setOptions(TEMPBASALSTART, R.string.careportal_tempbasalstart);
break; break;
case R.id.careportal_tempbasalend: case R.id.careportal_tempbasalend:
newDialog.setOptions(tempbasalend, R.string.careportal_tempbasalend); newDialog.setOptions(TEMPBASALEND, R.string.careportal_tempbasalend);
break; break;
case R.id.careportal_openapsoffline: case R.id.careportal_openapsoffline:
newDialog.setOptions(openapsoffline, R.string.careportal_openapsoffline); newDialog.setOptions(OPENAPSOFFLINE, R.string.careportal_openapsoffline);
break; break;
case R.id.careportal_temporarytarget: case R.id.careportal_temporarytarget:
temptarget.executeTempTarget = false; TEMPTARGET.executeTempTarget = false;
newDialog.setOptions(temptarget, R.string.careportal_temporarytarget); newDialog.setOptions(TEMPTARGET, R.string.careportal_temporarytarget);
break; break;
default: default:
newDialog = null; newDialog = null;

View file

@ -7,8 +7,17 @@ import info.nightscout.androidaps.interfaces.PluginBase;
public class CareportalPlugin implements PluginBase { public class CareportalPlugin implements PluginBase {
boolean fragmentEnabled = true; private boolean fragmentEnabled = true;
boolean fragmentVisible = true; private boolean fragmentVisible = true;
static CareportalPlugin careportalPlugin;
static public CareportalPlugin getPlugin() {
if (careportalPlugin == null) {
careportalPlugin = new CareportalPlugin();
}
return careportalPlugin;
}
@Override @Override
public int getType() { public int getType() {
@ -58,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
@ -71,4 +80,9 @@ public class CareportalPlugin implements PluginBase {
if (type == GENERAL) this.fragmentVisible = fragmentVisible; if (type == GENERAL) this.fragmentVisible = fragmentVisible;
} }
@Override
public int getPreferencesId() {
return R.xml.pref_careportal;
}
} }

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;
@ -14,7 +13,9 @@ import android.text.format.DateFormat;
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.AdapterView;
import android.widget.ArrayAdapter; import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.CompoundButton; import android.widget.CompoundButton;
import android.widget.EditText; import android.widget.EditText;
import android.widget.LinearLayout; import android.widget.LinearLayout;
@ -49,10 +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.ProfileCircadianPercentage.CircadianPercentageProfilePlugin; 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;
@ -73,17 +74,11 @@ public class NewNSTreatmentDialog extends DialogFragment implements View.OnClick
String units; String units;
TextView eventTypeText; TextView eventTypeText;
LinearLayout layoutBg;
LinearLayout layoutBgSource;
LinearLayout layoutInsulin;
LinearLayout layoutCarbs;
LinearLayout layoutSplit;
LinearLayout layoutDuration;
LinearLayout layoutPercent; LinearLayout layoutPercent;
LinearLayout layoutAbsolute; LinearLayout layoutAbsolute;
LinearLayout layoutCarbTime; LinearLayout layoutReuse;
LinearLayout layoutProfile;
LinearLayout layoutTempTarget;
TextView dateButton; TextView dateButton;
TextView timeButton; TextView timeButton;
@ -94,6 +89,7 @@ public class NewNSTreatmentDialog extends DialogFragment implements View.OnClick
EditText notesEdit; EditText notesEdit;
Spinner profileSpinner; Spinner profileSpinner;
Spinner reasonSpinner; Spinner reasonSpinner;
Button reuseButton;
NumberPicker editBg; NumberPicker editBg;
NumberPicker editCarbs; NumberPicker editCarbs;
@ -104,13 +100,11 @@ public class NewNSTreatmentDialog extends DialogFragment implements View.OnClick
NumberPicker editAbsolute; NumberPicker editAbsolute;
NumberPicker editCarbTime; NumberPicker editCarbTime;
NumberPicker editTemptarget; NumberPicker editTemptarget;
NumberPicker editPercentage;
NumberPicker editTimeshift;
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);
@ -118,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
@ -140,21 +129,15 @@ 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;
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);
layoutBg = (LinearLayout) view.findViewById(R.id.careportal_newnstreatment_bg_layout);
layoutBgSource = (LinearLayout) view.findViewById(R.id.careportal_newnstreatment_bgsource_layout);
layoutInsulin = (LinearLayout) view.findViewById(R.id.careportal_newnstreatment_insulin_layout);
layoutCarbs = (LinearLayout) view.findViewById(R.id.careportal_newnstreatment_carbs_layout);
layoutSplit = (LinearLayout) view.findViewById(R.id.careportal_newnstreatment_split_layout);
layoutDuration = (LinearLayout) view.findViewById(R.id.careportal_newnstreatment_duration_layout);
layoutPercent = (LinearLayout) view.findViewById(R.id.careportal_newnstreatment_percent_layout); layoutPercent = (LinearLayout) view.findViewById(R.id.careportal_newnstreatment_percent_layout);
layoutAbsolute = (LinearLayout) view.findViewById(R.id.careportal_newnstreatment_absolute_layout); layoutAbsolute = (LinearLayout) view.findViewById(R.id.careportal_newnstreatment_absolute_layout);
layoutCarbTime = (LinearLayout) view.findViewById(R.id.careportal_newnstreatment_carbtime_layout);
layoutProfile = (LinearLayout) view.findViewById(R.id.careportal_newnstreatment_profile_layout); layoutReuse = (LinearLayout) view.findViewById(R.id.careportal_newnstreatment_reuse_layout);
layoutTempTarget = (LinearLayout) view.findViewById(R.id.careportal_newnstreatment_temptarget_layout);
eventTypeText = (TextView) view.findViewById(R.id.careportal_newnstreatment_eventtype); eventTypeText = (TextView) view.findViewById(R.id.careportal_newnstreatment_eventtype);
eventTypeText.setText(event); eventTypeText.setText(event);
@ -164,6 +147,8 @@ public class NewNSTreatmentDialog extends DialogFragment implements View.OnClick
otherRadioButton = (RadioButton) view.findViewById(R.id.careportal_newnstreatment_other); otherRadioButton = (RadioButton) view.findViewById(R.id.careportal_newnstreatment_other);
profileSpinner = (Spinner) view.findViewById(R.id.careportal_newnstreatment_profile); profileSpinner = (Spinner) view.findViewById(R.id.careportal_newnstreatment_profile);
reuseButton = (Button) view.findViewById(R.id.careportal_newnstreatment_reusebutton);
notesEdit = (EditText) view.findViewById(R.id.careportal_newnstreatment_notes); notesEdit = (EditText) view.findViewById(R.id.careportal_newnstreatment_notes);
reasonSpinner = (Spinner) view.findViewById(R.id.careportal_newnstreatment_temptarget_reason); reasonSpinner = (Spinner) view.findViewById(R.id.careportal_newnstreatment_temptarget_reason);
@ -190,36 +175,64 @@ 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);
} }
final Double bg = Profile.fromMgdlToUnits(GlucoseStatus.getGlucoseStatusData() != null ? GlucoseStatus.getGlucoseStatusData().glucose : 0d, profile != null ? profile.getUnits() : Constants.MGDL);
// temp target // temp target
ArrayList<CharSequence> reasonList = new ArrayList<CharSequence>(); final ArrayList<CharSequence> reasonList = new ArrayList<CharSequence>();
reasonList.add(MainApp.sResources.getString(R.string.manual));
reasonList.add(MainApp.sResources.getString(R.string.eatingsoon)); reasonList.add(MainApp.sResources.getString(R.string.eatingsoon));
reasonList.add(MainApp.sResources.getString(R.string.activity)); reasonList.add(MainApp.sResources.getString(R.string.activity));
reasonList.add(MainApp.sResources.getString(R.string.manual));
ArrayAdapter<CharSequence> adapterReason = new ArrayAdapter<CharSequence>(getContext(), ArrayAdapter<CharSequence> adapterReason = new ArrayAdapter<CharSequence>(getContext(),
R.layout.spinner_centered, reasonList); R.layout.spinner_centered, reasonList);
reasonSpinner.setAdapter(adapterReason); reasonSpinner.setAdapter(adapterReason);
reasonSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
@Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
double defaultDuration = 0;
double defaultTarget = 0;
if (profile != null) {
defaultTarget = bg.doubleValue();
}
boolean erase = false;
if (MainApp.sResources.getString(R.string.eatingsoon).equals(reasonList.get(position))) {
defaultDuration = SP.getDouble(R.string.key_eatingsoon_duration, 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);
;
defaultTarget = SP.getDouble(R.string.key_activity_target, 0d);
;
} else {
defaultDuration = 0;
erase = true;
}
if (defaultTarget != 0 || erase) {
editTemptarget.setValue(defaultTarget);
}
if (defaultDuration != 0) {
editDuration.setValue(defaultDuration);
} else if (erase) {
editDuration.setValue(0d);
}
}
@Override
public void onNothingSelected(AdapterView<?> parent) {
}
});
// bg // bg
bgUnitsView.setText(units); bgUnitsView.setText(units);
Double bg = Profile.fromMgdlToUnits(GlucoseStatus.getGlucoseStatusData() != null ? GlucoseStatus.getGlucoseStatusData().glucose : 0d, profile != null ? profile.getUnits() : Constants.MGDL); TextWatcher bgTextWatcher = new TextWatcher() {
editBg = (NumberPicker) view.findViewById(R.id.careportal_newnstreatment_bginput);
editTemptarget = (NumberPicker) view.findViewById(R.id.careportal_newnstreatment_temptarget);
if (profile == null) {
editBg.setParams(bg, 0d, 500d, 0.1d, new DecimalFormat("0.0"), false);
editTemptarget.setParams(bg, 0d, 500d, 0.1d, new DecimalFormat("0.0"), false);
} else if (profile.getUnits().equals(Constants.MMOL)) {
editBg.setParams(bg, 0d, 30d, 0.1d, new DecimalFormat("0.0"), false);
editTemptarget.setParams(bg, 0d, 30d, 0.1d, new DecimalFormat("0.0"), false);
} else {
editBg.setParams(bg, 0d, 500d, 1d, new DecimalFormat("0"), false);
editTemptarget.setParams(bg, 0d, 500d, 1d, new DecimalFormat("0"), false);
}
editBg.addTextChangedListener(new TextWatcher() {
public void afterTextChanged(Editable s) { public void afterTextChanged(Editable s) {
} }
@ -229,8 +242,20 @@ public class NewNSTreatmentDialog extends DialogFragment implements View.OnClick
public void onTextChanged(CharSequence s, int start, int before, int count) { public void onTextChanged(CharSequence s, int start, int before, int count) {
if (sensorRadioButton.isChecked()) meterRadioButton.setChecked(true); if (sensorRadioButton.isChecked()) meterRadioButton.setChecked(true);
} }
}); };
editBg = (NumberPicker) view.findViewById(R.id.careportal_newnstreatment_bginput);
editTemptarget = (NumberPicker) view.findViewById(R.id.careportal_newnstreatment_temptarget);
if (profile == null) {
editBg.setParams(bg, 0d, 500d, 0.1d, new DecimalFormat("0.0"), false, bgTextWatcher);
editTemptarget.setParams(bg, 0d, 500d, 0.1d, new DecimalFormat("0.0"), false);
} else if (profile.getUnits().equals(Constants.MMOL)) {
editBg.setParams(bg, 0d, 30d, 0.1d, new DecimalFormat("0.0"), false, bgTextWatcher);
editTemptarget.setParams(bg, 0d, 30d, 0.1d, new DecimalFormat("0.0"), false);
} else {
editBg.setParams(bg, 0d, 500d, 1d, new DecimalFormat("0"), false, bgTextWatcher);
editTemptarget.setParams(bg, 0d, 500d, 1d, new DecimalFormat("0"), false);
}
sensorRadioButton.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { sensorRadioButton.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
@Override @Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
@ -252,10 +277,7 @@ public class NewNSTreatmentDialog extends DialogFragment implements View.OnClick
editDuration = (NumberPicker) view.findViewById(R.id.careportal_newnstreatment_durationinput); editDuration = (NumberPicker) view.findViewById(R.id.careportal_newnstreatment_durationinput);
editDuration.setParams(0d, 0d, 24 * 60d, 10d, new DecimalFormat("0"), false); editDuration.setParams(0d, 0d, 24 * 60d, 10d, new DecimalFormat("0"), false);
Integer maxPercent = MainApp.getConfigBuilder().applyBasalConstraints(Constants.basalPercentOnlyForCheckLimit); TextWatcher percentTextWatcher = new TextWatcher() {
editPercent = (NumberPicker) view.findViewById(R.id.careportal_newnstreatment_percentinput);
editPercent.setParams(0d, 0d, (double) maxPercent, 5d, new DecimalFormat("0"), true);
editPercent.addTextChangedListener(new TextWatcher() {
@Override @Override
public void afterTextChanged(Editable s) { public void afterTextChanged(Editable s) {
} }
@ -271,12 +293,13 @@ public class NewNSTreatmentDialog extends DialogFragment implements View.OnClick
layoutPercent.setVisibility(View.VISIBLE); layoutPercent.setVisibility(View.VISIBLE);
layoutAbsolute.setVisibility(View.GONE); layoutAbsolute.setVisibility(View.GONE);
} }
}); };
Double maxAbsolute = MainApp.getConfigBuilder().applyBasalConstraints(Constants.basalAbsoluteOnlyForCheckLimit); Integer maxPercent = MainApp.getConfigBuilder().applyBasalConstraints(Constants.basalPercentOnlyForCheckLimit);
editAbsolute = (NumberPicker) view.findViewById(R.id.careportal_newnstreatment_absoluteinput); editPercent = (NumberPicker) view.findViewById(R.id.careportal_newnstreatment_percentinput);
editAbsolute.setParams(0d, 0d, maxAbsolute, 0.05d, new DecimalFormat("0.00"), true); editPercent.setParams(0d, 0d, (double) maxPercent, 5d, new DecimalFormat("0"), true, percentTextWatcher);
editAbsolute.addTextChangedListener(new TextWatcher() {
TextWatcher absoluteTextWatcher = new TextWatcher() {
@Override @Override
public void afterTextChanged(Editable s) { public void afterTextChanged(Editable s) {
} }
@ -292,24 +315,53 @@ public class NewNSTreatmentDialog extends DialogFragment implements View.OnClick
layoutPercent.setVisibility(View.GONE); layoutPercent.setVisibility(View.GONE);
layoutAbsolute.setVisibility(View.VISIBLE); layoutAbsolute.setVisibility(View.VISIBLE);
} }
}); };
Double maxAbsolute = MainApp.getConfigBuilder().applyBasalConstraints(Constants.basalAbsoluteOnlyForCheckLimit);
editAbsolute = (NumberPicker) view.findViewById(R.id.careportal_newnstreatment_absoluteinput);
editAbsolute.setParams(0d, 0d, maxAbsolute, 0.05d, new DecimalFormat("0.00"), true, absoluteTextWatcher);
editCarbTime = (NumberPicker) view.findViewById(R.id.careportal_newnstreatment_carbtimeinput); editCarbTime = (NumberPicker) view.findViewById(R.id.careportal_newnstreatment_carbtimeinput);
editCarbTime.setParams(0d, -60d, 60d, 5d, new DecimalFormat("0"), false); editCarbTime.setParams(0d, -60d, 60d, 5d, new DecimalFormat("0"), false);
editPercentage = (NumberPicker) view.findViewById(R.id.careportal_newnstreatment_percentage);
editPercentage.setParams(100d, (double) Constants.CPP_MIN_PERCENTAGE, (double) Constants.CPP_MAX_PERCENTAGE, 1d, new DecimalFormat("0"), false);
showOrHide(layoutBg, options.bg); editTimeshift = (NumberPicker) view.findViewById(R.id.careportal_newnstreatment_timeshift);
showOrHide(layoutBgSource, options.bg); editTimeshift.setParams(0d, (double) Constants.CPP_MIN_TIMESHIFT, (double) Constants.CPP_MAX_TIMESHIFT, 1d, new DecimalFormat("0"), false);
showOrHide(layoutInsulin, options.insulin);
showOrHide(layoutCarbs, options.carbs); ProfileSwitch ps = MainApp.getConfigBuilder().getProfileSwitchFromHistory(System.currentTimeMillis());
showOrHide(layoutSplit, options.split); if (ps != null && ps.isCPP) {
showOrHide(layoutDuration, options.duration); final int percentage = ps.percentage;
final int timeshift = ps.timeshift;
reuseButton.setText(reuseButton.getText() + " " + percentage + "% " + timeshift + "h");
reuseButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
editPercentage.setValue((double) percentage);
editTimeshift.setValue((double) timeshift);
}
});
}
showOrHide((ViewGroup) view.findViewById(R.id.careportal_newnstreatment_eventtime_layout), options.date);
showOrHide((ViewGroup) view.findViewById(R.id.careportal_newnstreatment_bg_layout), options.bg);
showOrHide((ViewGroup) view.findViewById(R.id.careportal_newnstreatment_bgsource_layout), options.bg);
showOrHide((ViewGroup) view.findViewById(R.id.careportal_newnstreatment_insulin_layout), options.insulin);
showOrHide((ViewGroup) view.findViewById(R.id.careportal_newnstreatment_carbs_layout), options.carbs);
showOrHide((ViewGroup) view.findViewById(R.id.careportal_newnstreatment_split_layout), options.split);
showOrHide((ViewGroup) view.findViewById(R.id.careportal_newnstreatment_duration_layout), options.duration);
showOrHide(layoutPercent, options.percent); showOrHide(layoutPercent, options.percent);
showOrHide(layoutAbsolute, options.absolute); showOrHide(layoutAbsolute, options.absolute);
showOrHide(layoutCarbTime, options.prebolus); showOrHide((ViewGroup) view.findViewById(R.id.careportal_newnstreatment_carbtime_layout), options.prebolus);
showOrHide(layoutProfile, options.profile); showOrHide((ViewGroup) view.findViewById(R.id.careportal_newnstreatment_profile_layout), options.profile);
showOrHide(layoutTempTarget, options.tempTarget); 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_reuse_layout), options.profile && ps != null && ps.isCPP);
showOrHide((ViewGroup) view.findViewById(R.id.careportal_newnstreatment_temptarget_layout), options.tempTarget);
setCancelable(true);
getDialog().setCanceledOnTouchOutside(false);
return view; return view;
} }
@ -451,7 +503,7 @@ public class NewNSTreatmentDialog extends DialogFragment implements View.OnClick
allowZeroDuration = true; allowZeroDuration = true;
break; break;
} }
if (SafeParse.stringToDouble(editBg.getText()) != 0d) { if (options.bg && SafeParse.stringToDouble(editBg.getText()) != 0d) {
data.put("glucose", SafeParse.stringToDouble(editBg.getText())); data.put("glucose", SafeParse.stringToDouble(editBg.getText()));
if (meterRadioButton.isChecked()) data.put("glucoseType", "Finger"); if (meterRadioButton.isChecked()) data.put("glucoseType", "Finger");
if (sensorRadioButton.isChecked()) data.put("glucoseType", "Sensor"); if (sensorRadioButton.isChecked()) data.put("glucoseType", "Sensor");
@ -469,6 +521,10 @@ public class NewNSTreatmentDialog extends DialogFragment implements View.OnClick
data.put("absolute", SafeParse.stringToDouble(editAbsolute.getText())); data.put("absolute", SafeParse.stringToDouble(editAbsolute.getText()));
if (options.profile && profileSpinner.getSelectedItem() != null) if (options.profile && profileSpinner.getSelectedItem() != null)
data.put("profile", profileSpinner.getSelectedItem().toString()); data.put("profile", profileSpinner.getSelectedItem().toString());
if (options.profile)
data.put("percentage", SafeParse.stringToInt(editPercentage.getText()));
if (options.profile)
data.put("timeshift", SafeParse.stringToInt(editTimeshift.getText()));
if (SafeParse.stringToDouble(editCarbTime.getText()) != 0d) if (SafeParse.stringToDouble(editCarbTime.getText()) != 0d)
data.put("preBolus", SafeParse.stringToDouble(editCarbTime.getText())); data.put("preBolus", SafeParse.stringToDouble(editCarbTime.getText()));
if (!notesEdit.getText().toString().equals("")) if (!notesEdit.getText().toString().equals(""))
@ -478,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) {
@ -556,6 +612,18 @@ public class NewNSTreatmentDialog extends DialogFragment implements View.OnClick
ret += data.get("profile"); ret += data.get("profile");
ret += "\n"; ret += "\n";
} }
if (data.has("percentage")) {
ret += getString(R.string.careportal_newnstreatment_percentage_label);
ret += ": ";
ret += data.get("percentage");
ret += " %\n";
}
if (data.has("timeshift")) {
ret += getString(R.string.careportal_newnstreatment_timeshift_label);
ret += ": ";
ret += data.get("timeshift");
ret += " h\n";
}
if (data.has("targetBottom") && data.has("targetTop")) { if (data.has("targetBottom") && data.has("targetTop")) {
ret += getString(R.string.target_range); ret += getString(R.string.target_range);
ret += " "; ret += " ";
@ -594,7 +662,7 @@ public class NewNSTreatmentDialog extends DialogFragment implements View.OnClick
if (options.executeProfileSwitch) { if (options.executeProfileSwitch) {
if (data.has("profile")) { if (data.has("profile")) {
try { try {
doProfileSwitch(profileStore, data.getString("profile"), data.getInt("duration")); doProfileSwitch(profileStore, data.getString("profile"), data.getInt("duration"), data.getInt("percentage"), data.getInt("timeshift"));
} catch (JSONException e) { } catch (JSONException e) {
log.error("Unhandled exception", e); log.error("Unhandled exception", e);
} }
@ -602,10 +670,6 @@ 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() {
@Override
public void run() {
try {
TempTarget tempTarget = new TempTarget(); TempTarget tempTarget = new TempTarget();
tempTarget.date = eventTime.getTime(); tempTarget.date = eventTime.getTime();
tempTarget.durationInMinutes = data.getInt("duration"); tempTarget.durationInMinutes = data.getInt("duration");
@ -622,11 +686,6 @@ public class NewNSTreatmentDialog extends DialogFragment implements View.OnClick
MainApp.getDbHelper().createOrUpdate(tempTarget); MainApp.getDbHelper().createOrUpdate(tempTarget);
NSUpload.uploadCareportalEntryToNS(data); NSUpload.uploadCareportalEntryToNS(data);
Answers.getInstance().logCustom(new CustomEvent("TempTarget")); 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);
@ -641,10 +700,7 @@ public class NewNSTreatmentDialog extends DialogFragment implements View.OnClick
builder.show(); builder.show();
} }
public static void doProfileSwitch(final ProfileStore profileStore, final String profileName, final int duration) { public static void doProfileSwitch(final ProfileStore profileStore, final String profileName, final int duration, final int percentage, final int timeshift) {
sHandler.post(new Runnable() {
@Override
public void run() {
ProfileSwitch profileSwitch = new ProfileSwitch(); ProfileSwitch profileSwitch = new ProfileSwitch();
profileSwitch.date = System.currentTimeMillis(); profileSwitch.date = System.currentTimeMillis();
profileSwitch.source = Source.USER; profileSwitch.source = Source.USER;
@ -652,24 +708,61 @@ public class NewNSTreatmentDialog extends DialogFragment implements View.OnClick
profileSwitch.profileJson = profileStore.getSpecificProfile(profileName).getData().toString(); profileSwitch.profileJson = profileStore.getSpecificProfile(profileName).getData().toString();
profileSwitch.profilePlugin = ConfigBuilderPlugin.getActiveProfileInterface().getClass().getName(); profileSwitch.profilePlugin = ConfigBuilderPlugin.getActiveProfileInterface().getClass().getName();
profileSwitch.durationInMinutes = duration; profileSwitch.durationInMinutes = duration;
if (ConfigBuilderPlugin.getActiveProfileInterface() instanceof CircadianPercentageProfilePlugin) { profileSwitch.isCPP = percentage != 100 || timeshift != 0;
CircadianPercentageProfilePlugin cpp = (CircadianPercentageProfilePlugin) ConfigBuilderPlugin.getActiveProfileInterface(); profileSwitch.timeshift = timeshift;
profileSwitch.isCPP = true; profileSwitch.percentage = percentage;
profileSwitch.timeshift = cpp.timeshift;
profileSwitch.percentage = cpp.percentage;
}
MainApp.getConfigBuilder().addToHistoryProfileSwitch(profileSwitch); MainApp.getConfigBuilder().addToHistoryProfileSwitch(profileSwitch);
PumpInterface pump = MainApp.getConfigBuilder(); ConfigBuilderPlugin.getCommandQueue().setProfile(profileSwitch.getProfileObject(), new Callback() {
if (pump != null) { @Override
pump.setNewBasalProfile(profileStore.getSpecificProfile(profileName)); 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());
} }
}); });
Answers.getInstance().logCustom(new CustomEvent("ProfileSwitch"));
}
public static void doProfileSwitch(final int duration, final int percentage, final int timeshift) {
ProfileSwitch profileSwitch = MainApp.getConfigBuilder().getProfileSwitchFromHistory(System.currentTimeMillis());
if (profileSwitch != null) {
profileSwitch = new ProfileSwitch();
profileSwitch.date = System.currentTimeMillis();
profileSwitch.source = Source.USER;
profileSwitch.profileName = MainApp.getConfigBuilder().getProfileName(System.currentTimeMillis(), false);
profileSwitch.profileJson = MainApp.getConfigBuilder().getProfile().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
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.failedupdatebasalprofile));
i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
MainApp.instance().startActivity(i);
}
MainApp.bus().post(new EventNewBasalProfile());
}
});
Answers.getInstance().logCustom(new CustomEvent("ProfileSwitch"));
} else {
log.error("No profile switch existing");
}
} }
} }

View file

@ -7,6 +7,7 @@ package info.nightscout.androidaps.plugins.Careportal;
public class OptionsToShow { public class OptionsToShow {
public int eventType; public int eventType;
public int eventName; public int eventName;
public boolean date;
public boolean bg; public boolean bg;
public boolean insulin; public boolean insulin;
public boolean carbs; public boolean carbs;
@ -22,29 +23,63 @@ public class OptionsToShow {
public boolean executeProfileSwitch = false; public boolean executeProfileSwitch = false;
public boolean executeTempTarget = false; public boolean executeTempTarget = false;
public OptionsToShow(int eventType, public OptionsToShow(int eventType, int eventName) {
int eventName,
boolean bg,
boolean insulin,
boolean carbs,
boolean prebolus,
boolean duration,
boolean percent,
boolean absolute,
boolean profile,
boolean split,
boolean tempTarget) {
this.eventType = eventType; this.eventType = eventType;
this.eventName = eventName; this.eventName = eventName;
this.bg = bg; }
this.insulin = insulin;
this.carbs = carbs; public OptionsToShow date() {
this.prebolus = prebolus; date = true;
this.duration = duration; return this;
this.percent = percent; }
this.absolute = absolute;
this.profile = profile; public OptionsToShow bg() {
this.split = split; bg = true;
this.tempTarget = tempTarget; return this;
}
public OptionsToShow insulin() {
insulin = true;
return this;
}
public OptionsToShow carbs() {
carbs = true;
return this;
}
public OptionsToShow prebolus() {
prebolus = true;
return this;
}
public OptionsToShow duration() {
duration = true;
return this;
}
public OptionsToShow percent() {
percent = true;
return this;
}
public OptionsToShow absolute() {
absolute = true;
return this;
}
public OptionsToShow profile() {
profile = true;
return this;
}
public OptionsToShow split() {
split = true;
return this;
}
public OptionsToShow tempTarget() {
tempTarget = true;
return this;
} }
} }

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

@ -2,6 +2,7 @@ package info.nightscout.androidaps.plugins.ConfigBuilder;
import android.content.Context; import android.content.Context;
import android.content.Intent;
import android.os.Bundle; import android.os.Bundle;
import android.support.v4.app.Fragment; import android.support.v4.app.Fragment;
import android.view.LayoutInflater; import android.view.LayoutInflater;
@ -10,17 +11,20 @@ import android.view.ViewGroup;
import android.widget.ArrayAdapter; import android.widget.ArrayAdapter;
import android.widget.Button; import android.widget.Button;
import android.widget.CheckBox; import android.widget.CheckBox;
import android.widget.ImageView;
import android.widget.LinearLayout; import android.widget.LinearLayout;
import android.widget.ListAdapter; import android.widget.ListAdapter;
import android.widget.ListView; import android.widget.ListView;
import android.widget.TextView; import android.widget.TextView;
import com.crashlytics.android.Crashlytics;
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 java.util.ArrayList; import java.util.ArrayList;
import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.PreferencesActivity;
import info.nightscout.androidaps.R; import info.nightscout.androidaps.R;
import info.nightscout.androidaps.events.EventConfigBuilderChange; import info.nightscout.androidaps.events.EventConfigBuilderChange;
import info.nightscout.androidaps.events.EventRefreshGui; import info.nightscout.androidaps.events.EventRefreshGui;
@ -55,6 +59,8 @@ public class ConfigBuilderFragment extends Fragment {
TextView pumpLabel; TextView pumpLabel;
ListView loopListView; ListView loopListView;
TextView loopLabel; TextView loopLabel;
ListView treatmentsListView;
TextView treatmentsLabel;
ListView profileListView; ListView profileListView;
TextView profileLabel; TextView profileLabel;
ListView apsListView; ListView apsListView;
@ -71,6 +77,7 @@ public class ConfigBuilderFragment extends Fragment {
PluginCustomAdapter bgsourceDataAdapter = null; PluginCustomAdapter bgsourceDataAdapter = null;
PluginCustomAdapter pumpDataAdapter = null; PluginCustomAdapter pumpDataAdapter = null;
PluginCustomAdapter loopDataAdapter = null; PluginCustomAdapter loopDataAdapter = null;
PluginCustomAdapter treatmentDataAdapter = null;
PluginCustomAdapter profileDataAdapter = null; PluginCustomAdapter profileDataAdapter = null;
PluginCustomAdapter apsDataAdapter = null; PluginCustomAdapter apsDataAdapter = null;
PluginCustomAdapter constraintsDataAdapter = null; PluginCustomAdapter constraintsDataAdapter = null;
@ -79,6 +86,7 @@ public class ConfigBuilderFragment extends Fragment {
@Override @Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) { Bundle savedInstanceState) {
try {
View view = inflater.inflate(R.layout.configbuilder_fragment, container, false); View view = inflater.inflate(R.layout.configbuilder_fragment, container, false);
insulinListView = (ListView) view.findViewById(R.id.configbuilder_insulinlistview); insulinListView = (ListView) view.findViewById(R.id.configbuilder_insulinlistview);
@ -89,6 +97,8 @@ public class ConfigBuilderFragment extends Fragment {
pumpLabel = (TextView) view.findViewById(R.id.configbuilder_pumplabel); pumpLabel = (TextView) view.findViewById(R.id.configbuilder_pumplabel);
loopListView = (ListView) view.findViewById(R.id.configbuilder_looplistview); loopListView = (ListView) view.findViewById(R.id.configbuilder_looplistview);
loopLabel = (TextView) view.findViewById(R.id.configbuilder_looplabel); loopLabel = (TextView) view.findViewById(R.id.configbuilder_looplabel);
treatmentsListView = (ListView) view.findViewById(R.id.configbuilder_treatmentslistview);
treatmentsLabel = (TextView) view.findViewById(R.id.configbuilder_treatmentslabel);
profileListView = (ListView) view.findViewById(R.id.configbuilder_profilelistview); profileListView = (ListView) view.findViewById(R.id.configbuilder_profilelistview);
profileLabel = (TextView) view.findViewById(R.id.configbuilder_profilelabel); profileLabel = (TextView) view.findViewById(R.id.configbuilder_profilelabel);
apsListView = (ListView) view.findViewById(R.id.configbuilder_apslistview); apsListView = (ListView) view.findViewById(R.id.configbuilder_apslistview);
@ -120,6 +130,11 @@ public class ConfigBuilderFragment extends Fragment {
unlock.setVisibility(View.GONE); unlock.setVisibility(View.GONE);
} }
return view; return view;
} catch (Exception e) {
Crashlytics.logException(e);
}
return null;
} }
void setViews() { void setViews() {
@ -141,6 +156,11 @@ public class ConfigBuilderFragment extends Fragment {
setListViewHeightBasedOnChildren(loopListView); setListViewHeightBasedOnChildren(loopListView);
if (MainApp.getSpecificPluginsVisibleInList(PluginBase.LOOP).size() == 0) if (MainApp.getSpecificPluginsVisibleInList(PluginBase.LOOP).size() == 0)
loopLabel.setVisibility(View.GONE); loopLabel.setVisibility(View.GONE);
treatmentDataAdapter = new PluginCustomAdapter(getContext(), R.layout.configbuilder_simpleitem, MainApp.getSpecificPluginsVisibleInList(PluginBase.TREATMENT), PluginBase.TREATMENT);
treatmentsListView.setAdapter(treatmentDataAdapter);
setListViewHeightBasedOnChildren(treatmentsListView);
if (MainApp.getSpecificPluginsVisibleInList(PluginBase.TREATMENT).size() == 0)
treatmentsLabel.setVisibility(View.GONE);
profileDataAdapter = new PluginCustomAdapter(getContext(), R.layout.configbuilder_simpleitem, MainApp.getSpecificPluginsVisibleInListByInterface(ProfileInterface.class, PluginBase.PROFILE), PluginBase.PROFILE); profileDataAdapter = new PluginCustomAdapter(getContext(), R.layout.configbuilder_simpleitem, MainApp.getSpecificPluginsVisibleInListByInterface(ProfileInterface.class, PluginBase.PROFILE), PluginBase.PROFILE);
profileListView.setAdapter(profileDataAdapter); profileListView.setAdapter(profileDataAdapter);
if (MainApp.getSpecificPluginsVisibleInList(PluginBase.PROFILE).size() == 0) if (MainApp.getSpecificPluginsVisibleInList(PluginBase.PROFILE).size() == 0)
@ -177,7 +197,7 @@ public class ConfigBuilderFragment extends Fragment {
public PluginCustomAdapter(Context context, int textViewResourceId, public PluginCustomAdapter(Context context, int textViewResourceId,
ArrayList<PluginBase> pluginList, int type) { ArrayList<PluginBase> pluginList, int type) {
super(context, textViewResourceId, pluginList); super(context, textViewResourceId, pluginList);
this.pluginList = new ArrayList<PluginBase>(); this.pluginList = new ArrayList<>();
this.pluginList.addAll(pluginList); this.pluginList.addAll(pluginList);
this.type = type; this.type = type;
} }
@ -186,12 +206,14 @@ public class ConfigBuilderFragment extends Fragment {
TextView name; TextView name;
CheckBox checkboxEnabled; CheckBox checkboxEnabled;
CheckBox checkboxVisible; CheckBox checkboxVisible;
ImageView settings;
} }
@Override @Override
public View getView(int position, View view, ViewGroup parent) { public View getView(int position, View view, ViewGroup parent) {
PluginViewHolder holder = null; PluginViewHolder holder = null;
PluginBase plugin = pluginList.get(position);
if (view == null) { if (view == null) {
view = LayoutInflater.from(parent.getContext()).inflate(R.layout.configbuilder_simpleitem, null); view = LayoutInflater.from(parent.getContext()).inflate(R.layout.configbuilder_simpleitem, null);
@ -200,6 +222,13 @@ public class ConfigBuilderFragment extends Fragment {
holder.name = (TextView) view.findViewById(R.id.configbuilder_simpleitem_name); holder.name = (TextView) view.findViewById(R.id.configbuilder_simpleitem_name);
holder.checkboxEnabled = (CheckBox) view.findViewById(R.id.configbuilder_simpleitem_checkboxenabled); holder.checkboxEnabled = (CheckBox) view.findViewById(R.id.configbuilder_simpleitem_checkboxenabled);
holder.checkboxVisible = (CheckBox) view.findViewById(R.id.configbuilder_simpleitem_checkboxvisible); holder.checkboxVisible = (CheckBox) view.findViewById(R.id.configbuilder_simpleitem_checkboxvisible);
holder.settings = (ImageView) view.findViewById(R.id.configbuilder_simpleitem_settings);
if (plugin.isEnabled(type) && plugin.getPreferencesId() != -1)
holder.settings.setVisibility(View.VISIBLE);
else
holder.settings.setVisibility(View.INVISIBLE);
view.setTag(holder); view.setTag(holder);
holder.checkboxEnabled.setOnClickListener(new View.OnClickListener() { holder.checkboxEnabled.setOnClickListener(new View.OnClickListener() {
@ -227,17 +256,48 @@ public class ConfigBuilderFragment extends Fragment {
getPlugin().logPluginStatus(); getPlugin().logPluginStatus();
} }
}); });
holder.settings.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
final PluginBase plugin = (PluginBase) v.getTag();
PasswordProtection.QueryPassword(getContext(), R.string.settings_password, "settings_password", new Runnable() {
@Override
public void run() {
Intent i = new Intent(getContext(), PreferencesActivity.class);
i.putExtra("id", plugin.getPreferencesId());
startActivity(i);
}
}, null);
}
});
holder.name.setOnLongClickListener(new View.OnLongClickListener() {
@Override
public boolean onLongClick(View v) {
final PluginBase plugin = (PluginBase) v.getTag();
PasswordProtection.QueryPassword(getContext(), R.string.settings_password, "settings_password", new Runnable() {
@Override
public void run() {
Intent i = new Intent(getContext(), PreferencesActivity.class);
i.putExtra("id", plugin.getPreferencesId());
startActivity(i);
}
}, null);
return false;
}
});
} else { } else {
holder = (PluginViewHolder) view.getTag(); holder = (PluginViewHolder) view.getTag();
} }
PluginBase plugin = pluginList.get(position);
holder.name.setText(plugin.getName()); holder.name.setText(plugin.getName());
holder.checkboxEnabled.setChecked(plugin.isEnabled(type)); holder.checkboxEnabled.setChecked(plugin.isEnabled(type));
holder.checkboxVisible.setChecked(plugin.isVisibleInTabs(type)); holder.checkboxVisible.setChecked(plugin.isVisibleInTabs(type));
holder.name.setTag(plugin); holder.name.setTag(plugin);
holder.checkboxEnabled.setTag(plugin); holder.checkboxEnabled.setTag(plugin);
holder.checkboxVisible.setTag(plugin); holder.checkboxVisible.setTag(plugin);
holder.settings.setTag(plugin);
if (!plugin.canBeHidden(type)) { if (!plugin.canBeHidden(type)) {
holder.checkboxEnabled.setEnabled(false); holder.checkboxEnabled.setEnabled(false);

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
@ -146,9 +137,15 @@ public class ConfigBuilderPlugin implements PluginBase, PumpInterface, Constrain
// Always visible // Always visible
} }
@Override
public int getPreferencesId() {
return -1;
}
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() {
@ -192,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;
} }
@ -301,7 +302,7 @@ public class ConfigBuilderPlugin implements PluginBase, PumpInterface, Constrain
pluginsInCategory = MainApp.getSpecificPluginsList(PluginBase.PUMP); pluginsInCategory = MainApp.getSpecificPluginsList(PluginBase.PUMP);
activePump = (PumpInterface) getTheOneEnabledInArray(pluginsInCategory, PluginBase.PUMP); activePump = (PumpInterface) getTheOneEnabledInArray(pluginsInCategory, PluginBase.PUMP);
if (activePump == null) if (activePump == null)
activePump = VirtualPumpPlugin.getInstance(); // for NSClient build activePump = VirtualPumpPlugin.getPlugin(); // for NSClient build
if (Config.logConfigBuilder) if (Config.logConfigBuilder)
log.debug("Selected pump interface: " + ((PluginBase) activePump).getName()); log.debug("Selected pump interface: " + ((PluginBase) activePump).getName());
for (PluginBase p : pluginsInCategory) { for (PluginBase p : pluginsInCategory) {
@ -353,287 +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)
return activePump.isThisProfileSet(profile);
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()) < 0.05) { 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();
} }
} else if (isTempBasalInProgress() && Math.abs(request.rate - getTempBasalAbsoluteRateHistory()) < 0.05) { return false;
result = new PumpEnactResult(); }
result.absolute = getTempBasalAbsoluteRateHistory(); } else if (isTempBasalInProgress()
result.duration = getTempBasalFromHistory(System.currentTimeMillis()).getPlannedRemainingMinutes(); && getTempBasalRemainingMinutesFromHistory() > 5
result.enacted = false; && Math.abs(request.rate - getTempBasalAbsoluteRateHistory()) < pump.getPumpDescription().basalStep) {
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
@ -679,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) {
@ -691,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;
@ -810,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
@ -933,11 +734,19 @@ 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);
}
public String getProfileName(long time, boolean customized) {
ProfileSwitch profileSwitch = getProfileSwitchFromHistory(time); ProfileSwitch profileSwitch = getProfileSwitchFromHistory(time);
if (profileSwitch != null) { if (profileSwitch != null) {
if (profileSwitch.profileJson != null) { if (profileSwitch.profileJson != null) {
return profileSwitch.profileName; return customized ? profileSwitch.getCustomizedName() : profileSwitch.profileName;
} else { } else {
Profile profile = activeProfile.getProfile().getSpecificProfile(profileSwitch.profileName); Profile profile = activeProfile.getProfile().getSpecificProfile(profileSwitch.profileName);
if (profile != null) if (profile != null)
@ -952,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 activeProfile.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
@ -993,7 +805,7 @@ public class ConfigBuilderPlugin implements PluginBase, PumpInterface, Constrain
MainApp.bus().post(new EventNewNotification(nobasal)); MainApp.bus().post(new EventNewNotification(nobasal));
Notification notarget = new Notification(Notification.TARGET_MISSING, MainApp.sResources.getString(R.string.targetmissing), Notification.URGENT); Notification notarget = new Notification(Notification.TARGET_MISSING, MainApp.sResources.getString(R.string.targetmissing), Notification.URGENT);
MainApp.bus().post(new EventNewNotification(notarget)); MainApp.bus().post(new EventNewNotification(notarget));
return new Profile(new JSONObject("{\"dia\":\"3\",\"carbratio\":[{\"time\":\"00:00\",\"value\":\"20\"}],\"carbs_hr\":\"20\",\"delay\":\"20\",\"sens\":[{\"time\":\"00:00\",\"value\":\"20\"}],\"timezone\":\"UTC\",\"basal\":[{\"time\":\"00:00\",\"value\":\"0.1\"}],\"target_low\":[{\"time\":\"00:00\",\"value\":\"6\"}],\"target_high\":[{\"time\":\"00:00\",\"value\":\"8\"}],\"startDate\":\"1970-01-01T00:00:00.000Z\",\"units\":\"mmol\"}}")); return new Profile(new JSONObject("{\"dia\":\"3\",\"carbratio\":[{\"time\":\"00:00\",\"value\":\"20\"}],\"carbs_hr\":\"20\",\"delay\":\"20\",\"sens\":[{\"time\":\"00:00\",\"value\":\"20\"}],\"timezone\":\"UTC\",\"basal\":[{\"time\":\"00:00\",\"value\":\"0.1\"}],\"target_low\":[{\"time\":\"00:00\",\"value\":\"6\"}],\"target_high\":[{\"time\":\"00:00\",\"value\":\"8\"}],\"startDate\":\"1970-01-01T00:00:00.000Z\",\"units\":\"mmol\"}}"), 100, 0);
} catch (JSONException e) { } catch (JSONException e) {
log.error("Unhandled exception", e); log.error("Unhandled exception", e);
} }

View file

@ -20,7 +20,7 @@ public class DetailedBolusInfoStorage {
private static List<DetailedBolusInfo> store = new ArrayList<>(); private static List<DetailedBolusInfo> store = new ArrayList<>();
public static void add(DetailedBolusInfo detailedBolusInfo) { public static void add(DetailedBolusInfo detailedBolusInfo) {
log.debug("Bolus info stored: " + new Date(detailedBolusInfo.date).toLocaleString()); log.debug("Stored bolus info: " + detailedBolusInfo);
store.add(detailedBolusInfo); store.add(detailedBolusInfo);
} }
@ -29,7 +29,7 @@ public class DetailedBolusInfoStorage {
DetailedBolusInfo found = null; DetailedBolusInfo found = null;
for (int i = 0; i < store.size(); i++) { for (int i = 0; i < store.size(); i++) {
long infoTime = store.get(i).date; long infoTime = store.get(i).date;
log.debug("Existing info: " + new Date(infoTime).toLocaleString()); log.debug("Existing bolus info: " + store.get(i));
if (bolustime > infoTime - 60 * 1000 && bolustime < infoTime + 60 * 1000) { if (bolustime > infoTime - 60 * 1000 && bolustime < infoTime + 60 * 1000) {
found = store.get(i); found = store.get(i);
break; break;
@ -42,7 +42,7 @@ public class DetailedBolusInfoStorage {
for (int i = 0; i < store.size(); i++) { for (int i = 0; i < store.size(); i++) {
long infoTime = store.get(i).date; long infoTime = store.get(i).date;
if (bolustime > infoTime - 60 * 1000 && bolustime < infoTime + 60 * 1000) { if (bolustime > infoTime - 60 * 1000 && bolustime < infoTime + 60 * 1000) {
log.debug("Removing info: " + new Date(infoTime).toLocaleString()); log.debug("Removing bolus info: " + store.get(i));
store.remove(i); store.remove(i);
break; break;
} }

View file

@ -15,6 +15,8 @@ import android.widget.CheckBox;
import android.widget.LinearLayout; import android.widget.LinearLayout;
import android.widget.TextView; import android.widget.TextView;
import com.crashlytics.android.Crashlytics;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
@ -27,15 +29,6 @@ import info.nightscout.androidaps.R;
public class ObjectivesFragment extends Fragment { public class ObjectivesFragment extends Fragment {
private static Logger log = LoggerFactory.getLogger(ObjectivesFragment.class); private static Logger log = LoggerFactory.getLogger(ObjectivesFragment.class);
private static ObjectivesPlugin objectivesPlugin;
public static ObjectivesPlugin getPlugin() {
if (objectivesPlugin == null) {
objectivesPlugin = new ObjectivesPlugin();
}
return objectivesPlugin;
}
RecyclerView recyclerView; RecyclerView recyclerView;
LinearLayoutManager llm; LinearLayoutManager llm;
CheckBox enableFake; CheckBox enableFake;
@ -59,7 +52,7 @@ public class ObjectivesFragment extends Fragment {
@Override @Override
public void onBindViewHolder(ObjectiveViewHolder holder, int position) { public void onBindViewHolder(ObjectiveViewHolder holder, int position) {
ObjectivesPlugin.Objective o = objectives.get(position); ObjectivesPlugin.Objective o = objectives.get(position);
ObjectivesPlugin.RequirementResult requirementsMet = getPlugin().requirementsMet(position); ObjectivesPlugin.RequirementResult requirementsMet = ObjectivesPlugin.getPlugin().requirementsMet(position);
Context context = MainApp.instance().getApplicationContext(); Context context = MainApp.instance().getApplicationContext();
holder.position.setText(String.valueOf(position + 1)); holder.position.setText(String.valueOf(position + 1));
holder.objective.setText(o.objective); holder.objective.setText(o.objective);
@ -83,7 +76,7 @@ public class ObjectivesFragment extends Fragment {
holder.verifyButton.setOnClickListener(new View.OnClickListener() { holder.verifyButton.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) { public void onClick(View v) {
ObjectivesPlugin.Objective o = (ObjectivesPlugin.Objective) v.getTag(); ObjectivesPlugin.Objective o = (ObjectivesPlugin.Objective) v.getTag();
if (getPlugin().requirementsMet(o.num).done || enableFake.isChecked()) { if (ObjectivesPlugin.getPlugin().requirementsMet(o.num).done || enableFake.isChecked()) {
o.accomplished = new Date(); o.accomplished = new Date();
updateGUI(); updateGUI();
ObjectivesPlugin.saveProgress(); ObjectivesPlugin.saveProgress();
@ -173,6 +166,7 @@ public class ObjectivesFragment extends Fragment {
@Override @Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) { Bundle savedInstanceState) {
try {
View view = inflater.inflate(R.layout.objectives_fragment, container, false); View view = inflater.inflate(R.layout.objectives_fragment, container, false);
recyclerView = (RecyclerView) view.findViewById(R.id.objectives_recyclerview); recyclerView = (RecyclerView) view.findViewById(R.id.objectives_recyclerview);
@ -189,29 +183,35 @@ public class ObjectivesFragment extends Fragment {
}); });
reset.setOnClickListener(new View.OnClickListener() { reset.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) { public void onClick(View v) {
getPlugin().initializeData(); ObjectivesPlugin.getPlugin().initializeData();
getPlugin().saveProgress(); ObjectivesPlugin.saveProgress();
updateGUI(); updateGUI();
} }
}); });
// Add correct translations to array after app is initialized // Add correct translations to array after app is initialized
getPlugin().objectives.get(0).objective = MainApp.sResources.getString(R.string.objectives_0_objective); ObjectivesPlugin.objectives.get(0).objective = MainApp.sResources.getString(R.string.objectives_0_objective);
getPlugin().objectives.get(1).objective = MainApp.sResources.getString(R.string.objectives_1_objective); ObjectivesPlugin.objectives.get(1).objective = MainApp.sResources.getString(R.string.objectives_1_objective);
getPlugin().objectives.get(2).objective = MainApp.sResources.getString(R.string.objectives_2_objective); ObjectivesPlugin.objectives.get(2).objective = MainApp.sResources.getString(R.string.objectives_2_objective);
getPlugin().objectives.get(3).objective = MainApp.sResources.getString(R.string.objectives_3_objective); ObjectivesPlugin.objectives.get(3).objective = MainApp.sResources.getString(R.string.objectives_3_objective);
getPlugin().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);
getPlugin().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);
getPlugin().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);
getPlugin().objectives.get(0).gate = MainApp.sResources.getString(R.string.objectives_0_gate); ObjectivesPlugin.objectives.get(7).objective = MainApp.sResources.getString(R.string.objectives_7_objective);
getPlugin().objectives.get(1).gate = MainApp.sResources.getString(R.string.objectives_1_gate); ObjectivesPlugin.objectives.get(0).gate = MainApp.sResources.getString(R.string.objectives_0_gate);
getPlugin().objectives.get(2).gate = MainApp.sResources.getString(R.string.objectives_2_gate); ObjectivesPlugin.objectives.get(1).gate = MainApp.sResources.getString(R.string.objectives_1_gate);
getPlugin().objectives.get(3).gate = MainApp.sResources.getString(R.string.objectives_3_gate); ObjectivesPlugin.objectives.get(2).gate = MainApp.sResources.getString(R.string.objectives_2_gate);
getPlugin().objectives.get(4).gate = MainApp.sResources.getString(R.string.objectives_4_gate); ObjectivesPlugin.objectives.get(3).gate = MainApp.sResources.getString(R.string.objectives_3_gate);
getPlugin().objectives.get(5).gate = MainApp.sResources.getString(R.string.objectives_5_gate); ObjectivesPlugin.objectives.get(4).gate = MainApp.sResources.getString(R.string.objectives_4_gate);
ObjectivesPlugin.objectives.get(5).gate = MainApp.sResources.getString(R.string.objectives_5_gate);
updateGUI(); updateGUI();
return view; return view;
} catch (Exception e) {
Crashlytics.logException(e);
}
return null;
} }
void updateGUI() { void updateGUI() {

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;
/** /**
@ -25,11 +31,20 @@ import info.nightscout.utils.SP;
public class ObjectivesPlugin implements PluginBase, ConstraintsInterface { public class ObjectivesPlugin implements PluginBase, ConstraintsInterface {
private static Logger log = LoggerFactory.getLogger(ObjectivesPlugin.class); private static Logger log = LoggerFactory.getLogger(ObjectivesPlugin.class);
private static ObjectivesPlugin objectivesPlugin;
public static ObjectivesPlugin getPlugin() {
if (objectivesPlugin == null) {
objectivesPlugin = new ObjectivesPlugin();
}
return objectivesPlugin;
}
public static List<Objective> objectives; public static List<Objective> objectives;
boolean fragmentVisible = true; private boolean fragmentVisible = true;
public ObjectivesPlugin() { private ObjectivesPlugin() {
initializeData(); initializeData();
loadProgress(); loadProgress();
MainApp.bus().register(this); MainApp.bus().register(this);
@ -63,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
@ -95,7 +110,12 @@ public class ObjectivesPlugin implements PluginBase, ConstraintsInterface {
if (type == CONSTRAINTS) this.fragmentVisible = fragmentVisible; if (type == CONSTRAINTS) this.fragmentVisible = fragmentVisible;
} }
public class Objective { @Override
public int getPreferencesId() {
return -1;
}
class Objective {
Integer num; Integer num;
String objective; String objective;
String gate; String gate;
@ -118,13 +138,13 @@ public class ObjectivesPlugin implements PluginBase, ConstraintsInterface {
public static boolean pumpStatusIsAvailableInNS = false; public static boolean pumpStatusIsAvailableInNS = false;
// Objective 1 // Objective 1
public static Integer manualEnacts = 0; public static Integer manualEnacts = 0;
public static final Integer manualEnactsNeeded = 20; private static final Integer manualEnactsNeeded = 20;
public class RequirementResult { class RequirementResult {
boolean done = false; boolean done = false;
String comment = ""; String comment = "";
public RequirementResult(boolean done, String comment) { RequirementResult(boolean done, String comment) {
this.done = done; this.done = done;
this.comment = comment; this.comment = comment;
} }
@ -135,24 +155,47 @@ public class ObjectivesPlugin implements PluginBase, ConstraintsInterface {
else return "---"; else return "---";
} }
public 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, "");
} }
} }
public void initializeData() { void initializeData() {
bgIsAvailableInNS = false; bgIsAvailableInNS = false;
pumpStatusIsAvailableInNS = false; pumpStatusIsAvailableInNS = false;
manualEnacts = 0; manualEnacts = 0;
@ -198,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)));
} }
@ -220,7 +269,7 @@ public class ObjectivesPlugin implements PluginBase, ConstraintsInterface {
} }
} }
void loadProgress() { private void loadProgress() {
for (int num = 0; num < objectives.size(); num++) { for (int num = 0; num < objectives.size(); num++) {
Objective o = objectives.get(num); Objective o = objectives.get(num);
try { try {
@ -246,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
@ -264,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;
@ -86,9 +87,14 @@ public class SafetyPlugin implements PluginBase, ConstraintsInterface {
public void setFragmentVisible(int type, boolean fragmentVisible) { public void setFragmentVisible(int type, boolean fragmentVisible) {
} }
@Override
public int getPreferencesId() {
return R.xml.pref_safety;
}
@Override @Override
public boolean isLoopEnabled() { public boolean isLoopEnabled() {
return MainApp.getConfigBuilder().getPumpDescription().isTempBasalCapable; return ConfigBuilderPlugin.getActivePump().getPumpDescription().isTempBasalCapable;
} }
/** /**
@ -110,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

@ -0,0 +1,314 @@
package info.nightscout.androidaps.plugins.Food;
import android.app.Activity;
import android.content.DialogInterface;
import android.graphics.Paint;
import android.os.Bundle;
import android.support.v7.app.AlertDialog;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.text.Editable;
import android.text.TextWatcher;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.TextView;
import com.crashlytics.android.Crashlytics;
import com.squareup.otto.Subscribe;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.R;
import info.nightscout.androidaps.db.Food;
import info.nightscout.androidaps.events.EventFoodDatabaseChanged;
import info.nightscout.androidaps.plugins.Common.SubscriberFragment;
import info.nightscout.utils.NSUpload;
import info.nightscout.utils.SpinnerHelper;
/**
* Created by mike on 16.10.2017.
*/
public class FoodFragment extends SubscriberFragment {
private static Logger log = LoggerFactory.getLogger(FoodFragment.class);
EditText filter;
ImageView clearFilter;
SpinnerHelper category;
SpinnerHelper subcategory;
RecyclerView recyclerView;
List<Food> unfiltered;
List<Food> filtered;
ArrayList<CharSequence> categories;
ArrayList<CharSequence> subcategories;
final String EMPTY = MainApp.sResources.getString(R.string.none);
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
try {
View view = inflater.inflate(R.layout.food_fragment, container, false);
filter = (EditText) view.findViewById(R.id.food_filter);
clearFilter = (ImageView) view.findViewById(R.id.food_clearfilter);
category = new SpinnerHelper(view.findViewById(R.id.food_category));
subcategory = new SpinnerHelper(view.findViewById(R.id.food_subcategory));
recyclerView = (RecyclerView) view.findViewById(R.id.food_recyclerview);
recyclerView.setHasFixedSize(true);
LinearLayoutManager llm = new LinearLayoutManager(view.getContext());
recyclerView.setLayoutManager(llm);
clearFilter.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
filter.setText("");
category.setSelection(0);
subcategory.setSelection(0);
filterData();
}
});
category.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
@Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
fillSubcategories();
filterData();
}
@Override
public void onNothingSelected(AdapterView<?> parent) {
fillSubcategories();
filterData();
}
});
subcategory.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
@Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
filterData();
}
@Override
public void onNothingSelected(AdapterView<?> parent) {
filterData();
}
});
filter.addTextChangedListener(new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
filterData();
}
@Override
public void afterTextChanged(Editable s) {
}
});
RecyclerViewAdapter adapter = new RecyclerViewAdapter(MainApp.getDbHelper().foodHelper.getFoodData());
recyclerView.setAdapter(adapter);
loadData();
fillCategories();
fillSubcategories();
filterData();
return view;
} catch (Exception e) {
Crashlytics.logException(e);
}
return null;
}
@Subscribe
@SuppressWarnings("unused")
public void onStatusEvent(final EventFoodDatabaseChanged ev) {
loadData();
filterData();
}
void loadData() {
unfiltered = MainApp.getDbHelper().foodHelper.getFoodData();
}
void fillCategories() {
categories = new ArrayList<>();
for (Food f : unfiltered) {
if (f.category != null && !f.category.equals(""))
categories.add(f.category);
}
// make it unique
categories = new ArrayList<>(new HashSet<>(categories));
categories.add(0, MainApp.sResources.getString(R.string.none));
ArrayAdapter<CharSequence> adapterCategories = new ArrayAdapter<>(getContext(),
R.layout.spinner_centered, categories);
category.setAdapter(adapterCategories);
}
void fillSubcategories() {
String categoryFilter = category.getSelectedItem().toString();
subcategories = new ArrayList<>();
if (!categoryFilter.equals(EMPTY)) {
for (Food f : unfiltered) {
if (f.category != null && f.category.equals(categoryFilter))
if (f.subcategory != null && !f.subcategory.equals(""))
subcategories.add(f.subcategory);
}
}
// make it unique
subcategories = new ArrayList<>(new HashSet<>(subcategories));
subcategories.add(0, MainApp.sResources.getString(R.string.none));
ArrayAdapter<CharSequence> adapterSubcategories = new ArrayAdapter<>(getContext(),
R.layout.spinner_centered, subcategories);
subcategory.setAdapter(adapterSubcategories);
}
void filterData() {
String textFilter = filter.getText().toString();
String categoryFilter = category.getSelectedItem().toString();
String subcategoryFilter = subcategory.getSelectedItem().toString();
filtered = new ArrayList<>();
for (Food f : unfiltered) {
if (f.name == null || f.category == null || f.subcategory == null)
continue;
if (!subcategoryFilter.equals(EMPTY) && !f.subcategory.equals(subcategoryFilter))
continue;
if (!categoryFilter.equals(EMPTY) && !f.category.equals(categoryFilter))
continue;
if (!textFilter.equals("") && !f.name.toLowerCase().contains(textFilter.toLowerCase()))
continue;
filtered.add(f);
}
updateGUI();
}
@Override
protected void updateGUI() {
Activity activity = getActivity();
if (activity != null)
activity.runOnUiThread(new Runnable() {
@Override
public void run() {
recyclerView.swapAdapter(new FoodFragment.RecyclerViewAdapter(filtered), true);
}
});
}
public class RecyclerViewAdapter extends RecyclerView.Adapter<RecyclerViewAdapter.FoodsViewHolder> {
List<Food> foodList;
RecyclerViewAdapter(List<Food> foodList) {
this.foodList = foodList;
}
@Override
public FoodsViewHolder onCreateViewHolder(ViewGroup viewGroup, int viewType) {
View v = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.food_item, viewGroup, false);
return new FoodsViewHolder(v);
}
@Override
public void onBindViewHolder(FoodsViewHolder holder, int position) {
Food food = foodList.get(position);
holder.ns.setVisibility(food._id != null ? View.VISIBLE : View.GONE);
holder.name.setText(food.name);
holder.portion.setText(food.portion + food.units);
holder.carbs.setText(food.carbs + MainApp.sResources.getString(R.string.shortgramm));
holder.fat.setText(MainApp.sResources.getString(R.string.shortfat) + ": " + food.fat + MainApp.sResources.getString(R.string.shortgramm));
if (food.fat == 0)
holder.fat.setVisibility(View.INVISIBLE);
holder.protein.setText(MainApp.sResources.getString(R.string.shortprotein) + ": " + food.protein + MainApp.sResources.getString(R.string.shortgramm));
if (food.protein == 0)
holder.protein.setVisibility(View.INVISIBLE);
holder.energy.setText(MainApp.sResources.getString(R.string.shortenergy) + ": " + food.energy + MainApp.sResources.getString(R.string.shortkilojoul));
if (food.energy == 0)
holder.energy.setVisibility(View.INVISIBLE);
holder.remove.setTag(food);
}
@Override
public int getItemCount() {
return foodList.size();
}
class FoodsViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
TextView name;
TextView portion;
TextView carbs;
TextView fat;
TextView protein;
TextView energy;
TextView ns;
TextView remove;
FoodsViewHolder(View itemView) {
super(itemView);
name = (TextView) itemView.findViewById(R.id.food_name);
portion = (TextView) itemView.findViewById(R.id.food_portion);
carbs = (TextView) itemView.findViewById(R.id.food_carbs);
fat = (TextView) itemView.findViewById(R.id.food_fat);
protein = (TextView) itemView.findViewById(R.id.food_protein);
energy = (TextView) itemView.findViewById(R.id.food_energy);
ns = (TextView) itemView.findViewById(R.id.ns_sign);
remove = (TextView) itemView.findViewById(R.id.food_remove);
remove.setOnClickListener(this);
remove.setPaintFlags(remove.getPaintFlags() | Paint.UNDERLINE_TEXT_FLAG);
}
@Override
public void onClick(View v) {
final Food food = (Food) v.getTag();
switch (v.getId()) {
case R.id.food_remove:
AlertDialog.Builder builder = new AlertDialog.Builder(getContext());
builder.setTitle(MainApp.sResources.getString(R.string.confirmation));
builder.setMessage(MainApp.sResources.getString(R.string.removerecord) + "\n" + food.name);
builder.setPositiveButton(MainApp.sResources.getString(R.string.ok), new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
final String _id = food._id;
if (_id != null && !_id.equals("")) {
NSUpload.removeFoodFromNS(_id);
}
MainApp.getDbHelper().foodHelper.delete(food);
}
});
builder.setNegativeButton(MainApp.sResources.getString(R.string.cancel), null);
builder.show();
break;
}
}
}
}
}

View file

@ -0,0 +1,85 @@
package info.nightscout.androidaps.plugins.Food;
import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.R;
import info.nightscout.androidaps.interfaces.PluginBase;
/**
* Created by mike on 05.08.2016.
*/
public class FoodPlugin implements PluginBase {
private boolean fragmentEnabled = true;
private boolean fragmentVisible = false;
private static FoodPlugin plugin = null;
public static FoodPlugin getPlugin() {
if (plugin == null)
plugin = new FoodPlugin();
return plugin;
}
@Override
public String getFragmentClass() {
return FoodFragment.class.getName();
}
@Override
public int getType() {
return PluginBase.GENERAL;
}
@Override
public String getName() {
return MainApp.instance().getString(R.string.food);
}
@Override
public String getNameShort() {
// use long name as fallback (not visible in tabs)
return getName();
}
@Override
public boolean isEnabled(int type) {
return type == GENERAL && fragmentEnabled;
}
@Override
public boolean isVisibleInTabs(int type) {
return type == GENERAL && fragmentVisible;
}
@Override
public boolean canBeHidden(int type) {
return true;
}
@Override
public boolean hasFragment() {
return true;
}
@Override
public boolean showInList(int type) {
return true;
}
@Override
public void setFragmentEnabled(int type, boolean fragmentEnabled) {
if (type == GENERAL) this.fragmentEnabled = fragmentEnabled;
}
@Override
public void setFragmentVisible(int type, boolean fragmentVisible) {
if (type == GENERAL) this.fragmentVisible = fragmentVisible;
}
@Override
public int getPreferencesId() {
return -1;
}
}

View file

@ -14,8 +14,8 @@ import info.nightscout.androidaps.interfaces.PluginBase;
public class InsulinFastactingPlugin implements PluginBase, InsulinInterface { public class InsulinFastactingPlugin implements PluginBase, InsulinInterface {
private static boolean fragmentEnabled = true; private boolean fragmentEnabled = true;
private static boolean fragmentVisible = false; private boolean fragmentVisible = false;
private static InsulinFastactingPlugin plugin = null; private static InsulinFastactingPlugin plugin = null;
@ -80,6 +80,11 @@ public class InsulinFastactingPlugin implements PluginBase, InsulinInterface {
if (type == INSULIN) this.fragmentVisible = fragmentVisible; if (type == INSULIN) this.fragmentVisible = fragmentVisible;
} }
@Override
public int getPreferencesId() {
return -1;
}
// Insulin interface // Insulin interface
@Override @Override
public int getId() { public int getId() {
@ -102,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

@ -14,8 +14,8 @@ import info.nightscout.androidaps.interfaces.PluginBase;
public class InsulinFastactingProlongedPlugin implements PluginBase, InsulinInterface { public class InsulinFastactingProlongedPlugin implements PluginBase, InsulinInterface {
private static boolean fragmentEnabled = false; private boolean fragmentEnabled = false;
private static boolean fragmentVisible = false; private boolean fragmentVisible = false;
private static InsulinFastactingProlongedPlugin plugin = null; private static InsulinFastactingProlongedPlugin plugin = null;
@ -80,6 +80,11 @@ public class InsulinFastactingProlongedPlugin implements PluginBase, InsulinInte
if (type == INSULIN) this.fragmentVisible = fragmentVisible; if (type == INSULIN) this.fragmentVisible = fragmentVisible;
} }
@Override
public int getPreferencesId() {
return -1;
}
// Insulin interface // Insulin interface
@Override @Override
public int getId() { public int getId() {
@ -102,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

@ -7,8 +7,11 @@ import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.widget.TextView; import android.widget.TextView;
import com.crashlytics.android.Crashlytics;
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.ConfigBuilder.ConfigBuilderPlugin;
/** /**
* Created by mike on 17.04.2017. * Created by mike on 17.04.2017.
@ -22,6 +25,7 @@ public class InsulinFragment extends Fragment {
public View onCreateView(LayoutInflater inflater, ViewGroup container, public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) { Bundle savedInstanceState) {
try {
View view = inflater.inflate(R.layout.insulin_fragment, container, false); View view = inflater.inflate(R.layout.insulin_fragment, container, false);
insulinName = (TextView) view.findViewById(R.id.insulin_name); insulinName = (TextView) view.findViewById(R.id.insulin_name);
@ -32,6 +36,11 @@ public class InsulinFragment extends Fragment {
updateGUI(); updateGUI();
return view; return view;
} catch (Exception e) {
Crashlytics.logException(e);
}
return null;
} }
@Override @Override
@ -41,10 +50,10 @@ public class InsulinFragment extends Fragment {
} }
private void updateGUI() { private void updateGUI() {
insulinName.setText(MainApp.getConfigBuilder().getActiveInsulin().getFriendlyName()); insulinName.setText(ConfigBuilderPlugin.getActiveInsulin().getFriendlyName());
insulinComment.setText(MainApp.getConfigBuilder().getActiveInsulin().getComment()); insulinComment.setText(ConfigBuilderPlugin.getActiveInsulin().getComment());
insulinDia.setText(MainApp.sResources.getText(R.string.dia) + " " + Double.toString(MainApp.getConfigBuilder().getActiveInsulin().getDia()) + "h"); insulinDia.setText(MainApp.sResources.getText(R.string.dia) + " " + Double.toString(ConfigBuilderPlugin.getActiveInsulin().getDia()) + "h");
insulinGraph.show(MainApp.getConfigBuilder().getActiveInsulin()); insulinGraph.show(ConfigBuilderPlugin.getActiveInsulin());
} }
} }

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() : Constants.defaultDIA; 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

@ -10,8 +10,8 @@ import info.nightscout.utils.SP;
public class InsulinOrefFreePeakPlugin extends InsulinOrefBasePlugin { public class InsulinOrefFreePeakPlugin extends InsulinOrefBasePlugin {
private static boolean fragmentEnabled = false; private boolean fragmentEnabled = false;
private static boolean fragmentVisible = false; private boolean fragmentVisible = false;
private static InsulinOrefFreePeakPlugin plugin = null; private static InsulinOrefFreePeakPlugin plugin = null;
@ -68,6 +68,11 @@ public class InsulinOrefFreePeakPlugin extends InsulinOrefBasePlugin {
if (type == INSULIN) this.fragmentVisible = fragmentVisible; if (type == INSULIN) this.fragmentVisible = fragmentVisible;
} }
@Override
public int getPreferencesId() {
return R.xml.pref_insulinoreffreepeak;
}
@Override @Override
int getPeak() { int getPeak() {
return SP.getInt(R.string.key_insulin_oref_peak, DEFAULT_PEAK); return SP.getInt(R.string.key_insulin_oref_peak, DEFAULT_PEAK);

View file

@ -9,8 +9,8 @@ import info.nightscout.androidaps.R;
public class InsulinOrefRapidActingPlugin extends InsulinOrefBasePlugin { public class InsulinOrefRapidActingPlugin extends InsulinOrefBasePlugin {
private static boolean fragmentEnabled = false; private boolean fragmentEnabled = false;
private static boolean fragmentVisible = false; private boolean fragmentVisible = false;
private static InsulinOrefRapidActingPlugin plugin = null; private static InsulinOrefRapidActingPlugin plugin = null;
@ -67,6 +67,11 @@ public class InsulinOrefRapidActingPlugin extends InsulinOrefBasePlugin {
if (type == INSULIN) this.fragmentVisible = fragmentVisible; if (type == INSULIN) this.fragmentVisible = fragmentVisible;
} }
@Override
public int getPreferencesId() {
return -1;
}
@Override @Override
int getPeak() { int getPeak() {
return PEAK; return PEAK;

View file

@ -9,8 +9,8 @@ import info.nightscout.androidaps.R;
public class InsulinOrefUltraRapidActingPlugin extends InsulinOrefBasePlugin { public class InsulinOrefUltraRapidActingPlugin extends InsulinOrefBasePlugin {
private static boolean fragmentEnabled = false; private boolean fragmentEnabled = false;
private static boolean fragmentVisible = false; private boolean fragmentVisible = false;
private static InsulinOrefUltraRapidActingPlugin plugin = null; private static InsulinOrefUltraRapidActingPlugin plugin = null;
@ -67,6 +67,11 @@ public class InsulinOrefUltraRapidActingPlugin extends InsulinOrefBasePlugin {
if (type == INSULIN) this.fragmentVisible = fragmentVisible; if (type == INSULIN) this.fragmentVisible = fragmentVisible;
} }
@Override
public int getPreferencesId() {
return -1;
}
@Override @Override
int getPeak() { int getPeak() {
return PEAK; return PEAK;

View file

@ -13,6 +13,7 @@ import info.nightscout.androidaps.data.Profile;
import info.nightscout.androidaps.db.Treatment; import info.nightscout.androidaps.db.Treatment;
import info.nightscout.androidaps.interfaces.PluginBase; import info.nightscout.androidaps.interfaces.PluginBase;
import info.nightscout.androidaps.plugins.SensitivityAAPS.SensitivityAAPSPlugin; import info.nightscout.androidaps.plugins.SensitivityAAPS.SensitivityAAPSPlugin;
import info.nightscout.androidaps.plugins.SensitivityWeightedAverage.SensitivityWeightedAveragePlugin;
import info.nightscout.utils.SP; import info.nightscout.utils.SP;
/** /**
@ -32,7 +33,7 @@ public class AutosensData {
time = t.date; time = t.date;
carbs = t.carbs; carbs = t.carbs;
remaining = t.carbs; remaining = t.carbs;
if (MainApp.getSpecificPlugin(SensitivityAAPSPlugin.class) != null && MainApp.getSpecificPlugin(SensitivityAAPSPlugin.class).isEnabled(PluginBase.SENSITIVITY)) { if (SensitivityAAPSPlugin.getPlugin().isEnabled(PluginBase.SENSITIVITY) || SensitivityWeightedAveragePlugin.getPlugin().isEnabled(PluginBase.SENSITIVITY)) {
double maxAbsorptionHours = SP.getDouble(R.string.key_absorption_maxtime, 4d); double maxAbsorptionHours = SP.getDouble(R.string.key_absorption_maxtime, 4d);
Profile profile = MainApp.getConfigBuilder().getProfile(t.date); Profile profile = MainApp.getConfigBuilder().getProfile(t.date);
double sens = Profile.toMgdl(profile.getIsf(t.date), profile.getUnits()); double sens = Profile.toMgdl(profile.getIsf(t.date), profile.getUnits());

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;
@ -126,14 +124,13 @@ public class IobCobCalculatorPlugin implements PluginBase {
} }
@Override
public int getPreferencesId() {
return -1;
}
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
@ -170,15 +167,10 @@ public class IobCobCalculatorPlugin implements PluginBase {
return rouded; return rouded;
} }
private void loadBgData() { void loadBgData() {
//log.debug("Locking loadBgData");
synchronized (dataLock) {
onNewProfile(null);
bgReadings = MainApp.getDbHelper().getBgreadingsDataFromTime((long) (System.currentTimeMillis() - 60 * 60 * 1000L * (24 + dia)), false); bgReadings = MainApp.getDbHelper().getBgreadingsDataFromTime((long) (System.currentTimeMillis() - 60 * 60 * 1000L * (24 + dia)), false);
log.debug("BG data loaded. Size: " + bgReadings.size()); log.debug("BG data loaded. Size: " + bgReadings.size());
} }
//log.debug("Releasing loadBgData");
}
private boolean isAbout5minData() { private boolean isAbout5minData() {
synchronized (dataLock) { synchronized (dataLock) {
@ -204,7 +196,7 @@ public class IobCobCalculatorPlugin implements PluginBase {
} }
} }
private void createBucketedData() { void createBucketedData() {
if (isAbout5minData()) if (isAbout5minData())
createBucketedData5min(); createBucketedData5min();
else else
@ -236,7 +228,6 @@ 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;
@ -266,12 +257,9 @@ public class IobCobCalculatorPlugin implements PluginBase {
} }
} }
}
public void createBucketedData5min() { public void createBucketedData5min() {
//log.debug("Locking createBucketedData");
synchronized (dataLock) {
if (bgReadings == null || bgReadings.size() < 3) { if (bgReadings == null || bgReadings.size() < 3) {
bucketed_data = null; bucketed_data = null;
return; return;
@ -332,123 +320,6 @@ public class IobCobCalculatorPlugin implements PluginBase {
} }
log.debug("Bucketed data created. Size: " + bucketed_data.size()); log.debug("Bucketed data created. Size: " + bucketed_data.size());
} }
//log.debug("Releasing createBucketedData");
}
private void calculateSensitivityData() {
if (MainApp.getConfigBuilder() == null)
return; // app still initializing
if (MainApp.getConfigBuilder().getProfile() == null)
return; // app still initializing
//log.debug("Locking calculateSensitivityData");
long oldestTimeWithData = oldestDataAvailable();
synchronized (dataLock) {
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;
}
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("Releasing calculateSensitivityData");
}
public static long oldestDataAvailable() { public static long oldestDataAvailable() {
long now = System.currentTimeMillis(); long now = System.currentTimeMillis();
@ -535,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;
} }
@ -542,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;
} }
} }
@ -576,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);
} }
@ -589,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
@ -611,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);
@ -695,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

@ -1,8 +1,10 @@
package info.nightscout.androidaps.plugins.IobCobCalculator.events; package info.nightscout.androidaps.plugins.IobCobCalculator.events;
import info.nightscout.androidaps.events.EventLoop;
/** /**
* Created by mike on 30.04.2017. * Created by mike on 30.04.2017.
*/ */
public class EventAutosensCalculationFinished { public class EventAutosensCalculationFinished extends EventLoop {
} }

View file

@ -1,10 +1,12 @@
package info.nightscout.androidaps.plugins.IobCobCalculator.events; package info.nightscout.androidaps.plugins.IobCobCalculator.events;
import info.nightscout.androidaps.events.Event;
/** /**
* Created by mike on 26.04.2017. * Created by mike on 26.04.2017.
*/ */
public class EventNewHistoryData { public class EventNewHistoryData extends Event {
public long time = 0; public long time = 0;
public EventNewHistoryData(long time) { public EventNewHistoryData(long time) {

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

@ -9,6 +9,7 @@ import android.view.ViewGroup;
import android.widget.Button; import android.widget.Button;
import android.widget.TextView; import android.widget.TextView;
import com.crashlytics.android.Crashlytics;
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;
@ -25,15 +26,6 @@ import info.nightscout.androidaps.plugins.Loop.events.EventLoopUpdateGui;
public class LoopFragment extends SubscriberFragment implements View.OnClickListener { public class LoopFragment extends SubscriberFragment implements View.OnClickListener {
private static Logger log = LoggerFactory.getLogger(LoopFragment.class); private static Logger log = LoggerFactory.getLogger(LoopFragment.class);
private static LoopPlugin loopPlugin;
public static LoopPlugin getPlugin() {
if (loopPlugin == null){
loopPlugin = new LoopPlugin();
}
return loopPlugin;
}
Button runNowButton; Button runNowButton;
TextView lastRunView; TextView lastRunView;
TextView lastEnactView; TextView lastEnactView;
@ -46,6 +38,7 @@ public class LoopFragment extends SubscriberFragment implements View.OnClickList
@Override @Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) { Bundle savedInstanceState) {
try {
View view = inflater.inflate(R.layout.loop_fragment, container, false); View view = inflater.inflate(R.layout.loop_fragment, container, false);
lastRunView = (TextView) view.findViewById(R.id.loop_lastrun); lastRunView = (TextView) view.findViewById(R.id.loop_lastrun);
@ -59,6 +52,11 @@ public class LoopFragment extends SubscriberFragment implements View.OnClickList
updateGUI(); updateGUI();
return view; return view;
} catch (Exception e) {
Crashlytics.logException(e);
}
return null;
} }
@Override @Override
@ -69,7 +67,7 @@ public class LoopFragment extends SubscriberFragment implements View.OnClickList
Thread thread = new Thread(new Runnable() { Thread thread = new Thread(new Runnable() {
@Override @Override
public void run() { public void run() {
getPlugin().invoke("Loop button", true); LoopPlugin.getPlugin().invoke("Loop button", true);
} }
}); });
thread.start(); thread.start();
@ -105,13 +103,13 @@ public class LoopFragment extends SubscriberFragment implements View.OnClickList
activity.runOnUiThread(new Runnable() { activity.runOnUiThread(new Runnable() {
@Override @Override
public void run() { public void run() {
if (getPlugin().lastRun != null) { if (LoopPlugin.lastRun != null) {
requestView.setText(getPlugin().lastRun.request != null ? getPlugin().lastRun.request.toSpanned() : ""); requestView.setText(LoopPlugin.lastRun.request != null ? LoopPlugin.lastRun.request.toSpanned() : "");
constraintsProcessedView.setText(getPlugin().lastRun.constraintsProcessed != null ? getPlugin().lastRun.constraintsProcessed.toSpanned() : ""); constraintsProcessedView.setText(LoopPlugin.lastRun.constraintsProcessed != null ? LoopPlugin.lastRun.constraintsProcessed.toSpanned() : "");
setByPumpView.setText(getPlugin().lastRun.setByPump != null ? getPlugin().lastRun.setByPump.toSpanned() : ""); setByPumpView.setText(LoopPlugin.lastRun.setByPump != null ? LoopPlugin.lastRun.setByPump.toSpanned() : "");
sourceView.setText(getPlugin().lastRun.source != null ? getPlugin().lastRun.source : ""); sourceView.setText(LoopPlugin.lastRun.source != null ? LoopPlugin.lastRun.source : "");
lastRunView.setText(getPlugin().lastRun.lastAPSRun != null && getPlugin().lastRun.lastAPSRun.getTime() != 0 ? getPlugin().lastRun.lastAPSRun.toLocaleString() : ""); lastRunView.setText(LoopPlugin.lastRun.lastAPSRun != null && LoopPlugin.lastRun.lastAPSRun.getTime() != 0 ? LoopPlugin.lastRun.lastAPSRun.toLocaleString() : "");
lastEnactView.setText(getPlugin().lastRun.lastEnact != null && getPlugin().lastRun.lastEnact.getTime() != 0 ? getPlugin().lastRun.lastEnact.toLocaleString() : ""); lastEnactView.setText(LoopPlugin.lastRun.lastEnact != null && LoopPlugin.lastRun.lastEnact.getTime() != 0 ? LoopPlugin.lastRun.lastEnact.toLocaleString() : "");
} }
} }
}); });

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.
@ -46,14 +43,21 @@ import info.nightscout.utils.SafeParse;
public class LoopPlugin implements PluginBase { public class LoopPlugin implements PluginBase {
private static Logger log = LoggerFactory.getLogger(LoopPlugin.class); private static Logger log = LoggerFactory.getLogger(LoopPlugin.class);
private static Handler sHandler; private static LoopPlugin loopPlugin;
private static HandlerThread sHandlerThread;
public static LoopPlugin getPlugin() {
if (loopPlugin == null) {
loopPlugin = new LoopPlugin();
}
return loopPlugin;
}
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;
@ -68,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
@ -106,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
@ -139,6 +141,11 @@ public class LoopPlugin implements PluginBase {
if (type == LOOP) this.fragmentVisible = fragmentVisible; if (type == LOOP) this.fragmentVisible = fragmentVisible;
} }
@Override
public int getPreferencesId() {
return R.xml.pref_closedmode;
}
@Subscribe @Subscribe
public void onStatusEvent(final EventTreatmentChange ev) { public void onStatusEvent(final EventTreatmentChange ev) {
invoke("EventTreatmentChange", true); invoke("EventTreatmentChange", true);
@ -156,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,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)
@ -218,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();
@ -268,6 +291,20 @@ public class LoopPlugin implements PluginBase {
lastRun.source = ((PluginBase) usedAPS).getName(); lastRun.source = ((PluginBase) usedAPS).getName();
lastRun.setByPump = null; lastRun.setByPump = null;
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 (constraintsInterface.isClosedModeEnabled()) {
if (result.changeRequested) { if (result.changeRequested) {
final PumpEnactResult waiting = new PumpEnactResult(); final PumpEnactResult waiting = new PumpEnactResult();
@ -275,13 +312,12 @@ public class LoopPlugin implements PluginBase {
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;
@ -329,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");

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