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:
- platform-tools
- tools
- build-tools-25.0.2
- build-tools-27.0.2
- android-23
- extra-google-m2repository
- extra-android-m2repository
- extra-google-google_play_services
before_install:
- yes | sdkmanager "platforms;android-27"
script:
# 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)
[![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 {
repositories {
maven { url 'https://maven.fabric.io/public' }
jcenter()
}
dependencies {
classpath 'io.fabric.tools:gradle:1.+'
classpath 'com.dicedmelon.gradle:jacoco-android:0.1.2'
}
}
apply plugin: 'com.android.application'
apply plugin: 'io.fabric'
apply plugin: "com.android.application"
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 {
maven { url 'https://maven.fabric.io/public' }
@ -36,29 +48,45 @@ def generateGitBuild = { ->
}
android {
compileSdkVersion 23
buildToolsVersion "25.0.2"
compileSdkVersion 27
buildToolsVersion "${supportLibraryVersion}"
defaultConfig {
applicationId "info.nightscout.androidaps"
minSdkVersion 21
targetSdkVersion 23
multiDexEnabled true
versionCode 1500
version "1.53"
version "1.58"
buildConfigField "String", "VERSION", '"' + version + '"'
buildConfigField "String", "BUILDVERSION", generateGitBuild()
ndk {
moduleName "BleCommandUtil"
}
}
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 'ExtraTranslation'
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
debug {
testCoverageEnabled true
}
}
productFlavors {
flavorDimensions "standard", "wear"
flavorDimensions "standard"
full {
dimension "standard"
resValue "string", "app_name", "AndroidAPS"
@ -70,6 +98,8 @@ android {
buildConfigField "boolean", "PUMPDRIVERS", "true"
buildConfigField "boolean", "NSCLIENTOLNY", "false"
buildConfigField "boolean", "CLOSEDLOOP", "true"
buildConfigField "boolean", "G5UPLOADER", "false"
buildConfigField "boolean", "PUMPCONTROL", "false"
}
openloop {
dimension "standard"
@ -82,6 +112,8 @@ android {
buildConfigField "boolean", "PUMPDRIVERS", "true"
buildConfigField "boolean", "NSCLIENTOLNY", "false"
buildConfigField "boolean", "CLOSEDLOOP", "false"
buildConfigField "boolean", "G5UPLOADER", "false"
buildConfigField "boolean", "PUMPCONTROL", "false"
}
pumpcontrol {
dimension "standard"
@ -94,6 +126,8 @@ android {
buildConfigField "boolean", "PUMPDRIVERS", "true"
buildConfigField "boolean", "NSCLIENTOLNY", "false"
buildConfigField "boolean", "CLOSEDLOOP", "false"
buildConfigField "boolean", "G5UPLOADER", "false"
buildConfigField "boolean", "PUMPCONTROL", "true"
}
nsclient {
dimension "standard"
@ -106,22 +140,22 @@ android {
buildConfigField "boolean", "PUMPDRIVERS", "false"
buildConfigField "boolean", "NSCLIENTOLNY", "true"
buildConfigField "boolean", "CLOSEDLOOP", "false"
buildConfigField "boolean", "G5UPLOADER", "false"
buildConfigField "boolean", "PUMPCONTROL", "false"
}
wear {
dimension "wear"
buildConfigField "boolean", "WEAR", "true"
buildConfigField "boolean", "WEAR_CONTROL", "false"
}
wearcontrol {
dimension "wear"
buildConfigField "boolean", "WEAR", "true"
buildConfigField "boolean", "WEAR_CONTROL", "true"
}
nowear {
dimension "wear"
buildConfigField "boolean", "WEAR", "false"
buildConfigField "boolean", "WEAR_CONTROL", "false"
g5uploader {
dimension "standard"
resValue "string", "app_name", "NSClient"
versionName version + "-nsclient"
manifestPlaceholders = [
appIcon: "@mipmap/yellowowl"
]
buildConfigField "boolean", "APS", "false"
buildConfigField "boolean", "PUMPDRIVERS", "false"
buildConfigField "boolean", "NSCLIENTOLNY", "false"
buildConfigField "boolean", "CLOSEDLOOP", "false"
buildConfigField "boolean", "G5UPLOADER", "true"
buildConfigField "boolean", "PUMPCONTROL", "false"
}
}
}
@ -136,51 +170,61 @@ allprojects {
}
dependencies {
wearWearApp project(path: ':wear', configuration: 'restrictedRelease')
wearcontrolWearApp project(path: ':wear', configuration: 'fullRelease')
wearApp project(':wear')
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;
}
compile('com.crashlytics.sdk.android:answers:1.3.12@aar') {
compile("com.crashlytics.sdk.android:answers:1.3.12@aar") {
transitive = true;
}
compile 'com.android.support:appcompat-v7:23.4.0'
compile 'com.android.support:support-v4:23.4.0'
compile 'com.android.support:cardview-v7:23.4.0'
compile 'com.android.support:recyclerview-v7:23.4.0'
compile 'com.android.support:gridlayout-v7:23.4.0'
compile "com.android.support:design:23.4.0"
compile "com.android.support:percent:23.4.0"
compile 'com.wdullaer:materialdatetimepicker:2.3.0'
compile 'com.squareup:otto:1.3.7'
compile 'com.j256.ormlite:ormlite-core:4.46'
compile 'com.j256.ormlite:ormlite-android:4.46'
compile('com.github.tony19:logback-android-classic:1.1.1-6') {
exclude group: 'com.google.android', module: 'android'
compile "com.android.support:appcompat-v7:${supportLibraryVersion}"
compile "com.android.support:support-v4:${supportLibraryVersion}"
compile "com.android.support:cardview-v7:${supportLibraryVersion}"
compile "com.android.support:recyclerview-v7:${supportLibraryVersion}"
compile "com.android.support:gridlayout-v7:${supportLibraryVersion}"
compile "com.android.support:design:${supportLibraryVersion}"
compile "com.android.support:percent:${supportLibraryVersion}"
compile "com.wdullaer:materialdatetimepicker:2.3.0"
compile "com.squareup:otto:1.3.7"
compile "com.j256.ormlite:ormlite-core:${ormLiteVersion}"
compile "com.j256.ormlite:ormlite-android:${ormLiteVersion}"
compile("com.github.tony19:logback-android-classic:1.1.1-6") {
exclude group: "com.google.android", module: "android"
}
compile 'org.slf4j:slf4j-api:1.7.12'
compile 'com.jjoe64:graphview:4.0.1'
compile 'com.eclipsesource.j2v8:j2v8:3.1.6@aar'
compile 'com.joanzapata.iconify:android-iconify-fontawesome:2.1.1'
compile 'com.google.android.gms:play-services-wearable:7.5.0'
compile 'junit:junit:4.12'
testCompile 'org.json:json:20140107'
testCompile 'org.mockito:mockito-core:2.7.22'
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 "org.apache.commons:commons-lang3:3.6"
compile "org.slf4j:slf4j-api:1.7.12"
compile "com.jjoe64:graphview:4.0.1"
compile "com.joanzapata.iconify:android-iconify-fontawesome:2.1.1"
compile "com.google.android.gms:play-services-wearable:7.5.0"
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
exclude group: 'org.json', module: 'json'
exclude group: "org.json", module: "json"
}
compile 'com.google.code.gson:gson:2.7'
compile 'com.google.guava:guava:20.0'
compile "com.google.code.gson:gson:2.7"
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.ACCESS_NETWORK_STATE" />
<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" />
@ -41,6 +42,9 @@
<activity
android:name=".plugins.Overview.Dialogs.BolusProgressHelperActivity"
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=".plugins.PumpDanaR.activities.DanaRHistoryActivity" />
<activity android:name=".plugins.PumpDanaR.activities.DanaRStatsActivity" />
@ -50,6 +54,13 @@
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</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
android:name=".receivers.DataReceiver"
@ -64,6 +75,8 @@
<action android:name="com.eveningoutpost.dexdrip.NS_EMULATOR" />
<!-- Receiver from glimp -->
<action android:name="it.ct.glicemia.ACTION_GLUCOSE_MEASURED" />
<!-- Receiver from DexcomG5 -->
<action android:name="com.dexcom.cgm.DATA" />
</intent-filter>
</receiver>
<!-- Receiver keepalive, scheduled every 30 min -->
@ -113,6 +126,10 @@
android:name=".plugins.PumpDanaRv2.services.DanaRv2ExecutionService"
android:enabled="true"
android:exported="false" />
<service
android:name=".plugins.PumpDanaRS.services.DanaRSService"
android:enabled="true"
android:exported="true"></service>
<service
android:name=".plugins.Wear.wearintegration.WatchUpdaterService"
android:exported="true">
@ -128,6 +145,9 @@
android:name=".Services.AlarmSoundService"
android:enabled="true"
android:exported="true" />
<service
android:name=".plugins.Overview.notifications.DismissNotificationService"
android:exported="false"></service>
<meta-data
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>
</rollingPolicy>
<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>
</appender>
@ -24,7 +24,7 @@
<pattern>%logger{0}</pattern>
</tagEncoder>
<encoder>
<pattern>[%thread] %-5level [%file:%line]: %msg%n</pattern>
<pattern>[%thread] %-5level [%class:%line]: %msg%n</pattern>
</encoder>
</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.
*/
public class Config {
public static int SUPPORTEDNSVERSION = 1000; // 0.10.00
public static int SUPPORTEDNSVERSION = 1002; // 0.10.00
// MAIN FUCTIONALITY
public static final boolean APS = BuildConfig.APS;
// 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 G5UPLOADER = BuildConfig.G5UPLOADER;
public static final boolean PUMPCONTROL = BuildConfig.PUMPCONTROL;
public static final boolean DANAR = true && BuildConfig.PUMPDRIVERS;
public static final boolean DANARv2 = true && BuildConfig.PUMPDRIVERS;
public static final boolean DANAR = BuildConfig.PUMPDRIVERS;
public static final boolean ACTION = !BuildConfig.NSCLIENTOLNY;
public static final boolean VIRTUALPUMP = !BuildConfig.NSCLIENTOLNY;
public static final boolean MDI = !BuildConfig.NSCLIENTOLNY;
public static final boolean OTHERPROFILES = !BuildConfig.NSCLIENTOLNY;
public static final boolean SAFETY = !BuildConfig.NSCLIENTOLNY;
public static final boolean ACTION = !BuildConfig.NSCLIENTOLNY && !BuildConfig.G5UPLOADER;
public static final boolean VIRTUALPUMP = !BuildConfig.NSCLIENTOLNY && !BuildConfig.G5UPLOADER;
public static final boolean MDI = !BuildConfig.NSCLIENTOLNY && !BuildConfig.G5UPLOADER;
public static final boolean OTHERPROFILES = !BuildConfig.NSCLIENTOLNY && !BuildConfig.G5UPLOADER;
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 logFunctionCalls = true;
public static final boolean logIncommingData = true;
@ -40,10 +35,11 @@ public class Config {
public static final boolean logNSUpload = true;
public static final boolean logPumpActions = 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
public static final boolean logDanaBTComm = true;
public static final boolean logDanaMessageDetail = true;
public static boolean logDanaMessageDetail = true;
public static final boolean logDanaSerialEngine = true;
}

View file

@ -32,6 +32,8 @@ public class Constants {
// Circadian Percentage Profile
public static final int CPP_MIN_PERCENTAGE = 50;
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
// 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
public static final int SMALL_WIDTH = 320;
public static final int SMALL_HEIGHT = 320;
public static final int SMALL_HEIGHT = 480;
//Autosens
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_SMS = 0x2;
static final int CASE_LOCATION = 0x3;
private boolean askForSMS = false;
private boolean askForLocation = true;
ImageButton menuButton;
@ -80,7 +82,7 @@ public class MainActivity extends AppCompatActivity implements View.OnClickListe
Manifest.permission.WRITE_EXTERNAL_STORAGE}, CASE_STORAGE);
}
askForBatteryOptimizationPermission();
checkUpgradeToProfileTarget();
doMigrations();
if (Config.logFunctionCalls)
log.debug("onCreate");
@ -110,12 +112,16 @@ public class MainActivity extends AppCompatActivity implements View.OnClickListe
runOnUiThread(new Runnable() {
@Override
public void run() {
recreate();
try { // activity may be destroyed
setUpTabs(true);
} catch (IllegalStateException e) {
log.error("Unhandled exception", e);
if(ev.recreate) {
recreate();
}else {
try { // activity may be destroyed
setUpTabs(true);
} catch (IllegalStateException e) {
log.error("Unhandled exception", e);
}
}
boolean lockScreen = BuildConfig.NSCLIENTOLNY && SP.getBoolean("lockscreen", false);
if (lockScreen)
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
boolean oldKeyExists = SP.contains("openapsma_min_bg");
if (oldKeyExists) {
@ -202,6 +221,7 @@ public class MainActivity extends AppCompatActivity implements View.OnClickListe
protected void onResume() {
super.onResume();
askForSMSPermissions();
askForLocationPermissions();
}
@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) {
boolean test = false;
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.show();
break;
case CASE_LOCATION:
case CASE_SMS:
break;
}
@ -321,6 +353,7 @@ public class MainActivity extends AppCompatActivity implements View.OnClickListe
@Override
public void run() {
Intent i = new Intent(v.getContext(), PreferencesActivity.class);
i.putExtra("id", -1);
startActivity(i);
}
}, null);
@ -353,7 +386,7 @@ public class MainActivity extends AppCompatActivity implements View.OnClickListe
case R.id.nav_about:
AlertDialog.Builder builder = new AlertDialog.Builder(v.getContext());
builder.setTitle(getString(R.string.app_name) + " " + BuildConfig.VERSION);
if (Config.NSCLIENT)
if (Config.NSCLIENT|| Config.G5UPLOADER)
builder.setIcon(R.mipmap.yellowowl);
else
builder.setIcon(R.mipmap.blueowl);

View file

@ -1,7 +1,6 @@
package info.nightscout.androidaps;
import android.app.Application;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.res.Resources;
import android.os.SystemClock;
@ -13,8 +12,11 @@ import com.crashlytics.android.answers.Answers;
import com.crashlytics.android.answers.CustomEvent;
import com.j256.ormlite.android.apptools.OpenHelperManager;
import com.squareup.otto.Bus;
import com.squareup.otto.LoggingBus;
import com.squareup.otto.ThreadEnforcer;
import net.danlew.android.joda.JodaTimeAndroid;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -24,48 +26,47 @@ import info.nightscout.androidaps.Services.Intents;
import info.nightscout.androidaps.db.DatabaseHelper;
import info.nightscout.androidaps.interfaces.InsulinInterface;
import info.nightscout.androidaps.interfaces.PluginBase;
import info.nightscout.androidaps.interfaces.PumpInterface;
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.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.Food.FoodPlugin;
import info.nightscout.androidaps.plugins.Insulin.InsulinFastactingPlugin;
import info.nightscout.androidaps.plugins.Insulin.InsulinFastactingProlongedPlugin;
import info.nightscout.androidaps.plugins.Insulin.InsulinOrefFreePeakPlugin;
import info.nightscout.androidaps.plugins.Insulin.InsulinOrefRapidActingPlugin;
import info.nightscout.androidaps.plugins.Insulin.InsulinOrefUltraRapidActingPlugin;
import info.nightscout.androidaps.plugins.IobCobCalculator.IobCobCalculatorPlugin;
import info.nightscout.androidaps.plugins.Loop.LoopFragment;
import info.nightscout.androidaps.plugins.NSClientInternal.NSClientInternalFragment;
import info.nightscout.androidaps.plugins.Loop.LoopPlugin;
import info.nightscout.androidaps.plugins.NSClientInternal.NSClientInternalPlugin;
import info.nightscout.androidaps.plugins.NSClientInternal.receivers.AckAlarmReceiver;
import info.nightscout.androidaps.plugins.OpenAPSAMA.OpenAPSAMAFragment;
import info.nightscout.androidaps.plugins.OpenAPSMA.OpenAPSMAFragment;
import info.nightscout.androidaps.plugins.Overview.OverviewFragment;
import info.nightscout.androidaps.plugins.OpenAPSAMA.OpenAPSAMAPlugin;
import info.nightscout.androidaps.plugins.OpenAPSMA.OpenAPSMAPlugin;
import info.nightscout.androidaps.plugins.Overview.OverviewPlugin;
import info.nightscout.androidaps.plugins.Persistentnotification.PersistentNotificationPlugin;
import info.nightscout.androidaps.plugins.ProfileCircadianPercentage.CircadianPercentageProfileFragment;
import info.nightscout.androidaps.plugins.ProfileLocal.LocalProfileFragment;
import info.nightscout.androidaps.plugins.ProfileNS.NSProfileFragment;
import info.nightscout.androidaps.plugins.ProfileSimple.SimpleProfileFragment;
import info.nightscout.androidaps.plugins.ProfileLocal.LocalProfilePlugin;
import info.nightscout.androidaps.plugins.ProfileNS.NSProfilePlugin;
import info.nightscout.androidaps.plugins.ProfileSimple.SimpleProfilePlugin;
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.services.DanaRKoreanExecutionService;
import info.nightscout.androidaps.plugins.PumpDanaRS.DanaRSPlugin;
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.PumpVirtual.VirtualPumpPlugin;
import info.nightscout.androidaps.plugins.SensitivityAAPS.SensitivityAAPSPlugin;
import info.nightscout.androidaps.plugins.SensitivityOref0.SensitivityOref0Plugin;
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.SourceMM640g.SourceMM640gPlugin;
import info.nightscout.androidaps.plugins.SourceNSClient.SourceNSClientPlugin;
import info.nightscout.androidaps.plugins.SourceXdrip.SourceXdripPlugin;
import info.nightscout.androidaps.plugins.Treatments.TreatmentsFragment;
import info.nightscout.androidaps.plugins.Wear.WearFragment;
import info.nightscout.androidaps.plugins.Treatments.TreatmentsPlugin;
import info.nightscout.androidaps.plugins.Wear.WearPlugin;
import info.nightscout.androidaps.plugins.XDripStatusline.StatuslinePlugin;
import info.nightscout.androidaps.receivers.DataReceiver;
import info.nightscout.androidaps.receivers.KeepAliveReceiver;
@ -97,11 +98,13 @@ public class MainApp extends Application {
super.onCreate();
Fabric.with(this, new Crashlytics());
Fabric.with(this, new Answers());
JodaTimeAndroid.init(this);
Crashlytics.setString("BUILDVERSION", BuildConfig.BUILDVERSION);
log.info("Version: " + BuildConfig.VERSION_NAME);
log.info("BuildVersion: " + BuildConfig.BUILDVERSION);
sBus = new Bus(ThreadEnforcer.ANY);
sBus = Config.logEvents ? new LoggingBus(ThreadEnforcer.ANY) : new Bus(ThreadEnforcer.ANY);
sInstance = this;
sResources = getResources();
@ -110,7 +113,7 @@ public class MainApp extends Application {
if (pluginsList == null) {
pluginsList = new ArrayList<>();
// Register all tabs in app here
pluginsList.add(OverviewFragment.getPlugin());
pluginsList.add(OverviewPlugin.getPlugin());
pluginsList.add(IobCobCalculatorPlugin.getPlugin());
if (Config.ACTION) pluginsList.add(ActionsFragment.getPlugin());
pluginsList.add(InsulinFastactingPlugin.getPlugin());
@ -123,58 +126,64 @@ public class MainApp extends Application {
pluginsList.add(SensitivityWeightedAveragePlugin.getPlugin());
if (Config.DANAR) pluginsList.add(DanaRPlugin.getPlugin());
if (Config.DANAR) pluginsList.add(DanaRKoreanPlugin.getPlugin());
if (Config.DANARv2) pluginsList.add(DanaRv2Plugin.getPlugin());
pluginsList.add(CareportalFragment.getPlugin());
if (Config.DANAR) pluginsList.add(DanaRv2Plugin.getPlugin());
if (Config.DANAR) pluginsList.add(DanaRSPlugin.getPlugin());
pluginsList.add(CareportalPlugin.getPlugin());
if (Config.MDI) pluginsList.add(MDIPlugin.getPlugin());
if (Config.VIRTUALPUMP) pluginsList.add(VirtualPumpPlugin.getInstance());
if (Config.LOOPENABLED) pluginsList.add(LoopFragment.getPlugin());
if (Config.OPENAPSENABLED) pluginsList.add(OpenAPSMAFragment.getPlugin());
if (Config.OPENAPSENABLED) pluginsList.add(OpenAPSAMAFragment.getPlugin());
pluginsList.add(NSProfileFragment.getPlugin());
if (Config.OTHERPROFILES) pluginsList.add(SimpleProfileFragment.getPlugin());
if (Config.OTHERPROFILES) pluginsList.add(LocalProfileFragment.getPlugin());
if (Config.VIRTUALPUMP) pluginsList.add(VirtualPumpPlugin.getPlugin());
if (Config.APS) pluginsList.add(LoopPlugin.getPlugin());
if (Config.APS) pluginsList.add(OpenAPSMAPlugin.getPlugin());
if (Config.APS) pluginsList.add(OpenAPSAMAPlugin.getPlugin());
pluginsList.add(NSProfilePlugin.getPlugin());
if (Config.OTHERPROFILES) pluginsList.add(SimpleProfilePlugin.getPlugin());
if (Config.OTHERPROFILES) pluginsList.add(LocalProfilePlugin.getPlugin());
if (Config.OTHERPROFILES)
pluginsList.add(CircadianPercentageProfileFragment.getPlugin());
pluginsList.add(TreatmentsFragment.getPlugin());
pluginsList.add(TreatmentsPlugin.getPlugin());
if (Config.SAFETY) pluginsList.add(SafetyPlugin.getPlugin());
if (Config.APS) pluginsList.add(ObjectivesFragment.getPlugin());
if (!Config.NSCLIENT)
if (Config.APS) pluginsList.add(ObjectivesPlugin.getPlugin());
if (!Config.NSCLIENT && !Config.G5UPLOADER)
pluginsList.add(SourceXdripPlugin.getPlugin());
pluginsList.add(SourceNSClientPlugin.getPlugin());
if (!Config.NSCLIENT)
if (!Config.G5UPLOADER)
pluginsList.add(SourceNSClientPlugin.getPlugin());
if (!Config.NSCLIENT && !Config.G5UPLOADER)
pluginsList.add(SourceMM640gPlugin.getPlugin());
if (!Config.NSCLIENT)
if (!Config.NSCLIENT && !Config.G5UPLOADER)
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(StatuslinePlugin.getPlugin(this));
pluginsList.add(WearPlugin.initPlugin(this));
pluginsList.add(StatuslinePlugin.initPlugin(this));
pluginsList.add(new PersistentNotificationPlugin(this));
pluginsList.add(NSClientInternalFragment.getPlugin());
pluginsList.add(NSClientInternalPlugin.getPlugin());
pluginsList.add(sConfigBuilder = ConfigBuilderFragment.getPlugin());
MainApp.getConfigBuilder().initialize();
}
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"));
else
Answers.getInstance().logCustom(new CustomEvent("AppStart"));
Answers.getInstance().logCustom(new CustomEvent("AppStart-OpenLoop"));
startKeepAliveService();
Thread t = new Thread(new Runnable() {
new Thread(new Runnable() {
@Override
public void run() {
SystemClock.sleep(5000);
PumpInterface pump = MainApp.getConfigBuilder();
if (pump != null)
pump.refreshDataFromPump("Initialization");
ConfigBuilderPlugin.getCommandQueue().readStatus("Initialization", null);
startKeepAliveService();
}
});
t.start();
}).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_CHANGED_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_PROFILE));
lbm.registerReceiver(dataReceiver, new IntentFilter(Intents.ACTION_NEW_STATUS));
@ -203,11 +215,6 @@ public class MainApp extends Application {
private void startKeepAliveService() {
if (keepAliveReceiver == null) {
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);
}
}
@ -215,13 +222,21 @@ public class MainApp extends Application {
public void stopKeepAliveService() {
if (keepAliveReceiver != null)
keepAliveReceiver.cancelAlarm(this);
KeepAliveReceiver.cancelAlarm(this);
}
public static Bus bus() {
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() {
return sInstance;
}

View file

@ -1,5 +1,6 @@
package info.nightscout.androidaps;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.preference.EditTextPreference;
@ -15,17 +16,23 @@ import android.text.TextUtils;
import info.nightscout.androidaps.events.EventPreferenceChange;
import info.nightscout.androidaps.events.EventRefreshGui;
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.PumpDanaR.BluetoothDevicePreference;
import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPlugin;
import info.nightscout.androidaps.plugins.PumpDanaRKorean.DanaRKoreanPlugin;
import info.nightscout.androidaps.plugins.Loop.LoopPlugin;
import info.nightscout.androidaps.plugins.NSClientInternal.NSClientInternalPlugin;
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.PumpVirtual.VirtualPumpPlugin;
import info.nightscout.androidaps.plugins.SensitivityAAPS.SensitivityAAPSPlugin;
import info.nightscout.androidaps.plugins.SensitivityOref0.SensitivityOref0Plugin;
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.XDripStatusline.StatuslinePlugin;
import info.nightscout.utils.LocaleHelper;
@ -39,6 +46,9 @@ public class PreferencesActivity extends PreferenceActivity implements SharedPre
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
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();
PreferenceManager.getDefaultSharedPreferences(this).registerOnSharedPreferenceChangeListener(this);
}
@ -49,8 +59,9 @@ public class PreferencesActivity extends PreferenceActivity implements SharedPre
if (key.equals("language")) {
String lang = sharedPreferences.getString("language", "en");
LocaleHelper.setLocale(getApplicationContext(), lang);
recreate();
MainApp.bus().post(new EventRefreshGui());
MainApp.bus().post(new EventRefreshGui(true));
//recreate() does not update language so better close settings
finish();
}
if (key.equals("short_tabtitles")) {
MainApp.bus().post(new EventRefreshGui());
@ -62,7 +73,7 @@ public class PreferencesActivity extends PreferenceActivity implements SharedPre
}
private static void updatePrefSummary(Preference pref) {
if (pref instanceof ListPreference || pref instanceof BluetoothDevicePreference) {
if (pref instanceof ListPreference) {
ListPreference listPref = (ListPreference) pref;
pref.setSummary(listPref.getEntry());
}
@ -70,17 +81,14 @@ public class PreferencesActivity extends PreferenceActivity implements SharedPre
EditTextPreference editTextPref = (EditTextPreference) pref;
if (pref.getKey().contains("password") || pref.getKey().contains("secret")) {
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("")) {
((EditTextPreference) pref).setDialogMessage(editTextPref.getDialogMessage());
pref.setSummary(editTextPref.getText());
}
else if(pref.getKey().contains("smscommunicator_allowednumbers") && TextUtils.isEmpty(editTextPref.getText().toString().trim())){
} else if (pref.getKey().contains("smscommunicator_allowednumbers") && TextUtils.isEmpty(editTextPref.getText().trim())) {
pref.setSummary(MainApp.sResources.getString(R.string.smscommunicator_allowednumbers_summary));
}
}
if (pref instanceof MultiSelectListPreference) {
EditTextPreference editTextPref = (EditTextPreference) pref;
pref.setSummary(editTextPref.getText());
}
}
@ -96,85 +104,94 @@ public class PreferencesActivity extends PreferenceActivity implements SharedPre
}
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
public void onCreate(final Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (Config.ALLPREFERENCES) {
addPreferencesFromResource(R.xml.pref_password);
}
addPreferencesFromResource(R.xml.pref_age);
addPreferencesFromResource(R.xml.pref_language);
if (Config.ALLPREFERENCES) {
addPreferencesFromResource(R.xml.pref_quickwizard);
}
addPreferencesFromResource(R.xml.pref_careportal);
if (Config.ALLPREFERENCES) {
addPreferencesFromResource(R.xml.pref_treatments);
}
if (Config.APS)
addPreferencesFromResource(R.xml.pref_closedmode);
if (Config.OPENAPSENABLED) {
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);
}
if (Config.DANAR) {
DanaRPlugin danaRPlugin = MainApp.getSpecificPlugin(DanaRPlugin.class);
DanaRKoreanPlugin danaRKoreanPlugin = MainApp.getSpecificPlugin(DanaRKoreanPlugin.class);
DanaRv2Plugin danaRv2Plugin = MainApp.getSpecificPlugin(DanaRv2Plugin.class);
if (danaRPlugin.isEnabled(PluginBase.PUMP) || danaRKoreanPlugin.isEnabled(PluginBase.PUMP)) {
addPreferencesFromResource(R.xml.pref_danar);
}
if (danaRv2Plugin != null && danaRv2Plugin.isEnabled(PluginBase.PUMP)) {
addPreferencesFromResource(R.xml.pref_danarv2);
}
if (danaRPlugin.isEnabled(PluginBase.PROFILE) || danaRKoreanPlugin.isEnabled(PluginBase.PROFILE) || danaRv2Plugin != null && danaRv2Plugin.isEnabled(PluginBase.PROFILE)) {
addPreferencesFromResource(R.xml.pref_danarprofile);
}
}
VirtualPumpPlugin virtualPumpPlugin = MainApp.getSpecificPlugin(VirtualPumpPlugin.class);
if (virtualPumpPlugin != null && virtualPumpPlugin.isEnabled(PluginBase.PUMP)) {
addPreferencesFromResource(R.xml.pref_virtualpump);
}
InsulinOrefFreePeakPlugin insulinOrefFreePeakPlugin = MainApp.getSpecificPlugin(InsulinOrefFreePeakPlugin.class);
if(insulinOrefFreePeakPlugin.isEnabled(PluginBase.INSULIN)){
addPreferencesFromResource(R.xml.pref_insulinoreffreepeak);
if (savedInstanceState != null && savedInstanceState.containsKey("id")) {
id = savedInstanceState.getInt("id");
}
NSClientInternalPlugin nsClientInternalPlugin = MainApp.getSpecificPlugin(NSClientInternalPlugin.class);
if (nsClientInternalPlugin != null && nsClientInternalPlugin.isEnabled(PluginBase.GENERAL)) {
addPreferencesFromResource(R.xml.pref_nsclientinternal);
}
if (Config.SMSCOMMUNICATORENABLED)
addPreferencesFromResource(R.xml.pref_smscommunicator);
if (Config.ALLPREFERENCES) {
addPreferencesFromResource(R.xml.pref_others);
}
addPreferencesFromResource(R.xml.pref_advanced);
if (Config.WEAR) {
WearPlugin wearPlugin = MainApp.getSpecificPlugin(WearPlugin.class);
if (wearPlugin != null && wearPlugin.isEnabled(PluginBase.GENERAL)) {
addPreferencesFromResource(R.xml.pref_wear);
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_age);
addPreferencesFromResource(R.xml.pref_language);
StatuslinePlugin statuslinePlugin = MainApp.getSpecificPlugin(StatuslinePlugin.class);
if (statuslinePlugin != null && statuslinePlugin.isEnabled(PluginBase.GENERAL)) {
addPreferencesFromResource(R.xml.pref_xdripstatus);
if (!Config.NSCLIENT && !Config.G5UPLOADER) {
addPreferencesFromResource(R.xml.pref_quickwizard);
}
addPreferencesFromResourceIfEnabled(SourceDexcomG5Plugin.getPlugin(), PluginBase.BGSOURCE);
addPreferencesFromResourceIfEnabled(CareportalPlugin.getPlugin(), PluginBase.GENERAL);
addPreferencesFromResourceIfEnabled(SafetyPlugin.getPlugin(), PluginBase.CONSTRAINTS);
if (Config.APS) {
addPreferencesFromResourceIfEnabled(LoopPlugin.getPlugin(), PluginBase.LOOP);
addPreferencesFromResourceIfEnabled(OpenAPSMAPlugin.getPlugin(), PluginBase.APS);
addPreferencesFromResourceIfEnabled(OpenAPSAMAPlugin.getPlugin(), PluginBase.APS);
}
addPreferencesFromResourceIfEnabled(SensitivityAAPSPlugin.getPlugin(), PluginBase.SENSITIVITY);
addPreferencesFromResourceIfEnabled(SensitivityWeightedAveragePlugin.getPlugin(), PluginBase.SENSITIVITY);
addPreferencesFromResourceIfEnabled(SensitivityOref0Plugin.getPlugin(), PluginBase.SENSITIVITY);
if (Config.DANAR) {
addPreferencesFromResourceIfEnabled(DanaRPlugin.getPlugin(), PluginBase.PUMP);
addPreferencesFromResourceIfEnabled(DanaRKoreanPlugin.getPlugin(), PluginBase.PUMP);
addPreferencesFromResourceIfEnabled(DanaRv2Plugin.getPlugin(), PluginBase.PUMP);
addPreferencesFromResourceIfEnabled(DanaRSPlugin.getPlugin(), PluginBase.PUMP);
if (DanaRPlugin.getPlugin().isEnabled(PluginBase.PROFILE)
|| DanaRKoreanPlugin.getPlugin().isEnabled(PluginBase.PROFILE)
|| DanaRv2Plugin.getPlugin().isEnabled(PluginBase.PROFILE)
|| DanaRSPlugin.getPlugin().isEnabled(PluginBase.PROFILE)) {
addPreferencesFromResource(R.xml.pref_danarprofile);
}
}
if (!Config.NSCLIENT && !Config.G5UPLOADER) {
addPreferencesFromResourceIfEnabled(VirtualPumpPlugin.getPlugin(), PluginBase.PUMP);
}
addPreferencesFromResourceIfEnabled(InsulinOrefFreePeakPlugin.getPlugin(), PluginBase.INSULIN);
addPreferencesFromResourceIfEnabled(NSClientInternalPlugin.getPlugin(), PluginBase.GENERAL);
addPreferencesFromResourceIfEnabled(SmsCommunicatorPlugin.getPlugin(), PluginBase.GENERAL);
if (!Config.NSCLIENT && !Config.G5UPLOADER) {
addPreferencesFromResource(R.xml.pref_others);
}
addPreferencesFromResource(R.xml.pref_advanced);
addPreferencesFromResourceIfEnabled(WearPlugin.getPlugin(), PluginBase.GENERAL);
addPreferencesFromResourceIfEnabled(StatuslinePlugin.getPlugin(), PluginBase.GENERAL);
}
initSummary(getPreferenceScreen());
}
@Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putInt("id", id);
}
public Preference getPreference(String key) {
return findPreference(key);
}

View file

@ -15,29 +15,32 @@ import org.slf4j.LoggerFactory;
import info.nightscout.androidaps.Config;
import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.R;
import info.nightscout.androidaps.data.ProfileStore;
import info.nightscout.androidaps.db.BgReading;
import info.nightscout.androidaps.db.CareportalEvent;
import info.nightscout.androidaps.events.EventNewBasalProfile;
import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin;
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.NSSgv;
import info.nightscout.androidaps.data.ProfileStore;
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.events.EventDismissNotification;
import info.nightscout.androidaps.plugins.Overview.events.EventNewNotification;
import info.nightscout.androidaps.plugins.Overview.notifications.Notification;
import info.nightscout.androidaps.plugins.ProfileNS.NSProfilePlugin;
import info.nightscout.androidaps.plugins.ProfileNS.events.EventNSProfileUpdateGUI;
import info.nightscout.androidaps.plugins.PumpDanaR.activities.DanaRNSHistorySync;
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.SourceMM640g.SourceMM640gPlugin;
import info.nightscout.androidaps.plugins.SourceNSClient.SourceNSClientPlugin;
import info.nightscout.androidaps.plugins.SourceXdrip.SourceXdripPlugin;
import info.nightscout.androidaps.receivers.DataReceiver;
import info.nightscout.androidaps.plugins.NSClientInternal.data.NSDeviceStatus;
import info.nightscout.utils.BundleLogger;
import info.nightscout.utils.NSUpload;
import info.nightscout.utils.SP;
@ -48,6 +51,7 @@ public class DataService extends IntentService {
boolean nsClientEnabled = true;
boolean mm640gEnabled = false;
boolean glimpEnabled = false;
boolean dexcomG5Enabled = false;
public DataService() {
super("DataService");
@ -64,26 +68,41 @@ public class DataService extends IntentService {
nsClientEnabled = false;
mm640gEnabled = false;
glimpEnabled = false;
dexcomG5Enabled = false;
} else if (ConfigBuilderPlugin.getActiveBgSource().getClass().equals(SourceNSClientPlugin.class)) {
xDripEnabled = false;
nsClientEnabled = true;
mm640gEnabled = false;
glimpEnabled = false;
dexcomG5Enabled = false;
} else if (ConfigBuilderPlugin.getActiveBgSource().getClass().equals(SourceMM640gPlugin.class)) {
xDripEnabled = false;
nsClientEnabled = false;
mm640gEnabled = true;
glimpEnabled = false;
dexcomG5Enabled = false;
} else if (ConfigBuilderPlugin.getActiveBgSource().getClass().equals(SourceGlimpPlugin.class)) {
xDripEnabled = false;
nsClientEnabled = false;
mm640gEnabled = false;
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 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) {
final String action = intent.getAction();
@ -99,23 +118,28 @@ public class DataService extends IntentService {
if (glimpEnabled) {
handleNewDataFromGlimp(intent);
}
} else if (Intents.ACTION_NEW_SGV.equals(action)) {
// always handle SGV if NS-Client is the source
if (nsClientEnabled) {
handleNewDataFromNSClient(intent);
} else if (Intents.DEXCOMG5_BG.equals(action)) {
if (dexcomG5Enabled) {
handleNewDataFromDexcomG5(intent);
}
} else if (Intents.ACTION_NEW_SGV.equals(action)) {
// always backfill SGV from NS
handleNewDataFromNSClient(intent);
// Objectives 0
ObjectivesPlugin.bgIsAvailableInNS = true;
ObjectivesPlugin.saveProgress();
} 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
handleNewDataFromNSClient(intent);
} else if (!nsUploadOnly &&
} else if (acceptNSData &&
(Intents.ACTION_NEW_TREATMENT.equals(action) ||
Intents.ACTION_CHANGED_TREATMENT.equals(action) ||
Intents.ACTION_REMOVED_TREATMENT.equals(action) ||
Intents.ACTION_NEW_STATUS.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_MBG.equals(action))
) {
@ -184,6 +208,40 @@ public class DataService extends IntentService {
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) {
Bundle bundle = intent.getExtras();
if (bundle == null) return;
@ -247,7 +305,7 @@ public class DataService extends IntentService {
log.error("Unhandled exception", e);
}
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));
} else {
MainApp.bus().post(new EventDismissNotification(Notification.OLD_NS));
@ -308,36 +366,18 @@ public class DataService extends IntentService {
String profile = bundles.getString("profile");
ProfileStore profileStore = new ProfileStore(new JSONObject(profile));
NSProfilePlugin.storeNewProfile(profileStore);
MainApp.bus().post(new EventNewBasalProfile());
MainApp.bus().post(new EventNSProfileUpdateGUI());
// if there are no profile switches this should lead to profile update
if (MainApp.getConfigBuilder().getProfileSwitchesFromHistory().size() == 0)
MainApp.bus().post(new EventNewBasalProfile());
if (Config.logIncommingData)
log.debug("Received profileStore: " + activeProfile + " " + profile);
} catch (JSONException 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_CHANGED_TREATMENT)) {
if (intent.getAction().equals(Intents.ACTION_NEW_TREATMENT) || intent.getAction().equals(Intents.ACTION_CHANGED_TREATMENT)) {
try {
if (bundles.containsKey("treatment")) {
String trstring = bundles.getString("treatment");
@ -433,6 +473,56 @@ public class DataService extends IntentService {
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) {

View file

@ -8,6 +8,9 @@ public interface Intents {
String ACTION_NEW_PROFILE = "info.nightscout.client.NEW_PROFILE";
String ACTION_NEW_SGV = "info.nightscout.client.NEW_SGV";
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_CAL = "info.nightscout.client.NEW_CAL";
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 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 long pumpId = 0; // id of record if comming from pump history (not a newly created treatment)
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;
}
@Nullable
public static GlucoseStatus getGlucoseStatusData() {
public static GlucoseStatus getGlucoseStatusData(){
return getGlucoseStatusData(false);
}
@Nullable
public static GlucoseStatus getGlucoseStatusData(boolean allowOldData) {
// load 45min
long fromtime = (long) (System.currentTimeMillis() - 60 * 1000L * 45);
List<BgReading> data = MainApp.getDbHelper().getBgreadingsDataFromTime(fromtime, false);
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;
}

View file

@ -12,4 +12,26 @@ public class Iob {
activityContrib += iob.activityContrib;
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.util.Calendar;
import java.util.Date;
import java.util.TimeZone;
import info.nightscout.androidaps.Constants;
import info.nightscout.androidaps.MainApp;
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.EventNewNotification;
import info.nightscout.androidaps.plugins.Overview.notifications.Notification;
import info.nightscout.utils.DateUtil;
import info.nightscout.utils.DecimalFormatter;
import info.nightscout.utils.ToastUtils;
@ -29,19 +32,27 @@ public class Profile {
private JSONObject json;
private String units = null;
double dia = Constants.defaultDIA;
TimeZone timeZone = TimeZone.getDefault();
JSONArray isf;
private double dia = Constants.defaultDIA;
private TimeZone timeZone = TimeZone.getDefault();
private JSONArray isf;
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
JSONArray basal;
private JSONArray basal;
private LongSparseArray<Double> basal_v = null; // oldest at index 0
JSONArray targetLow;
JSONArray targetHigh;
private JSONArray targetLow;
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) {
this(json);
this(json, 100, 0);
if (this.units == null) {
if (units != null)
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;
try {
if (json.has("units"))
@ -110,7 +123,9 @@ public class Profile {
}
} catch (JSONException 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) {
double multiplier = getMultiplier(array);
LongSparseArray<Double> sparse = new LongSparseArray<>();
for (Integer index = 0; index < array.length(); index++) {
try {
JSONObject o = array.getJSONObject(index);
long tas = o.getLong("timeAsSeconds");
Double value = o.getDouble("value");
final JSONObject o = array.getJSONObject(index);
long tas = 0;
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);
} catch (JSONException 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;
}
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) {
Double lastValue = null;
@ -182,7 +279,47 @@ public class Profile {
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;
for (Integer index = 0; index < array.size(); index++) {
@ -197,26 +334,29 @@ public class Profile {
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 = "";
for (Integer index = 0; index < array.length(); index++) {
try {
JSONObject o = array.getJSONObject(index);
retValue += o.getString("time");
retValue += " ";
retValue += format.format(o.getDouble("value"));
if (array2 != null) {
JSONObject o2 = array2.getJSONObject(index);
retValue += " - ";
retValue += format.format(o2.getDouble("value"));
}
retValue += " " + units;
if (index + 1 < array.length())
retValue += "\n";
} catch (JSONException e) {
log.error("Unhandled exception", e);
for (Integer index = 0; index < array.size(); index++) {
retValue += format_HH_MM((int) array.keyAt(index));
retValue += " ";
retValue += format.format(array.valueAt(index));
if (array2 != null) {
retValue += " - ";
retValue += format.format(array2.valueAt(index));
}
retValue += " " + units;
if (index + 1 < array.size())
retValue += "\n";
}
return retValue;
}
@ -236,7 +376,7 @@ public class Profile {
}
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() {
@ -254,7 +394,7 @@ public class Profile {
}
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() {
@ -265,14 +405,15 @@ public class Profile {
return getBasal(secondsFromMidnight(time));
}
public Double getBasal(Integer timeAsSeconds) {
if (basal_v == null)
public synchronized Double getBasal(Integer timeAsSeconds) {
if (basal_v == null) {
basal_v = convertToSparseArray(basal);
}
return getValueToTime(basal_v, timeAsSeconds);
}
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 {
@ -285,21 +426,17 @@ public class Profile {
public Double value;
}
public BasalValue[] getBasalValues() {
try {
BasalValue[] ret = new BasalValue[basal.length()];
public synchronized BasalValue[] getBasalValues() {
if (basal_v == null)
basal_v = convertToSparseArray(basal);
BasalValue[] ret = new BasalValue[basal_v.size()];
for (Integer index = 0; index < basal.length(); index++) {
JSONObject o = basal.getJSONObject(index);
Integer tas = o.getInt("timeAsSeconds");
Double value = o.getDouble("value");
ret[index] = new BasalValue(tas, value);
}
return ret;
} catch (JSONException e) {
log.error("Unhandled exception", e);
for (Integer index = 0; index < basal_v.size(); index++) {
Integer tas = (int) basal_v.keyAt(index);
Double value = basal_v.valueAt(index);
ret[index] = new BasalValue(tas, value);
}
return new BasalValue[0];
return ret;
}
public Double getTargetLow() {
@ -311,7 +448,9 @@ public class Profile {
}
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() {
@ -323,11 +462,13 @@ public class Profile {
}
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() {
return getValuesList(targetLow, targetHigh, new DecimalFormat("0.0"), getUnits());
return getValuesList(targetLow_v, targetHigh_v, new DecimalFormat("0.0"), getUnits());
}
public double getMaxDailyBasal() {
@ -350,18 +491,6 @@ public class Profile {
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) {
Calendar c = Calendar.getInstance();
c.setTimeInMillis(date);
@ -410,4 +539,29 @@ public class Profile {
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,7 +31,8 @@ public class ProfileIntervals<T extends Interval> {
public synchronized void add(List<T> list) {
for (T interval : list) {
rawData.put(interval.start(), interval);
if (interval.isValid())
rawData.put(interval.start(), interval);
}
merge();
}
@ -62,7 +63,7 @@ public class ProfileIntervals<T extends Interval> {
public synchronized List<T> getReversedList() {
List<T> list = new ArrayList<>();
for (int i = rawData.size() -1; i>=0; i--)
for (int i = rawData.size() - 1; i >= 0; i--)
list.add(rawData.valueAt(i));
return list;
}

View file

@ -32,6 +32,56 @@ public class PumpEnactResult extends Object {
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() {
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.preference.PreferenceManager;
@ -9,11 +9,7 @@ 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.data.Profile;
import info.nightscout.utils.DateUtil;
/**
* Created by mike on 12.10.2016.
@ -22,84 +18,7 @@ import info.nightscout.utils.DateUtil;
public class QuickWizard {
private static Logger log = LoggerFactory.getLogger(QuickWizard.class);
public class QuickWizardEntry {
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();
private JSONArray storage = new JSONArray();
public void setData(JSONArray 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();
raw = sgv.getFiltered() != null ? sgv.getFiltered() : value;
direction = sgv.getDirection();
_id = sgv.getId();
}
public Double valueToUnits(String units) {
@ -96,7 +97,9 @@ public class BgReading implements DataPointWithLabelInterface {
direction.compareTo("NOT COMPUTABLE") == 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;
} else {
return false;

View file

@ -191,6 +191,17 @@ public class CareportalEvent implements DataPointWithLabelInterface {
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
public long getDuration() {
try {

View file

@ -30,9 +30,12 @@ import java.util.concurrent.TimeUnit;
import info.nightscout.androidaps.Config;
import info.nightscout.androidaps.Constants;
import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.R;
import info.nightscout.androidaps.data.Profile;
import info.nightscout.androidaps.data.ProfileStore;
import info.nightscout.androidaps.events.EventCareportalEventChange;
import info.nightscout.androidaps.events.EventExtendedBolusChange;
import info.nightscout.androidaps.events.EventFoodDatabaseChanged;
import info.nightscout.androidaps.events.EventNewBG;
import info.nightscout.androidaps.events.EventProfileSwitchChange;
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.EventTempTargetChange;
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.Overview.events.EventNewNotification;
import info.nightscout.androidaps.plugins.Overview.notifications.Notification;
import info.nightscout.androidaps.plugins.PumpDanaR.activities.DanaRNSHistorySync;
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 {
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_CAREPORTALEVENTS = "CareportalEvents";
public static final String DATABASE_PROFILESWITCHES = "ProfileSwitches";
public static final String DATABASE_FOODS = "Foods";
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 ScheduledFuture<?> scheduledProfileSwitchEventPost = null;
public FoodHelper foodHelper = new FoodHelper(this);
public DatabaseHelper(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
onCreate(getWritableDatabase(), getConnectionSource());
@ -104,6 +116,7 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
TableUtils.createTableIfNotExists(connectionSource, ExtendedBolus.class);
TableUtils.createTableIfNotExists(connectionSource, CareportalEvent.class);
TableUtils.createTableIfNotExists(connectionSource, ProfileSwitch.class);
TableUtils.createTableIfNotExists(connectionSource, Food.class);
} catch (SQLException e) {
log.error("Can't create database", e);
throw new RuntimeException(e);
@ -128,6 +141,7 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
TableUtils.dropTable(connectionSource, ExtendedBolus.class, true);
TableUtils.dropTable(connectionSource, CareportalEvent.class, true);
TableUtils.dropTable(connectionSource, ProfileSwitch.class, true);
TableUtils.dropTable(connectionSource, Food.class, true);
onCreate(database, connectionSource);
}
} catch (SQLException e) {
@ -205,6 +219,7 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
TableUtils.createTableIfNotExists(connectionSource, ExtendedBolus.class);
TableUtils.createTableIfNotExists(connectionSource, CareportalEvent.class);
TableUtils.createTableIfNotExists(connectionSource, ProfileSwitch.class);
foodHelper.resetFood();
updateEarliestDataChange(0);
} catch (SQLException e) {
log.error("Unhandled exception", e);
@ -217,6 +232,7 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
scheduleTemporaryTargetChange();
scheduleCareportalEventChange();
scheduleProfileSwitchChange();
foodHelper.scheduleFoodChange();
new java.util.Timer().schedule(
new java.util.TimerTask() {
@Override
@ -335,7 +351,7 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
}
// ------------------- BgReading handling -----------------------
public void createIfNotExists(BgReading bgReading, String from) {
public boolean createIfNotExists(BgReading bgReading, String from) {
try {
bgReading.date = roundDateToSec(bgReading.date);
BgReading old = getDaoBgReadings().queryForId(bgReading.date);
@ -343,18 +359,29 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
getDaoBgReadings().create(bgReading);
log.debug("BG: New record from: " + from + " " + bgReading.toString());
scheduleBgChange();
return;
return true;
}
if (!old.isEqual(bgReading)) {
log.debug("BG: Similiar found: " + old.toString());
old.copyFrom(bgReading);
getDaoBgReadings().update(old);
log.debug("BG: Updating record from: " + from + " " + old.toString());
log.debug("BG: Updating record from: " + from + " New data: " + old.toString());
scheduleBgChange();
return;
return false;
}
} catch (SQLException 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() {
@ -387,7 +414,7 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
QueryBuilder<BgReading, Long> queryBuilder = daoBgReadings.queryBuilder();
queryBuilder.orderBy("date", false);
queryBuilder.limit(1L);
queryBuilder.where().gt("value", 38);
queryBuilder.where().gt("value", 38).and().eq("isValid", true);
PreparedQuery<BgReading> preparedQuery = queryBuilder.prepare();
bgList = daoBgReadings.query(preparedQuery);
@ -425,7 +452,24 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
QueryBuilder<BgReading, Long> queryBuilder = daoBgreadings.queryBuilder();
queryBuilder.orderBy("date", ascending);
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();
bgReadings = daoBgreadings.query(preparedQuery);
return bgReadings;
@ -463,7 +507,7 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
return 0;
}
public int deleteDbRequestbyMongoId(String action, String id) {
public void deleteDbRequestbyMongoId(String action, String id) {
try {
QueryBuilder<DbRequest, String> queryBuilder = getDaoDbRequest().queryBuilder();
Where where = queryBuilder.where();
@ -471,16 +515,13 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
queryBuilder.limit(10L);
PreparedQuery<DbRequest> preparedQuery = queryBuilder.prepare();
List<DbRequest> dbList = getDaoDbRequest().query(preparedQuery);
if (dbList.size() != 1) {
log.error("deleteDbRequestbyMongoId query size: " + dbList.size());
} else {
//log.debug("Treatment findTreatmentById found: " + trList.get(0).log());
return delete(dbList.get(0));
log.error("deleteDbRequestbyMongoId query size: " + dbList.size());
for (DbRequest r : dbList) {
delete(r);
}
} catch (SQLException e) {
log.error("Unhandled exception", e);
}
return 0;
}
public void deleteAllDbRequests() {
@ -655,8 +696,7 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
class PostRunnable implements Runnable {
public void run() {
log.debug("Firing EventTreatmentChange");
MainApp.bus().post(new EventReloadTreatmentData());
MainApp.bus().post(new EventTreatmentChange());
MainApp.bus().post(new EventReloadTreatmentData(new EventTreatmentChange()));
if (earliestDataChange != null)
MainApp.bus().post(new EventNewHistoryData(earliestDataChange));
earliestDataChange = null;
@ -1344,7 +1384,7 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
return;
}
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._id = trJson.getString("_id");
createOrUpdate(extendedBolus);
@ -1357,8 +1397,7 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
class PostRunnable implements Runnable {
public void run() {
log.debug("Firing EventExtendedBolusChange");
MainApp.bus().post(new EventReloadTreatmentData());
MainApp.bus().post(new EventExtendedBolusChange());
MainApp.bus().post(new EventReloadTreatmentData(new EventExtendedBolusChange()));
if (earliestDataChange != null)
MainApp.bus().post(new EventNewHistoryData(earliestDataChange));
earliestDataChange = null;
@ -1431,7 +1470,21 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
} catch (SQLException 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) {
@ -1535,9 +1588,10 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
old = getDaoProfileSwitch().queryForId(profileSwitch.date);
if (old != null) {
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
old.copyFrom(profileSwitch);
getDaoProfileSwitch().create(old);
getDaoProfileSwitch().create(profileSwitch);
log.debug("PROFILESWITCH: Updating record by date from: " + Source.getString(profileSwitch.source) + " " + old.toString());
scheduleProfileSwitchChange();
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);
log.debug("PROFILESWITCH: New record from: " + Source.getString(profileSwitch.source) + " " + profileSwitch.toString());
scheduleProfileSwitchChange();
@ -1636,6 +1692,19 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
profileSwitch.percentage = trJson.getInt("percentage");
if (trJson.has("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"))
profileSwitch.profilePlugin = trJson.getString("profilePlugin");
createOrUpdate(profileSwitch);
@ -1672,4 +1741,5 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
return null;
}
// ---------------- Food handling ---------------
}

View file

@ -147,6 +147,11 @@ public class ExtendedBolus implements Interval, DataPointWithLabelInterface {
return durationInMinutes == 0;
}
@Override
public boolean isValid() {
return true;
}
// -------- Interval interface end ---------
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;
import android.graphics.Color;
import android.support.annotation.Nullable;
import com.j256.ormlite.field.DatabaseField;
import com.j256.ormlite.table.DatabaseTable;
@ -10,14 +11,19 @@ import org.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.Date;
import java.util.Objects;
import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.R;
import info.nightscout.androidaps.data.Profile;
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.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.DecimalFormatter;
@DatabaseTable(tableName = DatabaseHelper.DATABASE_PROFILESWITCHES)
public class ProfileSwitch implements Interval, DataPointWithLabelInterface {
@ -55,16 +61,32 @@ public class ProfileSwitch implements Interval, DataPointWithLabelInterface {
private Profile profile = null;
@Nullable
public Profile getProfileObject() {
if (profile == null)
try {
profile = new Profile(new JSONObject(profileJson));
} catch (JSONException e) {
profile = new Profile(new JSONObject(profileJson), percentage, timeshift);
} catch (Exception e) {
log.error("Unhandled exception", e);
log.error("Unhandled exception", profileJson);
}
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) {
if (date != other.date) {
return false;
@ -156,6 +178,20 @@ public class ProfileSwitch implements Interval, DataPointWithLabelInterface {
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 ---------
// ----------------- DataPointInterface --------------------
@ -179,7 +215,7 @@ public class ProfileSwitch implements Interval, DataPointWithLabelInterface {
@Override
public String getLabel() {
return profileName;
return getCustomizedName();
}
@Override

View file

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

View file

@ -182,6 +182,11 @@ public class TemporaryBasal implements Interval {
return durationInMinutes == 0;
}
@Override
public boolean isValid() {
return true;
}
// -------- Interval interface end ---------
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.
*/
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.
*/
public class EventBolusRequested {
public class EventBolusRequested extends Event {
private double amount;
public EventBolusRequested (double amount){

View file

@ -4,5 +4,5 @@ package info.nightscout.androidaps.events;
* 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.
*/
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.
*/
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.
*/
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.
*/
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.
*/
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.
*/
public class EventPreferenceChange {
public class EventPreferenceChange extends Event {
public String changedKey;
public EventPreferenceChange(String key) {
changedKey = key;

View file

@ -4,5 +4,5 @@ package info.nightscout.androidaps.events;
* 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.
*/
public class EventPumpStatusChanged {
public class EventPumpStatusChanged extends Event {
public static final int CONNECTING = 0;
public static final int CONNECTED = 1;
public static final int PERFORMING = 2;
@ -18,14 +18,24 @@ public class EventPumpStatusChanged {
public int sSecondsElapsed = 0;
public String sPerfomingAction = "";
public static String error = "";
public EventPumpStatusChanged(int status) {
sStatus = status;
sSecondsElapsed = 0;
error = "";
}
public EventPumpStatusChanged(int status, int secondsElapsed) {
sStatus = status;
sSecondsElapsed = secondsElapsed;
error = "";
}
public EventPumpStatusChanged(int status, String error) {
sStatus = status;
sSecondsElapsed = 0;
this.error = error;
}
public EventPumpStatusChanged(String action) {

View file

@ -3,5 +3,12 @@ package info.nightscout.androidaps.events;
/**
* 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.
*/
public class EventRefreshOverview {
public class EventRefreshOverview extends Event {
public String from;
public EventRefreshOverview(String from) {

View file

@ -4,5 +4,5 @@ package info.nightscout.androidaps.events;
* 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.
*/
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.
*/
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.
*/
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.
*/
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.
*/
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 isSMBModeEnabled();
Double applyBasalConstraints(Double absoluteRate);
Integer applyBasalConstraints(Integer percentRate);

View file

@ -1,9 +1,12 @@
package info.nightscout.androidaps.interfaces;
import info.nightscout.androidaps.data.PumpEnactResult;
/**
* Created by mike on 12.06.2017.
*/
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 getComment();
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 isEndingEvent();
boolean isValid();
}

View file

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

View file

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

View file

@ -16,27 +16,31 @@ public interface PumpInterface {
boolean isInitialized();
boolean isSuspended();
boolean isBusy();
boolean isConnected();
boolean isConnecting();
void connect(String reason);
void disconnect(String reason);
void stopConnecting();
void getPumpStatus();
// Upload to pump new basal profile
int SUCCESS = 0;
int FAILED = 1;
int NOT_NEEDED = 2;
int setNewBasalProfile(Profile profile);
PumpEnactResult setNewBasalProfile(Profile profile);
boolean isThisProfileSet(Profile profile);
Date lastDataTime();
void refreshDataFromPump(String reason);
double getBaseBasalRate(); // base basal rate, not temp basal
PumpEnactResult deliverTreatment(DetailedBolusInfo detailedBolusInfo);
void stopBolusDelivering();
PumpEnactResult setTempBasalAbsolute(Double absoluteRate, Integer durationInMinutes, boolean force);
PumpEnactResult setTempBasalPercent(Integer percent, Integer durationInMinutes);
PumpEnactResult setTempBasalAbsolute(Double absoluteRate, Integer durationInMinutes, boolean enforceNew);
PumpEnactResult setTempBasalPercent(Integer percent, Integer durationInMinutes, boolean enforceNew);
PumpEnactResult setExtendedBolus(Double insulin, Integer durationInMinutes);
//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
PumpEnactResult cancelTempBasal(boolean force);
PumpEnactResult cancelTempBasal(boolean enforceNew);
PumpEnactResult cancelExtendedBolus();
// Status to be passed to NS

View file

@ -3,15 +3,13 @@ package info.nightscout.androidaps.plugins.Actions;
import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.os.HandlerThread;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import com.crashlytics.android.Crashlytics;
import com.crashlytics.android.answers.Answers;
import com.crashlytics.android.answers.CustomEvent;
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.OptionsToShow;
import info.nightscout.androidaps.plugins.Common.SubscriberFragment;
import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin;
import info.nightscout.utils.SingleClickButton;
/**
* A simple {@link Fragment} subclass.
@ -45,50 +45,48 @@ public class ActionsFragment extends SubscriberFragment implements View.OnClickL
return actionsPlugin;
}
Button profileSwitch;
Button tempTarget;
Button extendedBolus;
Button extendedBolusCancel;
Button tempBasal;
Button tempBasalCancel;
Button fill;
private static Handler sHandler;
private static HandlerThread sHandlerThread;
SingleClickButton profileSwitch;
SingleClickButton tempTarget;
SingleClickButton extendedBolus;
SingleClickButton extendedBolusCancel;
SingleClickButton tempBasal;
SingleClickButton tempBasalCancel;
SingleClickButton fill;
public ActionsFragment() {
super();
if (sHandlerThread == null) {
sHandlerThread = new HandlerThread(ActionsFragment.class.getSimpleName());
sHandlerThread.start();
sHandler = new Handler(sHandlerThread.getLooper());
}
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.actions_fragment, container, false);
try {
View view = inflater.inflate(R.layout.actions_fragment, container, false);
profileSwitch = (Button) view.findViewById(R.id.actions_profileswitch);
tempTarget = (Button) view.findViewById(R.id.actions_temptarget);
extendedBolus = (Button) view.findViewById(R.id.actions_extendedbolus);
extendedBolusCancel = (Button) view.findViewById(R.id.actions_extendedbolus_cancel);
tempBasal = (Button) view.findViewById(R.id.actions_settempbasal);
tempBasalCancel = (Button) view.findViewById(R.id.actions_canceltempbasal);
fill = (Button) view.findViewById(R.id.actions_fill);
profileSwitch = (SingleClickButton) view.findViewById(R.id.actions_profileswitch);
tempTarget = (SingleClickButton) view.findViewById(R.id.actions_temptarget);
extendedBolus = (SingleClickButton) view.findViewById(R.id.actions_extendedbolus);
extendedBolusCancel = (SingleClickButton) view.findViewById(R.id.actions_extendedbolus_cancel);
tempBasal = (SingleClickButton) view.findViewById(R.id.actions_settempbasal);
tempBasalCancel = (SingleClickButton) view.findViewById(R.id.actions_canceltempbasal);
fill = (SingleClickButton) view.findViewById(R.id.actions_fill);
profileSwitch.setOnClickListener(this);
tempTarget.setOnClickListener(this);
extendedBolus.setOnClickListener(this);
extendedBolusCancel.setOnClickListener(this);
tempBasal.setOnClickListener(this);
tempBasalCancel.setOnClickListener(this);
fill.setOnClickListener(this);
profileSwitch.setOnClickListener(this);
tempTarget.setOnClickListener(this);
extendedBolus.setOnClickListener(this);
extendedBolusCancel.setOnClickListener(this);
tempBasal.setOnClickListener(this);
tempBasalCancel.setOnClickListener(this);
fill.setOnClickListener(this);
updateGUI();
return view;
updateGUI();
return view;
} catch (Exception e) {
Crashlytics.logException(e);
}
return null;
}
@Subscribe
@ -128,14 +126,14 @@ public class ActionsFragment extends SubscriberFragment implements View.OnClickL
fill.setVisibility(View.GONE);
return;
}
boolean allowProfileSwitch = MainApp.getConfigBuilder().getActiveProfileInterface().getProfile().getProfileList().size() > 1;
if (!MainApp.getConfigBuilder().getPumpDescription().isSetBasalProfileCapable || !MainApp.getConfigBuilder().isInitialized() || MainApp.getConfigBuilder().isSuspended() || !allowProfileSwitch)
final PumpInterface pump = ConfigBuilderPlugin.getActivePump();
if (!pump.getPumpDescription().isSetBasalProfileCapable || !pump.isInitialized() || pump.isSuspended())
profileSwitch.setVisibility(View.GONE);
else
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);
extendedBolusCancel.setVisibility(View.GONE);
} 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);
tempBasalCancel.setVisibility(View.GONE);
} else {
@ -159,14 +157,14 @@ public class ActionsFragment extends SubscriberFragment implements View.OnClickL
tempBasal.setVisibility(View.GONE);
tempBasalCancel.setVisibility(View.VISIBLE);
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 {
tempBasal.setVisibility(View.VISIBLE);
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);
else
fill.setVisibility(View.VISIBLE);
@ -183,18 +181,17 @@ public class ActionsFragment extends SubscriberFragment implements View.OnClickL
@Override
public void onClick(View view) {
FragmentManager manager = getFragmentManager();
final PumpInterface pump = MainApp.getConfigBuilder();
switch (view.getId()) {
case R.id.actions_profileswitch:
NewNSTreatmentDialog newDialog = new NewNSTreatmentDialog();
final OptionsToShow profileswitch = CareportalFragment.profileswitch;
final OptionsToShow profileswitch = CareportalFragment.PROFILESWITCH;
profileswitch.executeProfileSwitch = true;
newDialog.setOptions(profileswitch, R.string.careportal_profileswitch);
newDialog.show(manager, "NewNSTreatmentDialog");
break;
case R.id.actions_temptarget:
NewNSTreatmentDialog newTTDialog = new NewNSTreatmentDialog();
final OptionsToShow temptarget = CareportalFragment.temptarget;
final OptionsToShow temptarget = CareportalFragment.TEMPTARGET;
temptarget.executeTempTarget = true;
newTTDialog.setOptions(temptarget, R.string.careportal_temporarytarget);
newTTDialog.show(manager, "NewNSTreatmentDialog");
@ -205,24 +202,14 @@ public class ActionsFragment extends SubscriberFragment implements View.OnClickL
break;
case R.id.actions_extendedbolus_cancel:
if (MainApp.getConfigBuilder().isInHistoryExtendedBoluslInProgress()) {
sHandler.post(new Runnable() {
@Override
public void run() {
pump.cancelExtendedBolus();
Answers.getInstance().logCustom(new CustomEvent("CancelExtended"));
}
});
ConfigBuilderPlugin.getCommandQueue().cancelExtended(null);
Answers.getInstance().logCustom(new CustomEvent("CancelExtended"));
}
break;
case R.id.actions_canceltempbasal:
if (MainApp.getConfigBuilder().isTempBasalInProgress()) {
sHandler.post(new Runnable() {
@Override
public void run() {
pump.cancelTempBasal(true);
Answers.getInstance().logCustom(new CustomEvent("CancelTemp"));
}
});
ConfigBuilderPlugin.getCommandQueue().cancelTempBasal(true, null);
Answers.getInstance().logCustom(new CustomEvent("CancelTemp"));
}
break;
case R.id.actions_settempbasal:

View file

@ -10,8 +10,8 @@ import info.nightscout.androidaps.interfaces.PluginBase;
public class ActionsPlugin implements PluginBase {
boolean fragmentEnabled = true;
boolean fragmentVisible = true;
private boolean fragmentEnabled = true;
private boolean fragmentVisible = true;
@Override
public int getType() {
@ -74,4 +74,9 @@ public class ActionsPlugin implements PluginBase {
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.DialogInterface;
import android.content.SharedPreferences;
import android.content.Intent;
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.v7.app.AlertDialog;
import android.view.LayoutInflater;
@ -16,7 +13,6 @@ import android.view.ViewGroup;
import android.view.Window;
import android.view.WindowManager;
import android.widget.Button;
import android.widget.TextView;
import com.crashlytics.android.answers.Answers;
import com.crashlytics.android.answers.CustomEvent;
@ -30,14 +26,12 @@ import info.nightscout.androidaps.Constants;
import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.R;
import info.nightscout.androidaps.data.DetailedBolusInfo;
import info.nightscout.androidaps.data.PumpEnactResult;
import info.nightscout.androidaps.db.Source;
import info.nightscout.androidaps.interfaces.PumpInterface;
import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin;
import info.nightscout.androidaps.plugins.Overview.Notification;
import info.nightscout.androidaps.plugins.Overview.events.EventNewNotification;
import info.nightscout.androidaps.plugins.Overview.Dialogs.ErrorHelperActivity;
import info.nightscout.androidaps.queue.Callback;
import info.nightscout.utils.DecimalFormatter;
import info.nightscout.utils.PlusMinusEditText;
import info.nightscout.utils.NumberPicker;
import info.nightscout.utils.SP;
import info.nightscout.utils.SafeParse;
@ -45,21 +39,14 @@ public class FillDialog extends DialogFragment implements OnClickListener {
private static Logger log = LoggerFactory.getLogger(FillDialog.class);
Button deliverButton;
TextView insulin;
double amount1 = 0d;
double amount2 = 0d;
double amount3 = 0d;
PlusMinusEditText editInsulin;
Handler mHandler;
public static HandlerThread mHandlerThread;
NumberPicker editInsulin;
public FillDialog() {
mHandlerThread = new HandlerThread(FillDialog.class.getSimpleName());
mHandlerThread.start();
this.mHandler = new Handler(mHandlerThread.getLooper());
}
@Override
@ -73,10 +60,10 @@ public class FillDialog extends DialogFragment implements OnClickListener {
getDialog().getWindow().requestFeature(Window.FEATURE_NO_TITLE);
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 bolusstep = MainApp.getConfigBuilder().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);
double bolusstep = ConfigBuilderPlugin.getActivePump().getPumpDescription().bolusStep;
editInsulin = (NumberPicker) view.findViewById(R.id.treatments_newtreatment_insulinamount);
editInsulin.setParams(0d, 0d, maxInsulin, bolusstep, new DecimalFormat("0.00"), false);
//setup preset buttons
Button button1 = (Button) view.findViewById(R.id.fill_preset_button1);
@ -88,21 +75,21 @@ public class FillDialog extends DialogFragment implements OnClickListener {
amount2 = SP.getDouble("fill_button2", 0d);
amount3 = SP.getDouble("fill_button3", 0d);
if(amount1 >0) {
if (amount1 > 0) {
button1.setVisibility(View.VISIBLE);
button1.setText(DecimalFormatter.to2Decimal(amount1) + "U");
button1.setOnClickListener(this);
} else {
button1.setVisibility(View.GONE);
}
if(amount2 >0) {
if (amount2 > 0) {
button2.setVisibility(View.VISIBLE);
button2.setText(DecimalFormatter.to2Decimal(amount2) + "U");
button2.setOnClickListener(this);
} else {
button2.setVisibility(View.GONE);
}
if(amount3 >0) {
if (amount3 > 0) {
button3.setVisibility(View.VISIBLE);
button3.setText(DecimalFormatter.to2Decimal(amount3) + "U");
button3.setOnClickListener(this);
@ -110,9 +97,12 @@ public class FillDialog extends DialogFragment implements OnClickListener {
button3.setVisibility(View.GONE);
}
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);
}
setCancelable(true);
getDialog().setCanceledOnTouchOutside(false);
return view;
}
@ -127,7 +117,7 @@ public class FillDialog extends DialogFragment implements OnClickListener {
public void onClick(View view) {
switch (view.getId()) {
case R.id.treatments_newtreatment_deliverbutton:
Double insulin = SafeParse.stringToDouble(this.insulin.getText().toString());
Double insulin = SafeParse.stringToDouble(editInsulin.getText().toString());
confirmAndDeliver(insulin);
break;
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() {
public void onClick(DialogInterface dialog, int id) {
if (finalInsulinAfterConstraints > 0) {
final ConfigBuilderPlugin pump = MainApp.getConfigBuilder();
mHandler.post(new Runnable() {
DetailedBolusInfo detailedBolusInfo = new DetailedBolusInfo();
detailedBolusInfo.insulin = finalInsulinAfterConstraints;
detailedBolusInfo.context = context;
detailedBolusInfo.source = Source.USER;
detailedBolusInfo.isValid = false; // do not count it in IOB (for pump history)
ConfigBuilderPlugin.getCommandQueue().bolus(detailedBolusInfo, new Callback() {
@Override
public void run() {
DetailedBolusInfo detailedBolusInfo = new DetailedBolusInfo();
detailedBolusInfo.insulin = finalInsulinAfterConstraints;
detailedBolusInfo.context = context;
detailedBolusInfo.source = Source.USER;
detailedBolusInfo.isValid = false; // do not count it in IOB (for pump history)
PumpEnactResult result = pump.deliverTreatment(detailedBolusInfo);
if (!result.success) {
try {
AlertDialog.Builder builder = new AlertDialog.Builder(context);
builder.setTitle(MainApp.sResources.getString(R.string.treatmentdeliveryerror));
builder.setMessage(result.comment);
builder.setPositiveButton(MainApp.sResources.getString(R.string.ok), null);
builder.show();
} catch (WindowManager.BadTokenException | NullPointerException e) {
// window has been destroyed
Notification notification = new Notification(Notification.BOLUS_DELIVERY_ERROR, MainApp.sResources.getString(R.string.treatmentdeliveryerror), Notification.URGENT);
MainApp.bus().post(new EventNewNotification(notification));
}
Intent i = new Intent(MainApp.instance(), ErrorHelperActivity.class);
i.putExtra("soundid", R.raw.boluserror);
i.putExtra("status", result.comment);
i.putExtra("title", MainApp.sResources.getString(R.string.treatmentdeliveryerror));
i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
MainApp.instance().startActivity(i);
}
}
});

View file

@ -2,18 +2,13 @@ package info.nightscout.androidaps.plugins.Actions.dialogs;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import android.os.HandlerThread;
import android.support.v4.app.DialogFragment;
import android.support.v7.app.AlertDialog;
import android.view.LayoutInflater;
import android.view.View;
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.CustomEvent;
@ -26,26 +21,19 @@ import java.text.DecimalFormat;
import info.nightscout.androidaps.Constants;
import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.R;
import info.nightscout.androidaps.data.PumpEnactResult;
import info.nightscout.androidaps.interfaces.PumpInterface;
import info.nightscout.androidaps.plugins.Overview.Notification;
import info.nightscout.androidaps.plugins.Overview.events.EventNewNotification;
import info.nightscout.utils.PlusMinusEditText;
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.SafeParse;
public class NewExtendedBolusDialog extends DialogFragment implements View.OnClickListener {
private static Logger log = LoggerFactory.getLogger(NewExtendedBolusDialog.class);
PlusMinusEditText editInsulin;
PlusMinusEditText editDuration;
Handler mHandler;
public static HandlerThread mHandlerThread;
NumberPicker editInsulin;
NumberPicker editDuration;
public NewExtendedBolusDialog() {
mHandlerThread = new HandlerThread(NewExtendedBolusDialog.class.getSimpleName());
mHandlerThread.start();
this.mHandler = new Handler(mHandlerThread.getLooper());
}
@Override
@ -56,22 +44,20 @@ public class NewExtendedBolusDialog extends DialogFragment implements View.OnCli
View view = inflater.inflate(R.layout.overview_newextendedbolus_dialog, container, false);
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 extendedMaxDuration = MainApp.getConfigBuilder().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);
double extendedDurationStep = ConfigBuilderPlugin.getActivePump().getPumpDescription().extendedBolusDurationStep;
double extendedMaxDuration = ConfigBuilderPlugin.getActivePump().getPumpDescription().extendedBolusMaxDuration;
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.cancel).setOnClickListener(this);
return view;
}
@Override
public void onResume() {
super.onResume();
if (getDialog() != null)
getDialog().getWindow().setLayout(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
setCancelable(true);
getDialog().setCanceledOnTouchOutside(false);
return view;
}
@Override
@ -100,23 +86,16 @@ public class NewExtendedBolusDialog extends DialogFragment implements View.OnCli
builder.setMessage(confirmMessage);
builder.setPositiveButton(getString(R.string.ok), new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
final PumpInterface pump = MainApp.getConfigBuilder();
mHandler.post(new Runnable() {
ConfigBuilderPlugin.getCommandQueue().extendedBolus(finalInsulin, finalDurationInMinutes, new Callback() {
@Override
public void run() {
PumpEnactResult result = pump.setExtendedBolus(finalInsulin, finalDurationInMinutes);
if (!result.success) {
try {
AlertDialog.Builder builder = new AlertDialog.Builder(context);
builder.setTitle(context.getString(R.string.treatmentdeliveryerror));
builder.setMessage(result.comment);
builder.setPositiveButton(context.getString(R.string.ok), null);
builder.show();
} catch (WindowManager.BadTokenException | NullPointerException e) {
// window has been destroyed
Notification notification = new Notification(Notification.BOLUS_DELIVERY_ERROR, MainApp.sResources.getString(R.string.treatmentdeliveryerror), Notification.URGENT);
MainApp.bus().post(new EventNewNotification(notification));
}
Intent i = new Intent(MainApp.instance(), ErrorHelperActivity.class);
i.putExtra("soundid", R.raw.boluserror);
i.putExtra("status", result.comment);
i.putExtra("title", MainApp.sResources.getString(R.string.treatmentdeliveryerror));
i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
MainApp.instance().startActivity(i);
}
}
});

View file

@ -1,11 +1,9 @@
package info.nightscout.androidaps.plugins.Actions.dialogs;
import android.app.Activity;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import android.os.HandlerThread;
import android.support.v4.app.DialogFragment;
import android.support.v7.app.AlertDialog;
import android.view.LayoutInflater;
@ -14,7 +12,6 @@ import android.view.ViewGroup;
import android.widget.LinearLayout;
import android.widget.RadioButton;
import android.widget.RadioGroup;
import android.widget.RelativeLayout;
import com.crashlytics.android.answers.Answers;
import com.crashlytics.android.answers.CustomEvent;
@ -26,12 +23,12 @@ import java.text.DecimalFormat;
import info.nightscout.androidaps.MainApp;
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.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.PlusMinusEditText;
import info.nightscout.utils.SafeParse;
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 duration;
Handler mHandler;
public static HandlerThread mHandlerThread;
public NewTempBasalDialog() {
mHandlerThread = new HandlerThread(NewTempBasalDialog.class.getSimpleName());
mHandlerThread.start();
this.mHandler = new Handler(mHandlerThread.getLooper());
}
@Override
@ -72,9 +63,9 @@ public class NewTempBasalDialog extends DialogFragment implements View.OnClickLi
absoluteRadio = (RadioButton) view.findViewById(R.id.overview_newtempbasal_absolute_radio);
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 tempPercentStep = pumpDescription.tempPercentStep;
basalPercent.setParams(100d, 0d, maxTempPercent, tempPercentStep, new DecimalFormat("0"), true);
@ -111,6 +102,9 @@ public class NewTempBasalDialog extends DialogFragment implements View.OnClickLi
view.findViewById(R.id.ok).setOnClickListener(this);
view.findViewById(R.id.cancel).setOnClickListener(this);
basalTypeRadioGroup.setOnCheckedChangeListener(this);
setCancelable(true);
getDialog().setCanceledOnTouchOutside(false);
return view;
}
@ -145,37 +139,29 @@ public class NewTempBasalDialog extends DialogFragment implements View.OnClickLi
final Double finalBasal = absolute;
final int finalDurationInMinutes = durationInMinutes;
final Context context = getContext();
AlertDialog.Builder builder = new AlertDialog.Builder(context);
AlertDialog.Builder builder = new AlertDialog.Builder(getContext());
builder.setTitle(this.getContext().getString(R.string.confirmation));
builder.setMessage(confirmMessage);
builder.setPositiveButton(getString(R.string.ok), new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
final PumpInterface pump = MainApp.getConfigBuilder();
mHandler.post(new Runnable() {
Callback callback = new Callback() {
@Override
public void run() {
PumpEnactResult result;
if (setAsPercent) {
result = pump.setTempBasalPercent(finalBasalPercent, finalDurationInMinutes);
} else {
result = pump.setTempBasalAbsolute(finalBasal, finalDurationInMinutes, false);
}
if (!result.success) {
if (context instanceof Activity) {
Activity activity = (Activity) context;
if (activity.isFinishing()) {
return;
}
}
AlertDialog.Builder builder = new AlertDialog.Builder(context);
builder.setTitle(MainApp.sResources.getString(R.string.tempbasaldeliveryerror));
builder.setMessage(result.comment);
builder.setPositiveButton(MainApp.sResources.getString(R.string.ok), null);
builder.show();
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.tempbasaldeliveryerror));
i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
MainApp.instance().startActivity(i);
}
}
});
};
if (setAsPercent) {
ConfigBuilderPlugin.getCommandQueue().tempBasalPercent(finalBasalPercent, finalDurationInMinutes, true, callback);
} else {
ConfigBuilderPlugin.getCommandQueue().tempBasalAbsolute(finalBasal, finalDurationInMinutes, true, callback);
}
Answers.getInstance().logCustom(new CustomEvent("TempBasal"));
}
});

View file

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

View file

@ -7,8 +7,17 @@ import info.nightscout.androidaps.interfaces.PluginBase;
public class CareportalPlugin implements PluginBase {
boolean fragmentEnabled = true;
boolean fragmentVisible = true;
private boolean fragmentEnabled = true;
private boolean fragmentVisible = true;
static CareportalPlugin careportalPlugin;
static public CareportalPlugin getPlugin() {
if (careportalPlugin == null) {
careportalPlugin = new CareportalPlugin();
}
return careportalPlugin;
}
@Override
public int getType() {
@ -58,7 +67,7 @@ public class CareportalPlugin implements PluginBase {
@Override
public boolean showInList(int type) {
return !Config.NSCLIENT;
return !Config.NSCLIENT && !Config.G5UPLOADER;
}
@Override
@ -71,4 +80,9 @@ public class CareportalPlugin implements PluginBase {
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.content.DialogInterface;
import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import android.os.HandlerThread;
import android.support.v4.app.DialogFragment;
import android.support.v7.app.AlertDialog;
import android.text.Editable;
@ -14,7 +13,9 @@ import android.text.format.DateFormat;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.CompoundButton;
import android.widget.EditText;
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.TempTarget;
import info.nightscout.androidaps.events.EventNewBasalProfile;
import info.nightscout.androidaps.interfaces.PumpInterface;
import info.nightscout.androidaps.plugins.Careportal.OptionsToShow;
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.NSUpload;
import info.nightscout.utils.NumberPicker;
@ -73,17 +74,11 @@ public class NewNSTreatmentDialog extends DialogFragment implements View.OnClick
String units;
TextView eventTypeText;
LinearLayout layoutBg;
LinearLayout layoutBgSource;
LinearLayout layoutInsulin;
LinearLayout layoutCarbs;
LinearLayout layoutSplit;
LinearLayout layoutDuration;
LinearLayout layoutPercent;
LinearLayout layoutAbsolute;
LinearLayout layoutCarbTime;
LinearLayout layoutProfile;
LinearLayout layoutTempTarget;
LinearLayout layoutReuse;
TextView dateButton;
TextView timeButton;
@ -94,6 +89,7 @@ public class NewNSTreatmentDialog extends DialogFragment implements View.OnClick
EditText notesEdit;
Spinner profileSpinner;
Spinner reasonSpinner;
Button reuseButton;
NumberPicker editBg;
NumberPicker editCarbs;
@ -104,13 +100,11 @@ public class NewNSTreatmentDialog extends DialogFragment implements View.OnClick
NumberPicker editAbsolute;
NumberPicker editCarbTime;
NumberPicker editTemptarget;
NumberPicker editPercentage;
NumberPicker editTimeshift;
Date eventTime;
private static Handler sHandler;
private static HandlerThread sHandlerThread;
public void setOptions(OptionsToShow options, int event) {
this.options = options;
this.event = MainApp.sResources.getString(event);
@ -118,11 +112,6 @@ public class NewNSTreatmentDialog extends DialogFragment implements View.OnClick
public NewNSTreatmentDialog() {
super();
if (sHandlerThread == null) {
sHandlerThread = new HandlerThread(NewNSTreatmentDialog.class.getSimpleName());
sHandlerThread.start();
sHandler = new Handler(sHandlerThread.getLooper());
}
}
@Override
@ -140,21 +129,15 @@ public class NewNSTreatmentDialog extends DialogFragment implements View.OnClick
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
if (options == null) return null;
getDialog().setTitle(getString(options.eventName));
setStyle(DialogFragment.STYLE_NORMAL, getTheme());
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);
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);
layoutTempTarget = (LinearLayout) view.findViewById(R.id.careportal_newnstreatment_temptarget_layout);
layoutReuse = (LinearLayout) view.findViewById(R.id.careportal_newnstreatment_reuse_layout);
eventTypeText = (TextView) view.findViewById(R.id.careportal_newnstreatment_eventtype);
eventTypeText.setText(event);
@ -164,6 +147,8 @@ public class NewNSTreatmentDialog extends DialogFragment implements View.OnClick
otherRadioButton = (RadioButton) view.findViewById(R.id.careportal_newnstreatment_other);
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);
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);
// set selected to actual profile
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);
}
final Double bg = Profile.fromMgdlToUnits(GlucoseStatus.getGlucoseStatusData() != null ? GlucoseStatus.getGlucoseStatusData().glucose : 0d, profile != null ? profile.getUnits() : Constants.MGDL);
// 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.activity));
reasonList.add(MainApp.sResources.getString(R.string.manual));
ArrayAdapter<CharSequence> adapterReason = new ArrayAdapter<CharSequence>(getContext(),
R.layout.spinner_centered, reasonList);
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
bgUnitsView.setText(units);
Double bg = Profile.fromMgdlToUnits(GlucoseStatus.getGlucoseStatusData() != null ? GlucoseStatus.getGlucoseStatusData().glucose : 0d, profile != null ? profile.getUnits() : Constants.MGDL);
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() {
TextWatcher bgTextWatcher = new TextWatcher() {
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) {
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() {
@Override
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.setParams(0d, 0d, 24 * 60d, 10d, new DecimalFormat("0"), false);
Integer maxPercent = MainApp.getConfigBuilder().applyBasalConstraints(Constants.basalPercentOnlyForCheckLimit);
editPercent = (NumberPicker) view.findViewById(R.id.careportal_newnstreatment_percentinput);
editPercent.setParams(0d, 0d, (double) maxPercent, 5d, new DecimalFormat("0"), true);
editPercent.addTextChangedListener(new TextWatcher() {
TextWatcher percentTextWatcher = new TextWatcher() {
@Override
public void afterTextChanged(Editable s) {
}
@ -271,12 +293,13 @@ public class NewNSTreatmentDialog extends DialogFragment implements View.OnClick
layoutPercent.setVisibility(View.VISIBLE);
layoutAbsolute.setVisibility(View.GONE);
}
});
};
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);
editAbsolute.addTextChangedListener(new TextWatcher() {
Integer maxPercent = MainApp.getConfigBuilder().applyBasalConstraints(Constants.basalPercentOnlyForCheckLimit);
editPercent = (NumberPicker) view.findViewById(R.id.careportal_newnstreatment_percentinput);
editPercent.setParams(0d, 0d, (double) maxPercent, 5d, new DecimalFormat("0"), true, percentTextWatcher);
TextWatcher absoluteTextWatcher = new TextWatcher() {
@Override
public void afterTextChanged(Editable s) {
}
@ -292,24 +315,53 @@ public class NewNSTreatmentDialog extends DialogFragment implements View.OnClick
layoutPercent.setVisibility(View.GONE);
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.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);
showOrHide(layoutBgSource, options.bg);
showOrHide(layoutInsulin, options.insulin);
showOrHide(layoutCarbs, options.carbs);
showOrHide(layoutSplit, options.split);
showOrHide(layoutDuration, options.duration);
editTimeshift = (NumberPicker) view.findViewById(R.id.careportal_newnstreatment_timeshift);
editTimeshift.setParams(0d, (double) Constants.CPP_MIN_TIMESHIFT, (double) Constants.CPP_MAX_TIMESHIFT, 1d, new DecimalFormat("0"), false);
ProfileSwitch ps = MainApp.getConfigBuilder().getProfileSwitchFromHistory(System.currentTimeMillis());
if (ps != null && ps.isCPP) {
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(layoutAbsolute, options.absolute);
showOrHide(layoutCarbTime, options.prebolus);
showOrHide(layoutProfile, options.profile);
showOrHide(layoutTempTarget, options.tempTarget);
showOrHide((ViewGroup) view.findViewById(R.id.careportal_newnstreatment_carbtime_layout), options.prebolus);
showOrHide((ViewGroup) view.findViewById(R.id.careportal_newnstreatment_profile_layout), options.profile);
showOrHide((ViewGroup) view.findViewById(R.id.careportal_newnstreatment_percentage_layout), options.profile);
showOrHide((ViewGroup) view.findViewById(R.id.careportal_newnstreatment_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;
}
@ -451,7 +503,7 @@ public class NewNSTreatmentDialog extends DialogFragment implements View.OnClick
allowZeroDuration = true;
break;
}
if (SafeParse.stringToDouble(editBg.getText()) != 0d) {
if (options.bg && SafeParse.stringToDouble(editBg.getText()) != 0d) {
data.put("glucose", SafeParse.stringToDouble(editBg.getText()));
if (meterRadioButton.isChecked()) data.put("glucoseType", "Finger");
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()));
if (options.profile && profileSpinner.getSelectedItem() != null)
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)
data.put("preBolus", SafeParse.stringToDouble(editCarbTime.getText()));
if (!notesEdit.getText().toString().equals(""))
@ -478,7 +534,7 @@ public class NewNSTreatmentDialog extends DialogFragment implements View.OnClick
if (options.eventType == R.id.careportal_combobolus) {
Double enteredInsulin = SafeParse.stringToDouble(editInsulin.getText());
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);
}
} catch (JSONException e) {
@ -556,6 +612,18 @@ public class NewNSTreatmentDialog extends DialogFragment implements View.OnClick
ret += data.get("profile");
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")) {
ret += getString(R.string.target_range);
ret += " ";
@ -594,7 +662,7 @@ public class NewNSTreatmentDialog extends DialogFragment implements View.OnClick
if (options.executeProfileSwitch) {
if (data.has("profile")) {
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) {
log.error("Unhandled exception", e);
}
@ -602,31 +670,22 @@ public class NewNSTreatmentDialog extends DialogFragment implements View.OnClick
} else if (options.executeTempTarget) {
try {
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.date = eventTime.getTime();
tempTarget.durationInMinutes = data.getInt("duration");
tempTarget.reason = data.getString("reason");
tempTarget.source = Source.USER;
if (tempTarget.durationInMinutes != 0) {
tempTarget.low = Profile.toMgdl(data.getDouble("targetBottom"), profile.getUnits());
tempTarget.high = Profile.toMgdl(data.getDouble("targetTop"), profile.getUnits());
} else {
tempTarget.low = 0;
tempTarget.high = 0;
}
log.debug("Creating new TempTarget db record: " + tempTarget.toString());
MainApp.getDbHelper().createOrUpdate(tempTarget);
NSUpload.uploadCareportalEntryToNS(data);
Answers.getInstance().logCustom(new CustomEvent("TempTarget"));
} catch (JSONException e) {
log.error("Unhandled exception", e);
}
}
});
TempTarget tempTarget = new TempTarget();
tempTarget.date = eventTime.getTime();
tempTarget.durationInMinutes = data.getInt("duration");
tempTarget.reason = data.getString("reason");
tempTarget.source = Source.USER;
if (tempTarget.durationInMinutes != 0) {
tempTarget.low = Profile.toMgdl(data.getDouble("targetBottom"), profile.getUnits());
tempTarget.high = Profile.toMgdl(data.getDouble("targetTop"), profile.getUnits());
} else {
tempTarget.low = 0;
tempTarget.high = 0;
}
log.debug("Creating new TempTarget db record: " + tempTarget.toString());
MainApp.getDbHelper().createOrUpdate(tempTarget);
NSUpload.uploadCareportalEntryToNS(data);
Answers.getInstance().logCustom(new CustomEvent("TempTarget"));
}
} catch (JSONException e) {
log.error("Unhandled exception", e);
@ -641,35 +700,69 @@ public class NewNSTreatmentDialog extends DialogFragment implements View.OnClick
builder.show();
}
public static void doProfileSwitch(final ProfileStore profileStore, final String profileName, final int duration) {
sHandler.post(new Runnable() {
public static void doProfileSwitch(final ProfileStore profileStore, final String profileName, final int duration, final int percentage, final int timeshift) {
ProfileSwitch profileSwitch = new ProfileSwitch();
profileSwitch.date = System.currentTimeMillis();
profileSwitch.source = Source.USER;
profileSwitch.profileName = profileName;
profileSwitch.profileJson = profileStore.getSpecificProfile(profileName).getData().toString();
profileSwitch.profilePlugin = ConfigBuilderPlugin.getActiveProfileInterface().getClass().getName();
profileSwitch.durationInMinutes = duration;
profileSwitch.isCPP = percentage != 100 || timeshift != 0;
profileSwitch.timeshift = timeshift;
profileSwitch.percentage = percentage;
MainApp.getConfigBuilder().addToHistoryProfileSwitch(profileSwitch);
ConfigBuilderPlugin.getCommandQueue().setProfile(profileSwitch.getProfileObject(), new Callback() {
@Override
public void run() {
ProfileSwitch profileSwitch = new ProfileSwitch();
profileSwitch.date = System.currentTimeMillis();
profileSwitch.source = Source.USER;
profileSwitch.profileName = profileName;
profileSwitch.profileJson = profileStore.getSpecificProfile(profileName).getData().toString();
profileSwitch.profilePlugin = ConfigBuilderPlugin.getActiveProfileInterface().getClass().getName();
profileSwitch.durationInMinutes = duration;
if (ConfigBuilderPlugin.getActiveProfileInterface() instanceof CircadianPercentageProfilePlugin) {
CircadianPercentageProfilePlugin cpp = (CircadianPercentageProfilePlugin) ConfigBuilderPlugin.getActiveProfileInterface();
profileSwitch.isCPP = true;
profileSwitch.timeshift = cpp.timeshift;
profileSwitch.percentage = cpp.percentage;
}
MainApp.getConfigBuilder().addToHistoryProfileSwitch(profileSwitch);
PumpInterface pump = MainApp.getConfigBuilder();
if (pump != null) {
pump.setNewBasalProfile(profileStore.getSpecificProfile(profileName));
MainApp.bus().post(new EventNewBasalProfile());
} else {
log.error("No active pump selected");
}
Answers.getInstance().logCustom(new CustomEvent("ProfileSwitch"));
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"));
}
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 int eventType;
public int eventName;
public boolean date;
public boolean bg;
public boolean insulin;
public boolean carbs;
@ -22,29 +23,63 @@ public class OptionsToShow {
public boolean executeProfileSwitch = false;
public boolean executeTempTarget = false;
public OptionsToShow(int eventType,
int eventName,
boolean bg,
boolean insulin,
boolean carbs,
boolean prebolus,
boolean duration,
boolean percent,
boolean absolute,
boolean profile,
boolean split,
boolean tempTarget) {
public OptionsToShow(int eventType, int eventName) {
this.eventType = eventType;
this.eventName = eventName;
this.bg = bg;
this.insulin = insulin;
this.carbs = carbs;
this.prebolus = prebolus;
this.duration = duration;
this.percent = percent;
this.absolute = absolute;
this.profile = profile;
this.split = split;
this.tempTarget = tempTarget;
}
public OptionsToShow date() {
date = true;
return this;
}
public OptionsToShow bg() {
bg = true;
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 butterknife.Unbinder;
import info.nightscout.androidaps.MainApp;
abstract public class SubscriberFragment extends Fragment {
protected Unbinder unbinder;
@Override
public void onPause() {
super.onPause();
@ -18,5 +21,12 @@ abstract public class SubscriberFragment extends Fragment {
updateGUI();
}
@Override public void onDestroyView() {
super.onDestroyView();
if (unbinder != null)
unbinder.unbind();
}
protected abstract void updateGUI();
}

View file

@ -2,6 +2,7 @@ package info.nightscout.androidaps.plugins.ConfigBuilder;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
@ -10,17 +11,20 @@ import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ListAdapter;
import android.widget.ListView;
import android.widget.TextView;
import com.crashlytics.android.Crashlytics;
import com.crashlytics.android.answers.Answers;
import com.crashlytics.android.answers.CustomEvent;
import java.util.ArrayList;
import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.PreferencesActivity;
import info.nightscout.androidaps.R;
import info.nightscout.androidaps.events.EventConfigBuilderChange;
import info.nightscout.androidaps.events.EventRefreshGui;
@ -55,6 +59,8 @@ public class ConfigBuilderFragment extends Fragment {
TextView pumpLabel;
ListView loopListView;
TextView loopLabel;
ListView treatmentsListView;
TextView treatmentsLabel;
ListView profileListView;
TextView profileLabel;
ListView apsListView;
@ -71,6 +77,7 @@ public class ConfigBuilderFragment extends Fragment {
PluginCustomAdapter bgsourceDataAdapter = null;
PluginCustomAdapter pumpDataAdapter = null;
PluginCustomAdapter loopDataAdapter = null;
PluginCustomAdapter treatmentDataAdapter = null;
PluginCustomAdapter profileDataAdapter = null;
PluginCustomAdapter apsDataAdapter = null;
PluginCustomAdapter constraintsDataAdapter = null;
@ -79,47 +86,55 @@ public class ConfigBuilderFragment extends Fragment {
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.configbuilder_fragment, container, false);
try {
View view = inflater.inflate(R.layout.configbuilder_fragment, container, false);
insulinListView = (ListView) view.findViewById(R.id.configbuilder_insulinlistview);
sensitivityListView = (ListView) view.findViewById(R.id.configbuilder_sensitivitylistview);
bgsourceListView = (ListView) view.findViewById(R.id.configbuilder_bgsourcelistview);
bgsourceLabel = (TextView) view.findViewById(R.id.configbuilder_bgsourcelabel);
pumpListView = (ListView) view.findViewById(R.id.configbuilder_pumplistview);
pumpLabel = (TextView) view.findViewById(R.id.configbuilder_pumplabel);
loopListView = (ListView) view.findViewById(R.id.configbuilder_looplistview);
loopLabel = (TextView) view.findViewById(R.id.configbuilder_looplabel);
profileListView = (ListView) view.findViewById(R.id.configbuilder_profilelistview);
profileLabel = (TextView) view.findViewById(R.id.configbuilder_profilelabel);
apsListView = (ListView) view.findViewById(R.id.configbuilder_apslistview);
apsLabel = (TextView) view.findViewById(R.id.configbuilder_apslabel);
constraintsListView = (ListView) view.findViewById(R.id.configbuilder_constraintslistview);
constraintsLabel = (TextView) view.findViewById(R.id.configbuilder_constraintslabel);
generalListView = (ListView) view.findViewById(R.id.configbuilder_generallistview);
insulinListView = (ListView) view.findViewById(R.id.configbuilder_insulinlistview);
sensitivityListView = (ListView) view.findViewById(R.id.configbuilder_sensitivitylistview);
bgsourceListView = (ListView) view.findViewById(R.id.configbuilder_bgsourcelistview);
bgsourceLabel = (TextView) view.findViewById(R.id.configbuilder_bgsourcelabel);
pumpListView = (ListView) view.findViewById(R.id.configbuilder_pumplistview);
pumpLabel = (TextView) view.findViewById(R.id.configbuilder_pumplabel);
loopListView = (ListView) view.findViewById(R.id.configbuilder_looplistview);
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);
profileLabel = (TextView) view.findViewById(R.id.configbuilder_profilelabel);
apsListView = (ListView) view.findViewById(R.id.configbuilder_apslistview);
apsLabel = (TextView) view.findViewById(R.id.configbuilder_apslabel);
constraintsListView = (ListView) view.findViewById(R.id.configbuilder_constraintslistview);
constraintsLabel = (TextView) view.findViewById(R.id.configbuilder_constraintslabel);
generalListView = (ListView) view.findViewById(R.id.configbuilder_generallistview);
mainLayout = (LinearLayout) view.findViewById(R.id.configbuilder_mainlayout);
unlock = (Button) view.findViewById(R.id.configbuilder_unlock);
mainLayout = (LinearLayout) view.findViewById(R.id.configbuilder_mainlayout);
unlock = (Button) view.findViewById(R.id.configbuilder_unlock);
setViews();
setViews();
if (PasswordProtection.isLocked("settings_password")) {
mainLayout.setVisibility(View.GONE);
unlock.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
PasswordProtection.QueryPassword(getContext(), R.string.settings_password, "settings_password", new Runnable() {
@Override
public void run() {
mainLayout.setVisibility(View.VISIBLE);
unlock.setVisibility(View.GONE);
}
}, null);
}
});
} else {
unlock.setVisibility(View.GONE);
if (PasswordProtection.isLocked("settings_password")) {
mainLayout.setVisibility(View.GONE);
unlock.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
PasswordProtection.QueryPassword(getContext(), R.string.settings_password, "settings_password", new Runnable() {
@Override
public void run() {
mainLayout.setVisibility(View.VISIBLE);
unlock.setVisibility(View.GONE);
}
}, null);
}
});
} else {
unlock.setVisibility(View.GONE);
}
return view;
} catch (Exception e) {
Crashlytics.logException(e);
}
return view;
return null;
}
void setViews() {
@ -141,6 +156,11 @@ public class ConfigBuilderFragment extends Fragment {
setListViewHeightBasedOnChildren(loopListView);
if (MainApp.getSpecificPluginsVisibleInList(PluginBase.LOOP).size() == 0)
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);
profileListView.setAdapter(profileDataAdapter);
if (MainApp.getSpecificPluginsVisibleInList(PluginBase.PROFILE).size() == 0)
@ -177,7 +197,7 @@ public class ConfigBuilderFragment extends Fragment {
public PluginCustomAdapter(Context context, int textViewResourceId,
ArrayList<PluginBase> pluginList, int type) {
super(context, textViewResourceId, pluginList);
this.pluginList = new ArrayList<PluginBase>();
this.pluginList = new ArrayList<>();
this.pluginList.addAll(pluginList);
this.type = type;
}
@ -186,12 +206,14 @@ public class ConfigBuilderFragment extends Fragment {
TextView name;
CheckBox checkboxEnabled;
CheckBox checkboxVisible;
ImageView settings;
}
@Override
public View getView(int position, View view, ViewGroup parent) {
PluginViewHolder holder = null;
PluginBase plugin = pluginList.get(position);
if (view == 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.checkboxEnabled = (CheckBox) view.findViewById(R.id.configbuilder_simpleitem_checkboxenabled);
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);
holder.checkboxEnabled.setOnClickListener(new View.OnClickListener() {
@ -227,17 +256,48 @@ public class ConfigBuilderFragment extends Fragment {
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 {
holder = (PluginViewHolder) view.getTag();
}
PluginBase plugin = pluginList.get(position);
holder.name.setText(plugin.getName());
holder.checkboxEnabled.setChecked(plugin.isEnabled(type));
holder.checkboxVisible.setChecked(plugin.isVisibleInTabs(type));
holder.name.setTag(plugin);
holder.checkboxEnabled.setTag(plugin);
holder.checkboxVisible.setTag(plugin);
holder.settings.setTag(plugin);
if (!plugin.canBeHidden(type)) {
holder.checkboxEnabled.setEnabled(false);

View file

@ -1,12 +1,8 @@
package info.nightscout.androidaps.plugins.ConfigBuilder;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.PowerManager;
import android.preference.PreferenceManager;
import android.support.annotation.Nullable;
import android.support.v7.app.AppCompatActivity;
import org.json.JSONException;
import org.json.JSONObject;
@ -14,16 +10,16 @@ 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.R;
import info.nightscout.androidaps.data.DetailedBolusInfo;
import info.nightscout.androidaps.data.Intervals;
import info.nightscout.androidaps.data.IobTotal;
import info.nightscout.androidaps.data.MealData;
import info.nightscout.androidaps.data.Intervals;
import info.nightscout.androidaps.data.Profile;
import info.nightscout.androidaps.data.ProfileIntervals;
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.TemporaryBasal;
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.BgSourceInterface;
import info.nightscout.androidaps.interfaces.ConstraintsInterface;
import info.nightscout.androidaps.interfaces.InsulinInterface;
import info.nightscout.androidaps.interfaces.PluginBase;
import info.nightscout.androidaps.interfaces.ProfileInterface;
import info.nightscout.androidaps.interfaces.PumpDescription;
import info.nightscout.androidaps.interfaces.PumpInterface;
import info.nightscout.androidaps.interfaces.SensitivityInterface;
import info.nightscout.androidaps.interfaces.TreatmentsInterface;
import info.nightscout.androidaps.plugins.Loop.APSResult;
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.notifications.Notification;
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.SP;
/**
* 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 BgSourceInterface activeBgSource;
@ -77,12 +70,10 @@ public class ConfigBuilderPlugin implements PluginBase, PumpInterface, Constrain
private static ArrayList<PluginBase> pluginList;
private PowerManager.WakeLock mWakeLock;
private static CommandQueue commandQueue = new CommandQueue();
public ConfigBuilderPlugin() {
MainApp.bus().register(this);
PowerManager powerManager = (PowerManager) MainApp.instance().getApplicationContext().getSystemService(Context.POWER_SERVICE);
mWakeLock = powerManager.newWakeLock(PowerManager.SCREEN_DIM_WAKE_LOCK, "ConfigBuilderPlugin");
}
@Override
@ -146,9 +137,15 @@ public class ConfigBuilderPlugin implements PluginBase, PumpInterface, Constrain
// Always visible
}
@Override
public int getPreferencesId() {
return -1;
}
public void initialize() {
pluginList = MainApp.getPluginsList();
loadSettings();
MainApp.bus().post(new EventAppInitialized());
}
public void storeSettings() {
@ -192,6 +189,10 @@ public class ConfigBuilderPlugin implements PluginBase, PumpInterface, Constrain
verifySelectionInCategories();
}
public static CommandQueue getCommandQueue() {
return commandQueue;
}
public static BgSourceInterface getActiveBgSource() {
return activeBgSource;
}
@ -216,7 +217,7 @@ public class ConfigBuilderPlugin implements PluginBase, PumpInterface, Constrain
return activePump;
}
public static SensitivityInterface getActiveSensitivity() {
public static SensitivityInterface getActiveSensitivity() {
return activeSensitivity;
}
@ -301,7 +302,7 @@ public class ConfigBuilderPlugin implements PluginBase, PumpInterface, Constrain
pluginsInCategory = MainApp.getSpecificPluginsList(PluginBase.PUMP);
activePump = (PumpInterface) getTheOneEnabledInArray(pluginsInCategory, PluginBase.PUMP);
if (activePump == null)
activePump = VirtualPumpPlugin.getInstance(); // for NSClient build
activePump = VirtualPumpPlugin.getPlugin(); // for NSClient build
if (Config.logConfigBuilder)
log.debug("Selected pump interface: " + ((PluginBase) activePump).getName());
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
*/
@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
*
* @param request
* @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);
PumpEnactResult result;
if (!isInitialized()) {
result = new PumpEnactResult();
result.comment = MainApp.sResources.getString(R.string.pumpNotInitialized);
result.enacted = false;
result.success = false;
if (!pump.isInitialized()) {
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()) {
result = new PumpEnactResult();
result.comment = MainApp.sResources.getString(R.string.pumpsuspended);
result.enacted = false;
result.success = false;
if (pump.isSuspended()) {
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)
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 (Config.logCongigBuilderActions)
log.debug("applyAPSRequest: cancelTempBasal()");
result = cancelTempBasal(false);
getCommandQueue().cancelTempBasal(false, callback);
return true;
} 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)
log.debug("applyAPSRequest: Basal set correctly");
if (callback != null) {
callback.result(new PumpEnactResult().absolute(request.rate).duration(0).enacted(false).success(true).comment("Basal set correctly")).run();
}
return false;
}
} else if (isTempBasalInProgress() && Math.abs(request.rate - getTempBasalAbsoluteRateHistory()) < 0.05) {
result = new PumpEnactResult();
result.absolute = getTempBasalAbsoluteRateHistory();
result.duration = getTempBasalFromHistory(System.currentTimeMillis()).getPlannedRemainingMinutes();
result.enacted = false;
result.comment = "Temp basal set correctly";
result.success = true;
} else if (isTempBasalInProgress()
&& getTempBasalRemainingMinutesFromHistory() > 5
&& Math.abs(request.rate - getTempBasalAbsoluteRateHistory()) < pump.getPumpDescription().basalStep) {
if (Config.logCongigBuilderActions)
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 {
if (Config.logCongigBuilderActions)
log.debug("applyAPSRequest: setTempBasalAbsolute()");
result = setTempBasalAbsolute(request.rate, request.duration);
}
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;
getCommandQueue().tempBasalAbsolute(request.rate, request.duration, false, callback);
return true;
}
}
@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
@ -679,8 +468,7 @@ public class ConfigBuilderPlugin implements PluginBase, PumpInterface, Constrain
@Override
public boolean isAMAModeEnabled() {
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(MainApp.instance().getApplicationContext());
boolean result = preferences.getBoolean("openapsama_useautosens", false);
boolean result = SP.getBoolean("openapsama_useautosens", false);
ArrayList<PluginBase> constraintsPlugins = MainApp.getSpecificPluginsListByInterface(ConstraintsInterface.class);
for (PluginBase p : constraintsPlugins) {
@ -691,6 +479,19 @@ public class ConfigBuilderPlugin implements PluginBase, PumpInterface, Constrain
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
public Double applyBasalConstraints(Double absoluteRate) {
Double rateAfterConstrain = absoluteRate;
@ -810,13 +611,13 @@ public class ConfigBuilderPlugin implements PluginBase, PumpInterface, Constrain
@Override
public boolean isTempBasalInProgress() {
return activeTreatments.isTempBasalInProgress();
return activeTreatments != null && activeTreatments.isTempBasalInProgress();
}
@Override
@Nullable
public TemporaryBasal getTempBasalFromHistory(long time) {
return activeTreatments.getTempBasalFromHistory(time);
return activeTreatments != null ? activeTreatments.getTempBasalFromHistory(time) : null;
}
@Override
@ -933,11 +734,19 @@ public class ConfigBuilderPlugin implements PluginBase, PumpInterface, Constrain
return getProfileName(System.currentTimeMillis());
}
public String getProfileName(boolean customized) {
return getProfileName(System.currentTimeMillis(), customized);
}
public String getProfileName(long time) {
return getProfileName(time, true);
}
public String getProfileName(long time, boolean customized) {
ProfileSwitch profileSwitch = getProfileSwitchFromHistory(time);
if (profileSwitch != null) {
if (profileSwitch.profileJson != null) {
return profileSwitch.profileName;
return customized ? profileSwitch.getCustomizedName() : profileSwitch.profileName;
} else {
Profile profile = activeProfile.getProfile().getSpecificProfile(profileSwitch.profileName);
if (profile != null)
@ -952,14 +761,17 @@ public class ConfigBuilderPlugin implements PluginBase, PumpInterface, Constrain
return "Default";
}
@Nullable
public Profile getProfile() {
return getProfile(System.currentTimeMillis());
}
public String getProfileUnits() {
return activeProfile.getUnits();
Profile profile = getProfile();
return profile != null ? profile.getUnits() : Constants.MGDL;
}
@Nullable
public Profile getProfile(long time) {
if (activeTreatments == null)
return null; //app not initialized
@ -993,7 +805,7 @@ public class ConfigBuilderPlugin implements PluginBase, PumpInterface, Constrain
MainApp.bus().post(new EventNewNotification(nobasal));
Notification notarget = new Notification(Notification.TARGET_MISSING, MainApp.sResources.getString(R.string.targetmissing), Notification.URGENT);
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) {
log.error("Unhandled exception", e);
}

View file

@ -20,7 +20,7 @@ public class DetailedBolusInfoStorage {
private static List<DetailedBolusInfo> store = new ArrayList<>();
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);
}
@ -29,7 +29,7 @@ public class DetailedBolusInfoStorage {
DetailedBolusInfo found = null;
for (int i = 0; i < store.size(); i++) {
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) {
found = store.get(i);
break;
@ -42,7 +42,7 @@ public class DetailedBolusInfoStorage {
for (int i = 0; i < store.size(); i++) {
long infoTime = store.get(i).date;
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);
break;
}

View file

@ -15,6 +15,8 @@ import android.widget.CheckBox;
import android.widget.LinearLayout;
import android.widget.TextView;
import com.crashlytics.android.Crashlytics;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -27,15 +29,6 @@ import info.nightscout.androidaps.R;
public class ObjectivesFragment extends Fragment {
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;
LinearLayoutManager llm;
CheckBox enableFake;
@ -59,7 +52,7 @@ public class ObjectivesFragment extends Fragment {
@Override
public void onBindViewHolder(ObjectiveViewHolder holder, int 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();
holder.position.setText(String.valueOf(position + 1));
holder.objective.setText(o.objective);
@ -83,7 +76,7 @@ public class ObjectivesFragment extends Fragment {
holder.verifyButton.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
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();
updateGUI();
ObjectivesPlugin.saveProgress();
@ -173,45 +166,52 @@ public class ObjectivesFragment extends Fragment {
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.objectives_fragment, container, false);
try {
View view = inflater.inflate(R.layout.objectives_fragment, container, false);
recyclerView = (RecyclerView) view.findViewById(R.id.objectives_recyclerview);
recyclerView.setHasFixedSize(true);
llm = new LinearLayoutManager(view.getContext());
recyclerView.setLayoutManager(llm);
enableFake = (CheckBox) view.findViewById(R.id.objectives_fake);
fake_layout = (LinearLayout) view.findViewById(R.id.objectives_fake_layout);
reset = (TextView) view.findViewById(R.id.objectives_reset);
enableFake.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
updateGUI();
}
});
reset.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
getPlugin().initializeData();
getPlugin().saveProgress();
updateGUI();
}
});
recyclerView = (RecyclerView) view.findViewById(R.id.objectives_recyclerview);
recyclerView.setHasFixedSize(true);
llm = new LinearLayoutManager(view.getContext());
recyclerView.setLayoutManager(llm);
enableFake = (CheckBox) view.findViewById(R.id.objectives_fake);
fake_layout = (LinearLayout) view.findViewById(R.id.objectives_fake_layout);
reset = (TextView) view.findViewById(R.id.objectives_reset);
enableFake.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
updateGUI();
}
});
reset.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
ObjectivesPlugin.getPlugin().initializeData();
ObjectivesPlugin.saveProgress();
updateGUI();
}
});
// Add correct translations to array after app is initialized
getPlugin().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);
getPlugin().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);
getPlugin().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);
getPlugin().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);
getPlugin().objectives.get(1).gate = MainApp.sResources.getString(R.string.objectives_1_gate);
getPlugin().objectives.get(2).gate = MainApp.sResources.getString(R.string.objectives_2_gate);
getPlugin().objectives.get(3).gate = MainApp.sResources.getString(R.string.objectives_3_gate);
getPlugin().objectives.get(4).gate = MainApp.sResources.getString(R.string.objectives_4_gate);
getPlugin().objectives.get(5).gate = MainApp.sResources.getString(R.string.objectives_5_gate);
updateGUI();
// Add correct translations to array after app is initialized
ObjectivesPlugin.objectives.get(0).objective = MainApp.sResources.getString(R.string.objectives_0_objective);
ObjectivesPlugin.objectives.get(1).objective = MainApp.sResources.getString(R.string.objectives_1_objective);
ObjectivesPlugin.objectives.get(2).objective = MainApp.sResources.getString(R.string.objectives_2_objective);
ObjectivesPlugin.objectives.get(3).objective = MainApp.sResources.getString(R.string.objectives_3_objective);
ObjectivesPlugin.objectives.get(4).objective = MainApp.sResources.getString(R.string.objectives_4_objective);
ObjectivesPlugin.objectives.get(5).objective = MainApp.sResources.getString(R.string.objectives_5_objective);
ObjectivesPlugin.objectives.get(6).objective = MainApp.sResources.getString(R.string.objectives_6_objective);
ObjectivesPlugin.objectives.get(7).objective = MainApp.sResources.getString(R.string.objectives_7_objective);
ObjectivesPlugin.objectives.get(0).gate = MainApp.sResources.getString(R.string.objectives_0_gate);
ObjectivesPlugin.objectives.get(1).gate = MainApp.sResources.getString(R.string.objectives_1_gate);
ObjectivesPlugin.objectives.get(2).gate = MainApp.sResources.getString(R.string.objectives_2_gate);
ObjectivesPlugin.objectives.get(3).gate = MainApp.sResources.getString(R.string.objectives_3_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();
return view;
return view;
} catch (Exception e) {
Crashlytics.logException(e);
}
return null;
}
void updateGUI() {

View file

@ -14,9 +14,15 @@ import info.nightscout.androidaps.BuildConfig;
import info.nightscout.androidaps.Config;
import info.nightscout.androidaps.MainApp;
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.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.NSClientInternal.NSClientInternalPlugin;
import info.nightscout.androidaps.plugins.PumpVirtual.VirtualPumpPlugin;
import info.nightscout.utils.SP;
/**
@ -25,11 +31,20 @@ import info.nightscout.utils.SP;
public class ObjectivesPlugin implements PluginBase, ConstraintsInterface {
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;
boolean fragmentVisible = true;
private boolean fragmentVisible = true;
public ObjectivesPlugin() {
private ObjectivesPlugin() {
initializeData();
loadProgress();
MainApp.bus().register(this);
@ -53,7 +68,7 @@ public class ObjectivesPlugin implements PluginBase, ConstraintsInterface {
@Override
public String getNameShort() {
String name = MainApp.sResources.getString(R.string.objectives_shortname);
if (!name.trim().isEmpty()){
if (!name.trim().isEmpty()) {
//only if translation exists
return name;
}
@ -63,12 +78,12 @@ public class ObjectivesPlugin implements PluginBase, ConstraintsInterface {
@Override
public boolean isEnabled(int type) {
return type == CONSTRAINTS && MainApp.getConfigBuilder().getPumpDescription().isTempBasalCapable;
return type == CONSTRAINTS && ConfigBuilderPlugin.getActivePump().getPumpDescription().isTempBasalCapable;
}
@Override
public boolean isVisibleInTabs(int type) {
return type == CONSTRAINTS && fragmentVisible && !BuildConfig.NSCLIENTOLNY;
return type == CONSTRAINTS && fragmentVisible && !Config.NSCLIENT && !Config.G5UPLOADER;
}
@Override
@ -95,7 +110,12 @@ public class ObjectivesPlugin implements PluginBase, ConstraintsInterface {
if (type == CONSTRAINTS) this.fragmentVisible = fragmentVisible;
}
public class Objective {
@Override
public int getPreferencesId() {
return -1;
}
class Objective {
Integer num;
String objective;
String gate;
@ -118,13 +138,13 @@ public class ObjectivesPlugin implements PluginBase, ConstraintsInterface {
public static boolean pumpStatusIsAvailableInNS = false;
// Objective 1
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;
String comment = "";
public RequirementResult(boolean done, String comment) {
RequirementResult(boolean done, String comment) {
this.done = done;
this.comment = comment;
}
@ -135,24 +155,47 @@ public class ObjectivesPlugin implements PluginBase, ConstraintsInterface {
else return "---";
}
public RequirementResult requirementsMet(Integer objNum) {
RequirementResult requirementsMet(Integer objNum) {
switch (objNum) {
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_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:
return new RequirementResult(manualEnacts >= manualEnactsNeeded,
MainApp.sResources.getString(R.string.objectives_manualenacts) + ": " + manualEnacts + "/" + manualEnactsNeeded);
case 2:
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:
return new RequirementResult(true, "");
}
}
public void initializeData() {
void initializeData() {
bgIsAvailableInNS = false;
pumpStatusIsAvailableInNS = false;
manualEnacts = 0;
@ -198,7 +241,13 @@ public class ObjectivesPlugin implements PluginBase, ConstraintsInterface {
MainApp.sResources.getString(R.string.objectives_6_objective),
"",
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)));
}
@ -220,7 +269,7 @@ public class ObjectivesPlugin implements PluginBase, ConstraintsInterface {
}
}
void loadProgress() {
private void loadProgress() {
for (int num = 0; num < objectives.size(); num++) {
Objective o = objectives.get(num);
try {
@ -246,7 +295,7 @@ public class ObjectivesPlugin implements PluginBase, ConstraintsInterface {
**/
@Override
public boolean isLoopEnabled() {
return objectives.get(1).started.getTime() > 0;
return objectives.get(0).started.getTime() > 0;
}
@Override
@ -264,14 +313,19 @@ public class ObjectivesPlugin implements PluginBase, ConstraintsInterface {
return objectives.get(6).started.getTime() > 0;
}
@Override
public boolean isSMBModeEnabled() {
return objectives.get(7).started.getTime() > 0;
}
@Override
public Double applyMaxIOBConstraints(Double maxIob) {
if (objectives.get(4).started.getTime() > 0 || objectives.get(2).accomplished.getTime() == 0)
return maxIob;
else {
if (objectives.get(3).started.getTime() > 0 && objectives.get(3).accomplished.getTime() == 0) {
if (Config.logConstraintsChanges)
log.debug("Limiting maxIOB " + maxIob + " to " + 0 + "U");
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.MainApp;
import info.nightscout.androidaps.R;
import info.nightscout.androidaps.data.Profile;
import info.nightscout.androidaps.interfaces.ConstraintsInterface;
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.Round;
import info.nightscout.utils.SP;
@ -86,9 +87,14 @@ public class SafetyPlugin implements PluginBase, ConstraintsInterface {
public void setFragmentVisible(int type, boolean fragmentVisible) {
}
@Override
public int getPreferencesId() {
return R.xml.pref_safety;
}
@Override
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;
}
@Override
public boolean isSMBModeEnabled() {
return true;
}
@Override
public Double applyBasalConstraints(Double 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 {
private static boolean fragmentEnabled = true;
private static boolean fragmentVisible = false;
private boolean fragmentEnabled = true;
private boolean fragmentVisible = false;
private static InsulinFastactingPlugin plugin = null;
@ -80,6 +80,11 @@ public class InsulinFastactingPlugin implements PluginBase, InsulinInterface {
if (type == INSULIN) this.fragmentVisible = fragmentVisible;
}
@Override
public int getPreferencesId() {
return -1;
}
// Insulin interface
@Override
public int getId() {
@ -102,7 +107,7 @@ public class InsulinFastactingPlugin implements PluginBase, InsulinInterface {
}
@Override
public Iob iobCalcForTreatment(Treatment treatment, long time, Double dia) {
public Iob iobCalcForTreatment(Treatment treatment, long time, double dia) {
Iob result = new Iob();
double scaleFactor = 3.0 / dia;

View file

@ -14,8 +14,8 @@ import info.nightscout.androidaps.interfaces.PluginBase;
public class InsulinFastactingProlongedPlugin implements PluginBase, InsulinInterface {
private static boolean fragmentEnabled = false;
private static boolean fragmentVisible = false;
private boolean fragmentEnabled = false;
private boolean fragmentVisible = false;
private static InsulinFastactingProlongedPlugin plugin = null;
@ -80,6 +80,11 @@ public class InsulinFastactingProlongedPlugin implements PluginBase, InsulinInte
if (type == INSULIN) this.fragmentVisible = fragmentVisible;
}
@Override
public int getPreferencesId() {
return -1;
}
// Insulin interface
@Override
public int getId() {
@ -102,7 +107,7 @@ public class InsulinFastactingProlongedPlugin implements PluginBase, InsulinInte
}
@Override
public Iob iobCalcForTreatment(Treatment treatment, long time, Double dia) {
public Iob iobCalcForTreatment(Treatment treatment, long time, double dia) {
Iob result = new Iob();
//Double scaleFactor = 3.0 / dia;

View file

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

View file

@ -1,13 +1,14 @@
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.R;
import info.nightscout.androidaps.data.Iob;
import info.nightscout.androidaps.db.Treatment;
import info.nightscout.androidaps.interfaces.InsulinInterface;
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;
/**
@ -45,38 +46,53 @@ public abstract class InsulinOrefBasePlugin implements PluginBase, InsulinInterf
return true;
}
public Bus getBus() {
return MainApp.bus();
}
@Override
public double getDia() {
double dia = getUserDefinedDia();
if(dia >= MIN_DIA){
return dia;
} else {
if((System.currentTimeMillis() - lastWarned) > 60*1000) {
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));
}
sendShortDiaNotification(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() {
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
public Iob iobCalcForTreatment(Treatment treatment, long time, Double dia) {
public Iob iobCalcForTreatment(Treatment treatment, long time, double dia) {
Iob result = new Iob();
int peak = getPeak();
if (treatment.insulin != 0d) {
long bolusTime = treatment.date;
double t = (time - bolusTime) / 1000d / 60d;
double td = getDia()*60; //getDIA() always > 5
double td = getDia()*60; //getDIA() always >= MIN_DIA
double tp = peak;
// 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 {
private static boolean fragmentEnabled = false;
private static boolean fragmentVisible = false;
private boolean fragmentEnabled = false;
private boolean fragmentVisible = false;
private static InsulinOrefFreePeakPlugin plugin = null;
@ -68,6 +68,11 @@ public class InsulinOrefFreePeakPlugin extends InsulinOrefBasePlugin {
if (type == INSULIN) this.fragmentVisible = fragmentVisible;
}
@Override
public int getPreferencesId() {
return R.xml.pref_insulinoreffreepeak;
}
@Override
int getPeak() {
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 {
private static boolean fragmentEnabled = false;
private static boolean fragmentVisible = false;
private boolean fragmentEnabled = false;
private boolean fragmentVisible = false;
private static InsulinOrefRapidActingPlugin plugin = null;
@ -67,6 +67,11 @@ public class InsulinOrefRapidActingPlugin extends InsulinOrefBasePlugin {
if (type == INSULIN) this.fragmentVisible = fragmentVisible;
}
@Override
public int getPreferencesId() {
return -1;
}
@Override
int getPeak() {
return PEAK;

View file

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

View file

@ -13,6 +13,7 @@ import info.nightscout.androidaps.data.Profile;
import info.nightscout.androidaps.db.Treatment;
import info.nightscout.androidaps.interfaces.PluginBase;
import info.nightscout.androidaps.plugins.SensitivityAAPS.SensitivityAAPSPlugin;
import info.nightscout.androidaps.plugins.SensitivityWeightedAverage.SensitivityWeightedAveragePlugin;
import info.nightscout.utils.SP;
/**
@ -32,7 +33,7 @@ public class AutosensData {
time = t.date;
carbs = 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);
Profile profile = MainApp.getConfigBuilder().getProfile(t.date);
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.

View file

@ -1,7 +1,6 @@
package info.nightscout.androidaps.plugins.IobCobCalculator;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.SystemClock;
import android.support.annotation.Nullable;
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.db.BgReading;
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.EventNewBG;
import info.nightscout.androidaps.events.EventNewBasalProfile;
import info.nightscout.androidaps.events.EventPreferenceChange;
import info.nightscout.androidaps.interfaces.PluginBase;
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.utils.DateUtil;
/**
* Created by mike on 24.04.2017.
@ -50,10 +48,10 @@ public class IobCobCalculatorPlugin implements PluginBase {
private static double dia = Constants.defaultDIA;
private static Handler sHandler = null;
private static HandlerThread sHandlerThread = null;
static final Object dataLock = new Object();
private static final Object dataLock = new Object();
boolean stopCalculationTrigger = false;
IobCobThread thread = null;
private static IobCobCalculatorPlugin plugin = null;
@ -126,14 +124,13 @@ public class IobCobCalculatorPlugin implements PluginBase {
}
@Override
public int getPreferencesId() {
return -1;
}
IobCobCalculatorPlugin() {
MainApp.bus().register(this);
if (sHandlerThread == null) {
sHandlerThread = new HandlerThread(IobCobCalculatorPlugin.class.getSimpleName());
sHandlerThread.start();
sHandler = new Handler(sHandlerThread.getLooper());
}
onNewBg(new EventNewBG());
}
@Nullable
@ -170,14 +167,9 @@ public class IobCobCalculatorPlugin implements PluginBase {
return rouded;
}
private void loadBgData() {
//log.debug("Locking loadBgData");
synchronized (dataLock) {
onNewProfile(null);
bgReadings = MainApp.getDbHelper().getBgreadingsDataFromTime((long) (System.currentTimeMillis() - 60 * 60 * 1000L * (24 + dia)), false);
log.debug("BG data loaded. Size: " + bgReadings.size());
}
//log.debug("Releasing loadBgData");
void loadBgData() {
bgReadings = MainApp.getDbHelper().getBgreadingsDataFromTime((long) (System.currentTimeMillis() - 60 * 60 * 1000L * (24 + dia)), false);
log.debug("BG data loaded. Size: " + bgReadings.size());
}
private boolean isAbout5minData() {
@ -204,7 +196,7 @@ public class IobCobCalculatorPlugin implements PluginBase {
}
}
private void createBucketedData() {
void createBucketedData() {
if (isAbout5minData())
createBucketedData5min();
else
@ -227,7 +219,7 @@ public class IobCobCalculatorPlugin implements PluginBase {
private BgReading findOlder(long time) {
BgReading lastFound = bgReadings.get(bgReadings.size() - 1);
if (lastFound.date > time) return null;
for (int i = bgReadings.size() - 2; i >=0 ; --i) {
for (int i = bgReadings.size() - 2; i >= 0; --i) {
if (bgReadings.get(i).date < time) continue;
lastFound = bgReadings.get(i);
if (bgReadings.get(i).date > time) break;
@ -236,218 +228,97 @@ public class IobCobCalculatorPlugin implements PluginBase {
}
private void createBucketedDataRecalculated() {
synchronized (dataLock) {
if (bgReadings == null || bgReadings.size() < 3) {
bucketed_data = null;
return;
}
if (bgReadings == null || bgReadings.size() < 3) {
bucketed_data = null;
return;
}
bucketed_data = new ArrayList<>();
long currentTime = bgReadings.get(0).date + 5 * 60 * 1000 - bgReadings.get(0).date % (5 * 60 * 1000) - 5 * 60 * 1000L;
//log.debug("First reading: " + new Date(currentTime).toLocaleString());
bucketed_data = new ArrayList<>();
long currentTime = bgReadings.get(0).date + 5 * 60 * 1000 - bgReadings.get(0).date % (5 * 60 * 1000) - 5 * 60 * 1000L;
//log.debug("First reading: " + new Date(currentTime).toLocaleString());
while (true) {
// test if current value is older than current time
BgReading newer = findNewer(currentTime);
BgReading older = findOlder(currentTime);
if (newer == null || older == null)
break;
while (true) {
// test if current value is older than current time
BgReading newer = findNewer(currentTime);
BgReading older = findOlder(currentTime);
if (newer == null || older == null)
break;
double bgDelta = newer.value - older.value;
long timeDiffToNew = newer.date - currentTime;
double bgDelta = newer.value - older.value;
long timeDiffToNew = newer.date - currentTime;
double currentBg = newer.value - (double) timeDiffToNew / (newer.date - older.date) * bgDelta;
BgReading newBgreading = new BgReading();
newBgreading.date = currentTime;
newBgreading.value = Math.round(currentBg);
bucketed_data.add(newBgreading);
//log.debug("BG: " + newBgreading.value + " (" + new Date(newBgreading.date).toLocaleString() + ") Prev: " + older.value + " (" + new Date(older.date).toLocaleString() + ") Newer: " + newer.value + " (" + new Date(newer.date).toLocaleString() + ")");
currentTime -= 5 * 60 * 1000L;
double currentBg = newer.value - (double) timeDiffToNew / (newer.date - older.date) * bgDelta;
BgReading newBgreading = new BgReading();
newBgreading.date = currentTime;
newBgreading.value = Math.round(currentBg);
bucketed_data.add(newBgreading);
//log.debug("BG: " + newBgreading.value + " (" + new Date(newBgreading.date).toLocaleString() + ") Prev: " + older.value + " (" + new Date(older.date).toLocaleString() + ") Newer: " + newer.value + " (" + new Date(newer.date).toLocaleString() + ")");
currentTime -= 5 * 60 * 1000L;
}
}
}
public void createBucketedData5min() {
//log.debug("Locking createBucketedData");
synchronized (dataLock) {
if (bgReadings == null || bgReadings.size() < 3) {
bucketed_data = null;
return;
if (bgReadings == null || bgReadings.size() < 3) {
bucketed_data = null;
return;
}
bucketed_data = new ArrayList<>();
bucketed_data.add(bgReadings.get(0));
int j = 0;
for (int i = 1; i < bgReadings.size(); ++i) {
long bgTime = bgReadings.get(i).date;
long lastbgTime = bgReadings.get(i - 1).date;
//log.error("Processing " + i + ": " + new Date(bgTime).toString() + " " + bgReadings.get(i).value + " Previous: " + new Date(lastbgTime).toString() + " " + bgReadings.get(i - 1).value);
if (bgReadings.get(i).value < 39 || bgReadings.get(i - 1).value < 39) {
continue;
}
bucketed_data = new ArrayList<>();
bucketed_data.add(bgReadings.get(0));
int j = 0;
for (int i = 1; i < bgReadings.size(); ++i) {
long bgTime = bgReadings.get(i).date;
long lastbgTime = bgReadings.get(i - 1).date;
//log.error("Processing " + i + ": " + new Date(bgTime).toString() + " " + bgReadings.get(i).value + " Previous: " + new Date(lastbgTime).toString() + " " + bgReadings.get(i - 1).value);
if (bgReadings.get(i).value < 39 || bgReadings.get(i - 1).value < 39) {
continue;
}
long elapsed_minutes = (bgTime - lastbgTime) / (60 * 1000);
if (Math.abs(elapsed_minutes) > 8) {
// interpolate missing data points
double lastbg = bgReadings.get(i - 1).value;
elapsed_minutes = Math.abs(elapsed_minutes);
//console.error(elapsed_minutes);
long nextbgTime;
while (elapsed_minutes > 5) {
nextbgTime = lastbgTime - 5 * 60 * 1000;
j++;
BgReading newBgreading = new BgReading();
newBgreading.date = nextbgTime;
double gapDelta = bgReadings.get(i).value - lastbg;
//console.error(gapDelta, lastbg, elapsed_minutes);
double nextbg = lastbg + (5d / elapsed_minutes * gapDelta);
newBgreading.value = Math.round(nextbg);
//console.error("Interpolated", bucketed_data[j]);
bucketed_data.add(newBgreading);
//log.error("******************************************************************************************************* Adding:" + new Date(newBgreading.date).toString() + " " + newBgreading.value);
elapsed_minutes = elapsed_minutes - 5;
lastbg = nextbg;
lastbgTime = nextbgTime;
}
long elapsed_minutes = (bgTime - lastbgTime) / (60 * 1000);
if (Math.abs(elapsed_minutes) > 8) {
// interpolate missing data points
double lastbg = bgReadings.get(i - 1).value;
elapsed_minutes = Math.abs(elapsed_minutes);
//console.error(elapsed_minutes);
long nextbgTime;
while (elapsed_minutes > 5) {
nextbgTime = lastbgTime - 5 * 60 * 1000;
j++;
BgReading newBgreading = new BgReading();
newBgreading.value = bgReadings.get(i).value;
newBgreading.date = bgTime;
newBgreading.date = nextbgTime;
double gapDelta = bgReadings.get(i).value - lastbg;
//console.error(gapDelta, lastbg, elapsed_minutes);
double nextbg = lastbg + (5d / elapsed_minutes * gapDelta);
newBgreading.value = Math.round(nextbg);
//console.error("Interpolated", bucketed_data[j]);
bucketed_data.add(newBgreading);
//log.error("******************************************************************************************************* Copying:" + new Date(newBgreading.date).toString() + " " + newBgreading.value);
} else if (Math.abs(elapsed_minutes) > 2) {
j++;
BgReading newBgreading = new BgReading();
newBgreading.value = bgReadings.get(i).value;
newBgreading.date = bgTime;
bucketed_data.add(newBgreading);
//log.error("******************************************************************************************************* Copying:" + new Date(newBgreading.date).toString() + " " + newBgreading.value);
} else {
bucketed_data.get(j).value = (bucketed_data.get(j).value + bgReadings.get(i).value) / 2;
//log.error("***** Average");
//log.error("******************************************************************************************************* Adding:" + new Date(newBgreading.date).toString() + " " + newBgreading.value);
elapsed_minutes = elapsed_minutes - 5;
lastbg = nextbg;
lastbgTime = nextbgTime;
}
}
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));
j++;
BgReading newBgreading = new BgReading();
newBgreading.value = bgReadings.get(i).value;
newBgreading.date = bgTime;
bucketed_data.add(newBgreading);
//log.error("******************************************************************************************************* Copying:" + new Date(newBgreading.date).toString() + " " + newBgreading.value);
} else if (Math.abs(elapsed_minutes) > 2) {
j++;
BgReading newBgreading = new BgReading();
newBgreading.value = bgReadings.get(i).value;
newBgreading.date = bgTime;
bucketed_data.add(newBgreading);
//log.error("******************************************************************************************************* Copying:" + new Date(newBgreading.date).toString() + " " + newBgreading.value);
} else {
bucketed_data.get(j).value = (bucketed_data.get(j).value + bgReadings.get(i).value) / 2;
//log.error("***** Average");
}
}
MainApp.bus().post(new EventAutosensCalculationFinished());
//log.debug("Releasing calculateSensitivityData");
log.debug("Bucketed data created. Size: " + bucketed_data.size());
}
public static long oldestDataAvailable() {
@ -535,6 +406,10 @@ public class IobCobCalculatorPlugin implements PluginBase {
//log.debug(">>> getAutosensData Cache hit " + data.log(time));
return data;
} 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());
return null;
}
@ -542,13 +417,35 @@ public class IobCobCalculatorPlugin implements PluginBase {
}
@Nullable
public static AutosensData getLastAutosensData() {
if (autosensDataTable.size() < 1)
public static AutosensData getLastAutosensDataSynchronized(String reason) {
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;
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;
} else {
if (data == null)
log.debug("AUTOSENSDATA null: data == null (" + " " + reason + ") size()=" + autosensDataTable.size() + " lastdata=" + DateUtil.dateAndTimeString(data.time));
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);
}
@ -589,15 +486,33 @@ public class IobCobCalculatorPlugin implements PluginBase {
}
@Subscribe
public void onNewBg(EventNewBG ev) {
sHandler.post(new Runnable() {
@Override
public void run() {
loadBgData();
createBucketedData();
calculateSensitivityData();
public void onEventAppInitialized(EventAppInitialized ev) {
runCalculation("onEventAppInitialized", true);
}
@Subscribe
public void onEventNewBG(EventNewBG ev) {
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
@ -611,64 +526,53 @@ public class IobCobCalculatorPlugin implements PluginBase {
if (ev == null) { // on init no need of reset
return;
}
stopCalculation("onNewProfile");
synchronized (dataLock) {
log.debug("Invalidating cached data because of new profile. IOB: " + iobTable.size() + " Autosens: " + autosensDataTable.size() + " records");
iobTable = new LongSparseArray<>();
autosensDataTable = new LongSparseArray<>();
}
sHandler.post(new Runnable() {
@Override
public void run() {
calculateSensitivityData();
}
});
runCalculation("onNewProfile", false);
}
@Subscribe
public void onStatusEvent(EventPreferenceChange ev) {
public void onEventPreferenceChange(EventPreferenceChange ev) {
if (ev.isChanged(R.string.key_openapsama_autosens_period) ||
ev.isChanged(R.string.key_age) ||
ev.isChanged(R.string.key_absorption_maxtime)
) {
stopCalculation("onEventPreferenceChange");
synchronized (dataLock) {
log.debug("Invalidating cached data because of preference change. IOB: " + iobTable.size() + " Autosens: " + autosensDataTable.size() + " records");
iobTable = new LongSparseArray<>();
autosensDataTable = new LongSparseArray<>();
}
sHandler.post(new Runnable() {
@Override
public void run() {
calculateSensitivityData();
}
});
runCalculation("onEventPreferenceChange", false);
}
}
@Subscribe
public void onStatusEvent(EventConfigBuilderChange ev) {
public void onEventConfigBuilderChange(EventConfigBuilderChange ev) {
stopCalculation("onEventConfigBuilderChange");
synchronized (dataLock) {
log.debug("Invalidating cached data because of configuration change. IOB: " + iobTable.size() + " Autosens: " + autosensDataTable.size() + " records");
iobTable = new LongSparseArray<>();
autosensDataTable = new LongSparseArray<>();
}
sHandler.post(new Runnable() {
@Override
public void run() {
calculateSensitivityData();
}
});
runCalculation("onEventConfigBuilderChange", false);
}
// When historical data is changed (comming from NS etc) finished calculations after this date must be invalidated
@Subscribe
public void onNewHistoryData(EventNewHistoryData ev) {
public void onEventNewHistoryData(EventNewHistoryData ev) {
//log.debug("Locking onNewHistoryData");
stopCalculation("onEventNewHistoryData");
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());
for (int index = iobTable.size() - 1; index >= 0; index--) {
if (iobTable.keyAt(index) > time) {
if (Config.logAutosensData)
if (Config.logAutosensData)
log.debug("Removing from iobTable: " + new Date(iobTable.keyAt(index)).toLocaleString());
iobTable.removeAt(index);
@ -695,12 +599,7 @@ public class IobCobCalculatorPlugin implements PluginBase {
}
}
}
sHandler.post(new Runnable() {
@Override
public void run() {
calculateSensitivityData();
}
});
runCalculation("onEventNewHistoryData", false);
//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;
import info.nightscout.androidaps.events.EventLoop;
/**
* 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;
import info.nightscout.androidaps.events.Event;
/**
* Created by mike on 26.04.2017.
*/
public class EventNewHistoryData {
public class EventNewHistoryData extends Event {
public long time = 0;
public EventNewHistoryData(long time) {

View file

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

View file

@ -9,6 +9,7 @@ import android.view.ViewGroup;
import android.widget.Button;
import android.widget.TextView;
import com.crashlytics.android.Crashlytics;
import com.crashlytics.android.answers.Answers;
import com.crashlytics.android.answers.CustomEvent;
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 {
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;
TextView lastRunView;
TextView lastEnactView;
@ -46,19 +38,25 @@ public class LoopFragment extends SubscriberFragment implements View.OnClickList
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.loop_fragment, container, false);
try {
View view = inflater.inflate(R.layout.loop_fragment, container, false);
lastRunView = (TextView) view.findViewById(R.id.loop_lastrun);
lastEnactView = (TextView) view.findViewById(R.id.loop_lastenact);
sourceView = (TextView) view.findViewById(R.id.loop_source);
requestView = (TextView) view.findViewById(R.id.loop_request);
constraintsProcessedView = (TextView) view.findViewById(R.id.loop_constraintsprocessed);
setByPumpView = (TextView) view.findViewById(R.id.loop_setbypump);
runNowButton = (Button) view.findViewById(R.id.loop_run);
runNowButton.setOnClickListener(this);
lastRunView = (TextView) view.findViewById(R.id.loop_lastrun);
lastEnactView = (TextView) view.findViewById(R.id.loop_lastenact);
sourceView = (TextView) view.findViewById(R.id.loop_source);
requestView = (TextView) view.findViewById(R.id.loop_request);
constraintsProcessedView = (TextView) view.findViewById(R.id.loop_constraintsprocessed);
setByPumpView = (TextView) view.findViewById(R.id.loop_setbypump);
runNowButton = (Button) view.findViewById(R.id.loop_run);
runNowButton.setOnClickListener(this);
updateGUI();
return view;
updateGUI();
return view;
} catch (Exception e) {
Crashlytics.logException(e);
}
return null;
}
@Override
@ -69,7 +67,7 @@ public class LoopFragment extends SubscriberFragment implements View.OnClickList
Thread thread = new Thread(new Runnable() {
@Override
public void run() {
getPlugin().invoke("Loop button", true);
LoopPlugin.getPlugin().invoke("Loop button", true);
}
});
thread.start();
@ -105,13 +103,13 @@ public class LoopFragment extends SubscriberFragment implements View.OnClickList
activity.runOnUiThread(new Runnable() {
@Override
public void run() {
if (getPlugin().lastRun != null) {
requestView.setText(getPlugin().lastRun.request != null ? getPlugin().lastRun.request.toSpanned() : "");
constraintsProcessedView.setText(getPlugin().lastRun.constraintsProcessed != null ? getPlugin().lastRun.constraintsProcessed.toSpanned() : "");
setByPumpView.setText(getPlugin().lastRun.setByPump != null ? getPlugin().lastRun.setByPump.toSpanned() : "");
sourceView.setText(getPlugin().lastRun.source != null ? getPlugin().lastRun.source : "");
lastRunView.setText(getPlugin().lastRun.lastAPSRun != null && getPlugin().lastRun.lastAPSRun.getTime() != 0 ? getPlugin().lastRun.lastAPSRun.toLocaleString() : "");
lastEnactView.setText(getPlugin().lastRun.lastEnact != null && getPlugin().lastRun.lastEnact.getTime() != 0 ? getPlugin().lastRun.lastEnact.toLocaleString() : "");
if (LoopPlugin.lastRun != null) {
requestView.setText(LoopPlugin.lastRun.request != null ? LoopPlugin.lastRun.request.toSpanned() : "");
constraintsProcessedView.setText(LoopPlugin.lastRun.constraintsProcessed != null ? LoopPlugin.lastRun.constraintsProcessed.toSpanned() : "");
setByPumpView.setText(LoopPlugin.lastRun.setByPump != null ? LoopPlugin.lastRun.setByPump.toSpanned() : "");
sourceView.setText(LoopPlugin.lastRun.source != null ? LoopPlugin.lastRun.source : "");
lastRunView.setText(LoopPlugin.lastRun.lastAPSRun != null && LoopPlugin.lastRun.lastAPSRun.getTime() != 0 ? LoopPlugin.lastRun.lastAPSRun.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.content.Context;
import android.content.Intent;
import android.os.Handler;
import android.os.HandlerThread;
import android.support.v7.app.NotificationCompat;
import android.support.v4.app.NotificationCompat;
import com.crashlytics.android.answers.Answers;
import com.crashlytics.android.answers.CustomEvent;
import com.squareup.otto.Subscribe;
import org.json.JSONException;
import org.slf4j.Logger;
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.ConstraintsInterface;
import info.nightscout.androidaps.interfaces.PluginBase;
import info.nightscout.androidaps.interfaces.PumpInterface;
import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin;
import info.nightscout.androidaps.plugins.Loop.events.EventLoopSetLastRunGui;
import info.nightscout.androidaps.plugins.Loop.events.EventLoopUpdateGui;
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.SP;
import info.nightscout.utils.SafeParse;
/**
* Created by mike on 05.08.2016.
@ -46,14 +43,21 @@ import info.nightscout.utils.SafeParse;
public class LoopPlugin implements PluginBase {
private static Logger log = LoggerFactory.getLogger(LoopPlugin.class);
private static Handler sHandler;
private static HandlerThread sHandlerThread;
private static LoopPlugin loopPlugin;
public static LoopPlugin getPlugin() {
if (loopPlugin == null) {
loopPlugin = new LoopPlugin();
}
return loopPlugin;
}
private boolean fragmentEnabled = false;
private boolean fragmentVisible = false;
private long loopSuspendedTill = 0L; // end of manual loop suspend
private boolean isSuperBolus = false;
private boolean isDisconnected = false;
public class LastRun {
public APSResult request = null;
@ -68,14 +72,10 @@ public class LoopPlugin implements PluginBase {
static public LastRun lastRun = null;
public LoopPlugin() {
if (sHandlerThread == null) {
sHandlerThread = new HandlerThread(LoopPlugin.class.getSimpleName());
sHandlerThread.start();
sHandler = new Handler(sHandlerThread.getLooper());
}
MainApp.bus().register(this);
loopSuspendedTill = SP.getLong("loopSuspendedTill", 0L);
isSuperBolus = SP.getBoolean("isSuperBolus", false);
isDisconnected = SP.getBoolean("isDisconnected", false);
}
@Override
@ -96,7 +96,7 @@ public class LoopPlugin implements PluginBase {
@Override
public String getNameShort() {
String name = MainApp.sResources.getString(R.string.loop_shortname);
if (!name.trim().isEmpty()){
if (!name.trim().isEmpty()) {
//only if translation exists
return name;
}
@ -106,12 +106,14 @@ public class LoopPlugin implements PluginBase {
@Override
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
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
@ -139,6 +141,11 @@ public class LoopPlugin implements PluginBase {
if (type == LOOP) this.fragmentVisible = fragmentVisible;
}
@Override
public int getPreferencesId() {
return R.xml.pref_closedmode;
}
@Subscribe
public void onStatusEvent(final EventTreatmentChange ev) {
invoke("EventTreatmentChange", true);
@ -156,13 +163,28 @@ public class LoopPlugin implements PluginBase {
public void suspendTo(long endTime) {
loopSuspendedTill = endTime;
isSuperBolus = false;
isDisconnected = false;
SP.putLong("loopSuspendedTill", loopSuspendedTill);
SP.putBoolean("isSuperBolus", isSuperBolus);
SP.putBoolean("isDisconnected", isDisconnected);
}
public void superBolusTo(long endTime) {
loopSuspendedTill = endTime;
isSuperBolus = true;
isDisconnected = false;
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() {
@ -194,7 +216,7 @@ public class LoopPlugin implements PluginBase {
return true;
}
public boolean isSuperBolus() {
public boolean isSuperBolus() {
if (loopSuspendedTill == 0)
return false;
@ -208,6 +230,19 @@ public class LoopPlugin implements PluginBase {
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) {
try {
if (Config.logFunctionCalls)
@ -218,34 +253,22 @@ public class LoopPlugin implements PluginBase {
MainApp.bus().post(new EventLoopSetLastRunGui(MainApp.sResources.getString(R.string.loopdisabled)));
return;
}
final ConfigBuilderPlugin configBuilder = MainApp.getConfigBuilder();
final PumpInterface pump = ConfigBuilderPlugin.getActivePump();
APSResult result = null;
if (configBuilder == null || !isEnabled(PluginBase.LOOP))
if (!isEnabled(PluginBase.LOOP))
return;
if (isSuspended()) {
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) {
if (MainApp.getConfigBuilder().getProfile() == null) {
log.debug(MainApp.sResources.getString(R.string.noprofileselected));
MainApp.bus().post(new EventLoopSetLastRunGui(MainApp.sResources.getString(R.string.noprofileselected)));
return;
}
// 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)) {
usedAPS.invoke(initiator);
result = usedAPS.getLastAPSResult();
@ -268,20 +291,33 @@ public class LoopPlugin implements PluginBase {
lastRun.source = ((PluginBase) usedAPS).getName();
lastRun.setByPump = null;
if (constraintsInterface.isClosedModeEnabled()) {
NSUpload.uploadDeviceStatus();
if (isSuspended()) {
log.debug(MainApp.sResources.getString(R.string.loopsuspended));
MainApp.bus().post(new EventLoopSetLastRunGui(MainApp.sResources.getString(R.string.loopsuspended)));
return;
}
if (pump.isSuspended()) {
log.debug(MainApp.sResources.getString(R.string.pumpsuspended));
MainApp.bus().post(new EventLoopSetLastRunGui(MainApp.sResources.getString(R.string.pumpsuspended)));
return;
}
if (constraintsInterface.isClosedModeEnabled()) {
if (result.changeRequested) {
final PumpEnactResult waiting = new PumpEnactResult();
final PumpEnactResult previousResult = lastRun.setByPump;
waiting.queued = true;
lastRun.setByPump = waiting;
MainApp.bus().post(new EventLoopUpdateGui());
sHandler.post(new Runnable() {
MainApp.getConfigBuilder().applyAPSRequest(resultAfterConstraints, new Callback() {
@Override
public void run() {
final PumpEnactResult applyResult = configBuilder.applyAPSRequest(resultAfterConstraints);
Answers.getInstance().logCustom(new CustomEvent("APSRequest"));
if (applyResult.enacted || applyResult.success) {
lastRun.setByPump = applyResult;
if (result.enacted || result.success) {
lastRun.setByPump = result;
lastRun.lastEnact = lastRun.lastAPSRun;
} else {
lastRun.setByPump = previousResult;
@ -329,7 +365,6 @@ public class LoopPlugin implements PluginBase {
}
MainApp.bus().post(new EventLoopUpdateGui());
NSUpload.uploadDeviceStatus();
} finally {
if (Config.logFunctionCalls)
log.debug("invoke end");

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