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:
- platform-tools
- tools
- build-tools-26.0.2
- build-tools-27.0.2
- android-23
- extra-google-m2repository
- extra-android-m2repository
- extra-google-google_play_services
before_install:
- yes | sdkmanager "platforms;android-27"
script:
# Unit Test
- ./gradlew test jacocoTestReport

View file

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

View file

@ -82,7 +82,7 @@ public class MainActivity extends AppCompatActivity implements View.OnClickListe
Manifest.permission.WRITE_EXTERNAL_STORAGE}, CASE_STORAGE);
}
askForBatteryOptimizationPermission();
checkUpgradeToProfileTarget();
doMigrations();
if (Config.logFunctionCalls)
log.debug("onCreate");
@ -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
boolean oldKeyExists = SP.contains("openapsma_min_bg");
if (oldKeyExists) {

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

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 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.TemporaryBasal;
import info.nightscout.androidaps.db.Treatment;
import info.nightscout.androidaps.events.EventAppInitialized;
import info.nightscout.androidaps.interfaces.APSInterface;
import info.nightscout.androidaps.interfaces.BgSourceInterface;
import info.nightscout.androidaps.interfaces.ConstraintsInterface;
@ -146,6 +147,7 @@ public class ConfigBuilderPlugin implements PluginBase, ConstraintsInterface, Tr
public void initialize() {
pluginList = MainApp.getPluginsList();
loadSettings();
MainApp.bus().post(new EventAppInitialized());
}
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(5).objective = MainApp.sResources.getString(R.string.objectives_5_objective);
ObjectivesPlugin.objectives.get(6).objective = MainApp.sResources.getString(R.string.objectives_6_objective);
ObjectivesPlugin.objectives.get(7).objective = MainApp.sResources.getString(R.string.objectives_7_objective);
ObjectivesPlugin.objectives.get(0).gate = MainApp.sResources.getString(R.string.objectives_0_gate);
ObjectivesPlugin.objectives.get(1).gate = MainApp.sResources.getString(R.string.objectives_1_gate);
ObjectivesPlugin.objectives.get(2).gate = MainApp.sResources.getString(R.string.objectives_2_gate);

View file

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

View file

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

View file

@ -1,8 +1,6 @@
package info.nightscout.androidaps.plugins.IobCobCalculator;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Process;
import android.os.SystemClock;
import android.support.annotation.Nullable;
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.db.BgReading;
import info.nightscout.androidaps.db.TemporaryBasal;
import info.nightscout.androidaps.db.Treatment;
import info.nightscout.androidaps.events.EventAppInitialized;
import info.nightscout.androidaps.events.EventConfigBuilderChange;
import info.nightscout.androidaps.events.EventNewBG;
import info.nightscout.androidaps.events.EventNewBasalProfile;
import info.nightscout.androidaps.events.EventPreferenceChange;
import info.nightscout.androidaps.interfaces.PluginBase;
import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin;
import info.nightscout.androidaps.plugins.IobCobCalculator.events.EventAutosensCalculationFinished;
import info.nightscout.androidaps.plugins.IobCobCalculator.events.EventNewHistoryData;
import info.nightscout.androidaps.plugins.OpenAPSSMB.OpenAPSSMBPlugin;
import info.nightscout.utils.DateUtil;
/**
* Created by mike on 24.04.2017.
@ -51,10 +49,10 @@ public class IobCobCalculatorPlugin implements PluginBase {
private static double dia = Constants.defaultDIA;
private static Handler sHandler = null;
private static HandlerThread sHandlerThread = null;
static final Object dataLock = new Object();
private static final Object dataLock = new Object();
boolean stopCalculationTrigger = false;
IobCobThread thread = null;
private static IobCobCalculatorPlugin plugin = null;
@ -134,12 +132,6 @@ public class IobCobCalculatorPlugin implements PluginBase {
IobCobCalculatorPlugin() {
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
@ -176,15 +168,10 @@ public class IobCobCalculatorPlugin implements PluginBase {
return rouded;
}
private void loadBgData() {
//log.debug("Locking loadBgData");
synchronized (dataLock) {
onNewProfile(null);
void loadBgData() {
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() {
synchronized (dataLock) {
@ -210,7 +197,7 @@ public class IobCobCalculatorPlugin implements PluginBase {
}
}
private void createBucketedData() {
void createBucketedData() {
if (isAbout5minData())
createBucketedData5min();
else
@ -242,7 +229,6 @@ public class IobCobCalculatorPlugin implements PluginBase {
}
private void createBucketedDataRecalculated() {
synchronized (dataLock) {
if (bgReadings == null || bgReadings.size() < 3) {
bucketed_data = null;
return;
@ -272,12 +258,9 @@ public class IobCobCalculatorPlugin implements PluginBase {
}
}
}
public void createBucketedData5min() {
//log.debug("Locking createBucketedData");
synchronized (dataLock) {
if (bgReadings == null || bgReadings.size() < 3) {
bucketed_data = null;
return;
@ -338,163 +321,6 @@ public class IobCobCalculatorPlugin implements PluginBase {
}
log.debug("Bucketed data created. Size: " + bucketed_data.size());
}
//log.debug("Releasing createBucketedData");
}
private void calculateSensitivityData() {
if (MainApp.getConfigBuilder() == null)
return; // app still initializing
if (MainApp.getConfigBuilder().getProfile() == null)
return; // app still initializing
//log.debug("Locking calculateSensitivityData");
long oldestTimeWithData = oldestDataAvailable();
synchronized (dataLock) {
if (bucketed_data == null || bucketed_data.size() < 3) {
log.debug("calculateSensitivityData: No bucketed data available");
return;
}
long prevDataTime = roundUpTime(bucketed_data.get(bucketed_data.size() - 3).date);
log.debug("Prev data time: " + new Date(prevDataTime).toLocaleString());
AutosensData previous = autosensDataTable.get(prevDataTime);
// start from oldest to be able sub cob
for (int i = bucketed_data.size() - 4; i >= 0; i--) {
// check if data already exists
long bgTime = bucketed_data.get(i).date;
bgTime = roundUpTime(bgTime);
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("Releasing calculateSensitivityData");
}
public static long oldestDataAvailable() {
long now = System.currentTimeMillis();
@ -631,11 +457,11 @@ public class IobCobCalculatorPlugin implements PluginBase {
return null;
}
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;
} else {
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;
}
}
@ -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);
}
@ -693,15 +519,33 @@ public class IobCobCalculatorPlugin implements PluginBase {
}
@Subscribe
public void onNewBg(EventNewBG ev) {
sHandler.post(new Runnable() {
@Override
public void run() {
loadBgData();
createBucketedData();
calculateSensitivityData();
public void onEventAppInitialized(EventAppInitialized ev) {
runCalculation("onEventAppInitialized", true);
}
@Subscribe
public void onEventNewBG(EventNewBG ev) {
stopCalculation("onEventNewBG");
runCalculation("onEventNewBG", true);
}
private void stopCalculation(String from) {
if (thread != null && thread.getState() != Thread.State.TERMINATED) {
stopCalculationTrigger = true;
log.debug("Stopping calculation thread: " + from);
while (thread.getState() != Thread.State.TERMINATED) {
SystemClock.sleep(100);
}
log.debug("Calculation thread stopped: " + from);
}
}
private void runCalculation(String from, boolean bgDataReload) {
log.debug("Starting calculation thread: " + from);
if (thread == null || thread.getState() == Thread.State.TERMINATED) {
thread = new IobCobThread(this, from, bgDataReload);
thread.start();
}
});
}
@Subscribe
@ -715,64 +559,53 @@ public class IobCobCalculatorPlugin implements PluginBase {
if (ev == null) { // on init no need of reset
return;
}
stopCalculation("onNewProfile");
synchronized (dataLock) {
log.debug("Invalidating cached data because of new profile. IOB: " + iobTable.size() + " Autosens: " + autosensDataTable.size() + " records");
iobTable = new LongSparseArray<>();
autosensDataTable = new LongSparseArray<>();
}
sHandler.post(new Runnable() {
@Override
public void run() {
calculateSensitivityData();
}
});
runCalculation("onNewProfile", false);
}
@Subscribe
public void onStatusEvent(EventPreferenceChange ev) {
public void onEventPreferenceChange(EventPreferenceChange ev) {
if (ev.isChanged(R.string.key_openapsama_autosens_period) ||
ev.isChanged(R.string.key_age) ||
ev.isChanged(R.string.key_absorption_maxtime)
) {
stopCalculation("onEventPreferenceChange");
synchronized (dataLock) {
log.debug("Invalidating cached data because of preference change. IOB: " + iobTable.size() + " Autosens: " + autosensDataTable.size() + " records");
iobTable = new LongSparseArray<>();
autosensDataTable = new LongSparseArray<>();
}
sHandler.post(new Runnable() {
@Override
public void run() {
calculateSensitivityData();
}
});
runCalculation("onEventPreferenceChange", false);
}
}
@Subscribe
public void onStatusEvent(EventConfigBuilderChange ev) {
public void onEventConfigBuilderChange(EventConfigBuilderChange ev) {
stopCalculation("onEventConfigBuilderChange");
synchronized (dataLock) {
log.debug("Invalidating cached data because of configuration change. IOB: " + iobTable.size() + " Autosens: " + autosensDataTable.size() + " records");
iobTable = new LongSparseArray<>();
autosensDataTable = new LongSparseArray<>();
}
sHandler.post(new Runnable() {
@Override
public void run() {
calculateSensitivityData();
}
});
runCalculation("onEventConfigBuilderChange", false);
}
// When historical data is changed (comming from NS etc) finished calculations after this date must be invalidated
@Subscribe
public void onNewHistoryData(EventNewHistoryData ev) {
public void onEventNewHistoryData(EventNewHistoryData ev) {
//log.debug("Locking onNewHistoryData");
stopCalculation("onEventNewHistoryData");
synchronized (dataLock) {
long time = ev.time;
// clear up 5 min back for proper COB calculation
long time = ev.time - 5 * 60 * 1000L;
log.debug("Invalidating cached data to: " + new Date(time).toLocaleString());
for (int index = iobTable.size() - 1; index >= 0; index--) {
if (iobTable.keyAt(index) > time) {
if (Config.logAutosensData)
if (Config.logAutosensData)
log.debug("Removing from iobTable: " + new Date(iobTable.keyAt(index)).toLocaleString());
iobTable.removeAt(index);
@ -799,12 +632,7 @@ public class IobCobCalculatorPlugin implements PluginBase {
}
}
}
sHandler.post(new Runnable() {
@Override
public void run() {
calculateSensitivityData();
}
});
runCalculation("onEventNewHistoryData", false);
//log.debug("Releasing onNewHistoryData");
}

View file

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

View file

@ -6,7 +6,7 @@ import android.app.PendingIntent;
import android.app.TaskStackBuilder;
import android.content.Context;
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.CustomEvent;

View file

@ -159,6 +159,7 @@ public class NewTreatmentDialog extends DialogFragment implements OnClickListene
detailedBolusInfo.carbs = finalCarbsAfterConstraints;
detailedBolusInfo.context = context;
detailedBolusInfo.source = Source.USER;
if (detailedBolusInfo.insulin > 0 || ConfigBuilderPlugin.getActivePump().getPumpDescription().storesCarbInfo) {
ConfigBuilderPlugin.getCommandQueue().bolus(detailedBolusInfo, new Callback() {
@Override
public void run() {
@ -172,6 +173,9 @@ public class NewTreatmentDialog extends DialogFragment implements OnClickListene
}
}
});
} else {
MainApp.getConfigBuilder().addToHistoryTreatment(detailedBolusInfo);
}
Answers.getInstance().logCustom(new CustomEvent("Bolus"));
}
}

View file

@ -365,6 +365,7 @@ public class WizardDialog extends DialogFragment implements OnClickListener, Com
detailedBolusInfo.carbTime = carbTime;
detailedBolusInfo.boluscalc = boluscalcJSON;
detailedBolusInfo.source = Source.USER;
if (detailedBolusInfo.insulin > 0 || ConfigBuilderPlugin.getActivePump().getPumpDescription().storesCarbInfo) {
ConfigBuilderPlugin.getCommandQueue().bolus(detailedBolusInfo, new Callback() {
@Override
public void run() {
@ -378,6 +379,9 @@ public class WizardDialog extends DialogFragment implements OnClickListener, Com
}
}
});
} else {
MainApp.getConfigBuilder().addToHistoryTreatment(detailedBolusInfo);
}
Answers.getInstance().logCustom(new CustomEvent("Wizard"));
}
}
@ -528,12 +532,12 @@ public class WizardDialog extends DialogFragment implements OnClickListener, Com
if (calculatedTotalInsulin > 0d || calculatedCarbs > 0d) {
String insulinText = calculatedTotalInsulin > 0d ? (DecimalFormatter.to2Decimal(calculatedTotalInsulin) + "U") : "";
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);
} else {
// 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
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);
}

View file

@ -147,12 +147,18 @@ public class OverviewFragment extends Fragment implements View.OnClickListener,
TextView sage;
TextView pbage;
CheckBox showPredictionView;
CheckBox showBasalsView;
CheckBox showIobView;
CheckBox showCobView;
CheckBox showDeviationsView;
CheckBox showRatiosView;
TextView showPredictionLabel;
CheckBox showPredictionCheckbox;
TextView showBasalsLabel;
CheckBox showBasalsCheckbox;
TextView showIobLabel;
CheckBox showIobCheckbox;
TextView showCobLabel;
CheckBox showCobCheckbox;
TextView showDeviationsLabel;
CheckBox showDeviationsCheckbox;
TextView showRatiosLabel;
CheckBox showRatiosCheckbox;
RecyclerView notificationsView;
LinearLayoutManager llm;
@ -264,24 +270,37 @@ public class OverviewFragment extends Fragment implements View.OnClickListener,
acceptTempLayout = (LinearLayout) view.findViewById(R.id.overview_accepttemplayout);
showPredictionView = (CheckBox) view.findViewById(R.id.overview_showprediction);
showBasalsView = (CheckBox) view.findViewById(R.id.overview_showbasals);
showIobView = (CheckBox) view.findViewById(R.id.overview_showiob);
showCobView = (CheckBox) view.findViewById(R.id.overview_showcob);
showDeviationsView = (CheckBox) view.findViewById(R.id.overview_showdeviations);
showRatiosView = (CheckBox) view.findViewById(R.id.overview_showratios);
showPredictionView.setChecked(SP.getBoolean("showprediction", false));
showBasalsView.setChecked(SP.getBoolean("showbasals", true));
showIobView.setChecked(SP.getBoolean("showiob", false));
showCobView.setChecked(SP.getBoolean("showcob", false));
showDeviationsView.setChecked(SP.getBoolean("showdeviations", false));
showRatiosView.setChecked(SP.getBoolean("showratios", false));
showPredictionView.setOnCheckedChangeListener(this);
showBasalsView.setOnCheckedChangeListener(this);
showIobView.setOnCheckedChangeListener(this);
showCobView.setOnCheckedChangeListener(this);
showDeviationsView.setOnCheckedChangeListener(this);
showRatiosView.setOnCheckedChangeListener(this);
showPredictionCheckbox = (CheckBox) view.findViewById(R.id.overview_showprediction);
showBasalsCheckbox = (CheckBox) view.findViewById(R.id.overview_showbasals);
showIobCheckbox = (CheckBox) view.findViewById(R.id.overview_showiob);
showCobCheckbox = (CheckBox) view.findViewById(R.id.overview_showcob);
showDeviationsCheckbox = (CheckBox) view.findViewById(R.id.overview_showdeviations);
showRatiosCheckbox = (CheckBox) view.findViewById(R.id.overview_showratios);
showPredictionCheckbox.setChecked(SP.getBoolean("showprediction", false));
showBasalsCheckbox.setChecked(SP.getBoolean("showbasals", true));
showIobCheckbox.setChecked(SP.getBoolean("showiob", false));
showCobCheckbox.setChecked(SP.getBoolean("showcob", false));
showDeviationsCheckbox.setChecked(SP.getBoolean("showdeviations", false));
showRatiosCheckbox.setChecked(SP.getBoolean("showratios", false));
showPredictionCheckbox.setOnCheckedChangeListener(this);
showBasalsCheckbox.setOnCheckedChangeListener(this);
showIobCheckbox.setOnCheckedChangeListener(this);
showCobCheckbox.setOnCheckedChangeListener(this);
showDeviationsCheckbox.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.setHasFixedSize(true);
@ -374,24 +393,24 @@ public class OverviewFragment extends Fragment implements View.OnClickListener,
case R.id.overview_showiob:
break;
case R.id.overview_showcob:
showDeviationsView.setOnCheckedChangeListener(null);
showDeviationsView.setChecked(false);
showDeviationsView.setOnCheckedChangeListener(this);
showDeviationsCheckbox.setOnCheckedChangeListener(null);
showDeviationsCheckbox.setChecked(false);
showDeviationsCheckbox.setOnCheckedChangeListener(this);
break;
case R.id.overview_showdeviations:
showCobView.setOnCheckedChangeListener(null);
showCobView.setChecked(false);
showCobView.setOnCheckedChangeListener(this);
showCobCheckbox.setOnCheckedChangeListener(null);
showCobCheckbox.setChecked(false);
showCobCheckbox.setOnCheckedChangeListener(this);
break;
case R.id.overview_showratios:
break;
}
SP.putBoolean("showiob", showIobView.isChecked());
SP.putBoolean("showprediction", showPredictionView.isChecked());
SP.putBoolean("showbasals", showBasalsView.isChecked());
SP.putBoolean("showcob", showCobView.isChecked());
SP.putBoolean("showdeviations", showDeviationsView.isChecked());
SP.putBoolean("showratios", showRatiosView.isChecked());
SP.putBoolean("showiob", showIobCheckbox.isChecked());
SP.putBoolean("showprediction", showPredictionCheckbox.isChecked());
SP.putBoolean("showbasals", showBasalsCheckbox.isChecked());
SP.putBoolean("showcob", showCobCheckbox.isChecked());
SP.putBoolean("showdeviations", showDeviationsCheckbox.isChecked());
SP.putBoolean("showratios", showRatiosCheckbox.isChecked());
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);
return true;
} 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);
return true;
} 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);
return true;
} 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);
return true;
} 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())
ConfigBuilderPlugin.getCommandQueue().readStatus("RefreshClicked", null);
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;
if (predictionsAvailable) {
showPredictionView.setVisibility(View.VISIBLE);
getActivity().findViewById(R.id.overview_showprediction_label).setVisibility(View.VISIBLE);
showPredictionCheckbox.setVisibility(View.VISIBLE);
showPredictionLabel.setVisibility(View.VISIBLE);
} else {
showPredictionView.setVisibility(View.GONE);
getActivity().findViewById(R.id.overview_showprediction_label).setVisibility(View.GONE);
showPredictionCheckbox.setVisibility(View.GONE);
showPredictionLabel.setVisibility(View.GONE);
}
// pump status from ns
@ -1265,7 +1342,7 @@ public class OverviewFragment extends Fragment implements View.OnClickListener,
final long toTime;
final long fromTime;
final long endTime;
if (predictionsAvailable && showPredictionView.isChecked()) {
if (predictionsAvailable && showPredictionCheckbox.isChecked()) {
int predHours = (int) (Math.ceil(finalLastRun.constraintsProcessed.getLatestPredictionsTime() - System.currentTimeMillis()) / (60 * 60 * 1000));
predHours = Math.min(2, predHours);
predHours = Math.max(0, predHours);
@ -1292,7 +1369,7 @@ public class OverviewFragment extends Fragment implements View.OnClickListener,
graphData.addInRangeArea(fromTime, endTime, lowLine, highLine);
// **** BG ****
if (predictionsAvailable && showPredictionView.isChecked())
if (predictionsAvailable && showPredictionCheckbox.isChecked())
graphData.addBgReadings(fromTime, toTime, lowLine, highLine, finalLastRun.constraintsProcessed);
else
graphData.addBgReadings(fromTime, toTime, lowLine, highLine, null);
@ -1304,7 +1381,7 @@ public class OverviewFragment extends Fragment implements View.OnClickListener,
graphData.addTreatments(fromTime, endTime);
// add basal data
if (pump.getPumpDescription().isTempBasalCapable && showBasalsView.isChecked()) {
if (pump.getPumpDescription().isTempBasalCapable && showBasalsCheckbox.isChecked()) {
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 useDSForScale = false;
if (showIobView.isChecked()) {
if (showIobCheckbox.isChecked()) {
useIobForScale = true;
} else if (showCobView.isChecked()) {
} else if (showCobCheckbox.isChecked()) {
useCobForScale = true;
} else if (showDeviationsView.isChecked()) {
} else if (showDeviationsCheckbox.isChecked()) {
useDevForScale = true;
} else if (showRatiosView.isChecked()) {
} else if (showRatiosCheckbox.isChecked()) {
useRatioForScale = true;
} else if (Config.displayDeviationSlope) {
useDSForScale = true;
}
if (showIobView.isChecked())
if (showIobCheckbox.isChecked())
secondGraphData.addIob(fromTime, now, useIobForScale, 1d);
if (showCobView.isChecked())
if (showCobCheckbox.isChecked())
secondGraphData.addCob(fromTime, now, useCobForScale, useCobForScale ? 1d : 0.5d);
if (showDeviationsView.isChecked())
if (showDeviationsCheckbox.isChecked())
secondGraphData.addDeviations(fromTime, now, useDevForScale, 1d);
if (showRatiosView.isChecked())
if (showRatiosCheckbox.isChecked())
secondGraphData.addRatio(fromTime, now, useRatioForScale, 1d);
if (Config.displayDeviationSlope)
secondGraphData.addDeviationSlope(fromTime, now, useDSForScale, 1d);
@ -1356,7 +1433,7 @@ public class OverviewFragment extends Fragment implements View.OnClickListener,
activity.runOnUiThread(new Runnable() {
@Override
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);
} else {
iobGraph.setVisibility(View.GONE);

View file

@ -250,7 +250,7 @@ public class GraphData {
}
// 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++) {
DataPointWithLabelInterface t = careportalEvents.get(tx);

View file

@ -136,9 +136,6 @@ public class PointsWithLabelGraphSeries<E extends DataPointWithLabelInterface> e
Iterator<E> values = getValues(minX, maxX);
// draw background
double lastEndY = 0;
double lastEndX = 0;
// draw data
double diffY = maxY - minY;
@ -149,9 +146,8 @@ public class PointsWithLabelGraphSeries<E extends DataPointWithLabelInterface> e
float graphLeft = graphView.getGraphContentLeft();
float graphTop = graphView.getGraphContentTop();
lastEndY = 0;
lastEndX = 0;
float firstX = 0;
float scaleX = (float) (graphWidth / diffX);
int i=0;
while (values.hasNext()) {
E value = values.next();
@ -166,9 +162,6 @@ public class PointsWithLabelGraphSeries<E extends DataPointWithLabelInterface> e
double ratX = valX / diffX;
double x = graphWidth * ratX;
double orgX = x;
double orgY = y;
// overdraw
boolean overdraw = false;
if (x > graphWidth) { // end right
@ -180,6 +173,14 @@ public class PointsWithLabelGraphSeries<E extends DataPointWithLabelInterface> e
if (y > graphHeight) { // end top
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 */
if(x < 0) {
overdraw = true;
@ -190,8 +191,8 @@ public class PointsWithLabelGraphSeries<E extends DataPointWithLabelInterface> e
registerDataPoint(endX, endY, value);
float xpluslength = 0;
if (value.getDuration() > 0) {
xpluslength = endX + Math.min((float) (value.getDuration() * graphWidth / diffX), graphLeft + graphWidth);
if (duration > 0) {
xpluslength = Math.min(endWithDuration, graphLeft + graphWidth);
}
// draw data point

View file

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

View file

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

View file

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

View file

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

View file

@ -9,6 +9,7 @@ import java.util.Calendar;
import java.util.GregorianCalendar;
import info.nightscout.androidaps.Config;
import info.nightscout.utils.DateUtil;
public class DanaRS_Packet_APS_Set_Event_History extends DanaRS_Packet {
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.param1 = param1;
this.param2 = param2;
if (Config.logDanaMessageDetail)
log.debug("Set history entry: " + DateUtil.dateAndTimeString(time) + " type: " + type + " param1: " + param1 + " param2: " + param2);
}
@Override

View file

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

View file

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

View file

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

View file

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

View file

@ -217,7 +217,7 @@ public class SensitivityWeightedAveragePlugin implements PluginBase, Sensitivity
}
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();
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.ConfigBuilder.ConfigBuilderPlugin;
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.TreatmentsProfileSwitchFragment;
import info.nightscout.androidaps.plugins.Treatments.fragments.TreatmentsTempTargetFragment;
@ -33,6 +34,7 @@ public class TreatmentsFragment extends SubscriberFragment implements View.OnCli
TextView tempBasalsTab;
TextView tempTargetTab;
TextView profileSwitchTab;
TextView careportalTab;
@Override
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);
tempTargetTab = (TextView) view.findViewById(R.id.treatments_temptargets);
profileSwitchTab = (TextView) view.findViewById(R.id.treatments_profileswitches);
careportalTab = (TextView) view.findViewById(R.id.treatments_careportal);
treatmentsTab.setOnClickListener(this);
extendedBolusesTab.setOnClickListener(this);
tempBasalsTab.setOnClickListener(this);
tempTargetTab.setOnClickListener(this);
profileSwitchTab.setOnClickListener(this);
careportalTab.setOnClickListener(this);
setFragment(new TreatmentsBolusFragment());
setBackgroundColorOnSelected(treatmentsTab);
@ -87,6 +91,10 @@ public class TreatmentsFragment extends SubscriberFragment implements View.OnCli
setFragment(new TreatmentsProfileSwitchFragment());
setBackgroundColorOnSelected(profileSwitchTab);
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));
tempTargetTab.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));
}

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

View file

@ -148,8 +148,6 @@ public class CommandQueue {
public static void independentConnect(String reason, Callback callback) {
CommandQueue tempCommandQueue = new CommandQueue();
tempCommandQueue.readStatus(reason, callback);
QueueThread tempThread = new QueueThread(tempCommandQueue);
tempThread.start();
}
// 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.plugins.ConfigBuilder.ConfigBuilderPlugin;
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.utils.SP;
@ -35,7 +37,7 @@ public class QueueThread extends Thread {
private PowerManager.WakeLock mWakeLock;
public QueueThread(CommandQueue queue) {
super(QueueThread.class.toString());
super();
this.queue = queue;
PowerManager powerManager = (PowerManager) MainApp.instance().getApplicationContext().getSystemService(Context.POWER_SERVICE);
@ -52,12 +54,6 @@ public class QueueThread extends Thread {
while (true) {
PumpInterface pump = ConfigBuilderPlugin.getActivePump();
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) {
MainApp.bus().post(new EventDismissBolusprogressIfRunning(null));
@ -74,19 +70,37 @@ public class QueueThread extends Thread {
//write time
SP.putLong(R.string.key_btwatchdog_lastbark, System.currentTimeMillis());
//toggle BT
pump.stopConnecting();
pump.disconnect("watchdog");
SystemClock.sleep(1000);
BluetoothAdapter mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
mBluetoothAdapter.disable();
SystemClock.sleep(1000);
mBluetoothAdapter.enable();
SystemClock.sleep(1000);
//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();
pump.connect("watchdog");
} else {
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;
}
}
if (pump.isConnecting()) {
log.debug("QUEUE: connecting " + secondsElapsed);
MainApp.bus().post(new EventPumpStatusChanged(EventPumpStatusChanged.CONNECTING, (int) secondsElapsed));
SystemClock.sleep(1000);
continue;
}
if (!pump.isConnected()) {
log.debug("QUEUE: connect");
MainApp.bus().post(new EventPumpStatusChanged(EventPumpStatusChanged.CONNECTING, (int) secondsElapsed));

View file

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

View file

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

View file

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

View file

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

View file

@ -231,8 +231,8 @@
<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 name="smscommunicator_bolusfailed">Bolo falló</string>
<string formatted="false" name="bolusdelivered">Bolo% .2fU entregado con éxito</string>
<string formatted="false" name="bolusdelivering">Entregando% .2fU</string>
<string formatted="false" name="bolusdelivered">Bolo %.2fU entregado con éxito</string>
<string formatted="false" name="bolusdelivering">Entregando %.2fU</string>
<string name="smscommunicator_remotebolusnotallowed">Bolo remoto no permitido</string>
<string name="glucosetype_finger">Dedo</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_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="extendedbolusdeliveryerror">Extended bolus delivery error</string>
</resources>

View file

@ -1,5 +1,6 @@
<?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
android:key="others"
android:title="@string/othersettings_title">
@ -76,12 +77,16 @@
android:defaultValue="true"
android:key="@string/key_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:dependency="@string/key_enable_pump_unreachable_alert"
android:inputType="number"
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>
<SwitchPreference
android:defaultValue="false"

View file

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