diff --git a/app/src/main/java/info/nightscout/androidaps/MainApp.java b/app/src/main/java/info/nightscout/androidaps/MainApp.java index 13ab45c10e..e09c90fab8 100644 --- a/app/src/main/java/info/nightscout/androidaps/MainApp.java +++ b/app/src/main/java/info/nightscout/androidaps/MainApp.java @@ -39,6 +39,7 @@ import info.nightscout.androidaps.plugins.SourceMM640g.SourceMM640gFragment; import info.nightscout.androidaps.plugins.SourceNSClient.SourceNSClientFragment; import info.nightscout.androidaps.plugins.SourceXdrip.SourceXdripFragment; import info.nightscout.androidaps.plugins.TempBasals.TempBasalsFragment; +import info.nightscout.androidaps.plugins.TempTargetRange.TempTargetRangeFragment; import info.nightscout.androidaps.plugins.Treatments.TreatmentsFragment; import info.nightscout.androidaps.plugins.VirtualPump.VirtualPumpFragment; import info.nightscout.androidaps.plugins.Wear.WearFragment; @@ -89,6 +90,7 @@ public class MainApp extends Application { pluginsList.add(SimpleProfileFragment.getPlugin()); pluginsList.add(LocalProfileFragment.getPlugin()); pluginsList.add(CircadianPercentageProfileFragment.getPlugin()); + pluginsList.add(TempTargetRangeFragment.getPlugin()); pluginsList.add(TreatmentsFragment.getPlugin()); pluginsList.add(TempBasalsFragment.getPlugin()); pluginsList.add(SafetyFragment.getPlugin()); diff --git a/app/src/main/java/info/nightscout/androidaps/Services/DataService.java b/app/src/main/java/info/nightscout/androidaps/Services/DataService.java index 0d809bb6d9..1c590c2dac 100644 --- a/app/src/main/java/info/nightscout/androidaps/Services/DataService.java +++ b/app/src/main/java/info/nightscout/androidaps/Services/DataService.java @@ -29,6 +29,7 @@ import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.R; import info.nightscout.androidaps.db.BgReading; import info.nightscout.androidaps.db.DanaRHistoryRecord; +import info.nightscout.androidaps.db.TempTarget; import info.nightscout.androidaps.db.Treatment; import info.nightscout.androidaps.events.EventNewBG; import info.nightscout.androidaps.events.EventNewBasalProfile; @@ -39,12 +40,16 @@ import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin; import info.nightscout.androidaps.plugins.DanaR.History.DanaRNSHistorySync; import info.nightscout.androidaps.plugins.NSProfile.NSProfilePlugin; import info.nightscout.androidaps.plugins.Objectives.ObjectivesPlugin; +import info.nightscout.androidaps.plugins.Overview.Notification; 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.SmsCommunicator.SmsCommunicatorPlugin; import info.nightscout.androidaps.plugins.SmsCommunicator.events.EventNewSMS; import info.nightscout.androidaps.plugins.SourceMM640g.SourceMM640gPlugin; import info.nightscout.androidaps.plugins.SourceNSClient.SourceNSClientPlugin; import info.nightscout.androidaps.plugins.SourceXdrip.SourceXdripPlugin; +import info.nightscout.androidaps.plugins.TempTargetRange.events.EventTempTargetRangeChange; import info.nightscout.androidaps.receivers.DataReceiver; import info.nightscout.client.data.NSProfile; import info.nightscout.client.data.NSSgv; @@ -251,10 +256,15 @@ public class DataService extends IntentService { ConfigBuilderPlugin.nsClientVersionCode = bundles.getInt("nsclientversioncode"); // for ver 1.17 contains 117 ConfigBuilderPlugin.nsClientVersionName = bundles.getString("nsclientversionname"); log.debug("Got versions: NSClient: " + ConfigBuilderPlugin.nsClientVersionName + " Nightscout: " + ConfigBuilderPlugin.nightscoutVersionName); - if (ConfigBuilderPlugin.nsClientVersionCode < 118) - ToastUtils.showToastInUiThread(MainApp.instance().getApplicationContext(), MainApp.sResources.getString(R.string.unsupportedclientver)); + if (ConfigBuilderPlugin.nsClientVersionCode < 121) { + Notification notification = new Notification(Notification.OLD_NSCLIENT, MainApp.sResources.getString(R.string.unsupportedclientver), Notification.URGENT); + MainApp.bus().post(new EventNewNotification(notification)); + } else { + MainApp.bus().post(new EventDismissNotification(Notification.OLD_NSCLIENT)); + } } else { - ToastUtils.showToastInUiThread(MainApp.instance().getApplicationContext(), MainApp.sResources.getString(R.string.unsupportedclientver)); + Notification notification = new Notification(Notification.OLD_NSCLIENT, MainApp.sResources.getString(R.string.unsupportedclientver), Notification.URGENT); + MainApp.bus().post(new EventNewNotification(notification)); } if (bundles.containsKey("status")) { try { @@ -379,6 +389,7 @@ public class DataService extends IntentService { JSONObject trJson = new JSONObject(trstring); String _id = trJson.getString("_id"); removeTreatmentFromDb(_id); + handleRemoveTempTargetRecord(trJson); } if (bundles.containsKey("treatments")) { @@ -388,6 +399,7 @@ public class DataService extends IntentService { JSONObject trJson = jsonArray.getJSONObject(i); String _id = trJson.getString("_id"); removeTreatmentFromDb(_id); + handleRemoveTempTargetRecord(trJson); } } } catch (Exception e) { @@ -443,6 +455,7 @@ public class DataService extends IntentService { private void handleAddedTreatment(String trstring) throws JSONException, SQLException { JSONObject trJson = new JSONObject(trstring); handleDanaRHistoryRecords(trJson); // update record _id in history + handleAddChangeTempTargetRecord(trJson); if (!trJson.has("insulin") && !trJson.has("carbs")) { if (Config.logIncommingData) log.debug("ADD: Uninterested treatment: " + trstring); @@ -507,6 +520,7 @@ public class DataService extends IntentService { private void handleChangedTreatment(String trstring) throws JSONException, SQLException { JSONObject trJson = new JSONObject(trstring); handleDanaRHistoryRecords(trJson); // update record _id in history + handleAddChangeTempTargetRecord(trJson); if (!trJson.has("insulin") && !trJson.has("carbs")) { if (Config.logIncommingData) log.debug("CHANGE: Uninterested treatment: " + trstring); @@ -589,6 +603,86 @@ public class DataService extends IntentService { } } + /* + { + "_id": "58795998aa86647ba4d68ce7", + "enteredBy": "", + "eventType": "Temporary Target", + "reason": "Eating Soon", + "targetTop": 80, + "targetBottom": 80, + "duration": 120, + "created_at": "2017-01-13T22:50:00.782Z", + "carbs": null, + "insulin": null +} + */ + + public void handleAddChangeTempTargetRecord(JSONObject trJson) throws JSONException, SQLException { + if (trJson.has("eventType") && trJson.getString("eventType").equals("Temporary Target")) { + if (Config.logIncommingData) + log.debug("Processing TempTarget record: " + trJson.toString()); + Dao daoTempTargets = MainApp.getDbHelper().getDaoTempTargets(); + QueryBuilder queryBuilder = daoTempTargets.queryBuilder(); + Where where = queryBuilder.where(); + where.eq("_id", trJson.getString("_id")).or().eq("timeIndex", trJson.getLong("mills")); + PreparedQuery preparedQuery = queryBuilder.prepare(); + List list = daoTempTargets.query(preparedQuery); + NSProfile profile = MainApp.getConfigBuilder().getActiveProfile().getProfile(); + if (profile == null) return; // no profile data, better ignore than do something wrong + String units = profile.getUnits(); + if (list.size() == 0) { + // Record does not exists. add + TempTarget newRecord = new TempTarget(); + newRecord.timeStart = new Date(trJson.getLong("mills")); + newRecord.duration = trJson.getInt("duration"); + newRecord.low = NSProfile.toMgdl(trJson.getDouble("targetBottom"), units); + newRecord.high = NSProfile.toMgdl(trJson.getDouble("targetTop"), units); + newRecord.reason = trJson.getString("reason"); + newRecord._id = trJson.getString("_id"); + newRecord.setTimeIndex(newRecord.getTimeIndex()); + daoTempTargets.createIfNotExists(newRecord); + if (Config.logIncommingData) + log.debug("Adding TempTarget record to database: " + newRecord.log()); + MainApp.bus().post(new EventTempTargetRangeChange()); + } else if (list.size() == 1) { + if (Config.logIncommingData) + log.debug("Updating TempTarget record in database: " + trJson.getString("_id")); + TempTarget record = list.get(0); + record.timeStart = new Date(trJson.getLong("mills")); + record.duration = trJson.getInt("duration"); + record.low = NSProfile.toMgdl(trJson.getDouble("targetBottom"), units); + record.high = NSProfile.toMgdl(trJson.getDouble("targetTop"), units); + record.reason = trJson.getString("reason"); + record._id = trJson.getString("_id"); + daoTempTargets.update(record); + MainApp.bus().post(new EventTempTargetRangeChange()); + } + } + } + + public void handleRemoveTempTargetRecord(JSONObject trJson) throws JSONException, SQLException { + if (trJson.has("_id")) { + Dao daoTempTargets = MainApp.getDbHelper().getDaoTempTargets(); + QueryBuilder queryBuilder = daoTempTargets.queryBuilder(); + Where where = queryBuilder.where(); + where.eq("_id", trJson.getString("_id")); + PreparedQuery preparedQuery = queryBuilder.prepare(); + List list = daoTempTargets.query(preparedQuery); + + if (list.size() == 1) { + TempTarget record = list.get(0); + if (Config.logIncommingData) + log.debug("Removing TempTarget record from database: " + record.log()); + daoTempTargets.delete(record); + MainApp.bus().post(new EventTempTargetRangeChange()); + } else { + if (Config.logIncommingData) + log.debug("TempTarget not found database: " + trJson.toString()); + } + } + } + @Nullable public static Treatment findById(String _id) { try { 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 8cd27ec69d..abf843460e 100644 --- a/app/src/main/java/info/nightscout/androidaps/db/DatabaseHelper.java +++ b/app/src/main/java/info/nightscout/androidaps/db/DatabaseHelper.java @@ -31,6 +31,7 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper { public static final String DATABASE_NAME = "AndroidAPSDb"; public static final String DATABASE_BGREADINGS = "BgReadings"; public static final String DATABASE_TEMPBASALS = "TempBasals"; + public static final String DATABASE_TEMPTARGETS = "TempTargets"; public static final String DATABASE_TREATMENTS = "Treatments"; public static final String DATABASE_DANARHISTORY = "DanaRHistory"; @@ -38,6 +39,7 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper { public DatabaseHelper(Context context) { super(context, DATABASE_NAME, null, DATABASE_VERSION); + onCreate(getWritableDatabase(), getConnectionSource()); } @@ -46,11 +48,12 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper { try { log.info("onCreate"); TableUtils.createTableIfNotExists(connectionSource, TempBasal.class); + TableUtils.createTableIfNotExists(connectionSource, TempTarget.class); TableUtils.createTableIfNotExists(connectionSource, Treatment.class); TableUtils.createTableIfNotExists(connectionSource, BgReading.class); TableUtils.createTableIfNotExists(connectionSource, DanaRHistoryRecord.class); } catch (SQLException e) { - log.error(DatabaseHelper.class.getName(), "Can't create database", e); + log.error("Can't create database", e); throw new RuntimeException(e); } } @@ -60,12 +63,13 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper { try { log.info(DatabaseHelper.class.getName(), "onUpgrade"); TableUtils.dropTable(connectionSource, TempBasal.class, true); + TableUtils.dropTable(connectionSource, TempTarget.class, true); TableUtils.dropTable(connectionSource, Treatment.class, true); TableUtils.dropTable(connectionSource, BgReading.class, true); TableUtils.dropTable(connectionSource, DanaRHistoryRecord.class, true); onCreate(database, connectionSource); } catch (SQLException e) { - log.error(DatabaseHelper.class.getName(), "Can't drop databases", e); + log.error("Can't drop databases", e); throw new RuntimeException(e); } } @@ -81,35 +85,38 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper { public void cleanUpDatabases() { // TODO: call it somewhere log.debug("Before BgReadings size: " + DatabaseUtils.queryNumEntries(getReadableDatabase(), DATABASE_BGREADINGS)); - getWritableDatabase().delete("BgReadings", "timeIndex" + " < '" + (new Date().getTime() - Constants.hoursToKeepInDatabase * 60 * 60 * 1000L) + "'", null); + getWritableDatabase().delete(DATABASE_BGREADINGS, "timeIndex" + " < '" + (new Date().getTime() - Constants.hoursToKeepInDatabase * 60 * 60 * 1000L) + "'", null); log.debug("After BgReadings size: " + DatabaseUtils.queryNumEntries(getReadableDatabase(), DATABASE_BGREADINGS)); log.debug("Before TempBasals size: " + DatabaseUtils.queryNumEntries(getReadableDatabase(), DATABASE_TEMPBASALS)); - getWritableDatabase().delete("TempBasals", "timeIndex" + " < '" + (new Date().getTime() - Constants.hoursToKeepInDatabase * 60 * 60 * 1000L) + "'", null); + getWritableDatabase().delete(DATABASE_TEMPBASALS, "timeIndex" + " < '" + (new Date().getTime() - Constants.hoursToKeepInDatabase * 60 * 60 * 1000L) + "'", null); log.debug("After TempBasals size: " + DatabaseUtils.queryNumEntries(getReadableDatabase(), DATABASE_TEMPBASALS)); + log.debug("Before TempTargets size: " + DatabaseUtils.queryNumEntries(getReadableDatabase(), DATABASE_TEMPTARGETS)); + getWritableDatabase().delete(DATABASE_TEMPTARGETS, "timeIndex" + " < '" + (new Date().getTime() - Constants.hoursToKeepInDatabase * 60 * 60 * 1000L) + "'", null); + log.debug("After TempTargets size: " + DatabaseUtils.queryNumEntries(getReadableDatabase(), DATABASE_TEMPTARGETS)); + log.debug("Before Treatments size: " + DatabaseUtils.queryNumEntries(getReadableDatabase(), DATABASE_TREATMENTS)); - getWritableDatabase().delete("Treatments", "timeIndex" + " < '" + (new Date().getTime() - Constants.hoursToKeepInDatabase * 60 * 60 * 1000L) + "'", null); + getWritableDatabase().delete(DATABASE_TREATMENTS, "timeIndex" + " < '" + (new Date().getTime() - Constants.hoursToKeepInDatabase * 60 * 60 * 1000L) + "'", null); log.debug("After Treatments size: " + DatabaseUtils.queryNumEntries(getReadableDatabase(), DATABASE_TREATMENTS)); - log.debug("Before History size: " + DatabaseUtils.queryNumEntries(getReadableDatabase(), "DanaRHistory")); - getWritableDatabase().delete("History", "recordDate" + " < '" + (new Date().getTime() - Constants.daysToKeepHistoryInDatabase * 24 * 60 * 60 * 1000L) + "'", null); - log.debug("After History size: " + DatabaseUtils.queryNumEntries(getReadableDatabase(), "DanaRHistory")); + log.debug("Before History size: " + DatabaseUtils.queryNumEntries(getReadableDatabase(), DATABASE_DANARHISTORY)); + getWritableDatabase().delete(DATABASE_DANARHISTORY, "recordDate" + " < '" + (new Date().getTime() - Constants.daysToKeepHistoryInDatabase * 24 * 60 * 60 * 1000L) + "'", null); + log.debug("After History size: " + DatabaseUtils.queryNumEntries(getReadableDatabase(), DATABASE_DANARHISTORY)); } public void resetDatabases() { try { TableUtils.dropTable(connectionSource, TempBasal.class, true); + TableUtils.dropTable(connectionSource, TempTarget.class, true); TableUtils.dropTable(connectionSource, Treatment.class, true); TableUtils.dropTable(connectionSource, BgReading.class, true); TableUtils.dropTable(connectionSource, DanaRHistoryRecord.class, true); TableUtils.createTableIfNotExists(connectionSource, TempBasal.class); + TableUtils.createTableIfNotExists(connectionSource, TempTarget.class); TableUtils.createTableIfNotExists(connectionSource, Treatment.class); TableUtils.createTableIfNotExists(connectionSource, BgReading.class); TableUtils.createTableIfNotExists(connectionSource, DanaRHistoryRecord.class); -// MainApp.bus().post(new EventNewBG()); -// MainApp.bus().post(new EventTreatmentChange()); -// MainApp.bus().post(new EventTempBasalChange()); } catch (SQLException e) { e.printStackTrace(); } @@ -117,7 +124,6 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper { public void resetTreatments() { try { - TableUtils.dropTable(connectionSource, Treatment.class, true); TableUtils.createTableIfNotExists(connectionSource, Treatment.class); } catch (SQLException e) { @@ -125,10 +131,23 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper { } } + public void resetTempTargets() { + try { + TableUtils.dropTable(connectionSource, TempTarget.class, true); + TableUtils.createTableIfNotExists(connectionSource, TempTarget.class); + } catch (SQLException e) { + e.printStackTrace(); + } + } + public Dao getDaoTempBasals() throws SQLException { return getDao(TempBasal.class); } + public Dao getDaoTempTargets() throws SQLException { + return getDao(TempTarget.class); + } + public Dao getDaoTreatments() throws SQLException { return getDao(Treatment.class); } @@ -217,6 +236,24 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper { return new ArrayList(); } + public List getTemptargetsDataFromTime(long mills, boolean ascending) { + try { + Dao daoTempTargets = getDaoTempTargets(); + List tempTargets; + QueryBuilder queryBuilder = daoTempTargets.queryBuilder(); + queryBuilder.orderBy("timeIndex", ascending); + Where where = queryBuilder.where(); + where.ge("timeIndex", mills); + PreparedQuery preparedQuery = queryBuilder.prepare(); + tempTargets = daoTempTargets.query(preparedQuery); + return tempTargets; + } catch (SQLException e) { + e.printStackTrace(); + } + return new ArrayList(); + } + + public List getTempbasalsDataFromTime(long mills, boolean ascending, boolean isExtended) { try { Dao daoTempbasals = getDaoTempBasals(); diff --git a/app/src/main/java/info/nightscout/androidaps/db/TempTarget.java b/app/src/main/java/info/nightscout/androidaps/db/TempTarget.java new file mode 100644 index 0000000000..051a1d3d40 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/db/TempTarget.java @@ -0,0 +1,78 @@ +package info.nightscout.androidaps.db; + +import com.j256.ormlite.field.DatabaseField; +import com.j256.ormlite.table.DatabaseTable; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.Date; + +import info.nightscout.androidaps.Constants; +import info.nightscout.androidaps.MainApp; +import info.nightscout.androidaps.plugins.TempTargetRange.TempTargetRangePlugin; +import info.nightscout.utils.DecimalFormatter; + +@DatabaseTable(tableName = DatabaseHelper.DATABASE_TEMPTARGETS) +public class TempTarget { + private static Logger log = LoggerFactory.getLogger(TempTarget.class); + + public long getTimeIndex() { + return timeStart.getTime() - timeStart.getTime() % 1000; + } + + public void setTimeIndex(long timeIndex) { + this.timeIndex = timeIndex; + } + + @DatabaseField(id = true, useGetSet = true) + public long timeIndex; + + @DatabaseField + public Date timeStart; + + @DatabaseField + public double low; // in mgdl + + @DatabaseField + public double high; // in mgdl + + @DatabaseField + public String reason; + + @DatabaseField + public int duration; // in minutes + + @DatabaseField + public String _id; // NS _id + + public Date getPlannedTimeEnd() { + return new Date(timeStart.getTime() + 60 * 1_000 * duration); + } + + public String lowValueToUnitsToString(String units) { + if (units.equals(Constants.MGDL)) return DecimalFormatter.to0Decimal(low); + else return DecimalFormatter.to1Decimal(low * Constants.MGDL_TO_MMOLL); + } + + public String highValueToUnitsToString(String units) { + if (units.equals(Constants.MGDL)) return DecimalFormatter.to0Decimal(high); + else return DecimalFormatter.to1Decimal(low * Constants.MGDL_TO_MMOLL); + } + + public boolean isInProgress() { + return ((TempTargetRangePlugin) MainApp.getSpecificPlugin(TempTargetRangePlugin.class)).getTempTargetInProgress(new Date().getTime()) == this; + } + + public String log() { + return "TempTarget{" + + "timeIndex=" + timeIndex + + ", timeStart=" + timeStart + + ", duration=" + duration + + ", reason=" + reason + + ", low=" + low + + ", high=" + high + + '}'; + } + +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Actions/ActionsFragment.java b/app/src/main/java/info/nightscout/androidaps/plugins/Actions/ActionsFragment.java index 88643752ee..af6676442c 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/Actions/ActionsFragment.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/Actions/ActionsFragment.java @@ -12,6 +12,7 @@ import android.widget.Button; import com.squareup.otto.Subscribe; +import info.nightscout.androidaps.Config; import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.R; import info.nightscout.androidaps.events.EventInitializationChanged; @@ -35,6 +36,7 @@ public class ActionsFragment extends Fragment implements FragmentBase, View.OnCl } Button profileSwitch; + Button tempTarget; Button extendedBolus; Button tempBasal; Button fill; @@ -49,11 +51,13 @@ public class ActionsFragment extends Fragment implements FragmentBase, View.OnCl View view = inflater.inflate(R.layout.actions_fragment, container, false); profileSwitch = (Button) view.findViewById(R.id.actions_profileswitch); + tempTarget = (Button) view.findViewById(R.id.actions_temptarget); extendedBolus = (Button) view.findViewById(R.id.actions_extendedbolus); tempBasal = (Button) view.findViewById(R.id.actions_settempbasal); fill = (Button) view.findViewById(R.id.actions_fill); profileSwitch.setOnClickListener(this); + tempTarget.setOnClickListener(this); extendedBolus.setOnClickListener(this); tempBasal.setOnClickListener(this); fill.setOnClickListener(this); @@ -106,6 +110,10 @@ public class ActionsFragment extends Fragment implements FragmentBase, View.OnCl fill.setVisibility(View.GONE); else fill.setVisibility(View.VISIBLE); + if (!Config.APS) + tempTarget.setVisibility(View.GONE); + else + tempTarget.setVisibility(View.VISIBLE); } }); } @@ -117,11 +125,18 @@ public class ActionsFragment extends Fragment implements FragmentBase, View.OnCl switch (view.getId()) { case R.id.actions_profileswitch: NewNSTreatmentDialog newDialog = new NewNSTreatmentDialog(); - final OptionsToShow profileswitch = new OptionsToShow(R.id.careportal_profileswitch, R.string.careportal_profileswitch, true, false, false, false, false, false, false, true, false); + final OptionsToShow profileswitch = new OptionsToShow(R.id.careportal_profileswitch, R.string.careportal_profileswitch, true, false, false, false, false, false, false, true, false, false); profileswitch.executeProfileSwitch = true; newDialog.setOptions(profileswitch); newDialog.show(manager, "NewNSTreatmentDialog"); break; + case R.id.actions_temptarget: + NewNSTreatmentDialog newTTDialog = new NewNSTreatmentDialog(); + final OptionsToShow temptarget = new OptionsToShow(R.id.careportal_temptarget, R.string.careportal_temptarget, false, false, false, false, true, false, false, false, false, true); + temptarget.executeTempTarget = true; + newTTDialog.setOptions(temptarget); + newTTDialog.show(manager, "NewNSTreatmentDialog"); + break; case R.id.actions_extendedbolus: NewExtendedBolusDialog newExtendedDialog = new NewExtendedBolusDialog(); newExtendedDialog.show(manager, "NewExtendedDialog"); diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Careportal/CareportalFragment.java b/app/src/main/java/info/nightscout/androidaps/plugins/Careportal/CareportalFragment.java index 05245bd0b1..5c53864d36 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/Careportal/CareportalFragment.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/Careportal/CareportalFragment.java @@ -25,25 +25,26 @@ public class CareportalFragment extends Fragment implements FragmentBase, View.O return careportalPlugin; } - // bg,insulin,carbs,prebolus,duration,percent,absolute,profile,split - final OptionsToShow bgcheck = new OptionsToShow(R.id.careportal_bgcheck, R.string.careportal_bgcheck, true, true, true, false, false, false, false, false, false); - final OptionsToShow snackbolus = new OptionsToShow(R.id.careportal_snackbolus, R.string.careportal_snackbolus, true, true, true, true, false, false, false, false, false); - final OptionsToShow mealbolus = new OptionsToShow(R.id.careportal_mealbolus, R.string.careportal_mealbolus, true, true, true, true, false, false, false, false, false); - final OptionsToShow correctionbolus = new OptionsToShow(R.id.careportal_correctionbolus, R.string.careportal_correctionbolus, true, true, true, true, false, false, false, false, false); - final OptionsToShow carbcorrection = new OptionsToShow(R.id.careportal_carbscorrection, R.string.careportal_carbscorrection, true, false, true, false, false, false, false, false, false); - final OptionsToShow combobolus = new OptionsToShow(R.id.careportal_combobolus, R.string.careportal_combobolus, true, true, true, true, true, false, false, false, true); - final OptionsToShow announcement = new OptionsToShow(R.id.careportal_announcement, R.string.careportal_announcement, true, false, false, false, false, false, false, false, false); - final OptionsToShow note = new OptionsToShow(R.id.careportal_note, R.string.careportal_note, true, false, false, false, true, false, false, false, false); - final OptionsToShow question = new OptionsToShow(R.id.careportal_question, R.string.careportal_question, true, false, false, false, false, false, false, false, false); - final OptionsToShow exercise = new OptionsToShow(R.id.careportal_exercise, R.string.careportal_exercise, false, false, false, false, true, false, false, false, false); - final OptionsToShow sitechange = new OptionsToShow(R.id.careportal_pumpsitechange, R.string.careportal_pumpsitechange, true, true, false, false, false, false, false, false, false); - final OptionsToShow sensorstart = new OptionsToShow(R.id.careportal_cgmsensorstart, R.string.careportal_cgmsensorstart, true, false, false, false, false, false, false, false, false); - final OptionsToShow sensorchange = new OptionsToShow(R.id.careportal_cgmsensorinsert, R.string.careportal_cgmsensorinsert, true, false, false, false, false, false, false, false, false); - final OptionsToShow insulinchange = new OptionsToShow(R.id.careportal_insulincartridgechange, R.string.careportal_insulincartridgechange, true, false, false, false, false, false, false, false, false); - final OptionsToShow tempbasalstart = new OptionsToShow(R.id.careportal_tempbasalstart, R.string.careportal_tempbasalstart, true, false, false, false, true, true, true, false, false); - final OptionsToShow tempbasalend = new OptionsToShow(R.id.careportal_tempbasalend, R.string.careportal_tempbasalend, true, false, false, false, false, false, false, false, false); - final OptionsToShow profileswitch = new OptionsToShow(R.id.careportal_profileswitch, R.string.careportal_profileswitch, true, false, false, false, false, false, false, true, false); - final OptionsToShow openapsoffline = new OptionsToShow(R.id.careportal_openapsoffline, R.string.careportal_openapsoffline, false, false, false, false, true, false, false, false, false); + // bg,insulin,carbs,prebolus,duration,percent,absolute,profile,split,temptarget + final OptionsToShow bgcheck = new OptionsToShow(R.id.careportal_bgcheck, R.string.careportal_bgcheck, true, true, true, false, false, false, false, false, false, false); + final OptionsToShow snackbolus = new OptionsToShow(R.id.careportal_snackbolus, R.string.careportal_snackbolus, true, true, true, true, false, false, false, false, false, false); + final OptionsToShow mealbolus = new OptionsToShow(R.id.careportal_mealbolus, R.string.careportal_mealbolus, true, true, true, true, false, false, false, false, false, false); + final OptionsToShow correctionbolus = new OptionsToShow(R.id.careportal_correctionbolus, R.string.careportal_correctionbolus, true, true, true, true, false, false, false, false, false, false); + final OptionsToShow carbcorrection = new OptionsToShow(R.id.careportal_carbscorrection, R.string.careportal_carbscorrection, true, false, true, false, false, false, false, false, false, false); + final OptionsToShow combobolus = new OptionsToShow(R.id.careportal_combobolus, R.string.careportal_combobolus, true, true, true, true, true, false, false, false, true, false); + final OptionsToShow announcement = new OptionsToShow(R.id.careportal_announcement, R.string.careportal_announcement, true, false, false, false, false, false, false, false, false, false); + final OptionsToShow note = new OptionsToShow(R.id.careportal_note, R.string.careportal_note, true, false, false, false, true, false, false, false, false, false); + final OptionsToShow question = new OptionsToShow(R.id.careportal_question, R.string.careportal_question, true, false, false, false, false, false, false, false, false, false); + final OptionsToShow exercise = new OptionsToShow(R.id.careportal_exercise, R.string.careportal_exercise, false, false, false, false, true, false, false, false, false, false); + final OptionsToShow sitechange = new OptionsToShow(R.id.careportal_pumpsitechange, R.string.careportal_pumpsitechange, true, true, false, false, false, false, false, false, false, false); + final OptionsToShow sensorstart = new OptionsToShow(R.id.careportal_cgmsensorstart, R.string.careportal_cgmsensorstart, true, false, false, false, false, false, false, false, false, false); + final OptionsToShow sensorchange = new OptionsToShow(R.id.careportal_cgmsensorinsert, R.string.careportal_cgmsensorinsert, true, false, false, false, false, false, false, false, false, false); + final OptionsToShow insulinchange = new OptionsToShow(R.id.careportal_insulincartridgechange, R.string.careportal_insulincartridgechange, true, false, false, false, false, false, false, false, false, false); + final OptionsToShow tempbasalstart = new OptionsToShow(R.id.careportal_tempbasalstart, R.string.careportal_tempbasalstart, true, false, false, false, true, true, true, false, false, false); + final OptionsToShow tempbasalend = new OptionsToShow(R.id.careportal_tempbasalend, R.string.careportal_tempbasalend, true, false, false, false, false, false, false, false, false, false); + final OptionsToShow profileswitch = new OptionsToShow(R.id.careportal_profileswitch, R.string.careportal_profileswitch, true, false, false, false, false, false, false, true, false, false); + final OptionsToShow openapsoffline = new OptionsToShow(R.id.careportal_openapsoffline, R.string.careportal_openapsoffline, false, false, false, false, true, false, false, false, false, false); + final OptionsToShow temptarget = new OptionsToShow(R.id.careportal_temptarget, R.string.careportal_temptarget, false, false, false, false, true, false, false, false, false, true); @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, @@ -68,6 +69,7 @@ public class CareportalFragment extends Fragment implements FragmentBase, View.O view.findViewById(R.id.careportal_tempbasalend).setOnClickListener(this); view.findViewById(R.id.careportal_tempbasalstart).setOnClickListener(this); view.findViewById(R.id.careportal_openapsoffline).setOnClickListener(this); + view.findViewById(R.id.careportal_temptarget).setOnClickListener(this); return view; } @@ -130,6 +132,9 @@ public class CareportalFragment extends Fragment implements FragmentBase, View.O case R.id.careportal_openapsoffline: newDialog.setOptions(openapsoffline); break; + case R.id.careportal_temptarget: + newDialog.setOptions(temptarget); + break; default: newDialog = null; } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Careportal/Dialogs/NewNSTreatmentDialog.java b/app/src/main/java/info/nightscout/androidaps/plugins/Careportal/Dialogs/NewNSTreatmentDialog.java index b941cdb4c2..d0acb2a3b4 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/Careportal/Dialogs/NewNSTreatmentDialog.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/Careportal/Dialogs/NewNSTreatmentDialog.java @@ -24,6 +24,7 @@ import android.widget.RadioButton; import android.widget.Spinner; import android.widget.TextView; +import com.j256.ormlite.dao.Dao; import com.wdullaer.materialdatetimepicker.date.DatePickerDialog; import com.wdullaer.materialdatetimepicker.time.RadialPickerLayout; import com.wdullaer.materialdatetimepicker.time.TimePickerDialog; @@ -33,6 +34,7 @@ import org.json.JSONObject; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import java.sql.SQLException; import java.text.DecimalFormat; import java.util.ArrayList; import java.util.Calendar; @@ -42,10 +44,13 @@ import java.util.Date; import info.nightscout.androidaps.Constants; import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.R; +import info.nightscout.androidaps.db.BgReading; +import info.nightscout.androidaps.db.TempTarget; import info.nightscout.androidaps.events.EventNewBasalProfile; import info.nightscout.androidaps.interfaces.PumpInterface; import info.nightscout.androidaps.plugins.Careportal.OptionsToShow; import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin; +import info.nightscout.androidaps.plugins.TempTargetRange.events.EventTempTargetRangeChange; import info.nightscout.client.data.NSProfile; import info.nightscout.utils.DateUtil; import info.nightscout.utils.PlusMinusEditText; @@ -73,6 +78,7 @@ public class NewNSTreatmentDialog extends DialogFragment implements View.OnClick LinearLayout layoutAbsolute; LinearLayout layoutCarbTime; LinearLayout layoutProfile; + LinearLayout layoutTempTarget; Button dateButton; Button timeButton; Button okButton; @@ -91,6 +97,9 @@ public class NewNSTreatmentDialog extends DialogFragment implements View.OnClick EditText carbTimeEdit; EditText splitEdit; Spinner profileSpinner; + EditText low; + EditText high; + Spinner reasonSpinner; PlusMinusEditText editBg; PlusMinusEditText editCarbs; @@ -142,6 +151,7 @@ public class NewNSTreatmentDialog extends DialogFragment implements View.OnClick layoutAbsolute = (LinearLayout) view.findViewById(R.id.careportal_newnstreatment_absolute_layout); layoutCarbTime = (LinearLayout) view.findViewById(R.id.careportal_newnstreatment_carbtime_layout); layoutProfile = (LinearLayout) view.findViewById(R.id.careportal_newnstreatment_profile_layout); + layoutTempTarget = (LinearLayout) view.findViewById(R.id.careportal_newnstreatment_temptarget_layout); bgUnitsView = (TextView) view.findViewById(R.id.careportal_newnstreatment_bgunits); meterRadioButton = (RadioButton) view.findViewById(R.id.careportal_newnstreatment_meter); @@ -193,6 +203,10 @@ public class NewNSTreatmentDialog extends DialogFragment implements View.OnClick notesEdit = (EditText) view.findViewById(R.id.careportal_newnstreatment_notes); splitEdit = (EditText) view.findViewById(R.id.careportal_newnstreatment_splitinput); + reasonSpinner = (Spinner) view.findViewById(R.id.careportal_newnstreatment_temptarget_reason); + low = (EditText) view.findViewById(R.id.careportal_temptarget_low); + high = (EditText) view.findViewById(R.id.careportal_temptarget_high); + eventTime = new Date(); dateButton = (Button) view.findViewById(R.id.careportal_newnstreatment_eventdate); timeButton = (Button) view.findViewById(R.id.careportal_newnstreatment_eventtime); @@ -204,7 +218,7 @@ public class NewNSTreatmentDialog extends DialogFragment implements View.OnClick okButton = (Button) view.findViewById(R.id.careportal_newnstreatment_ok); okButton.setOnClickListener(this); - // BG + // profile profile = MainApp.getConfigBuilder().getActiveProfile().getProfile(); ArrayList profileList; units = Constants.MGDL; @@ -227,6 +241,17 @@ public class NewNSTreatmentDialog extends DialogFragment implements View.OnClick } } + // temp target + ArrayList reasonList = new ArrayList(); + reasonList.add(MainApp.sResources.getString(R.string.eatingsoon)); + reasonList.add(MainApp.sResources.getString(R.string.activity)); + reasonList.add(MainApp.sResources.getString(R.string.manual)); + ArrayAdapter adapterReason = new ArrayAdapter(getContext(), + android.R.layout.simple_spinner_item, reasonList); + adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); + reasonSpinner.setAdapter(adapterReason); + + // bg bgUnitsView.setText(units); // Set BG if not old @@ -271,6 +296,7 @@ public class NewNSTreatmentDialog extends DialogFragment implements View.OnClick showOrHide(layoutAbsolute, options.absolute); showOrHide(layoutCarbTime, options.prebolus); showOrHide(layoutProfile, options.profile); + showOrHide(layoutTempTarget, options.tempTarget); return view; } @@ -403,6 +429,9 @@ public class NewNSTreatmentDialog extends DialogFragment implements View.OnClick case R.id.careportal_openapsoffline: data.put("eventType", "OpenAPS Offline"); break; + case R.id.careportal_temptarget: + data.put("eventType", "Temporary Target"); + break; } if (SafeParse.stringToDouble(bgInputEdit.getText().toString()) != 0d) { data.put("glucose", SafeParse.stringToDouble(bgInputEdit.getText().toString())); @@ -426,6 +455,12 @@ public class NewNSTreatmentDialog extends DialogFragment implements View.OnClick data.put("preBolus", SafeParse.stringToDouble(carbTimeEdit.getText().toString())); if (!notesEdit.getText().toString().equals("")) data.put("notes", notesEdit.getText().toString()); + if (!reasonSpinner.getSelectedItem().toString().equals("")) + data.put("reason", reasonSpinner.getSelectedItem().toString()); + if (SafeParse.stringToDouble(low.getText().toString()) != 0d) + data.put("targetBottom", SafeParse.stringToDouble(low.getText().toString())); + if (SafeParse.stringToDouble(high.getText().toString()) != 0d) + data.put("targetTop", SafeParse.stringToDouble(high.getText().toString())); data.put("units", units); if (!enteredBy.equals("")) data.put("enteredBy", enteredBy); if (options.eventType == R.id.careportal_combobolus) { @@ -509,6 +544,14 @@ public class NewNSTreatmentDialog extends DialogFragment implements View.OnClick ret += data.get("profile"); ret += "\n"; } + if (data.has("targetBottom") && data.has("targetTop")) { + ret += getString(R.string.target_range); + ret += " "; + ret += data.get("targetBottom"); + ret += " - "; + ret += data.get("targetTop"); + ret += "\n"; + } if (data.has("created_at")) { ret += getString(R.string.careportal_newnstreatment_eventtime_label); ret += ": "; @@ -563,6 +606,35 @@ public class NewNSTreatmentDialog extends DialogFragment implements View.OnClick } else { ConfigBuilderPlugin.uploadCareportalEntryToNS(data); } + if (options.executeTempTarget) { + if (data.has("targetBottom") && data.has("targetTop")) { + sHandler.post(new Runnable() { + @Override + public void run() { + try { + TempTarget tempTarget = new TempTarget(); + tempTarget.timeStart = eventTime; + tempTarget.duration = data.getInt("duration"); + tempTarget.reason = data.getString("reason"); + tempTarget.low = NSProfile.toMgdl(data.getDouble("targetBottom"), MainApp.getConfigBuilder().getActiveProfile().getProfile().getUnits()); + tempTarget.high = NSProfile.toMgdl(data.getDouble("targetTop"), MainApp.getConfigBuilder().getActiveProfile().getProfile().getUnits()); + tempTarget.setTimeIndex(tempTarget.getTimeIndex()); + Dao dao = MainApp.getDbHelper().getDaoTempTargets(); + log.debug("Creating new TempTarget db record: " + tempTarget.log()); + dao.createIfNotExists(tempTarget); + MainApp.bus().post(new EventTempTargetRangeChange()); + ConfigBuilderPlugin.uploadCareportalEntryToNS(data); + } catch (JSONException e) { + e.printStackTrace(); + } catch (SQLException e) { + e.printStackTrace(); + } + } + }); + } + } else { + ConfigBuilderPlugin.uploadCareportalEntryToNS(data); + } } }); builder.setNegativeButton(getContext().getString(R.string.cancel), null); diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Careportal/OptionsToShow.java b/app/src/main/java/info/nightscout/androidaps/plugins/Careportal/OptionsToShow.java index e5a086c07e..23ce1dbcde 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/Careportal/OptionsToShow.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/Careportal/OptionsToShow.java @@ -16,9 +16,11 @@ public class OptionsToShow { public boolean absolute; public boolean profile; public boolean split; + public boolean tempTarget; // perform direct actions public boolean executeProfileSwitch = false; + public boolean executeTempTarget = false; public OptionsToShow(int eventType, int eventName, @@ -30,7 +32,8 @@ public class OptionsToShow { boolean percent, boolean absolute, boolean profile, - boolean split) { + boolean split, + boolean tempTarget) { this.eventType = eventType; this.eventName = eventName; this.bg = bg; @@ -42,5 +45,6 @@ public class OptionsToShow { this.absolute = absolute; this.profile = profile; this.split = split; + this.tempTarget = tempTarget; } } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/CircadianPercentageProfile/CircadianPercentageProfileFragment.java b/app/src/main/java/info/nightscout/androidaps/plugins/CircadianPercentageProfile/CircadianPercentageProfileFragment.java index 8158490197..c68c873401 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/CircadianPercentageProfile/CircadianPercentageProfileFragment.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/CircadianPercentageProfile/CircadianPercentageProfileFragment.java @@ -133,7 +133,7 @@ public class CircadianPercentageProfileFragment extends Fragment implements Frag @Override public void onClick(View view) { NewNSTreatmentDialog newDialog = new NewNSTreatmentDialog(); - final OptionsToShow profileswitch = new OptionsToShow(R.id.careportal_profileswitch, R.string.careportal_profileswitch, true, false, false, false, false, false, false, true, false); + final OptionsToShow profileswitch = new OptionsToShow(R.id.careportal_profileswitch, R.string.careportal_profileswitch, true, false, false, false, false, false, false, true, false, false); profileswitch.executeProfileSwitch = true; newDialog.setOptions(profileswitch); newDialog.show(getFragmentManager(), "NewNSTreatmentDialog"); 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 ffd27f771b..6a00276e7d 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 @@ -981,7 +981,25 @@ public class ConfigBuilderPlugin implements PluginBase, PumpInterface, Constrain intent.putExtras(bundle); intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES); context.sendBroadcast(intent); - DbLogger.dbAdd(intent, data.toString(), NewExtendedBolusDialog.class); + DbLogger.dbAdd(intent, data.toString(), ConfigBuilderPlugin.class); + } catch (Exception e) { + e.printStackTrace(); + } + + } + + public static void removeCareportalEntryFromNS(String _id) { + try { + Context context = MainApp.instance().getApplicationContext(); + Bundle bundle = new Bundle(); + bundle.putString("action", "dbRemove"); + bundle.putString("collection", "treatments"); + bundle.putString("_id", _id); + Intent intent = new Intent(Intents.ACTION_DATABASE); + intent.putExtras(bundle); + intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES); + context.sendBroadcast(intent); + DbLogger.dbRemove(intent, _id, ConfigBuilderPlugin.class); } catch (Exception e) { e.printStackTrace(); } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/LocalProfile/LocalProfileFragment.java b/app/src/main/java/info/nightscout/androidaps/plugins/LocalProfile/LocalProfileFragment.java index cc891eb98a..2efcecc936 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/LocalProfile/LocalProfileFragment.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/LocalProfile/LocalProfileFragment.java @@ -106,7 +106,7 @@ public class LocalProfileFragment extends Fragment implements FragmentBase { @Override public void onClick(View view) { NewNSTreatmentDialog newDialog = new NewNSTreatmentDialog(); - final OptionsToShow profileswitch = new OptionsToShow(R.id.careportal_profileswitch, R.string.careportal_profileswitch, true, false, false, false, false, false, false, true, false); + final OptionsToShow profileswitch = new OptionsToShow(R.id.careportal_profileswitch, R.string.careportal_profileswitch, true, false, false, false, false, false, false, true, false, false); profileswitch.executeProfileSwitch = true; newDialog.setOptions(profileswitch); newDialog.show(getFragmentManager(), "NewNSTreatmentDialog"); diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/OpenAPSMA/OpenAPSMAPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/OpenAPSMA/OpenAPSMAPlugin.java index 8f5e9552c2..6ccd75575c 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/OpenAPSMA/OpenAPSMAPlugin.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/OpenAPSMA/OpenAPSMAPlugin.java @@ -17,6 +17,7 @@ import info.nightscout.androidaps.R; import info.nightscout.androidaps.data.GlucoseStatus; import info.nightscout.androidaps.data.IobTotal; import info.nightscout.androidaps.data.MealData; +import info.nightscout.androidaps.db.TempTarget; import info.nightscout.androidaps.interfaces.APSInterface; import info.nightscout.androidaps.interfaces.PluginBase; import info.nightscout.androidaps.interfaces.PumpInterface; @@ -26,6 +27,7 @@ import info.nightscout.androidaps.plugins.Loop.APSResult; import info.nightscout.androidaps.plugins.Loop.ScriptReader; import info.nightscout.androidaps.plugins.OpenAPSMA.events.EventOpenAPSUpdateGui; import info.nightscout.androidaps.plugins.OpenAPSMA.events.EventOpenAPSUpdateResultGui; +import info.nightscout.androidaps.plugins.TempTargetRange.TempTargetRangePlugin; import info.nightscout.client.data.NSProfile; import info.nightscout.utils.DateUtil; import info.nightscout.utils.Round; @@ -179,6 +181,17 @@ public class OpenAPSMAPlugin implements PluginBase, APSInterface { minBg = verifyHardLimits(minBg, "minBg", 72, 180); maxBg = verifyHardLimits(maxBg, "maxBg", 100, 270); targetBg = verifyHardLimits(targetBg, "targetBg", 80, 200); + + TempTargetRangePlugin tempTargetRangePlugin = (TempTargetRangePlugin) MainApp.getSpecificPlugin(TempTargetRangePlugin.class); + if (tempTargetRangePlugin != null && tempTargetRangePlugin.isEnabled(PluginBase.GENERAL)) { + TempTarget tempTarget = tempTargetRangePlugin.getTempTargetInProgress(new Date().getTime()); + if (tempTarget != null) { + minBg = verifyHardLimits(tempTarget.low, "minBg", 72, 180); + maxBg = verifyHardLimits(tempTarget.high, "maxBg", 72, 270); + targetBg = verifyHardLimits((tempTarget.low + tempTarget.high) / 2, "targetBg", 80, 200); + } + } + maxIob = verifyHardLimits(maxIob, "maxIob", 0, 7); maxBasal = verifyHardLimits(maxBasal, "max_basal", 0.1, 10); diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Overview/Notification.java b/app/src/main/java/info/nightscout/androidaps/plugins/Overview/Notification.java index 38e954571b..daa882bd8f 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/Overview/Notification.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/Overview/Notification.java @@ -20,6 +20,7 @@ public class Notification { public static final int PROFILE_NOT_SET_NOT_INITIALIZED = 5; public static final int FAILED_UDPATE_PROFILE = 6; public static final int BASAL_VALUE_BELOW_MINIMUM = 7; + public static final int OLD_NSCLIENT = 8; public int id; public Date date; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Overview/OverviewFragment.java b/app/src/main/java/info/nightscout/androidaps/plugins/Overview/OverviewFragment.java index e7832f7cfb..709037362b 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/Overview/OverviewFragment.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/Overview/OverviewFragment.java @@ -56,6 +56,7 @@ import info.nightscout.androidaps.data.IobTotal; import info.nightscout.androidaps.data.PumpEnactResult; import info.nightscout.androidaps.db.BgReading; import info.nightscout.androidaps.db.TempBasal; +import info.nightscout.androidaps.db.TempTarget; import info.nightscout.androidaps.db.Treatment; import info.nightscout.androidaps.events.EventInitializationChanged; import info.nightscout.androidaps.events.EventNewBG; @@ -80,6 +81,8 @@ import info.nightscout.androidaps.plugins.Overview.events.EventDismissNotificati import info.nightscout.androidaps.plugins.Overview.events.EventNewNotification; import info.nightscout.androidaps.plugins.Overview.graphExtensions.PointsWithLabelGraphSeries; import info.nightscout.androidaps.plugins.Overview.graphExtensions.TimeAsXAxisLabelFormatter; +import info.nightscout.androidaps.plugins.TempBasals.TempBasalsPlugin; +import info.nightscout.androidaps.plugins.TempTargetRange.TempTargetRangePlugin; import info.nightscout.client.data.NSProfile; import info.nightscout.utils.BolusWizard; import info.nightscout.utils.DateUtil; @@ -109,6 +112,7 @@ public class OverviewFragment extends Fragment { TextView activeProfileView; TextView iobView; TextView apsModeView; + TextView tempTargetView; GraphView bgGraph; CheckBox showPredictionView; @@ -157,6 +161,7 @@ public class OverviewFragment extends Fragment { iobView = (TextView) view.findViewById(R.id.overview_iob); apsModeView = (TextView) view.findViewById(R.id.overview_apsmode); + tempTargetView = (TextView) view.findViewById(R.id.overview_temptarget); bgGraph = (GraphView) view.findViewById(R.id.overview_bggraph); cancelTempButton = (Button) view.findViewById(R.id.overview_canceltemp); treatmentButton = (Button) view.findViewById(R.id.overview_treatment); @@ -459,7 +464,7 @@ public class OverviewFragment extends Fragment { updateNotifications(); BgReading actualBG = MainApp.getDbHelper().actualBg(); BgReading lastBG = MainApp.getDbHelper().lastBg(); - if (MainApp.getConfigBuilder() == null || MainApp.getConfigBuilder().getActiveProfile() == null) // app not initialized yet + if (MainApp.getConfigBuilder() == null || MainApp.getConfigBuilder().getActiveProfile() == null || MainApp.getConfigBuilder().getActiveProfile().getProfile() == null) // app not initialized yet return; // Skip if not initialized yet @@ -515,8 +520,20 @@ public class OverviewFragment extends Fragment { apsModeView.setVisibility(View.GONE); } - // **** Temp button **** + // temp target NSProfile profile = MainApp.getConfigBuilder().getActiveProfile().getProfile(); + TempTargetRangePlugin tempTargetRangePlugin = (TempTargetRangePlugin) MainApp.getSpecificPlugin(TempTargetRangePlugin.class); + if (tempTargetRangePlugin != null && tempTargetRangePlugin.isEnabled(PluginBase.GENERAL)) { + TempTarget tempTarget = tempTargetRangePlugin.getTempTargetInProgress(new Date().getTime()); + if (tempTarget != null) { + tempTargetView.setVisibility(View.VISIBLE); + tempTargetView.setText(NSProfile.toUnitsString(tempTarget.low, NSProfile.fromMgdlToUnits(tempTarget.low, profile.getUnits()), profile.getUnits()) + " - " + NSProfile.toUnitsString(tempTarget.high, NSProfile.fromMgdlToUnits(tempTarget.high, profile.getUnits()), profile.getUnits())); + } else { + tempTargetView.setVisibility(View.GONE); + } + } + + // **** Temp button **** PumpInterface pump = MainApp.getConfigBuilder(); boolean showAcceptButton = !MainApp.getConfigBuilder().isClosedModeEnabled(); // Open mode needed @@ -557,7 +574,7 @@ public class OverviewFragment extends Fragment { public boolean onLongClick(View view) { view.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS); NewNSTreatmentDialog newDialog = new NewNSTreatmentDialog(); - final OptionsToShow profileswitch = new OptionsToShow(R.id.careportal_profileswitch, R.string.careportal_profileswitch, true, false, false, false, false, false, false, true, false); + final OptionsToShow profileswitch = new OptionsToShow(R.id.careportal_profileswitch, R.string.careportal_profileswitch, true, false, false, false, false, false, false, true, false, false); profileswitch.executeProfileSwitch = true; newDialog.setOptions(profileswitch); newDialog.show(getFragmentManager(), "NewNSTreatmentDialog"); diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/SimpleProfile/SimpleProfileFragment.java b/app/src/main/java/info/nightscout/androidaps/plugins/SimpleProfile/SimpleProfileFragment.java index 22e293a023..c0e8926ebd 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/SimpleProfile/SimpleProfileFragment.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/SimpleProfile/SimpleProfileFragment.java @@ -110,7 +110,7 @@ public class SimpleProfileFragment extends Fragment implements FragmentBase { @Override public void onClick(View view) { NewNSTreatmentDialog newDialog = new NewNSTreatmentDialog(); - final OptionsToShow profileswitch = new OptionsToShow(R.id.careportal_profileswitch, R.string.careportal_profileswitch, true, false, false, false, false, false, false, true, false); + final OptionsToShow profileswitch = new OptionsToShow(R.id.careportal_profileswitch, R.string.careportal_profileswitch, true, false, false, false, false, false, false, true, false, false); profileswitch.executeProfileSwitch = true; newDialog.setOptions(profileswitch); newDialog.show(getFragmentManager(), "NewNSTreatmentDialog"); diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/TempTargetRange/TempTargetRangeFragment.java b/app/src/main/java/info/nightscout/androidaps/plugins/TempTargetRange/TempTargetRangeFragment.java new file mode 100644 index 0000000000..332da1d8bd --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/TempTargetRange/TempTargetRangeFragment.java @@ -0,0 +1,234 @@ +package info.nightscout.androidaps.plugins.TempTargetRange; + +import android.app.Activity; +import android.content.Context; +import android.content.DialogInterface; +import android.content.Intent; +import android.content.SharedPreferences; +import android.graphics.Paint; +import android.os.Bundle; +import android.preference.PreferenceManager; +import android.support.v4.app.Fragment; +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.LinearLayout; +import android.widget.TextView; + +import com.j256.ormlite.dao.Dao; +import com.squareup.otto.Subscribe; + +import java.sql.SQLException; +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.TempTarget; +import info.nightscout.androidaps.interfaces.FragmentBase; +import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin; +import info.nightscout.androidaps.plugins.TempTargetRange.events.EventTempTargetRangeChange; +import info.nightscout.client.data.NSProfile; +import info.nightscout.utils.DateUtil; +import info.nightscout.utils.DecimalFormatter; +import info.nightscout.utils.ToastUtils; + +/** + * Created by mike on 13/01/17. + */ + +public class TempTargetRangeFragment extends Fragment implements View.OnClickListener, FragmentBase { + + private static TempTargetRangePlugin tempTargetRangePlugin = new TempTargetRangePlugin(); + + public static TempTargetRangePlugin getPlugin() { + return tempTargetRangePlugin; + } + + RecyclerView recyclerView; + LinearLayoutManager llm; + Button refreshFromNS; + + Context context; + + public class RecyclerViewAdapter extends RecyclerView.Adapter { + + List tempTargetList; + + RecyclerViewAdapter(List TempTargetList) { + this.tempTargetList = TempTargetList; + } + + @Override + public TempTargetsViewHolder onCreateViewHolder(ViewGroup viewGroup, int viewType) { + View v = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.temptargetrange_item, viewGroup, false); + TempTargetsViewHolder TempTargetsViewHolder = new TempTargetsViewHolder(v); + return TempTargetsViewHolder; + } + + @Override + public void onBindViewHolder(TempTargetsViewHolder holder, int position) { + NSProfile profile = ConfigBuilderPlugin.getActiveProfile().getProfile(); + if (profile == null) return; + TempTarget tempTarget = tempTargetList.get(position); + holder.date.setText(DateUtil.dateAndTimeString(tempTarget.timeStart) + " - " + DateUtil.timeString(tempTargetList.get(position).getPlannedTimeEnd())); + holder.duration.setText(DecimalFormatter.to0Decimal(tempTarget.duration) + " min"); + holder.low.setText(tempTarget.lowValueToUnitsToString(profile.getUnits())); + holder.high.setText(tempTarget.highValueToUnitsToString(profile.getUnits())); + holder.reason.setText(tempTarget.reason); + if (tempTarget.isInProgress()) + holder.dateLinearLayout.setBackgroundColor(MainApp.instance().getResources().getColor(R.color.colorInProgress)); + else + holder.dateLinearLayout.setBackgroundColor(MainApp.instance().getResources().getColor(R.color.cardColorBackground)); + holder.remove.setTag(tempTarget); + } + + @Override + public int getItemCount() { + return tempTargetList.size(); + } + + @Override + public void onAttachedToRecyclerView(RecyclerView recyclerView) { + super.onAttachedToRecyclerView(recyclerView); + } + + public class TempTargetsViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener { + CardView cv; + TextView date; + TextView duration; + TextView low; + TextView high; + TextView reason; + TextView remove; + LinearLayout dateLinearLayout; + + TempTargetsViewHolder(View itemView) { + super(itemView); + cv = (CardView) itemView.findViewById(R.id.temptargetrange_cardview); + date = (TextView) itemView.findViewById(R.id.temptargetrange_date); + duration = (TextView) itemView.findViewById(R.id.temptargetrange_duration); + low = (TextView) itemView.findViewById(R.id.temptargetrange_low); + high = (TextView) itemView.findViewById(R.id.temptargetrange_high); + reason = (TextView) itemView.findViewById(R.id.temptargetrange_reason); + remove = (TextView) itemView.findViewById(R.id.temptargetrange_remove); + remove.setOnClickListener(this); + remove.setPaintFlags(remove.getPaintFlags() | Paint.UNDERLINE_TEXT_FLAG); + dateLinearLayout = (LinearLayout) itemView.findViewById(R.id.temptargetrange_datelinearlayout); + } + + @Override + public void onClick(View v) { + final TempTarget tempTarget = (TempTarget) v.getTag(); + final Context finalContext = context; + switch (v.getId()) { + case R.id.temptargetrange_remove: + final String _id = tempTarget._id; + if (_id != null && !_id.equals("")) { + AlertDialog.Builder builder = new AlertDialog.Builder(context); + builder.setTitle(MainApp.sResources.getString(R.string.confirmation)); + builder.setMessage(MainApp.sResources.getString(R.string.removerecord) + "\n" + _id); + builder.setPositiveButton(MainApp.sResources.getString(R.string.ok), new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, int id) { + MainApp.getConfigBuilder().removeCareportalEntryFromNS(_id); + try { + Dao daoTempTargets = MainApp.getDbHelper().getDaoTempTargets(); + daoTempTargets.delete(tempTarget); + MainApp.bus().post(new EventTempTargetRangeChange()); + } catch (SQLException e) { + e.printStackTrace(); + } + } + }); + 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.temptargetrange_fragment, container, false); + + recyclerView = (RecyclerView) view.findViewById(R.id.temptargetrange_recyclerview); + recyclerView.setHasFixedSize(true); + llm = new LinearLayoutManager(view.getContext()); + recyclerView.setLayoutManager(llm); + + RecyclerViewAdapter adapter = new RecyclerViewAdapter(tempTargetRangePlugin.getList()); + recyclerView.setAdapter(adapter); + + refreshFromNS = (Button) view.findViewById(R.id.temptargetrange_refreshfromnightscout); + refreshFromNS.setOnClickListener(this); + + context = getContext(); + + updateGUI(); + return view; + } + + @Override + public void onClick(View view) { + switch (view.getId()) { + case R.id.temptargetrange_refreshfromnightscout: + SharedPreferences SP = PreferenceManager.getDefaultSharedPreferences(getContext()); + boolean nsUploadOnly = SP.getBoolean("ns_upload_only", false); + if(nsUploadOnly){ + ToastUtils.showToastInUiThread(getContext(),this.getContext().getString(R.string.ns_upload_only_enabled)); + } else { + AlertDialog.Builder builder = new AlertDialog.Builder(this.getContext()); + builder.setTitle(this.getContext().getString(R.string.confirmation)); + builder.setMessage(this.getContext().getString(R.string.refreshtemptargetsfromnightscout)); + builder.setPositiveButton(this.getContext().getString(R.string.ok), new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, int id) { + MainApp.getDbHelper().resetTempTargets(); + tempTargetRangePlugin.initializeData(); + updateGUI(); + Intent restartNSClient = new Intent(Intents.ACTION_RESTART); + MainApp.instance().getApplicationContext().sendBroadcast(restartNSClient); + } + }); + builder.setNegativeButton(this.getContext().getString(R.string.cancel), null); + builder.show(); + } + break; + } + } + + @Override + public void onPause() { + super.onPause(); + MainApp.bus().unregister(this); + } + + @Override + public void onResume() { + super.onResume(); + MainApp.bus().register(this); + } + + @Subscribe + public void onStatusEvent(final EventTempTargetRangeChange ev) { + updateGUI(); + } + + void updateGUI() { + Activity activity = getActivity(); + if (activity != null) + activity.runOnUiThread(new Runnable() { + @Override + public void run() { + recyclerView.swapAdapter(new RecyclerViewAdapter(tempTargetRangePlugin.getList()), false); + } + }); + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/TempTargetRange/TempTargetRangePlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/TempTargetRange/TempTargetRangePlugin.java new file mode 100644 index 0000000000..8b7068d94f --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/TempTargetRange/TempTargetRangePlugin.java @@ -0,0 +1,100 @@ +package info.nightscout.androidaps.plugins.TempTargetRange; + +import android.support.annotation.Nullable; + +import com.squareup.otto.Subscribe; + +import java.util.Date; +import java.util.List; + +import info.nightscout.androidaps.MainApp; +import info.nightscout.androidaps.R; +import info.nightscout.androidaps.db.TempTarget; +import info.nightscout.androidaps.interfaces.PluginBase; +import info.nightscout.androidaps.plugins.TempTargetRange.events.EventTempTargetRangeChange; + +/** + * Created by mike on 13/01/17. + */ + +public class TempTargetRangePlugin implements PluginBase { + + static boolean fragmentEnabled = true; + static boolean fragmentVisible = true; + + private static List tempTargets; + + TempTargetRangePlugin() { + initializeData(); + MainApp.bus().register(this); + } + + @Override + public int getType() { + return PluginBase.GENERAL; + } + + @Override + public String getFragmentClass() { + return TempTargetRangeFragment.class.getName(); + } + + @Override + public String getName() { + return MainApp.sResources.getString(R.string.temptargetrange); + } + + @Override + public boolean isEnabled(int type) { + return type == GENERAL && fragmentEnabled; + } + + @Override + public boolean isVisibleInTabs(int type) { + return type == GENERAL && fragmentVisible; + } + + @Override + public boolean canBeHidden(int type) { + return true; + } + + @Override + public void setFragmentEnabled(int type, boolean fragmentEnabled) { + if (type == GENERAL) { + this.fragmentEnabled = fragmentEnabled; + } + } + + @Override + public void setFragmentVisible(int type, boolean fragmentVisible) { + if (type == GENERAL) this.fragmentVisible = fragmentVisible; + } + + public static boolean isEnabled() { + return fragmentEnabled; + } + + @Subscribe + public void onStatusEvent(final EventTempTargetRangeChange ev) { + initializeData(); + } + + public void initializeData() { + long fromMills = (long) (new Date().getTime() - 60 * 60 * 1000L * 24); + tempTargets = MainApp.getDbHelper().getTemptargetsDataFromTime(fromMills, false); + } + + public List getList() { + return tempTargets; + } + + @Nullable + public TempTarget getTempTargetInProgress(long time) { + for (int i = tempTargets.size() - 1; i >= 0; i--) { + if (tempTargets.get(i).timeStart.getTime() > time) continue; + if (tempTargets.get(i).getPlannedTimeEnd().getTime() >= time) return tempTargets.get(i); + } + return null; + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/TempTargetRange/events/EventTempTargetRangeChange.java b/app/src/main/java/info/nightscout/androidaps/plugins/TempTargetRange/events/EventTempTargetRangeChange.java new file mode 100644 index 0000000000..8d5f537fec --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/TempTargetRange/events/EventTempTargetRangeChange.java @@ -0,0 +1,8 @@ +package info.nightscout.androidaps.plugins.TempTargetRange.events; + +/** + * Created by mike on 13.01.2017. + */ + +public class EventTempTargetRangeChange { +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Treatments/TreatmentsFragment.java b/app/src/main/java/info/nightscout/androidaps/plugins/Treatments/TreatmentsFragment.java index 818d33f245..7257207e74 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/Treatments/TreatmentsFragment.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/Treatments/TreatmentsFragment.java @@ -157,7 +157,7 @@ public class TreatmentsFragment extends Fragment implements View.OnClickListener } else { AlertDialog.Builder builder = new AlertDialog.Builder(this.getContext()); builder.setTitle(this.getContext().getString(R.string.confirmation)); - builder.setMessage(this.getContext().getString(R.string.refreshfromnightscout)); + builder.setMessage(this.getContext().getString(R.string.refreshtreatmentsfromnightscout)); builder.setPositiveButton(this.getContext().getString(R.string.ok), new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int id) { MainApp.getDbHelper().resetTreatments(); diff --git a/app/src/main/java/info/nightscout/client/data/DbLogger.java b/app/src/main/java/info/nightscout/client/data/DbLogger.java index af2345a5b0..3695d5e735 100644 --- a/app/src/main/java/info/nightscout/client/data/DbLogger.java +++ b/app/src/main/java/info/nightscout/client/data/DbLogger.java @@ -26,4 +26,14 @@ public class DbLogger { } else if (Config.logNSUpload) log.debug("DBADD dbAdd " + q.size() + " receivers " + data); } + + public static void dbRemove(Intent intent, String data, Class sender) { + Logger log = LoggerFactory.getLogger(sender); + List q = MainApp.instance().getApplicationContext().getPackageManager().queryBroadcastReceivers(intent, 0); + if (q.size() < 1) { + ToastUtils.showToastInUiThread(MainApp.instance().getApplicationContext(),MainApp.sResources.getString(R.string.nsclientnotinstalled)); + log.error("DBREMOVE No receivers"); + } else if (Config.logNSUpload) + log.debug("DBREMOVE dbRemove " + q.size() + " receivers " + data); + } } diff --git a/app/src/main/java/info/nightscout/utils/Translator.java b/app/src/main/java/info/nightscout/utils/Translator.java index 93194655d7..75ee881c21 100644 --- a/app/src/main/java/info/nightscout/utils/Translator.java +++ b/app/src/main/java/info/nightscout/utils/Translator.java @@ -56,7 +56,7 @@ public class Translator { case "Sensor": return MainApp.sResources.getString(R.string.glucosetype_sensor); case "Manual": - return MainApp.sResources.getString(R.string.glucosetype_manual); + return MainApp.sResources.getString(R.string.manual); } return text; } diff --git a/app/src/main/res/drawable-mdpi-v11/temptargetborder.xml b/app/src/main/res/drawable-mdpi-v11/temptargetborder.xml new file mode 100644 index 0000000000..8dc85926e2 --- /dev/null +++ b/app/src/main/res/drawable-mdpi-v11/temptargetborder.xml @@ -0,0 +1,7 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/actions_fragment.xml b/app/src/main/res/layout/actions_fragment.xml index 071fabb527..78b6fa00ae 100644 --- a/app/src/main/res/layout/actions_fragment.xml +++ b/app/src/main/res/layout/actions_fragment.xml @@ -22,6 +22,19 @@ android:text="@string/careportal_profileswitch" android:textColor="@color/colorProfileSwitchButton" /> +