diff --git a/app/src/main/java/info/nightscout/androidaps/MainApp.java b/app/src/main/java/info/nightscout/androidaps/MainApp.java index 1732e313a8..da11d69c61 100644 --- a/app/src/main/java/info/nightscout/androidaps/MainApp.java +++ b/app/src/main/java/info/nightscout/androidaps/MainApp.java @@ -47,7 +47,7 @@ import info.nightscout.androidaps.plugins.OpenAPSMA.OpenAPSMAPlugin; import info.nightscout.androidaps.plugins.Overview.OverviewPlugin; import info.nightscout.androidaps.plugins.Persistentnotification.PersistentNotificationPlugin; import info.nightscout.androidaps.plugins.ProfileCircadianPercentage.CircadianPercentageProfileFragment; -import info.nightscout.androidaps.plugins.ProfileLocal.LocalProfileFragment; +import info.nightscout.androidaps.plugins.ProfileLocal.LocalProfilePlugin; import info.nightscout.androidaps.plugins.ProfileNS.NSProfilePlugin; import info.nightscout.androidaps.plugins.ProfileSimple.SimpleProfilePlugin; import info.nightscout.androidaps.plugins.PumpCombo.ComboPlugin; @@ -138,7 +138,7 @@ public class MainApp extends Application { if (Config.APS) pluginsList.add(OpenAPSAMAPlugin.getPlugin()); pluginsList.add(NSProfilePlugin.getPlugin()); if (Config.OTHERPROFILES) pluginsList.add(SimpleProfilePlugin.getPlugin()); - if (Config.OTHERPROFILES) pluginsList.add(LocalProfileFragment.getPlugin()); + if (Config.OTHERPROFILES) pluginsList.add(LocalProfilePlugin.getPlugin()); if (Config.OTHERPROFILES) pluginsList.add(CircadianPercentageProfileFragment.getPlugin()); pluginsList.add(TreatmentsPlugin.getPlugin()); diff --git a/app/src/main/java/info/nightscout/androidaps/data/Profile.java b/app/src/main/java/info/nightscout/androidaps/data/Profile.java index db34f9d692..5235545362 100644 --- a/app/src/main/java/info/nightscout/androidaps/data/Profile.java +++ b/app/src/main/java/info/nightscout/androidaps/data/Profile.java @@ -20,9 +20,9 @@ import info.nightscout.androidaps.R; import info.nightscout.androidaps.interfaces.PumpDescription; import info.nightscout.androidaps.interfaces.PumpInterface; import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin; -import info.nightscout.androidaps.plugins.Overview.notifications.Notification; import info.nightscout.androidaps.plugins.Overview.events.EventDismissNotification; import info.nightscout.androidaps.plugins.Overview.events.EventNewNotification; +import info.nightscout.androidaps.plugins.Overview.notifications.Notification; import info.nightscout.utils.DateUtil; import info.nightscout.utils.DecimalFormatter; import info.nightscout.utils.ToastUtils; @@ -48,6 +48,9 @@ public class Profile { private int percentage = 100; private int timeshift = 0; + private boolean isValid = true; + private boolean isValidated = false; + public Profile(JSONObject json, String units) { this(json, 100, 0); if (this.units == null) { @@ -121,6 +124,8 @@ public class Profile { } catch (JSONException e) { log.error("Unhandled exception", e); ToastUtils.showToastInUiThread(MainApp.instance().getApplicationContext(), MainApp.gs(R.string.invalidprofile)); + isValid = false; + isValidated = true; } } @@ -174,10 +179,6 @@ public class Profile { } double value = o.getDouble("value") * multiplier; sparse.put(tas, value); - if (value == 0) { - Notification notification = new Notification(Notification.ZERO_VALUE_IN_PROFILE, MainApp.sResources.getString(R.string.zerovalueinprofile), Notification.URGENT); - MainApp.bus().post(new EventNewNotification(notification)); - } } catch (JSONException e) { log.error("Unhandled exception", e); log.error(json.toString()); @@ -192,6 +193,71 @@ public class Profile { return sparse; } + public synchronized boolean isValid(String from) { + if (!isValid) + return false; + if (!isValidated) { + if (basal_v == null) + basal_v = convertToSparseArray(basal); + validate(basal_v); + if (isf_v == null) + isf_v = convertToSparseArray(isf); + validate(isf_v); + if (ic_v == null) + ic_v = convertToSparseArray(ic); + validate(ic_v); + if (targetLow_v == null) + targetLow_v = convertToSparseArray(targetLow); + validate(targetLow_v); + if (targetHigh_v == null) + targetHigh_v = convertToSparseArray(targetHigh); + validate(targetHigh_v); + isValidated = true; + } + + if (isValid) { + // Check for hours alignment + for (int index = 0; index < basal_v.size(); index++) { + long secondsFromMidnight = basal_v.keyAt(index); + if (secondsFromMidnight % 3600 != 0) { + Notification notification = new Notification(Notification.BASAL_PROFILE_NOT_ALIGNED_TO_HOURS, String.format(MainApp.gs(R.string.basalprofilenotaligned), from), Notification.NORMAL); + MainApp.bus().post(new EventNewNotification(notification)); + } + } + + // Check for minimal basal value + PumpInterface pump = ConfigBuilderPlugin.getActivePump(); + if (pump != null) { + PumpDescription description = pump.getPumpDescription(); + for (int i = 0; i < basal_v.size(); i++) { + if (basal_v.valueAt(i) < description.basalMinimumRate) { + basal_v.setValueAt(i, description.basalMinimumRate); + MainApp.bus().post(new EventNewNotification(new Notification(Notification.MINIMAL_BASAL_VALUE_REPLACED, String.format(MainApp.gs(R.string.minimalbasalvaluereplaced), from), Notification.NORMAL))); + } + } + } else { + // if pump not available (at start) + // do not store converted array + basal_v = null; + } + + } + return isValid; + } + + private void validate(LongSparseArray array) { + if (array.size() == 0) { + isValid = false; + return; + } + for (int index = 0; index < array.size(); index++) { + if (array.valueAt(index).equals(0d)) { + isValid = false; + return; + } + } + } + private Double getValueToTime(JSONArray array, Integer timeAsSeconds) { Double lastValue = null; @@ -338,35 +404,9 @@ public class Profile { return getBasal(secondsFromMidnight(time)); } - public Double getBasal(Integer timeAsSeconds) { + public synchronized Double getBasal(Integer timeAsSeconds) { if (basal_v == null) { basal_v = convertToSparseArray(basal); - for (int index = 0; index < basal_v.size(); index++) { - long secondsFromMidnight = basal_v.keyAt(index); - if (secondsFromMidnight % 3600 != 0) { - Notification notification = new Notification(Notification.BASAL_PROFILE_NOT_ALIGNED_TO_HOURS, MainApp.sResources.getString(R.string.basalprofilenotaligned), Notification.URGENT); - MainApp.bus().post(new EventNewNotification(notification)); - } - } - - // Check for minimal basal value - PumpInterface pump = ConfigBuilderPlugin.getActivePump(); - if (pump != null) { - PumpDescription description = pump.getPumpDescription(); - for (int i = 0; i < basal_v.size(); i++) { - if (basal_v.valueAt(i) < description.basalMinimumRate) { - basal_v.setValueAt(i, description.basalMinimumRate); - MainApp.bus().post(new EventNewNotification(new Notification(Notification.MINIMAL_BASAL_VALUE_REPLACED, MainApp.sResources.getString(R.string.minimalbasalvaluereplaced), Notification.NORMAL))); - } - } - return getValueToTime(basal_v, timeAsSeconds); - } else { - // if pump not available (at start) - // do not store converted array - Double value = getValueToTime(basal_v, timeAsSeconds); - basal_v = null; - return value; - } } return getValueToTime(basal_v, timeAsSeconds); } @@ -385,7 +425,7 @@ public class Profile { public Double value; } - public BasalValue[] getBasalValues() { + public synchronized BasalValue[] getBasalValues() { if (basal_v == null) basal_v = convertToSparseArray(basal); BasalValue[] ret = new BasalValue[basal_v.size()]; diff --git a/app/src/main/java/info/nightscout/androidaps/data/ProfileIntervals.java b/app/src/main/java/info/nightscout/androidaps/data/ProfileIntervals.java index 3633f1079e..0ea76ffb15 100644 --- a/app/src/main/java/info/nightscout/androidaps/data/ProfileIntervals.java +++ b/app/src/main/java/info/nightscout/androidaps/data/ProfileIntervals.java @@ -31,7 +31,8 @@ public class ProfileIntervals { public synchronized void add(List list) { for (T interval : list) { - rawData.put(interval.start(), interval); + if (interval.isValid()) + rawData.put(interval.start(), interval); } merge(); } @@ -62,7 +63,7 @@ public class ProfileIntervals { public synchronized List getReversedList() { List list = new ArrayList<>(); - for (int i = rawData.size() -1; i>=0; i--) + for (int i = rawData.size() - 1; i >= 0; i--) list.add(rawData.valueAt(i)); return list; } diff --git a/app/src/main/java/info/nightscout/androidaps/db/DatabaseHelper.java b/app/src/main/java/info/nightscout/androidaps/db/DatabaseHelper.java index e4e627d711..c74233bd9c 100644 --- a/app/src/main/java/info/nightscout/androidaps/db/DatabaseHelper.java +++ b/app/src/main/java/info/nightscout/androidaps/db/DatabaseHelper.java @@ -51,6 +51,8 @@ import info.nightscout.androidaps.plugins.Overview.events.EventNewNotification; import info.nightscout.androidaps.plugins.Overview.notifications.Notification; import info.nightscout.androidaps.plugins.PumpDanaR.activities.DanaRNSHistorySync; import info.nightscout.androidaps.plugins.PumpVirtual.VirtualPumpPlugin; +import info.nightscout.utils.DateUtil; +import info.nightscout.utils.NSUpload; import info.nightscout.utils.PercentageSplitter; public class DatabaseHelper extends OrmLiteSqliteOpenHelper { @@ -1720,10 +1722,10 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper { if (profile != null) { profileSwitch.profileJson = profile.getData().toString(); log.debug("Profile switch prefilled with JSON from local store"); + // Update data in NS + NSUpload.updateProfileSwitch(profileSwitch); } else { - Notification notification = new Notification(Notification.NO_LOCALE_PROFILE_FOUND, MainApp.sResources.getString(R.string.nolocaleprofilefound), Notification.URGENT); - MainApp.bus().post(new EventNewNotification(notification)); - log.debug("JSON for profile switch doesn't exist. Ignoring ..."); + log.debug("JSON for profile switch doesn't exist. Ignoring: " + trJson.toString()); return; } } diff --git a/app/src/main/java/info/nightscout/androidaps/db/ExtendedBolus.java b/app/src/main/java/info/nightscout/androidaps/db/ExtendedBolus.java index 0bd929030f..4232a2fc86 100644 --- a/app/src/main/java/info/nightscout/androidaps/db/ExtendedBolus.java +++ b/app/src/main/java/info/nightscout/androidaps/db/ExtendedBolus.java @@ -147,6 +147,11 @@ public class ExtendedBolus implements Interval, DataPointWithLabelInterface { return durationInMinutes == 0; } + @Override + public boolean isValid() { + return true; + } + // -------- Interval interface end --------- public String log() { diff --git a/app/src/main/java/info/nightscout/androidaps/db/ProfileSwitch.java b/app/src/main/java/info/nightscout/androidaps/db/ProfileSwitch.java index 7aea077e0a..dcce69639f 100644 --- a/app/src/main/java/info/nightscout/androidaps/db/ProfileSwitch.java +++ b/app/src/main/java/info/nightscout/androidaps/db/ProfileSwitch.java @@ -1,6 +1,7 @@ package info.nightscout.androidaps.db; import android.graphics.Color; +import android.support.annotation.Nullable; import com.j256.ormlite.field.DatabaseField; import com.j256.ormlite.table.DatabaseTable; @@ -12,10 +13,14 @@ import org.slf4j.LoggerFactory; import java.util.Objects; +import info.nightscout.androidaps.MainApp; +import info.nightscout.androidaps.R; import info.nightscout.androidaps.data.Profile; import info.nightscout.androidaps.interfaces.Interval; +import info.nightscout.androidaps.plugins.Overview.events.EventNewNotification; import info.nightscout.androidaps.plugins.Overview.graphExtensions.DataPointWithLabelInterface; import info.nightscout.androidaps.plugins.Overview.graphExtensions.PointsWithLabelGraphSeries; +import info.nightscout.androidaps.plugins.Overview.notifications.Notification; import info.nightscout.androidaps.plugins.ProfileLocal.LocalProfilePlugin; import info.nightscout.utils.DateUtil; import info.nightscout.utils.DecimalFormatter; @@ -56,12 +61,14 @@ public class ProfileSwitch implements Interval, DataPointWithLabelInterface { private Profile profile = null; + @Nullable public Profile getProfileObject() { if (profile == null) try { profile = new Profile(new JSONObject(profileJson), percentage, timeshift); - } catch (JSONException e) { + } catch (Exception e) { log.error("Unhandled exception", e); + log.error("Unhandled exception", profileJson); } return profile; } @@ -171,6 +178,20 @@ public class ProfileSwitch implements Interval, DataPointWithLabelInterface { return durationInMinutes == 0; } + @Override + public boolean isValid() { + + boolean isValid = getProfileObject() != null && getProfileObject().isValid(DateUtil.dateAndTimeString(date)); + if (!isValid) + createNotificationInvalidProfile(DateUtil.dateAndTimeString(date)); + return isValid; + } + + public void createNotificationInvalidProfile(String detail) { + Notification notification = new Notification(Notification.ZERO_VALUE_IN_PROFILE, String.format(MainApp.gs(R.string.zerovalueinprofile), detail), Notification.LOW, 5); + MainApp.bus().post(new EventNewNotification(notification)); + } + // -------- Interval interface end --------- // ----------------- DataPointInterface -------------------- diff --git a/app/src/main/java/info/nightscout/androidaps/db/TempTarget.java b/app/src/main/java/info/nightscout/androidaps/db/TempTarget.java index 3bbdcbc06c..c6d0ed18c4 100644 --- a/app/src/main/java/info/nightscout/androidaps/db/TempTarget.java +++ b/app/src/main/java/info/nightscout/androidaps/db/TempTarget.java @@ -123,6 +123,11 @@ public class TempTarget implements Interval { return durationInMinutes == 0; } + @Override + public boolean isValid() { + return true; + } + // -------- Interval interface end --------- public String lowValueToUnitsToString(String units) { diff --git a/app/src/main/java/info/nightscout/androidaps/db/TemporaryBasal.java b/app/src/main/java/info/nightscout/androidaps/db/TemporaryBasal.java index 3c8f95f5af..3feb9c4ad2 100644 --- a/app/src/main/java/info/nightscout/androidaps/db/TemporaryBasal.java +++ b/app/src/main/java/info/nightscout/androidaps/db/TemporaryBasal.java @@ -182,6 +182,11 @@ public class TemporaryBasal implements Interval { return durationInMinutes == 0; } + @Override + public boolean isValid() { + return true; + } + // -------- Interval interface end --------- public IobTotal iobCalc(long time) { diff --git a/app/src/main/java/info/nightscout/androidaps/interfaces/Interval.java b/app/src/main/java/info/nightscout/androidaps/interfaces/Interval.java index f3b4111642..6fac33cba4 100644 --- a/app/src/main/java/info/nightscout/androidaps/interfaces/Interval.java +++ b/app/src/main/java/info/nightscout/androidaps/interfaces/Interval.java @@ -21,4 +21,6 @@ public interface Interval { boolean isInProgress(); boolean isEndingEvent(); + + boolean isValid(); } \ No newline at end of file diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/ConfigBuilder/ConfigBuilderPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/ConfigBuilder/ConfigBuilderPlugin.java index 9cbb0bef4c..99ff546eac 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/ConfigBuilder/ConfigBuilderPlugin.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/ConfigBuilder/ConfigBuilderPlugin.java @@ -13,6 +13,7 @@ import java.util.ArrayList; import java.util.List; import info.nightscout.androidaps.Config; +import info.nightscout.androidaps.Constants; import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.R; import info.nightscout.androidaps.data.DetailedBolusInfo; @@ -758,14 +759,17 @@ public class ConfigBuilderPlugin implements PluginBase, ConstraintsInterface, Tr return "Default"; } + @Nullable public Profile getProfile() { return getProfile(System.currentTimeMillis()); } public String getProfileUnits() { - return getProfile().getUnits(); + Profile profile = getProfile(); + return profile != null ? profile.getUnits() : Constants.MGDL; } + @Nullable public Profile getProfile(long time) { if (activeTreatments == null) return null; //app not initialized diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/NSClientInternal/receivers/DBAccessReceiver.java b/app/src/main/java/info/nightscout/androidaps/plugins/NSClientInternal/receivers/DBAccessReceiver.java index 1ab93a53d1..c3cea9806a 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/NSClientInternal/receivers/DBAccessReceiver.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/NSClientInternal/receivers/DBAccessReceiver.java @@ -79,6 +79,11 @@ public class DBAccessReceiver extends BroadcastReceiver { DbRequest dbr = new DbRequest(action, collection, nsclientid.toString(), _id); UploadQueue.add(dbr); } + } else if (action.equals("dbUpdate")) { + if (shouldUpload()) { + DbRequest dbr = new DbRequest(action, collection, nsclientid.toString(), _id, data); + UploadQueue.add(dbr); + } } else { DbRequest dbr = new DbRequest(action, collection, nsclientid.toString(), data); // this is not used as mongo _id but only for searching in UploadQueue database diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Overview/notifications/Notification.java b/app/src/main/java/info/nightscout/androidaps/plugins/Overview/notifications/Notification.java index da2a6b04aa..34ad8ff7ba 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/Overview/notifications/Notification.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/Overview/notifications/Notification.java @@ -60,7 +60,6 @@ public class Notification { public static final int MINIMAL_BASAL_VALUE_REPLACED = 29; public static final int BASAL_PROFILE_NOT_ALIGNED_TO_HOURS = 30; public static final int ZERO_VALUE_IN_PROFILE = 31; - public static final int NO_LOCALE_PROFILE_FOUND = 32; public int id; public Date date; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/ProfileLocal/LocalProfileFragment.java b/app/src/main/java/info/nightscout/androidaps/plugins/ProfileLocal/LocalProfileFragment.java index ebd31e915f..364484aff8 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/ProfileLocal/LocalProfileFragment.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/ProfileLocal/LocalProfileFragment.java @@ -11,6 +11,7 @@ import android.view.View; import android.view.ViewGroup; import android.widget.Button; import android.widget.RadioButton; +import android.widget.TextView; import com.crashlytics.android.Crashlytics; import com.squareup.otto.Subscribe; @@ -22,6 +23,8 @@ import java.text.DecimalFormat; import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.R; +import info.nightscout.androidaps.data.Profile; +import info.nightscout.androidaps.data.ProfileStore; import info.nightscout.androidaps.events.EventInitializationChanged; import info.nightscout.androidaps.interfaces.PumpDescription; import info.nightscout.androidaps.plugins.Careportal.CareportalFragment; @@ -37,12 +40,6 @@ import info.nightscout.utils.TimeListEdit; public class LocalProfileFragment extends SubscriberFragment { private static Logger log = LoggerFactory.getLogger(LocalProfileFragment.class); - private static LocalProfilePlugin localProfilePlugin = new LocalProfilePlugin(); - - public static LocalProfilePlugin getPlugin() { - return localProfilePlugin; - } - NumberPicker diaView; RadioButton mgdlView; RadioButton mmolView; @@ -51,6 +48,7 @@ public class LocalProfileFragment extends SubscriberFragment { TimeListEdit basalView; TimeListEdit targetView; Button profileswitchButton; + TextView invalidProfile; @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, @@ -59,10 +57,11 @@ public class LocalProfileFragment extends SubscriberFragment { Runnable save = new Runnable() { @Override public void run() { - localProfilePlugin.storeSettings(); + LocalProfilePlugin.getPlugin().storeSettings(); if (basalView != null) { basalView.updateLabel(MainApp.sResources.getString(R.string.nsprofileview_basal_label) + ": " + getSumLabel()); } + updateGUI(); } }; @@ -80,8 +79,9 @@ public class LocalProfileFragment extends SubscriberFragment { @Override public void onTextChanged(CharSequence s, int start, int before, int count) { - localProfilePlugin.dia = SafeParse.stringToDouble(diaView.getText().toString()); - localProfilePlugin.storeSettings(); + LocalProfilePlugin.getPlugin().dia = SafeParse.stringToDouble(diaView.getText().toString()); + LocalProfilePlugin.getPlugin().storeSettings(); + updateGUI(); } }; @@ -89,40 +89,39 @@ public class LocalProfileFragment extends SubscriberFragment { View layout = inflater.inflate(R.layout.localprofile_fragment, container, false); diaView = (NumberPicker) layout.findViewById(R.id.localprofile_dia); - diaView.setParams(localProfilePlugin.dia, 2d, 48d, 0.1d, new DecimalFormat("0.0"), false, textWatch); + diaView.setParams(LocalProfilePlugin.getPlugin().dia, 2d, 48d, 0.1d, new DecimalFormat("0.0"), false, textWatch); mgdlView = (RadioButton) layout.findViewById(R.id.localprofile_mgdl); mmolView = (RadioButton) layout.findViewById(R.id.localprofile_mmol); - icView = new TimeListEdit(getContext(), layout, R.id.localprofile_ic, MainApp.sResources.getString(R.string.nsprofileview_ic_label) + ":", getPlugin().ic, null, 0.5, 50d, 0.1d, new DecimalFormat("0.0"), save); - isfView = new TimeListEdit(getContext(), layout, R.id.localprofile_isf, MainApp.sResources.getString(R.string.nsprofileview_isf_label) + ":", getPlugin().isf, null, 0.5, 500d, 0.1d, new DecimalFormat("0.0"), save); - basalView = new TimeListEdit(getContext(), layout, R.id.localprofile_basal, MainApp.sResources.getString(R.string.nsprofileview_basal_label) + ": " + getSumLabel(), getPlugin().basal, null, pumpDescription.basalMinimumRate, 10, 0.01d, new DecimalFormat("0.00"), save); - targetView = new TimeListEdit(getContext(), layout, R.id.localprofile_target, MainApp.sResources.getString(R.string.nsprofileview_target_label) + ":", getPlugin().targetLow, getPlugin().targetHigh, 3d, 200, 0.1d, new DecimalFormat("0.0"), save); + icView = new TimeListEdit(getContext(), layout, R.id.localprofile_ic, MainApp.sResources.getString(R.string.nsprofileview_ic_label) + ":", LocalProfilePlugin.getPlugin().ic, null, 0.5, 50d, 0.1d, new DecimalFormat("0.0"), save); + isfView = new TimeListEdit(getContext(), layout, R.id.localprofile_isf, MainApp.sResources.getString(R.string.nsprofileview_isf_label) + ":", LocalProfilePlugin.getPlugin().isf, null, 0.5, 500d, 0.1d, new DecimalFormat("0.0"), save); + basalView = new TimeListEdit(getContext(), layout, R.id.localprofile_basal, MainApp.sResources.getString(R.string.nsprofileview_basal_label) + ": " + getSumLabel(), LocalProfilePlugin.getPlugin().basal, null, pumpDescription.basalMinimumRate, 10, 0.01d, new DecimalFormat("0.00"), save); + targetView = new TimeListEdit(getContext(), layout, R.id.localprofile_target, MainApp.sResources.getString(R.string.nsprofileview_target_label) + ":", LocalProfilePlugin.getPlugin().targetLow, LocalProfilePlugin.getPlugin().targetHigh, 3d, 200, 0.1d, new DecimalFormat("0.0"), save); profileswitchButton = (Button) layout.findViewById(R.id.localprofile_profileswitch); + invalidProfile = (TextView) layout.findViewById(R.id.invalidprofile); if (!ConfigBuilderPlugin.getActivePump().getPumpDescription().isTempBasalCapable) { layout.findViewById(R.id.localprofile_basal).setVisibility(View.GONE); } - updateGUI(); - - mgdlView.setChecked(localProfilePlugin.mgdl); - mmolView.setChecked(localProfilePlugin.mmol); + mgdlView.setChecked(LocalProfilePlugin.getPlugin().mgdl); + mmolView.setChecked(LocalProfilePlugin.getPlugin().mmol); mgdlView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { - localProfilePlugin.mgdl = mgdlView.isChecked(); - localProfilePlugin.mmol = !localProfilePlugin.mgdl; - mmolView.setChecked(localProfilePlugin.mmol); - localProfilePlugin.storeSettings(); + LocalProfilePlugin.getPlugin().mgdl = mgdlView.isChecked(); + LocalProfilePlugin.getPlugin().mmol = !LocalProfilePlugin.getPlugin().mgdl; + mmolView.setChecked(LocalProfilePlugin.getPlugin().mmol); + LocalProfilePlugin.getPlugin().storeSettings(); } }); mmolView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { - localProfilePlugin.mmol = mmolView.isChecked(); - localProfilePlugin.mgdl = !localProfilePlugin.mmol; - mgdlView.setChecked(localProfilePlugin.mgdl); - localProfilePlugin.storeSettings(); + LocalProfilePlugin.getPlugin().mmol = mmolView.isChecked(); + LocalProfilePlugin.getPlugin().mgdl = !LocalProfilePlugin.getPlugin().mmol; + mgdlView.setChecked(LocalProfilePlugin.getPlugin().mgdl); + LocalProfilePlugin.getPlugin().storeSettings(); } }); @@ -138,7 +137,6 @@ public class LocalProfileFragment extends SubscriberFragment { }); - updateGUI(); return layout; } catch (Exception e) { log.error("Unhandled exception: ", e); @@ -150,7 +148,11 @@ public class LocalProfileFragment extends SubscriberFragment { @NonNull public String getSumLabel() { - return " ∑" + DecimalFormatter.to2Decimal(localProfilePlugin.getProfile().getDefaultProfile().baseBasalSum()) + "U"; + ProfileStore profile = LocalProfilePlugin.getPlugin().getProfile(); + if (profile != null) + return " ∑" + DecimalFormatter.to2Decimal(profile.getDefaultProfile().baseBasalSum()) + "U"; + else + return MainApp.gs(R.string.localprofile); } @Subscribe @@ -165,11 +167,16 @@ public class LocalProfileFragment extends SubscriberFragment { activity.runOnUiThread(new Runnable() { @Override public void run() { - if (!ConfigBuilderPlugin.getActivePump().isInitialized() || ConfigBuilderPlugin.getActivePump().isSuspended()) { + boolean isValid = LocalProfilePlugin.getPlugin().getProfile() != null && LocalProfilePlugin.getPlugin().getProfile().getDefaultProfile().isValid(MainApp.gs(R.string.localprofile)); + if (!ConfigBuilderPlugin.getActivePump().isInitialized() || ConfigBuilderPlugin.getActivePump().isSuspended() || !isValid) { profileswitchButton.setVisibility(View.GONE); } else { profileswitchButton.setVisibility(View.VISIBLE); } + if (isValid) + invalidProfile.setVisibility(View.GONE); + else + invalidProfile.setVisibility(View.VISIBLE); } }); } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/ProfileLocal/LocalProfilePlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/ProfileLocal/LocalProfilePlugin.java index b13945ae03..69272cc2ae 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/ProfileLocal/LocalProfilePlugin.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/ProfileLocal/LocalProfilePlugin.java @@ -13,9 +13,9 @@ import info.nightscout.androidaps.Config; import info.nightscout.androidaps.Constants; import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.R; +import info.nightscout.androidaps.data.ProfileStore; import info.nightscout.androidaps.interfaces.PluginBase; import info.nightscout.androidaps.interfaces.ProfileInterface; -import info.nightscout.androidaps.data.ProfileStore; import info.nightscout.utils.DecimalFormatter; import info.nightscout.utils.SP; @@ -26,6 +26,14 @@ public class LocalProfilePlugin implements PluginBase, ProfileInterface { public static final String LOCAL_PROFILE = "LocalProfile"; private static Logger log = LoggerFactory.getLogger(LocalProfilePlugin.class); + private static LocalProfilePlugin localProfilePlugin; + + public static LocalProfilePlugin getPlugin() { + if (localProfilePlugin == null) + localProfilePlugin = new LocalProfilePlugin(); + return localProfilePlugin; + } + private boolean fragmentEnabled = false; private boolean fragmentVisible = false; @@ -128,7 +136,7 @@ public class LocalProfilePlugin implements PluginBase, ProfileInterface { editor.apply(); createConvertedProfile(); if (Config.logPrefsChange) - log.debug("Storing settings: " + getProfile().getData().toString()); + log.debug("Storing settings: " + getRawProfile().getData().toString()); } public void loadSettings() { @@ -243,6 +251,14 @@ public class LocalProfilePlugin implements PluginBase, ProfileInterface { @Override public ProfileStore getProfile() { + if (convertedProfile == null) + createConvertedProfile(); + if (!convertedProfile.getDefaultProfile().isValid(MainApp.gs(R.string.localprofile))) + return null; + return convertedProfile; + } + + public ProfileStore getRawProfile() { if (convertedProfile == null) createConvertedProfile(); return convertedProfile; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/ProfileNS/NSProfileFragment.java b/app/src/main/java/info/nightscout/androidaps/plugins/ProfileNS/NSProfileFragment.java index 546a232ca4..c7d5d8edbf 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/ProfileNS/NSProfileFragment.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/ProfileNS/NSProfileFragment.java @@ -84,30 +84,36 @@ public class NSProfileFragment extends SubscriberFragment implements AdapterView } ProfileStore profileStore = NSProfilePlugin.getPlugin().getProfile(); - ArrayList profileList = profileStore.getProfileList(); - ArrayAdapter adapter = new ArrayAdapter<>(getContext(), - R.layout.spinner_centered, profileList); - profileSpinner.setAdapter(adapter); - // set selected to actual profile - for (int p = 0; p < profileList.size(); p++) { - if (profileList.get(p).equals(MainApp.getConfigBuilder().getProfileName())) - profileSpinner.setSelection(p); + if (profileStore != null) { + ArrayList profileList = profileStore.getProfileList(); + ArrayAdapter adapter = new ArrayAdapter<>(getContext(), + R.layout.spinner_centered, profileList); + profileSpinner.setAdapter(adapter); + // set selected to actual profile + for (int p = 0; p < profileList.size(); p++) { + if (profileList.get(p).equals(MainApp.getConfigBuilder().getProfileName())) + profileSpinner.setSelection(p); + } } - } @Override public void onItemSelected(AdapterView parent, View view, int position, long id) { String name = parent.getItemAtPosition(position).toString(); - Profile profile = NSProfilePlugin.getPlugin().getProfile().getSpecificProfile(name); - units.setText(profile.getUnits()); - dia.setText(DecimalFormatter.to2Decimal(profile.getDia()) + " h"); - activeProfile.setText(name); - ic.setText(profile.getIcList()); - isf.setText(profile.getIsfList()); - basal.setText(profile.getBasalList()); - target.setText(profile.getTargetList()); + ProfileStore store = NSProfilePlugin.getPlugin().getProfile(); + if (store != null) { + Profile profile = store.getSpecificProfile(name); + if (profile != null) { + units.setText(profile.getUnits()); + dia.setText(DecimalFormatter.to2Decimal(profile.getDia()) + " h"); + activeProfile.setText(name); + ic.setText(profile.getIcList()); + isf.setText(profile.getIsfList()); + basal.setText(profile.getBasalList()); + target.setText(profile.getTargetList()); + } + } } @Override diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/ProfileSimple/SimpleProfileFragment.java b/app/src/main/java/info/nightscout/androidaps/plugins/ProfileSimple/SimpleProfileFragment.java index 47080e26db..9a0b64f6d1 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/ProfileSimple/SimpleProfileFragment.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/ProfileSimple/SimpleProfileFragment.java @@ -11,6 +11,7 @@ import android.view.ViewGroup; import android.widget.Button; import android.widget.EditText; import android.widget.RadioButton; +import android.widget.TextView; import com.crashlytics.android.Crashlytics; import com.squareup.otto.Subscribe; @@ -18,6 +19,7 @@ import com.squareup.otto.Subscribe; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.R; import info.nightscout.androidaps.events.EventInitializationChanged; import info.nightscout.androidaps.plugins.Careportal.CareportalFragment; @@ -39,6 +41,7 @@ public class SimpleProfileFragment extends SubscriberFragment { EditText targetlowView; EditText targethighView; Button profileswitchButton; + TextView invalidProfile; @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, @@ -54,14 +57,13 @@ public class SimpleProfileFragment extends SubscriberFragment { targetlowView = (EditText) layout.findViewById(R.id.simpleprofile_targetlow); targethighView = (EditText) layout.findViewById(R.id.simpleprofile_targethigh); profileswitchButton = (Button) layout.findViewById(R.id.simpleprofile_profileswitch); + invalidProfile = (TextView) layout.findViewById(R.id.invalidprofile); if (!ConfigBuilderPlugin.getActivePump().getPumpDescription().isTempBasalCapable) { layout.findViewById(R.id.simpleprofile_basalrate).setVisibility(View.GONE); layout.findViewById(R.id.simpleprofile_basalrate_label).setVisibility(View.GONE); } - updateGUI(); - mgdlView.setChecked(SimpleProfilePlugin.getPlugin().mgdl); mmolView.setChecked(SimpleProfilePlugin.getPlugin().mmol); diaView.setText(SimpleProfilePlugin.getPlugin().dia.toString()); @@ -122,6 +124,7 @@ public class SimpleProfileFragment extends SubscriberFragment { SimpleProfilePlugin.getPlugin().targetLow = SafeParse.stringToDouble(targetlowView.getText().toString()); SimpleProfilePlugin.getPlugin().targetHigh = SafeParse.stringToDouble(targethighView.getText().toString()); SimpleProfilePlugin.getPlugin().storeSettings(); + updateGUI(); } }; @@ -132,8 +135,6 @@ public class SimpleProfileFragment extends SubscriberFragment { targetlowView.addTextChangedListener(textWatch); targethighView.addTextChangedListener(textWatch); - updateGUI(); - return layout; } catch (Exception e) { Crashlytics.logException(e); @@ -154,11 +155,16 @@ public class SimpleProfileFragment extends SubscriberFragment { activity.runOnUiThread(new Runnable() { @Override public void run() { - if (!ConfigBuilderPlugin.getActivePump().isInitialized() || ConfigBuilderPlugin.getActivePump().isSuspended()) { + boolean isValid = SimpleProfilePlugin.getPlugin().getProfile() != null && SimpleProfilePlugin.getPlugin().getProfile().getDefaultProfile().isValid(MainApp.gs(R.string.simpleprofile)); + if (!ConfigBuilderPlugin.getActivePump().isInitialized() || ConfigBuilderPlugin.getActivePump().isSuspended() || !isValid) { profileswitchButton.setVisibility(View.GONE); } else { profileswitchButton.setVisibility(View.VISIBLE); } + if (isValid) + invalidProfile.setVisibility(View.GONE); + else + invalidProfile.setVisibility(View.VISIBLE); } }); } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/ProfileSimple/SimpleProfilePlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/ProfileSimple/SimpleProfilePlugin.java index fbc9cf6b4c..b538a28512 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/ProfileSimple/SimpleProfilePlugin.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/ProfileSimple/SimpleProfilePlugin.java @@ -132,6 +132,8 @@ public class SimpleProfilePlugin implements PluginBase, ProfileInterface { editor.apply(); createConvertedProfile(); + if (Config.logPrefsChange) + log.debug("Storing settings: " + getRawProfile().getData().toString()); } private void loadSettings() { @@ -141,11 +143,11 @@ public class SimpleProfilePlugin implements PluginBase, ProfileInterface { mgdl = SP.getBoolean("SimpleProfile" + "mgdl", true); mmol = SP.getBoolean("SimpleProfile" + "mmol", false); dia = SP.getDouble("SimpleProfile" + "dia", Constants.defaultDIA); - ic = SP.getDouble("SimpleProfile" + "ic", 20d); - isf = SP.getDouble("SimpleProfile" + "isf", 200d); - basal = SP.getDouble("SimpleProfile" + "basal", 1d); - targetLow = SP.getDouble("SimpleProfile" + "targetlow", 80d); - targetHigh = SP.getDouble("SimpleProfile" + "targethigh", 120d); + ic = SP.getDouble("SimpleProfile" + "ic", 0d); + isf = SP.getDouble("SimpleProfile" + "isf", 0d); + basal = SP.getDouble("SimpleProfile" + "basal", 0d); + targetLow = SP.getDouble("SimpleProfile" + "targetlow", 0d); + targetHigh = SP.getDouble("SimpleProfile" + "targethigh", 0d); } /* @@ -210,6 +212,14 @@ public class SimpleProfilePlugin implements PluginBase, ProfileInterface { @Override public ProfileStore getProfile() { + if (convertedProfile == null) + createConvertedProfile(); + if (!convertedProfile.getDefaultProfile().isValid(MainApp.gs(R.string.simpleprofile))) + return null; + return convertedProfile; + } + + public ProfileStore getRawProfile() { if (convertedProfile == null) createConvertedProfile(); return convertedProfile; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Treatments/fragments/TreatmentsProfileSwitchFragment.java b/app/src/main/java/info/nightscout/androidaps/plugins/Treatments/fragments/TreatmentsProfileSwitchFragment.java index 591a8a6964..21cf5e27d9 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/Treatments/fragments/TreatmentsProfileSwitchFragment.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/Treatments/fragments/TreatmentsProfileSwitchFragment.java @@ -83,6 +83,7 @@ public class TreatmentsProfileSwitchFragment extends SubscriberFragment implemen holder.remove.setTag(profileSwitch); holder.name.setTag(profileSwitch); holder.date.setTag(profileSwitch); + holder.invalid.setVisibility(profileSwitch.isValid() ? View.GONE : View.VISIBLE); } @@ -104,6 +105,7 @@ public class TreatmentsProfileSwitchFragment extends SubscriberFragment implemen TextView remove; TextView ph; TextView ns; + TextView invalid; ProfileSwitchViewHolder(View itemView) { super(itemView); @@ -113,6 +115,7 @@ public class TreatmentsProfileSwitchFragment extends SubscriberFragment implemen name = (TextView) itemView.findViewById(R.id.profileswitch_name); ph = (TextView) itemView.findViewById(R.id.pump_sign); ns = (TextView) itemView.findViewById(R.id.ns_sign); + invalid = (TextView) itemView.findViewById(R.id.invalid_sign); remove = (TextView) itemView.findViewById(R.id.profileswitch_remove); remove.setOnClickListener(this); remove.setPaintFlags(remove.getPaintFlags() | Paint.UNDERLINE_TEXT_FLAG); diff --git a/app/src/main/java/info/nightscout/utils/NSUpload.java b/app/src/main/java/info/nightscout/utils/NSUpload.java index cee8e6e9b5..2ec3a57dd6 100644 --- a/app/src/main/java/info/nightscout/utils/NSUpload.java +++ b/app/src/main/java/info/nightscout/utils/NSUpload.java @@ -296,6 +296,39 @@ public class NSUpload { } } + public static void updateProfileSwitch(ProfileSwitch profileSwitch) { + try { + JSONObject data = new JSONObject(); + data.put("eventType", CareportalEvent.PROFILESWITCH); + data.put("duration", profileSwitch.durationInMinutes); + data.put("profile", profileSwitch.getCustomizedName()); + data.put("profileJson", profileSwitch.profileJson); + data.put("profilePlugin", profileSwitch.profilePlugin); + if (profileSwitch.isCPP) { + data.put("CircadianPercentageProfile", true); + data.put("timeshift", profileSwitch.timeshift); + data.put("percentage", profileSwitch.percentage); + } + data.put("created_at", DateUtil.toISOString(profileSwitch.date)); + data.put("enteredBy", MainApp.instance().getString(R.string.app_name)); + if (profileSwitch._id != null) { + Context context = MainApp.instance().getApplicationContext(); + Bundle bundle = new Bundle(); + bundle.putString("action", "dbUpdate"); + bundle.putString("collection", "treatments"); + bundle.putString("data", data.toString()); + bundle.putString("_id", profileSwitch._id); + Intent intent = new Intent(Intents.ACTION_DATABASE); + intent.putExtras(bundle); + intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES); + context.sendBroadcast(intent); + DbLogger.dbAdd(intent, data.toString()); + } + } catch (JSONException e) { + log.error("Unhandled exception", e); + } + } + public static void uploadCareportalEntryToNS(JSONObject data) { try { if (data.has("preBolus") && data.has("carbs")) { diff --git a/app/src/main/res/layout/localprofile_fragment.xml b/app/src/main/res/layout/localprofile_fragment.xml index e64f7a14a1..4b61e0235d 100644 --- a/app/src/main/res/layout/localprofile_fragment.xml +++ b/app/src/main/res/layout/localprofile_fragment.xml @@ -13,6 +13,16 @@ android:layout_height="wrap_content" android:orientation="vertical"> + + + + + + Bitte starte dein Telefon neu oder starte AndroidAPS in den System-Einstellungen neu. Andernfalls wird AndroidAPS nicht protokolliert (wichtig zum Nachverfolgen und Verifizieren, dass der Algorithmus korrekt funktioniert) TBR %.1f IE (%s, %s) - Nutze System-Benachrichtigungen für Alarme Ein gleich großer Bolus wurde in der letzten Minute angefordert. Dies ist nicht zulässig, um ungewollte Doppelboli zu verhindern und vor eventuellen Bugs zu schützen. Historie wird gelesen Basalratenprofil wird aktualisiert diff --git a/app/src/main/res/values-nl/strings.xml b/app/src/main/res/values-nl/strings.xml index 4c553da786..699e846127 100644 --- a/app/src/main/res/values-nl/strings.xml +++ b/app/src/main/res/values-nl/strings.xml @@ -685,7 +685,6 @@ estopt Bolus toediening wordt Vet Bolus toediening gestopt - Gebruik systeem notificaties voor waarschuwingen Toon gedetaillieerde delta Niet ondersteune pomp firmware DexcomG5 App (aangepast) @@ -733,13 +732,11 @@ ]]> ]]> AndroidAPS - Nul waarde in basaal profiel BG beschikbaar op gekozen bron Enkel positief Enkel negatief Maximum IOB juist ingesteld Trend berekening - Profiel wissel ontvangen via NS maar dit profiel bestaat niet op gsm "Bolus in pomp programmeren " Vernieuw Status @@ -767,7 +764,7 @@ Gestopt door de gebruiker Actief Insuline ampul is bijna leeg - Pomp is in storing, controleer op de pomp + Pomp is in storing, controleer op de pomp: E%d %s Bolus (%.1f E) Minimum: %3.1f E Gemiddelde: %3.1f E diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 27d56f524e..f0d9e42c40 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -297,6 +297,8 @@ Pump is busy Delivered Stopped + Bolus stopped + Stopping bolus Occlusion Stop STOP PRESSED @@ -809,9 +811,8 @@ Closed mode enabled Maximal IOB set properly BG available from selected source - Basal values not aligned to hours - Zero value in profile - Received profile switch from NS but profile doesn\'t exist localy + Basal values not aligned to hours: %s + Invalid profile: %s Programming pump for bolusing Refresh TDDS