Merge branch 'dev' into smb060

This commit is contained in:
Milos Kozak 2018-01-26 11:54:09 +01:00
commit 98e850b1b3
49 changed files with 1057 additions and 460 deletions

View file

@ -7,12 +7,15 @@ android:
components: components:
- platform-tools - platform-tools
- tools - tools
- build-tools-26.0.2 - build-tools-27.0.2
- android-23 - android-23
- extra-google-m2repository - extra-google-m2repository
- extra-android-m2repository - extra-android-m2repository
- extra-google-google_play_services - extra-google-google_play_services
before_install:
- yes | sdkmanager "platforms;android-27"
script: script:
# Unit Test # Unit Test
- ./gradlew test jacocoTestReport - ./gradlew test jacocoTestReport

View file

@ -12,9 +12,10 @@ buildscript {
apply plugin: "com.android.application" apply plugin: "com.android.application"
apply plugin: "io.fabric" apply plugin: "io.fabric"
apply plugin: "jacoco-android" apply plugin: "jacoco-android"
apply plugin: 'com.jakewharton.butterknife'
ext { ext {
supportLibraryVersion = "23.4.0" supportLibraryVersion = "27.0.2"
ormLiteVersion = "4.46" ormLiteVersion = "4.46"
powermockVersion = "1.7.3" powermockVersion = "1.7.3"
dexmakerVersion = "1.2" dexmakerVersion = "1.2"
@ -47,8 +48,8 @@ def generateGitBuild = { ->
} }
android { android {
compileSdkVersion 23 compileSdkVersion 27
buildToolsVersion "26.0.2" buildToolsVersion "${supportLibraryVersion}"
defaultConfig { defaultConfig {
applicationId "info.nightscout.androidaps" applicationId "info.nightscout.androidaps"
@ -204,6 +205,9 @@ dependencies {
compile "net.danlew:android.joda:2.9.9.1" 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 "junit:junit:4.12"
testCompile "org.json:json:20140107" testCompile "org.json:json:20140107"
testCompile "org.mockito:mockito-core:2.7.22" testCompile "org.mockito:mockito-core:2.7.22"

View file

@ -82,7 +82,7 @@ public class MainActivity extends AppCompatActivity implements View.OnClickListe
Manifest.permission.WRITE_EXTERNAL_STORAGE}, CASE_STORAGE); Manifest.permission.WRITE_EXTERNAL_STORAGE}, CASE_STORAGE);
} }
askForBatteryOptimizationPermission(); askForBatteryOptimizationPermission();
checkUpgradeToProfileTarget(); doMigrations();
if (Config.logFunctionCalls) if (Config.logFunctionCalls)
log.debug("onCreate"); log.debug("onCreate");
@ -163,6 +163,19 @@ public class MainActivity extends AppCompatActivity implements View.OnClickListe
} }
} }
private void doMigrations() {
checkUpgradeToProfileTarget();
// guarantee that the unreachable threshold is at least 30 and of type String
// Added in 1.57 at 21.01.2018
Integer unreachable_threshold = SP.getInt(R.string.key_pump_unreachable_threshold, 30);
SP.remove(R.string.key_pump_unreachable_threshold);
if(unreachable_threshold < 30) unreachable_threshold = 30;
SP.putString(R.string.key_pump_unreachable_threshold, unreachable_threshold.toString());
}
private void checkUpgradeToProfileTarget() { // TODO: can be removed in the future private void checkUpgradeToProfileTarget() { // TODO: can be removed in the future
boolean oldKeyExists = SP.contains("openapsma_min_bg"); boolean oldKeyExists = SP.contains("openapsma_min_bg");
if (oldKeyExists) { if (oldKeyExists) {

View file

@ -235,6 +235,10 @@ public class MainApp extends Application {
return sResources.getString(id); return sResources.getString(id);
} }
public static String gs(int id, Object... args) {
return sResources.getString(id, args);
}
public static MainApp instance() { public static MainApp instance() {
return sInstance; return sInstance;
} }

View file

@ -15,20 +15,22 @@ import org.slf4j.LoggerFactory;
import info.nightscout.androidaps.Config; import info.nightscout.androidaps.Config;
import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.R; import info.nightscout.androidaps.R;
import info.nightscout.androidaps.data.ProfileStore;
import info.nightscout.androidaps.db.BgReading; import info.nightscout.androidaps.db.BgReading;
import info.nightscout.androidaps.db.CareportalEvent; import info.nightscout.androidaps.db.CareportalEvent;
import info.nightscout.androidaps.events.EventNewBasalProfile; import info.nightscout.androidaps.events.EventNewBasalProfile;
import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin; import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin;
import info.nightscout.androidaps.plugins.ConstraintsObjectives.ObjectivesPlugin; import info.nightscout.androidaps.plugins.ConstraintsObjectives.ObjectivesPlugin;
import info.nightscout.androidaps.plugins.NSClientInternal.data.NSDeviceStatus;
import info.nightscout.androidaps.plugins.NSClientInternal.data.NSMbg; import info.nightscout.androidaps.plugins.NSClientInternal.data.NSMbg;
import info.nightscout.androidaps.plugins.NSClientInternal.data.NSSgv;
import info.nightscout.androidaps.data.ProfileStore;
import info.nightscout.androidaps.plugins.NSClientInternal.data.NSSettingsStatus; import info.nightscout.androidaps.plugins.NSClientInternal.data.NSSettingsStatus;
import info.nightscout.androidaps.plugins.Overview.notifications.Notification; import info.nightscout.androidaps.plugins.NSClientInternal.data.NSSgv;
import info.nightscout.androidaps.plugins.Overview.OverviewPlugin; import info.nightscout.androidaps.plugins.Overview.OverviewPlugin;
import info.nightscout.androidaps.plugins.Overview.events.EventDismissNotification; import info.nightscout.androidaps.plugins.Overview.events.EventDismissNotification;
import info.nightscout.androidaps.plugins.Overview.events.EventNewNotification; import info.nightscout.androidaps.plugins.Overview.events.EventNewNotification;
import info.nightscout.androidaps.plugins.Overview.notifications.Notification;
import info.nightscout.androidaps.plugins.ProfileNS.NSProfilePlugin; import info.nightscout.androidaps.plugins.ProfileNS.NSProfilePlugin;
import info.nightscout.androidaps.plugins.ProfileNS.events.EventNSProfileUpdateGUI;
import info.nightscout.androidaps.plugins.PumpDanaR.activities.DanaRNSHistorySync; import info.nightscout.androidaps.plugins.PumpDanaR.activities.DanaRNSHistorySync;
import info.nightscout.androidaps.plugins.SmsCommunicator.events.EventNewSMS; import info.nightscout.androidaps.plugins.SmsCommunicator.events.EventNewSMS;
import info.nightscout.androidaps.plugins.SourceDexcomG5.SourceDexcomG5Plugin; import info.nightscout.androidaps.plugins.SourceDexcomG5.SourceDexcomG5Plugin;
@ -37,7 +39,6 @@ import info.nightscout.androidaps.plugins.SourceMM640g.SourceMM640gPlugin;
import info.nightscout.androidaps.plugins.SourceNSClient.SourceNSClientPlugin; import info.nightscout.androidaps.plugins.SourceNSClient.SourceNSClientPlugin;
import info.nightscout.androidaps.plugins.SourceXdrip.SourceXdripPlugin; import info.nightscout.androidaps.plugins.SourceXdrip.SourceXdripPlugin;
import info.nightscout.androidaps.receivers.DataReceiver; import info.nightscout.androidaps.receivers.DataReceiver;
import info.nightscout.androidaps.plugins.NSClientInternal.data.NSDeviceStatus;
import info.nightscout.utils.BundleLogger; import info.nightscout.utils.BundleLogger;
import info.nightscout.utils.NSUpload; import info.nightscout.utils.NSUpload;
import info.nightscout.utils.SP; import info.nightscout.utils.SP;
@ -365,8 +366,10 @@ public class DataService extends IntentService {
String profile = bundles.getString("profile"); String profile = bundles.getString("profile");
ProfileStore profileStore = new ProfileStore(new JSONObject(profile)); ProfileStore profileStore = new ProfileStore(new JSONObject(profile));
NSProfilePlugin.storeNewProfile(profileStore); NSProfilePlugin.storeNewProfile(profileStore);
MainApp.bus().post(new EventNewBasalProfile()); MainApp.bus().post(new EventNSProfileUpdateGUI());
// if there are no profile switches this should lead to profile update
if (MainApp.getConfigBuilder().getProfileSwitchesFromHistory().size() == 0)
MainApp.bus().post(new EventNewBasalProfile());
if (Config.logIncommingData) if (Config.logIncommingData)
log.debug("Received profileStore: " + activeProfile + " " + profile); log.debug("Received profileStore: " + activeProfile + " " + profile);
} catch (JSONException e) { } catch (JSONException e) {

View file

@ -239,6 +239,7 @@ public class Profile {
// if pump not available (at start) // if pump not available (at start)
// do not store converted array // do not store converted array
basal_v = null; basal_v = null;
isValidated = false;
} }
} }

View file

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

View file

@ -507,7 +507,7 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
return 0; return 0;
} }
public int deleteDbRequestbyMongoId(String action, String id) { public void deleteDbRequestbyMongoId(String action, String id) {
try { try {
QueryBuilder<DbRequest, String> queryBuilder = getDaoDbRequest().queryBuilder(); QueryBuilder<DbRequest, String> queryBuilder = getDaoDbRequest().queryBuilder();
Where where = queryBuilder.where(); Where where = queryBuilder.where();
@ -515,16 +515,13 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
queryBuilder.limit(10L); queryBuilder.limit(10L);
PreparedQuery<DbRequest> preparedQuery = queryBuilder.prepare(); PreparedQuery<DbRequest> preparedQuery = queryBuilder.prepare();
List<DbRequest> dbList = getDaoDbRequest().query(preparedQuery); List<DbRequest> dbList = getDaoDbRequest().query(preparedQuery);
if (dbList.size() != 1) { log.error("deleteDbRequestbyMongoId query size: " + dbList.size());
log.error("deleteDbRequestbyMongoId query size: " + dbList.size()); for (DbRequest r : dbList) {
} else { delete(r);
//log.debug("Treatment findTreatmentById found: " + trList.get(0).log());
return delete(dbList.get(0));
} }
} catch (SQLException e) { } catch (SQLException e) {
log.error("Unhandled exception", e); log.error("Unhandled exception", e);
} }
return 0;
} }
public void deleteAllDbRequests() { public void deleteAllDbRequests() {
@ -1473,7 +1470,21 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
} catch (SQLException e) { } catch (SQLException e) {
log.error("Unhandled exception", e); log.error("Unhandled exception", e);
} }
return new ArrayList<CareportalEvent>(); return new ArrayList<>();
}
public List<CareportalEvent> getCareportalEventsFromTime(boolean ascending) {
try {
List<CareportalEvent> careportalEvents;
QueryBuilder<CareportalEvent, Long> queryBuilder = getDaoCareportalEvents().queryBuilder();
queryBuilder.orderBy("date", ascending);
PreparedQuery<CareportalEvent> preparedQuery = queryBuilder.prepare();
careportalEvents = getDaoCareportalEvents().query(preparedQuery);
return careportalEvents;
} catch (SQLException e) {
log.error("Unhandled exception", e);
}
return new ArrayList<>();
} }
public void deleteCareportalEventById(String _id) { public void deleteCareportalEventById(String _id) {

View file

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

View file

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

View file

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

View file

@ -30,6 +30,7 @@ import info.nightscout.androidaps.db.Source;
import info.nightscout.androidaps.db.TempTarget; import info.nightscout.androidaps.db.TempTarget;
import info.nightscout.androidaps.db.TemporaryBasal; import info.nightscout.androidaps.db.TemporaryBasal;
import info.nightscout.androidaps.db.Treatment; import info.nightscout.androidaps.db.Treatment;
import info.nightscout.androidaps.events.EventAppInitialized;
import info.nightscout.androidaps.interfaces.APSInterface; import info.nightscout.androidaps.interfaces.APSInterface;
import info.nightscout.androidaps.interfaces.BgSourceInterface; import info.nightscout.androidaps.interfaces.BgSourceInterface;
import info.nightscout.androidaps.interfaces.ConstraintsInterface; import info.nightscout.androidaps.interfaces.ConstraintsInterface;
@ -146,6 +147,7 @@ public class ConfigBuilderPlugin implements PluginBase, ConstraintsInterface, Tr
public void initialize() { public void initialize() {
pluginList = MainApp.getPluginsList(); pluginList = MainApp.getPluginsList();
loadSettings(); loadSettings();
MainApp.bus().post(new EventAppInitialized());
} }
public void storeSettings() { public void storeSettings() {

View file

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

View file

@ -161,14 +161,14 @@ public class ObjectivesPlugin implements PluginBase, ConstraintsInterface {
boolean isVirtualPump = VirtualPumpPlugin.getPlugin().isEnabled(PluginBase.PUMP); boolean isVirtualPump = VirtualPumpPlugin.getPlugin().isEnabled(PluginBase.PUMP);
boolean vpUploadEnabled = SP.getBoolean("virtualpump_uploadstatus", false); boolean vpUploadEnabled = SP.getBoolean("virtualpump_uploadstatus", false);
boolean vpUploadNeeded = !isVirtualPump || vpUploadEnabled; boolean vpUploadNeeded = !isVirtualPump || vpUploadEnabled;
boolean hasBGData = DatabaseHelper.lastBg()!=null; boolean hasBGData = DatabaseHelper.lastBg() != null;
boolean apsEnabled = false; boolean apsEnabled = false;
APSInterface usedAPS = ConfigBuilderPlugin.getActiveAPS(); APSInterface usedAPS = ConfigBuilderPlugin.getActiveAPS();
if (usedAPS != null && ((PluginBase) usedAPS).isEnabled(PluginBase.APS)) if (usedAPS != null && ((PluginBase) usedAPS).isEnabled(PluginBase.APS))
apsEnabled = true; apsEnabled = true;
return new RequirementResult(hasBGData&&bgIsAvailableInNS && pumpStatusIsAvailableInNS && NSClientInternalPlugin.getPlugin().hasWritePermission() && LoopPlugin.getPlugin().isEnabled(PluginBase.LOOP) && apsEnabled && vpUploadNeeded, return new RequirementResult(hasBGData && bgIsAvailableInNS && pumpStatusIsAvailableInNS && NSClientInternalPlugin.getPlugin().hasWritePermission() && LoopPlugin.getPlugin().isEnabled(PluginBase.LOOP) && apsEnabled && vpUploadNeeded,
MainApp.sResources.getString(R.string.objectives_bgavailableinns) + ": " + yesOrNo(bgIsAvailableInNS) MainApp.sResources.getString(R.string.objectives_bgavailableinns) + ": " + yesOrNo(bgIsAvailableInNS)
+ "\n" + MainApp.sResources.getString(R.string.nsclienthaswritepermission) + ": " + yesOrNo(NSClientInternalPlugin.getPlugin().hasWritePermission()) + "\n" + MainApp.sResources.getString(R.string.nsclienthaswritepermission) + ": " + yesOrNo(NSClientInternalPlugin.getPlugin().hasWritePermission())
+ (isVirtualPump ? "\n" + MainApp.sResources.getString(R.string.virtualpump_uploadstatus_title) + ": " + yesOrNo(vpUploadEnabled) : "") + (isVirtualPump ? "\n" + MainApp.sResources.getString(R.string.virtualpump_uploadstatus_title) + ": " + yesOrNo(vpUploadEnabled) : "")
@ -187,7 +187,7 @@ public class ObjectivesPlugin implements PluginBase, ConstraintsInterface {
return new RequirementResult(closedModeEnabled, MainApp.sResources.getString(R.string.closedmodeenabled) + ": " + yesOrNo(closedModeEnabled)); return new RequirementResult(closedModeEnabled, MainApp.sResources.getString(R.string.closedmodeenabled) + ": " + yesOrNo(closedModeEnabled));
case 4: case 4:
double maxIOB = MainApp.getConfigBuilder().applyMaxIOBConstraints(1000d); double maxIOB = MainApp.getConfigBuilder().applyMaxIOBConstraints(1000d);
boolean maxIobSet = maxIOB > 0; boolean maxIobSet = maxIOB > 0;
return new RequirementResult(maxIobSet, MainApp.sResources.getString(R.string.maxiobset) + ": " + yesOrNo(maxIobSet)); return new RequirementResult(maxIobSet, MainApp.sResources.getString(R.string.maxiobset) + ": " + yesOrNo(maxIobSet));
default: default:
return new RequirementResult(true, ""); return new RequirementResult(true, "");
@ -320,12 +320,12 @@ public class ObjectivesPlugin implements PluginBase, ConstraintsInterface {
@Override @Override
public Double applyMaxIOBConstraints(Double maxIob) { public Double applyMaxIOBConstraints(Double maxIob) {
if (objectives.get(4).started.getTime() > 0 || objectives.get(2).accomplished.getTime() == 0) if (objectives.get(3).started.getTime() > 0 && objectives.get(3).accomplished.getTime() == 0) {
return maxIob;
else {
if (Config.logConstraintsChanges) if (Config.logConstraintsChanges)
log.debug("Limiting maxIOB " + maxIob + " to " + 0 + "U"); log.debug("Limiting maxIOB " + maxIob + " to " + 0 + "U");
return 0d; return 0d;
} else {
return maxIob;
} }
} }

View file

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

View file

@ -1,8 +1,6 @@
package info.nightscout.androidaps.plugins.IobCobCalculator; package info.nightscout.androidaps.plugins.IobCobCalculator;
import android.os.Handler; import android.os.SystemClock;
import android.os.HandlerThread;
import android.os.Process;
import android.support.annotation.Nullable; import android.support.annotation.Nullable;
import android.support.v4.util.LongSparseArray; import android.support.v4.util.LongSparseArray;
@ -24,16 +22,16 @@ import info.nightscout.androidaps.data.IobTotal;
import info.nightscout.androidaps.data.Profile; import info.nightscout.androidaps.data.Profile;
import info.nightscout.androidaps.db.BgReading; import info.nightscout.androidaps.db.BgReading;
import info.nightscout.androidaps.db.TemporaryBasal; import info.nightscout.androidaps.db.TemporaryBasal;
import info.nightscout.androidaps.db.Treatment; import info.nightscout.androidaps.events.EventAppInitialized;
import info.nightscout.androidaps.events.EventConfigBuilderChange; import info.nightscout.androidaps.events.EventConfigBuilderChange;
import info.nightscout.androidaps.events.EventNewBG; import info.nightscout.androidaps.events.EventNewBG;
import info.nightscout.androidaps.events.EventNewBasalProfile; import info.nightscout.androidaps.events.EventNewBasalProfile;
import info.nightscout.androidaps.events.EventPreferenceChange; import info.nightscout.androidaps.events.EventPreferenceChange;
import info.nightscout.androidaps.interfaces.PluginBase; import info.nightscout.androidaps.interfaces.PluginBase;
import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin; import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin;
import info.nightscout.androidaps.plugins.IobCobCalculator.events.EventAutosensCalculationFinished;
import info.nightscout.androidaps.plugins.IobCobCalculator.events.EventNewHistoryData; import info.nightscout.androidaps.plugins.IobCobCalculator.events.EventNewHistoryData;
import info.nightscout.androidaps.plugins.OpenAPSSMB.OpenAPSSMBPlugin; import info.nightscout.androidaps.plugins.OpenAPSSMB.OpenAPSSMBPlugin;
import info.nightscout.utils.DateUtil;
/** /**
* Created by mike on 24.04.2017. * Created by mike on 24.04.2017.
@ -51,10 +49,10 @@ public class IobCobCalculatorPlugin implements PluginBase {
private static double dia = Constants.defaultDIA; private static double dia = Constants.defaultDIA;
private static Handler sHandler = null; static final Object dataLock = new Object();
private static HandlerThread sHandlerThread = null;
private static final Object dataLock = new Object(); boolean stopCalculationTrigger = false;
IobCobThread thread = null;
private static IobCobCalculatorPlugin plugin = null; private static IobCobCalculatorPlugin plugin = null;
@ -134,12 +132,6 @@ public class IobCobCalculatorPlugin implements PluginBase {
IobCobCalculatorPlugin() { IobCobCalculatorPlugin() {
MainApp.bus().register(this); MainApp.bus().register(this);
if (sHandlerThread == null) {
sHandlerThread = new HandlerThread(IobCobCalculatorPlugin.class.getSimpleName(), Process.THREAD_PRIORITY_LOWEST);
sHandlerThread.start();
sHandler = new Handler(sHandlerThread.getLooper());
}
onNewBg(new EventNewBG());
} }
@Nullable @Nullable
@ -176,14 +168,9 @@ public class IobCobCalculatorPlugin implements PluginBase {
return rouded; return rouded;
} }
private void loadBgData() { void loadBgData() {
//log.debug("Locking loadBgData"); bgReadings = MainApp.getDbHelper().getBgreadingsDataFromTime((long) (System.currentTimeMillis() - 60 * 60 * 1000L * (24 + dia)), false);
synchronized (dataLock) { log.debug("BG data loaded. Size: " + bgReadings.size());
onNewProfile(null);
bgReadings = MainApp.getDbHelper().getBgreadingsDataFromTime((long) (System.currentTimeMillis() - 60 * 60 * 1000L * (24 + dia)), false);
log.debug("BG data loaded. Size: " + bgReadings.size());
}
//log.debug("Releasing loadBgData");
} }
private boolean isAbout5minData() { private boolean isAbout5minData() {
@ -210,7 +197,7 @@ public class IobCobCalculatorPlugin implements PluginBase {
} }
} }
private void createBucketedData() { void createBucketedData() {
if (isAbout5minData()) if (isAbout5minData())
createBucketedData5min(); createBucketedData5min();
else else
@ -242,258 +229,97 @@ public class IobCobCalculatorPlugin implements PluginBase {
} }
private void createBucketedDataRecalculated() { private void createBucketedDataRecalculated() {
synchronized (dataLock) { if (bgReadings == null || bgReadings.size() < 3) {
if (bgReadings == null || bgReadings.size() < 3) { bucketed_data = null;
bucketed_data = null; return;
return; }
}
bucketed_data = new ArrayList<>(); bucketed_data = new ArrayList<>();
long currentTime = bgReadings.get(0).date + 5 * 60 * 1000 - bgReadings.get(0).date % (5 * 60 * 1000) - 5 * 60 * 1000L; long currentTime = bgReadings.get(0).date + 5 * 60 * 1000 - bgReadings.get(0).date % (5 * 60 * 1000) - 5 * 60 * 1000L;
//log.debug("First reading: " + new Date(currentTime).toLocaleString()); //log.debug("First reading: " + new Date(currentTime).toLocaleString());
while (true) { while (true) {
// test if current value is older than current time // test if current value is older than current time
BgReading newer = findNewer(currentTime); BgReading newer = findNewer(currentTime);
BgReading older = findOlder(currentTime); BgReading older = findOlder(currentTime);
if (newer == null || older == null) if (newer == null || older == null)
break; break;
double bgDelta = newer.value - older.value; double bgDelta = newer.value - older.value;
long timeDiffToNew = newer.date - currentTime; long timeDiffToNew = newer.date - currentTime;
double currentBg = newer.value - (double) timeDiffToNew / (newer.date - older.date) * bgDelta; double currentBg = newer.value - (double) timeDiffToNew / (newer.date - older.date) * bgDelta;
BgReading newBgreading = new BgReading(); BgReading newBgreading = new BgReading();
newBgreading.date = currentTime; newBgreading.date = currentTime;
newBgreading.value = Math.round(currentBg); newBgreading.value = Math.round(currentBg);
bucketed_data.add(newBgreading); bucketed_data.add(newBgreading);
//log.debug("BG: " + newBgreading.value + " (" + new Date(newBgreading.date).toLocaleString() + ") Prev: " + older.value + " (" + new Date(older.date).toLocaleString() + ") Newer: " + newer.value + " (" + new Date(newer.date).toLocaleString() + ")"); //log.debug("BG: " + newBgreading.value + " (" + new Date(newBgreading.date).toLocaleString() + ") Prev: " + older.value + " (" + new Date(older.date).toLocaleString() + ") Newer: " + newer.value + " (" + new Date(newer.date).toLocaleString() + ")");
currentTime -= 5 * 60 * 1000L; currentTime -= 5 * 60 * 1000L;
}
} }
} }
public void createBucketedData5min() { public void createBucketedData5min() {
//log.debug("Locking createBucketedData"); if (bgReadings == null || bgReadings.size() < 3) {
synchronized (dataLock) { bucketed_data = null;
if (bgReadings == null || bgReadings.size() < 3) { return;
bucketed_data = null; }
return;
bucketed_data = new ArrayList<>();
bucketed_data.add(bgReadings.get(0));
int j = 0;
for (int i = 1; i < bgReadings.size(); ++i) {
long bgTime = bgReadings.get(i).date;
long lastbgTime = bgReadings.get(i - 1).date;
//log.error("Processing " + i + ": " + new Date(bgTime).toString() + " " + bgReadings.get(i).value + " Previous: " + new Date(lastbgTime).toString() + " " + bgReadings.get(i - 1).value);
if (bgReadings.get(i).value < 39 || bgReadings.get(i - 1).value < 39) {
continue;
} }
bucketed_data = new ArrayList<>(); long elapsed_minutes = (bgTime - lastbgTime) / (60 * 1000);
bucketed_data.add(bgReadings.get(0)); if (Math.abs(elapsed_minutes) > 8) {
int j = 0; // interpolate missing data points
for (int i = 1; i < bgReadings.size(); ++i) { double lastbg = bgReadings.get(i - 1).value;
long bgTime = bgReadings.get(i).date; elapsed_minutes = Math.abs(elapsed_minutes);
long lastbgTime = bgReadings.get(i - 1).date; //console.error(elapsed_minutes);
//log.error("Processing " + i + ": " + new Date(bgTime).toString() + " " + bgReadings.get(i).value + " Previous: " + new Date(lastbgTime).toString() + " " + bgReadings.get(i - 1).value); long nextbgTime;
if (bgReadings.get(i).value < 39 || bgReadings.get(i - 1).value < 39) { while (elapsed_minutes > 5) {
continue; nextbgTime = lastbgTime - 5 * 60 * 1000;
}
long elapsed_minutes = (bgTime - lastbgTime) / (60 * 1000);
if (Math.abs(elapsed_minutes) > 8) {
// interpolate missing data points
double lastbg = bgReadings.get(i - 1).value;
elapsed_minutes = Math.abs(elapsed_minutes);
//console.error(elapsed_minutes);
long nextbgTime;
while (elapsed_minutes > 5) {
nextbgTime = lastbgTime - 5 * 60 * 1000;
j++;
BgReading newBgreading = new BgReading();
newBgreading.date = nextbgTime;
double gapDelta = bgReadings.get(i).value - lastbg;
//console.error(gapDelta, lastbg, elapsed_minutes);
double nextbg = lastbg + (5d / elapsed_minutes * gapDelta);
newBgreading.value = Math.round(nextbg);
//console.error("Interpolated", bucketed_data[j]);
bucketed_data.add(newBgreading);
//log.error("******************************************************************************************************* Adding:" + new Date(newBgreading.date).toString() + " " + newBgreading.value);
elapsed_minutes = elapsed_minutes - 5;
lastbg = nextbg;
lastbgTime = nextbgTime;
}
j++; j++;
BgReading newBgreading = new BgReading(); BgReading newBgreading = new BgReading();
newBgreading.value = bgReadings.get(i).value; newBgreading.date = nextbgTime;
newBgreading.date = bgTime; double gapDelta = bgReadings.get(i).value - lastbg;
//console.error(gapDelta, lastbg, elapsed_minutes);
double nextbg = lastbg + (5d / elapsed_minutes * gapDelta);
newBgreading.value = Math.round(nextbg);
//console.error("Interpolated", bucketed_data[j]);
bucketed_data.add(newBgreading); bucketed_data.add(newBgreading);
//log.error("******************************************************************************************************* Copying:" + new Date(newBgreading.date).toString() + " " + newBgreading.value); //log.error("******************************************************************************************************* Adding:" + new Date(newBgreading.date).toString() + " " + newBgreading.value);
} else if (Math.abs(elapsed_minutes) > 2) {
j++; elapsed_minutes = elapsed_minutes - 5;
BgReading newBgreading = new BgReading(); lastbg = nextbg;
newBgreading.value = bgReadings.get(i).value; lastbgTime = nextbgTime;
newBgreading.date = bgTime;
bucketed_data.add(newBgreading);
//log.error("******************************************************************************************************* Copying:" + new Date(newBgreading.date).toString() + " " + newBgreading.value);
} else {
bucketed_data.get(j).value = (bucketed_data.get(j).value + bgReadings.get(i).value) / 2;
//log.error("***** Average");
} }
} j++;
log.debug("Bucketed data created. Size: " + bucketed_data.size()); BgReading newBgreading = new BgReading();
} newBgreading.value = bgReadings.get(i).value;
//log.debug("Releasing createBucketedData"); newBgreading.date = bgTime;
} bucketed_data.add(newBgreading);
//log.error("******************************************************************************************************* Copying:" + new Date(newBgreading.date).toString() + " " + newBgreading.value);
private void calculateSensitivityData() { } else if (Math.abs(elapsed_minutes) > 2) {
if (MainApp.getConfigBuilder() == null) j++;
return; // app still initializing BgReading newBgreading = new BgReading();
if (MainApp.getConfigBuilder().getProfile() == null) newBgreading.value = bgReadings.get(i).value;
return; // app still initializing newBgreading.date = bgTime;
//log.debug("Locking calculateSensitivityData"); bucketed_data.add(newBgreading);
long oldestTimeWithData = oldestDataAvailable(); //log.error("******************************************************************************************************* Copying:" + new Date(newBgreading.date).toString() + " " + newBgreading.value);
} else {
synchronized (dataLock) { bucketed_data.get(j).value = (bucketed_data.get(j).value + bgReadings.get(i).value) / 2;
//log.error("***** Average");
if (bucketed_data == null || bucketed_data.size() < 3) {
log.debug("calculateSensitivityData: No bucketed data available");
return;
}
long prevDataTime = roundUpTime(bucketed_data.get(bucketed_data.size() - 3).date);
log.debug("Prev data time: " + new Date(prevDataTime).toLocaleString());
AutosensData previous = autosensDataTable.get(prevDataTime);
// start from oldest to be able sub cob
for (int i = bucketed_data.size() - 4; i >= 0; i--) {
// check if data already exists
long bgTime = bucketed_data.get(i).date;
bgTime = roundUpTime(bgTime);
if (bgTime > System.currentTimeMillis())
continue;
Profile profile = MainApp.getConfigBuilder().getProfile(bgTime);
AutosensData existing;
if ((existing = autosensDataTable.get(bgTime)) != null) {
previous = existing;
continue;
}
if (profile.getIsf(bgTime) == null)
return; // profile not set yet
double sens = Profile.toMgdl(profile.getIsf(bgTime), profile.getUnits());
AutosensData autosensData = new AutosensData();
autosensData.time = bgTime;
if (previous != null)
autosensData.activeCarbsList = new ArrayList<>(previous.activeCarbsList);
else
autosensData.activeCarbsList = new ArrayList<>();
//console.error(bgTime , bucketed_data[i].glucose);
double bg = bucketed_data.get(i).value;
if (bg < 39 || bucketed_data.get(i + 3).value < 39) {
log.error("! value < 39");
continue;
}
double avgDelta = (bg - bucketed_data.get(i + 3).value) / 3;
double delta = (bg - bucketed_data.get(i + 1).value);
IobTotal iob = calculateFromTreatmentsAndTemps(bgTime);
double bgi = -iob.activity * sens * 5;
double deviation = delta - bgi;
double avgDeviation = Math.round((avgDelta - bgi) * 1000) / 1000;
double currentDeviation;
double slopeFromMaxDeviation = 0;
double slopeFromMinDeviation = 999;
double maxDeviation = 0;
double minDeviation = 999;
// https://github.com/openaps/oref0/blob/master/lib/determine-basal/cob-autosens.js#L169
if (i < bucketed_data.size() - 16) { // we need 1h of data to calculate minDeviationSlope
long hourago = bgTime + 10 * 1000 - 60 * 60 * 1000L;
AutosensData hourAgoData = getAutosensData(hourago);
currentDeviation = hourAgoData.avgDeviation;
int initialIndex = autosensDataTable.indexOfKey(hourAgoData.time);
for (int past = 1; past < 12; past++) {
AutosensData ad = autosensDataTable.valueAt(initialIndex + past);
double deviationSlope = (ad.avgDeviation - currentDeviation) / (ad.time - bgTime) * 1000 * 60 * 5;
if (ad.avgDeviation > maxDeviation) {
slopeFromMaxDeviation = Math.min(0, deviationSlope);
maxDeviation = ad.avgDeviation;
}
if (avgDeviation < minDeviation) {
slopeFromMinDeviation = Math.max(0, deviationSlope);
minDeviation = avgDeviation;
}
//if (Config.logAutosensData)
// log.debug("Deviations: " + new Date(bgTime) + new Date(ad.time) + " avgDeviation=" + avgDeviation + " deviationSlope=" + deviationSlope + " slopeFromMaxDeviation=" + slopeFromMaxDeviation + " slopeFromMinDeviation=" + slopeFromMinDeviation);
}
}
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;
autosensData.avgDelta = avgDelta;
autosensData.avgDeviation = avgDeviation;
autosensData.slopeFromMaxDeviation = slopeFromMaxDeviation;
autosensData.slopeFromMinDeviation = slopeFromMinDeviation;
// calculate autosens only without COB
if (autosensData.cob <= 0) {
if (Math.abs(deviation) < Constants.DEVIATION_TO_BE_EQUAL) {
autosensData.pastSensitivity += "=";
autosensData.nonEqualDeviation = true;
} else if (deviation > 0) {
autosensData.pastSensitivity += "+";
autosensData.nonEqualDeviation = true;
} else {
autosensData.pastSensitivity += "-";
autosensData.nonEqualDeviation = true;
}
autosensData.nonCarbsDeviation = true;
} else {
autosensData.pastSensitivity += "C";
}
//log.debug("TIME: " + new Date(bgTime).toString() + " BG: " + bg + " SENS: " + sens + " DELTA: " + delta + " AVGDELTA: " + avgDelta + " IOB: " + iob.iob + " ACTIVITY: " + iob.activity + " BGI: " + bgi + " DEVIATION: " + deviation);
previous = autosensData;
autosensDataTable.put(bgTime, autosensData);
autosensData.autosensRatio = detectSensitivity(oldestTimeWithData, bgTime).ratio;
//if (Config.logAutosensData)
// log.debug(autosensData.log(bgTime));
} }
} }
MainApp.bus().post(new EventAutosensCalculationFinished()); log.debug("Bucketed data created. Size: " + bucketed_data.size());
//log.debug("Releasing calculateSensitivityData");
} }
public static long oldestDataAvailable() { public static long oldestDataAvailable() {
@ -631,11 +457,11 @@ public class IobCobCalculatorPlugin implements PluginBase {
return null; return null;
} }
if (data.time < System.currentTimeMillis() - 11 * 60 * 1000) { if (data.time < System.currentTimeMillis() - 11 * 60 * 1000) {
log.debug("AUTOSENSDATA null: data is old (" + reason + ")"); log.debug("AUTOSENSDATA null: data is old (" + reason + ") size()=" + autosensDataTable.size() + " lastdata=" + DateUtil.dateAndTimeString(data.time));
return null; return null;
} else { } else {
if (data == null) if (data == null)
log.debug("AUTOSENSDATA null: data == null (" + " " + reason + ")"); log.debug("AUTOSENSDATA null: data == null (" + " " + reason + ") size()=" + autosensDataTable.size() + " lastdata=" + DateUtil.dateAndTimeString(data.time));
return data; return data;
} }
} }
@ -680,7 +506,7 @@ public class IobCobCalculatorPlugin implements PluginBase {
} }
} }
private static AutosensResult detectSensitivity(long fromTime, long toTime) { static AutosensResult detectSensitivity(long fromTime, long toTime) {
return ConfigBuilderPlugin.getActiveSensitivity().detectSensitivity(fromTime, toTime); return ConfigBuilderPlugin.getActiveSensitivity().detectSensitivity(fromTime, toTime);
} }
@ -693,15 +519,33 @@ public class IobCobCalculatorPlugin implements PluginBase {
} }
@Subscribe @Subscribe
public void onNewBg(EventNewBG ev) { public void onEventAppInitialized(EventAppInitialized ev) {
sHandler.post(new Runnable() { runCalculation("onEventAppInitialized", true);
@Override }
public void run() {
loadBgData(); @Subscribe
createBucketedData(); public void onEventNewBG(EventNewBG ev) {
calculateSensitivityData(); stopCalculation("onEventNewBG");
runCalculation("onEventNewBG", true);
}
private void stopCalculation(String from) {
if (thread != null && thread.getState() != Thread.State.TERMINATED) {
stopCalculationTrigger = true;
log.debug("Stopping calculation thread: " + from);
while (thread.getState() != Thread.State.TERMINATED) {
SystemClock.sleep(100);
} }
}); log.debug("Calculation thread stopped: " + from);
}
}
private void runCalculation(String from, boolean bgDataReload) {
log.debug("Starting calculation thread: " + from);
if (thread == null || thread.getState() == Thread.State.TERMINATED) {
thread = new IobCobThread(this, from, bgDataReload);
thread.start();
}
} }
@Subscribe @Subscribe
@ -715,66 +559,55 @@ public class IobCobCalculatorPlugin implements PluginBase {
if (ev == null) { // on init no need of reset if (ev == null) { // on init no need of reset
return; return;
} }
stopCalculation("onNewProfile");
synchronized (dataLock) { synchronized (dataLock) {
log.debug("Invalidating cached data because of new profile. IOB: " + iobTable.size() + " Autosens: " + autosensDataTable.size() + " records"); log.debug("Invalidating cached data because of new profile. IOB: " + iobTable.size() + " Autosens: " + autosensDataTable.size() + " records");
iobTable = new LongSparseArray<>(); iobTable = new LongSparseArray<>();
autosensDataTable = new LongSparseArray<>(); autosensDataTable = new LongSparseArray<>();
} }
sHandler.post(new Runnable() { runCalculation("onNewProfile", false);
@Override
public void run() {
calculateSensitivityData();
}
});
} }
@Subscribe @Subscribe
public void onStatusEvent(EventPreferenceChange ev) { public void onEventPreferenceChange(EventPreferenceChange ev) {
if (ev.isChanged(R.string.key_openapsama_autosens_period) || if (ev.isChanged(R.string.key_openapsama_autosens_period) ||
ev.isChanged(R.string.key_age) || ev.isChanged(R.string.key_age) ||
ev.isChanged(R.string.key_absorption_maxtime) ev.isChanged(R.string.key_absorption_maxtime)
) { ) {
stopCalculation("onEventPreferenceChange");
synchronized (dataLock) { synchronized (dataLock) {
log.debug("Invalidating cached data because of preference change. IOB: " + iobTable.size() + " Autosens: " + autosensDataTable.size() + " records"); log.debug("Invalidating cached data because of preference change. IOB: " + iobTable.size() + " Autosens: " + autosensDataTable.size() + " records");
iobTable = new LongSparseArray<>(); iobTable = new LongSparseArray<>();
autosensDataTable = new LongSparseArray<>(); autosensDataTable = new LongSparseArray<>();
} }
sHandler.post(new Runnable() { runCalculation("onEventPreferenceChange", false);
@Override
public void run() {
calculateSensitivityData();
}
});
} }
} }
@Subscribe @Subscribe
public void onStatusEvent(EventConfigBuilderChange ev) { public void onEventConfigBuilderChange(EventConfigBuilderChange ev) {
stopCalculation("onEventConfigBuilderChange");
synchronized (dataLock) { synchronized (dataLock) {
log.debug("Invalidating cached data because of configuration change. IOB: " + iobTable.size() + " Autosens: " + autosensDataTable.size() + " records"); log.debug("Invalidating cached data because of configuration change. IOB: " + iobTable.size() + " Autosens: " + autosensDataTable.size() + " records");
iobTable = new LongSparseArray<>(); iobTable = new LongSparseArray<>();
autosensDataTable = new LongSparseArray<>(); autosensDataTable = new LongSparseArray<>();
} }
sHandler.post(new Runnable() { runCalculation("onEventConfigBuilderChange", false);
@Override
public void run() {
calculateSensitivityData();
}
});
} }
// When historical data is changed (comming from NS etc) finished calculations after this date must be invalidated // When historical data is changed (comming from NS etc) finished calculations after this date must be invalidated
@Subscribe @Subscribe
public void onNewHistoryData(EventNewHistoryData ev) { public void onEventNewHistoryData(EventNewHistoryData ev) {
//log.debug("Locking onNewHistoryData"); //log.debug("Locking onNewHistoryData");
stopCalculation("onEventNewHistoryData");
synchronized (dataLock) { synchronized (dataLock) {
long time = ev.time; // clear up 5 min back for proper COB calculation
long time = ev.time - 5 * 60 * 1000L;
log.debug("Invalidating cached data to: " + new Date(time).toLocaleString()); log.debug("Invalidating cached data to: " + new Date(time).toLocaleString());
for (int index = iobTable.size() - 1; index >= 0; index--) { for (int index = iobTable.size() - 1; index >= 0; index--) {
if (iobTable.keyAt(index) > time) { if (iobTable.keyAt(index) > time) {
if (Config.logAutosensData) if (Config.logAutosensData)
if (Config.logAutosensData) log.debug("Removing from iobTable: " + new Date(iobTable.keyAt(index)).toLocaleString());
log.debug("Removing from iobTable: " + new Date(iobTable.keyAt(index)).toLocaleString());
iobTable.removeAt(index); iobTable.removeAt(index);
} else { } else {
break; break;
@ -799,12 +632,7 @@ public class IobCobCalculatorPlugin implements PluginBase {
} }
} }
} }
sHandler.post(new Runnable() { runCalculation("onEventNewHistoryData", false);
@Override
public void run() {
calculateSensitivityData();
}
});
//log.debug("Releasing onNewHistoryData"); //log.debug("Releasing onNewHistoryData");
} }

View file

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

View file

@ -6,7 +6,7 @@ import android.app.PendingIntent;
import android.app.TaskStackBuilder; import android.app.TaskStackBuilder;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.support.v7.app.NotificationCompat; import android.support.v4.app.NotificationCompat;
import com.crashlytics.android.answers.Answers; import com.crashlytics.android.answers.Answers;
import com.crashlytics.android.answers.CustomEvent; import com.crashlytics.android.answers.CustomEvent;

View file

@ -159,19 +159,23 @@ public class NewTreatmentDialog extends DialogFragment implements OnClickListene
detailedBolusInfo.carbs = finalCarbsAfterConstraints; detailedBolusInfo.carbs = finalCarbsAfterConstraints;
detailedBolusInfo.context = context; detailedBolusInfo.context = context;
detailedBolusInfo.source = Source.USER; detailedBolusInfo.source = Source.USER;
ConfigBuilderPlugin.getCommandQueue().bolus(detailedBolusInfo, new Callback() { if (detailedBolusInfo.insulin > 0 || ConfigBuilderPlugin.getActivePump().getPumpDescription().storesCarbInfo) {
@Override ConfigBuilderPlugin.getCommandQueue().bolus(detailedBolusInfo, new Callback() {
public void run() { @Override
if (!result.success) { public void run() {
Intent i = new Intent(MainApp.instance(), ErrorHelperActivity.class); if (!result.success) {
i.putExtra("soundid", R.raw.boluserror); Intent i = new Intent(MainApp.instance(), ErrorHelperActivity.class);
i.putExtra("status", result.comment); i.putExtra("soundid", R.raw.boluserror);
i.putExtra("title", MainApp.sResources.getString(R.string.treatmentdeliveryerror)); i.putExtra("status", result.comment);
i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); i.putExtra("title", MainApp.sResources.getString(R.string.treatmentdeliveryerror));
MainApp.instance().startActivity(i); i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
MainApp.instance().startActivity(i);
}
} }
} });
}); } else {
MainApp.getConfigBuilder().addToHistoryTreatment(detailedBolusInfo);
}
Answers.getInstance().logCustom(new CustomEvent("Bolus")); Answers.getInstance().logCustom(new CustomEvent("Bolus"));
} }
} }

View file

@ -365,19 +365,23 @@ public class WizardDialog extends DialogFragment implements OnClickListener, Com
detailedBolusInfo.carbTime = carbTime; detailedBolusInfo.carbTime = carbTime;
detailedBolusInfo.boluscalc = boluscalcJSON; detailedBolusInfo.boluscalc = boluscalcJSON;
detailedBolusInfo.source = Source.USER; detailedBolusInfo.source = Source.USER;
ConfigBuilderPlugin.getCommandQueue().bolus(detailedBolusInfo, new Callback() { if (detailedBolusInfo.insulin > 0 || ConfigBuilderPlugin.getActivePump().getPumpDescription().storesCarbInfo) {
@Override ConfigBuilderPlugin.getCommandQueue().bolus(detailedBolusInfo, new Callback() {
public void run() { @Override
if (!result.success) { public void run() {
Intent i = new Intent(MainApp.instance(), ErrorHelperActivity.class); if (!result.success) {
i.putExtra("soundid", R.raw.boluserror); Intent i = new Intent(MainApp.instance(), ErrorHelperActivity.class);
i.putExtra("status", result.comment); i.putExtra("soundid", R.raw.boluserror);
i.putExtra("title", MainApp.sResources.getString(R.string.treatmentdeliveryerror)); i.putExtra("status", result.comment);
i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); i.putExtra("title", MainApp.sResources.getString(R.string.treatmentdeliveryerror));
MainApp.instance().startActivity(i); i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
MainApp.instance().startActivity(i);
}
} }
} });
}); } else {
MainApp.getConfigBuilder().addToHistoryTreatment(detailedBolusInfo);
}
Answers.getInstance().logCustom(new CustomEvent("Wizard")); Answers.getInstance().logCustom(new CustomEvent("Wizard"));
} }
} }
@ -528,12 +532,12 @@ public class WizardDialog extends DialogFragment implements OnClickListener, Com
if (calculatedTotalInsulin > 0d || calculatedCarbs > 0d) { if (calculatedTotalInsulin > 0d || calculatedCarbs > 0d) {
String insulinText = calculatedTotalInsulin > 0d ? (DecimalFormatter.to2Decimal(calculatedTotalInsulin) + "U") : ""; String insulinText = calculatedTotalInsulin > 0d ? (DecimalFormatter.to2Decimal(calculatedTotalInsulin) + "U") : "";
String carbsText = calculatedCarbs > 0d ? (DecimalFormatter.to0Decimal(calculatedCarbs) + "g") : ""; String carbsText = calculatedCarbs > 0d ? (DecimalFormatter.to0Decimal(calculatedCarbs) + "g") : "";
total.setText(getString(R.string.result) + ": " + insulinText + " " + carbsText); total.setText(MainApp.gs(R.string.result) + ": " + insulinText + " " + carbsText);
okButton.setVisibility(View.VISIBLE); okButton.setVisibility(View.VISIBLE);
} else { } else {
// TODO this should also be run when loading the dialog as the OK button is initially visible // TODO this should also be run when loading the dialog as the OK button is initially visible
// but does nothing if neither carbs nor insulin is > 0 // but does nothing if neither carbs nor insulin is > 0
total.setText(getString(R.string.missing) + " " + DecimalFormatter.to0Decimal(wizard.carbsEquivalent) + "g"); total.setText(MainApp.gs(R.string.missing) + " " + DecimalFormatter.to0Decimal(wizard.carbsEquivalent) + "g");
okButton.setVisibility(View.INVISIBLE); okButton.setVisibility(View.INVISIBLE);
} }

View file

@ -147,12 +147,18 @@ public class OverviewFragment extends Fragment implements View.OnClickListener,
TextView sage; TextView sage;
TextView pbage; TextView pbage;
CheckBox showPredictionView; TextView showPredictionLabel;
CheckBox showBasalsView; CheckBox showPredictionCheckbox;
CheckBox showIobView; TextView showBasalsLabel;
CheckBox showCobView; CheckBox showBasalsCheckbox;
CheckBox showDeviationsView; TextView showIobLabel;
CheckBox showRatiosView; CheckBox showIobCheckbox;
TextView showCobLabel;
CheckBox showCobCheckbox;
TextView showDeviationsLabel;
CheckBox showDeviationsCheckbox;
TextView showRatiosLabel;
CheckBox showRatiosCheckbox;
RecyclerView notificationsView; RecyclerView notificationsView;
LinearLayoutManager llm; LinearLayoutManager llm;
@ -264,24 +270,37 @@ public class OverviewFragment extends Fragment implements View.OnClickListener,
acceptTempLayout = (LinearLayout) view.findViewById(R.id.overview_accepttemplayout); acceptTempLayout = (LinearLayout) view.findViewById(R.id.overview_accepttemplayout);
showPredictionView = (CheckBox) view.findViewById(R.id.overview_showprediction); showPredictionCheckbox = (CheckBox) view.findViewById(R.id.overview_showprediction);
showBasalsView = (CheckBox) view.findViewById(R.id.overview_showbasals); showBasalsCheckbox = (CheckBox) view.findViewById(R.id.overview_showbasals);
showIobView = (CheckBox) view.findViewById(R.id.overview_showiob); showIobCheckbox = (CheckBox) view.findViewById(R.id.overview_showiob);
showCobView = (CheckBox) view.findViewById(R.id.overview_showcob); showCobCheckbox = (CheckBox) view.findViewById(R.id.overview_showcob);
showDeviationsView = (CheckBox) view.findViewById(R.id.overview_showdeviations); showDeviationsCheckbox = (CheckBox) view.findViewById(R.id.overview_showdeviations);
showRatiosView = (CheckBox) view.findViewById(R.id.overview_showratios); showRatiosCheckbox = (CheckBox) view.findViewById(R.id.overview_showratios);
showPredictionView.setChecked(SP.getBoolean("showprediction", false)); showPredictionCheckbox.setChecked(SP.getBoolean("showprediction", false));
showBasalsView.setChecked(SP.getBoolean("showbasals", true)); showBasalsCheckbox.setChecked(SP.getBoolean("showbasals", true));
showIobView.setChecked(SP.getBoolean("showiob", false)); showIobCheckbox.setChecked(SP.getBoolean("showiob", false));
showCobView.setChecked(SP.getBoolean("showcob", false)); showCobCheckbox.setChecked(SP.getBoolean("showcob", false));
showDeviationsView.setChecked(SP.getBoolean("showdeviations", false)); showDeviationsCheckbox.setChecked(SP.getBoolean("showdeviations", false));
showRatiosView.setChecked(SP.getBoolean("showratios", false)); showRatiosCheckbox.setChecked(SP.getBoolean("showratios", false));
showPredictionView.setOnCheckedChangeListener(this); showPredictionCheckbox.setOnCheckedChangeListener(this);
showBasalsView.setOnCheckedChangeListener(this); showBasalsCheckbox.setOnCheckedChangeListener(this);
showIobView.setOnCheckedChangeListener(this); showIobCheckbox.setOnCheckedChangeListener(this);
showCobView.setOnCheckedChangeListener(this); showCobCheckbox.setOnCheckedChangeListener(this);
showDeviationsView.setOnCheckedChangeListener(this); showDeviationsCheckbox.setOnCheckedChangeListener(this);
showRatiosView.setOnCheckedChangeListener(this); showRatiosCheckbox.setOnCheckedChangeListener(this);
showPredictionLabel = (TextView) view.findViewById(R.id.overview_showprediction_label);
showPredictionLabel.setOnClickListener(this);
showBasalsLabel = (TextView) view.findViewById(R.id.overview_showbasals_label);
showBasalsLabel.setOnClickListener(this);
showIobLabel = (TextView) view.findViewById(R.id.overview_showiob_label);
showIobLabel.setOnClickListener(this);
showCobLabel = (TextView) view.findViewById(R.id.overview_showcob_label);
showCobLabel.setOnClickListener(this);
showDeviationsLabel = (TextView) view.findViewById(R.id.overview_showdeviations_label);
showDeviationsLabel.setOnClickListener(this);
showRatiosLabel = (TextView) view.findViewById(R.id.overview_showratios_label);
showRatiosLabel.setOnClickListener(this);
notificationsView = (RecyclerView) view.findViewById(R.id.overview_notifications); notificationsView = (RecyclerView) view.findViewById(R.id.overview_notifications);
notificationsView.setHasFixedSize(true); notificationsView.setHasFixedSize(true);
@ -374,24 +393,24 @@ public class OverviewFragment extends Fragment implements View.OnClickListener,
case R.id.overview_showiob: case R.id.overview_showiob:
break; break;
case R.id.overview_showcob: case R.id.overview_showcob:
showDeviationsView.setOnCheckedChangeListener(null); showDeviationsCheckbox.setOnCheckedChangeListener(null);
showDeviationsView.setChecked(false); showDeviationsCheckbox.setChecked(false);
showDeviationsView.setOnCheckedChangeListener(this); showDeviationsCheckbox.setOnCheckedChangeListener(this);
break; break;
case R.id.overview_showdeviations: case R.id.overview_showdeviations:
showCobView.setOnCheckedChangeListener(null); showCobCheckbox.setOnCheckedChangeListener(null);
showCobView.setChecked(false); showCobCheckbox.setChecked(false);
showCobView.setOnCheckedChangeListener(this); showCobCheckbox.setOnCheckedChangeListener(this);
break; break;
case R.id.overview_showratios: case R.id.overview_showratios:
break; break;
} }
SP.putBoolean("showiob", showIobView.isChecked()); SP.putBoolean("showiob", showIobCheckbox.isChecked());
SP.putBoolean("showprediction", showPredictionView.isChecked()); SP.putBoolean("showprediction", showPredictionCheckbox.isChecked());
SP.putBoolean("showbasals", showBasalsView.isChecked()); SP.putBoolean("showbasals", showBasalsCheckbox.isChecked());
SP.putBoolean("showcob", showCobView.isChecked()); SP.putBoolean("showcob", showCobCheckbox.isChecked());
SP.putBoolean("showdeviations", showDeviationsView.isChecked()); SP.putBoolean("showdeviations", showDeviationsCheckbox.isChecked());
SP.putBoolean("showratios", showRatiosView.isChecked()); SP.putBoolean("showratios", showRatiosCheckbox.isChecked());
scheduleUpdateGUI("onGraphCheckboxesCheckedChanged"); scheduleUpdateGUI("onGraphCheckboxesCheckedChanged");
} }
@ -496,6 +515,16 @@ public class OverviewFragment extends Fragment implements View.OnClickListener,
} }
} }
}); });
if (MainApp.getConfigBuilder().getActivePump().getPumpDescription().isExtendedBolusCapable && MainApp.getConfigBuilder().isInHistoryExtendedBoluslInProgress()) {
ConfigBuilderPlugin.getCommandQueue().cancelExtended( new Callback() {
@Override
public void run() {
if (!result.success) {
ToastUtils.showToastInUiThread(MainApp.instance().getApplicationContext(), MainApp.sResources.getString(R.string.extendedbolusdeliveryerror));
}
}
});
}
NSUpload.uploadOpenAPSOffline(30); NSUpload.uploadOpenAPSOffline(30);
return true; return true;
} else if (item.getTitle().equals(MainApp.sResources.getString(R.string.disconnectpumpfor1h))) { } else if (item.getTitle().equals(MainApp.sResources.getString(R.string.disconnectpumpfor1h))) {
@ -509,6 +538,16 @@ public class OverviewFragment extends Fragment implements View.OnClickListener,
} }
} }
}); });
if (MainApp.getConfigBuilder().getActivePump().getPumpDescription().isExtendedBolusCapable && MainApp.getConfigBuilder().isInHistoryExtendedBoluslInProgress()) {
ConfigBuilderPlugin.getCommandQueue().cancelExtended( new Callback() {
@Override
public void run() {
if (!result.success) {
ToastUtils.showToastInUiThread(MainApp.instance().getApplicationContext(), MainApp.sResources.getString(R.string.extendedbolusdeliveryerror));
}
}
});
}
NSUpload.uploadOpenAPSOffline(60); NSUpload.uploadOpenAPSOffline(60);
return true; return true;
} else if (item.getTitle().equals(MainApp.sResources.getString(R.string.disconnectpumpfor2h))) { } else if (item.getTitle().equals(MainApp.sResources.getString(R.string.disconnectpumpfor2h))) {
@ -522,6 +561,16 @@ public class OverviewFragment extends Fragment implements View.OnClickListener,
} }
} }
}); });
if (MainApp.getConfigBuilder().getActivePump().getPumpDescription().isExtendedBolusCapable && MainApp.getConfigBuilder().isInHistoryExtendedBoluslInProgress()) {
ConfigBuilderPlugin.getCommandQueue().cancelExtended( new Callback() {
@Override
public void run() {
if (!result.success) {
ToastUtils.showToastInUiThread(MainApp.instance().getApplicationContext(), MainApp.sResources.getString(R.string.extendedbolusdeliveryerror));
}
}
});
}
NSUpload.uploadOpenAPSOffline(120); NSUpload.uploadOpenAPSOffline(120);
return true; return true;
} else if (item.getTitle().equals(MainApp.sResources.getString(R.string.disconnectpumpfor3h))) { } else if (item.getTitle().equals(MainApp.sResources.getString(R.string.disconnectpumpfor3h))) {
@ -535,6 +584,16 @@ public class OverviewFragment extends Fragment implements View.OnClickListener,
} }
} }
}); });
if (MainApp.getConfigBuilder().getActivePump().getPumpDescription().isExtendedBolusCapable && MainApp.getConfigBuilder().isInHistoryExtendedBoluslInProgress()) {
ConfigBuilderPlugin.getCommandQueue().cancelExtended( new Callback() {
@Override
public void run() {
if (!result.success) {
ToastUtils.showToastInUiThread(MainApp.instance().getApplicationContext(), MainApp.sResources.getString(R.string.extendedbolusdeliveryerror));
}
}
});
}
NSUpload.uploadOpenAPSOffline(180); NSUpload.uploadOpenAPSOffline(180);
return true; return true;
} else if (item.getTitle().equals(MainApp.sResources.getString(R.string.careportal_profileswitch))) { } else if (item.getTitle().equals(MainApp.sResources.getString(R.string.careportal_profileswitch))) {
@ -578,6 +637,24 @@ public class OverviewFragment extends Fragment implements View.OnClickListener,
if (ConfigBuilderPlugin.getActivePump().isSuspended() || !ConfigBuilderPlugin.getActivePump().isInitialized()) if (ConfigBuilderPlugin.getActivePump().isSuspended() || !ConfigBuilderPlugin.getActivePump().isInitialized())
ConfigBuilderPlugin.getCommandQueue().readStatus("RefreshClicked", null); ConfigBuilderPlugin.getCommandQueue().readStatus("RefreshClicked", null);
break; break;
case R.id.overview_showprediction_label:
showPredictionCheckbox.toggle();
break;
case R.id.overview_showbasals_label:
showBasalsCheckbox.toggle();
break;
case R.id.overview_showiob_label:
showIobCheckbox.toggle();
break;
case R.id.overview_showcob_label:
showCobCheckbox.toggle();
break;
case R.id.overview_showdeviations_label:
showDeviationsCheckbox.toggle();
break;
case R.id.overview_showratios_label:
showRatiosCheckbox.toggle();
break;
} }
} }
@ -1208,11 +1285,11 @@ public class OverviewFragment extends Fragment implements View.OnClickListener,
final boolean predictionsAvailable = finalLastRun != null && finalLastRun.request.hasPredictions; final boolean predictionsAvailable = finalLastRun != null && finalLastRun.request.hasPredictions;
if (predictionsAvailable) { if (predictionsAvailable) {
showPredictionView.setVisibility(View.VISIBLE); showPredictionCheckbox.setVisibility(View.VISIBLE);
getActivity().findViewById(R.id.overview_showprediction_label).setVisibility(View.VISIBLE); showPredictionLabel.setVisibility(View.VISIBLE);
} else { } else {
showPredictionView.setVisibility(View.GONE); showPredictionCheckbox.setVisibility(View.GONE);
getActivity().findViewById(R.id.overview_showprediction_label).setVisibility(View.GONE); showPredictionLabel.setVisibility(View.GONE);
} }
// pump status from ns // pump status from ns
@ -1265,7 +1342,7 @@ public class OverviewFragment extends Fragment implements View.OnClickListener,
final long toTime; final long toTime;
final long fromTime; final long fromTime;
final long endTime; final long endTime;
if (predictionsAvailable && showPredictionView.isChecked()) { if (predictionsAvailable && showPredictionCheckbox.isChecked()) {
int predHours = (int) (Math.ceil(finalLastRun.constraintsProcessed.getLatestPredictionsTime() - System.currentTimeMillis()) / (60 * 60 * 1000)); int predHours = (int) (Math.ceil(finalLastRun.constraintsProcessed.getLatestPredictionsTime() - System.currentTimeMillis()) / (60 * 60 * 1000));
predHours = Math.min(2, predHours); predHours = Math.min(2, predHours);
predHours = Math.max(0, predHours); predHours = Math.max(0, predHours);
@ -1292,7 +1369,7 @@ public class OverviewFragment extends Fragment implements View.OnClickListener,
graphData.addInRangeArea(fromTime, endTime, lowLine, highLine); graphData.addInRangeArea(fromTime, endTime, lowLine, highLine);
// **** BG **** // **** BG ****
if (predictionsAvailable && showPredictionView.isChecked()) if (predictionsAvailable && showPredictionCheckbox.isChecked())
graphData.addBgReadings(fromTime, toTime, lowLine, highLine, finalLastRun.constraintsProcessed); graphData.addBgReadings(fromTime, toTime, lowLine, highLine, finalLastRun.constraintsProcessed);
else else
graphData.addBgReadings(fromTime, toTime, lowLine, highLine, null); graphData.addBgReadings(fromTime, toTime, lowLine, highLine, null);
@ -1304,7 +1381,7 @@ public class OverviewFragment extends Fragment implements View.OnClickListener,
graphData.addTreatments(fromTime, endTime); graphData.addTreatments(fromTime, endTime);
// add basal data // add basal data
if (pump.getPumpDescription().isTempBasalCapable && showBasalsView.isChecked()) { if (pump.getPumpDescription().isTempBasalCapable && showBasalsCheckbox.isChecked()) {
graphData.addBasals(fromTime, now, lowLine / graphData.maxY / 1.2d); graphData.addBasals(fromTime, now, lowLine / graphData.maxY / 1.2d);
} }
@ -1322,25 +1399,25 @@ public class OverviewFragment extends Fragment implements View.OnClickListener,
boolean useRatioForScale = false; boolean useRatioForScale = false;
boolean useDSForScale = false; boolean useDSForScale = false;
if (showIobView.isChecked()) { if (showIobCheckbox.isChecked()) {
useIobForScale = true; useIobForScale = true;
} else if (showCobView.isChecked()) { } else if (showCobCheckbox.isChecked()) {
useCobForScale = true; useCobForScale = true;
} else if (showDeviationsView.isChecked()) { } else if (showDeviationsCheckbox.isChecked()) {
useDevForScale = true; useDevForScale = true;
} else if (showRatiosView.isChecked()) { } else if (showRatiosCheckbox.isChecked()) {
useRatioForScale = true; useRatioForScale = true;
} else if (Config.displayDeviationSlope) { } else if (Config.displayDeviationSlope) {
useDSForScale = true; useDSForScale = true;
} }
if (showIobView.isChecked()) if (showIobCheckbox.isChecked())
secondGraphData.addIob(fromTime, now, useIobForScale, 1d); secondGraphData.addIob(fromTime, now, useIobForScale, 1d);
if (showCobView.isChecked()) if (showCobCheckbox.isChecked())
secondGraphData.addCob(fromTime, now, useCobForScale, useCobForScale ? 1d : 0.5d); secondGraphData.addCob(fromTime, now, useCobForScale, useCobForScale ? 1d : 0.5d);
if (showDeviationsView.isChecked()) if (showDeviationsCheckbox.isChecked())
secondGraphData.addDeviations(fromTime, now, useDevForScale, 1d); secondGraphData.addDeviations(fromTime, now, useDevForScale, 1d);
if (showRatiosView.isChecked()) if (showRatiosCheckbox.isChecked())
secondGraphData.addRatio(fromTime, now, useRatioForScale, 1d); secondGraphData.addRatio(fromTime, now, useRatioForScale, 1d);
if (Config.displayDeviationSlope) if (Config.displayDeviationSlope)
secondGraphData.addDeviationSlope(fromTime, now, useDSForScale, 1d); secondGraphData.addDeviationSlope(fromTime, now, useDSForScale, 1d);
@ -1356,7 +1433,7 @@ public class OverviewFragment extends Fragment implements View.OnClickListener,
activity.runOnUiThread(new Runnable() { activity.runOnUiThread(new Runnable() {
@Override @Override
public void run() { public void run() {
if (showIobView.isChecked() || showCobView.isChecked() || showDeviationsView.isChecked() || showRatiosView.isChecked() || Config.displayDeviationSlope) { if (showIobCheckbox.isChecked() || showCobCheckbox.isChecked() || showDeviationsCheckbox.isChecked() || showRatiosCheckbox.isChecked() || Config.displayDeviationSlope) {
iobGraph.setVisibility(View.VISIBLE); iobGraph.setVisibility(View.VISIBLE);
} else { } else {
iobGraph.setVisibility(View.GONE); iobGraph.setVisibility(View.GONE);

View file

@ -250,7 +250,7 @@ public class GraphData {
} }
// Careportal // Careportal
List<CareportalEvent> careportalEvents = MainApp.getDbHelper().getCareportalEventsFromTime(fromTime, true); List<CareportalEvent> careportalEvents = MainApp.getDbHelper().getCareportalEventsFromTime(fromTime - 6 * 60 * 60 * 1000, true);
for (int tx = 0; tx < careportalEvents.size(); tx++) { for (int tx = 0; tx < careportalEvents.size(); tx++) {
DataPointWithLabelInterface t = careportalEvents.get(tx); DataPointWithLabelInterface t = careportalEvents.get(tx);

View file

@ -136,9 +136,6 @@ public class PointsWithLabelGraphSeries<E extends DataPointWithLabelInterface> e
Iterator<E> values = getValues(minX, maxX); Iterator<E> values = getValues(minX, maxX);
// draw background // draw background
double lastEndY = 0;
double lastEndX = 0;
// draw data // draw data
double diffY = maxY - minY; double diffY = maxY - minY;
@ -149,9 +146,8 @@ public class PointsWithLabelGraphSeries<E extends DataPointWithLabelInterface> e
float graphLeft = graphView.getGraphContentLeft(); float graphLeft = graphView.getGraphContentLeft();
float graphTop = graphView.getGraphContentTop(); float graphTop = graphView.getGraphContentTop();
lastEndY = 0; float scaleX = (float) (graphWidth / diffX);
lastEndX = 0;
float firstX = 0;
int i=0; int i=0;
while (values.hasNext()) { while (values.hasNext()) {
E value = values.next(); E value = values.next();
@ -166,9 +162,6 @@ public class PointsWithLabelGraphSeries<E extends DataPointWithLabelInterface> e
double ratX = valX / diffX; double ratX = valX / diffX;
double x = graphWidth * ratX; double x = graphWidth * ratX;
double orgX = x;
double orgY = y;
// overdraw // overdraw
boolean overdraw = false; boolean overdraw = false;
if (x > graphWidth) { // end right if (x > graphWidth) { // end right
@ -180,6 +173,14 @@ public class PointsWithLabelGraphSeries<E extends DataPointWithLabelInterface> e
if (y > graphHeight) { // end top if (y > graphHeight) { // end top
overdraw = true; overdraw = true;
} }
long duration = value.getDuration();
float endWithDuration = (float) (x + duration * scaleX + graphLeft + 1);
// cut off to graph start if needed
if (x < 0 && endWithDuration > 0) {
x = 0;
}
/* Fix a bug that continue to show the DOT after Y axis */ /* Fix a bug that continue to show the DOT after Y axis */
if(x < 0) { if(x < 0) {
overdraw = true; overdraw = true;
@ -190,8 +191,8 @@ public class PointsWithLabelGraphSeries<E extends DataPointWithLabelInterface> e
registerDataPoint(endX, endY, value); registerDataPoint(endX, endY, value);
float xpluslength = 0; float xpluslength = 0;
if (value.getDuration() > 0) { if (duration > 0) {
xpluslength = endX + Math.min((float) (value.getDuration() * graphWidth / diffX), graphLeft + graphWidth); xpluslength = Math.min(endWithDuration, graphLeft + graphWidth);
} }
// draw data point // draw data point

View file

@ -7,7 +7,7 @@ import android.content.Intent;
import android.graphics.Bitmap; import android.graphics.Bitmap;
import android.graphics.BitmapFactory; import android.graphics.BitmapFactory;
import android.support.v4.app.TaskStackBuilder; import android.support.v4.app.TaskStackBuilder;
import android.support.v7.app.NotificationCompat; import android.support.v4.app.NotificationCompat;
import com.squareup.otto.Subscribe; import com.squareup.otto.Subscribe;

View file

@ -110,6 +110,8 @@ public class DanaRPlugin implements PluginBase, PumpInterface, DanaRInterface, C
pumpDescription.basalMinimumRate = 0.04d; pumpDescription.basalMinimumRate = 0.04d;
pumpDescription.isRefillingCapable = true; pumpDescription.isRefillingCapable = true;
pumpDescription.storesCarbInfo = true;
} }
private ServiceConnection mConnection = new ServiceConnection() { private ServiceConnection mConnection = new ServiceConnection() {

View file

@ -112,6 +112,8 @@ public class DanaRKoreanPlugin implements PluginBase, PumpInterface, DanaRInterf
pumpDescription.basalMinimumRate = 0.1d; pumpDescription.basalMinimumRate = 0.1d;
pumpDescription.isRefillingCapable = true; pumpDescription.isRefillingCapable = true;
pumpDescription.storesCarbInfo = true;
} }
private ServiceConnection mConnection = new ServiceConnection() { private ServiceConnection mConnection = new ServiceConnection() {

View file

@ -189,6 +189,8 @@ public class DanaRSPlugin implements PluginBase, PumpInterface, DanaRInterface,
pumpDescription.basalMinimumRate = 0.04d; pumpDescription.basalMinimumRate = 0.04d;
pumpDescription.isRefillingCapable = true; pumpDescription.isRefillingCapable = true;
pumpDescription.storesCarbInfo = true;
} }
private ServiceConnection mConnection = new ServiceConnection() { private ServiceConnection mConnection = new ServiceConnection() {

View file

@ -9,6 +9,7 @@ import java.util.Calendar;
import java.util.GregorianCalendar; import java.util.GregorianCalendar;
import info.nightscout.androidaps.Config; import info.nightscout.androidaps.Config;
import info.nightscout.utils.DateUtil;
public class DanaRS_Packet_APS_Set_Event_History extends DanaRS_Packet { public class DanaRS_Packet_APS_Set_Event_History extends DanaRS_Packet {
private static Logger log = LoggerFactory.getLogger(DanaRS_Packet_APS_Set_Event_History.class); private static Logger log = LoggerFactory.getLogger(DanaRS_Packet_APS_Set_Event_History.class);
@ -30,6 +31,8 @@ public class DanaRS_Packet_APS_Set_Event_History extends DanaRS_Packet {
this.time = time; this.time = time;
this.param1 = param1; this.param1 = param1;
this.param2 = param2; this.param2 = param2;
if (Config.logDanaMessageDetail)
log.debug("Set history entry: " + DateUtil.dateAndTimeString(time) + " type: " + type + " param1: " + param1 + " param2: " + param2);
} }
@Override @Override

View file

@ -164,6 +164,8 @@ public class BLEComm {
scheduledDisconnection = null; scheduledDisconnection = null;
if ((mBluetoothAdapter == null) || (mBluetoothGatt == null)) { if ((mBluetoothAdapter == null) || (mBluetoothGatt == null)) {
log.debug("disconnect not possible: (mBluetoothAdapter == null) " + (mBluetoothAdapter == null));
log.debug("disconnect not possible: (mBluetoothGatt == null) " + (mBluetoothGatt == null));
return; return;
} }
setCharacteristicNotification(getUARTReadBTGattChar(), false); setCharacteristicNotification(getUARTReadBTGattChar(), false);
@ -257,6 +259,8 @@ public class BLEComm {
log.debug("setCharacteristicNotification"); log.debug("setCharacteristicNotification");
if ((mBluetoothAdapter == null) || (mBluetoothGatt == null)) { if ((mBluetoothAdapter == null) || (mBluetoothGatt == null)) {
log.debug("BluetoothAdapter not initialized_ERROR"); log.debug("BluetoothAdapter not initialized_ERROR");
isConnecting = false;
isConnected = false;
return; return;
} }
mBluetoothGatt.setCharacteristicNotification(characteristic, enabled); mBluetoothGatt.setCharacteristicNotification(characteristic, enabled);
@ -266,6 +270,8 @@ public class BLEComm {
log.debug("readCharacteristic"); log.debug("readCharacteristic");
if ((mBluetoothAdapter == null) || (mBluetoothGatt == null)) { if ((mBluetoothAdapter == null) || (mBluetoothGatt == null)) {
log.debug("BluetoothAdapter not initialized_ERROR"); log.debug("BluetoothAdapter not initialized_ERROR");
isConnecting = false;
isConnected = false;
return; return;
} }
mBluetoothGatt.readCharacteristic(characteristic); mBluetoothGatt.readCharacteristic(characteristic);
@ -274,6 +280,8 @@ public class BLEComm {
public void writeCharacteristic_NO_RESPONSE(final BluetoothGattCharacteristic characteristic, final byte[] data) { public void writeCharacteristic_NO_RESPONSE(final BluetoothGattCharacteristic characteristic, final byte[] data) {
if ((mBluetoothAdapter == null) || (mBluetoothGatt == null)) { if ((mBluetoothAdapter == null) || (mBluetoothGatt == null)) {
log.debug("BluetoothAdapter not initialized_ERROR"); log.debug("BluetoothAdapter not initialized_ERROR");
isConnecting = false;
isConnected = false;
return; return;
} }
@ -306,6 +314,8 @@ public class BLEComm {
log.debug("getSupportedGattServices"); log.debug("getSupportedGattServices");
if ((mBluetoothAdapter == null) || (mBluetoothGatt == null)) { if ((mBluetoothAdapter == null) || (mBluetoothGatt == null)) {
log.debug("BluetoothAdapter not initialized_ERROR"); log.debug("BluetoothAdapter not initialized_ERROR");
isConnecting = false;
isConnected = false;
return null; return null;
} }

View file

@ -109,6 +109,8 @@ public class DanaRv2Plugin implements PluginBase, PumpInterface, DanaRInterface,
pumpDescription.basalMinimumRate = 0.04d; pumpDescription.basalMinimumRate = 0.04d;
pumpDescription.isRefillingCapable = true; pumpDescription.isRefillingCapable = true;
pumpDescription.storesCarbInfo = true;
} }
private ServiceConnection mConnection = new ServiceConnection() { private ServiceConnection mConnection = new ServiceConnection() {

View file

@ -11,6 +11,7 @@ import java.util.Arrays;
import java.util.Date; import java.util.Date;
import java.util.List; import java.util.List;
import info.nightscout.androidaps.Config;
import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.R; import info.nightscout.androidaps.R;
import info.nightscout.androidaps.data.Profile; import info.nightscout.androidaps.data.Profile;
@ -191,8 +192,10 @@ public class SensitivityAAPSPlugin implements PluginBase, SensitivityInterface{
log.debug(ratioLimit); log.debug(ratioLimit);
} }
log.debug("Sensitivity to: " + new Date(toTime).toLocaleString() + " percentile: " + percentile + " ratio: " + ratio); if (Config.logAutosensData) {
log.debug("Sensitivity to: deviations " + Arrays.toString(deviations)); log.debug("Sensitivity to: " + new Date(toTime).toLocaleString() + " percentile: " + percentile + " ratio: " + ratio + " mealCOB: " + current.cob);
log.debug("Sensitivity to: deviations " + Arrays.toString(deviations));
}
AutosensResult output = new AutosensResult(); AutosensResult output = new AutosensResult();
output.ratio = Round.roundTo(ratio, 0.01); output.ratio = Round.roundTo(ratio, 0.01);

View file

@ -7,8 +7,10 @@ import org.slf4j.LoggerFactory;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.Date;
import java.util.List; import java.util.List;
import info.nightscout.androidaps.Config;
import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.R; import info.nightscout.androidaps.R;
import info.nightscout.androidaps.data.Profile; import info.nightscout.androidaps.data.Profile;
@ -118,7 +120,7 @@ public class SensitivityOref0Plugin implements PluginBase, SensitivityInterface
return new AutosensResult(); return new AutosensResult();
} }
AutosensData current = IobCobCalculatorPlugin.getLastAutosensData("SensitivityOref0"); // this is running inside lock already AutosensData current = IobCobCalculatorPlugin.getAutosensData(toTime); // this is running inside lock already
if (current == null) { if (current == null) {
log.debug("No current autosens data available"); log.debug("No current autosens data available");
return new AutosensResult(); return new AutosensResult();
@ -199,10 +201,8 @@ public class SensitivityOref0Plugin implements PluginBase, SensitivityInterface
log.debug(ratioLimit); log.debug(ratioLimit);
} }
double newisf = Math.round(Profile.toMgdl(sens, profile.getUnits()) / ratio); if (Config.logAutosensData)
if (ratio != 1) { log.debug("Sensitivity to: " + new Date(toTime).toLocaleString() + " ratio: " + ratio + " mealCOB: " + current.cob);
log.debug("ISF adjusted from " + Profile.toMgdl(sens, profile.getUnits()) + " to " + newisf);
}
AutosensResult output = new AutosensResult(); AutosensResult output = new AutosensResult();
output.ratio = Round.roundTo(ratio, 0.01); output.ratio = Round.roundTo(ratio, 0.01);

View file

@ -217,7 +217,7 @@ public class SensitivityWeightedAveragePlugin implements PluginBase, Sensitivity
} }
if (Config.logAutosensData) if (Config.logAutosensData)
log.debug("Sensitivity to: " + new Date(toTime).toLocaleString() + " weightedaverage: " + average + " ratio: " + ratio); log.debug("Sensitivity to: " + new Date(toTime).toLocaleString() + " weightedaverage: " + average + " ratio: " + ratio + " mealCOB: " + current.cob);
AutosensResult output = new AutosensResult(); AutosensResult output = new AutosensResult();
output.ratio = Round.roundTo(ratio, 0.01); output.ratio = Round.roundTo(ratio, 0.01);

View file

@ -20,6 +20,7 @@ import info.nightscout.androidaps.events.EventExtendedBolusChange;
import info.nightscout.androidaps.plugins.Common.SubscriberFragment; import info.nightscout.androidaps.plugins.Common.SubscriberFragment;
import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin; import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin;
import info.nightscout.androidaps.plugins.Treatments.fragments.TreatmentsBolusFragment; import info.nightscout.androidaps.plugins.Treatments.fragments.TreatmentsBolusFragment;
import info.nightscout.androidaps.plugins.Treatments.fragments.TreatmentsCareportalFragment;
import info.nightscout.androidaps.plugins.Treatments.fragments.TreatmentsExtendedBolusesFragment; import info.nightscout.androidaps.plugins.Treatments.fragments.TreatmentsExtendedBolusesFragment;
import info.nightscout.androidaps.plugins.Treatments.fragments.TreatmentsProfileSwitchFragment; import info.nightscout.androidaps.plugins.Treatments.fragments.TreatmentsProfileSwitchFragment;
import info.nightscout.androidaps.plugins.Treatments.fragments.TreatmentsTempTargetFragment; import info.nightscout.androidaps.plugins.Treatments.fragments.TreatmentsTempTargetFragment;
@ -33,6 +34,7 @@ public class TreatmentsFragment extends SubscriberFragment implements View.OnCli
TextView tempBasalsTab; TextView tempBasalsTab;
TextView tempTargetTab; TextView tempTargetTab;
TextView profileSwitchTab; TextView profileSwitchTab;
TextView careportalTab;
@Override @Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, public View onCreateView(LayoutInflater inflater, ViewGroup container,
@ -45,11 +47,13 @@ public class TreatmentsFragment extends SubscriberFragment implements View.OnCli
tempBasalsTab = (TextView) view.findViewById(R.id.treatments_tempbasals); tempBasalsTab = (TextView) view.findViewById(R.id.treatments_tempbasals);
tempTargetTab = (TextView) view.findViewById(R.id.treatments_temptargets); tempTargetTab = (TextView) view.findViewById(R.id.treatments_temptargets);
profileSwitchTab = (TextView) view.findViewById(R.id.treatments_profileswitches); profileSwitchTab = (TextView) view.findViewById(R.id.treatments_profileswitches);
careportalTab = (TextView) view.findViewById(R.id.treatments_careportal);
treatmentsTab.setOnClickListener(this); treatmentsTab.setOnClickListener(this);
extendedBolusesTab.setOnClickListener(this); extendedBolusesTab.setOnClickListener(this);
tempBasalsTab.setOnClickListener(this); tempBasalsTab.setOnClickListener(this);
tempTargetTab.setOnClickListener(this); tempTargetTab.setOnClickListener(this);
profileSwitchTab.setOnClickListener(this); profileSwitchTab.setOnClickListener(this);
careportalTab.setOnClickListener(this);
setFragment(new TreatmentsBolusFragment()); setFragment(new TreatmentsBolusFragment());
setBackgroundColorOnSelected(treatmentsTab); setBackgroundColorOnSelected(treatmentsTab);
@ -87,6 +91,10 @@ public class TreatmentsFragment extends SubscriberFragment implements View.OnCli
setFragment(new TreatmentsProfileSwitchFragment()); setFragment(new TreatmentsProfileSwitchFragment());
setBackgroundColorOnSelected(profileSwitchTab); setBackgroundColorOnSelected(profileSwitchTab);
break; break;
case R.id.treatments_careportal:
setFragment(new TreatmentsCareportalFragment());
setBackgroundColorOnSelected(careportalTab);
break;
} }
} }
@ -104,6 +112,7 @@ public class TreatmentsFragment extends SubscriberFragment implements View.OnCli
tempBasalsTab.setBackgroundColor(MainApp.sResources.getColor(R.color.defaultbackground)); tempBasalsTab.setBackgroundColor(MainApp.sResources.getColor(R.color.defaultbackground));
tempTargetTab.setBackgroundColor(MainApp.sResources.getColor(R.color.defaultbackground)); tempTargetTab.setBackgroundColor(MainApp.sResources.getColor(R.color.defaultbackground));
profileSwitchTab.setBackgroundColor(MainApp.sResources.getColor(R.color.defaultbackground)); profileSwitchTab.setBackgroundColor(MainApp.sResources.getColor(R.color.defaultbackground));
careportalTab.setBackgroundColor(MainApp.sResources.getColor(R.color.defaultbackground));
selected.setBackgroundColor(MainApp.sResources.getColor(R.color.tabBgColorSelected)); selected.setBackgroundColor(MainApp.sResources.getColor(R.color.tabBgColorSelected));
} }

View file

@ -0,0 +1,192 @@
package info.nightscout.androidaps.plugins.Treatments.fragments;
import android.app.Activity;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.graphics.Paint;
import android.os.Bundle;
import android.support.v7.app.AlertDialog;
import android.support.v7.widget.CardView;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.TextView;
import com.squareup.otto.Subscribe;
import java.util.List;
import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.R;
import info.nightscout.androidaps.Services.Intents;
import info.nightscout.androidaps.db.CareportalEvent;
import info.nightscout.androidaps.events.EventCareportalEventChange;
import info.nightscout.androidaps.plugins.Common.SubscriberFragment;
import info.nightscout.androidaps.plugins.NSClientInternal.UploadQueue;
import info.nightscout.utils.DateUtil;
import info.nightscout.utils.NSUpload;
import info.nightscout.utils.SP;
import info.nightscout.utils.Translator;
/**
* Created by mike on 13/01/17.
*/
public class TreatmentsCareportalFragment extends SubscriberFragment implements View.OnClickListener {
RecyclerView recyclerView;
LinearLayoutManager llm;
Button refreshFromNS;
Context context;
public class RecyclerViewAdapter extends RecyclerView.Adapter<RecyclerViewAdapter.CareportalEventsViewHolder> {
List<CareportalEvent> careportalEventList;
RecyclerViewAdapter(List<CareportalEvent> careportalEventList) {
this.careportalEventList = careportalEventList;
}
@Override
public CareportalEventsViewHolder onCreateViewHolder(ViewGroup viewGroup, int viewType) {
View v = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.treatments_careportal_item, viewGroup, false);
CareportalEventsViewHolder CareportalEventsViewHolder = new CareportalEventsViewHolder(v);
return CareportalEventsViewHolder;
}
@Override
public void onBindViewHolder(CareportalEventsViewHolder holder, int position) {
CareportalEvent careportalEvent = careportalEventList.get(position);
holder.ns.setVisibility(NSUpload.isIdValid(careportalEvent._id) ? View.VISIBLE : View.GONE);
holder.date.setText(DateUtil.dateAndTimeString(careportalEvent.date));
holder.note.setText(careportalEvent.getNotes());
holder.type.setText(Translator.translate(careportalEvent.eventType));
holder.remove.setTag(careportalEvent);
}
@Override
public int getItemCount() {
return careportalEventList.size();
}
@Override
public void onAttachedToRecyclerView(RecyclerView recyclerView) {
super.onAttachedToRecyclerView(recyclerView);
}
public class CareportalEventsViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
CardView cv;
TextView date;
TextView type;
TextView note;
TextView remove;
TextView ns;
CareportalEventsViewHolder(View itemView) {
super(itemView);
cv = (CardView) itemView.findViewById(R.id.careportal_cardview);
date = (TextView) itemView.findViewById(R.id.careportal_date);
type = (TextView) itemView.findViewById(R.id.careportal_type);
note = (TextView) itemView.findViewById(R.id.careportal_note);
ns = (TextView) itemView.findViewById(R.id.ns_sign);
remove = (TextView) itemView.findViewById(R.id.careportal_remove);
remove.setOnClickListener(this);
remove.setPaintFlags(remove.getPaintFlags() | Paint.UNDERLINE_TEXT_FLAG);
}
@Override
public void onClick(View v) {
final CareportalEvent careportalEvent = (CareportalEvent) v.getTag();
switch (v.getId()) {
case R.id.careportal_remove:
AlertDialog.Builder builder = new AlertDialog.Builder(context);
builder.setTitle(MainApp.sResources.getString(R.string.confirmation));
builder.setMessage(MainApp.sResources.getString(R.string.removerecord) + "\n" + DateUtil.dateAndTimeString(careportalEvent.date));
builder.setPositiveButton(MainApp.sResources.getString(R.string.ok), new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
final String _id = careportalEvent._id;
if (NSUpload.isIdValid(_id)) {
NSUpload.removeCareportalEntryFromNS(_id);
} else {
UploadQueue.removeID("dbAdd", _id);
}
MainApp.getDbHelper().delete(careportalEvent);
}
});
builder.setNegativeButton(MainApp.sResources.getString(R.string.cancel), null);
builder.show();
break;
}
}
}
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.treatments_careportal_fragment, container, false);
recyclerView = (RecyclerView) view.findViewById(R.id.careportal_recyclerview);
recyclerView.setHasFixedSize(true);
llm = new LinearLayoutManager(view.getContext());
recyclerView.setLayoutManager(llm);
RecyclerViewAdapter adapter = new RecyclerViewAdapter(MainApp.getDbHelper().getCareportalEventsFromTime(false));
recyclerView.setAdapter(adapter);
refreshFromNS = (Button) view.findViewById(R.id.careportal_refreshfromnightscout);
refreshFromNS.setOnClickListener(this);
context = getContext();
boolean nsUploadOnly = SP.getBoolean(R.string.key_ns_upload_only, false);
if (nsUploadOnly)
refreshFromNS.setVisibility(View.GONE);
updateGUI();
return view;
}
@Override
public void onClick(View view) {
switch (view.getId()) {
case R.id.careportal_refreshfromnightscout:
AlertDialog.Builder builder = new AlertDialog.Builder(this.getContext());
builder.setTitle(this.getContext().getString(R.string.confirmation));
builder.setMessage(this.getContext().getString(R.string.refresheventsfromnightscout) + " ?");
builder.setPositiveButton(this.getContext().getString(R.string.ok), new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
MainApp.getDbHelper().resetCareportalEvents();
Intent restartNSClient = new Intent(Intents.ACTION_RESTART);
MainApp.instance().getApplicationContext().sendBroadcast(restartNSClient);
}
});
builder.setNegativeButton(this.getContext().getString(R.string.cancel), null);
builder.show();
break;
}
}
@Subscribe
public void onStatusEvent(final EventCareportalEventChange ev) {
updateGUI();
}
@Override
protected void updateGUI() {
Activity activity = getActivity();
if (activity != null)
activity.runOnUiThread(new Runnable() {
@Override
public void run() {
recyclerView.swapAdapter(new RecyclerViewAdapter(MainApp.getDbHelper().getCareportalEventsFromTime(false)), false);
}
});
}
}

View file

@ -637,6 +637,11 @@ public class WatchUpdaterService extends WearableListenerService implements
private String generateBasalString(TreatmentsInterface treatmentsInterface) { private String generateBasalString(TreatmentsInterface treatmentsInterface) {
String basalStringResult; String basalStringResult;
Profile profile = MainApp.getConfigBuilder().getProfile();
if (profile == null)
return "";
TemporaryBasal activeTemp = treatmentsInterface.getTempBasalFromHistory(System.currentTimeMillis()); TemporaryBasal activeTemp = treatmentsInterface.getTempBasalFromHistory(System.currentTimeMillis());
if (activeTemp != null) { if (activeTemp != null) {
basalStringResult = activeTemp.toStringShort(); basalStringResult = activeTemp.toStringShort();
@ -644,7 +649,7 @@ public class WatchUpdaterService extends WearableListenerService implements
if (SP.getBoolean(R.string.key_danar_visualizeextendedaspercentage, false)) { if (SP.getBoolean(R.string.key_danar_visualizeextendedaspercentage, false)) {
basalStringResult = "100%"; basalStringResult = "100%";
} else { } else {
basalStringResult = DecimalFormatter.to2Decimal(MainApp.getConfigBuilder().getProfile().getBasal()) + "U/h"; basalStringResult = DecimalFormatter.to2Decimal(profile.getBasal()) + "U/h";
} }
} }
return basalStringResult; return basalStringResult;

View file

@ -148,8 +148,6 @@ public class CommandQueue {
public static void independentConnect(String reason, Callback callback) { public static void independentConnect(String reason, Callback callback) {
CommandQueue tempCommandQueue = new CommandQueue(); CommandQueue tempCommandQueue = new CommandQueue();
tempCommandQueue.readStatus(reason, callback); tempCommandQueue.readStatus(reason, callback);
QueueThread tempThread = new QueueThread(tempCommandQueue);
tempThread.start();
} }
// returns true if command is queued // returns true if command is queued

View file

@ -16,6 +16,8 @@ import info.nightscout.androidaps.events.EventPumpStatusChanged;
import info.nightscout.androidaps.interfaces.PumpInterface; import info.nightscout.androidaps.interfaces.PumpInterface;
import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin; import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin;
import info.nightscout.androidaps.plugins.Overview.events.EventDismissBolusprogressIfRunning; import info.nightscout.androidaps.plugins.Overview.events.EventDismissBolusprogressIfRunning;
import info.nightscout.androidaps.plugins.Overview.events.EventNewNotification;
import info.nightscout.androidaps.plugins.Overview.notifications.Notification;
import info.nightscout.androidaps.queue.events.EventQueueChanged; import info.nightscout.androidaps.queue.events.EventQueueChanged;
import info.nightscout.utils.SP; import info.nightscout.utils.SP;
@ -35,7 +37,7 @@ public class QueueThread extends Thread {
private PowerManager.WakeLock mWakeLock; private PowerManager.WakeLock mWakeLock;
public QueueThread(CommandQueue queue) { public QueueThread(CommandQueue queue) {
super(QueueThread.class.toString()); super();
this.queue = queue; this.queue = queue;
PowerManager powerManager = (PowerManager) MainApp.instance().getApplicationContext().getSystemService(Context.POWER_SERVICE); PowerManager powerManager = (PowerManager) MainApp.instance().getApplicationContext().getSystemService(Context.POWER_SERVICE);
@ -52,12 +54,6 @@ public class QueueThread extends Thread {
while (true) { while (true) {
PumpInterface pump = ConfigBuilderPlugin.getActivePump(); PumpInterface pump = ConfigBuilderPlugin.getActivePump();
long secondsElapsed = (System.currentTimeMillis() - connectionStartTime) / 1000; long secondsElapsed = (System.currentTimeMillis() - connectionStartTime) / 1000;
if (pump.isConnecting()) {
log.debug("QUEUE: connecting " + secondsElapsed);
MainApp.bus().post(new EventPumpStatusChanged(EventPumpStatusChanged.CONNECTING, (int) secondsElapsed));
SystemClock.sleep(1000);
continue;
}
if (!pump.isConnected() && secondsElapsed > Constants.PUMP_MAX_CONNECTION_TIME_IN_SECONDS) { if (!pump.isConnected() && secondsElapsed > Constants.PUMP_MAX_CONNECTION_TIME_IN_SECONDS) {
MainApp.bus().post(new EventDismissBolusprogressIfRunning(null)); MainApp.bus().post(new EventDismissBolusprogressIfRunning(null));
@ -74,19 +70,37 @@ public class QueueThread extends Thread {
//write time //write time
SP.putLong(R.string.key_btwatchdog_lastbark, System.currentTimeMillis()); SP.putLong(R.string.key_btwatchdog_lastbark, System.currentTimeMillis());
//toggle BT //toggle BT
pump.stopConnecting();
pump.disconnect("watchdog");
SystemClock.sleep(1000);
BluetoothAdapter mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter(); BluetoothAdapter mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
mBluetoothAdapter.disable(); mBluetoothAdapter.disable();
SystemClock.sleep(1000); SystemClock.sleep(1000);
mBluetoothAdapter.enable(); mBluetoothAdapter.enable();
SystemClock.sleep(1000); SystemClock.sleep(1000);
//start over again once after watchdog barked //start over again once after watchdog barked
//Notification notification = new Notification(Notification.OLD_NSCLIENT, "Watchdog", Notification.URGENT);
//MainApp.bus().post(new EventNewNotification(notification));
connectionStartTime = lastCommandTime = System.currentTimeMillis(); connectionStartTime = lastCommandTime = System.currentTimeMillis();
pump.connect("watchdog");
} else { } else {
queue.clear(); queue.clear();
log.debug("QUEUE: no connection possible");
MainApp.bus().post(new EventPumpStatusChanged(EventPumpStatusChanged.DISCONNECTING));
pump.disconnect("Queue empty");
MainApp.bus().post(new EventPumpStatusChanged(EventPumpStatusChanged.DISCONNECTED));
return; return;
} }
} }
if (pump.isConnecting()) {
log.debug("QUEUE: connecting " + secondsElapsed);
MainApp.bus().post(new EventPumpStatusChanged(EventPumpStatusChanged.CONNECTING, (int) secondsElapsed));
SystemClock.sleep(1000);
continue;
}
if (!pump.isConnected()) { if (!pump.isConnected()) {
log.debug("QUEUE: connect"); log.debug("QUEUE: connect");
MainApp.bus().post(new EventPumpStatusChanged(EventPumpStatusChanged.CONNECTING, (int) secondsElapsed)); MainApp.bus().post(new EventPumpStatusChanged(EventPumpStatusChanged.CONNECTING, (int) secondsElapsed));

View file

@ -270,6 +270,7 @@
app:buttonTint="@color/basal" /> app:buttonTint="@color/basal" />
<TextView <TextView
android:id="@+id/overview_showbasals_label"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_gravity="center" android:layout_gravity="center"
@ -286,6 +287,7 @@
app:buttonTint="@color/iob" /> app:buttonTint="@color/iob" />
<TextView <TextView
android:id="@+id/overview_showiob_label"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_gravity="center" android:layout_gravity="center"
@ -294,7 +296,6 @@
android:textColor="@color/iob" android:textColor="@color/iob"
android:textStyle="bold" /> android:textStyle="bold" />
<CheckBox <CheckBox
android:id="@+id/overview_showcob" android:id="@+id/overview_showcob"
android:layout_width="wrap_content" android:layout_width="wrap_content"
@ -303,6 +304,7 @@
app:buttonTint="@color/cob" /> app:buttonTint="@color/cob" />
<TextView <TextView
android:id="@+id/overview_showcob_label"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_gravity="center" android:layout_gravity="center"
@ -319,6 +321,7 @@
app:buttonTint="@color/deviations" /> app:buttonTint="@color/deviations" />
<TextView <TextView
android:id="@+id/overview_showdeviations_label"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_gravity="center" android:layout_gravity="center"
@ -334,6 +337,7 @@
android:layout_gravity="center" /> android:layout_gravity="center" />
<TextView <TextView
android:id="@+id/overview_showratios_label"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_gravity="center" android:layout_gravity="center"

View file

@ -479,7 +479,7 @@
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_gravity="center" android:layout_gravity="center"
app:buttonTint="@color/prediction" /> android:buttonTint="@color/prediction" />
<TextView <TextView
android:id="@+id/overview_showprediction_label" android:id="@+id/overview_showprediction_label"
@ -496,9 +496,10 @@
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_gravity="center" android:layout_gravity="center"
app:buttonTint="@color/basal" /> android:buttonTint="@color/basal" />
<TextView <TextView
android:id="@+id/overview_showbasals_label"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_gravity="center" android:layout_gravity="center"
@ -512,9 +513,10 @@
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_gravity="center" android:layout_gravity="center"
app:buttonTint="@color/iob" /> android:buttonTint="@color/iob" />
<TextView <TextView
android:id="@+id/overview_showiob_label"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_gravity="center" android:layout_gravity="center"
@ -529,9 +531,10 @@
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_gravity="center" android:layout_gravity="center"
app:buttonTint="@color/cob" /> android:buttonTint="@color/cob" />
<TextView <TextView
android:id="@+id/overview_showcob_label"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_gravity="center" android:layout_gravity="center"
@ -545,9 +548,10 @@
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_gravity="center" android:layout_gravity="center"
app:buttonTint="@color/deviations" /> android:buttonTint="@color/deviations" />
<TextView <TextView
android:id="@+id/overview_showdeviations_label"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_gravity="center" android:layout_gravity="center"
@ -563,6 +567,7 @@
android:layout_gravity="center" /> android:layout_gravity="center" />
<TextView <TextView
android:id="@+id/overview_showratios_label"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_gravity="center" android:layout_gravity="center"

View file

@ -563,7 +563,7 @@
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_gravity="center" android:layout_gravity="center"
app:buttonTint="@color/prediction" /> android:buttonTint="@color/prediction" />
<TextView <TextView
android:id="@+id/overview_showprediction_label" android:id="@+id/overview_showprediction_label"
@ -580,9 +580,10 @@
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_gravity="center" android:layout_gravity="center"
app:buttonTint="@color/basal" /> android:buttonTint="@color/basal" />
<TextView <TextView
android:id="@+id/overview_showbasals_label"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_gravity="center" android:layout_gravity="center"
@ -596,9 +597,10 @@
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_gravity="center" android:layout_gravity="center"
app:buttonTint="@color/iob" /> android:buttonTint="@color/iob" />
<TextView <TextView
android:id="@+id/overview_showiob_label"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_gravity="center" android:layout_gravity="center"
@ -613,9 +615,10 @@
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_gravity="center" android:layout_gravity="center"
app:buttonTint="@color/cob" /> android:buttonTint="@color/cob" />
<TextView <TextView
android:id="@+id/overview_showcob_label"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_gravity="center" android:layout_gravity="center"
@ -629,9 +632,10 @@
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_gravity="center" android:layout_gravity="center"
app:buttonTint="@color/deviations" /> android:buttonTint="@color/deviations" />
<TextView <TextView
android:id="@+id/overview_showdeviations_label"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_gravity="center" android:layout_gravity="center"
@ -647,6 +651,7 @@
android:layout_gravity="center" /> android:layout_gravity="center" />
<TextView <TextView
android:id="@+id/overview_showratios_label"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_gravity="center" android:layout_gravity="center"

View file

@ -245,7 +245,7 @@
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_gravity="center" android:layout_gravity="center"
app:buttonTint="@color/prediction" /> android:buttonTint="@color/prediction" />
<TextView <TextView
android:id="@+id/overview_showprediction_label" android:id="@+id/overview_showprediction_label"
@ -262,9 +262,10 @@
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_gravity="center" android:layout_gravity="center"
app:buttonTint="@color/basal" /> android:buttonTint="@color/basal" />
<TextView <TextView
android:id="@+id/overview_showbasals_label"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_gravity="center" android:layout_gravity="center"
@ -278,9 +279,10 @@
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_gravity="center" android:layout_gravity="center"
app:buttonTint="@color/iob" /> android:buttonTint="@color/iob" />
<TextView <TextView
android:id="@+id/overview_showiob_label"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_gravity="center" android:layout_gravity="center"
@ -295,9 +297,10 @@
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_gravity="center" android:layout_gravity="center"
app:buttonTint="@color/cob" /> android:buttonTint="@color/cob" />
<TextView <TextView
android:id="@+id/overview_showcob_label"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_gravity="center" android:layout_gravity="center"
@ -311,9 +314,10 @@
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_gravity="center" android:layout_gravity="center"
app:buttonTint="@color/deviations" /> android:buttonTint="@color/deviations" />
<TextView <TextView
android:id="@+id/overview_showdeviations_label"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_gravity="center" android:layout_gravity="center"
@ -329,6 +333,7 @@
android:layout_gravity="center" /> android:layout_gravity="center" />
<TextView <TextView
android:id="@+id/overview_showratios_label"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_gravity="center" android:layout_gravity="center"

View file

@ -0,0 +1,28 @@
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="info.nightscout.androidaps.plugins.Treatments.fragments.TreatmentsCareportalFragment">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<Button
android:id="@+id/careportal_refreshfromnightscout"
style="?android:attr/buttonStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:text="@string/refresheventsfromnightscout" />
<android.support.v7.widget.RecyclerView
android:id="@+id/careportal_recyclerview"
android:layout_width="match_parent"
android:layout_height="match_parent">
</android.support.v7.widget.RecyclerView>
</LinearLayout>
</FrameLayout>

View file

@ -0,0 +1,104 @@
<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:card_view="http://schemas.android.com/apk/res-auto"
android:id="@+id/careportal_cardview"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center"
card_view:cardBackgroundColor="?android:colorBackground">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:baselineAligned="true"
android:orientation="horizontal">
<com.joanzapata.iconify.widget.IconTextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:gravity="center_vertical|right"
android:paddingLeft="10dp"
android:paddingRight="5dp"
android:text="{fa-clock-o}" />
<TextView
android:id="@+id/careportal_date"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingRight="10dp"
android:text="1.1.2000 18:00"
android:textAppearance="?android:attr/textAppearanceSmall" />
<TextView
android:id="@+id/careportal_type"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_weight="1"
android:paddingRight="10dp"
android:text=""
android:textStyle="bold" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginRight="10dp"
android:layout_weight="1"
android:text="" />
<TextView
android:id="@+id/ns_sign"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginRight="10dp"
android:text="NS"
android:textColor="@color/colorSetTempButton" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal">
<TextView
android:id="@+id/careportal_note"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_weight="1"
android:paddingLeft="10dp"
android:paddingRight="10dp"
android:text="Activity" />
<TextView
android:id="@+id/careportal_remove"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginRight="10dp"
android:text="@string/overview_quickwizard_item_remove_button"
android:textAlignment="viewEnd"
android:textColor="@android:color/holo_orange_light" />
</LinearLayout>
<View
android:layout_width="fill_parent"
android:layout_height="2dip"
android:layout_alignParentBottom="true"
android:layout_marginBottom="5dp"
android:layout_marginLeft="5dp"
android:layout_marginRight="5dp"
android:layout_marginTop="5dp"
android:background="@color/listdelimiter" />
</LinearLayout>
</android.support.v7.widget.CardView>

View file

@ -71,6 +71,16 @@
android:paddingRight="5dp" android:paddingRight="5dp"
android:text="@string/profileswitch" /> android:text="@string/profileswitch" />
<TextView
android:id="@+id/treatments_careportal"
android:layout_width="wrap_content"
android:layout_height="30dp"
android:layout_weight="1"
android:gravity="center_vertical|center_horizontal"
android:paddingLeft="5dp"
android:paddingRight="5dp"
android:text="@string/careportal" />
</com.google.android.flexbox.FlexboxLayout> </com.google.android.flexbox.FlexboxLayout>
<FrameLayout <FrameLayout

View file

@ -231,8 +231,8 @@
<string name="smscommunicator_allowednumbers_summary">XXXXXXXXXX +; + YYYYYYYYYY</string> <string name="smscommunicator_allowednumbers_summary">XXXXXXXXXX +; + YYYYYYYYYY</string>
<string formatted="false" name="smscommunicator_bolusreplywithcode">Para entregar bolo% .2fU responder con código% s</string> <string formatted="false" name="smscommunicator_bolusreplywithcode">Para entregar bolo% .2fU responder con código% s</string>
<string name="smscommunicator_bolusfailed">Bolo falló</string> <string name="smscommunicator_bolusfailed">Bolo falló</string>
<string formatted="false" name="bolusdelivered">Bolo% .2fU entregado con éxito</string> <string formatted="false" name="bolusdelivered">Bolo %.2fU entregado con éxito</string>
<string formatted="false" name="bolusdelivering">Entregando% .2fU</string> <string formatted="false" name="bolusdelivering">Entregando %.2fU</string>
<string name="smscommunicator_remotebolusnotallowed">Bolo remoto no permitido</string> <string name="smscommunicator_remotebolusnotallowed">Bolo remoto no permitido</string>
<string name="glucosetype_finger">Dedo</string> <string name="glucosetype_finger">Dedo</string>
<string name="glucosetype_sensor">Sensor</string> <string name="glucosetype_sensor">Sensor</string>

View file

@ -871,5 +871,6 @@
<string name="combo_error_bolus_verification_failed">Delivering the bolus and verifying the pump\'s history failed, please check the pump and manually create a bolus record using the Careportal tab if a bolus was delivered.</string> <string name="combo_error_bolus_verification_failed">Delivering the bolus and verifying the pump\'s history failed, please check the pump and manually create a bolus record using the Careportal tab if a bolus was delivered.</string>
<string name="combo_error_bolus_recovery_progress">Recovering from connection loss</string> <string name="combo_error_bolus_recovery_progress">Recovering from connection loss</string>
<string name="combo_reservoir_level_insufficient_for_bolus">Not enough insulin for bolus left in reservoir</string> <string name="combo_reservoir_level_insufficient_for_bolus">Not enough insulin for bolus left in reservoir</string>
<string name="extendedbolusdeliveryerror">Extended bolus delivery error</string>
</resources> </resources>

View file

@ -1,5 +1,6 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"> <PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:validate="http://schemas.android.com/apk/res-auto">
<PreferenceCategory <PreferenceCategory
android:key="others" android:key="others"
android:title="@string/othersettings_title"> android:title="@string/othersettings_title">
@ -76,12 +77,16 @@
android:defaultValue="true" android:defaultValue="true"
android:key="@string/key_enable_pump_unreachable_alert" android:key="@string/key_enable_pump_unreachable_alert"
android:title="@string/enable_pump_unreachable_alert" /> android:title="@string/enable_pump_unreachable_alert" />
<EditTextPreference <com.andreabaccega.widget.ValidatingEditTextPreference
validate:testType="numericRange"
validate:minNumber="30"
validate:maxNumber="300"
android:defaultValue="30" android:defaultValue="30"
android:dependency="@string/key_enable_pump_unreachable_alert" android:dependency="@string/key_enable_pump_unreachable_alert"
android:inputType="number" android:inputType="number"
android:key="@string/key_pump_unreachable_threshold" android:key="@string/key_pump_unreachable_threshold"
android:title="@string/pump_unreachable_threshold"></EditTextPreference> android:title="@string/pump_unreachable_threshold">
</com.andreabaccega.widget.ValidatingEditTextPreference>
</PreferenceScreen> </PreferenceScreen>
<SwitchPreference <SwitchPreference
android:defaultValue="false" android:defaultValue="false"

View file

@ -10,12 +10,17 @@ buildscript {
// NOTE: Do not place your application dependencies here; they belong // NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files // in the individual module build.gradle files
classpath 'com.jakewharton:butterknife-gradle-plugin:8.4.0'
} }
} }
allprojects { allprojects {
repositories { repositories {
jcenter() jcenter()
maven {
url "https://maven.google.com"
}
} }
} }