diff --git a/ISSUE_TEMPLATE.md b/ISSUE_TEMPLATE.md
index db66ffec38..2465b9d9a5 100644
--- a/ISSUE_TEMPLATE.md
+++ b/ISSUE_TEMPLATE.md
@@ -1,10 +1,10 @@
Reporting bugs
--------------
-- Note the precise time the problem occurred and describe the circumstances and steps that caused
+- **Note the precise time the problem occurred** and describe the circumstances and steps that caused
the problem
- Note the Build version (found in the About dialog in the app, when pressing the three dots in the
upper-right corner).
- Obtain the app's log files, which can be found on the phone in
_/storage/emulated/0/Android/data/info.nightscout.androidaps/_
See https://github.com/MilosKozak/AndroidAPS/wiki/Accessing-logfiles
-- Open an issue at https://github.com/MilosKozak/AndroidAPS/issues/new
\ No newline at end of file
+- Open an issue at https://github.com/MilosKozak/AndroidAPS/issues/new
diff --git a/README.md b/README.md
index deeea159bc..d1e1e8a47c 100644
--- a/README.md
+++ b/README.md
@@ -1,6 +1,6 @@
# AndroidAPS
-* Check the wiki: https://github.com/MilosKozak/AndroidAPS/wiki
+* Check the wiki: http://wiki.androidaps.org
* Everyone who’s been looping with AndroidAPS needs to fill out the form after 3 days of looping https://docs.google.com/forms/d/14KcMjlINPMJHVt28MDRupa4sz4DDIooI4SrW0P3HSN8/viewform?c=0&w=1
[![Gitter](https://badges.gitter.im/MilosKozak/AndroidAPS.svg)](https://gitter.im/MilosKozak/AndroidAPS?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
diff --git a/app/build.gradle b/app/build.gradle
index f56f727cd4..e65d5ab4b8 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -63,7 +63,7 @@ android {
targetSdkVersion 25
multiDexEnabled true
versionCode 1500
- version "2.0g-dev"
+ version "2.0"
buildConfigField "String", "VERSION", '"' + version + '"'
buildConfigField "String", "BUILDVERSION", '"' + generateGitBuild() + '-' + generateDate() + '"'
buildConfigField "String", "HEAD", '"' + generateGitBuild() + '"'
@@ -198,6 +198,7 @@ dependencies {
implementation "com.google.android.gms:play-services-wearable:7.5.0"
implementation(name: "android-edittext-validator-v1.3.4-mod", ext: "aar")
implementation(name: "sightparser-release", ext: "aar")
+ implementation 'com.madgag.spongycastle:core:1.58.0.0'
implementation("com.google.android:flexbox:0.3.0") {
exclude group: "com.android.support"
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index ea96e1f18c..a62e80413a 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -12,6 +12,7 @@
+
@@ -31,10 +32,13 @@
android:name=".MainApp"
android:allowBackup="true"
android:icon="${appIcon}"
- android:roundIcon="${appIconRound}"
android:label="@string/app_name"
+ android:roundIcon="${appIconRound}"
android:supportsRtl="true"
android:theme="@style/AppTheme.NoActionBar">
+
@@ -181,6 +185,8 @@
android:exported="false" />
+
+
+ android:label="@string/title_activity_setup_wizard"
+ android:theme="@style/AppTheme.NoActionBar" />
-
+
+
+
\ No newline at end of file
diff --git a/app/src/main/assets/OpenAPSSMB/basal-set-temp.js b/app/src/main/assets/OpenAPSSMB/basal-set-temp.js
index 1686ea2c47..9cb932022c 100644
--- a/app/src/main/assets/OpenAPSSMB/basal-set-temp.js
+++ b/app/src/main/assets/OpenAPSSMB/basal-set-temp.js
@@ -9,33 +9,32 @@ var tempBasalFunctions = {};
tempBasalFunctions.getMaxSafeBasal = function getMaxSafeBasal(profile) {
- var max_daily_safety_multiplier = (isNaN(profile.max_daily_safety_multiplier) || profile.max_daily_safety_multiplier == null) ? 3 : profile.max_daily_safety_multiplier;
- var current_basal_safety_multiplier = (isNaN(profile.current_basal_safety_multiplier) || profile.current_basal_safety_multiplier == null) ? 4 : profile.current_basal_safety_multiplier;
-
- return Math.min(profile.max_basal, max_daily_safety_multiplier * profile.max_daily_basal, current_basal_safety_multiplier * profile.current_basal);
+ var max_daily_safety_multiplier = (isNaN(profile.max_daily_safety_multiplier) || profile.max_daily_safety_multiplier == null) ? 3 : profile.max_daily_safety_multiplier;
+ var current_basal_safety_multiplier = (isNaN(profile.current_basal_safety_multiplier) || profile.current_basal_safety_multiplier == null) ? 4 : profile.current_basal_safety_multiplier;
+
+ return Math.min(profile.max_basal, max_daily_safety_multiplier * profile.max_daily_basal, current_basal_safety_multiplier * profile.current_basal);
};
tempBasalFunctions.setTempBasal = function setTempBasal(rate, duration, profile, rT, currenttemp) {
//var maxSafeBasal = Math.min(profile.max_basal, 3 * profile.max_daily_basal, 4 * profile.current_basal);
-
+
var maxSafeBasal = tempBasalFunctions.getMaxSafeBasal(profile);
-var round_basal = require('./round-basal');
-
- if (rate < 0) {
- rate = 0;
- } // if >30m @ 0 required, zero temp will be extended to 30m instead
- else if (rate > maxSafeBasal) {
- rate = maxSafeBasal;
+ var round_basal = require('./round-basal');
+
+ if (rate < 0) {
+ rate = 0;
+ } else if (rate > maxSafeBasal) {
+ rate = maxSafeBasal;
}
var suggestedRate = round_basal(rate, profile);
- if (typeof(currenttemp) !== 'undefined' && typeof(currenttemp.duration) !== 'undefined' && typeof(currenttemp.rate) !== 'undefined' && currenttemp.duration > (duration-10) && currenttemp.duration <= 120 && suggestedRate <= currenttemp.rate * 1.2 && suggestedRate >= currenttemp.rate * 0.8) {
+ if (typeof(currenttemp) !== 'undefined' && typeof(currenttemp.duration) !== 'undefined' && typeof(currenttemp.rate) !== 'undefined' && currenttemp.duration > (duration-10) && currenttemp.duration <= 120 && suggestedRate <= currenttemp.rate * 1.2 && suggestedRate >= currenttemp.rate * 0.8 && duration > 0 ) {
rT.reason += " "+currenttemp.duration+"m left and " + currenttemp.rate + " ~ req " + suggestedRate + "U/hr: no temp required";
return rT;
}
if (suggestedRate === profile.current_basal) {
- if (profile.skip_neutral_temps) {
+ if (profile.skip_neutral_temps === true) {
if (typeof(currenttemp) !== 'undefined' && typeof(currenttemp.duration) !== 'undefined' && currenttemp.duration > 0) {
reason(rT, 'Suggested rate is same as profile rate, a temp basal is active, canceling current temp');
rT.duration = 0;
@@ -58,4 +57,4 @@ var round_basal = require('./round-basal');
}
};
-module.exports = tempBasalFunctions;
\ No newline at end of file
+module.exports = tempBasalFunctions;
diff --git a/app/src/main/java/info/nightscout/androidaps/MainActivity.java b/app/src/main/java/info/nightscout/androidaps/MainActivity.java
index 6c3d6f9820..844f218803 100644
--- a/app/src/main/java/info/nightscout/androidaps/MainActivity.java
+++ b/app/src/main/java/info/nightscout/androidaps/MainActivity.java
@@ -182,7 +182,7 @@ public class MainActivity extends AppCompatActivity {
@Subscribe
public void onStatusEvent(final EventRefreshGui ev) {
- String lang = SP.getString("language", "en");
+ String lang = SP.getString(R.string.key_language, "en");
LocaleHelper.setLocale(getApplicationContext(), lang);
runOnUiThread(() -> {
if (ev.recreate) {
@@ -326,6 +326,7 @@ public class MainActivity extends AppCompatActivity {
case AndroidPermission.CASE_LOCATION:
case AndroidPermission.CASE_SMS:
case AndroidPermission.CASE_BATTERY:
+ case AndroidPermission.CASE_PHONESTATE:
break;
}
}
diff --git a/app/src/main/java/info/nightscout/androidaps/MainApp.java b/app/src/main/java/info/nightscout/androidaps/MainApp.java
index a540359860..4fe8804ead 100644
--- a/app/src/main/java/info/nightscout/androidaps/MainApp.java
+++ b/app/src/main/java/info/nightscout/androidaps/MainApp.java
@@ -59,6 +59,7 @@ import info.nightscout.androidaps.plugins.PumpDanaRKorean.DanaRKoreanPlugin;
import info.nightscout.androidaps.plugins.PumpDanaRS.DanaRSPlugin;
import info.nightscout.androidaps.plugins.PumpDanaRv2.DanaRv2Plugin;
import info.nightscout.androidaps.plugins.PumpInsight.InsightPlugin;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.LocalInsightPlugin;
import info.nightscout.androidaps.plugins.PumpMDI.MDIPlugin;
import info.nightscout.androidaps.plugins.PumpVirtual.VirtualPumpPlugin;
import info.nightscout.androidaps.plugins.Sensitivity.SensitivityAAPSPlugin;
@@ -158,9 +159,10 @@ public class MainApp extends Application {
if (Config.PUMPDRIVERS) pluginsList.add(DanaRKoreanPlugin.getPlugin());
if (Config.PUMPDRIVERS) pluginsList.add(DanaRv2Plugin.getPlugin());
if (Config.PUMPDRIVERS) pluginsList.add(DanaRSPlugin.getPlugin());
+ if (Config.PUMPDRIVERS && engineeringMode) pluginsList.add(LocalInsightPlugin.getInstance());
pluginsList.add(CareportalPlugin.getPlugin());
- if (Config.PUMPDRIVERS && engineeringMode)
- pluginsList.add(InsightPlugin.getPlugin()); // <-- Enable Insight plugin here
+ /*if (Config.PUMPDRIVERS && engineeringMode)
+ pluginsList.add(InsightPlugin.getPlugin());*/
if (Config.PUMPDRIVERS) pluginsList.add(ComboPlugin.getPlugin());
if (Config.MDI) pluginsList.add(MDIPlugin.getPlugin());
pluginsList.add(VirtualPumpPlugin.getPlugin());
diff --git a/app/src/main/java/info/nightscout/androidaps/activities/PreferencesActivity.java b/app/src/main/java/info/nightscout/androidaps/activities/PreferencesActivity.java
index 0cf891e8cd..eacb07f164 100644
--- a/app/src/main/java/info/nightscout/androidaps/activities/PreferencesActivity.java
+++ b/app/src/main/java/info/nightscout/androidaps/activities/PreferencesActivity.java
@@ -9,6 +9,7 @@ import android.preference.PreferenceActivity;
import android.preference.PreferenceFragment;
import android.preference.PreferenceGroup;
import android.preference.PreferenceManager;
+import android.preference.PreferenceScreen;
import android.text.TextUtils;
import info.nightscout.androidaps.Config;
@@ -192,6 +193,17 @@ public class PreferencesActivity extends PreferenceActivity implements SharedPre
addPreferencesFromResourceIfEnabled(StatuslinePlugin.getPlugin(), PluginType.GENERAL);
}
+ if (Config.NSCLIENT) {
+ PreferenceScreen scrnAdvancedSettings = (PreferenceScreen)findPreference(getString(R.string.key_advancedsettings));
+ if (scrnAdvancedSettings != null) {
+ scrnAdvancedSettings.removePreference(getPreference(getString(R.string.key_statuslights_res_warning)));
+ scrnAdvancedSettings.removePreference(getPreference(getString(R.string.key_statuslights_res_critical)));
+ scrnAdvancedSettings.removePreference(getPreference(getString(R.string.key_statuslights_bat_warning)));
+ scrnAdvancedSettings.removePreference(getPreference(getString(R.string.key_statuslights_bat_critical)));
+ scrnAdvancedSettings.removePreference(getPreference(getString(R.string.key_show_statuslights)));
+ }
+ }
+
initSummary(getPreferenceScreen());
}
diff --git a/app/src/main/java/info/nightscout/androidaps/data/ConstraintChecker.java b/app/src/main/java/info/nightscout/androidaps/data/ConstraintChecker.java
index fc37f5f2a5..ceb85c6967 100644
--- a/app/src/main/java/info/nightscout/androidaps/data/ConstraintChecker.java
+++ b/app/src/main/java/info/nightscout/androidaps/data/ConstraintChecker.java
@@ -42,6 +42,10 @@ public class ConstraintChecker implements ConstraintsInterface {
return isSMBModeEnabled(new Constraint<>(true));
}
+ public Constraint isUAMEnabled() {
+ return isUAMEnabled(new Constraint<>(true));
+ }
+
public Constraint isAdvancedFilteringEnabled() {
return isAdvancedFilteringEnabled(new Constraint<>(true));
}
@@ -130,6 +134,18 @@ public class ConstraintChecker implements ConstraintsInterface {
return value;
}
+ @Override
+ public Constraint isUAMEnabled(Constraint value) {
+
+ ArrayList constraintsPlugins = mainApp.getSpecificPluginsListByInterface(ConstraintsInterface.class);
+ for (PluginBase p : constraintsPlugins) {
+ ConstraintsInterface constraint = (ConstraintsInterface) p;
+ if (!p.isEnabled(PluginType.CONSTRAINTS)) continue;
+ constraint.isUAMEnabled(value);
+ }
+ return value;
+ }
+
@Override
public Constraint isAdvancedFilteringEnabled(Constraint value) {
ArrayList constraintsPlugins = mainApp.getSpecificPluginsListByInterface(ConstraintsInterface.class);
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 8d78ca19b6..e6df495c40 100644
--- a/app/src/main/java/info/nightscout/androidaps/data/Profile.java
+++ b/app/src/main/java/info/nightscout/androidaps/data/Profile.java
@@ -23,6 +23,7 @@ import info.nightscout.androidaps.plugins.Overview.notifications.Notification;
import info.nightscout.utils.DateUtil;
import info.nightscout.utils.DecimalFormatter;
import info.nightscout.utils.FabricPrivacy;
+import info.nightscout.utils.MidnightTime;
public class Profile {
private static Logger log = LoggerFactory.getLogger(Profile.class);
@@ -381,7 +382,7 @@ public class Profile {
}
public double getIsf() {
- return getIsfTimeFromMidnight(secondsFromMidnight(System.currentTimeMillis()));
+ return getIsfTimeFromMidnight(secondsFromMidnight());
}
public double getIsf(long time) {
@@ -397,11 +398,11 @@ public class Profile {
public String getIsfList() {
if (isf_v == null)
isf_v = convertToSparseArray(isf);
- return getValuesList(isf_v, null, new DecimalFormat("0.0"), getUnits() + "/U");
+ return getValuesList(isf_v, null, new DecimalFormat("0.0"), getUnits() + MainApp.gs(R.string.profile_per_unit));
}
public double getIc() {
- return getIcTimeFromMidnight(secondsFromMidnight(System.currentTimeMillis()));
+ return getIcTimeFromMidnight(secondsFromMidnight());
}
public double getIc(long time) {
@@ -417,11 +418,11 @@ public class Profile {
public String getIcList() {
if (ic_v == null)
ic_v = convertToSparseArray(ic);
- return getValuesList(ic_v, null, new DecimalFormat("0.0"), "g/U");
+ return getValuesList(ic_v, null, new DecimalFormat("0.0"), MainApp.gs(R.string.profile_carbs_per_unit));
}
public double getBasal() {
- return getBasalTimeFromMidnight(secondsFromMidnight(System.currentTimeMillis()));
+ return getBasalTimeFromMidnight(secondsFromMidnight());
}
public double getBasal(long time) {
@@ -438,7 +439,7 @@ public class Profile {
public String getBasalList() {
if (basal_v == null)
basal_v = convertToSparseArray(basal);
- return getValuesList(basal_v, null, new DecimalFormat("0.00"), "U/h");
+ return getValuesList(basal_v, null, new DecimalFormat("0.00"), MainApp.gs(R.string.profile_ins_units_per_hout));
}
public class BasalValue {
@@ -465,7 +466,7 @@ public class Profile {
}
public double getTarget() {
- return getTarget(secondsFromMidnight(System.currentTimeMillis()));
+ return getTarget(secondsFromMidnight());
}
protected double getTarget(int timeAsSeconds) {
@@ -473,7 +474,7 @@ public class Profile {
}
public double getTargetLow() {
- return getTargetLowTimeFromMidnight(secondsFromMidnight(System.currentTimeMillis()));
+ return getTargetLowTimeFromMidnight(secondsFromMidnight());
}
public double getTargetLow(long time) {
@@ -487,7 +488,7 @@ public class Profile {
}
public double getTargetHigh() {
- return getTargetHighTimeFromMidnight(secondsFromMidnight(System.currentTimeMillis()));
+ return getTargetHighTimeFromMidnight(secondsFromMidnight());
}
public double getTargetHigh(long time) {
@@ -518,24 +519,13 @@ public class Profile {
}
public static int secondsFromMidnight() {
- Calendar c = Calendar.getInstance();
- long now = c.getTimeInMillis();
- c.set(Calendar.HOUR_OF_DAY, 0);
- c.set(Calendar.MINUTE, 0);
- c.set(Calendar.SECOND, 0);
- c.set(Calendar.MILLISECOND, 0);
- long passed = now - c.getTimeInMillis();
+ long passed = DateUtil.now() - MidnightTime.calc();
return (int) (passed / 1000);
}
public static int secondsFromMidnight(long date) {
- Calendar c = Calendar.getInstance();
- c.setTimeInMillis(date);
- c.set(Calendar.HOUR_OF_DAY, 0);
- c.set(Calendar.MINUTE, 0);
- c.set(Calendar.SECOND, 0);
- c.set(Calendar.MILLISECOND, 0);
- long passed = date - c.getTimeInMillis();
+ long midnight = MidnightTime.calc(date);
+ long passed = date - midnight;
return (int) (passed / 1000);
}
diff --git a/app/src/main/java/info/nightscout/androidaps/db/BgReading.java b/app/src/main/java/info/nightscout/androidaps/db/BgReading.java
index a2e06d0bb1..3b5963b83b 100644
--- a/app/src/main/java/info/nightscout/androidaps/db/BgReading.java
+++ b/app/src/main/java/info/nightscout/androidaps/db/BgReading.java
@@ -220,14 +220,8 @@ public class BgReading implements DataPointWithLabelInterface {
@Override
public int getColor() {
String units = ProfileFunctions.getInstance().getProfileUnits();
- Double lowLine = SP.getDouble("low_mark", 0d);
- Double highLine = SP.getDouble("high_mark", 0d);
- if (lowLine < 1) {
- lowLine = Profile.fromMgdlToUnits(OverviewPlugin.bgTargetLow, units);
- }
- if (highLine < 1) {
- highLine = Profile.fromMgdlToUnits(OverviewPlugin.bgTargetHigh, units);
- }
+ Double lowLine = OverviewPlugin.getPlugin().determineLowLine(units);
+ Double highLine = OverviewPlugin.getPlugin().determineHighLine(units);
int color = MainApp.gc(R.color.inrange);
if (isPrediction())
return getPredectionColor();
diff --git a/app/src/main/java/info/nightscout/androidaps/db/CareportalEvent.java b/app/src/main/java/info/nightscout/androidaps/db/CareportalEvent.java
index 60c7553cc3..92a2b221ff 100644
--- a/app/src/main/java/info/nightscout/androidaps/db/CareportalEvent.java
+++ b/app/src/main/java/info/nightscout/androidaps/db/CareportalEvent.java
@@ -90,8 +90,8 @@ public class CareportalEvent implements DataPointWithLabelInterface, Interval {
return System.currentTimeMillis() - date;
}
- public long getHoursFromStart() {
- return (System.currentTimeMillis() - date) / (60 * 60 * 1000);
+ public double getHoursFromStart() {
+ return (System.currentTimeMillis() - date) / (60 * 60 * 1000.0);
}
public String age() {
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 89eb892f05..bd45ab7434 100644
--- a/app/src/main/java/info/nightscout/androidaps/db/DatabaseHelper.java
+++ b/app/src/main/java/info/nightscout/androidaps/db/DatabaseHelper.java
@@ -50,6 +50,9 @@ import info.nightscout.androidaps.plugins.IobCobCalculator.events.EventNewHistor
import info.nightscout.androidaps.plugins.NSClientInternal.NSUpload;
import info.nightscout.androidaps.plugins.PumpDanaR.activities.DanaRNSHistorySync;
import info.nightscout.androidaps.plugins.PumpDanaR.comm.RecordTypes;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.database.InsightBolusID;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.database.InsightHistoryOffset;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.database.InsightPumpID;
import info.nightscout.androidaps.plugins.PumpVirtual.VirtualPumpPlugin;
import info.nightscout.utils.JsonHelper;
import info.nightscout.utils.PercentageSplitter;
@@ -76,8 +79,11 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
public static final String DATABASE_CAREPORTALEVENTS = "CareportalEvents";
public static final String DATABASE_PROFILESWITCHES = "ProfileSwitches";
public static final String DATABASE_TDDS = "TDDs";
+ public static final String DATABASE_INSIGHT_HISTORY_OFFSETS = "InsightHistoryOffsets";
+ public static final String DATABASE_INSIGHT_BOLUS_IDS = "InsightBolusIDs";
+ public static final String DATABASE_INSIGHT_PUMP_IDS = "InsightPumpIDs";
- private static final int DATABASE_VERSION = 9;
+ private static final int DATABASE_VERSION = 10;
public static Long earliestDataChange = null;
@@ -122,6 +128,9 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
TableUtils.createTableIfNotExists(connectionSource, CareportalEvent.class);
TableUtils.createTableIfNotExists(connectionSource, ProfileSwitch.class);
TableUtils.createTableIfNotExists(connectionSource, TDD.class);
+ TableUtils.createTableIfNotExists(connectionSource, InsightHistoryOffset.class);
+ TableUtils.createTableIfNotExists(connectionSource, InsightBolusID.class);
+ TableUtils.createTableIfNotExists(connectionSource, InsightPumpID.class);
} catch (SQLException e) {
log.error("Can't create database", e);
throw new RuntimeException(e);
@@ -138,6 +147,10 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
log.debug("Upgrading database from v7 to v8");
} else if (oldVersion == 8 && newVersion == 9) {
log.debug("Upgrading database from v8 to v9");
+ } else if (oldVersion == 9 && newVersion == 10) {
+ TableUtils.createTableIfNotExists(connectionSource, InsightHistoryOffset.class);
+ TableUtils.createTableIfNotExists(connectionSource, InsightBolusID.class);
+ TableUtils.createTableIfNotExists(connectionSource, InsightPumpID.class);
} else {
log.info(DatabaseHelper.class.getName(), "onUpgrade");
TableUtils.dropTable(connectionSource, TempTarget.class, true);
@@ -156,6 +169,12 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
}
}
+ @Override
+ public void onDowngrade(SQLiteDatabase db, int oldVersion, int newVersion) {
+ log.info("Do nothing for downgrading...");
+ log.debug("oldVersion: {}, newVersion: {}", oldVersion, newVersion);
+ }
+
public int getOldVersion() {
return oldVersion;
}
@@ -321,6 +340,18 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
return getDao(ProfileSwitch.class);
}
+ private Dao getDaoInsightPumpID() throws SQLException {
+ return getDao(InsightPumpID.class);
+ }
+
+ private Dao getDaoInsightBolusID() throws SQLException {
+ return getDao(InsightBolusID.class);
+ }
+
+ private Dao getDaoInsightHistoryOffset() throws SQLException {
+ return getDao(InsightHistoryOffset.class);
+ }
+
public static long roundDateToSec(long date) {
long rounded = date - date % 1000;
if (rounded != date)
@@ -397,7 +428,7 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
QueryBuilder queryBuilder = daoBgReadings.queryBuilder();
queryBuilder.orderBy("date", false);
queryBuilder.limit(1L);
- queryBuilder.where().gt("value", 38).and().eq("isValid", true);
+ queryBuilder.where().ge("value", 39).and().eq("isValid", true);
PreparedQuery preparedQuery = queryBuilder.prepare();
bgList = daoBgReadings.query(preparedQuery);
@@ -435,7 +466,7 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
QueryBuilder queryBuilder = daoBgreadings.queryBuilder();
queryBuilder.orderBy("date", ascending);
Where where = queryBuilder.where();
- where.ge("date", mills).and().gt("value", 38).and().eq("isValid", true);
+ where.ge("date", mills).and().ge("value", 39).and().eq("isValid", true);
PreparedQuery preparedQuery = queryBuilder.prepare();
bgReadings = daoBgreadings.query(preparedQuery);
return bgReadings;
@@ -452,7 +483,7 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
QueryBuilder queryBuilder = daoBgreadings.queryBuilder();
queryBuilder.orderBy("date", ascending);
Where where = queryBuilder.where();
- where.between("date", start, end).and().gt("value", 38).and().eq("isValid", true);
+ where.between("date", start, end).and().ge("value", 39).and().eq("isValid", true);
PreparedQuery preparedQuery = queryBuilder.prepare();
bgReadings = daoBgreadings.query(preparedQuery);
return bgReadings;
@@ -1143,6 +1174,17 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
return false;
}
+ public ExtendedBolus getExtendedBolusByPumpId(long pumpId) {
+ try {
+ return getDaoExtendedBolus().queryBuilder()
+ .where().eq("pumpId", pumpId)
+ .queryForFirst();
+ } catch (SQLException e) {
+ log.error("Unhandled exception", e);
+ }
+ return null;
+ }
+
public void delete(ExtendedBolus extendedBolus) {
try {
getDaoExtendedBolus().delete(extendedBolus);
@@ -1650,5 +1692,67 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
return null;
}
+ // ---------------- Insight history handling ---------------
+
+ public void createOrUpdate(InsightHistoryOffset offset) {
+ try {
+ getDaoInsightHistoryOffset().createOrUpdate(offset);
+ } catch (SQLException e) {
+ log.error("Unhandled exception", e);
+ }
+ }
+
+ public InsightHistoryOffset getInsightHistoryOffset(String pumpSerial) {
+ try {
+ return getDaoInsightHistoryOffset().queryForId(pumpSerial);
+ } catch (SQLException e) {
+ log.error("Unhandled exception", e);
+ }
+ return null;
+ }
+
+ public void createOrUpdate(InsightBolusID bolusID) {
+ try {
+ getDaoInsightBolusID().createOrUpdate(bolusID);
+ } catch (SQLException e) {
+ log.error("Unhandled exception", e);
+ }
+ }
+
+ public InsightBolusID getInsightBolusID(String pumpSerial, int bolusID, long timestamp) {
+ try {
+ return getDaoInsightBolusID().queryBuilder()
+ .where().eq("pumpSerial", pumpSerial)
+ .and().eq("bolusID", bolusID)
+ .and().between("timestamp", timestamp - 259200000, timestamp + 259200000)
+ .queryForFirst();
+ } catch (SQLException e) {
+ log.error("Unhandled exception", e);
+ }
+ return null;
+ }
+
+ public void createOrUpdate(InsightPumpID pumpID) {
+ try {
+ getDaoInsightPumpID().createOrUpdate(pumpID);
+ } catch (SQLException e) {
+ log.error("Unhandled exception", e);
+ }
+ }
+
+ public InsightPumpID getPumpStoppedEvent(String pumpSerial, long before) {
+ try {
+ return getDaoInsightPumpID().queryBuilder()
+ .orderBy("timestamp", false)
+ .where().eq("pumpSerial", pumpSerial)
+ .and().eq("eventType", "PumpStopped")
+ .and().lt("timestamp", before)
+ .queryForFirst();
+ } catch (SQLException e) {
+ log.error("Unhandled exception", e);
+ }
+ return null;
+ }
+
// ---------------- Food handling ---------------
}
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 0527864fd2..f7252e97df 100644
--- a/app/src/main/java/info/nightscout/androidaps/db/ProfileSwitch.java
+++ b/app/src/main/java/info/nightscout/androidaps/db/ProfileSwitch.java
@@ -101,6 +101,11 @@ public class ProfileSwitch implements Interval, DataPointWithLabelInterface {
return profile;
}
+ /**
+ * Note: the name returned here is used as the PS name when uploading to NS. When such a PS is retrieved
+ * again from NS, the added parts must be removed again, see
+ * {@link info.nightscout.utils.PercentageSplitter#pureName}
+ */
public String getCustomizedName() {
String name = profileName;
if(LocalProfilePlugin.LOCAL_PROFILE.equals(name)){
diff --git a/app/src/main/java/info/nightscout/androidaps/interfaces/ConstraintsInterface.java b/app/src/main/java/info/nightscout/androidaps/interfaces/ConstraintsInterface.java
index 310c94ac20..5ac8cc83f7 100644
--- a/app/src/main/java/info/nightscout/androidaps/interfaces/ConstraintsInterface.java
+++ b/app/src/main/java/info/nightscout/androidaps/interfaces/ConstraintsInterface.java
@@ -27,6 +27,10 @@ public interface ConstraintsInterface {
return value;
}
+ default Constraint isUAMEnabled(Constraint value) {
+ return value;
+ }
+
default Constraint isAdvancedFilteringEnabled(Constraint value) {
return value;
}
diff --git a/app/src/main/java/info/nightscout/androidaps/interfaces/PumpInterface.java b/app/src/main/java/info/nightscout/androidaps/interfaces/PumpInterface.java
index 614c6033d3..976ac5c607 100644
--- a/app/src/main/java/info/nightscout/androidaps/interfaces/PumpInterface.java
+++ b/app/src/main/java/info/nightscout/androidaps/interfaces/PumpInterface.java
@@ -33,6 +33,10 @@ public interface PumpInterface {
double getBaseBasalRate(); // base basal rate, not temp basal
+ double getReservoirLevel();
+
+ int getBatteryLevel(); // in percent as integer
+
PumpEnactResult deliverTreatment(DetailedBolusInfo detailedBolusInfo);
void stopBolusDelivering();
PumpEnactResult setTempBasalAbsolute(Double absoluteRate, Integer durationInMinutes, Profile profile, boolean enforceNew);
diff --git a/app/src/main/java/info/nightscout/androidaps/logging/L.java b/app/src/main/java/info/nightscout/androidaps/logging/L.java
index 846825af6b..caa22757fa 100644
--- a/app/src/main/java/info/nightscout/androidaps/logging/L.java
+++ b/app/src/main/java/info/nightscout/androidaps/logging/L.java
@@ -100,13 +100,13 @@ public class L {
private static void initialize() {
logElements = new ArrayList<>();
logElements.add(new LogElement(APS, true));
- logElements.add(new LogElement(AUTOSENS, true));
+ logElements.add(new LogElement(AUTOSENS, false));
logElements.add(new LogElement(BGSOURCE, true));
- logElements.add(new LogElement(CONFIGBUILDER, true));
+ logElements.add(new LogElement(CONFIGBUILDER, false));
logElements.add(new LogElement(CONSTRAINTS, true));
logElements.add(new LogElement(CORE, true));
logElements.add(new LogElement(DATABASE, true));
- logElements.add(new LogElement(DATAFOOD, true));
+ logElements.add(new LogElement(DATAFOOD, false));
logElements.add(new LogElement(DATASERVICE, true));
logElements.add(new LogElement(DATATREATMENTS, true));
logElements.add(new LogElement(EVENTS, false, true));
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Actions/dialogs/FillDialog.java b/app/src/main/java/info/nightscout/androidaps/plugins/Actions/dialogs/FillDialog.java
index 880bee86a8..aed10c9e2f 100644
--- a/app/src/main/java/info/nightscout/androidaps/plugins/Actions/dialogs/FillDialog.java
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/Actions/dialogs/FillDialog.java
@@ -185,7 +185,7 @@ public class FillDialog extends DialogFragment implements OnClickListener {
confirmMessage.add(MainApp.gs(R.string.fillwarning));
confirmMessage.add("");
confirmMessage.add(MainApp.gs(R.string.bolus) + ": " + "" + DecimalFormatter.toPumpSupportedBolus(insulinAfterConstraints) + "U" + "");
- if (!insulinAfterConstraints.equals(insulin))
+ if (Math.abs(insulinAfterConstraints - insulin) > 0.01d)
confirmMessage.add("" + MainApp.gs(R.string.bolusconstraintapplied) + "");
}
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 2a169dc4f3..cb495059b8 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
@@ -270,7 +270,7 @@ public class NewNSTreatmentDialog extends DialogFragment implements View.OnClick
if (profile == null) {
editBg.setParams(bg, 0d, 500d, 0.1d, new DecimalFormat("0.0"), false, bgTextWatcher);
editTemptarget.setParams(bg, 0d, 500d, 0.1d, new DecimalFormat("0.0"), false);
- } else if (profile.getUnits().equals(Constants.MMOL)) {
+ } else if (units.equals(Constants.MMOL)) {
editBg.setParams(bg, 0d, 30d, 0.1d, new DecimalFormat("0.0"), false, bgTextWatcher);
editTemptarget.setParams(bg, 0d, 30d, 0.1d, new DecimalFormat("0.0"), false);
} else {
@@ -279,7 +279,7 @@ public class NewNSTreatmentDialog extends DialogFragment implements View.OnClick
}
sensorRadioButton.setOnCheckedChangeListener((buttonView, isChecked) -> {
- Double bg1 = Profile.fromMgdlToUnits(GlucoseStatus.getGlucoseStatusData() != null ? GlucoseStatus.getGlucoseStatusData().glucose : 0d, profile.getUnits());
+ Double bg1 = Profile.fromMgdlToUnits(GlucoseStatus.getGlucoseStatusData() != null ? GlucoseStatus.getGlucoseStatusData().glucose : 0d, units);
if (savedInstanceState != null && savedInstanceState.getDouble("editBg") != bg1) {
editBg.setValue(savedInstanceState.getDouble("editBg"));
} else {
@@ -459,7 +459,7 @@ public class NewNSTreatmentDialog extends DialogFragment implements View.OnClick
if ((data.size() > 0) &&
(data.get(0).date > millis - 7 * 60 * 1000L) &&
(data.get(0).date < millis + 7 * 60 * 1000L)) {
- editBg.setValue(Profile.fromMgdlToUnits(data.get(0).value, profile != null ? profile.getUnits() : Constants.MGDL));
+ editBg.setValue(Profile.fromMgdlToUnits(data.get(0).value, units));
}
}
@@ -736,8 +736,8 @@ public class NewNSTreatmentDialog extends DialogFragment implements View.OnClick
.reason(reason)
.source(Source.USER);
if (tempTarget.durationInMinutes != 0) {
- tempTarget.low(Profile.toMgdl(targetBottom, profile.getUnits()))
- .high(Profile.toMgdl(targetTop, profile.getUnits()));
+ tempTarget.low(Profile.toMgdl(targetBottom, units))
+ .high(Profile.toMgdl(targetTop, units));
} else {
tempTarget.low(0).high(0);
}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/ConstraintsSafety/SafetyPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/ConstraintsSafety/SafetyPlugin.java
index 9229164eb0..a1a9d5ff6e 100644
--- a/app/src/main/java/info/nightscout/androidaps/plugins/ConstraintsSafety/SafetyPlugin.java
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/ConstraintsSafety/SafetyPlugin.java
@@ -18,6 +18,7 @@ import info.nightscout.androidaps.plugins.OpenAPSMA.OpenAPSMAPlugin;
import info.nightscout.androidaps.plugins.OpenAPSSMB.OpenAPSSMBPlugin;
import info.nightscout.androidaps.plugins.Overview.events.EventNewNotification;
import info.nightscout.androidaps.plugins.Overview.notifications.Notification;
+import info.nightscout.androidaps.plugins.Sensitivity.SensitivityOref1Plugin;
import info.nightscout.utils.DecimalFormatter;
import info.nightscout.utils.HardLimits;
import info.nightscout.utils.Round;
@@ -94,6 +95,17 @@ public class SafetyPlugin extends PluginBase implements ConstraintsInterface {
return value;
}
+ @Override
+ public Constraint isUAMEnabled(Constraint value) {
+ boolean enabled = SP.getBoolean(R.string.key_use_uam, false);
+ if (!enabled)
+ value.set(false, MainApp.gs(R.string.uamdisabledinpreferences), this);
+ boolean oref1Enabled = SensitivityOref1Plugin.getPlugin().isEnabled(PluginType.SENSITIVITY);
+ if (!oref1Enabled)
+ value.set(false, MainApp.gs(R.string.uamdisabledoref1notselected), this);
+ return value;
+ }
+
@Override
public Constraint isAdvancedFilteringEnabled(Constraint value) {
BgSourceInterface bgSource = ConfigBuilderPlugin.getPlugin().getActiveBgSource();
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/IobCobCalculator/AutosensData.java b/app/src/main/java/info/nightscout/androidaps/plugins/IobCobCalculator/AutosensData.java
index 60a5851011..56af4ba12f 100644
--- a/app/src/main/java/info/nightscout/androidaps/plugins/IobCobCalculator/AutosensData.java
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/IobCobCalculator/AutosensData.java
@@ -21,6 +21,7 @@ import info.nightscout.androidaps.plugins.Overview.graphExtensions.Scale;
import info.nightscout.androidaps.plugins.Sensitivity.SensitivityAAPSPlugin;
import info.nightscout.androidaps.plugins.Sensitivity.SensitivityWeightedAveragePlugin;
import info.nightscout.androidaps.plugins.Treatments.Treatment;
+import info.nightscout.utils.DateUtil;
import info.nightscout.utils.SP;
/**
@@ -40,7 +41,7 @@ public class AutosensData implements DataPointWithLabelInterface {
double min5minCarbImpact = 0d;
double remaining = 0d;
- public CarbsInPast(Treatment t) {
+ CarbsInPast(Treatment t) {
time = t.date;
carbs = t.carbs;
remaining = t.carbs;
@@ -56,6 +57,18 @@ public class AutosensData implements DataPointWithLabelInterface {
min5minCarbImpact = SP.getDouble(R.string.key_openapsama_min_5m_carbimpact, SMBDefaults.min_5m_carbimpact);
}
}
+
+ CarbsInPast (CarbsInPast other) {
+ this.time = other.time;
+ this.carbs = other.carbs;
+ this.min5minCarbImpact = other.min5minCarbImpact;
+ this.remaining = other.remaining;
+ }
+
+ @Override
+ public String toString() {
+ return String.format("CarbsInPast: time: %s carbs: %.02f min5minCI: %.02f remaining: %.2f", new Date(time).toLocaleString(), carbs, min5minCarbImpact, remaining);
+ }
}
public long time = 0L;
@@ -89,11 +102,18 @@ public class AutosensData implements DataPointWithLabelInterface {
@Override
public String toString() {
- return "AutosensData: " + new Date(time).toLocaleString() + " " + pastSensitivity + " Delta=" + delta + " avgDelta=" + avgDelta + " Bgi=" + bgi + " Deviation=" + deviation + " avgDeviation=" + avgDeviation + " Absorbed=" + absorbed + " CarbsFromBolus=" + carbsFromBolus + " COB=" + cob + " autosensRatio=" + autosensResult.ratio + " slopeFromMaxDeviation=" + slopeFromMaxDeviation + " slopeFromMinDeviation=" + slopeFromMinDeviation;
+ return String.format("AutosensData: %s pastSensitivity=%s delta=%.02f avgDelta=%.02f bgi=%.02f deviation=%.02f avgDeviation=%.02f absorbed=%.02f carbsFromBolus=%.02f cob=%.02f autosensRatio=%.02f slopeFromMaxDeviation=%.02f slopeFromMinDeviation=%.02f activeCarbsList=%s",
+ new Date(time).toLocaleString(), pastSensitivity, delta, avgDelta, bgi, deviation, avgDeviation, absorbed, carbsFromBolus, cob, autosensResult.ratio, slopeFromMaxDeviation, slopeFromMinDeviation, activeCarbsList.toString());
}
- public int minOld() {
- return (int) ((System.currentTimeMillis() - time) / 1000 / 60);
+ public List cloneCarbsList() {
+ List newActiveCarbsList = new ArrayList<>();
+
+ for(CarbsInPast c: activeCarbsList) {
+ newActiveCarbsList.add(new CarbsInPast(c));
+ }
+
+ return newActiveCarbsList;
}
// remove carbs older than timeframe
@@ -111,7 +131,7 @@ public class AutosensData implements DataPointWithLabelInterface {
if (c.remaining > 0)
cob -= c.remaining;
if (L.isEnabled(L.AUTOSENS))
- log.debug("Removing carbs at " + new Date(toTime).toLocaleString() + " + after " + maxAbsorptionHours + "h :" + new Date(c.time).toLocaleString());
+ log.debug("Removing carbs at " + new Date(toTime).toLocaleString() + " after " + maxAbsorptionHours + "h > " + c.toString());
}
}
}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/IobCobCalculator/IobCobCalculatorPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/IobCobCalculator/IobCobCalculatorPlugin.java
index 951fa0b895..b94076a377 100644
--- a/app/src/main/java/info/nightscout/androidaps/plugins/IobCobCalculator/IobCobCalculatorPlugin.java
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/IobCobCalculator/IobCobCalculatorPlugin.java
@@ -146,8 +146,8 @@ public class IobCobCalculatorPlugin extends PluginBase {
return false;
}
}
- double averageDiff = totalDiff / (bgReadings.size() - 1) / 1000d;
- boolean is5mindata = averageDiff < 10;
+ long averageDiff = totalDiff / bgReadings.size() / 1000;
+ boolean is5mindata = averageDiff < 1;
if (L.isEnabled(L.AUTOSENS))
log.debug("Interval detection: values: " + bgReadings.size() + " averageDiff: " + averageDiff + "[s] is5minData: " + is5mindata);
return is5mindata;
@@ -231,13 +231,15 @@ public class IobCobCalculatorPlugin extends PluginBase {
bucketed_data = new ArrayList<>();
bucketed_data.add(bgReadings.get(0));
+ if (L.isEnabled(L.AUTOSENS))
+ log.debug("Adding. bgTime: " + DateUtil.toISOString(bgReadings.get(0).date) + " lastbgTime: " + "none-first-value" + " " + bgReadings.get(0).toString());
int j = 0;
for (int i = 1; i < bgReadings.size(); ++i) {
long bgTime = bgReadings.get(i).date;
long lastbgTime = bgReadings.get(i - 1).date;
//log.error("Processing " + i + ": " + new Date(bgTime).toString() + " " + bgReadings.get(i).value + " Previous: " + new Date(lastbgTime).toString() + " " + bgReadings.get(i - 1).value);
if (bgReadings.get(i).value < 39 || bgReadings.get(i - 1).value < 39) {
- continue;
+ throw new IllegalStateException("<39");
}
long elapsed_minutes = (bgTime - lastbgTime) / (60 * 1000);
@@ -294,6 +296,13 @@ public class IobCobCalculatorPlugin extends PluginBase {
long adjusted = (msecDiff - T.mins(5).msecs()) / 1000;
if (L.isEnabled(L.AUTOSENS))
log.debug("Adjusting bucketed data time. Current: " + DateUtil.toISOString(current.date) + " to: " + DateUtil.toISOString(previous.date + T.mins(5).msecs()) + " by " + adjusted + " sec");
+ if (Math.abs(adjusted) > 90) {
+ // too big adjustment, fallback to non 5 min data
+ if (L.isEnabled(L.AUTOSENS))
+ log.debug("Fallback to non 5 min data");
+ createBucketedDataRecalculated();
+ return;
+ }
current.date = previous.date + T.mins(5).msecs();
}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/IobCobCalculator/IobCobOref1Thread.java b/app/src/main/java/info/nightscout/androidaps/plugins/IobCobCalculator/IobCobOref1Thread.java
index 4032546f7a..172a6bbc47 100644
--- a/app/src/main/java/info/nightscout/androidaps/plugins/IobCobCalculator/IobCobOref1Thread.java
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/IobCobCalculator/IobCobOref1Thread.java
@@ -36,7 +36,10 @@ import info.nightscout.androidaps.plugins.Overview.notifications.Notification;
import info.nightscout.androidaps.plugins.Treatments.Treatment;
import info.nightscout.androidaps.plugins.Treatments.TreatmentsPlugin;
import info.nightscout.utils.DateUtil;
+import info.nightscout.utils.DecimalFormatter;
import info.nightscout.utils.FabricPrivacy;
+import info.nightscout.utils.MidnightTime;
+import info.nightscout.utils.Profiler;
import info.nightscout.utils.SP;
import static info.nightscout.utils.DateUtil.now;
@@ -74,6 +77,7 @@ public class IobCobOref1Thread extends Thread {
@Override
public final void run() {
+ long start = DateUtil.now();
mWakeLock.acquire();
try {
if (L.isEnabled(L.AUTOSENS))
@@ -148,7 +152,7 @@ public class IobCobOref1Thread extends Thread {
AutosensData autosensData = new AutosensData();
autosensData.time = bgTime;
if (previous != null)
- autosensData.activeCarbsList = new ArrayList<>(previous.activeCarbsList);
+ autosensData.activeCarbsList = previous.cloneCarbsList();
else
autosensData.activeCarbsList = new ArrayList<>();
@@ -242,6 +246,7 @@ public class IobCobOref1Thread extends Thread {
for (int ir = 0; ir < recentTreatments.size(); ir++) {
autosensData.carbsFromBolus += recentTreatments.get(ir).carbs;
autosensData.activeCarbsList.add(new AutosensData.CarbsInPast(recentTreatments.get(ir)));
+ autosensData.pastSensitivity += "[" + DecimalFormatter.to0Decimal(recentTreatments.get(ir).carbs) + "g]";
}
@@ -339,19 +344,19 @@ public class IobCobOref1Thread extends Thread {
// Exclude meal-related deviations (carb absorption) from autosens
if (autosensData.type.equals("non-meal")) {
if (Math.abs(deviation) < Constants.DEVIATION_TO_BE_EQUAL) {
- autosensData.pastSensitivity = "=";
+ autosensData.pastSensitivity += "=";
autosensData.validDeviation = true;
} else if (deviation > 0) {
- autosensData.pastSensitivity = "+";
+ autosensData.pastSensitivity += "+";
autosensData.validDeviation = true;
} else {
- autosensData.pastSensitivity = "-";
+ autosensData.pastSensitivity += "-";
autosensData.validDeviation = true;
}
} else if (autosensData.type.equals("uam")) {
- autosensData.pastSensitivity = "u";
+ autosensData.pastSensitivity += "u";
} else {
- autosensData.pastSensitivity = "x";
+ autosensData.pastSensitivity += "x";
}
//log.debug("TIME: " + new Date(bgTime).toString() + " BG: " + bg + " SENS: " + sens + " DELTA: " + delta + " AVGDELTA: " + avgDelta + " IOB: " + iob.iob + " ACTIVITY: " + iob.activity + " BGI: " + bgi + " DEVIATION: " + deviation);
@@ -391,8 +396,11 @@ public class IobCobOref1Thread extends Thread {
} finally {
mWakeLock.release();
MainApp.bus().post(new EventIobCalculationProgress(""));
- if (L.isEnabled(L.AUTOSENS))
+ if (L.isEnabled(L.AUTOSENS)) {
log.debug("AUTOSENSDATA thread ended: " + from);
+ log.debug("Midnights: " + MidnightTime.log());
+ }
+ Profiler.log(log, "IobCobOref1Thread", start);
}
}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/IobCobCalculator/IobCobThread.java b/app/src/main/java/info/nightscout/androidaps/plugins/IobCobCalculator/IobCobThread.java
index 07df247a21..aa1f09592e 100644
--- a/app/src/main/java/info/nightscout/androidaps/plugins/IobCobCalculator/IobCobThread.java
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/IobCobCalculator/IobCobThread.java
@@ -36,7 +36,10 @@ import info.nightscout.androidaps.plugins.Sensitivity.SensitivityWeightedAverage
import info.nightscout.androidaps.plugins.Treatments.Treatment;
import info.nightscout.androidaps.plugins.Treatments.TreatmentsPlugin;
import info.nightscout.utils.DateUtil;
+import info.nightscout.utils.DecimalFormatter;
import info.nightscout.utils.FabricPrivacy;
+import info.nightscout.utils.MidnightTime;
+import info.nightscout.utils.Profiler;
import info.nightscout.utils.SP;
import static info.nightscout.utils.DateUtil.now;
@@ -73,6 +76,7 @@ public class IobCobThread extends Thread {
@Override
public final void run() {
+ long start = DateUtil.now();
mWakeLock.acquire();
try {
if (L.isEnabled(L.AUTOSENS))
@@ -147,7 +151,7 @@ public class IobCobThread extends Thread {
AutosensData autosensData = new AutosensData();
autosensData.time = bgTime;
if (previous != null)
- autosensData.activeCarbsList = new ArrayList<>(previous.activeCarbsList);
+ autosensData.activeCarbsList = previous.cloneCarbsList();
else
autosensData.activeCarbsList = new ArrayList<>();
@@ -241,6 +245,7 @@ public class IobCobThread extends Thread {
for (int ir = 0; ir < recentTreatments.size(); ir++) {
autosensData.carbsFromBolus += recentTreatments.get(ir).carbs;
autosensData.activeCarbsList.add(new AutosensData.CarbsInPast(recentTreatments.get(ir)));
+ autosensData.pastSensitivity += "[" + DecimalFormatter.to0Decimal(recentTreatments.get(ir).carbs) + "g]";
}
@@ -284,17 +289,17 @@ public class IobCobThread extends Thread {
// calculate autosens only without COB
if (autosensData.cob <= 0) {
if (Math.abs(deviation) < Constants.DEVIATION_TO_BE_EQUAL) {
- autosensData.pastSensitivity = "=";
+ autosensData.pastSensitivity += "=";
autosensData.validDeviation = true;
} else if (deviation > 0) {
- autosensData.pastSensitivity = "+";
+ autosensData.pastSensitivity += "+";
autosensData.validDeviation = true;
} else {
- autosensData.pastSensitivity = "-";
+ autosensData.pastSensitivity += "-";
autosensData.validDeviation = true;
}
} else {
- autosensData.pastSensitivity = "C";
+ autosensData.pastSensitivity += "C";
}
//log.debug("TIME: " + new Date(bgTime).toString() + " BG: " + bg + " SENS: " + sens + " DELTA: " + delta + " AVGDELTA: " + avgDelta + " IOB: " + iob.iob + " ACTIVITY: " + iob.activity + " BGI: " + bgi + " DEVIATION: " + deviation);
@@ -318,8 +323,11 @@ public class IobCobThread extends Thread {
} finally {
mWakeLock.release();
MainApp.bus().post(new EventIobCalculationProgress(""));
- if (L.isEnabled(L.AUTOSENS))
+ if (L.isEnabled(L.AUTOSENS)) {
log.debug("AUTOSENSDATA thread ended: " + from);
+ log.debug("Midnights: " + MidnightTime.log());
+ }
+ Profiler.log(log, "IobCobThread", start);
}
}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Loop/APSResult.java b/app/src/main/java/info/nightscout/androidaps/plugins/Loop/APSResult.java
index 5135c6b87b..3678617c96 100644
--- a/app/src/main/java/info/nightscout/androidaps/plugins/Loop/APSResult.java
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/Loop/APSResult.java
@@ -307,6 +307,11 @@ public class APSResult {
PumpInterface pump = ConfigBuilderPlugin.getPlugin().getActivePump();
Profile profile = ProfileFunctions.getInstance().getProfile();
+ if (profile == null) {
+ log.error("FALSE: No Profile");
+ return false;
+ }
+
if (usePercent) {
if (activeTemp == null && percent == 100) {
if (L.isEnabled(L.APS))
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Loop/LoopPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/Loop/LoopPlugin.java
index ac5076be72..0b20ddf582 100644
--- a/app/src/main/java/info/nightscout/androidaps/plugins/Loop/LoopPlugin.java
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/Loop/LoopPlugin.java
@@ -409,8 +409,10 @@ public class LoopPlugin extends PluginBase {
.setAutoCancel(true)
.setPriority(Notification.PRIORITY_HIGH)
.setCategory(Notification.CATEGORY_ALARM)
- .setVisibility(Notification.VISIBILITY_PUBLIC)
- .setLocalOnly(true);
+ .setVisibility(Notification.VISIBILITY_PUBLIC);
+ if (SP.getBoolean("wearcontrol", false)) {
+ builder.setLocalOnly(true);
+ }
// Creates an explicit intent for an Activity in your app
Intent resultIntent = new Intent(MainApp.instance().getApplicationContext(), MainActivity.class);
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Maintenance/MaintenancePlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/Maintenance/MaintenancePlugin.java
index 09ab7feee1..c73a5160ac 100644
--- a/app/src/main/java/info/nightscout/androidaps/plugins/Maintenance/MaintenancePlugin.java
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/Maintenance/MaintenancePlugin.java
@@ -73,8 +73,8 @@ public class MaintenancePlugin extends PluginBase {
}
public void sendLogs() {
- String recipient = SP.getString("key_maintenance_logs_email", "logs@androidaps.org");
- int amount = SP.getInt("key_maintenance_logs_amount", 2);
+ String recipient = SP.getString(R.string.key_maintenance_logs_email, "logs@androidaps.org");
+ int amount = SP.getInt(R.string.key_maintenance_logs_amount, 2);
String logDirectory = LoggerUtils.getLogDirectory();
List logs = this.getLogfiles(logDirectory, amount);
@@ -103,7 +103,7 @@ public class MaintenancePlugin extends PluginBase {
Arrays.sort(files, (f1, f2) -> f1.getName().compareTo(f2.getName()));
List delFiles = Arrays.asList(files);
- int amount = SP.getInt("key_logshipper_amount", 2);
+ int amount = SP.getInt(R.string.key_logshipper_amount, 2);
int keepIndex = amount - 1;
if (keepIndex < delFiles.size()) {
@@ -213,6 +213,10 @@ public class MaintenancePlugin extends PluginBase {
builder.append("ADD TIME OF EVENT HERE: " + System.lineSeparator());
builder.append("ADD ISSUE DESCRIPTION OR GITHUB ISSUE REFERENCE NUMBER: " + System.lineSeparator());
builder.append("-------------------------------------------------------" + System.lineSeparator());
+ builder.append("(Please remember this will send only very recent logs." + System.lineSeparator());
+ builder.append("If you want to provide logs for event older than a few hours," + System.lineSeparator());
+ builder.append("you have to do it manually)" + System.lineSeparator());
+ builder.append("-------------------------------------------------------" + System.lineSeparator());
builder.append(MainApp.gs(R.string.app_name) + " " + BuildConfig.VERSION + System.lineSeparator());
if (Config.NSCLIENT)
builder.append("NSCLIENT" + System.lineSeparator());
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/OpenAPSSMB/DetermineBasalAdapterSMBJS.java b/app/src/main/java/info/nightscout/androidaps/plugins/OpenAPSSMB/DetermineBasalAdapterSMBJS.java
index f974ff472e..bdd06372d9 100644
--- a/app/src/main/java/info/nightscout/androidaps/plugins/OpenAPSSMB/DetermineBasalAdapterSMBJS.java
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/OpenAPSSMB/DetermineBasalAdapterSMBJS.java
@@ -211,6 +211,7 @@ public class DetermineBasalAdapterSMBJS {
double autosensDataRatio,
boolean tempTargetSet,
boolean microBolusAllowed,
+ boolean uamAllowed,
boolean advancedFiltering
) throws JSONException {
@@ -247,7 +248,7 @@ public class DetermineBasalAdapterSMBJS {
// mProfile.put("min_5m_carbimpact", SP.getDouble(R.string.key_openapsama_min_5m_carbimpact, SMBDefaults.min_5m_carbimpact));
//}
mProfile.put("remainingCarbsCap", SMBDefaults.remainingCarbsCap);
- mProfile.put("enableUAM", SP.getBoolean(R.string.key_use_uam, false));
+ mProfile.put("enableUAM", uamAllowed);
mProfile.put("A52_risk_enable", SMBDefaults.A52_risk_enable);
mProfile.put("enableSMB_with_COB", SP.getBoolean(R.string.key_enableSMB_with_COB, false));
mProfile.put("enableSMB_with_temptarget", SP.getBoolean(R.string.key_enableSMB_with_temptarget, false));
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/OpenAPSSMB/OpenAPSSMBPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/OpenAPSSMB/OpenAPSSMBPlugin.java
index d42ca9e89f..1d6b558c74 100644
--- a/app/src/main/java/info/nightscout/androidaps/plugins/OpenAPSSMB/OpenAPSSMBPlugin.java
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/OpenAPSSMB/OpenAPSSMBPlugin.java
@@ -198,6 +198,10 @@ public class OpenAPSSMBPlugin extends PluginBase implements APSInterface {
MainApp.getConstraintChecker().isAdvancedFilteringEnabled(advancedFiltering);
inputConstraints.copyReasons(advancedFiltering);
+ Constraint uam = new Constraint<>(true);
+ MainApp.getConstraintChecker().isUAMEnabled(uam);
+ inputConstraints.copyReasons(uam);
+
if (L.isEnabled(L.APS))
Profiler.log(log, "detectSensitivityandCarbAbsorption()", startPart);
if (L.isEnabled(L.APS))
@@ -209,6 +213,7 @@ public class OpenAPSSMBPlugin extends PluginBase implements APSInterface {
lastAutosensResult.ratio, //autosensDataRatio
isTempTarget,
smbAllowed.value(),
+ uam.value(),
advancedFiltering.value()
);
} catch (JSONException e) {
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Overview/Dialogs/BolusProgressDialog.java b/app/src/main/java/info/nightscout/androidaps/plugins/Overview/Dialogs/BolusProgressDialog.java
index 1baac9a694..6ac7d13cfa 100644
--- a/app/src/main/java/info/nightscout/androidaps/plugins/Overview/Dialogs/BolusProgressDialog.java
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/Overview/Dialogs/BolusProgressDialog.java
@@ -107,9 +107,9 @@ public class BolusProgressDialog extends DialogFragment implements View.OnClickL
@Override
public void onPause() {
+ running = false;
super.onPause();
MainApp.unsubscribe(this);
- running = false;
if (L.isEnabled(L.UI))
log.debug("onPause");
}
@@ -173,10 +173,12 @@ public class BolusProgressDialog extends DialogFragment implements View.OnClickL
Activity activity = getActivity();
if (activity != null) {
activity.runOnUiThread(() -> {
- if (L.isEnabled(L.UI))
- log.debug("executing");
try {
- dismiss();
+ if (running) {
+ if (L.isEnabled(L.UI))
+ log.debug("executing");
+ dismiss();
+ }
} catch (Exception e) {
log.error("Unhandled exception", e);
}
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 a414d38310..281a06d472 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
@@ -3,6 +3,7 @@ package info.nightscout.androidaps.plugins.Overview;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.app.NotificationManager;
+import android.arch.core.util.Function;
import android.content.ActivityNotFoundException;
import android.content.Context;
import android.content.Intent;
@@ -97,6 +98,7 @@ import info.nightscout.androidaps.plugins.Loop.LoopPlugin;
import info.nightscout.androidaps.plugins.Loop.events.EventNewOpenLoopNotification;
import info.nightscout.androidaps.plugins.NSClientInternal.NSUpload;
import info.nightscout.androidaps.plugins.NSClientInternal.data.NSDeviceStatus;
+import info.nightscout.androidaps.plugins.NSClientInternal.data.NSSettingsStatus;
import info.nightscout.androidaps.plugins.Overview.Dialogs.CalibrationDialog;
import info.nightscout.androidaps.plugins.Overview.Dialogs.ErrorHelperActivity;
import info.nightscout.androidaps.plugins.Overview.Dialogs.NewCarbsDialog;
@@ -162,6 +164,13 @@ public class OverviewFragment extends Fragment implements View.OnClickListener,
TextView sage;
TextView pbage;
+ TextView iageView;
+ TextView cageView;
+ TextView reservoirView;
+ TextView sageView;
+ TextView batteryView;
+ LinearLayout statuslightsLayout;
+
RecyclerView notificationsView;
LinearLayoutManager llm;
@@ -258,8 +267,15 @@ public class OverviewFragment extends Fragment implements View.OnClickListener,
sage = (TextView) view.findViewById(R.id.careportal_sensorage);
pbage = (TextView) view.findViewById(R.id.careportal_pbage);
- bgGraph = (GraphView) view.findViewById(R.id.overview_bggraph);
- iobGraph = (GraphView) view.findViewById(R.id.overview_iobgraph);
+ iageView = (TextView) view.findViewById(R.id.overview_insulinage);
+ cageView = (TextView) view.findViewById(R.id.overview_canulaage);
+ reservoirView = (TextView) view.findViewById(R.id.overview_reservoirlevel);
+ sageView = (TextView) view.findViewById(R.id.overview_sensorage);
+ batteryView = (TextView) view.findViewById(R.id.overview_batterylevel);
+ statuslightsLayout = (LinearLayout) view.findViewById(R.id.overview_statuslights);
+
+ bgGraph = (GraphView) view.findViewById(R.id.overview_bggraph);
+ iobGraph = (GraphView) view.findViewById(R.id.overview_iobgraph);
treatmentButton = (SingleClickButton) view.findViewById(R.id.overview_treatmentbutton);
treatmentButton.setOnClickListener(this);
@@ -446,7 +462,8 @@ public class OverviewFragment extends Fragment implements View.OnClickListener,
super.onCreateContextMenu(menu, v, menuInfo);
if (v == apsModeView) {
final LoopPlugin loopPlugin = LoopPlugin.getPlugin();
- final PumpDescription pumpDescription = ConfigBuilderPlugin.getPlugin().getActivePump().getPumpDescription();
+ final PumpDescription pumpDescription =
+ ConfigBuilderPlugin.getPlugin().getActivePump().getPumpDescription();
if (!ProfileFunctions.getInstance().isProfileValid("ContexMenuCreation"))
return;
menu.setHeaderTitle(MainApp.gs(R.string.loop));
@@ -457,19 +474,23 @@ public class OverviewFragment extends Fragment implements View.OnClickListener,
menu.add(MainApp.gs(R.string.suspendloopfor2h));
menu.add(MainApp.gs(R.string.suspendloopfor3h));
menu.add(MainApp.gs(R.string.suspendloopfor10h));
- if (pumpDescription.tempDurationStep15mAllowed)
- menu.add(MainApp.gs(R.string.disconnectpumpfor15m));
- if (pumpDescription.tempDurationStep30mAllowed)
- menu.add(MainApp.gs(R.string.disconnectpumpfor30m));
- menu.add(MainApp.gs(R.string.disconnectpumpfor1h));
- menu.add(MainApp.gs(R.string.disconnectpumpfor2h));
- menu.add(MainApp.gs(R.string.disconnectpumpfor3h));
- } else {
- menu.add(MainApp.gs(R.string.resume));
+ } else {
+ if (!loopPlugin.isDisconnected()) {
+ menu.add(MainApp.gs(R.string.resume));
+ }
}
}
- if (!loopPlugin.isEnabled(PluginType.LOOP))
+
+ if (!loopPlugin.isEnabled(PluginType.LOOP)) {
menu.add(MainApp.gs(R.string.enableloop));
+ }
+
+ if (!loopPlugin.isDisconnected()) {
+ showSuspendtPump(menu, pumpDescription);
+ } else {
+ menu.add(MainApp.gs(R.string.reconnect));
+ }
+
} else if (v == activeProfileView) {
menu.setHeaderTitle(MainApp.gs(R.string.profile));
menu.add(MainApp.gs(R.string.danar_viewprofile));
@@ -488,6 +509,17 @@ public class OverviewFragment extends Fragment implements View.OnClickListener,
}
}
+ private void showSuspendtPump(ContextMenu menu,
+ PumpDescription pumpDescription) {
+ if (pumpDescription.tempDurationStep15mAllowed)
+ menu.add(MainApp.gs(R.string.disconnectpumpfor15m));
+ if (pumpDescription.tempDurationStep30mAllowed)
+ menu.add(MainApp.gs(R.string.disconnectpumpfor30m));
+ menu.add(MainApp.gs(R.string.disconnectpumpfor1h));
+ menu.add(MainApp.gs(R.string.disconnectpumpfor2h));
+ menu.add(MainApp.gs(R.string.disconnectpumpfor3h));
+ }
+
@Override
public boolean onContextItemSelected(MenuItem item) {
final Profile profile = ProfileFunctions.getInstance().getProfile();
@@ -516,7 +548,8 @@ public class OverviewFragment extends Fragment implements View.OnClickListener,
updateGUI("suspendmenu");
NSUpload.uploadOpenAPSOffline(0);
return true;
- } else if (item.getTitle().equals(MainApp.gs(R.string.resume))) {
+ } else if (item.getTitle().equals(MainApp.gs(R.string.resume)) ||
+ item.getTitle().equals(MainApp.gs(R.string.reconnect))) {
loopPlugin.suspendTo(0L);
updateGUI("suspendmenu");
ConfigBuilderPlugin.getPlugin().getCommandQueue().cancelTempBasal(true, new Callback() {
@@ -1088,25 +1121,25 @@ public class OverviewFragment extends Fragment implements View.OnClickListener,
final LoopPlugin.LastRun finalLastRun = LoopPlugin.lastRun;
if (Config.APS && pump.getPumpDescription().isTempBasalCapable) {
apsModeView.setVisibility(View.VISIBLE);
- apsModeView.setBackgroundColor(MainApp.gc(R.color.loopenabled));
- apsModeView.setTextColor(Color.BLACK);
+ apsModeView.setBackgroundColor(MainApp.gc(R.color.ribbonDefault));
+ apsModeView.setTextColor(MainApp.gc(R.color.ribbonTextDefault));
final LoopPlugin loopPlugin = LoopPlugin.getPlugin();
if (loopPlugin.isEnabled(PluginType.LOOP) && loopPlugin.isSuperBolus()) {
- apsModeView.setBackgroundColor(MainApp.gc(R.color.looppumpsuspended));
+ apsModeView.setBackgroundColor(MainApp.gc(R.color.ribbonWarning));
apsModeView.setText(String.format(MainApp.gs(R.string.loopsuperbolusfor), loopPlugin.minutesToEndOfSuspend()));
- apsModeView.setTextColor(Color.WHITE);
- } else if (loopPlugin.isEnabled(PluginType.LOOP) && loopPlugin.isDisconnected()) {
- apsModeView.setBackgroundColor(MainApp.gc(R.color.looppumpsuspended));
+ apsModeView.setTextColor(MainApp.gc(R.color.ribbonTextWarning));
+ } else if (loopPlugin.isDisconnected()) {
+ apsModeView.setBackgroundColor(MainApp.gc(R.color.ribbonCritical));
apsModeView.setText(String.format(MainApp.gs(R.string.loopdisconnectedfor), loopPlugin.minutesToEndOfSuspend()));
- apsModeView.setTextColor(Color.WHITE);
+ apsModeView.setTextColor(MainApp.gc(R.color.ribbonTextCritical));
} else if (loopPlugin.isEnabled(PluginType.LOOP) && loopPlugin.isSuspended()) {
- apsModeView.setBackgroundColor(MainApp.gc(R.color.looppumpsuspended));
+ apsModeView.setBackgroundColor(MainApp.gc(R.color.ribbonWarning));
apsModeView.setText(String.format(MainApp.gs(R.string.loopsuspendedfor), loopPlugin.minutesToEndOfSuspend()));
- apsModeView.setTextColor(Color.WHITE);
+ apsModeView.setTextColor(MainApp.gc(R.color.ribbonTextWarning));
} else if (pump.isSuspended()) {
- apsModeView.setBackgroundColor(MainApp.gc(R.color.looppumpsuspended));
+ apsModeView.setBackgroundColor(MainApp.gc(R.color.ribbonWarning));
apsModeView.setText(MainApp.gs(R.string.pumpsuspended));
- apsModeView.setTextColor(Color.WHITE);
+ apsModeView.setTextColor(MainApp.gc(R.color.ribbonTextWarning));
} else if (loopPlugin.isEnabled(PluginType.LOOP)) {
if (closedLoopEnabled.value()) {
apsModeView.setText(MainApp.gs(R.string.closedloop));
@@ -1114,9 +1147,9 @@ public class OverviewFragment extends Fragment implements View.OnClickListener,
apsModeView.setText(MainApp.gs(R.string.openloop));
}
} else {
- apsModeView.setBackgroundColor(MainApp.gc(R.color.loopdisabled));
+ apsModeView.setBackgroundColor(MainApp.gc(R.color.ribbonCritical));
apsModeView.setText(MainApp.gs(R.string.disabledloop));
- apsModeView.setTextColor(Color.WHITE);
+ apsModeView.setTextColor(MainApp.gc(R.color.ribbonTextCritical));
}
} else {
apsModeView.setVisibility(View.GONE);
@@ -1125,13 +1158,13 @@ public class OverviewFragment extends Fragment implements View.OnClickListener,
// temp target
TempTarget tempTarget = TreatmentsPlugin.getPlugin().getTempTargetFromHistory();
if (tempTarget != null) {
- tempTargetView.setTextColor(Color.BLACK);
- tempTargetView.setBackgroundColor(MainApp.gc(R.color.tempTargetBackground));
+ tempTargetView.setTextColor(MainApp.gc(R.color.ribbonTextWarning));
+ tempTargetView.setBackgroundColor(MainApp.gc(R.color.ribbonWarning));
tempTargetView.setVisibility(View.VISIBLE);
tempTargetView.setText(Profile.toTargetRangeString(tempTarget.low, tempTarget.high, Constants.MGDL, units) + " " + DateUtil.untilString(tempTarget.end()));
} else {
- tempTargetView.setTextColor(Color.WHITE);
- tempTargetView.setBackgroundColor(MainApp.gc(R.color.tempTargetDisabledBackground));
+ tempTargetView.setTextColor(MainApp.gc(R.color.ribbonTextDefault));
+ tempTargetView.setBackgroundColor(MainApp.gc(R.color.ribbonDefault));
tempTargetView.setText(Profile.toTargetRangeString(profile.getTargetLow(), profile.getTargetHigh(), units, units));
tempTargetView.setVisibility(View.VISIBLE);
}
@@ -1230,7 +1263,13 @@ public class OverviewFragment extends Fragment implements View.OnClickListener,
}
activeProfileView.setText(ProfileFunctions.getInstance().getProfileName());
- activeProfileView.setBackgroundColor(Color.GRAY);
+ if (profile.getPercentage() != 100 || profile.getTimeshift() != 0) {
+ activeProfileView.setBackgroundColor(MainApp.gc(R.color.ribbonWarning));
+ activeProfileView.setTextColor(MainApp.gc(R.color.ribbonTextWarning));
+ } else {
+ activeProfileView.setBackgroundColor(MainApp.gc(R.color.ribbonDefault));
+ activeProfileView.setTextColor(MainApp.gc(R.color.ribbonTextDefault));
+ }
// QuickWizard button
QuickWizardEntry quickWizardEntry = OverviewPlugin.getPlugin().quickWizard.getActive();
@@ -1335,6 +1374,56 @@ public class OverviewFragment extends Fragment implements View.OnClickListener,
cobView.setText(cobText);
}
+ if (statuslightsLayout != null) {
+ if (SP.getBoolean(R.string.key_show_statuslights, false)) {
+ CareportalEvent careportalEvent;
+ NSSettingsStatus nsSettings = new NSSettingsStatus().getInstance();
+ double iageUrgent = nsSettings.getExtendedWarnValue("iage", "urgent", 96);
+ double iageWarn = nsSettings.getExtendedWarnValue("iage", "warn", 72);
+ double cageUrgent = nsSettings.getExtendedWarnValue("cage", "urgent", 72);
+ double cageWarn = nsSettings.getExtendedWarnValue("cage", "warn", 48);
+ double sageUrgent = nsSettings.getExtendedWarnValue("sage", "urgent", 166);
+ double sageWarn = nsSettings.getExtendedWarnValue("sage", "warn", 164);
+ //double pbageUrgent = nsSettings.getExtendedWarnValue("pgage", "urgent", 360);
+ //double pbageWarn = nsSettings.getExtendedWarnValue("pgage", "warn", 240);
+ double batUrgent = SP.getDouble(R.string.key_statuslights_bat_critical, 5.0);
+ double batWarn = SP.getDouble(R.string.key_statuslights_bat_warning, 25.0);
+ double resUrgent = SP.getDouble(R.string.key_statuslights_res_critical, 10.0);
+ double resWarn = SP.getDouble(R.string.key_statuslights_res_warning, 80.0);
+
+ if (cageView != null) {
+ careportalEvent = MainApp.getDbHelper().getLastCareportalEvent(CareportalEvent.SITECHANGE);
+ double canAge = careportalEvent != null ? careportalEvent.getHoursFromStart() : Double.MAX_VALUE;
+ applyStatuslight(cageView, "CAN", canAge, cageWarn, cageUrgent, Double.MAX_VALUE, true);
+ }
+
+ if (iageView != null) {
+ careportalEvent = MainApp.getDbHelper().getLastCareportalEvent(CareportalEvent.INSULINCHANGE);
+ double insulinAge = careportalEvent != null ? careportalEvent.getHoursFromStart() : Double.MAX_VALUE;
+ applyStatuslight(iageView, "INS", insulinAge, iageWarn, iageUrgent, Double.MAX_VALUE, true);
+ }
+
+ if (reservoirView != null) {
+ double reservoirLevel = pump.isInitialized() ? pump.getReservoirLevel() : -1;
+ applyStatuslight(reservoirView, "RES", reservoirLevel, resWarn, resUrgent, -1, false);
+ }
+
+ if (sageView != null) {
+ careportalEvent = MainApp.getDbHelper().getLastCareportalEvent(CareportalEvent.SENSORCHANGE);
+ double sensorAge = careportalEvent != null ? careportalEvent.getHoursFromStart() : Double.MAX_VALUE;
+ applyStatuslight(sageView, "SEN", sensorAge, sageWarn, sageUrgent, Double.MAX_VALUE, true);
+ }
+
+ if (batteryView != null) {
+ double batteryLevel = pump.isInitialized() ? pump.getBatteryLevel() : -1;
+ applyStatuslight(batteryView, "BAT", batteryLevel, batWarn, batUrgent, -1, false);
+ }
+ statuslightsLayout.setVisibility(View.VISIBLE);
+ } else {
+ statuslightsLayout.setVisibility(View.GONE);
+ }
+ }
+
boolean predictionsAvailable;
if (Config.APS)
predictionsAvailable = finalLastRun != null && finalLastRun.request.hasPredictions;
@@ -1364,7 +1453,7 @@ public class OverviewFragment extends Fragment implements View.OnClickListener,
// Sensitivity
if (sensitivityView != null) {
- AutosensData autosensData = IobCobCalculatorPlugin.getPlugin().getLastAutosensDataSynchronized("Overview");
+ AutosensData autosensData = IobCobCalculatorPlugin.getPlugin().getLastAutosensData("Overview");
if (autosensData != null)
sensitivityView.setText(String.format("%.0f%%", autosensData.autosensResult.ratio * 100));
else
@@ -1525,4 +1614,21 @@ public class OverviewFragment extends Fragment implements View.OnClickListener,
}
}
+ public static void applyStatuslight(TextView view, String text, double value, double warnThreshold, double urgentThreshold, double invalid, boolean checkAscending) {
+ Function check = checkAscending ? (Double threshold) -> value >= threshold : (Double threshold) -> value <= threshold;
+ if (value != invalid) {
+ view.setText(text);
+ if (check.apply(urgentThreshold)) {
+ view.setTextColor(MainApp.gc(R.color.ribbonCritical));
+ } else if (check.apply(warnThreshold)) {
+ view.setTextColor(MainApp.gc(R.color.ribbonWarning));
+ } else {
+ view.setTextColor(MainApp.gc(R.color.ribbonDefault));
+ }
+ view.setVisibility(View.VISIBLE);
+ } else {
+ view.setVisibility(View.GONE);
+ }
+
+ }
}
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 23e9ec9643..0c80910284 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
@@ -68,6 +68,11 @@ public class Notification {
public static final int NSMALFUNCTION = 40;
public static final int NEWVERSIONDETECTED = 41;
public static final int SENDLOGFILES = 42;
+ public static final int DEVICENOTPAIRED = 43;
+ public static final int MEDTRONIC_PUMP_ALARM = 44;
+ public static final int RILEYLINK_CONNECTION = 45;
+ public static final int PERMISSION_PHONESTATE = 46;
+ public static final int INSIGHT_DATE_TIME_UPDATED = 47;
public int id;
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Persistentnotification/PersistentNotificationPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/Persistentnotification/PersistentNotificationPlugin.java
index cd69e88210..6b93b7a715 100644
--- a/app/src/main/java/info/nightscout/androidaps/plugins/Persistentnotification/PersistentNotificationPlugin.java
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/Persistentnotification/PersistentNotificationPlugin.java
@@ -13,6 +13,14 @@ import android.os.Build;
import android.support.v4.app.NotificationCompat;
import android.support.v4.app.TaskStackBuilder;
+// Android Auto
+import android.support.v4.app.NotificationCompat;
+import android.support.v4.app.NotificationManagerCompat;
+import android.support.v4.app.RemoteInput;
+
+
+
+
import com.squareup.otto.Subscribe;
import info.nightscout.androidaps.Config;
@@ -60,6 +68,18 @@ public class PersistentNotificationPlugin extends PluginBase {
public static final int ONGOING_NOTIFICATION_ID = 4711;
private final Context ctx;
+ /// For Android Auto
+ /// Intents are not declared in manifest and not consumed, this is intentionally because actually we can't do anything with
+ private static final String PACKAGE = "info.nightscout";
+ private static final String READ_ACTION =
+ "info.nightscout.androidaps.ACTION_MESSAGE_READ";
+ private static final String REPLY_ACTION =
+ "info.nightscout.androidaps.ACTION_MESSAGE_REPLY";
+ private static final String CONVERSATION_ID = "conversation_id";
+ private static final String EXTRA_VOICE_REPLY = "extra_voice_reply";
+ /// End Android Auto
+
+
public PersistentNotificationPlugin(Context ctx) {
super(new PluginDescription()
.mainType(PluginType.GENERAL)
@@ -107,7 +127,8 @@ public class PersistentNotificationPlugin extends PluginBase {
return null;
}
- String line1 = "";
+ String line1;
+ String line1_aa;
if (ConfigBuilderPlugin.getPlugin().getActiveProfileInterface() == null || !ProfileFunctions.getInstance().isProfileValid("Notificiation"))
return null;
@@ -118,22 +139,25 @@ public class PersistentNotificationPlugin extends PluginBase {
GlucoseStatus glucoseStatus = GlucoseStatus.getGlucoseStatusData();
if (lastBG != null) {
- line1 = lastBG.valueToUnitsToString(units);
+ line1 = line1_aa = lastBG.valueToUnitsToString(units);
if (glucoseStatus != null) {
line1 += " Δ" + deltastring(glucoseStatus.delta, glucoseStatus.delta * Constants.MGDL_TO_MMOLL, units)
+ " avgΔ" + deltastring(glucoseStatus.avgdelta, glucoseStatus.avgdelta * Constants.MGDL_TO_MMOLL, units);
+ line1_aa += " " + lastBG.directionToSymbol();
} else {
line1 += " " +
MainApp.gs(R.string.old_data) +
" ";
+ line1_aa += line1 + ".";
}
} else {
- line1 = MainApp.gs(R.string.missed_bg_readings);
+ line1 = line1_aa = MainApp.gs(R.string.missed_bg_readings);
}
TemporaryBasal activeTemp = TreatmentsPlugin.getPlugin().getTempBasalFromHistory(System.currentTimeMillis());
if (activeTemp != null) {
line1 += " " + activeTemp.toStringShort();
+ line1_aa += " " + activeTemp.toStringShort() + ".";
}
//IOB
@@ -143,12 +167,55 @@ public class PersistentNotificationPlugin extends PluginBase {
IobTotal basalIob = TreatmentsPlugin.getPlugin().getLastCalculationTempBasals().round();
- String line2 = MainApp.gs(R.string.treatments_iob_label_string) + " " + DecimalFormatter.to2Decimal(bolusIob.iob + basalIob.basaliob) + "U " + MainApp.gs(R.string.cob)+": " + IobCobCalculatorPlugin.getPlugin().getCobInfo(false, "PersistentNotificationPlugin").generateCOBString();;
-
+ String line2 = MainApp.gs(R.string.treatments_iob_label_string) + " " + DecimalFormatter.to2Decimal(bolusIob.iob + basalIob.basaliob) + "U " + MainApp.gs(R.string.cob)+": " + IobCobCalculatorPlugin.getPlugin().getCobInfo(false, "PersistentNotificationPlugin").generateCOBString();
+ String line2_aa = MainApp.gs(R.string.treatments_iob_label_string) + " " + DecimalFormatter.to2Decimal(bolusIob.iob + basalIob.basaliob) + "U. " + MainApp.gs(R.string.cob)+": " + IobCobCalculatorPlugin.getPlugin().getCobInfo(false, "PersistentNotificationPlugin").generateCOBString() + ".";
+
+
String line3 = DecimalFormatter.to2Decimal(ConfigBuilderPlugin.getPlugin().getActivePump().getBaseBasalRate()) + " U/h";
+ String line3_aa = DecimalFormatter.to2Decimal(ConfigBuilderPlugin.getPlugin().getActivePump().getBaseBasalRate()) + " U/h.";
line3 += " - " + ProfileFunctions.getInstance().getProfileName();
+ line3_aa += " - " + ProfileFunctions.getInstance().getProfileName() + ".";
+
+ /// For Android Auto
+ Intent msgReadIntent = new Intent()
+ .addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES)
+ .setAction(READ_ACTION)
+ .putExtra(CONVERSATION_ID, ONGOING_NOTIFICATION_ID)
+ .setPackage(PACKAGE);
+
+ PendingIntent msgReadPendingIntent =
+ PendingIntent.getBroadcast(ctx,
+ ONGOING_NOTIFICATION_ID,
+ msgReadIntent,
+ PendingIntent.FLAG_UPDATE_CURRENT);
+
+ Intent msgReplyIntent = new Intent()
+ .addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES)
+ .setAction(REPLY_ACTION)
+ .putExtra(CONVERSATION_ID, ONGOING_NOTIFICATION_ID)
+ .setPackage(PACKAGE);
+
+ PendingIntent msgReplyPendingIntent = PendingIntent.getBroadcast(
+ ctx,
+ ONGOING_NOTIFICATION_ID,
+ msgReplyIntent,
+ PendingIntent.FLAG_UPDATE_CURRENT);
+
+ // Build a RemoteInput for receiving voice input from devices
+ RemoteInput remoteInput = new RemoteInput.Builder(EXTRA_VOICE_REPLY).build();
+
+ // Create the UnreadConversation
+ NotificationCompat.CarExtender.UnreadConversation.Builder unreadConversationBuilder =
+ new NotificationCompat.CarExtender.UnreadConversation.Builder(line1_aa + "\n" + line2_aa)
+ .setLatestTimestamp(System.currentTimeMillis())
+ .setReadPendingIntent(msgReadPendingIntent)
+ .setReplyAction(msgReplyPendingIntent, remoteInput);
+
+ /// Add dot to produce a "more natural sounding result"
+ unreadConversationBuilder.addMessage(line3_aa);
+ /// End Android Auto
NotificationCompat.Builder builder = new NotificationCompat.Builder(ctx, CHANNEL_ID);
@@ -167,6 +234,11 @@ public class PersistentNotificationPlugin extends PluginBase {
builder.setContentTitle(line1);
builder.setContentText(line2);
builder.setSubText(line3);
+ /// Android Auto
+ builder.extend(new NotificationCompat.CarExtender()
+ .setUnreadConversation(unreadConversationBuilder.build()));
+ /// End Android Auto
+
Intent resultIntent = new Intent(ctx, MainActivity.class);
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 fc45928f89..0445ef3402 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
@@ -156,7 +156,7 @@ public class LocalProfileFragment extends SubscriberFragment {
public String getSumLabel() {
ProfileStore profile = LocalProfilePlugin.getPlugin().createProfileStore();
if (profile != null)
- return " ∑" + DecimalFormatter.to2Decimal(profile.getDefaultProfile().baseBasalSum()) + "U";
+ return " ∑" + DecimalFormatter.to2Decimal(profile.getDefaultProfile().baseBasalSum()) + MainApp.gs(R.string.insulin_unit_shortname);
else
return MainApp.gs(R.string.localprofile);
}
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 e3aeca0c45..4edaef1761 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
@@ -52,6 +52,8 @@ public class NSProfileFragment extends SubscriberFragment {
TextView isf;
@BindView(R.id.profileview_basal)
TextView basal;
+ @BindView(R.id.profileview_basaltotal)
+ TextView basaltotal;
@BindView(R.id.profileview_target)
TextView target;
@BindView(R.id.basal_graph)
@@ -116,6 +118,7 @@ public class NSProfileFragment extends SubscriberFragment {
ic.setText(profile.getIcList());
isf.setText(profile.getIsfList());
basal.setText(profile.getBasalList());
+ basaltotal.setText(String.format(MainApp.gs(R.string.profile_total), DecimalFormatter.to2Decimal(profile.baseBasalSum())));
target.setText(profile.getTargetList());
basalGraph.show(profile);
}
@@ -141,6 +144,7 @@ public class NSProfileFragment extends SubscriberFragment {
ic.setText("");
isf.setText("");
basal.setText("");
+ basaltotal.setText("");
target.setText("");
activateButton.setVisibility(View.GONE);
}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpCombo/ComboPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpCombo/ComboPlugin.java
index 3f30071327..08e8edfb92 100644
--- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpCombo/ComboPlugin.java
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpCombo/ComboPlugin.java
@@ -435,6 +435,23 @@ public class ComboPlugin extends PluginBase implements PumpInterface, Constraint
return pump.basalProfile.hourlyRates[currentHour];
}
+ @Override
+ public double getReservoirLevel() {
+ return pump.reservoirLevel;
+ }
+
+ @Override
+ public int getBatteryLevel() {
+ switch (pump.state.batteryState) {
+ case PumpState.EMPTY:
+ return 5;
+ case PumpState.LOW:
+ return 25;
+ default:
+ return 100;
+ }
+ }
+
private static BolusProgressReporter bolusProgressReporter = (state, percent, delivered) -> {
EventOverviewBolusProgress event = EventOverviewBolusProgress.getInstance();
switch (state) {
@@ -653,11 +670,7 @@ public class ComboPlugin extends PluginBase implements PumpInterface, Constraint
}
}
- /**
- * Updates a DetailedBolusInfo from a pump bolus and adds it as a Treatment to the DB.
- * Handles edge cases when dates aren't unique which are extremely unlikely to occur,
- * but if they do, the user should be warned since a bolus will be missing from calculations.
- */
+ /** Creates a treatment record based on the request in DetailBolusInfo and the delivered bolus. */
private boolean addBolusToTreatments(DetailedBolusInfo detailedBolusInfo, Bolus lastPumpBolus) {
DetailedBolusInfo dbi = detailedBolusInfo.copy();
dbi.date = calculateFakeBolusDate(lastPumpBolus);
@@ -665,15 +678,7 @@ public class ComboPlugin extends PluginBase implements PumpInterface, Constraint
dbi.source = Source.PUMP;
dbi.insulin = lastPumpBolus.amount;
try {
- boolean treatmentCreated = TreatmentsPlugin.getPlugin().addToHistoryTreatment(dbi, false);
- if (!treatmentCreated) {
- log.error("Adding treatment record overrode an existing record: " + dbi);
- if (dbi.isSMB) {
- Notification notification = new Notification(Notification.COMBO_PUMP_ALARM, MainApp.gs(R.string.combo_error_updating_treatment_record), Notification.URGENT);
- MainApp.bus().post(new EventNewNotification(notification));
- }
- return false;
- }
+ TreatmentsPlugin.getPlugin().addToHistoryTreatment(dbi, true);
} catch (Exception e) {
log.error("Adding treatment record failed", e);
if (dbi.isSMB) {
@@ -1149,6 +1154,7 @@ public class ComboPlugin extends PluginBase implements PumpInterface, Constraint
return historyResult.success;
}
+ /** Return value indicates whether a new record was created. */
private boolean updateDbFromPumpHistory(@NonNull PumpHistory history) {
boolean updated = false;
for (Bolus pumpBolus : history.bolusHistory) {
@@ -1158,8 +1164,7 @@ public class ComboPlugin extends PluginBase implements PumpInterface, Constraint
dbi.source = Source.PUMP;
dbi.insulin = pumpBolus.amount;
dbi.eventType = CareportalEvent.CORRECTIONBOLUS;
- if (TreatmentsPlugin.getPlugin().getService().getPumpRecordById(dbi.pumpId) == null) {
- TreatmentsPlugin.getPlugin().addToHistoryTreatment(dbi, false);
+ if (TreatmentsPlugin.getPlugin().addToHistoryTreatment(dbi, true)) {
updated = true;
}
}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/defs/PumpType.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/defs/PumpType.java
index 1c064d0cf0..ab97f2cff2 100644
--- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/defs/PumpType.java
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/defs/PumpType.java
@@ -56,7 +56,7 @@ public enum PumpType {
AnimasVibe("Animas Vibe", 0.05d, null, // AnimasBolus?
new DoseSettings(0.05d, 30, 12*60, 0.05d), //
PumpTempBasalType.Percent, //
- new DoseSettings(10, 30, 24*60, 0d, 200d), PumpCapability.BasalRate_Duration30minAllowed, //
+ new DoseSettings(10, 30, 24*60, 0d, 300d), PumpCapability.BasalRate_Duration30minAllowed, //
0.025d, 5d, 0d, null, PumpCapability.VirtualPumpCapabilities), //
AnimasPing("Animas Ping", AnimasVibe),
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/AbstractDanaRPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/AbstractDanaRPlugin.java
index c50e635eb8..75eb9bdf3c 100644
--- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/AbstractDanaRPlugin.java
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/AbstractDanaRPlugin.java
@@ -152,6 +152,12 @@ public abstract class AbstractDanaRPlugin extends PluginBase implements PumpInte
return DanaRPump.getInstance().currentBasal;
}
+ @Override
+ public double getReservoirLevel() { return DanaRPump.getInstance().reservoirRemainingUnits; }
+
+ @Override
+ public int getBatteryLevel() { return DanaRPump.getInstance().batteryRemaining; }
+
@Override
public void stopBolusDelivering() {
if (sExecutionService == null) {
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/DanaRPump.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/DanaRPump.java
index 3a6b3b5786..df9b48f795 100644
--- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/DanaRPump.java
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/DanaRPump.java
@@ -20,7 +20,7 @@ import info.nightscout.utils.SP;
* Created by mike on 04.07.2016.
*/
public class DanaRPump {
- private Logger log = LoggerFactory.getLogger(L.PUMP);
+ private static Logger log = LoggerFactory.getLogger(L.PUMP);
private static DanaRPump instance = null;
@@ -30,6 +30,7 @@ public class DanaRPump {
}
public static void reset() {
+ log.debug("DanaRPump reset");
instance = null;
}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/services/AbstractDanaRExecutionService.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/services/AbstractDanaRExecutionService.java
index f45f222861..ae09281c91 100644
--- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/services/AbstractDanaRExecutionService.java
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/services/AbstractDanaRExecutionService.java
@@ -40,6 +40,7 @@ import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgPCCommStart;
import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgPCCommStop;
import info.nightscout.androidaps.plugins.PumpDanaR.comm.RecordTypes;
import info.nightscout.androidaps.plugins.Treatments.Treatment;
+import info.nightscout.utils.DateUtil;
import info.nightscout.utils.SP;
import info.nightscout.utils.ToastUtils;
@@ -55,7 +56,6 @@ public abstract class AbstractDanaRExecutionService extends Service {
protected BluetoothSocket mRfcommSocket;
protected BluetoothDevice mBTDevice;
- protected DanaRPump mDanaRPump = DanaRPump.getInstance();
protected Treatment mBolusingTreatment = null;
protected boolean mConnectionInProgress = false;
@@ -237,4 +237,15 @@ public abstract class AbstractDanaRExecutionService extends Service {
result.comment = "OK";
return result;
}
+
+ protected void waitForWholeMinute() {
+ while (true) {
+ long time = DateUtil.now();
+ long timeToWholeMinute = (60000 - time % 60000);
+ if (timeToWholeMinute > 59800 || timeToWholeMinute < 3000)
+ break;
+ MainApp.bus().post(new EventPumpStatusChanged(MainApp.gs(R.string.waitingfortimesynchronization, (int) (timeToWholeMinute / 1000))));
+ SystemClock.sleep(Math.min(timeToWholeMinute, 100));
+ }
+ }
}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/services/DanaRExecutionService.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/services/DanaRExecutionService.java
index 425e72ea04..268d5378c1 100644
--- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/services/DanaRExecutionService.java
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/services/DanaRExecutionService.java
@@ -133,6 +133,7 @@ public class DanaRExecutionService extends AbstractDanaRExecutionService {
}
public void getPumpStatus() {
+ DanaRPump danaRPump = DanaRPump.getInstance();
try {
MainApp.bus().post(new EventPumpStatusChanged(MainApp.gs(R.string.gettingpumpstatus)));
MsgStatus statusMsg = new MsgStatus();
@@ -141,7 +142,7 @@ public class DanaRExecutionService extends AbstractDanaRExecutionService {
MsgStatusBolusExtended exStatusMsg = new MsgStatusBolusExtended();
MsgCheckValue checkValue = new MsgCheckValue();
- if (mDanaRPump.isNewPump) {
+ if (danaRPump.isNewPump) {
mSerialIOThread.sendMessage(checkValue);
if (!checkValue.received) {
return;
@@ -157,11 +158,11 @@ public class DanaRExecutionService extends AbstractDanaRExecutionService {
MainApp.bus().post(new EventPumpStatusChanged(MainApp.gs(R.string.gettingbolusstatus)));
long now = System.currentTimeMillis();
- mDanaRPump.lastConnection = now;
+ danaRPump.lastConnection = now;
Profile profile = ProfileFunctions.getInstance().getProfile();
PumpInterface pump = ConfigBuilderPlugin.getPlugin().getActivePump();
- if (profile != null && Math.abs(mDanaRPump.currentBasal - profile.getBasal()) >= pump.getPumpDescription().basalStep) {
+ if (profile != null && Math.abs(danaRPump.currentBasal - profile.getBasal()) >= pump.getPumpDescription().basalStep) {
MainApp.bus().post(new EventPumpStatusChanged(MainApp.gs(R.string.gettingpumpsettings)));
mSerialIOThread.sendMessage(new MsgSettingBasal());
if (!pump.isThisProfileSet(profile) && !ConfigBuilderPlugin.getPlugin().getCommandQueue().isRunning(Command.CommandType.BASALPROFILE)) {
@@ -169,7 +170,7 @@ public class DanaRExecutionService extends AbstractDanaRExecutionService {
}
}
- if (mDanaRPump.lastSettingsRead + 60 * 60 * 1000L < now || !pump.isInitialized()) {
+ if (danaRPump.lastSettingsRead + 60 * 60 * 1000L < now || !pump.isInitialized()) {
MainApp.bus().post(new EventPumpStatusChanged(MainApp.gs(R.string.gettingpumpsettings)));
mSerialIOThread.sendMessage(new MsgSettingShippingInfo());
mSerialIOThread.sendMessage(new MsgSettingActiveProfile());
@@ -184,29 +185,29 @@ public class DanaRExecutionService extends AbstractDanaRExecutionService {
mSerialIOThread.sendMessage(new MsgSettingUserOptions());
MainApp.bus().post(new EventPumpStatusChanged(MainApp.gs(R.string.gettingpumptime)));
mSerialIOThread.sendMessage(new MsgSettingPumpTime());
- long timeDiff = (mDanaRPump.pumpTime - System.currentTimeMillis()) / 1000L;
+ long timeDiff = (danaRPump.pumpTime - System.currentTimeMillis()) / 1000L;
if (L.isEnabled(L.PUMP))
log.debug("Pump time difference: " + timeDiff + " seconds");
if (Math.abs(timeDiff) > 10) {
mSerialIOThread.sendMessage(new MsgSetTime(new Date()));
mSerialIOThread.sendMessage(new MsgSettingPumpTime());
- timeDiff = (mDanaRPump.pumpTime - System.currentTimeMillis()) / 1000L;
+ timeDiff = (danaRPump.pumpTime - System.currentTimeMillis()) / 1000L;
if (L.isEnabled(L.PUMP))
log.debug("Pump time difference: " + timeDiff + " seconds");
}
- mDanaRPump.lastSettingsRead = now;
+ danaRPump.lastSettingsRead = now;
}
MainApp.bus().post(new EventDanaRNewStatus());
MainApp.bus().post(new EventInitializationChanged());
NSUpload.uploadDeviceStatus();
- if (mDanaRPump.dailyTotalUnits > mDanaRPump.maxDailyTotalUnits * Constants.dailyLimitWarning) {
+ if (danaRPump.dailyTotalUnits > danaRPump.maxDailyTotalUnits * Constants.dailyLimitWarning) {
if (L.isEnabled(L.PUMP))
- log.debug("Approaching daily limit: " + mDanaRPump.dailyTotalUnits + "/" + mDanaRPump.maxDailyTotalUnits);
+ log.debug("Approaching daily limit: " + danaRPump.dailyTotalUnits + "/" + danaRPump.maxDailyTotalUnits);
if (System.currentTimeMillis() > lastApproachingDailyLimit + 30 * 60 * 1000) {
Notification reportFail = new Notification(Notification.APPROACHING_DAILY_LIMIT, MainApp.gs(R.string.approachingdailylimit), Notification.URGENT);
MainApp.bus().post(new EventNewNotification(reportFail));
- NSUpload.uploadError(MainApp.gs(R.string.approachingdailylimit) + ": " + mDanaRPump.dailyTotalUnits + "/" + mDanaRPump.maxDailyTotalUnits + "U");
+ NSUpload.uploadError(MainApp.gs(R.string.approachingdailylimit) + ": " + danaRPump.dailyTotalUnits + "/" + danaRPump.maxDailyTotalUnits + "U");
lastApproachingDailyLimit = System.currentTimeMillis();
}
}
@@ -216,8 +217,9 @@ public class DanaRExecutionService extends AbstractDanaRExecutionService {
}
public boolean tempBasal(int percent, int durationInHours) {
+ DanaRPump danaRPump = DanaRPump.getInstance();
if (!isConnected()) return false;
- if (mDanaRPump.isTempBasalInProgress) {
+ if (danaRPump.isTempBasalInProgress) {
MainApp.bus().post(new EventPumpStatusChanged(MainApp.gs(R.string.stoppingtempbasal)));
mSerialIOThread.sendMessage(new MsgSetTempBasalStop());
SystemClock.sleep(500);
@@ -262,6 +264,7 @@ public class DanaRExecutionService extends AbstractDanaRExecutionService {
}
public boolean bolus(double amount, int carbs, long carbtime, final Treatment t) {
+ DanaRPump danaRPump = DanaRPump.getInstance();
if (!isConnected()) return false;
if (BolusProgressDialog.stopPressed) return false;
@@ -335,13 +338,13 @@ public class DanaRExecutionService extends AbstractDanaRExecutionService {
ConfigBuilderPlugin.getPlugin().getCommandQueue().independentConnect("bolusingInterrupted", new Callback() {
@Override
public void run() {
- if (mDanaRPump.lastBolusTime > System.currentTimeMillis() - 60 * 1000L) { // last bolus max 1 min old
- t.insulin = mDanaRPump.lastBolusAmount;
+ if (danaRPump.lastBolusTime > System.currentTimeMillis() - 60 * 1000L) { // last bolus max 1 min old
+ t.insulin = danaRPump.lastBolusAmount;
if (L.isEnabled(L.PUMP))
- log.debug("Used bolus amount from history: " + mDanaRPump.lastBolusAmount);
+ log.debug("Used bolus amount from history: " + danaRPump.lastBolusAmount);
} else {
if (L.isEnabled(L.PUMP))
- log.debug("Bolus amount in history too old: " + DateUtil.dateAndTimeFullString(mDanaRPump.lastBolusTime));
+ log.debug("Bolus amount in history too old: " + DateUtil.dateAndTimeFullString(danaRPump.lastBolusTime));
}
synchronized (o) {
o.notify();
@@ -379,6 +382,7 @@ public class DanaRExecutionService extends AbstractDanaRExecutionService {
}
public boolean updateBasalsInPump(final Profile profile) {
+ DanaRPump danaRPump = DanaRPump.getInstance();
if (!isConnected()) return false;
MainApp.bus().post(new EventPumpStatusChanged(MainApp.gs(R.string.updatingbasalrates)));
double[] basal = DanaRPump.getInstance().buildDanaRProfileRecord(profile);
@@ -386,7 +390,7 @@ public class DanaRExecutionService extends AbstractDanaRExecutionService {
mSerialIOThread.sendMessage(msgSet);
MsgSetActivateBasalProfile msgActivate = new MsgSetActivateBasalProfile((byte) 0);
mSerialIOThread.sendMessage(msgActivate);
- mDanaRPump.lastSettingsRead = 0; // force read full settings
+ danaRPump.lastSettingsRead = 0; // force read full settings
getPumpStatus();
MainApp.bus().post(new EventPumpStatusChanged(EventPumpStatusChanged.DISCONNECTING));
return true;
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRKorean/comm/MsgInitConnStatusBolus_k.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRKorean/comm/MsgInitConnStatusBolus_k.java
index 4be04f538f..b8bdfd053c 100644
--- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRKorean/comm/MsgInitConnStatusBolus_k.java
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRKorean/comm/MsgInitConnStatusBolus_k.java
@@ -6,6 +6,7 @@ import org.slf4j.LoggerFactory;
import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.R;
import info.nightscout.androidaps.logging.L;
+import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin;
import info.nightscout.androidaps.plugins.Overview.events.EventDismissNotification;
import info.nightscout.androidaps.plugins.Overview.events.EventNewNotification;
import info.nightscout.androidaps.plugins.Overview.notifications.Notification;
@@ -51,5 +52,9 @@ public class MsgInitConnStatusBolus_k extends MessageBase {
} else {
MainApp.bus().post(new EventDismissNotification(Notification.EXTENDED_BOLUS_DISABLED));
}
+
+ // This is last message of initial sequence
+ if (ConfigBuilderPlugin.getPlugin().getActivePump() != null)
+ ConfigBuilderPlugin.getPlugin().getActivePump().finishHandshaking();
}
}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRKorean/services/DanaRKoreanExecutionService.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRKorean/services/DanaRKoreanExecutionService.java
index d419d7c1f1..f3588c4efa 100644
--- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRKorean/services/DanaRKoreanExecutionService.java
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRKorean/services/DanaRKoreanExecutionService.java
@@ -24,6 +24,7 @@ import info.nightscout.androidaps.interfaces.PumpInterface;
import info.nightscout.androidaps.logging.L;
import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin;
import info.nightscout.androidaps.plugins.ConfigBuilder.ProfileFunctions;
+import info.nightscout.androidaps.plugins.NSClientInternal.NSUpload;
import info.nightscout.androidaps.plugins.Overview.Dialogs.BolusProgressDialog;
import info.nightscout.androidaps.plugins.Overview.events.EventNewNotification;
import info.nightscout.androidaps.plugins.Overview.notifications.Notification;
@@ -55,8 +56,8 @@ import info.nightscout.androidaps.plugins.PumpDanaRKorean.comm.MsgSettingBasal_k
import info.nightscout.androidaps.plugins.PumpDanaRKorean.comm.MsgStatusBasic_k;
import info.nightscout.androidaps.plugins.Treatments.Treatment;
import info.nightscout.androidaps.queue.commands.Command;
-import info.nightscout.androidaps.plugins.NSClientInternal.NSUpload;
-import info.nightscout.utils.SP;
+import info.nightscout.utils.DateUtil;
+import info.nightscout.utils.T;
public class DanaRKoreanExecutionService extends AbstractDanaRExecutionService {
@@ -137,6 +138,7 @@ public class DanaRKoreanExecutionService extends AbstractDanaRExecutionService {
}
public void getPumpStatus() {
+ DanaRPump danaRPump = DanaRPump.getInstance();
try {
MainApp.bus().post(new EventPumpStatusChanged(MainApp.gs(R.string.gettingpumpstatus)));
//MsgStatus_k statusMsg = new MsgStatus_k();
@@ -145,7 +147,7 @@ public class DanaRKoreanExecutionService extends AbstractDanaRExecutionService {
MsgStatusBolusExtended exStatusMsg = new MsgStatusBolusExtended();
MsgCheckValue_k checkValue = new MsgCheckValue_k();
- if (mDanaRPump.isNewPump) {
+ if (danaRPump.isNewPump) {
mSerialIOThread.sendMessage(checkValue);
if (!checkValue.received) {
return;
@@ -161,11 +163,11 @@ public class DanaRKoreanExecutionService extends AbstractDanaRExecutionService {
MainApp.bus().post(new EventPumpStatusChanged(MainApp.gs(R.string.gettingbolusstatus)));
long now = System.currentTimeMillis();
- mDanaRPump.lastConnection = now;
+ danaRPump.lastConnection = now;
Profile profile = ProfileFunctions.getInstance().getProfile();
PumpInterface pump = ConfigBuilderPlugin.getPlugin().getActivePump();
- if (profile != null && Math.abs(mDanaRPump.currentBasal - profile.getBasal()) >= pump.getPumpDescription().basalStep) {
+ if (profile != null && Math.abs(danaRPump.currentBasal - profile.getBasal()) >= pump.getPumpDescription().basalStep) {
MainApp.bus().post(new EventPumpStatusChanged(MainApp.gs(R.string.gettingpumpsettings)));
mSerialIOThread.sendMessage(new MsgSettingBasal());
if (!pump.isThisProfileSet(profile) && !ConfigBuilderPlugin.getPlugin().getCommandQueue().isRunning(Command.CommandType.BASALPROFILE)) {
@@ -173,7 +175,7 @@ public class DanaRKoreanExecutionService extends AbstractDanaRExecutionService {
}
}
- if (mDanaRPump.lastSettingsRead + 60 * 60 * 1000L < now || !pump.isInitialized()) {
+ if (danaRPump.lastSettingsRead + 60 * 60 * 1000L < now || !pump.isInitialized()) {
MainApp.bus().post(new EventPumpStatusChanged(MainApp.gs(R.string.gettingpumpsettings)));
mSerialIOThread.sendMessage(new MsgSettingShippingInfo());
mSerialIOThread.sendMessage(new MsgSettingMeal());
@@ -184,29 +186,31 @@ public class DanaRKoreanExecutionService extends AbstractDanaRExecutionService {
mSerialIOThread.sendMessage(new MsgSettingProfileRatios());
MainApp.bus().post(new EventPumpStatusChanged(MainApp.gs(R.string.gettingpumptime)));
mSerialIOThread.sendMessage(new MsgSettingPumpTime());
- long timeDiff = (mDanaRPump.pumpTime - System.currentTimeMillis()) / 1000L;
+ long timeDiff = (danaRPump.pumpTime - System.currentTimeMillis()) / 1000L;
if (L.isEnabled(L.PUMP))
log.debug("Pump time difference: " + timeDiff + " seconds");
if (Math.abs(timeDiff) > 10) {
- mSerialIOThread.sendMessage(new MsgSetTime(new Date()));
+ waitForWholeMinute(); // Dana can set only whole minute
+ // add 10sec to be sure we are over minute (will be cutted off anyway)
+ mSerialIOThread.sendMessage(new MsgSetTime(new Date(DateUtil.now() + T.secs(10).msecs())));
mSerialIOThread.sendMessage(new MsgSettingPumpTime());
- timeDiff = (mDanaRPump.pumpTime - System.currentTimeMillis()) / 1000L;
+ timeDiff = (danaRPump.pumpTime - System.currentTimeMillis()) / 1000L;
if (L.isEnabled(L.PUMP))
log.debug("Pump time difference: " + timeDiff + " seconds");
}
- mDanaRPump.lastSettingsRead = now;
+ danaRPump.lastSettingsRead = now;
}
MainApp.bus().post(new EventDanaRNewStatus());
MainApp.bus().post(new EventInitializationChanged());
NSUpload.uploadDeviceStatus();
- if (mDanaRPump.dailyTotalUnits > mDanaRPump.maxDailyTotalUnits * Constants.dailyLimitWarning) {
+ if (danaRPump.dailyTotalUnits > danaRPump.maxDailyTotalUnits * Constants.dailyLimitWarning) {
if (L.isEnabled(L.PUMP))
- log.debug("Approaching daily limit: " + mDanaRPump.dailyTotalUnits + "/" + mDanaRPump.maxDailyTotalUnits);
+ log.debug("Approaching daily limit: " + danaRPump.dailyTotalUnits + "/" + danaRPump.maxDailyTotalUnits);
if (System.currentTimeMillis() > lastApproachingDailyLimit + 30 * 60 * 1000) {
Notification reportFail = new Notification(Notification.APPROACHING_DAILY_LIMIT, MainApp.gs(R.string.approachingdailylimit), Notification.URGENT);
MainApp.bus().post(new EventNewNotification(reportFail));
- NSUpload.uploadError(MainApp.gs(R.string.approachingdailylimit) + ": " + mDanaRPump.dailyTotalUnits + "/" + mDanaRPump.maxDailyTotalUnits + "U");
+ NSUpload.uploadError(MainApp.gs(R.string.approachingdailylimit) + ": " + danaRPump.dailyTotalUnits + "/" + danaRPump.maxDailyTotalUnits + "U");
lastApproachingDailyLimit = System.currentTimeMillis();
}
}
@@ -216,8 +220,9 @@ public class DanaRKoreanExecutionService extends AbstractDanaRExecutionService {
}
public boolean tempBasal(int percent, int durationInHours) {
+ DanaRPump danaRPump = DanaRPump.getInstance();
if (!isConnected()) return false;
- if (mDanaRPump.isTempBasalInProgress) {
+ if (danaRPump.isTempBasalInProgress) {
MainApp.bus().post(new EventPumpStatusChanged(MainApp.gs(R.string.stoppingtempbasal)));
mSerialIOThread.sendMessage(new MsgSetTempBasalStop());
SystemClock.sleep(500);
@@ -318,12 +323,13 @@ public class DanaRKoreanExecutionService extends AbstractDanaRExecutionService {
}
public boolean updateBasalsInPump(final Profile profile) {
+ DanaRPump danaRPump = DanaRPump.getInstance();
if (!isConnected()) return false;
MainApp.bus().post(new EventPumpStatusChanged(MainApp.gs(R.string.updatingbasalrates)));
double[] basal = DanaRPump.getInstance().buildDanaRProfileRecord(profile);
MsgSetSingleBasalProfile msgSet = new MsgSetSingleBasalProfile(basal);
mSerialIOThread.sendMessage(msgSet);
- mDanaRPump.lastSettingsRead = 0; // force read full settings
+ danaRPump.lastSettingsRead = 0; // force read full settings
getPumpStatus();
MainApp.bus().post(new EventPumpStatusChanged(EventPumpStatusChanged.DISCONNECTING));
return true;
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/DanaRSPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/DanaRSPlugin.java
index e3c8f9de94..33422d55f1 100644
--- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/DanaRSPlugin.java
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/DanaRSPlugin.java
@@ -373,6 +373,12 @@ public class DanaRSPlugin extends PluginBase implements PumpInterface, DanaRInte
return DanaRPump.getInstance().currentBasal;
}
+ @Override
+ public double getReservoirLevel() { return DanaRPump.getInstance().reservoirRemainingUnits; }
+
+ @Override
+ public int getBatteryLevel() { return DanaRPump.getInstance().batteryRemaining; }
+
@Override
public synchronized PumpEnactResult deliverTreatment(DetailedBolusInfo detailedBolusInfo) {
detailedBolusInfo.insulin = MainApp.getConstraintChecker().applyBolusConstraints(new Constraint<>(detailedBolusInfo.insulin)).value();
@@ -415,6 +421,7 @@ public class DanaRSPlugin extends PluginBase implements PumpInterface, DanaRInte
if (!result.success) {
String error = "" + DanaRS_Packet_Bolus_Set_Step_Bolus_Start.errorCode;
switch (DanaRS_Packet_Bolus_Set_Step_Bolus_Start.errorCode) {
+ // 4 reported as max bolus violation. Check later
case 0x10:
error = MainApp.gs(R.string.maxbolusviolation);
break;
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_APS_History_Events.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_APS_History_Events.java
index dd3e5398c9..98e08a7ee3 100644
--- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_APS_History_Events.java
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_APS_History_Events.java
@@ -45,6 +45,12 @@ public class DanaRS_Packet_APS_History_Events extends DanaRS_Packet {
public DanaRS_Packet_APS_History_Events(long from) {
this();
GregorianCalendar cal = new GregorianCalendar();
+
+ if (from > DateUtil.now()) {
+ log.debug("Asked to load from the future");
+ from = 0;
+ }
+
if (from != 0)
cal.setTimeInMillis(from);
else
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/services/BLEComm.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/services/BLEComm.java
index be241dbbfd..48bb311385 100644
--- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/services/BLEComm.java
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/services/BLEComm.java
@@ -144,9 +144,9 @@ public class BLEComm {
if (L.isEnabled(L.PUMPBTCOMM))
log.debug("Trying to create a new connection from: " + from);
+ mBluetoothDeviceName = device.getName();
mBluetoothGatt = device.connectGatt(service.getApplicationContext(), false, mGattCallback);
setCharacteristicNotification(getUARTReadBTGattChar(), true);
- mBluetoothDeviceName = device.getName();
return true;
}
@@ -662,7 +662,13 @@ public class BLEComm {
private void SendPumpCheck() {
// 1st message sent to pump after connect
- byte[] bytes = BleCommandUtil.getInstance().getEncryptedPacket(BleCommandUtil.DANAR_PACKET__OPCODE_ENCRYPTION__PUMP_CHECK, null, getConnectDeviceName());
+ String devicename = getConnectDeviceName();
+ if(devicename == null || devicename.equals("")){
+ Notification n = new Notification(Notification.DEVICENOTPAIRED, MainApp.gs(R.string.pairfirst), Notification.URGENT);
+ MainApp.bus().post(new EventNewNotification(n));
+ return;
+ }
+ byte[] bytes = BleCommandUtil.getInstance().getEncryptedPacket(BleCommandUtil.DANAR_PACKET__OPCODE_ENCRYPTION__PUMP_CHECK, null, devicename);
if (L.isEnabled(L.PUMPBTCOMM))
log.debug(">>>>> " + "ENCRYPTION__PUMP_CHECK (0x00)" + " " + DanaRS_Packet.toHexString(bytes));
writeCharacteristic_NO_RESPONSE(getUARTWriteBTGattChar(), bytes);
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRv2/comm/MsgHistoryEvents_v2.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRv2/comm/MsgHistoryEvents_v2.java
index b12116e1a0..32ac8862ee 100644
--- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRv2/comm/MsgHistoryEvents_v2.java
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRv2/comm/MsgHistoryEvents_v2.java
@@ -26,23 +26,30 @@ public class MsgHistoryEvents_v2 extends MessageBase {
public static long lastEventTimeLoaded = 0;
- public MsgHistoryEvents_v2(long from) {
- SetCommand(0xE003);
- GregorianCalendar gfrom = new GregorianCalendar();
- gfrom.setTimeInMillis(from);
- AddParamDate(gfrom);
- done = false;
- if (L.isEnabled(L.PUMPCOMM))
- log.debug("New message");
+ public MsgHistoryEvents_v2() {
+ this(0);
}
- public MsgHistoryEvents_v2() {
+ public MsgHistoryEvents_v2(long from) {
SetCommand(0xE003);
- AddParamByte((byte) 0);
- AddParamByte((byte) 1);
- AddParamByte((byte) 1);
- AddParamByte((byte) 0);
- AddParamByte((byte) 0);
+
+ if (from > DateUtil.now()) {
+ log.debug("Asked to load from the future");
+ from = 0;
+ }
+
+ if (from == 0) {
+ AddParamByte((byte) 0);
+ AddParamByte((byte) 1);
+ AddParamByte((byte) 1);
+ AddParamByte((byte) 0);
+ AddParamByte((byte) 0);
+ } else {
+ GregorianCalendar gfrom = new GregorianCalendar();
+ gfrom.setTimeInMillis(from);
+ AddParamDate(gfrom);
+ }
+
done = false;
if (L.isEnabled(L.PUMPCOMM))
log.debug("New message");
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRv2/services/DanaRv2ExecutionService.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRv2/services/DanaRv2ExecutionService.java
index 073cbbde1e..f51f846978 100644
--- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRv2/services/DanaRv2ExecutionService.java
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRv2/services/DanaRv2ExecutionService.java
@@ -25,6 +25,7 @@ import info.nightscout.androidaps.interfaces.PumpInterface;
import info.nightscout.androidaps.logging.L;
import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin;
import info.nightscout.androidaps.plugins.ConfigBuilder.ProfileFunctions;
+import info.nightscout.androidaps.plugins.NSClientInternal.NSUpload;
import info.nightscout.androidaps.plugins.Overview.Dialogs.BolusProgressDialog;
import info.nightscout.androidaps.plugins.Overview.Dialogs.ErrorHelperActivity;
import info.nightscout.androidaps.plugins.Overview.events.EventNewNotification;
@@ -71,7 +72,6 @@ import info.nightscout.androidaps.plugins.Treatments.Treatment;
import info.nightscout.androidaps.queue.Callback;
import info.nightscout.androidaps.queue.commands.Command;
import info.nightscout.utils.DateUtil;
-import info.nightscout.androidaps.plugins.NSClientInternal.NSUpload;
import info.nightscout.utils.SP;
import info.nightscout.utils.T;
@@ -156,6 +156,7 @@ public class DanaRv2ExecutionService extends AbstractDanaRExecutionService {
}
public void getPumpStatus() {
+ DanaRPump danaRPump = DanaRPump.getInstance();
try {
MainApp.bus().post(new EventPumpStatusChanged(MainApp.gs(R.string.gettingpumpstatus)));
MsgStatus statusMsg = new MsgStatus();
@@ -164,7 +165,7 @@ public class DanaRv2ExecutionService extends AbstractDanaRExecutionService {
MsgStatusBolusExtended_v2 exStatusMsg = new MsgStatusBolusExtended_v2();
MsgCheckValue_v2 checkValue = new MsgCheckValue_v2();
- if (mDanaRPump.isNewPump) {
+ if (danaRPump.isNewPump) {
mSerialIOThread.sendMessage(checkValue);
if (!checkValue.received) {
return;
@@ -179,11 +180,11 @@ public class DanaRv2ExecutionService extends AbstractDanaRExecutionService {
MainApp.bus().post(new EventPumpStatusChanged(MainApp.gs(R.string.gettingextendedbolusstatus)));
mSerialIOThread.sendMessage(exStatusMsg);
- mDanaRPump.lastConnection = System.currentTimeMillis();
+ danaRPump.lastConnection = System.currentTimeMillis();
Profile profile = ProfileFunctions.getInstance().getProfile();
PumpInterface pump = ConfigBuilderPlugin.getPlugin().getActivePump();
- if (profile != null && Math.abs(mDanaRPump.currentBasal - profile.getBasal()) >= pump.getPumpDescription().basalStep) {
+ if (profile != null && Math.abs(danaRPump.currentBasal - profile.getBasal()) >= pump.getPumpDescription().basalStep) {
MainApp.bus().post(new EventPumpStatusChanged(MainApp.gs(R.string.gettingpumpsettings)));
mSerialIOThread.sendMessage(new MsgSettingBasal());
if (!pump.isThisProfileSet(profile) && !ConfigBuilderPlugin.getPlugin().getCommandQueue().isRunning(Command.CommandType.BASALPROFILE)) {
@@ -193,7 +194,7 @@ public class DanaRv2ExecutionService extends AbstractDanaRExecutionService {
MainApp.bus().post(new EventPumpStatusChanged(MainApp.gs(R.string.gettingpumptime)));
mSerialIOThread.sendMessage(new MsgSettingPumpTime());
- long timeDiff = (mDanaRPump.pumpTime - System.currentTimeMillis()) / 1000L;
+ long timeDiff = (danaRPump.pumpTime - System.currentTimeMillis()) / 1000L;
if (L.isEnabled(L.PUMP))
log.debug("Pump time difference: " + timeDiff + " seconds");
if (Math.abs(timeDiff) > 3) {
@@ -209,7 +210,7 @@ public class DanaRv2ExecutionService extends AbstractDanaRExecutionService {
MainApp.instance().startActivity(i);
//deinitialize pump
- mDanaRPump.lastConnection = 0;
+ danaRPump.lastConnection = 0;
MainApp.bus().post(new EventDanaRNewStatus());
MainApp.bus().post(new EventInitializationChanged());
return;
@@ -218,14 +219,14 @@ public class DanaRv2ExecutionService extends AbstractDanaRExecutionService {
// add 10sec to be sure we are over minute (will be cutted off anyway)
mSerialIOThread.sendMessage(new MsgSetTime(new Date(DateUtil.now() + T.secs(10).msecs())));
mSerialIOThread.sendMessage(new MsgSettingPumpTime());
- timeDiff = (mDanaRPump.pumpTime - System.currentTimeMillis()) / 1000L;
+ timeDiff = (danaRPump.pumpTime - System.currentTimeMillis()) / 1000L;
if (L.isEnabled(L.PUMP))
log.debug("Pump time difference: " + timeDiff + " seconds");
}
}
long now = System.currentTimeMillis();
- if (mDanaRPump.lastSettingsRead + 60 * 60 * 1000L < now || !pump.isInitialized()) {
+ if (danaRPump.lastSettingsRead + 60 * 60 * 1000L < now || !pump.isInitialized()) {
MainApp.bus().post(new EventPumpStatusChanged(MainApp.gs(R.string.gettingpumpsettings)));
mSerialIOThread.sendMessage(new MsgSettingShippingInfo());
mSerialIOThread.sendMessage(new MsgSettingActiveProfile());
@@ -238,7 +239,7 @@ public class DanaRv2ExecutionService extends AbstractDanaRExecutionService {
mSerialIOThread.sendMessage(new MsgSettingProfileRatios());
mSerialIOThread.sendMessage(new MsgSettingUserOptions());
mSerialIOThread.sendMessage(new MsgSettingProfileRatiosAll());
- mDanaRPump.lastSettingsRead = now;
+ danaRPump.lastSettingsRead = now;
}
loadEvents();
@@ -246,13 +247,13 @@ public class DanaRv2ExecutionService extends AbstractDanaRExecutionService {
MainApp.bus().post(new EventDanaRNewStatus());
MainApp.bus().post(new EventInitializationChanged());
NSUpload.uploadDeviceStatus();
- if (mDanaRPump.dailyTotalUnits > mDanaRPump.maxDailyTotalUnits * Constants.dailyLimitWarning) {
+ if (danaRPump.dailyTotalUnits > danaRPump.maxDailyTotalUnits * Constants.dailyLimitWarning) {
if (L.isEnabled(L.PUMP))
- log.debug("Approaching daily limit: " + mDanaRPump.dailyTotalUnits + "/" + mDanaRPump.maxDailyTotalUnits);
+ log.debug("Approaching daily limit: " + danaRPump.dailyTotalUnits + "/" + danaRPump.maxDailyTotalUnits);
if (System.currentTimeMillis() > lastApproachingDailyLimit + 30 * 60 * 1000) {
Notification reportFail = new Notification(Notification.APPROACHING_DAILY_LIMIT, MainApp.gs(R.string.approachingdailylimit), Notification.URGENT);
MainApp.bus().post(new EventNewNotification(reportFail));
- NSUpload.uploadError(MainApp.gs(R.string.approachingdailylimit) + ": " + mDanaRPump.dailyTotalUnits + "/" + mDanaRPump.maxDailyTotalUnits + "U");
+ NSUpload.uploadError(MainApp.gs(R.string.approachingdailylimit) + ": " + danaRPump.dailyTotalUnits + "/" + danaRPump.maxDailyTotalUnits + "U");
lastApproachingDailyLimit = System.currentTimeMillis();
}
}
@@ -262,8 +263,9 @@ public class DanaRv2ExecutionService extends AbstractDanaRExecutionService {
}
public boolean tempBasal(int percent, int durationInHours) {
+ DanaRPump danaRPump = DanaRPump.getInstance();
if (!isConnected()) return false;
- if (mDanaRPump.isTempBasalInProgress) {
+ if (danaRPump.isTempBasalInProgress) {
MainApp.bus().post(new EventPumpStatusChanged(MainApp.gs(R.string.stoppingtempbasal)));
mSerialIOThread.sendMessage(new MsgSetTempBasalStop());
SystemClock.sleep(500);
@@ -277,8 +279,9 @@ public class DanaRv2ExecutionService extends AbstractDanaRExecutionService {
}
public boolean highTempBasal(int percent) {
+ DanaRPump danaRPump = DanaRPump.getInstance();
if (!isConnected()) return false;
- if (mDanaRPump.isTempBasalInProgress) {
+ if (danaRPump.isTempBasalInProgress) {
MainApp.bus().post(new EventPumpStatusChanged(MainApp.gs(R.string.stoppingtempbasal)));
mSerialIOThread.sendMessage(new MsgSetTempBasalStop());
SystemClock.sleep(500);
@@ -292,13 +295,14 @@ public class DanaRv2ExecutionService extends AbstractDanaRExecutionService {
}
public boolean tempBasalShortDuration(int percent, int durationInMinutes) {
+ DanaRPump danaRPump = DanaRPump.getInstance();
if (durationInMinutes != 15 && durationInMinutes != 30) {
log.error("Wrong duration param");
return false;
}
if (!isConnected()) return false;
- if (mDanaRPump.isTempBasalInProgress) {
+ if (danaRPump.isTempBasalInProgress) {
MainApp.bus().post(new EventPumpStatusChanged(MainApp.gs(R.string.stoppingtempbasal)));
mSerialIOThread.sendMessage(new MsgSetTempBasalStop());
SystemClock.sleep(500);
@@ -449,6 +453,7 @@ public class DanaRv2ExecutionService extends AbstractDanaRExecutionService {
}
public PumpEnactResult loadEvents() {
+ DanaRPump danaRPump = DanaRPump.getInstance();
if (!MainApp.getSpecificPlugin(DanaRv2Plugin.class).isInitialized()) {
PumpEnactResult result = new PumpEnactResult().success(false);
@@ -460,16 +465,10 @@ public class DanaRv2ExecutionService extends AbstractDanaRExecutionService {
if (!isConnected())
return new PumpEnactResult().success(false);
SystemClock.sleep(300);
- MsgHistoryEvents_v2 msg;
- if (lastHistoryFetched == 0) {
- msg = new MsgHistoryEvents_v2();
- if (L.isEnabled(L.PUMP))
- log.debug("Loading complete event history");
- } else {
- msg = new MsgHistoryEvents_v2(lastHistoryFetched);
- if (L.isEnabled(L.PUMP))
- log.debug("Loading event history from: " + DateUtil.dateAndTimeFullString(lastHistoryFetched));
- }
+ MsgHistoryEvents_v2 msg = new MsgHistoryEvents_v2(lastHistoryFetched);
+ if (L.isEnabled(L.PUMP))
+ log.debug("Loading event history from: " + DateUtil.dateAndTimeFullString(lastHistoryFetched));
+
mSerialIOThread.sendMessage(msg);
while (!msg.done && mRfcommSocket.isConnected()) {
SystemClock.sleep(100);
@@ -479,11 +478,12 @@ public class DanaRv2ExecutionService extends AbstractDanaRExecutionService {
lastHistoryFetched = MsgHistoryEvents_v2.lastEventTimeLoaded - T.mins(1).msecs();
else
lastHistoryFetched = 0;
- mDanaRPump.lastConnection = System.currentTimeMillis();
+ danaRPump.lastConnection = System.currentTimeMillis();
return new PumpEnactResult().success(true);
}
public boolean updateBasalsInPump(final Profile profile) {
+ DanaRPump danaRPump = DanaRPump.getInstance();
if (!isConnected()) return false;
MainApp.bus().post(new EventPumpStatusChanged(MainApp.gs(R.string.updatingbasalrates)));
double[] basal = DanaRPump.getInstance().buildDanaRProfileRecord(profile);
@@ -491,23 +491,12 @@ public class DanaRv2ExecutionService extends AbstractDanaRExecutionService {
mSerialIOThread.sendMessage(msgSet);
MsgSetActivateBasalProfile msgActivate = new MsgSetActivateBasalProfile((byte) 0);
mSerialIOThread.sendMessage(msgActivate);
- mDanaRPump.lastSettingsRead = 0; // force read full settings
+ danaRPump.lastSettingsRead = 0; // force read full settings
getPumpStatus();
MainApp.bus().post(new EventPumpStatusChanged(EventPumpStatusChanged.DISCONNECTING));
return true;
}
- void waitForWholeMinute() {
- while (true) {
- long time = DateUtil.now();
- long timeToWholeMinute = (60000 - time % 60000);
- if (timeToWholeMinute > 59800 || timeToWholeMinute < 3000)
- break;
- MainApp.bus().post(new EventPumpStatusChanged(MainApp.gs(R.string.waitingfortimesynchronization, (int) (timeToWholeMinute / 1000))));
- SystemClock.sleep(Math.min(timeToWholeMinute, 100));
- }
- }
-
public PumpEnactResult setUserOptions() {
if (!isConnected())
return new PumpEnactResult().success(false);
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsight/InsightPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsight/InsightPlugin.java
index c72da31fdf..4dcf8a41a5 100644
--- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsight/InsightPlugin.java
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsight/InsightPlugin.java
@@ -408,6 +408,12 @@ public class InsightPlugin extends PluginBase implements PumpInterface, Constrai
return basalRate;
}
+ @Override
+ public double getReservoirLevel() { return reservoirInUnits; }
+
+ @Override
+ public int getBatteryLevel() { return batteryPercent; }
+
public String getBaseBasalRateString() {
final DecimalFormat df = new DecimalFormat("#.##");
return df.format(basalRate);
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsightLocal/EventLocalInsightUpdateGUI.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsightLocal/EventLocalInsightUpdateGUI.java
new file mode 100644
index 0000000000..cc2fc15f86
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsightLocal/EventLocalInsightUpdateGUI.java
@@ -0,0 +1,6 @@
+package info.nightscout.androidaps.plugins.PumpInsightLocal;
+
+import info.nightscout.androidaps.events.EventUpdateGui;
+
+public class EventLocalInsightUpdateGUI extends EventUpdateGui {
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsightLocal/InsightAlertService.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsightLocal/InsightAlertService.java
new file mode 100644
index 0000000000..9122132de8
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsightLocal/InsightAlertService.java
@@ -0,0 +1,233 @@
+package info.nightscout.androidaps.plugins.PumpInsightLocal;
+
+import android.app.Service;
+import android.content.ComponentName;
+import android.content.Intent;
+import android.content.ServiceConnection;
+import android.media.AudioAttributes;
+import android.media.AudioManager;
+import android.media.Ringtone;
+import android.media.RingtoneManager;
+import android.net.Uri;
+import android.os.Binder;
+import android.os.Build;
+import android.os.Handler;
+import android.os.IBinder;
+import android.os.Looper;
+import android.os.Vibrator;
+import android.support.annotation.Nullable;
+
+import info.nightscout.androidaps.plugins.PumpInsightLocal.activities.InsightAlertActivity;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.remote_control.ConfirmAlertMessage;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.remote_control.SnoozeAlertMessage;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.status.GetActiveAlertMessage;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.connection_service.InsightConnectionService;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.descriptors.Alert;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.descriptors.AlertStatus;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.descriptors.AlertType;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.descriptors.InsightState;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.utils.ExceptionTranslator;
+
+public class InsightAlertService extends Service implements InsightConnectionService.StateCallback {
+
+ private LocalBinder localBinder = new LocalBinder();
+ private boolean connectionRequested;
+ private final Object $alertLock = new Object[0];
+ private Alert alert;
+ private Thread thread;
+ private InsightAlertActivity alertActivity;
+ private Ringtone ringtone;
+ private Vibrator vibrator;
+ private boolean vibrating;
+ private InsightConnectionService connectionService;
+ private long ignoreTimestamp;
+ private AlertType ignoreType;
+
+ private ServiceConnection serviceConnection = new ServiceConnection() {
+ @Override
+ public void onServiceConnected(ComponentName name, IBinder binder) {
+ connectionService = ((InsightConnectionService.LocalBinder) binder).getService();
+ connectionService.registerStateCallback(InsightAlertService.this);
+ stateChanged(connectionService.getState());
+ }
+
+ @Override
+ public void onServiceDisconnected(ComponentName name) {
+ connectionService = null;
+ }
+ };
+
+ private void retrieveRingtone() {
+ Uri uri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_RINGTONE);
+ ringtone = RingtoneManager.getRingtone(this, uri);
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
+ ringtone.setAudioAttributes(new AudioAttributes.Builder()
+ .setUsage(AudioAttributes.USAGE_NOTIFICATION_RINGTONE)
+ .setContentType(AudioAttributes.CONTENT_TYPE_UNKNOWN)
+ .setLegacyStreamType(AudioManager.STREAM_RING).build());
+ } else ringtone.setStreamType(AudioManager.STREAM_RING);
+ }
+
+ public Alert getAlert() {
+ synchronized ($alertLock) {
+ return alert;
+ }
+ }
+
+ public void setAlertActivity(InsightAlertActivity alertActivity) {
+ this.alertActivity = alertActivity;
+ }
+
+ public void ignore(AlertType alertType) {
+ synchronized ($alertLock) {
+ if (alertType == null) {
+ ignoreTimestamp = 0;
+ ignoreType = null;
+ } else {
+ ignoreTimestamp = System.currentTimeMillis();
+ ignoreType = alertType;
+ }
+ }
+ }
+
+ @Nullable
+ @Override
+ public IBinder onBind(Intent intent) {
+ return localBinder;
+ }
+
+ @Override
+ public void onCreate() {
+ vibrator = (Vibrator) getSystemService(VIBRATOR_SERVICE);
+ bindService(new Intent(this, InsightConnectionService.class), serviceConnection, BIND_AUTO_CREATE);
+ }
+
+ @Override
+ public void onDestroy() {
+ if (thread != null) thread.interrupt();
+ unbindService(serviceConnection);
+ }
+
+ @Override
+ public int onStartCommand(Intent intent, int flags, int startId) {
+ return START_STICKY;
+ }
+
+ @Override
+ public void stateChanged(InsightState state) {
+ if (state == InsightState.CONNECTED) {
+ thread = new Thread(this::queryActiveAlert);
+ thread.start();
+
+ } else if (thread != null) thread.interrupt();
+ }
+
+ private void queryActiveAlert() {
+ while (!Thread.currentThread().isInterrupted()) {
+ try {
+ Alert alert = connectionService.requestMessage(new GetActiveAlertMessage()).await().getAlert();
+ if (Thread.currentThread().isInterrupted()) {
+ connectionService.withdrawConnectionRequest(thread);
+ break;
+ }
+ synchronized ($alertLock) {
+ if ((this.alert == null && alert != null)
+ || (this.alert != null && alert == null)
+ || (this.alert != null && alert != null && !this.alert.equals(alert))) {
+ if (this.alert != null && (alert == null || this.alert.getAlertId() != alert.getAlertId())) stopAlerting();
+ this.alert = alert;
+ if (alertActivity != null && alert != null)
+ new Handler(Looper.getMainLooper()).post(() -> alertActivity.update(alert));
+ }
+ if (alert == null) {
+ stopAlerting();
+ if (connectionRequested) {
+ connectionService.withdrawConnectionRequest(this);
+ connectionRequested = false;
+ }
+ if (alertActivity != null)
+ new Handler(Looper.getMainLooper()).post(() -> alertActivity.finish());
+ } else if (!(alert.getAlertType() == ignoreType && System.currentTimeMillis() - ignoreTimestamp < 10000)) {
+ if (alert.getAlertStatus() == AlertStatus.ACTIVE) alert();
+ else stopAlerting();
+ if (!connectionRequested) {
+ connectionService.requestConnection(this);
+ connectionRequested = true;
+ }
+ if (alertActivity == null) {
+ Intent intent = new Intent(InsightAlertService.this, InsightAlertActivity.class);
+ intent.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_ACTIVITY_NEW_TASK);
+ new Handler(Looper.getMainLooper()).post(() -> startActivity(intent));
+ }
+ }
+ }
+ } catch (InterruptedException ignored) {
+ connectionService.withdrawConnectionRequest(thread);
+ break;
+ } catch (Exception ignored) {
+ }
+ try {
+ Thread.sleep(1000);
+ } catch (InterruptedException e) {
+ break;
+ }
+ }
+ if (connectionRequested) {
+ connectionService.withdrawConnectionRequest(thread);
+ connectionRequested = false;
+ }
+ if (alertActivity != null)
+ new Handler(Looper.getMainLooper()).post(() -> alertActivity.finish());
+ stopAlerting();
+ thread = null;
+ }
+
+ private void alert() {
+ if (!vibrating) {
+ vibrator.vibrate(new long[] {0, 1000, 1000}, 0);
+ vibrating = true;
+ }
+ if (ringtone == null || !ringtone.isPlaying()) {
+ retrieveRingtone();
+ ringtone.play();
+ }
+ }
+
+ private void stopAlerting() {
+ if (vibrating) {
+ vibrator.cancel();
+ vibrating = false;
+ }
+ if (ringtone != null && ringtone.isPlaying()) ringtone.stop();
+ }
+
+ public void mute() {
+ new Thread(() -> {
+ try {
+ SnoozeAlertMessage snoozeAlertMessage = new SnoozeAlertMessage();
+ snoozeAlertMessage.setAlertID(alert.getAlertId());
+ connectionService.requestMessage(snoozeAlertMessage).await();
+ } catch (Exception e) {
+ ExceptionTranslator.makeToast(InsightAlertService.this, e);
+ }
+ }).start();
+ }
+
+ public void confirm() {
+ new Thread(() -> {
+ try {
+ ConfirmAlertMessage confirmAlertMessage = new ConfirmAlertMessage();
+ confirmAlertMessage.setAlertID(alert.getAlertId());
+ connectionService.requestMessage(confirmAlertMessage).await();
+ } catch (Exception e) {
+ ExceptionTranslator.makeToast(InsightAlertService.this, e);
+ }
+ }).start();
+ }
+
+ public class LocalBinder extends Binder {
+ public InsightAlertService getService() {
+ return InsightAlertService.this;
+ }
+ }
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsightLocal/LocalInsightFragment.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsightLocal/LocalInsightFragment.java
new file mode 100644
index 0000000000..a79fdad542
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsightLocal/LocalInsightFragment.java
@@ -0,0 +1,297 @@
+package info.nightscout.androidaps.plugins.PumpInsightLocal;
+
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.Looper;
+import android.support.annotation.NonNull;
+import android.support.annotation.Nullable;
+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 android.widget.Toast;
+
+import com.squareup.otto.Subscribe;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import info.nightscout.androidaps.MainApp;
+import info.nightscout.androidaps.R;
+import info.nightscout.androidaps.plugins.Common.SubscriberFragment;
+import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.parameter_blocks.TBROverNotificationBlock;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.descriptors.ActiveBasalRate;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.descriptors.ActiveBolus;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.descriptors.ActiveTBR;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.descriptors.CartridgeStatus;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.descriptors.TotalDailyDose;
+import info.nightscout.androidaps.queue.Callback;
+import info.nightscout.utils.DateUtil;
+import info.nightscout.utils.DecimalFormatter;
+
+public class LocalInsightFragment extends SubscriberFragment implements View.OnClickListener {
+
+ private static final boolean ENABLE_OPERATING_MODE_BUTTON = false;
+
+ private boolean viewsCreated;
+ private Button operatingMode;
+ private Button tbrOverNotification;
+ private Button refresh;
+ private LinearLayout statusItemContainer = null;
+
+ private Callback operatingModeCallback;
+ private Callback tbrOverNotificationCallback;
+ private Callback refreshCallback;
+
+ @Nullable
+ @Override
+ public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
+ View view = inflater.inflate(R.layout.local_insight_fragment, container, false);
+ statusItemContainer = view.findViewById(R.id.status_item_container);
+ tbrOverNotification = view.findViewById(R.id.tbr_over_notification);
+ tbrOverNotification.setOnClickListener(this);
+ operatingMode = view.findViewById(R.id.operating_mode);
+ operatingMode.setOnClickListener(this);
+ refresh = view.findViewById(R.id.refresh);
+ refresh.setOnClickListener(this);
+ viewsCreated = true;
+ return view;
+ }
+
+ @Override
+ public synchronized void onDestroyView() {
+ super.onDestroyView();
+ viewsCreated = false;
+ }
+
+ @Override
+ public void onClick(View v) {
+ if (v == operatingMode) {
+ if (LocalInsightPlugin.getInstance().getOperatingMode() != null) {
+ operatingMode.setEnabled(false);
+ operatingModeCallback = new Callback() {
+ @Override
+ public void run() {
+ new Handler(Looper.getMainLooper()).post(() -> {
+ operatingModeCallback = null;
+ updateGUI();
+ });
+ }
+ };
+ switch (LocalInsightPlugin.getInstance().getOperatingMode()) {
+ case PAUSED:
+ case STOPPED:
+ ConfigBuilderPlugin.getPlugin().getCommandQueue().startPump(operatingModeCallback);
+ break;
+ case STARTED:
+ ConfigBuilderPlugin.getPlugin().getCommandQueue().stopPump(operatingModeCallback);
+ }
+ }
+ } else if (v == tbrOverNotification) {
+ TBROverNotificationBlock notificationBlock = LocalInsightPlugin.getInstance().getTBROverNotificationBlock();
+ if (notificationBlock != null) {
+ tbrOverNotification.setEnabled(false);
+ tbrOverNotificationCallback = new Callback() {
+ @Override
+ public void run() {
+ new Handler(Looper.getMainLooper()).post(() -> {
+ tbrOverNotificationCallback = null;
+ updateGUI();
+ });
+ }
+ };
+ ConfigBuilderPlugin.getPlugin().getCommandQueue()
+ .setTBROverNotification(tbrOverNotificationCallback, !notificationBlock.isEnabled());
+ }
+ } else if (v == refresh) {
+ refresh.setEnabled(false);
+ refreshCallback = new Callback() {
+ @Override
+ public void run() {
+ new Handler(Looper.getMainLooper()).post(() -> {
+ refreshCallback = null;
+ updateGUI();
+ });
+ }
+ };
+ ConfigBuilderPlugin.getPlugin().getCommandQueue().readStatus("InsightRefreshButton", refreshCallback);
+ }
+ }
+
+ @Subscribe
+ public void onUpdateGUIEvent(EventLocalInsightUpdateGUI event) {
+ updateGUI();
+ }
+
+ @Override
+ protected void updateGUI() {
+ if (!viewsCreated) return;
+ statusItemContainer.removeAllViews();
+ if (!LocalInsightPlugin.getInstance().isInitialized()) {
+ operatingMode.setVisibility(View.GONE);
+ tbrOverNotification.setVisibility(View.GONE);
+ refresh.setVisibility(View.GONE);
+ return;
+ }
+ refresh.setVisibility(View.VISIBLE);
+ refresh.setEnabled(refreshCallback == null);
+ TBROverNotificationBlock notificationBlock = LocalInsightPlugin.getInstance().getTBROverNotificationBlock();
+ tbrOverNotification.setVisibility(notificationBlock == null ? View.GONE : View.VISIBLE);
+ if (notificationBlock != null)
+ tbrOverNotification.setText(notificationBlock.isEnabled() ? R.string.disable_tbr_over_notification : R.string.enable_tbr_over_notification);
+ tbrOverNotification.setEnabled(tbrOverNotificationCallback == null);
+ List statusItems = new ArrayList<>();
+ getConnectionStatusItem(statusItems);
+ getLastConnectedItem(statusItems);
+ getOperatingModeItem(statusItems);
+ getBatteryStatusItem(statusItems);
+ getCartridgeStatusItem(statusItems);
+ getTDDItems(statusItems);
+ getBaseBasalRateItem(statusItems);
+ getTBRItem(statusItems);
+ getBolusItems(statusItems);
+ for (int i = 0; i < statusItems.size(); i++) {
+ statusItemContainer.addView(statusItems.get(i));
+ if (i != statusItems.size() - 1)
+ getLayoutInflater().inflate(R.layout.local_insight_status_delimitter, statusItemContainer);
+ }
+ }
+
+ private View getStatusItem(String label, String value) {
+ View statusItem = getLayoutInflater().inflate(R.layout.local_insight_status_item, null);
+ ((TextView) statusItem.findViewById(R.id.label)).setText(label);
+ ((TextView) statusItem.findViewById(R.id.value)).setText(value);
+ return statusItem;
+ }
+
+ private void getConnectionStatusItem(List statusItems) {
+ int string = 0;
+ switch (LocalInsightPlugin.getInstance().getConnectionService().getState()) {
+ case NOT_PAIRED:
+ string = R.string.not_paired;
+ break;
+ case DISCONNECTED:
+ string = R.string.disconnected;
+ break;
+ case CONNECTING:
+ case SATL_CONNECTION_REQUEST:
+ case SATL_KEY_REQUEST:
+ case SATL_SYN_REQUEST:
+ case SATL_VERIFY_CONFIRM_REQUEST:
+ case SATL_VERIFY_DISPLAY_REQUEST:
+ case APP_ACTIVATE_PARAMETER_SERVICE:
+ case APP_ACTIVATE_STATUS_SERVICE:
+ case APP_BIND_MESSAGE:
+ case APP_CONNECT_MESSAGE:
+ case APP_FIRMWARE_VERSIONS:
+ case APP_SYSTEM_IDENTIFICATION:
+ case AWAITING_CODE_CONFIRMATION:
+ string = R.string.connecting;
+ break;
+ case CONNECTED:
+ string = R.string.connected;
+ break;
+ case RECOVERING:
+ string = R.string.recovering;
+ break;
+ }
+ statusItems.add(getStatusItem(MainApp.gs(R.string.insight_status), MainApp.gs(string)));
+ }
+
+ private void getLastConnectedItem(List statusItems) {
+ switch (LocalInsightPlugin.getInstance().getConnectionService().getState()) {
+ case CONNECTED:
+ case NOT_PAIRED:
+ return;
+ default:
+ long lastConnection = LocalInsightPlugin.getInstance().getConnectionService().getLastConnected();
+ if (lastConnection == 0) return;
+ int min = (int) ((System.currentTimeMillis() - lastConnection) / 60000);
+ statusItems.add(getStatusItem(MainApp.gs(R.string.last_connected), DateUtil.timeString(lastConnection)));
+ }
+ }
+
+ private void getOperatingModeItem(List statusItems) {
+ if (LocalInsightPlugin.getInstance().getOperatingMode() == null) {
+ operatingMode.setVisibility(View.GONE);
+ return;
+ }
+ int string = 0;
+ if (ENABLE_OPERATING_MODE_BUTTON) operatingMode.setVisibility(View.VISIBLE);
+ operatingMode.setEnabled(operatingModeCallback == null);
+ switch (LocalInsightPlugin.getInstance().getOperatingMode()) {
+ case STARTED:
+ operatingMode.setText(R.string.stop_pump);
+ string = R.string.started;
+ break;
+ case STOPPED:
+ operatingMode.setText(R.string.start_pump);
+ string = R.string.stopped;
+ break;
+ case PAUSED:
+ operatingMode.setText(R.string.start_pump);
+ string = R.string.paused;
+ break;
+ }
+ statusItems.add(getStatusItem(MainApp.gs(R.string.operating_mode), MainApp.gs(string)));
+ }
+
+ private void getBatteryStatusItem(List statusItems) {
+ if (LocalInsightPlugin.getInstance().getBatteryStatus() == null) return;
+ statusItems.add(getStatusItem(MainApp.gs(R.string.pump_battery_label),
+ LocalInsightPlugin.getInstance().getBatteryStatus().getBatteryAmount() + "%"));
+ }
+
+ private void getCartridgeStatusItem(List statusItems) {
+ CartridgeStatus cartridgeStatus = LocalInsightPlugin.getInstance().getCartridgeStatus();
+ if (cartridgeStatus == null) return;
+ String status;
+ if (cartridgeStatus.isInserted())
+ status = DecimalFormatter.to2Decimal(LocalInsightPlugin.getInstance().getCartridgeStatus().getRemainingAmount()) + "U";
+ else status = MainApp.gs(R.string.not_inserted);
+ statusItems.add(getStatusItem(MainApp.gs(R.string.pump_reservoir_label), status));
+ }
+
+ private void getTDDItems(List statusItems) {
+ if (LocalInsightPlugin.getInstance().getTotalDailyDose() == null) return;
+ TotalDailyDose tdd = LocalInsightPlugin.getInstance().getTotalDailyDose();
+ statusItems.add(getStatusItem(MainApp.gs(R.string.tdd_bolus), DecimalFormatter.to2Decimal(tdd.getBolus())));
+ statusItems.add(getStatusItem(MainApp.gs(R.string.tdd_basal), DecimalFormatter.to2Decimal(tdd.getBasal())));
+ statusItems.add(getStatusItem(MainApp.gs(R.string.tdd_total), DecimalFormatter.to2Decimal(tdd.getBolusAndBasal())));
+ }
+
+ private void getBaseBasalRateItem(List statusItems) {
+ if (LocalInsightPlugin.getInstance().getActiveBasalRate() == null) return;
+ ActiveBasalRate activeBasalRate = LocalInsightPlugin.getInstance().getActiveBasalRate();
+ statusItems.add(getStatusItem(MainApp.gs(R.string.pump_basebasalrate_label),
+ DecimalFormatter.to2Decimal(activeBasalRate.getActiveBasalRate()) + " U/h (" + activeBasalRate.getActiveBasalProfileName() + ")"));
+ }
+
+ private void getTBRItem(List statusItems) {
+ if (LocalInsightPlugin.getInstance().getActiveTBR() == null) return;
+ ActiveTBR activeTBR = LocalInsightPlugin.getInstance().getActiveTBR();
+ statusItems.add(getStatusItem(MainApp.gs(R.string.pump_tempbasal_label),
+ MainApp.gs(R.string.tbr_formatter, activeTBR.getPercentage(), activeTBR.getInitialDuration() - activeTBR.getRemainingDuration(), activeTBR.getInitialDuration())));
+ }
+
+ private void getBolusItems(List statusItems) {
+ if (LocalInsightPlugin.getInstance().getActiveBoluses() == null) return;
+ for (ActiveBolus activeBolus : LocalInsightPlugin.getInstance().getActiveBoluses()) {
+ String label;
+ switch (activeBolus.getBolusType()) {
+ case MULTIWAVE:
+ label = MainApp.gs(R.string.multiwave_bolus);
+ break;
+ case EXTENDED:
+ label = MainApp.gs(R.string.extended_bolus);
+ break;
+ default:
+ continue;
+ }
+ statusItems.add(getStatusItem(label, MainApp.gs(R.string.eb_formatter, activeBolus.getRemainingAmount(), activeBolus.getInitialAmount(), activeBolus.getRemainingDuration())));
+ }
+ }
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsightLocal/LocalInsightPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsightLocal/LocalInsightPlugin.java
new file mode 100644
index 0000000000..36eca29d11
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsightLocal/LocalInsightPlugin.java
@@ -0,0 +1,1491 @@
+package info.nightscout.androidaps.plugins.PumpInsightLocal;
+
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.ServiceConnection;
+import android.os.Handler;
+import android.os.IBinder;
+import android.os.Looper;
+
+import org.json.JSONException;
+import org.json.JSONObject;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.ArrayList;
+import java.util.Calendar;
+import java.util.Collections;
+import java.util.Date;
+import java.util.List;
+import java.util.TimeZone;
+
+import info.nightscout.androidaps.BuildConfig;
+import info.nightscout.androidaps.MainApp;
+import info.nightscout.androidaps.R;
+import info.nightscout.androidaps.data.DetailedBolusInfo;
+import info.nightscout.androidaps.data.Profile;
+import info.nightscout.androidaps.data.PumpEnactResult;
+import info.nightscout.androidaps.db.CareportalEvent;
+import info.nightscout.androidaps.db.ExtendedBolus;
+import info.nightscout.androidaps.db.Source;
+import info.nightscout.androidaps.db.TDD;
+import info.nightscout.androidaps.db.TemporaryBasal;
+import info.nightscout.androidaps.events.EventInitializationChanged;
+import info.nightscout.androidaps.events.EventRefreshOverview;
+import info.nightscout.androidaps.interfaces.Constraint;
+import info.nightscout.androidaps.interfaces.ConstraintsInterface;
+import info.nightscout.androidaps.interfaces.PluginBase;
+import info.nightscout.androidaps.interfaces.PluginDescription;
+import info.nightscout.androidaps.interfaces.PluginType;
+import info.nightscout.androidaps.interfaces.PumpDescription;
+import info.nightscout.androidaps.interfaces.PumpInterface;
+import info.nightscout.androidaps.logging.L;
+import info.nightscout.androidaps.plugins.ConfigBuilder.ProfileFunctions;
+import info.nightscout.androidaps.plugins.NSClientInternal.NSUpload;
+import info.nightscout.androidaps.plugins.NSClientInternal.UploadQueue;
+import info.nightscout.androidaps.plugins.Overview.events.EventDismissNotification;
+import info.nightscout.androidaps.plugins.Overview.events.EventNewNotification;
+import info.nightscout.androidaps.plugins.Overview.events.EventOverviewBolusProgress;
+import info.nightscout.androidaps.plugins.Overview.notifications.Notification;
+import info.nightscout.androidaps.plugins.PumpCommon.defs.PumpType;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.Service;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.history.HistoryReadingDirection;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.history.ReadHistoryEventsMessage;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.history.StartReadingHistoryMessage;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.history.StopReadingHistoryMessage;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.history.history_events.BolusDeliveredEvent;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.history.history_events.BolusProgrammedEvent;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.history.history_events.CannulaFilledEvent;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.history.history_events.DateTimeChangedEvent;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.history.history_events.DefaultDateTimeSetEvent;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.history.history_events.EndOfTBREvent;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.history.history_events.HistoryEvent;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.history.history_events.OccurrenceOfAlertEvent;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.history.history_events.OperatingModeChangedEvent;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.history.history_events.PowerUpEvent;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.history.history_events.SniffingDoneEvent;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.history.history_events.StartOfTBREvent;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.history.history_events.TotalDailyDoseEvent;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.history.history_events.TubeFilledEvent;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.parameter_blocks.ActiveBRProfileBlock;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.parameter_blocks.BRProfile1Block;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.parameter_blocks.BRProfile2Block;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.parameter_blocks.BRProfile3Block;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.parameter_blocks.BRProfile4Block;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.parameter_blocks.BRProfile5Block;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.parameter_blocks.BRProfileBlock;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.parameter_blocks.FactoryMinBolusAmountBlock;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.parameter_blocks.MaxBasalAmountBlock;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.parameter_blocks.MaxBolusAmountBlock;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.parameter_blocks.TBROverNotificationBlock;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.remote_control.CancelBolusMessage;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.remote_control.CancelTBRMessage;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.remote_control.ChangeTBRMessage;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.remote_control.ConfirmAlertMessage;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.remote_control.DeliverBolusMessage;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.remote_control.SetDateTimeMessage;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.remote_control.SetOperatingModeMessage;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.remote_control.SetTBRMessage;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.status.GetActiveAlertMessage;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.status.GetActiveBasalRateMessage;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.status.GetActiveBolusesMessage;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.status.GetActiveTBRMessage;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.status.GetBatteryStatusMessage;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.status.GetCartridgeStatusMessage;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.status.GetDateTimeMessage;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.status.GetOperatingModeMessage;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.status.GetPumpStatusRegisterMessage;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.status.GetTotalDailyDoseMessage;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.status.ResetPumpStatusRegisterMessage;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.connection_service.InsightConnectionService;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.database.InsightBolusID;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.database.InsightHistoryOffset;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.database.InsightPumpID;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.descriptors.ActiveBasalRate;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.descriptors.ActiveBolus;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.descriptors.ActiveTBR;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.descriptors.AlertType;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.descriptors.BasalProfileBlock;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.descriptors.BatteryStatus;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.descriptors.BolusType;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.descriptors.CartridgeStatus;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.descriptors.InsightState;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.descriptors.OperatingMode;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.descriptors.PumpTime;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.descriptors.TotalDailyDose;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.exceptions.InsightException;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.exceptions.app_layer_errors.NoActiveTBRToCanceLException;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.utils.ExceptionTranslator;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.utils.ParameterBlockUtil;
+import info.nightscout.androidaps.plugins.Treatments.Treatment;
+import info.nightscout.androidaps.plugins.Treatments.TreatmentsPlugin;
+import info.nightscout.utils.DateUtil;
+import info.nightscout.utils.SP;
+
+public class LocalInsightPlugin extends PluginBase implements PumpInterface, ConstraintsInterface, InsightConnectionService.StateCallback {
+
+ private static LocalInsightPlugin instance = null;
+
+ private Logger log = LoggerFactory.getLogger(L.PUMP);
+
+ private PumpDescription pumpDescription;
+ private InsightAlertService alertService;
+ private InsightConnectionService connectionService;
+ private long timeOffset;
+ private ServiceConnection serviceConnection = new ServiceConnection() {
+ @Override
+ public void onServiceConnected(ComponentName name, IBinder binder) {
+ if (binder instanceof InsightConnectionService.LocalBinder) {
+ connectionService = ((InsightConnectionService.LocalBinder) binder).getService();
+ connectionService.registerStateCallback(LocalInsightPlugin.this);
+ } else if (binder instanceof InsightAlertService.LocalBinder) {
+ alertService = ((InsightAlertService.LocalBinder) binder).getService();
+ }
+ if (connectionService != null && alertService != null)
+ MainApp.bus().post(new EventInitializationChanged());
+ }
+
+ @Override
+ public void onServiceDisconnected(ComponentName name) {
+ connectionService = null;
+ }
+ };
+
+ private final Object $bolusLock = new Object[0];
+ private boolean bolusInProgress;
+ private int bolusID = -1;
+ private List profileBlocks;
+ private boolean limitsFetched;
+ private double maximumBolusAmount;
+ private double maximumBasalAmount;
+ private double minimumBolusAmount;
+ private double minimumBasalAmount;
+ private long lastUpdated = -1;
+ private OperatingMode operatingMode;
+ private BatteryStatus batteryStatus;
+ private CartridgeStatus cartridgeStatus;
+ private TotalDailyDose totalDailyDose;
+ private ActiveBasalRate activeBasalRate;
+ private ActiveTBR activeTBR;
+ private List activeBoluses;
+ private boolean statusLoaded;
+ private TBROverNotificationBlock tbrOverNotificationBlock;
+
+ public static LocalInsightPlugin getInstance() {
+ if (instance == null) instance = new LocalInsightPlugin();
+ return instance;
+ }
+
+ public LocalInsightPlugin() {
+ super(new PluginDescription()
+ .pluginName(R.string.insight_local)
+ .shortName(R.string.insightpump_shortname)
+ .mainType(PluginType.PUMP)
+ .description(R.string.description_pump_insight_local)
+ .fragmentClass(LocalInsightFragment.class.getName())
+ .preferencesId(R.xml.pref_insight_local));
+
+ pumpDescription = new PumpDescription();
+ pumpDescription.setPumpDescription(PumpType.AccuChekInsight);
+ }
+
+ public TBROverNotificationBlock getTBROverNotificationBlock() {
+ return tbrOverNotificationBlock;
+ }
+
+ public long getLastUpdated() {
+ return lastUpdated;
+ }
+
+ public InsightConnectionService getConnectionService() {
+ return connectionService;
+ }
+
+ public OperatingMode getOperatingMode() {
+ return operatingMode;
+ }
+
+ public BatteryStatus getBatteryStatus() {
+ return batteryStatus;
+ }
+
+ public CartridgeStatus getCartridgeStatus() {
+ return cartridgeStatus;
+ }
+
+ public TotalDailyDose getTotalDailyDose() {
+ return totalDailyDose;
+ }
+
+ public ActiveBasalRate getActiveBasalRate() {
+ return activeBasalRate;
+ }
+
+ public ActiveTBR getActiveTBR() {
+ return activeTBR;
+ }
+
+ public List getActiveBoluses() {
+ return activeBoluses;
+ }
+
+ @Override
+ protected void onStart() {
+ super.onStart();
+ MainApp.instance().bindService(new Intent(MainApp.instance(), InsightConnectionService.class), serviceConnection, Context.BIND_AUTO_CREATE);
+ MainApp.instance().bindService(new Intent(MainApp.instance(), InsightAlertService.class), serviceConnection, Context.BIND_AUTO_CREATE);
+ }
+
+ @Override
+ protected void onStop() {
+ super.onStop();
+ MainApp.instance().unbindService(serviceConnection);
+ }
+
+ @Override
+ public boolean isInitialized() {
+ return connectionService != null && alertService != null && connectionService.isPaired();
+ }
+
+ @Override
+ public boolean isSuspended() {
+ return operatingMode != null && operatingMode != OperatingMode.STARTED;
+ }
+
+ @Override
+ public boolean isBusy() {
+ return false;
+ }
+
+ @Override
+ public boolean isConnected() {
+ if (connectionService == null || alertService == null) return false;
+ return connectionService.getState() == InsightState.CONNECTED;
+ }
+
+ @Override
+ public boolean isConnecting() {
+ if (connectionService == null || alertService == null) return false;
+ InsightState state = connectionService.getState();
+ return state == InsightState.CONNECTING
+ || state == InsightState.APP_CONNECT_MESSAGE
+ || state == InsightState.RECOVERING;
+ }
+
+ @Override
+ public boolean isHandshakeInProgress() {
+ return false;
+ }
+
+ @Override
+ public void finishHandshaking() {
+
+ }
+
+ @Override
+ public void connect(String reason) {
+ if (connectionService != null && alertService != null)
+ connectionService.requestConnection(this);
+ }
+
+ @Override
+ public void disconnect(String reason) {
+ if (connectionService != null && alertService != null)
+ connectionService.withdrawConnectionRequest(this);
+ }
+
+ @Override
+ public void stopConnecting() {
+ if (connectionService != null && alertService != null)
+ connectionService.withdrawConnectionRequest(this);
+ }
+
+ @Override
+ public void getPumpStatus() {
+ try {
+ tbrOverNotificationBlock = ParameterBlockUtil.readParameterBlock(connectionService, Service.CONFIGURATION, TBROverNotificationBlock.class);
+ fetchStatus();
+ fetchBasalProfile();
+ fetchLimitations();
+ updatePumpTimeIfNeeded();
+ readHistory();
+ } catch (InsightException e) {
+ log.info("Exception while fetching status: " + e.getClass().getCanonicalName());
+ } catch (Exception e) {
+ log.error("Exception while fetching status", e);
+ }
+ }
+
+ private void updatePumpTimeIfNeeded() throws Exception {
+ PumpTime pumpTime = connectionService.requestMessage(new GetDateTimeMessage()).await().getPumpTime();
+ Calendar calendar = Calendar.getInstance();
+ calendar.set(Calendar.YEAR, pumpTime.getYear());
+ calendar.set(Calendar.MONTH, pumpTime.getMonth() - 1);
+ calendar.set(Calendar.DAY_OF_MONTH, pumpTime.getDay());
+ calendar.set(Calendar.HOUR_OF_DAY, pumpTime.getHour());
+ calendar.set(Calendar.MINUTE, pumpTime.getMinute());
+ calendar.set(Calendar.SECOND, pumpTime.getSecond());
+ if (Math.abs(calendar.getTimeInMillis() - System.currentTimeMillis()) > 10000) {
+ calendar.setTime(new Date());
+ pumpTime.setYear(calendar.get(Calendar.YEAR));
+ pumpTime.setMonth(calendar.get(Calendar.MONTH) + 1);
+ pumpTime.setDay(calendar.get(Calendar.DAY_OF_MONTH));
+ pumpTime.setHour(calendar.get(Calendar.HOUR_OF_DAY));
+ pumpTime.setMinute(calendar.get(Calendar.MINUTE));
+ pumpTime.setSecond(calendar.get(Calendar.SECOND));
+ SetDateTimeMessage setDateTimeMessage = new SetDateTimeMessage();
+ setDateTimeMessage.setPumpTime(pumpTime);
+ connectionService.requestMessage(setDateTimeMessage).await();
+ Notification notification = new Notification(Notification.INSIGHT_DATE_TIME_UPDATED, MainApp.gs(R.string.pump_time_updated), Notification.INFO, 60);
+ MainApp.bus().post(new EventNewNotification(notification));
+ }
+ }
+
+ private void fetchBasalProfile() throws Exception {
+ profileBlocks = ParameterBlockUtil.readParameterBlock(connectionService, Service.CONFIGURATION, BRProfile1Block.class).getProfileBlocks();
+ }
+
+ private void fetchStatus() throws Exception {
+ if (statusLoaded) {
+ GetPumpStatusRegisterMessage registerMessage = connectionService.requestMessage(new GetPumpStatusRegisterMessage()).await();
+ ResetPumpStatusRegisterMessage resetMessage = new ResetPumpStatusRegisterMessage();
+ resetMessage.setOperatingModeChanged(registerMessage.isOperatingModeChanged());
+ resetMessage.setBatteryStatusChanged(registerMessage.isBatteryStatusChanged());
+ resetMessage.setCartridgeStatusChanged(registerMessage.isCartridgeStatusChanged());
+ resetMessage.setTotalDailyDoseChanged(registerMessage.isTotalDailyDoseChanged());
+ resetMessage.setActiveTBRChanged(registerMessage.isActiveTBRChanged());
+ resetMessage.setActiveBolusesChanged(registerMessage.isActiveBolusesChanged());
+ connectionService.requestMessage(resetMessage).await();
+ if (registerMessage.isOperatingModeChanged())
+ operatingMode = connectionService.requestMessage(new GetOperatingModeMessage()).await().getOperatingMode();
+ if (registerMessage.isBatteryStatusChanged())
+ batteryStatus = connectionService.requestMessage(new GetBatteryStatusMessage()).await().getBatteryStatus();
+ if (registerMessage.isCartridgeStatusChanged())
+ cartridgeStatus = connectionService.requestMessage(new GetCartridgeStatusMessage()).await().getCartridgeStatus();
+ if (registerMessage.isTotalDailyDoseChanged())
+ totalDailyDose = connectionService.requestMessage(new GetTotalDailyDoseMessage()).await().getTDD();
+ if (operatingMode == OperatingMode.STARTED) {
+ if (registerMessage.isActiveBasalRateChanged())
+ activeBasalRate = connectionService.requestMessage(new GetActiveBasalRateMessage()).await().getActiveBasalRate();
+ if (registerMessage.isActiveTBRChanged())
+ activeTBR = connectionService.requestMessage(new GetActiveTBRMessage()).await().getActiveTBR();
+ if (registerMessage.isActiveBolusesChanged())
+ activeBoluses = connectionService.requestMessage(new GetActiveBolusesMessage()).await().getActiveBoluses();
+ } else {
+ activeBasalRate = null;
+ activeTBR = null;
+ activeBoluses = null;
+ }
+
+ } else {
+ ResetPumpStatusRegisterMessage resetMessage = new ResetPumpStatusRegisterMessage();
+ resetMessage.setOperatingModeChanged(true);
+ resetMessage.setBatteryStatusChanged(true);
+ resetMessage.setCartridgeStatusChanged(true);
+ resetMessage.setTotalDailyDoseChanged(true);
+ resetMessage.setActiveBasalRateChanged(true);
+ resetMessage.setActiveTBRChanged(true);
+ resetMessage.setActiveBolusesChanged(true);
+ connectionService.requestMessage(resetMessage).await();
+ operatingMode = connectionService.requestMessage(new GetOperatingModeMessage()).await().getOperatingMode();
+ batteryStatus = connectionService.requestMessage(new GetBatteryStatusMessage()).await().getBatteryStatus();
+ cartridgeStatus = connectionService.requestMessage(new GetCartridgeStatusMessage()).await().getCartridgeStatus();
+ totalDailyDose = connectionService.requestMessage(new GetTotalDailyDoseMessage()).await().getTDD();
+ if (operatingMode == OperatingMode.STARTED) {
+ activeBasalRate = connectionService.requestMessage(new GetActiveBasalRateMessage()).await().getActiveBasalRate();
+ activeTBR = connectionService.requestMessage(new GetActiveTBRMessage()).await().getActiveTBR();
+ activeBoluses = connectionService.requestMessage(new GetActiveBolusesMessage()).await().getActiveBoluses();
+ } else {
+ activeBasalRate = null;
+ activeTBR = null;
+ activeBoluses = null;
+ }
+ statusLoaded = true;
+ }
+ lastUpdated = System.currentTimeMillis();
+ new Handler(Looper.getMainLooper()).post(() -> {
+ MainApp.bus().post(new EventLocalInsightUpdateGUI());
+ MainApp.bus().post(new EventRefreshOverview("LocalInsightPlugin::fetchStatus"));
+ });
+ }
+
+ private void fetchLimitations() throws Exception {
+ maximumBolusAmount = ParameterBlockUtil.readParameterBlock(connectionService, Service.CONFIGURATION, MaxBolusAmountBlock.class).getAmountLimitation();
+ maximumBasalAmount = ParameterBlockUtil.readParameterBlock(connectionService, Service.CONFIGURATION, MaxBasalAmountBlock.class).getAmountLimitation();
+ minimumBolusAmount = ParameterBlockUtil.readParameterBlock(connectionService, Service.CONFIGURATION, FactoryMinBolusAmountBlock.class).getAmountLimitation();
+ minimumBasalAmount = ParameterBlockUtil.readParameterBlock(connectionService, Service.CONFIGURATION, FactoryMinBolusAmountBlock.class).getAmountLimitation();
+ this.pumpDescription.basalMaximumRate = maximumBasalAmount;
+ this.pumpDescription.basalMinimumRate = minimumBasalAmount;
+ limitsFetched = true;
+ }
+
+ @Override
+ public PumpEnactResult setNewBasalProfile(Profile profile) {
+ PumpEnactResult result = new PumpEnactResult();
+ MainApp.bus().post(new EventDismissNotification(Notification.PROFILE_NOT_SET_NOT_INITIALIZED));
+ List profileBlocks = new ArrayList<>();
+ for (int i = 0; i < profile.getBasalValues().length; i++) {
+ Profile.BasalValue basalValue = profile.getBasalValues()[i];
+ Profile.BasalValue nextValue = null;
+ if (profile.getBasalValues().length > i + 1)
+ nextValue = profile.getBasalValues()[i + 1];
+ BasalProfileBlock profileBlock = new BasalProfileBlock();
+ profileBlock.setBasalAmount(basalValue.value);
+ profileBlock.setDuration((((nextValue != null ? nextValue.timeAsSeconds : 24 * 60 * 60) - basalValue.timeAsSeconds) / 60));
+ profileBlocks.add(profileBlock);
+ }
+ try {
+ BRProfileBlock profileBlock = new BRProfile1Block();
+ profileBlock.setProfileBlocks(profileBlocks);
+ ParameterBlockUtil.writeConfigurationBlock(connectionService, profileBlock);
+ MainApp.bus().post(new EventDismissNotification(Notification.FAILED_UDPATE_PROFILE));
+ Notification notification = new Notification(Notification.PROFILE_SET_OK, MainApp.gs(R.string.profile_set_ok), Notification.INFO, 60);
+ MainApp.bus().post(new EventNewNotification(notification));
+ result.success = true;
+ result.enacted = true;
+ result.comment = MainApp.gs(R.string.virtualpump_resultok);
+ this.profileBlocks = profileBlocks;
+ try {
+ fetchStatus();
+ } catch (Exception ignored) {
+ }
+ } catch (InsightException e) {
+ log.info("Exception while setting profile: " + e.getClass().getCanonicalName());
+ Notification notification = new Notification(Notification.FAILED_UDPATE_PROFILE, MainApp.gs(R.string.failedupdatebasalprofile), Notification.URGENT);
+ MainApp.bus().post(new EventNewNotification(notification));
+ result.comment = ExceptionTranslator.getString(e);
+ } catch (Exception e) {
+ log.error("Exception while setting profile", e);
+ Notification notification = new Notification(Notification.FAILED_UDPATE_PROFILE, MainApp.gs(R.string.failedupdatebasalprofile), Notification.URGENT);
+ MainApp.bus().post(new EventNewNotification(notification));
+ result.comment = ExceptionTranslator.getString(e);
+ }
+ return result;
+ }
+
+ @Override
+ public boolean isThisProfileSet(Profile profile) {
+ if (!isInitialized() || profileBlocks == null) return true;
+ if (profile.getBasalValues().length != profileBlocks.size()) return false;
+ for (int i = 0; i < profileBlocks.size(); i++) {
+ BasalProfileBlock profileBlock = profileBlocks.get(i);
+ Profile.BasalValue basalValue = profile.getBasalValues()[i];
+ Profile.BasalValue nextValue = null;
+ if (profile.getBasalValues().length > i + 1)
+ nextValue = profile.getBasalValues()[i + 1];
+ if (profileBlock.getDuration() * 60 != (nextValue != null ? nextValue.timeAsSeconds : 24 * 60 * 60) - basalValue.timeAsSeconds)
+ return false;
+ if (Math.abs(profileBlock.getBasalAmount() - basalValue.value) > 0.01D)
+ return false;
+ }
+ return true;
+ }
+
+ @Override
+ public long lastDataTime() {
+ if (connectionService == null || alertService == null) return System.currentTimeMillis();
+ return connectionService.getLastDataTime();
+ }
+
+ @Override
+ public double getBaseBasalRate() {
+ if (connectionService == null || alertService == null) return 0;
+ if (activeBasalRate != null) return activeBasalRate.getActiveBasalRate();
+ else return 0;
+ }
+
+ @Override
+ public double getReservoirLevel() {
+ if (cartridgeStatus == null) return 0;
+ return cartridgeStatus.getRemainingAmount();
+ }
+
+ @Override
+ public int getBatteryLevel() {
+ if (batteryStatus == null) return 0;
+ return batteryStatus.getBatteryAmount();
+ }
+
+ @Override
+ public PumpEnactResult deliverTreatment(DetailedBolusInfo detailedBolusInfo) {
+ PumpEnactResult result = new PumpEnactResult();
+ if (detailedBolusInfo.insulin > 0) {
+ try {
+ synchronized ($bolusLock) {
+ DeliverBolusMessage bolusMessage = new DeliverBolusMessage();
+ bolusMessage.setBolusType(BolusType.STANDARD);
+ bolusMessage.setDuration(0);
+ bolusMessage.setExtendedAmount(0);
+ bolusMessage.setImmediateAmount(detailedBolusInfo.insulin);
+ bolusID = connectionService.requestMessage(bolusMessage).await().getBolusId();
+ }
+ result.success = true;
+ result.enacted = true;
+ Treatment t = new Treatment();
+ t.isSMB = detailedBolusInfo.isSMB;
+ final EventOverviewBolusProgress bolusingEvent = EventOverviewBolusProgress.getInstance();
+ bolusingEvent.t = t;
+ bolusingEvent.status = MainApp.gs(R.string.insight_delivered, 0d, detailedBolusInfo.insulin);
+ bolusingEvent.percent = 0;
+ MainApp.bus().post(bolusingEvent);
+ int trials = 0;
+ InsightBolusID insightBolusID = new InsightBolusID();
+ insightBolusID.bolusID = bolusID;
+ insightBolusID.timestamp = System.currentTimeMillis();
+ insightBolusID.pumpSerial = connectionService.getPumpSystemIdentification().getSerialNumber();
+ MainApp.getDbHelper().createOrUpdate(insightBolusID);
+ detailedBolusInfo.date = insightBolusID.timestamp;
+ detailedBolusInfo.source = Source.PUMP;
+ detailedBolusInfo.pumpId = insightBolusID.id;
+ TreatmentsPlugin.getPlugin().addToHistoryTreatment(detailedBolusInfo, true);
+ while (true) {
+ List activeBoluses = connectionService.requestMessage(new GetActiveBolusesMessage()).await().getActiveBoluses();
+ ActiveBolus activeBolus = null;
+ for (ActiveBolus bolus : activeBoluses) {
+ if (bolus.getBolusID() == bolusID) activeBolus = bolus;
+ }
+ if (activeBolus != null) {
+ trials = -1;
+ int percentBefore = bolusingEvent.percent;
+ bolusingEvent.percent = (int) (100D / activeBolus.getInitialAmount() * (activeBolus.getInitialAmount() - activeBolus.getRemainingAmount()));
+ bolusingEvent.status = MainApp.gs(R.string.insight_delivered, activeBolus.getInitialAmount() - activeBolus.getRemainingAmount(), activeBolus.getInitialAmount());
+ if (percentBefore != bolusingEvent.percent)
+ MainApp.bus().post(bolusingEvent);
+ } else if (trials == -1 || trials++ >= 5) break;
+ Thread.sleep(200);
+ }
+ bolusingEvent.status = MainApp.gs(R.string.insight_delivered, detailedBolusInfo.insulin, detailedBolusInfo.insulin);
+ bolusingEvent.percent = 100;
+ MainApp.bus().post(bolusingEvent);
+ readHistory();
+ fetchStatus();
+ } catch (InsightException e) {
+ log.info("Exception while delivering bolus: " + e.getClass().getCanonicalName());
+ result.comment = ExceptionTranslator.getString(e);
+ } catch (Exception e) {
+ log.error("Exception while delivering bolus", e);
+ result.comment = ExceptionTranslator.getString(e);
+ }
+ } else if (detailedBolusInfo.carbs > 0) {
+ result.success = true;
+ result.enacted = true;
+ }
+ result.carbsDelivered = detailedBolusInfo.carbs;
+ return result;
+ }
+
+ @Override
+ public void stopBolusDelivering() {
+ new Thread(() -> {
+ synchronized ($bolusLock) {
+ try {
+ alertService.ignore(AlertType.WARNING_38);
+ CancelBolusMessage cancelBolusMessage = new CancelBolusMessage();
+ cancelBolusMessage.setBolusID(bolusID);
+ connectionService.requestMessage(cancelBolusMessage).await();
+ confirmAlert(AlertType.WARNING_38);
+ } catch (InsightException e) {
+ log.info("Exception while canceling bolus: " + e.getClass().getCanonicalName());
+ } catch (Exception e) {
+ log.error("Exception while canceling bolus", e);
+ }
+ }
+ }).start();
+ }
+
+ @Override
+ public PumpEnactResult setTempBasalAbsolute(Double absoluteRate, Integer durationInMinutes, Profile profile, boolean enforceNew) {
+ PumpEnactResult result = new PumpEnactResult();
+ if (activeBasalRate == null) return result;
+ if (activeBasalRate.getActiveBasalRate() == 0) return result;
+ double percent = 100D / activeBasalRate.getActiveBasalRate() * absoluteRate;
+ if (isFakingTempsByExtendedBoluses()) {
+ PumpEnactResult cancelEBResult = cancelExtendedBolusOnly();
+ if (cancelEBResult.success) {
+ if (percent > 250) {
+ PumpEnactResult cancelTBRResult = cancelTempBasalOnly();
+ if (cancelTBRResult.success) {
+ PumpEnactResult ebResult = setExtendedBolusOnly((absoluteRate - getBaseBasalRate()) / 60D
+ * ((double) durationInMinutes), durationInMinutes);
+ if (ebResult.success) {
+ result.success = true;
+ result.enacted = true;
+ result.isPercent = false;
+ result.absolute = absoluteRate;
+ result.duration = durationInMinutes;
+ result.comment = MainApp.gs(R.string.virtualpump_resultok);
+ } else {
+ result.comment = ebResult.comment;
+ }
+ } else {
+ result.comment = cancelTBRResult.comment;
+ }
+ } else {
+ return setTempBasalPercent((int) Math.round(percent), durationInMinutes, profile, enforceNew);
+ }
+ } else {
+ result.comment = cancelEBResult.comment;
+ }
+ } else {
+ return setTempBasalPercent((int) Math.round(percent), durationInMinutes, profile, enforceNew);
+ }
+ try {
+ fetchStatus();
+ readHistory();
+ } catch (InsightException e) {
+ log.info("Exception after setting TBR: " + e.getClass().getCanonicalName());
+ } catch (Exception e) {
+ log.error("Exception after setting TBR", e);
+ }
+ return result;
+ }
+
+ @Override
+ public PumpEnactResult setTempBasalPercent(Integer percent, Integer durationInMinutes, Profile profile, boolean enforceNew) {
+ PumpEnactResult result = new PumpEnactResult();
+ percent = (int) Math.round(((double) percent) / 10d) * 10;
+ if (percent == 100) return cancelTempBasal(true);
+ else if (percent > 250) percent = 250;
+ try {
+ if (activeTBR != null) {
+ ChangeTBRMessage message = new ChangeTBRMessage();
+ message.setDuration(durationInMinutes);
+ message.setPercentage(percent);
+ connectionService.requestMessage(message);
+ } else {
+ SetTBRMessage message = new SetTBRMessage();
+ message.setDuration(durationInMinutes);
+ message.setPercentage(percent);
+ connectionService.requestMessage(message);
+ }
+ result.isPercent = true;
+ result.percent = percent;
+ result.duration = durationInMinutes;
+ result.success = true;
+ result.enacted = true;
+ result.comment = MainApp.gs(R.string.virtualpump_resultok);
+ readHistory();
+ fetchStatus();
+ } catch (InsightException e) {
+ log.info("Exception while setting TBR: " + e.getClass().getCanonicalName());
+ result.comment = ExceptionTranslator.getString(e);
+ } catch (Exception e) {
+ log.error("Exception while setting TBR", e);
+ result.comment = ExceptionTranslator.getString(e);
+ }
+ return result;
+ }
+
+ @Override
+ public PumpEnactResult setExtendedBolus(Double insulin, Integer durationInMinutes) {
+ PumpEnactResult result = cancelExtendedBolusOnly();
+ try {
+ fetchStatus();
+ readHistory();
+ } catch (InsightException e) {
+ log.info("Exception after delivering extended bolus: " + e.getClass().getCanonicalName());
+ } catch (Exception e) {
+ log.error("Exception after delivering extended bolus", e);
+ }
+ return result;
+ }
+
+ public PumpEnactResult setExtendedBolusOnly(Double insulin, Integer durationInMinutes) {
+ PumpEnactResult result = new PumpEnactResult();
+ try {
+ DeliverBolusMessage bolusMessage = new DeliverBolusMessage();
+ bolusMessage.setBolusType(BolusType.EXTENDED);
+ bolusMessage.setDuration(durationInMinutes);
+ bolusMessage.setExtendedAmount(insulin);
+ bolusMessage.setImmediateAmount(0);
+ int bolusID = connectionService.requestMessage(bolusMessage).await().getBolusId();
+ InsightBolusID insightBolusID = new InsightBolusID();
+ insightBolusID.bolusID = bolusID;
+ insightBolusID.timestamp = System.currentTimeMillis();
+ insightBolusID.pumpSerial = connectionService.getPumpSystemIdentification().getSerialNumber();
+ MainApp.getDbHelper().createOrUpdate(insightBolusID);
+ ExtendedBolus extendedBolus = new ExtendedBolus();
+ extendedBolus.date = insightBolusID.timestamp;
+ extendedBolus.source = Source.PUMP;
+ extendedBolus.durationInMinutes = durationInMinutes;
+ extendedBolus.insulin = insulin;
+ extendedBolus.pumpId = insightBolusID.id;
+ TreatmentsPlugin.getPlugin().addToHistoryExtendedBolus(extendedBolus);
+ result.success = true;
+ result.enacted = true;
+ result.comment = MainApp.gs(R.string.virtualpump_resultok);
+ } catch (InsightException e) {
+ log.info("Exception while delivering extended bolus: " + e.getClass().getCanonicalName());
+ result.comment = ExceptionTranslator.getString(e);
+ } catch (Exception e) {
+ log.error("Exception while delivering extended bolus", e);
+ result.comment = ExceptionTranslator.getString(e);
+ }
+ return result;
+ }
+
+ @Override
+ public PumpEnactResult cancelTempBasal(boolean enforceNew) {
+ PumpEnactResult result = new PumpEnactResult();
+ PumpEnactResult cancelEBResult = null;
+ if (isFakingTempsByExtendedBoluses()) cancelEBResult = cancelExtendedBolusOnly();
+ PumpEnactResult cancelTBRResult = cancelTempBasalOnly();
+ result.success = (cancelEBResult != null && cancelEBResult.success) && cancelTBRResult.success;
+ result.enacted = (cancelEBResult != null && cancelEBResult.enacted) || cancelTBRResult.enacted;
+ result.comment = cancelEBResult != null ? cancelEBResult.comment : cancelTBRResult.comment;
+ try {
+ fetchStatus();
+ readHistory();
+ } catch (InsightException e) {
+ log.info("Exception after canceling TBR: " + e.getClass().getCanonicalName());
+ } catch (Exception e) {
+ log.error("Exception after canceling TBR", e);
+ }
+ return result;
+ }
+
+ private PumpEnactResult cancelTempBasalOnly() {
+ PumpEnactResult result = new PumpEnactResult();
+ try {
+ alertService.ignore(AlertType.WARNING_36);
+ connectionService.requestMessage(new CancelTBRMessage()).await();
+ result.success = true;
+ result.enacted = true;
+ result.isTempCancel = true;
+ confirmAlert(AlertType.WARNING_36);
+ alertService.ignore(null);
+ result.comment = MainApp.gs(R.string.virtualpump_resultok);
+ } catch (NoActiveTBRToCanceLException e) {
+ result.success = true;
+ result.comment = MainApp.gs(R.string.virtualpump_resultok);
+ } catch (InsightException e) {
+ log.info("Exception while canceling TBR: " + e.getClass().getCanonicalName());
+ result.comment = ExceptionTranslator.getString(e);
+ } catch (Exception e) {
+ log.error("Exception while canceling TBR", e);
+ result.comment = ExceptionTranslator.getString(e);
+ }
+ return result;
+ }
+
+ @Override
+ public PumpEnactResult cancelExtendedBolus() {
+ PumpEnactResult result = cancelExtendedBolusOnly();
+ try {
+ fetchStatus();
+ readHistory();
+ } catch (InsightException e) {
+ log.info("Exception after canceling bolus: " + e.getClass().getCanonicalName());
+ } catch (Exception e) {
+ log.error("Exception after canceling bolus", e);
+ }
+ return result;
+ }
+
+ private PumpEnactResult cancelExtendedBolusOnly() {
+ PumpEnactResult result = new PumpEnactResult();
+ try {
+ for (ActiveBolus activeBolus : activeBoluses) {
+ if (activeBolus.getBolusType() == BolusType.EXTENDED || activeBolus.getBolusType() == BolusType.MULTIWAVE) {
+ alertService.ignore(AlertType.WARNING_38);
+ CancelBolusMessage cancelBolusMessage = new CancelBolusMessage();
+ cancelBolusMessage.setBolusID(activeBolus.getBolusID());
+ connectionService.requestMessage(cancelBolusMessage).await();
+ confirmAlert(AlertType.WARNING_38);
+ alertService.ignore(null);
+ InsightBolusID insightBolusID = MainApp.getDbHelper().getInsightBolusID(connectionService.getPumpSystemIdentification().getSerialNumber(),
+ activeBolus.getBolusID(), System.currentTimeMillis());
+ if (insightBolusID != null) {
+ ExtendedBolus extendedBolus = MainApp.getDbHelper().getExtendedBolusByPumpId(insightBolusID.id);
+ if (extendedBolus != null) {
+ extendedBolus.durationInMinutes = (int) ((System.currentTimeMillis() - extendedBolus.date) / 60000);
+ if (extendedBolus.durationInMinutes <= 0) {
+ ;
+ final String _id = extendedBolus._id;
+ if (NSUpload.isIdValid(_id))
+ NSUpload.removeCareportalEntryFromNS(_id);
+ else UploadQueue.removeID("dbAdd", _id);
+ MainApp.getDbHelper().delete(extendedBolus);
+ } else
+ TreatmentsPlugin.getPlugin().addToHistoryExtendedBolus(extendedBolus);
+ }
+ result.enacted = true;
+ result.success = true;
+ }
+ }
+ }
+ result.success = true;
+ result.comment = MainApp.gs(R.string.virtualpump_resultok);
+ } catch (InsightException e) {
+ log.info("Exception while canceling bolus: " + e.getClass().getCanonicalName());
+ result.comment = ExceptionTranslator.getString(e);
+ } catch (Exception e) {
+ log.error("Exception while canceling bolus", e);
+ result.comment = ExceptionTranslator.getString(e);
+ }
+ return result;
+ }
+
+ private void confirmAlert(AlertType alertType) {
+ try {
+ long started = System.currentTimeMillis();
+ while (System.currentTimeMillis() - started < 10000) {
+ GetActiveAlertMessage activeAlertMessage = connectionService.requestMessage(new GetActiveAlertMessage()).await();
+ if (activeAlertMessage.getAlert() != null) {
+ if (activeAlertMessage.getAlert().getAlertType() == alertType) {
+ ConfirmAlertMessage confirmMessage = new ConfirmAlertMessage();
+ confirmMessage.setAlertID(activeAlertMessage.getAlert().getAlertId());
+ connectionService.requestMessage(confirmMessage).await();
+ } else break;
+ }
+ }
+ } catch (InsightException e) {
+ log.info("Exception while confirming alert: " + e.getClass().getCanonicalName());
+ } catch (Exception e) {
+ log.error("Exception while confirming alert", e);
+ }
+ }
+
+ @Override
+ public JSONObject getJSONStatus(Profile profile, String profileName) {
+ long now = System.currentTimeMillis();
+ if (System.currentTimeMillis() - connectionService.getLastConnected() > (60 * 60 * 1000)) {
+ return null;
+ }
+
+ final JSONObject pump = new JSONObject();
+ final JSONObject battery = new JSONObject();
+ final JSONObject status = new JSONObject();
+ final JSONObject extended = new JSONObject();
+ try {
+ status.put("timestamp", DateUtil.toISOString(connectionService.getLastConnected()));
+ extended.put("Version", BuildConfig.VERSION_NAME + "-" + BuildConfig.BUILDVERSION);
+ try {
+ extended.put("ActiveProfile", ProfileFunctions.getInstance().getProfileName());
+ } catch (Exception e) {
+ }
+ TemporaryBasal tb = TreatmentsPlugin.getPlugin().getTempBasalFromHistory(now);
+ if (tb != null) {
+ extended.put("TempBasalAbsoluteRate", tb.tempBasalConvertedToAbsolute(now, profile));
+ extended.put("TempBasalStart", DateUtil.dateAndTimeString(tb.date));
+ extended.put("TempBasalRemaining", tb.getPlannedRemainingMinutes());
+ }
+ ExtendedBolus eb = TreatmentsPlugin.getPlugin().getExtendedBolusFromHistory(now);
+ if (eb != null) {
+ extended.put("ExtendedBolusAbsoluteRate", eb.absoluteRate());
+ extended.put("ExtendedBolusStart", DateUtil.dateAndTimeString(eb.date));
+ extended.put("ExtendedBolusRemaining", eb.getPlannedRemainingMinutes());
+ }
+ extended.put("BaseBasalRate", getBaseBasalRate());
+ status.put("timestamp", DateUtil.toISOString(now));
+
+ pump.put("extended", extended);
+ if (statusLoaded) {
+ status.put("status", operatingMode != OperatingMode.STARTED ? "suspended" : "normal");
+ pump.put("status", status);
+ battery.put("percent", batteryStatus.getBatteryAmount());
+ pump.put("battery", battery);
+ pump.put("reservoir", cartridgeStatus.getRemainingAmount());
+ }
+ pump.put("clock", DateUtil.toISOString(now));
+ } catch (JSONException e) {
+ log.error("Unhandled exception", e);
+ }
+ return pump;
+ }
+
+ @Override
+ public String deviceID() {
+ if (connectionService == null || alertService == null) return null;
+ return connectionService.getPumpSystemIdentification().getSerialNumber();
+ }
+
+ public PumpEnactResult stopPump() {
+ PumpEnactResult result = new PumpEnactResult();
+ try {
+ SetOperatingModeMessage operatingModeMessage = new SetOperatingModeMessage();
+ operatingModeMessage.setOperatingMode(OperatingMode.STOPPED);
+ connectionService.requestMessage(operatingModeMessage).await();
+ result.success = true;
+ result.enacted = true;
+ fetchStatus();
+ readHistory();
+ } catch (InsightException e) {
+ log.info("Exception while stopping pump: " + e.getClass().getCanonicalName());
+ result.comment = ExceptionTranslator.getString(e);
+ } catch (Exception e) {
+ log.error("Exception while stopping pump", e);
+ result.comment = ExceptionTranslator.getString(e);
+ }
+ return result;
+ }
+
+ public PumpEnactResult startPump() {
+ PumpEnactResult result = new PumpEnactResult();
+ try {
+ SetOperatingModeMessage operatingModeMessage = new SetOperatingModeMessage();
+ operatingModeMessage.setOperatingMode(OperatingMode.STARTED);
+ connectionService.requestMessage(operatingModeMessage).await();
+ result.success = true;
+ result.enacted = true;
+ fetchStatus();
+ readHistory();
+ } catch (InsightException e) {
+ log.info("Exception while starting pump: " + e.getClass().getCanonicalName());
+ } catch (Exception e) {
+ log.error("Exception while starting pump", e);
+ result.comment = ExceptionTranslator.getString(e);
+ }
+ return result;
+ }
+
+ public PumpEnactResult setTBROverNotification(boolean enabled) {
+ PumpEnactResult result = new PumpEnactResult();
+ boolean valueBefore = tbrOverNotificationBlock.isEnabled();
+ tbrOverNotificationBlock.setEnabled(enabled);
+ try {
+ ParameterBlockUtil.writeConfigurationBlock(connectionService, tbrOverNotificationBlock);
+ result.success = true;
+ result.enacted = true;
+ } catch (InsightException e) {
+ tbrOverNotificationBlock.setEnabled(valueBefore);
+ log.info("Exception while updating TBR notification block: " + e.getClass().getSimpleName());
+ result.comment = ExceptionTranslator.getString(e);
+ } catch (Exception e) {
+ tbrOverNotificationBlock.setEnabled(valueBefore);
+ log.error("Exception while updating TBR notification block", e);
+ result.comment = ExceptionTranslator.getString(e);
+ }
+ return result;
+ }
+
+ @Override
+ public PumpDescription getPumpDescription() {
+ return pumpDescription;
+ }
+
+ @Override
+ public String shortStatus(boolean veryShort) {
+ StringBuilder ret = new StringBuilder();
+ if (connectionService.getLastConnected() != 0) {
+ Long agoMsec = System.currentTimeMillis() - connectionService.getLastConnected();
+ int agoMin = (int) (agoMsec / 60d / 1000d);
+ ret.append(MainApp.gs(R.string.short_status_last_connected, agoMin) + "\n");
+ }
+ if (activeTBR != null) {
+ ret.append(MainApp.gs(R.string.short_status_tbr, activeTBR.getPercentage(),
+ activeTBR.getInitialDuration() - activeTBR.getRemainingDuration(), activeTBR.getInitialDuration()) + "\n");
+ }
+ if (activeBoluses != null) for (ActiveBolus activeBolus : activeBoluses) {
+ if (activeBolus.getBolusType() == BolusType.STANDARD) continue;
+ ret.append(MainApp.gs(activeBolus.getBolusType() == BolusType.MULTIWAVE ? R.string.short_status_multiwave : R.string.short_status_extended,
+ activeBolus.getRemainingAmount(), activeBolus.getInitialAmount(), activeBolus.getRemainingDuration()) + "\n");
+ }
+ if (!veryShort && totalDailyDose != null) {
+ ret.append(MainApp.gs(R.string.short_status_tdd, totalDailyDose.getBolusAndBasal()) + "\n");
+ }
+ if (cartridgeStatus != null) {
+ ret.append(MainApp.gs(R.string.short_status_reservoir, cartridgeStatus.getRemainingAmount()) + "\n");
+ }
+ if (batteryStatus != null) {
+ ret.append(MainApp.gs(R.string.short_status_battery, batteryStatus.getBatteryAmount()) + "\n");
+ }
+ return ret.toString();
+ }
+
+ @Override
+ public boolean isFakingTempsByExtendedBoluses() {
+ return SP.getBoolean("insight_enable_tbr_emulation", false);
+ }
+
+ @Override
+ public PumpEnactResult loadTDDs() {
+ return new PumpEnactResult().success(true);
+ }
+
+ private void readHistory() {
+ try {
+ PumpTime pumpTime = connectionService.requestMessage(new GetDateTimeMessage()).await().getPumpTime();
+ String pumpSerial = connectionService.getPumpSystemIdentification().getSerialNumber();
+ timeOffset = Calendar.getInstance(TimeZone.getTimeZone("UTC")).getTimeInMillis() - parseDate(pumpTime.getYear(),
+ pumpTime.getMonth(), pumpTime.getDay(), pumpTime.getHour(), pumpTime.getMinute(), pumpTime.getSecond());
+ InsightHistoryOffset historyOffset = MainApp.getDbHelper().getInsightHistoryOffset(pumpSerial);
+ try {
+ List historyEvents = new ArrayList<>();
+ if (historyOffset == null) {
+ StartReadingHistoryMessage startMessage = new StartReadingHistoryMessage();
+ startMessage.setDirection(HistoryReadingDirection.BACKWARD);
+ startMessage.setOffset(0xFFFFFFFF);
+ connectionService.requestMessage(startMessage).await();
+ for (int i = 0; i < 50; i++) {
+ List newEvents = connectionService.requestMessage(new ReadHistoryEventsMessage()).await().getHistoryEvents();
+ if (newEvents.size() == 0) break;
+ historyEvents.addAll(newEvents);
+ }
+ } else {
+ StartReadingHistoryMessage startMessage = new StartReadingHistoryMessage();
+ startMessage.setDirection(HistoryReadingDirection.FORWARD);
+ startMessage.setOffset(historyOffset.offset + 1);
+ connectionService.requestMessage(startMessage).await();
+ while (true) {
+ List newEvents = connectionService.requestMessage(new ReadHistoryEventsMessage()).await().getHistoryEvents();
+ if (newEvents.size() == 0) break;
+ historyEvents.addAll(newEvents);
+ }
+ }
+ processHistoryEvents(pumpSerial, historyEvents);
+ } catch (InsightException e) {
+ log.info("Error while reading history: " + e.getClass().getSimpleName());
+ } catch (Exception e) {
+ log.error("Error while reading history", e);
+ } finally {
+ try {
+ connectionService.requestMessage(new StopReadingHistoryMessage()).await();
+ } catch (Exception ignored) {
+ }
+ }
+ } catch (InsightException e) {
+ log.info("Exception while reading history: " + e.getClass().getSimpleName());
+ } catch (Exception e) {
+ log.error("Exception while reading history", e);
+ }
+ new Handler(Looper.getMainLooper()).post(() -> MainApp.bus().post(new EventRefreshOverview("LocalInsightPlugin::readHistory")));
+ }
+
+ private void processHistoryEvents(String serial, List historyEvents) {
+ Collections.sort(historyEvents);
+ Collections.reverse(historyEvents);
+ List temporaryBasals = new ArrayList<>();
+ List pumpStartedEvents = new ArrayList<>();
+ for (HistoryEvent historyEvent : historyEvents)
+ if (!processHistoryEvent(serial, temporaryBasals, pumpStartedEvents, historyEvent))
+ break;
+ Collections.reverse(temporaryBasals);
+ for (InsightPumpID pumpID : pumpStartedEvents) {
+ InsightPumpID stoppedEvent = MainApp.getDbHelper().getPumpStoppedEvent(pumpID.pumpSerial, pumpID.timestamp);
+ if (stoppedEvent == null) continue;
+ long tbrStart = stoppedEvent.timestamp + 10000;
+ TemporaryBasal temporaryBasal = new TemporaryBasal();
+ temporaryBasal.durationInMinutes = (int) ((pumpID.timestamp - tbrStart) / 60000);
+ temporaryBasal.date = tbrStart;
+ temporaryBasal.source = Source.PUMP;
+ temporaryBasal.pumpId = pumpID.id;
+ temporaryBasal.percentRate = 0;
+ temporaryBasal.isAbsolute = false;
+ temporaryBasals.add(temporaryBasal);
+ }
+ Collections.sort(temporaryBasals, (o1, o2) -> (int) (o1.date - o2.date));
+ for (TemporaryBasal temporaryBasal : temporaryBasals)
+ TreatmentsPlugin.getPlugin().addToHistoryTempBasal(temporaryBasal);
+ if (historyEvents.size() > 0) {
+ InsightHistoryOffset historyOffset = new InsightHistoryOffset();
+ historyOffset.pumpSerial = serial;
+ historyOffset.offset = historyEvents.get(0).getEventPosition();
+ MainApp.getDbHelper().createOrUpdate(historyOffset);
+ }
+ }
+
+ private boolean processHistoryEvent(String serial, List temporaryBasals, List pumpStartedEvents, HistoryEvent event) {
+ if (event instanceof DefaultDateTimeSetEvent) return false;
+ else if (event instanceof DateTimeChangedEvent)
+ processDateTimeChangedEvent((DateTimeChangedEvent) event);
+ else if (event instanceof CannulaFilledEvent)
+ processCannulaFilledEvent((CannulaFilledEvent) event);
+ else if (event instanceof TotalDailyDoseEvent)
+ processTotalDailyDoseEvent((TotalDailyDoseEvent) event);
+ else if (event instanceof TubeFilledEvent) processTubeFilledEvent((TubeFilledEvent) event);
+ else if (event instanceof SniffingDoneEvent)
+ processSniffingDoneEvent((SniffingDoneEvent) event);
+ else if (event instanceof PowerUpEvent) processPowerUpEvent((PowerUpEvent) event);
+ else if (event instanceof OperatingModeChangedEvent)
+ processOperatingModeChangedEvent(serial, pumpStartedEvents, (OperatingModeChangedEvent) event);
+ else if (event instanceof StartOfTBREvent)
+ processStartOfTBREvent(serial, temporaryBasals, (StartOfTBREvent) event);
+ else if (event instanceof EndOfTBREvent)
+ processEndOfTBREvent(serial, temporaryBasals, (EndOfTBREvent) event);
+ else if (event instanceof BolusProgrammedEvent)
+ processBolusProgrammedEvent(serial, (BolusProgrammedEvent) event);
+ else if (event instanceof BolusDeliveredEvent)
+ processBolusDeliveredEvent(serial, (BolusDeliveredEvent) event);
+ else if (event instanceof OccurrenceOfAlertEvent)
+ processOccurrenceOfAlertEvent((OccurrenceOfAlertEvent) event);
+ return true;
+ }
+
+ private void processDateTimeChangedEvent(DateTimeChangedEvent event) {
+ long timeAfter = parseDate(event.getEventYear(), event.getEventMonth(), event.getEventDay(), event.getEventHour(), event.getEventMinute(), event.getEventSecond());
+ long timeBefore = parseDate(event.getBeforeYear(), event.getBeforeMonth(), event.getBeforeDay(), event.getBeforeHour(), event.getBeforeMinute(), event.getBeforeSecond());
+ timeOffset -= timeAfter - timeBefore;
+ }
+
+ private void processCannulaFilledEvent(CannulaFilledEvent event) {
+ long timestamp = parseDate(event.getEventYear(), event.getEventMonth(), event.getEventDay(),
+ event.getEventHour(), event.getEventMinute(), event.getEventSecond()) + timeOffset;
+ uploadCareportalEvent(timestamp, CareportalEvent.SITECHANGE);
+ }
+
+ private void processTotalDailyDoseEvent(TotalDailyDoseEvent event) {
+ Calendar calendar = Calendar.getInstance();
+ calendar.setTime(new Date(0));
+ calendar.set(Calendar.YEAR, event.getTotalYear());
+ calendar.set(Calendar.MONTH, event.getTotalMonth() - 1);
+ calendar.set(Calendar.DAY_OF_MONTH, event.getTotalDay());
+ TDD tdd = new TDD();
+ tdd.basal = event.getBasalTotal();
+ tdd.bolus = event.getBolusTotal();
+ tdd.total = tdd.basal + tdd.bolus;
+ tdd.date = calendar.getTimeInMillis();
+ MainApp.getDbHelper().createOrUpdateTDD(tdd);
+ }
+
+ private void processTubeFilledEvent(TubeFilledEvent event) {
+ if (!SP.getBoolean("insight_log_tube_changes", false)) return;
+ long timestamp = parseDate(event.getEventYear(), event.getEventMonth(), event.getEventDay(),
+ event.getEventHour(), event.getEventMinute(), event.getEventSecond()) + timeOffset;
+ logNote(timestamp, MainApp.gs(R.string.tube_changed));
+ }
+
+ private void processSniffingDoneEvent(SniffingDoneEvent event) {
+ if (!SP.getBoolean("insight_log_site_changes", false)) return;
+ long timestamp = parseDate(event.getEventYear(), event.getEventMonth(), event.getEventDay(),
+ event.getEventHour(), event.getEventMinute(), event.getEventSecond()) + timeOffset;
+ uploadCareportalEvent(timestamp, CareportalEvent.INSULINCHANGE);
+ }
+
+ private void processPowerUpEvent(PowerUpEvent event) {
+ if (!SP.getBoolean("insight_log_battery_changes", false)) return;
+ long timestamp = parseDate(event.getEventYear(), event.getEventMonth(), event.getEventDay(),
+ event.getEventHour(), event.getEventMinute(), event.getEventSecond()) + timeOffset;
+ uploadCareportalEvent(timestamp, CareportalEvent.PUMPBATTERYCHANGE);
+ }
+
+ private void processOperatingModeChangedEvent(String serial, List pumpStartedEvents, OperatingModeChangedEvent event) {
+ long timestamp = parseDate(event.getEventYear(), event.getEventMonth(), event.getEventDay(),
+ event.getEventHour(), event.getEventMinute(), event.getEventSecond()) + timeOffset;
+ InsightPumpID pumpID = new InsightPumpID();
+ pumpID.eventID = event.getEventPosition();
+ pumpID.pumpSerial = serial;
+ pumpID.timestamp = timestamp;
+ switch (event.getNewValue()) {
+ case STARTED:
+ pumpID.eventType = "PumpStarted";
+ MainApp.getDbHelper().createOrUpdate(pumpID);
+ pumpStartedEvents.add(pumpID);
+ if (SP.getBoolean("insight_log_operating_mode_changes", false))
+ logNote(timestamp, MainApp.gs(R.string.pump_started));
+ break;
+ case STOPPED:
+ if (SP.getBoolean("insight_log_operating_mode_changes", false))
+ pumpID.eventType = "PumpStopped";
+ MainApp.getDbHelper().createOrUpdate(pumpID);
+ logNote(timestamp, MainApp.gs(R.string.pump_stopped));
+ break;
+ case PAUSED:
+ if (SP.getBoolean("insight_log_operating_mode_changes", false))
+ logNote(timestamp, MainApp.gs(R.string.pump_paused));
+ break;
+ }
+ }
+
+ private void processStartOfTBREvent(String serial, List temporaryBasals, StartOfTBREvent event) {
+ long timestamp = parseDate(event.getEventYear(), event.getEventMonth(), event.getEventDay(),
+ event.getEventHour(), event.getEventMinute(), event.getEventSecond()) + timeOffset;
+ InsightPumpID pumpID = new InsightPumpID();
+ pumpID.eventID = event.getEventPosition();
+ pumpID.pumpSerial = serial;
+ pumpID.timestamp = timestamp;
+ pumpID.eventType = "StartOfTBR";
+ MainApp.getDbHelper().createOrUpdate(pumpID);
+ TemporaryBasal temporaryBasal = new TemporaryBasal();
+ temporaryBasal.durationInMinutes = event.getDuration();
+ temporaryBasal.source = Source.PUMP;
+ temporaryBasal.pumpId = pumpID.id;
+ temporaryBasal.percentRate = event.getAmount();
+ temporaryBasal.isAbsolute = false;
+ temporaryBasal.date = timestamp;
+ temporaryBasals.add(temporaryBasal);
+ }
+
+ private void processEndOfTBREvent(String serial, List temporaryBasals, EndOfTBREvent event) {
+ long timestamp = parseDate(event.getEventYear(), event.getEventMonth(), event.getEventDay(),
+ event.getEventHour(), event.getEventMinute(), event.getEventSecond()) + timeOffset;
+ InsightPumpID pumpID = new InsightPumpID();
+ pumpID.eventID = event.getEventPosition();
+ pumpID.pumpSerial = serial;
+ pumpID.eventType = "EndOfTBR";
+ pumpID.timestamp = timestamp;
+ MainApp.getDbHelper().createOrUpdate(pumpID);
+ TemporaryBasal temporaryBasal = new TemporaryBasal();
+ temporaryBasal.durationInMinutes = 0;
+ temporaryBasal.source = Source.PUMP;
+ temporaryBasal.pumpId = pumpID.id;
+ temporaryBasal.date = timestamp;
+ temporaryBasals.add(temporaryBasal);
+ }
+
+ private void processBolusProgrammedEvent(String serial, BolusProgrammedEvent event) {
+ long timestamp = parseDate(event.getEventYear(), event.getEventMonth(), event.getEventDay(),
+ event.getEventHour(), event.getEventMinute(), event.getEventSecond()) + timeOffset;
+ InsightBolusID bolusID = MainApp.getDbHelper().getInsightBolusID(serial, event.getBolusID(), timestamp);
+ if (bolusID != null && bolusID.endID != null) {
+ bolusID.startID = event.getEventPosition();
+ MainApp.getDbHelper().createOrUpdate(bolusID);
+ return;
+ }
+ if (bolusID == null || bolusID.startID != null) {
+ bolusID = new InsightBolusID();
+ bolusID.timestamp = timestamp;
+ bolusID.bolusID = event.getBolusID();
+ bolusID.pumpSerial = serial;
+ }
+ bolusID.startID = event.getEventPosition();
+ MainApp.getDbHelper().createOrUpdate(bolusID);
+ if (event.getBolusType() == BolusType.STANDARD || event.getBolusType() == BolusType.MULTIWAVE) {
+ DetailedBolusInfo detailedBolusInfo = new DetailedBolusInfo();
+ detailedBolusInfo.date = bolusID.timestamp;
+ detailedBolusInfo.source = Source.PUMP;
+ detailedBolusInfo.pumpId = bolusID.id;
+ detailedBolusInfo.insulin = event.getImmediateAmount();
+ TreatmentsPlugin.getPlugin().addToHistoryTreatment(detailedBolusInfo, true);
+ }
+ if ((event.getBolusType() == BolusType.EXTENDED || event.getBolusType() == BolusType.MULTIWAVE)) {
+ ExtendedBolus extendedBolus = new ExtendedBolus();
+ extendedBolus.date = bolusID.timestamp;
+ extendedBolus.source = Source.PUMP;
+ extendedBolus.durationInMinutes = event.getDuration();
+ extendedBolus.insulin = event.getExtendedAmount();
+ extendedBolus.pumpId = bolusID.id;
+ if (ProfileFunctions.getInstance().getProfile(extendedBolus.date) != null)
+ TreatmentsPlugin.getPlugin().addToHistoryExtendedBolus(extendedBolus);
+ }
+ }
+
+ private void processBolusDeliveredEvent(String serial, BolusDeliveredEvent event) {
+ long timestamp = parseDate(event.getEventYear(), event.getEventMonth(), event.getEventDay(),
+ event.getEventHour(), event.getEventMinute(), event.getEventSecond()) + timeOffset;
+ long startTimestamp = parseRelativeDate(event.getEventYear(), event.getEventMonth(), event.getEventDay(), event.getEventHour(),
+ event.getEventMinute(), event.getEventSecond(), event.getStartHour(), event.getStartMinute(), event.getStartSecond()) + timeOffset;
+ InsightBolusID bolusID = MainApp.getDbHelper().getInsightBolusID(serial, event.getBolusID(), timestamp);
+ if (bolusID == null || bolusID.endID != null) {
+ bolusID = new InsightBolusID();
+ bolusID.timestamp = startTimestamp;
+ bolusID.bolusID = event.getBolusID();
+ bolusID.pumpSerial = serial;
+ }
+ bolusID.endID = event.getEventPosition();
+ MainApp.getDbHelper().createOrUpdate(bolusID);
+ if (event.getBolusType() == BolusType.STANDARD || event.getBolusType() == BolusType.MULTIWAVE) {
+ DetailedBolusInfo detailedBolusInfo = new DetailedBolusInfo();
+ detailedBolusInfo.date = bolusID.timestamp;
+ detailedBolusInfo.source = Source.PUMP;
+ detailedBolusInfo.pumpId = bolusID.id;
+ detailedBolusInfo.insulin = event.getImmediateAmount();
+ TreatmentsPlugin.getPlugin().addToHistoryTreatment(detailedBolusInfo, true);
+ }
+ if (event.getBolusType() == BolusType.EXTENDED || event.getBolusType() == BolusType.MULTIWAVE) {
+ if (event.getDuration() == 0) {
+ ExtendedBolus extendedBolus = MainApp.getDbHelper().getExtendedBolusByPumpId(bolusID.id);
+ if (extendedBolus != null) {
+ final String _id = extendedBolus._id;
+ if (NSUpload.isIdValid(_id)) NSUpload.removeCareportalEntryFromNS(_id);
+ else UploadQueue.removeID("dbAdd", _id);
+ MainApp.getDbHelper().delete(extendedBolus);
+ }
+ } else {
+ ExtendedBolus extendedBolus = new ExtendedBolus();
+ extendedBolus.date = bolusID.timestamp;
+ extendedBolus.source = Source.PUMP;
+ extendedBolus.durationInMinutes = event.getDuration();
+ extendedBolus.insulin = event.getExtendedAmount();
+ extendedBolus.pumpId = bolusID.id;
+ if (ProfileFunctions.getInstance().getProfile(extendedBolus.date) != null)
+ TreatmentsPlugin.getPlugin().addToHistoryExtendedBolus(extendedBolus);
+ }
+ }
+ }
+
+ private void processOccurrenceOfAlertEvent(OccurrenceOfAlertEvent event) {
+ if (!SP.getBoolean("insight_log_alerts", false)) return;
+ long timestamp = parseDate(event.getEventYear(), event.getEventMonth(), event.getEventDay(),
+ event.getEventHour(), event.getEventMinute(), event.getEventSecond()) + timeOffset;
+ Integer code = null;
+ Integer title = null;
+ switch (event.getAlertType()) {
+ case ERROR_6:
+ code = R.string.alert_e6_code;
+ title = R.string.alert_e6_title;
+ break;
+ case ERROR_10:
+ code = R.string.alert_e10_code;
+ title = R.string.alert_e10_title;
+ break;
+ case ERROR_13:
+ code = R.string.alert_e13_code;
+ title = R.string.alert_e13_title;
+ break;
+ case MAINTENANCE_20:
+ code = R.string.alert_m20_code;
+ title = R.string.alert_m20_title;
+ break;
+ case MAINTENANCE_21:
+ code = R.string.alert_m21_code;
+ title = R.string.alert_m21_title;
+ break;
+ case MAINTENANCE_22:
+ code = R.string.alert_m22_code;
+ title = R.string.alert_m22_title;
+ break;
+ case MAINTENANCE_23:
+ code = R.string.alert_m23_code;
+ title = R.string.alert_m23_title;
+ break;
+ case MAINTENANCE_24:
+ code = R.string.alert_m24_code;
+ title = R.string.alert_m24_title;
+ break;
+ case MAINTENANCE_25:
+ code = R.string.alert_m25_code;
+ title = R.string.alert_m25_title;
+ break;
+ case MAINTENANCE_26:
+ code = R.string.alert_m26_code;
+ title = R.string.alert_m26_title;
+ break;
+ case MAINTENANCE_27:
+ code = R.string.alert_m27_code;
+ title = R.string.alert_m27_title;
+ break;
+ case MAINTENANCE_28:
+ code = R.string.alert_m28_code;
+ title = R.string.alert_m28_title;
+ break;
+ case MAINTENANCE_29:
+ code = R.string.alert_m29_code;
+ title = R.string.alert_m29_title;
+ break;
+ case MAINTENANCE_30:
+ code = R.string.alert_m30_code;
+ title = R.string.alert_m30_title;
+ break;
+ case WARNING_31:
+ code = R.string.alert_w31_code;
+ title = R.string.alert_w31_title;
+ break;
+ case WARNING_32:
+ code = R.string.alert_w32_code;
+ title = R.string.alert_w32_title;
+ break;
+ case WARNING_33:
+ code = R.string.alert_w33_code;
+ title = R.string.alert_w33_title;
+ break;
+ case WARNING_34:
+ code = R.string.alert_w34_code;
+ title = R.string.alert_w34_title;
+ break;
+ case WARNING_39:
+ code = R.string.alert_w39_code;
+ title = R.string.alert_w39_title;
+ break;
+ }
+ if (code != null)
+ logNote(timestamp, MainApp.gs(R.string.insight_alert_formatter, MainApp.gs(code), MainApp.gs(title)));
+ }
+
+ private long parseDate(int year, int month, int day, int hour, int minute, int second) {
+ Calendar calendar = Calendar.getInstance(TimeZone.getTimeZone("UTC"));
+ calendar.set(Calendar.YEAR, year);
+ calendar.set(Calendar.MONTH, month - 1);
+ calendar.set(Calendar.DAY_OF_MONTH, day);
+ calendar.set(Calendar.HOUR_OF_DAY, hour);
+ calendar.set(Calendar.MINUTE, minute);
+ calendar.set(Calendar.SECOND, second);
+ return calendar.getTimeInMillis();
+ }
+
+ private void logNote(long date, String note) {
+ try {
+ if (MainApp.getDbHelper().getCareportalEventFromTimestamp(date) != null)
+ return;
+ JSONObject data = new JSONObject();
+ String enteredBy = SP.getString("careportal_enteredby", "");
+ if (!enteredBy.equals("")) data.put("enteredBy", enteredBy);
+ data.put("created_at", DateUtil.toISOString(date));
+ data.put("eventType", CareportalEvent.NOTE);
+ data.put("notes", note);
+ NSUpload.uploadCareportalEntryToNS(data);
+ } catch (JSONException e) {
+ e.printStackTrace();
+ }
+ }
+
+ private long parseRelativeDate(int year, int month, int day, int hour, int minute, int second, int relativeHour, int relativeMinute, int relativeSecond) {
+ if (relativeHour * 60 * 60 + relativeMinute * 60 + relativeSecond >= hour * 60 * 60 * minute * 60 + second)
+ day--;
+ Calendar calendar = Calendar.getInstance(TimeZone.getTimeZone("UTC"));
+ calendar.set(Calendar.YEAR, year);
+ calendar.set(Calendar.MONTH, month - 1);
+ calendar.set(Calendar.DAY_OF_MONTH, day);
+ calendar.set(Calendar.HOUR_OF_DAY, relativeHour);
+ calendar.set(Calendar.MINUTE, relativeMinute);
+ calendar.set(Calendar.SECOND, relativeSecond);
+ return calendar.getTimeInMillis();
+ }
+
+ private void uploadCareportalEvent(long date, String event) {
+ if (MainApp.getDbHelper().getCareportalEventFromTimestamp(date) != null)
+ return;
+ try {
+ JSONObject data = new JSONObject();
+ String enteredBy = SP.getString("careportal_enteredby", "");
+ if (!enteredBy.equals("")) data.put("enteredBy", enteredBy);
+ data.put("created_at", DateUtil.toISOString(date));
+ data.put("eventType", event);
+ NSUpload.uploadCareportalEntryToNS(data);
+ } catch (JSONException e) {
+ e.printStackTrace();
+ }
+ }
+
+ @Override
+ public Constraint applyBasalPercentConstraints(Constraint percentRate, Profile profile) {
+ percentRate.setIfGreater(0, String.format(MainApp.gs(R.string.limitingpercentrate), 0, MainApp.gs(R.string.itmustbepositivevalue)), this);
+ percentRate.setIfSmaller(getPumpDescription().maxTempPercent, String.format(MainApp.gs(R.string.limitingpercentrate), getPumpDescription().maxTempPercent, MainApp.gs(R.string.pumplimit)), this);
+ return percentRate;
+ }
+
+ @Override
+ public Constraint applyBolusConstraints(Constraint insulin) {
+ if (!limitsFetched) return insulin;
+ insulin.setIfSmaller(maximumBolusAmount, String.format(MainApp.gs(R.string.limitingbolus), maximumBolusAmount, MainApp.gs(R.string.pumplimit)), this);
+ if (insulin.value() < minimumBolusAmount) {
+
+ //TODO: Add function to Constraints or use different approach
+ // This only works if the interface of the InsightPlugin is called last.
+ // If not, another constraint could theoretically set the value between 0 and minimumBolusAmount
+
+ insulin.set(0d, String.format(MainApp.gs(R.string.limitingbolus), minimumBolusAmount, MainApp.gs(R.string.pumplimit)), this);
+ }
+ return insulin;
+ }
+
+ @Override
+ public void stateChanged(InsightState state) {
+ if (state == InsightState.CONNECTED) statusLoaded = false;
+ else if (state == InsightState.NOT_PAIRED) {
+ connectionService.withdrawConnectionRequest(this);
+ statusLoaded = false;
+ profileBlocks = null;
+ operatingMode = null;
+ batteryStatus = null;
+ cartridgeStatus = null;
+ totalDailyDose = null;
+ activeBasalRate = null;
+ activeTBR = null;
+ activeBoluses = null;
+ tbrOverNotificationBlock = null;
+ }
+ new Handler(Looper.getMainLooper()).post(() -> MainApp.bus().post(new EventLocalInsightUpdateGUI()));
+ }
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsightLocal/activities/InsightAlertActivity.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsightLocal/activities/InsightAlertActivity.java
new file mode 100644
index 0000000000..5262ad9de5
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsightLocal/activities/InsightAlertActivity.java
@@ -0,0 +1,257 @@
+package info.nightscout.androidaps.plugins.PumpInsightLocal.activities;
+
+import android.content.ComponentName;
+import android.content.Intent;
+import android.content.ServiceConnection;
+import android.os.Bundle;
+import android.os.IBinder;
+import android.support.v4.content.ContextCompat;
+import android.support.v7.app.AppCompatActivity;
+import android.text.Html;
+import android.view.View;
+import android.view.WindowManager;
+import android.widget.Button;
+import android.widget.ImageView;
+import android.widget.TextView;
+
+import java.text.DecimalFormat;
+
+import info.nightscout.androidaps.R;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.InsightAlertService;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.descriptors.Alert;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.descriptors.AlertStatus;
+
+public class InsightAlertActivity extends AppCompatActivity {
+
+ private Alert alert;
+ private InsightAlertService alertService;
+
+ private ImageView icon;
+ private TextView errorCode;
+ private TextView errorTitle;
+ private TextView errorDescription;
+ private Button mute;
+ private Button confirm;
+
+ private ServiceConnection serviceConnection = new ServiceConnection() {
+ @Override
+ public void onServiceConnected(ComponentName name, IBinder binder) {
+ alertService = ((InsightAlertService.LocalBinder) binder).getService();
+ alertService.setAlertActivity(InsightAlertActivity.this);
+ alert = alertService.getAlert();
+ if (alert == null) finish();
+ update(alert);
+ }
+
+ @Override
+ public void onServiceDisconnected(ComponentName name) {
+ alertService = null;
+ }
+ };
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_insight_alert);
+
+ bindService(new Intent(this, InsightAlertService.class), serviceConnection, BIND_AUTO_CREATE);
+
+ icon = findViewById(R.id.icon);
+ errorCode = findViewById(R.id.error_code);
+ errorTitle = findViewById(R.id.error_title);
+ errorDescription = findViewById(R.id.error_description);
+ mute = findViewById(R.id.mute);
+ confirm = findViewById(R.id.confirm);
+
+ setFinishOnTouchOutside(false);
+
+ getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON
+ | WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD
+ | WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED
+ | WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON);
+ WindowManager.LayoutParams layoutParams = getWindow().getAttributes();
+ layoutParams.screenBrightness = 1.0F;
+ getWindow().setAttributes(layoutParams);
+ }
+
+ @Override
+ protected void onDestroy() {
+ alertService.setAlertActivity(null);
+ unbindService(serviceConnection);
+ super.onDestroy();
+ }
+
+ public void update(Alert alert) {
+ this.alert = alert;
+ mute.setEnabled(true);
+ mute.setVisibility(alert.getAlertStatus() == AlertStatus.SNOOZED ? View.GONE : View.VISIBLE);
+ confirm.setEnabled(true);
+ int icon = 0;
+ int code = 0;
+ int title = 0;
+ String description = null;
+ switch (alert.getAlertCategory()) {
+ case ERROR:
+ icon = R.drawable.ic_error;
+ break;
+ case MAINTENANCE:
+ icon = R.drawable.ic_maintenance;
+ break;
+ case WARNING:
+ icon = R.drawable.ic_warning;
+ break;
+ case REMINDER:
+ icon = R.drawable.ic_reminder;
+ break;
+ }
+ DecimalFormat decimalFormat = new DecimalFormat("##0.00");
+ int hours = alert.getTBRDuration() / 60;
+ int minutes = alert.getTBRDuration() - hours * 60;
+ switch (alert.getAlertType()) {
+ case REMINDER_01:
+ code = R.string.alert_r1_code;
+ title = R.string.alert_r1_title;
+ break;
+ case REMINDER_02:
+ code = R.string.alert_r2_code;
+ title = R.string.alert_r2_title;
+ break;
+ case REMINDER_03:
+ code = R.string.alert_r3_code;
+ title = R.string.alert_r3_title;
+ break;
+ case REMINDER_04:
+ code = R.string.alert_r4_code;
+ title = R.string.alert_r4_title;
+ break;
+ case REMINDER_07:
+ code = R.string.alert_r7_code;
+ title = R.string.alert_r7_title;
+ description = getString(R.string.alert_r7_description, alert.getTBRAmount(), new DecimalFormat("#0").format(hours) + ":" + new DecimalFormat("00").format(minutes));
+ break;
+ case WARNING_31:
+ code = R.string.alert_w31_code;
+ title = R.string.alert_w31_title;
+ description = getString(R.string.alert_w31_description, decimalFormat.format(alert.getCartridgeAmount()));
+ break;
+ case WARNING_32:
+ code = R.string.alert_w32_code;
+ title = R.string.alert_w32_title;
+ description = getString(R.string.alert_w32_description);
+ break;
+ case WARNING_33:
+ code = R.string.alert_w33_code;
+ title = R.string.alert_w33_title;
+ description = getString(R.string.alert_w33_description);
+ break;
+ case WARNING_34:
+ code = R.string.alert_w34_code;
+ title = R.string.alert_w34_title;
+ description = getString(R.string.alert_w34_description);
+ break;
+ case WARNING_36:
+ code = R.string.alert_w36_code;
+ title = R.string.alert_w36_title;
+ description = getString(R.string.alert_w36_description, alert.getTBRAmount(), new DecimalFormat("#0").format(hours) + ":" + new DecimalFormat("00").format(minutes));
+ break;
+ case WARNING_38:
+ code = R.string.alert_w38_code;
+ title = R.string.alert_w38_title;
+ description = getString(R.string.alert_w38_description, decimalFormat.format(alert.getProgrammedBolusAmount()), decimalFormat.format(alert.getDeliveredBolusAmount()));
+ break;
+ case WARNING_39:
+ code = R.string.alert_w39_code;
+ title = R.string.alert_w39_title;
+ break;
+ case MAINTENANCE_20:
+ code = R.string.alert_m20_code;
+ title = R.string.alert_m20_title;
+ description = getString(R.string.alert_m20_description);
+ break;
+ case MAINTENANCE_21:
+ code = R.string.alert_m21_code;
+ title = R.string.alert_m21_title;
+ description = getString(R.string.alert_m21_description);
+ break;
+ case MAINTENANCE_22:
+ code = R.string.alert_m22_code;
+ title = R.string.alert_m22_title;
+ description = getString(R.string.alert_m22_description);
+ break;
+ case MAINTENANCE_23:
+ code = R.string.alert_m23_code;
+ title = R.string.alert_m23_title;
+ description = getString(R.string.alert_m23_description);
+ break;
+ case MAINTENANCE_24:
+ code = R.string.alert_m24_code;
+ title = R.string.alert_m24_title;
+ description = getString(R.string.alert_m24_description);
+ break;
+ case MAINTENANCE_25:
+ code = R.string.alert_m25_code;
+ title = R.string.alert_m25_title;
+ description = getString(R.string.alert_m25_description);
+ break;
+ case MAINTENANCE_26:
+ code = R.string.alert_m26_code;
+ title = R.string.alert_m26_title;
+ description = getString(R.string.alert_m26_description);
+ break;
+ case MAINTENANCE_27:
+ code = R.string.alert_m27_code;
+ title = R.string.alert_m27_title;
+ description = getString(R.string.alert_m27_description);
+ break;
+ case MAINTENANCE_28:
+ code = R.string.alert_m28_code;
+ title = R.string.alert_m28_title;
+ description = getString(R.string.alert_m28_description);
+ break;
+ case MAINTENANCE_29:
+ code = R.string.alert_m29_code;
+ title = R.string.alert_m29_title;
+ description = getString(R.string.alert_m29_description);
+ break;
+ case MAINTENANCE_30:
+ code = R.string.alert_m30_code;
+ title = R.string.alert_m30_title;
+ description = getString(R.string.alert_m30_description);
+ break;
+ case ERROR_6:
+ code = R.string.alert_e6_code;
+ title = R.string.alert_e6_title;
+ description = getString(R.string.alert_e6_description);
+ break;
+ case ERROR_10:
+ code = R.string.alert_e10_code;
+ title = R.string.alert_e10_title;
+ description = getString(R.string.alert_e10_description);
+ break;
+ case ERROR_13:
+ code = R.string.alert_e13_code;
+ title = R.string.alert_e13_title;
+ description = getString(R.string.alert_e13_description);
+ break;
+ }
+ this.icon.setImageDrawable(ContextCompat.getDrawable(this, icon));
+ this.errorCode.setText(code);
+ this.errorTitle.setText(title);
+ if (description == null) this.errorDescription.setVisibility(View.GONE);
+ else {
+ this.errorDescription.setVisibility(View.VISIBLE);
+ this.errorDescription.setText(Html.fromHtml(description));
+ }
+ }
+
+ public void muteClicked(View view) {
+ mute.setEnabled(false);
+ alertService.mute();
+ }
+
+ public void confirmClicked(View view) {
+ mute.setEnabled(false);
+ confirm.setEnabled(false);
+ alertService.confirm();
+ }
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsightLocal/activities/InsightPairingActivity.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsightLocal/activities/InsightPairingActivity.java
new file mode 100644
index 0000000000..390e9a233e
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsightLocal/activities/InsightPairingActivity.java
@@ -0,0 +1,255 @@
+package info.nightscout.androidaps.plugins.PumpInsightLocal.activities;
+
+import android.bluetooth.BluetoothAdapter;
+import android.bluetooth.BluetoothDevice;
+import android.content.BroadcastReceiver;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.ServiceConnection;
+import android.os.Bundle;
+import android.os.IBinder;
+import android.support.annotation.NonNull;
+import android.support.annotation.Nullable;
+import android.support.v7.app.AppCompatActivity;
+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 android.widget.Toast;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import info.nightscout.androidaps.R;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.connection_service.InsightConnectionService;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.descriptors.InsightState;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.utils.ExceptionTranslator;
+
+public class InsightPairingActivity extends AppCompatActivity implements InsightConnectionService.StateCallback, View.OnClickListener, InsightConnectionService.ExceptionCallback {
+
+ private boolean scanning;
+ private LinearLayout deviceSearchSection;
+ private TextView pleaseWaitSection;
+ private LinearLayout codeCompareSection;
+ private LinearLayout pairingCompletedSection;
+ private Button yes;
+ private Button no;
+ private TextView code;
+ private Button exit;
+ private RecyclerView deviceList;
+ private DeviceAdapter deviceAdapter = new DeviceAdapter();
+
+ private InsightConnectionService service;
+
+ private ServiceConnection serviceConnection = new ServiceConnection() {
+ @Override
+ public void onServiceConnected(ComponentName name, IBinder binder) {
+ service = ((InsightConnectionService.LocalBinder) binder).getService();
+ if (service.isPaired()) return;
+ else {
+ service.requestConnection(InsightPairingActivity.this);
+ service.registerStateCallback(InsightPairingActivity.this);
+ service.registerExceptionCallback(InsightPairingActivity.this);
+ stateChanged(service.getState());
+ }
+ }
+
+ @Override
+ public void onServiceDisconnected(ComponentName name) {
+
+ }
+ };
+
+ @Override
+ protected void onCreate(@Nullable Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_insight_pairing);
+
+ deviceSearchSection = findViewById(R.id.device_search_section);
+ pleaseWaitSection = findViewById(R.id.please_wait_section);
+ codeCompareSection = findViewById(R.id.code_compare_section);
+ pairingCompletedSection = findViewById(R.id.pairing_completed_section);
+ yes = findViewById(R.id.yes);
+ no = findViewById(R.id.no);
+ code = findViewById(R.id.code);
+ exit = findViewById(R.id.exit);
+ deviceList = findViewById(R.id.device_list);
+
+ yes.setOnClickListener(this);
+ no.setOnClickListener(this);
+ exit.setOnClickListener(this);
+
+ deviceList.setLayoutManager(new LinearLayoutManager(this));
+ deviceList.setAdapter(deviceAdapter);
+
+
+ bindService(new Intent(this, InsightConnectionService.class), serviceConnection, BIND_AUTO_CREATE);
+}
+
+ @Override
+ protected void onDestroy() {
+ if (service != null) {
+ service.withdrawConnectionRequest(InsightPairingActivity.this);
+ service.unregisterStateCallback(InsightPairingActivity.this);
+ service.unregisterExceptionCallback(InsightPairingActivity.this);
+ }
+ unbindService(serviceConnection);
+ super.onDestroy();
+ }
+
+ @Override
+ protected void onStart() {
+ super.onStart();
+ if (service != null && service.getState() == InsightState.NOT_PAIRED) startBLScan();
+ }
+
+ @Override
+ protected void onStop() {
+ stopBLScan();
+ super.onStop();
+ }
+
+ @Override
+ public void stateChanged(InsightState state) {
+ runOnUiThread(() -> {
+ switch (state) {
+ case NOT_PAIRED:
+ startBLScan();
+ deviceSearchSection.setVisibility(View.VISIBLE);
+ pleaseWaitSection.setVisibility(View.GONE);
+ codeCompareSection.setVisibility(View.GONE);
+ pairingCompletedSection.setVisibility(View.GONE);
+ break;
+ case CONNECTING:
+ case SATL_CONNECTION_REQUEST:
+ case SATL_KEY_REQUEST:
+ case SATL_VERIFY_DISPLAY_REQUEST:
+ case SATL_VERIFY_CONFIRM_REQUEST:
+ case APP_BIND_MESSAGE:
+ stopBLScan();
+ deviceSearchSection.setVisibility(View.GONE);
+ pleaseWaitSection.setVisibility(View.VISIBLE);
+ codeCompareSection.setVisibility(View.GONE);
+ pairingCompletedSection.setVisibility(View.GONE);
+ break;
+ case AWAITING_CODE_CONFIRMATION:
+ stopBLScan();
+ deviceSearchSection.setVisibility(View.GONE);
+ pleaseWaitSection.setVisibility(View.GONE);
+ codeCompareSection.setVisibility(View.VISIBLE);
+ pairingCompletedSection.setVisibility(View.GONE);
+ code.setText(service.getVerificationString());
+ break;
+ case DISCONNECTED:
+ case CONNECTED:
+ stopBLScan();
+ deviceSearchSection.setVisibility(View.GONE);
+ pleaseWaitSection.setVisibility(View.GONE);
+ codeCompareSection.setVisibility(View.GONE);
+ pairingCompletedSection.setVisibility(View.VISIBLE);
+ break;
+ }
+ });
+ }
+
+ private void startBLScan() {
+ if (!scanning) {
+ BluetoothAdapter bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
+ if (!bluetoothAdapter.isEnabled()) bluetoothAdapter.enable();
+ IntentFilter intentFilter = new IntentFilter();
+ intentFilter.addAction(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);
+ intentFilter.addAction(BluetoothDevice.ACTION_FOUND);
+ registerReceiver(broadcastReceiver, intentFilter);
+ bluetoothAdapter.startDiscovery();
+ scanning = true;
+ }
+ }
+
+ private void stopBLScan() {
+ if (scanning) {
+ unregisterReceiver(broadcastReceiver);
+ BluetoothAdapter.getDefaultAdapter().cancelDiscovery();
+ scanning = false;
+ }
+ }
+ @Override
+ public void onClick(View v) {
+ if (v == exit) finish();
+ else if (v == yes) service.confirmVerificationString();
+ else if (v == no) service.rejectVerificationString();
+ }
+
+ @Override
+ public void onExceptionOccur(Exception e) {
+ ExceptionTranslator.makeToast(this, e);
+ }
+
+ private void deviceSelected(BluetoothDevice device) {
+ service.pair(device.getAddress());
+ }
+
+ private BroadcastReceiver broadcastReceiver = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ String action = intent.getAction();
+ if (action.equals(BluetoothAdapter.ACTION_DISCOVERY_FINISHED))
+ BluetoothAdapter.getDefaultAdapter().startDiscovery();
+ else if (action.equals(BluetoothDevice.ACTION_FOUND)) {
+ BluetoothDevice bluetoothDevice = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
+ deviceAdapter.addDevice(bluetoothDevice);
+ }
+ }
+ };
+
+ private class DeviceAdapter extends RecyclerView.Adapter {
+
+ private List bluetoothDevices = new ArrayList<>();
+
+ public void addDevice(BluetoothDevice bluetoothDevice) {
+ if (!bluetoothDevices.contains(bluetoothDevice)) {
+ bluetoothDevices.add(bluetoothDevice);
+ notifyDataSetChanged();
+ }
+ }
+
+ public void clear() {
+ bluetoothDevices.clear();
+ notifyDataSetChanged();
+ }
+
+ @NonNull
+ @Override
+ public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
+ return new ViewHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.bluetooth_device, parent, false));
+ }
+
+ @Override
+ public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
+ BluetoothDevice bluetoothDevice = bluetoothDevices.get(position);
+ holder.deviceName.setText(bluetoothDevice.getName() == null ? bluetoothDevice.getAddress() : bluetoothDevice.getName());
+ holder.deviceName.setOnClickListener((v) -> deviceSelected(bluetoothDevice));
+ }
+
+ @Override
+ public int getItemCount() {
+ return bluetoothDevices.size();
+ }
+
+ public class ViewHolder extends RecyclerView.ViewHolder {
+
+ private TextView deviceName;
+
+ public ViewHolder(View itemView) {
+ super(itemView);
+ deviceName = (TextView) itemView;
+ }
+ }
+
+ }
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsightLocal/activities/InsightPairingInformationActivity.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsightLocal/activities/InsightPairingInformationActivity.java
new file mode 100644
index 0000000000..27528cfeab
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsightLocal/activities/InsightPairingInformationActivity.java
@@ -0,0 +1,88 @@
+package info.nightscout.androidaps.plugins.PumpInsightLocal.activities;
+
+import android.content.ComponentName;
+import android.content.Intent;
+import android.content.ServiceConnection;
+import android.os.Bundle;
+import android.os.IBinder;
+import android.support.annotation.Nullable;
+import android.support.v7.app.AppCompatActivity;
+import android.view.View;
+import android.widget.TextView;
+
+import info.nightscout.androidaps.R;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.connection_service.InsightConnectionService;
+
+public class InsightPairingInformationActivity extends AppCompatActivity {
+
+ private InsightConnectionService connectionService;
+
+ private TextView serialNumber;
+ private TextView releaseSWVersion;
+ private TextView uiProcSWVersion;
+ private TextView pcProcSWVersion;
+ private TextView mdTelSWVersion;
+ private TextView safetyProcSWVersion;
+ private TextView btInfoPageVersion;
+ private TextView bluetoothAddress;
+ private TextView systemIdAppendix;
+ private TextView manufacturingDate;
+
+ private ServiceConnection serviceConnection = new ServiceConnection() {
+ @Override
+ public void onServiceConnected(ComponentName name, IBinder binder) {
+ connectionService = ((InsightConnectionService.LocalBinder) binder).getService();
+ if (!connectionService.isPaired()) {
+ overridePendingTransition(0, 0);
+ finish();
+ startActivity(new Intent(InsightPairingInformationActivity.this, InsightPairingActivity.class));
+ } else {
+ serialNumber.setText(connectionService.getPumpSystemIdentification().getSerialNumber());
+ manufacturingDate.setText(connectionService.getPumpSystemIdentification().getManufacturingDate());
+ systemIdAppendix.setText(connectionService.getPumpSystemIdentification().getSystemIdAppendix() + "");
+ releaseSWVersion.setText(connectionService.getPumpFirmwareVersions().getReleaseSWVersion());
+ uiProcSWVersion.setText(connectionService.getPumpFirmwareVersions().getUiProcSWVersion());
+ pcProcSWVersion.setText(connectionService.getPumpFirmwareVersions().getPcProcSWVersion());
+ mdTelSWVersion.setText(connectionService.getPumpFirmwareVersions().getMdTelProcSWVersion());
+ safetyProcSWVersion.setText(connectionService.getPumpFirmwareVersions().getSafetyProcSWVersion());
+ btInfoPageVersion.setText(connectionService.getPumpFirmwareVersions().getBtInfoPageVersion());
+ bluetoothAddress.setText(connectionService.getBluetoothAddress());
+ }
+ }
+
+ @Override
+ public void onServiceDisconnected(ComponentName name) {
+ connectionService = null;
+ }
+ };
+
+ @Override
+ protected void onCreate(@Nullable Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_insight_pairing_information);
+ serialNumber = findViewById(R.id.serial_number);
+ releaseSWVersion = findViewById(R.id.release_sw_version);
+ uiProcSWVersion = findViewById(R.id.ui_proc_sw_version);
+ pcProcSWVersion = findViewById(R.id.pc_proc_sw_version);
+ mdTelSWVersion = findViewById(R.id.md_tel_sw_version);
+ safetyProcSWVersion = findViewById(R.id.safety_proc_sw_version);
+ btInfoPageVersion = findViewById(R.id.bt_info_page_version);
+ bluetoothAddress = findViewById(R.id.bluetooth_address);
+ systemIdAppendix = findViewById(R.id.system_id_appendix);
+ manufacturingDate = findViewById(R.id.manufacturing_date);
+ bindService(new Intent(this, InsightConnectionService.class), serviceConnection, BIND_AUTO_CREATE);
+ }
+
+ @Override
+ protected void onDestroy() {
+ unbindService(serviceConnection);
+ super.onDestroy();
+ }
+
+ public void deletePairing(View view) {
+ if (connectionService != null) {
+ connectionService.reset();
+ finish();
+ }
+ }
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsightLocal/app_layer/AppLayerMessage.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsightLocal/app_layer/AppLayerMessage.java
new file mode 100644
index 0000000000..69243dde63
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsightLocal/app_layer/AppLayerMessage.java
@@ -0,0 +1,91 @@
+package info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer;
+
+import info.nightscout.androidaps.plugins.PumpInsightLocal.descriptors.MessagePriority;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.exceptions.IncompatibleAppVersionException;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.exceptions.InvalidAppCRCException;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.exceptions.UnknownAppCommandException;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.exceptions.UnknownServiceException;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.exceptions.app_layer_errors.AppLayerErrorException;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.exceptions.app_layer_errors.UnknownAppLayerErrorCodeException;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.ids.AppCommandIDs;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.ids.AppErrorIDs;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.ids.ServiceIDs;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.satl.DataMessage;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.utils.ByteBuf;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.utils.crypto.Cryptograph;
+
+public class AppLayerMessage implements Comparable {
+
+ private static final byte VERSION = 0x20;
+
+ private final MessagePriority messagePriority;
+ private final boolean inCRC;
+ private final boolean outCRC;
+ private final Service service;
+
+ public AppLayerMessage(MessagePriority messagePriority, boolean inCRC, boolean outCRC, Service service) {
+ this.messagePriority = messagePriority;
+ this.inCRC = inCRC;
+ this.outCRC = outCRC;
+ this.service = service;
+ }
+
+ protected ByteBuf getData() {
+ return new ByteBuf(0);
+ }
+
+ protected void parse(ByteBuf byteBuf) throws Exception {
+
+ }
+
+ public ByteBuf serialize(Class extends AppLayerMessage> clazz) {
+ byte[] data = getData().getBytes();
+ ByteBuf byteBuf = new ByteBuf(4 + data.length + (outCRC ? 2 : 0));
+ byteBuf.putByte(VERSION);
+ byteBuf.putByte(ServiceIDs.IDS.getID(getService()));
+ byteBuf.putUInt16LE(AppCommandIDs.IDS.getID(clazz));
+ byteBuf.putBytes(data);
+ if (outCRC) byteBuf.putUInt16LE(Cryptograph.calculateCRC(data));
+ return byteBuf;
+ }
+
+ public static AppLayerMessage deserialize(ByteBuf byteBuf) throws Exception {
+ byte version = byteBuf.readByte();
+ byte service = byteBuf.readByte();
+ int command = byteBuf.readUInt16LE();
+ int error = byteBuf.readUInt16LE();
+ Class extends AppLayerMessage> clazz = AppCommandIDs.IDS.getType(command);
+ if (clazz == null) throw new UnknownAppCommandException();
+ if (version != VERSION) throw new IncompatibleAppVersionException();
+ AppLayerMessage message = clazz.newInstance();
+ if (ServiceIDs.IDS.getType(service) == null) throw new UnknownServiceException();
+ if (error != 0) {
+ Class extends AppLayerErrorException> exceptionClass = AppErrorIDs.IDS.getType(error);
+ if (exceptionClass == null) throw new UnknownAppLayerErrorCodeException(error);
+ else throw exceptionClass.getConstructor(int.class).newInstance(error);
+ }
+ byte[] data = byteBuf.readBytes(byteBuf.getSize() - (message.inCRC ? 2 : 0));
+ if (message.inCRC && Cryptograph.calculateCRC(data) != byteBuf.readUInt16LE()) throw new InvalidAppCRCException();
+ message.parse(ByteBuf.from(data));
+ return message;
+ }
+
+ public static DataMessage wrap(AppLayerMessage message) {
+ DataMessage dataMessage = new DataMessage();
+ dataMessage.setData(message.serialize(message.getClass()));
+ return dataMessage;
+ }
+
+ public static AppLayerMessage unwrap(DataMessage dataMessage) throws Exception {
+ return deserialize(dataMessage.getData());
+ }
+
+ @Override
+ public int compareTo(AppLayerMessage o) {
+ return messagePriority.compareTo(o.messagePriority);
+ }
+
+ public Service getService() {
+ return this.service;
+ }
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsightLocal/app_layer/ReadParameterBlockMessage.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsightLocal/app_layer/ReadParameterBlockMessage.java
new file mode 100644
index 0000000000..43aae60e75
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsightLocal/app_layer/ReadParameterBlockMessage.java
@@ -0,0 +1,48 @@
+package info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer;
+
+import info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.parameter_blocks.ParameterBlock;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.descriptors.MessagePriority;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.ids.ParameterBlockIDs;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.utils.ByteBuf;
+
+public class ReadParameterBlockMessage extends AppLayerMessage {
+
+ private Class extends ParameterBlock> parameterBlockId;
+ private ParameterBlock parameterBlock;
+ private Service service;
+
+ public ReadParameterBlockMessage() {
+ super(MessagePriority.NORMAL, true, false, null);
+ }
+
+ @Override
+ public Service getService() {
+ return service;
+ }
+
+ public void setService(Service service) {
+ this.service = service;
+ }
+
+ @Override
+ protected ByteBuf getData() {
+ ByteBuf byteBuf = new ByteBuf(2);
+ byteBuf.putUInt16LE(ParameterBlockIDs.IDS.getID(parameterBlockId));
+ return byteBuf;
+ }
+
+ @Override
+ protected void parse(ByteBuf byteBuf) throws Exception {
+ parameterBlock = ParameterBlockIDs.IDS.getType(byteBuf.readUInt16LE()).newInstance();
+ byteBuf.shift(2); //Restriction level
+ parameterBlock.parse(byteBuf);
+ }
+
+ public ParameterBlock getParameterBlock() {
+ return this.parameterBlock;
+ }
+
+ public void setParameterBlockId(Class extends ParameterBlock> configurationBlockId) {
+ this.parameterBlockId = configurationBlockId;
+ }
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsightLocal/app_layer/Service.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsightLocal/app_layer/Service.java
new file mode 100644
index 0000000000..685dc8a52c
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsightLocal/app_layer/Service.java
@@ -0,0 +1,31 @@
+package info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer;
+
+public enum Service {
+
+ CONNECTION((short) 0x0000, null),
+ STATUS((short) 0x0100, null),
+ HISTORY((short) 0x0200, null),
+ CONFIGURATION((short) 0x0200, "u+5Fhz6Gw4j1Kkas"),
+ PARAMETER((short) 0x0200, null),
+ REMOTE_CONTROL((short) 0x0100, "MAbcV2X6PVjxuz+R");
+
+ private short version;
+ private String servicePassword;
+
+ Service(short version, String servicePassword) {
+ this.version = version;
+ this.servicePassword = servicePassword;
+ }
+
+ public short getVersion() {
+ return this.version;
+ }
+
+ public String getServicePassword() {
+ return this.servicePassword;
+ }
+
+ public void setServicePassword(String servicePassword) {
+ this.servicePassword = servicePassword;
+ }
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsightLocal/app_layer/configuration/CloseConfigurationWriteSessionMessage.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsightLocal/app_layer/configuration/CloseConfigurationWriteSessionMessage.java
new file mode 100644
index 0000000000..3bf10ba6c0
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsightLocal/app_layer/configuration/CloseConfigurationWriteSessionMessage.java
@@ -0,0 +1,12 @@
+package info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.configuration;
+
+import info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.AppLayerMessage;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.descriptors.MessagePriority;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.Service;
+
+public class CloseConfigurationWriteSessionMessage extends AppLayerMessage {
+
+ public CloseConfigurationWriteSessionMessage() {
+ super(MessagePriority.NORMAL, false, false, Service.CONFIGURATION);
+ }
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsightLocal/app_layer/configuration/OpenConfigurationWriteSessionMessage.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsightLocal/app_layer/configuration/OpenConfigurationWriteSessionMessage.java
new file mode 100644
index 0000000000..fe7e39c013
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsightLocal/app_layer/configuration/OpenConfigurationWriteSessionMessage.java
@@ -0,0 +1,12 @@
+package info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.configuration;
+
+import info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.AppLayerMessage;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.descriptors.MessagePriority;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.Service;
+
+public class OpenConfigurationWriteSessionMessage extends AppLayerMessage {
+
+ public OpenConfigurationWriteSessionMessage() {
+ super(MessagePriority.NORMAL, false, false, Service.CONFIGURATION);
+ }
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsightLocal/app_layer/configuration/WriteConfigurationBlockMessage.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsightLocal/app_layer/configuration/WriteConfigurationBlockMessage.java
new file mode 100644
index 0000000000..e842beb69f
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsightLocal/app_layer/configuration/WriteConfigurationBlockMessage.java
@@ -0,0 +1,41 @@
+package info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.configuration;
+
+import info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.AppLayerMessage;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.Service;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.parameter_blocks.ParameterBlock;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.descriptors.MessagePriority;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.ids.ParameterBlockIDs;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.utils.ByteBuf;
+
+public class WriteConfigurationBlockMessage extends AppLayerMessage {
+
+ private ParameterBlock parameterBlock;
+ private Class extends ParameterBlock> configurationBlockId;
+
+ public WriteConfigurationBlockMessage() {
+ super(MessagePriority.NORMAL, false, true, Service.CONFIGURATION);
+ }
+
+ @Override
+ protected ByteBuf getData() {
+ ByteBuf configBlockData = parameterBlock.getData();
+ ByteBuf data = new ByteBuf(4 + configBlockData.getSize());
+ data.putUInt16LE(ParameterBlockIDs.IDS.getID(parameterBlock.getClass()));
+ data.putUInt16LE(31);
+ data.putByteBuf(configBlockData);
+ return data;
+ }
+
+ @Override
+ protected void parse(ByteBuf byteBuf) throws Exception {
+ configurationBlockId = ParameterBlockIDs.IDS.getType(byteBuf.readUInt16LE());
+ }
+
+ public Class extends ParameterBlock> getConfigurationBlockId() {
+ return this.configurationBlockId;
+ }
+
+ public void setParameterBlock(ParameterBlock parameterBlock) {
+ this.parameterBlock = parameterBlock;
+ }
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsightLocal/app_layer/connection/ActivateServiceMessage.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsightLocal/app_layer/connection/ActivateServiceMessage.java
new file mode 100644
index 0000000000..9a07ea7ecb
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsightLocal/app_layer/connection/ActivateServiceMessage.java
@@ -0,0 +1,51 @@
+package info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.connection;
+
+import info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.AppLayerMessage;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.Service;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.descriptors.MessagePriority;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.utils.ByteBuf;
+
+public class ActivateServiceMessage extends AppLayerMessage {
+
+ private byte serviceID;
+ private short version;
+ private byte[] servicePassword;
+
+ public ActivateServiceMessage() {
+ super(MessagePriority.NORMAL, false, false, Service.CONNECTION);
+ }
+
+ protected void parse(ByteBuf byteBuf) {
+ serviceID = byteBuf.readByte();
+ version = byteBuf.readShort();
+ }
+
+ @Override
+ protected ByteBuf getData() {
+ ByteBuf byteBuf = new ByteBuf(19);
+ byteBuf.putByte(serviceID);
+ byteBuf.putShort(version);
+ byteBuf.putBytes(servicePassword);
+ return byteBuf;
+ }
+
+ public byte getServiceID() {
+ return this.serviceID;
+ }
+
+ public short getVersion() {
+ return this.version;
+ }
+
+ public void setServiceID(byte serviceID) {
+ this.serviceID = serviceID;
+ }
+
+ public void setVersion(short version) {
+ this.version = version;
+ }
+
+ public void setServicePassword(byte[] servicePassword) {
+ this.servicePassword = servicePassword;
+ }
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsightLocal/app_layer/connection/BindMessage.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsightLocal/app_layer/connection/BindMessage.java
new file mode 100644
index 0000000000..94a67d25b9
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsightLocal/app_layer/connection/BindMessage.java
@@ -0,0 +1,20 @@
+package info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.connection;
+
+import org.spongycastle.util.encoders.Hex;
+
+import info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.AppLayerMessage;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.Service;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.descriptors.MessagePriority;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.utils.ByteBuf;
+
+public class BindMessage extends AppLayerMessage {
+
+ public BindMessage() {
+ super(MessagePriority.NORMAL, false, false, Service.CONNECTION);
+ }
+
+ @Override
+ protected ByteBuf getData() {
+ return ByteBuf.from(Hex.decode("3438310000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"));
+ }
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsightLocal/app_layer/connection/ConnectMessage.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsightLocal/app_layer/connection/ConnectMessage.java
new file mode 100644
index 0000000000..5f728731d7
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsightLocal/app_layer/connection/ConnectMessage.java
@@ -0,0 +1,20 @@
+package info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.connection;
+
+import org.spongycastle.util.encoders.Hex;
+
+import info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.AppLayerMessage;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.Service;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.descriptors.MessagePriority;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.utils.ByteBuf;
+
+public class ConnectMessage extends AppLayerMessage {
+
+ public ConnectMessage() {
+ super(MessagePriority.NORMAL, false, false, Service.CONNECTION);
+ }
+
+ @Override
+ protected ByteBuf getData() {
+ return ByteBuf.from(Hex.decode("0000080100196000"));
+ }
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsightLocal/app_layer/connection/DisconnectMessage.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsightLocal/app_layer/connection/DisconnectMessage.java
new file mode 100644
index 0000000000..992523b5b5
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsightLocal/app_layer/connection/DisconnectMessage.java
@@ -0,0 +1,20 @@
+package info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.connection;
+
+import org.spongycastle.util.encoders.Hex;
+
+import info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.AppLayerMessage;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.Service;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.descriptors.MessagePriority;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.utils.ByteBuf;
+
+public class DisconnectMessage extends AppLayerMessage {
+
+ public DisconnectMessage() {
+ super(MessagePriority.NORMAL, false, false, Service.CONNECTION);
+ }
+
+ @Override
+ protected ByteBuf getData() {
+ return ByteBuf.from(Hex.decode("0360"));
+ }
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsightLocal/app_layer/connection/ServiceChallengeMessage.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsightLocal/app_layer/connection/ServiceChallengeMessage.java
new file mode 100644
index 0000000000..d43f523ec2
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsightLocal/app_layer/connection/ServiceChallengeMessage.java
@@ -0,0 +1,42 @@
+package info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.connection;
+
+import info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.AppLayerMessage;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.Service;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.descriptors.MessagePriority;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.utils.ByteBuf;
+
+public class ServiceChallengeMessage extends AppLayerMessage {
+
+ private byte serviceID;
+ private byte[] randomData;
+ private short version;
+
+ public ServiceChallengeMessage() {
+ super(MessagePriority.NORMAL, false, false, Service.CONNECTION);
+ }
+
+ @Override
+ protected void parse(ByteBuf byteBuf) {
+ randomData = byteBuf.getBytes(16);
+ }
+
+ @Override
+ protected ByteBuf getData() {
+ ByteBuf byteBuf = new ByteBuf(3);
+ byteBuf.putByte(serviceID);
+ byteBuf.putShort(version);
+ return byteBuf;
+ }
+
+ public byte[] getRandomData() {
+ return this.randomData;
+ }
+
+ public void setServiceID(byte serviceID) {
+ this.serviceID = serviceID;
+ }
+
+ public void setVersion(short version) {
+ this.version = version;
+ }
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsightLocal/app_layer/history/HistoryReadingDirection.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsightLocal/app_layer/history/HistoryReadingDirection.java
new file mode 100644
index 0000000000..77d40214d5
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsightLocal/app_layer/history/HistoryReadingDirection.java
@@ -0,0 +1,8 @@
+package info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.history;
+
+public enum HistoryReadingDirection {
+
+ FORWARD,
+ BACKWARD;
+
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsightLocal/app_layer/history/ReadHistoryEventsMessage.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsightLocal/app_layer/history/ReadHistoryEventsMessage.java
new file mode 100644
index 0000000000..324ce9d44f
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsightLocal/app_layer/history/ReadHistoryEventsMessage.java
@@ -0,0 +1,34 @@
+package info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.history;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.AppLayerMessage;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.Service;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.history.history_events.HistoryEvent;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.descriptors.MessagePriority;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.utils.ByteBuf;
+
+public class ReadHistoryEventsMessage extends AppLayerMessage {
+
+ private List historyEvents;
+
+ public ReadHistoryEventsMessage() {
+ super(MessagePriority.NORMAL, true, false, Service.HISTORY);
+ }
+
+ @Override
+ protected void parse(ByteBuf byteBuf) throws Exception {
+ historyEvents = new ArrayList<>();
+ byteBuf.shift(2);
+ int frameCount = byteBuf.readUInt16LE();
+ for (int i = 0; i < frameCount; i++) {
+ int length = byteBuf.readUInt16LE();
+ historyEvents.add(HistoryEvent.deserialize(ByteBuf.from(byteBuf.readBytes(length))));
+ }
+ }
+
+ public List getHistoryEvents() {
+ return historyEvents;
+ }
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsightLocal/app_layer/history/StartReadingHistoryMessage.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsightLocal/app_layer/history/StartReadingHistoryMessage.java
new file mode 100644
index 0000000000..cb5779f9e7
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsightLocal/app_layer/history/StartReadingHistoryMessage.java
@@ -0,0 +1,34 @@
+package info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.history;
+
+import info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.AppLayerMessage;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.Service;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.descriptors.MessagePriority;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.ids.HistoryReadingDirectionIDs;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.utils.ByteBuf;
+
+public class StartReadingHistoryMessage extends AppLayerMessage {
+
+ private long offset;
+ private HistoryReadingDirection direction;
+
+ public StartReadingHistoryMessage() {
+ super(MessagePriority.NORMAL, false, true, Service.HISTORY);
+ }
+
+ @Override
+ protected ByteBuf getData() {
+ ByteBuf byteBuf = new ByteBuf(8);
+ byteBuf.putUInt16LE(31);
+ byteBuf.putUInt16LE(HistoryReadingDirectionIDs.IDS.getID(direction));
+ byteBuf.putUInt32LE(offset);
+ return byteBuf;
+ }
+
+ public void setOffset(long offset) {
+ this.offset = offset;
+ }
+
+ public void setDirection(HistoryReadingDirection direction) {
+ this.direction = direction;
+ }
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsightLocal/app_layer/history/StopReadingHistoryMessage.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsightLocal/app_layer/history/StopReadingHistoryMessage.java
new file mode 100644
index 0000000000..16dcab7d27
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsightLocal/app_layer/history/StopReadingHistoryMessage.java
@@ -0,0 +1,13 @@
+package info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.history;
+
+import info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.AppLayerMessage;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.Service;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.descriptors.MessagePriority;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.utils.ByteBuf;
+
+public class StopReadingHistoryMessage extends AppLayerMessage {
+
+ public StopReadingHistoryMessage() {
+ super(MessagePriority.NORMAL, false, false, Service.HISTORY);
+ }
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsightLocal/app_layer/history/history_events/BasalDeliveryChangedEvent.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsightLocal/app_layer/history/history_events/BasalDeliveryChangedEvent.java
new file mode 100644
index 0000000000..9e21c54311
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsightLocal/app_layer/history/history_events/BasalDeliveryChangedEvent.java
@@ -0,0 +1,23 @@
+package info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.history.history_events;
+
+import info.nightscout.androidaps.plugins.PumpInsightLocal.utils.ByteBuf;
+
+public class BasalDeliveryChangedEvent extends HistoryEvent {
+
+ private double oldBasalRate;
+ private double newBasalRate;
+
+ @Override
+ public void parse(ByteBuf byteBuf) {
+ oldBasalRate = byteBuf.readUInt32Decimal1000();
+ newBasalRate = byteBuf.readUInt32Decimal1000();
+ }
+
+ public double getOldBasalRate() {
+ return oldBasalRate;
+ }
+
+ public double getNewBasalRate() {
+ return newBasalRate;
+ }
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsightLocal/app_layer/history/history_events/BolusDeliveredEvent.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsightLocal/app_layer/history/history_events/BolusDeliveredEvent.java
new file mode 100644
index 0000000000..913a576662
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsightLocal/app_layer/history/history_events/BolusDeliveredEvent.java
@@ -0,0 +1,64 @@
+package info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.history.history_events;
+
+import info.nightscout.androidaps.plugins.PumpInsightLocal.descriptors.BolusType;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.ids.BolusTypeIDs;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.utils.BOCUtil;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.utils.ByteBuf;
+
+public class BolusDeliveredEvent extends HistoryEvent {
+
+ private BolusType bolusType;
+ private int startHour;
+ private int startMinute;
+ private int startSecond;
+ private double immediateAmount;
+ private double extendedAmount;
+ private int duration;
+ private int bolusID;
+
+ @Override
+ public void parse(ByteBuf byteBuf) {
+ bolusType = BolusTypeIDs.IDS.getType(byteBuf.readUInt16LE());
+ byteBuf.shift(1);
+ startHour = BOCUtil.parseBOC(byteBuf.readByte());
+ startMinute = BOCUtil.parseBOC(byteBuf.readByte());
+ startSecond = BOCUtil.parseBOC(byteBuf.readByte());
+ immediateAmount = byteBuf.readUInt16Decimal();
+ extendedAmount = byteBuf.readUInt16Decimal();
+ duration = byteBuf.readUInt16LE();
+ byteBuf.shift(2);
+ bolusID = byteBuf.readUInt16LE();
+ }
+
+ public BolusType getBolusType() {
+ return bolusType;
+ }
+
+ public int getStartHour() {
+ return startHour;
+ }
+
+ public int getStartMinute() {
+ return startMinute;
+ }
+
+ public int getStartSecond() {
+ return startSecond;
+ }
+
+ public double getImmediateAmount() {
+ return immediateAmount;
+ }
+
+ public double getExtendedAmount() {
+ return extendedAmount;
+ }
+
+ public int getDuration() {
+ return duration;
+ }
+
+ public int getBolusID() {
+ return bolusID;
+ }
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsightLocal/app_layer/history/history_events/BolusProgrammedEvent.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsightLocal/app_layer/history/history_events/BolusProgrammedEvent.java
new file mode 100644
index 0000000000..9e355a0555
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsightLocal/app_layer/history/history_events/BolusProgrammedEvent.java
@@ -0,0 +1,45 @@
+package info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.history.history_events;
+
+import info.nightscout.androidaps.plugins.PumpInsightLocal.descriptors.BolusType;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.ids.BolusTypeIDs;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.utils.ByteBuf;
+
+public class BolusProgrammedEvent extends HistoryEvent {
+
+ private BolusType bolusType;
+ private double immediateAmount;
+ private double extendedAmount;
+ private int duration;
+ private int bolusID;
+
+ @Override
+ public void parse(ByteBuf byteBuf) {
+ bolusType = BolusTypeIDs.IDS.getType(byteBuf.readUInt16LE());
+ immediateAmount = byteBuf.readUInt16Decimal();
+ extendedAmount = byteBuf.readUInt16Decimal();
+ duration = byteBuf.readUInt16LE();
+ byteBuf.shift(4);
+ bolusID = byteBuf.readUInt16LE();
+ }
+
+
+ public BolusType getBolusType() {
+ return bolusType;
+ }
+
+ public double getImmediateAmount() {
+ return immediateAmount;
+ }
+
+ public double getExtendedAmount() {
+ return extendedAmount;
+ }
+
+ public int getDuration() {
+ return duration;
+ }
+
+ public int getBolusID() {
+ return bolusID;
+ }
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsightLocal/app_layer/history/history_events/CannulaFilledEvent.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsightLocal/app_layer/history/history_events/CannulaFilledEvent.java
new file mode 100644
index 0000000000..ed49da1f18
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsightLocal/app_layer/history/history_events/CannulaFilledEvent.java
@@ -0,0 +1,17 @@
+package info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.history.history_events;
+
+import info.nightscout.androidaps.plugins.PumpInsightLocal.utils.ByteBuf;
+
+public class CannulaFilledEvent extends HistoryEvent {
+
+ private double amount;
+
+ @Override
+ public void parse(ByteBuf byteBuf) {
+ amount = byteBuf.readUInt16Decimal();
+ }
+
+ public double getAmount() {
+ return amount;
+ }
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsightLocal/app_layer/history/history_events/CartridgeInsertedEvent.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsightLocal/app_layer/history/history_events/CartridgeInsertedEvent.java
new file mode 100644
index 0000000000..750c481116
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsightLocal/app_layer/history/history_events/CartridgeInsertedEvent.java
@@ -0,0 +1,4 @@
+package info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.history.history_events;
+
+public class CartridgeInsertedEvent extends HistoryEvent {
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsightLocal/app_layer/history/history_events/CartridgeRemovedEvent.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsightLocal/app_layer/history/history_events/CartridgeRemovedEvent.java
new file mode 100644
index 0000000000..e32e9a1c23
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsightLocal/app_layer/history/history_events/CartridgeRemovedEvent.java
@@ -0,0 +1,4 @@
+package info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.history.history_events;
+
+public class CartridgeRemovedEvent extends HistoryEvent {
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsightLocal/app_layer/history/history_events/DateTimeChangedEvent.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsightLocal/app_layer/history/history_events/DateTimeChangedEvent.java
new file mode 100644
index 0000000000..338422832d
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsightLocal/app_layer/history/history_events/DateTimeChangedEvent.java
@@ -0,0 +1,49 @@
+package info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.history.history_events;
+
+import info.nightscout.androidaps.plugins.PumpInsightLocal.utils.BOCUtil;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.utils.ByteBuf;
+
+public class DateTimeChangedEvent extends HistoryEvent {
+
+ private int beforeYear;
+ private int beforeMonth;
+ private int beforeDay;
+ private int beforeHour;
+ private int beforeMinute;
+ private int beforeSecond;
+
+ @Override
+ public void parse(ByteBuf byteBuf) {
+ beforeYear = BOCUtil.parseBOC(byteBuf.readByte()) * 100 + BOCUtil.parseBOC(byteBuf.readByte());
+ beforeMonth = BOCUtil.parseBOC(byteBuf.readByte());
+ beforeDay = BOCUtil.parseBOC(byteBuf.readByte());
+ byteBuf.shift(1);
+ beforeHour = BOCUtil.parseBOC(byteBuf.readByte());
+ beforeMinute = BOCUtil.parseBOC(byteBuf.readByte());
+ beforeSecond = BOCUtil.parseBOC(byteBuf.readByte());
+ }
+
+ public int getBeforeYear() {
+ return beforeYear;
+ }
+
+ public int getBeforeMonth() {
+ return beforeMonth;
+ }
+
+ public int getBeforeDay() {
+ return beforeDay;
+ }
+
+ public int getBeforeHour() {
+ return beforeHour;
+ }
+
+ public int getBeforeMinute() {
+ return beforeMinute;
+ }
+
+ public int getBeforeSecond() {
+ return beforeSecond;
+ }
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsightLocal/app_layer/history/history_events/DefaultDateTimeSetEvent.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsightLocal/app_layer/history/history_events/DefaultDateTimeSetEvent.java
new file mode 100644
index 0000000000..2c0971f474
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsightLocal/app_layer/history/history_events/DefaultDateTimeSetEvent.java
@@ -0,0 +1,4 @@
+package info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.history.history_events;
+
+public class DefaultDateTimeSetEvent extends HistoryEvent {
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsightLocal/app_layer/history/history_events/EndOfTBREvent.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsightLocal/app_layer/history/history_events/EndOfTBREvent.java
new file mode 100644
index 0000000000..9fdcb14fcf
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsightLocal/app_layer/history/history_events/EndOfTBREvent.java
@@ -0,0 +1,43 @@
+package info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.history.history_events;
+
+import info.nightscout.androidaps.plugins.PumpInsightLocal.utils.BOCUtil;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.utils.ByteBuf;
+
+public class EndOfTBREvent extends HistoryEvent {
+
+ private int startHour;
+ private int startMinute;
+ private int startSecond;
+ private int amount;
+ private int duration;
+
+ @Override
+ public void parse(ByteBuf byteBuf) {
+ byteBuf.shift(1);
+ startHour = BOCUtil.parseBOC(byteBuf.readByte());
+ startMinute = BOCUtil.parseBOC(byteBuf.readByte());
+ startSecond = BOCUtil.parseBOC(byteBuf.readByte());
+ amount = byteBuf.readUInt16LE();
+ duration = byteBuf.readUInt16LE();
+ }
+
+ public int getStartHour() {
+ return startHour;
+ }
+
+ public int getStartMinute() {
+ return startMinute;
+ }
+
+ public int getStartSecond() {
+ return startSecond;
+ }
+
+ public int getAmount() {
+ return amount;
+ }
+
+ public int getDuration() {
+ return duration;
+ }
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsightLocal/app_layer/history/history_events/HistoryEvent.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsightLocal/app_layer/history/history_events/HistoryEvent.java
new file mode 100644
index 0000000000..44f60e62c6
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsightLocal/app_layer/history/history_events/HistoryEvent.java
@@ -0,0 +1,83 @@
+package info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.history.history_events;
+
+import info.nightscout.androidaps.plugins.PumpInsightLocal.ids.HistoryEventIDs;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.utils.BOCUtil;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.utils.ByteBuf;
+
+public class HistoryEvent implements Comparable {
+
+ private int eventYear;
+ private int eventMonth;
+ private int eventDay;
+ private int eventHour;
+ private int eventMinute;
+ private int eventSecond;
+ private long eventPosition;
+
+ public static HistoryEvent deserialize(ByteBuf byteBuf) {
+ int eventID = byteBuf.readUInt16LE();
+ Class extends HistoryEvent> eventClass = HistoryEventIDs.IDS.getType(eventID);
+ HistoryEvent event = null;
+ if (eventClass == null) event = new HistoryEvent();
+ else {
+ try {
+ event = eventClass.newInstance();
+ } catch (IllegalAccessException e) {
+ e.printStackTrace();
+ } catch (InstantiationException e) {
+ e.printStackTrace();
+ }
+ }
+ event.parseHeader(byteBuf);
+ event.parse(byteBuf);
+ return event;
+ }
+
+ public final void parseHeader(ByteBuf byteBuf) {
+ eventYear = BOCUtil.parseBOC(byteBuf.readByte()) * 100 + BOCUtil.parseBOC(byteBuf.readByte());
+ eventMonth = BOCUtil.parseBOC(byteBuf.readByte());
+ eventDay = BOCUtil.parseBOC(byteBuf.readByte());
+ byteBuf.shift(1);
+ eventHour = BOCUtil.parseBOC(byteBuf.readByte());
+ eventMinute = BOCUtil.parseBOC(byteBuf.readByte());
+ eventSecond = BOCUtil.parseBOC(byteBuf.readByte());
+ eventPosition = byteBuf.readUInt32LE();
+ }
+
+ public void parse(ByteBuf byteBuf) {
+
+ }
+
+ public int getEventYear() {
+ return eventYear;
+ }
+
+ public int getEventMonth() {
+ return eventMonth;
+ }
+
+ public int getEventDay() {
+ return eventDay;
+ }
+
+ public int getEventHour() {
+ return eventHour;
+ }
+
+ public int getEventMinute() {
+ return eventMinute;
+ }
+
+ public int getEventSecond() {
+ return eventSecond;
+ }
+
+ public long getEventPosition() {
+ return eventPosition;
+ }
+
+ @Override
+ public int compareTo(HistoryEvent historyEvent) {
+ return (int) (eventPosition - historyEvent.eventPosition);
+ }
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsightLocal/app_layer/history/history_events/OccurrenceOfAlertEvent.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsightLocal/app_layer/history/history_events/OccurrenceOfAlertEvent.java
new file mode 100644
index 0000000000..fc0e732bd5
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsightLocal/app_layer/history/history_events/OccurrenceOfAlertEvent.java
@@ -0,0 +1,25 @@
+package info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.history.history_events;
+
+import info.nightscout.androidaps.plugins.PumpInsightLocal.descriptors.AlertType;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.ids.AlertTypeIncrementalIDs;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.utils.ByteBuf;
+
+public abstract class OccurrenceOfAlertEvent extends HistoryEvent {
+
+ private AlertType alertType;
+ private int alertID;
+
+ @Override
+ public void parse(ByteBuf byteBuf) {
+ alertType = AlertTypeIncrementalIDs.IDS.getType(byteBuf.readUInt16LE());
+ alertID = byteBuf.readUInt16LE();
+ }
+
+ public AlertType getAlertType() {
+ return alertType;
+ }
+
+ public int getAlertID() {
+ return alertID;
+ }
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsightLocal/app_layer/history/history_events/OccurrenceOfErrorEvent.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsightLocal/app_layer/history/history_events/OccurrenceOfErrorEvent.java
new file mode 100644
index 0000000000..0c17f9a6be
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsightLocal/app_layer/history/history_events/OccurrenceOfErrorEvent.java
@@ -0,0 +1,4 @@
+package info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.history.history_events;
+
+public class OccurrenceOfErrorEvent extends OccurrenceOfAlertEvent {
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsightLocal/app_layer/history/history_events/OccurrenceOfMaintenanceEvent.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsightLocal/app_layer/history/history_events/OccurrenceOfMaintenanceEvent.java
new file mode 100644
index 0000000000..e18de9ab27
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsightLocal/app_layer/history/history_events/OccurrenceOfMaintenanceEvent.java
@@ -0,0 +1,4 @@
+package info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.history.history_events;
+
+public class OccurrenceOfMaintenanceEvent extends OccurrenceOfAlertEvent {
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsightLocal/app_layer/history/history_events/OccurrenceOfWarningEvent.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsightLocal/app_layer/history/history_events/OccurrenceOfWarningEvent.java
new file mode 100644
index 0000000000..95d40e36c2
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsightLocal/app_layer/history/history_events/OccurrenceOfWarningEvent.java
@@ -0,0 +1,4 @@
+package info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.history.history_events;
+
+public class OccurrenceOfWarningEvent extends OccurrenceOfAlertEvent {
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsightLocal/app_layer/history/history_events/OperatingModeChangedEvent.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsightLocal/app_layer/history/history_events/OperatingModeChangedEvent.java
new file mode 100644
index 0000000000..47f5707f97
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsightLocal/app_layer/history/history_events/OperatingModeChangedEvent.java
@@ -0,0 +1,26 @@
+package info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.history.history_events;
+
+import info.nightscout.androidaps.plugins.PumpInsightLocal.descriptors.OperatingMode;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.ids.OperatingModeIDs;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.utils.ByteBuf;
+
+public class OperatingModeChangedEvent extends HistoryEvent {
+
+ private OperatingMode oldValue;
+ private OperatingMode newValue;
+
+ @Override
+ public void parse(ByteBuf byteBuf) {
+ oldValue = OperatingModeIDs.IDS.getType(byteBuf.readUInt16LE());
+ newValue = OperatingModeIDs.IDS.getType(byteBuf.readUInt16LE());
+ }
+
+
+ public OperatingMode getOldValue() {
+ return oldValue;
+ }
+
+ public OperatingMode getNewValue() {
+ return newValue;
+ }
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsightLocal/app_layer/history/history_events/PowerDownEvent.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsightLocal/app_layer/history/history_events/PowerDownEvent.java
new file mode 100644
index 0000000000..939f028fd8
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsightLocal/app_layer/history/history_events/PowerDownEvent.java
@@ -0,0 +1,4 @@
+package info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.history.history_events;
+
+public class PowerDownEvent extends HistoryEvent {
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsightLocal/app_layer/history/history_events/PowerUpEvent.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsightLocal/app_layer/history/history_events/PowerUpEvent.java
new file mode 100644
index 0000000000..e5ec8184cb
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsightLocal/app_layer/history/history_events/PowerUpEvent.java
@@ -0,0 +1,4 @@
+package info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.history.history_events;
+
+public class PowerUpEvent extends HistoryEvent {
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsightLocal/app_layer/history/history_events/SniffingDoneEvent.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsightLocal/app_layer/history/history_events/SniffingDoneEvent.java
new file mode 100644
index 0000000000..b176324e38
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsightLocal/app_layer/history/history_events/SniffingDoneEvent.java
@@ -0,0 +1,18 @@
+package info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.history.history_events;
+
+
+import info.nightscout.androidaps.plugins.PumpInsightLocal.utils.ByteBuf;
+
+public class SniffingDoneEvent extends HistoryEvent {
+
+ private double amount;
+
+ @Override
+ public void parse(ByteBuf byteBuf) {
+ amount = byteBuf.readUInt16Decimal();
+ }
+
+ public double getAmount() {
+ return amount;
+ }
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsightLocal/app_layer/history/history_events/StartOfTBREvent.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsightLocal/app_layer/history/history_events/StartOfTBREvent.java
new file mode 100644
index 0000000000..062804ff06
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsightLocal/app_layer/history/history_events/StartOfTBREvent.java
@@ -0,0 +1,23 @@
+package info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.history.history_events;
+
+import info.nightscout.androidaps.plugins.PumpInsightLocal.utils.ByteBuf;
+
+public class StartOfTBREvent extends HistoryEvent {
+
+ private int amount;
+ private int duration;
+
+ @Override
+ public void parse(ByteBuf byteBuf) {
+ amount = byteBuf.readUInt16LE();
+ duration = byteBuf.readUInt16LE();
+ }
+
+ public int getAmount() {
+ return amount;
+ }
+
+ public int getDuration() {
+ return duration;
+ }
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsightLocal/app_layer/history/history_events/TotalDailyDoseEvent.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsightLocal/app_layer/history/history_events/TotalDailyDoseEvent.java
new file mode 100644
index 0000000000..4c3ab74213
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsightLocal/app_layer/history/history_events/TotalDailyDoseEvent.java
@@ -0,0 +1,42 @@
+package info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.history.history_events;
+
+import info.nightscout.androidaps.plugins.PumpInsightLocal.utils.BOCUtil;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.utils.ByteBuf;
+
+public class TotalDailyDoseEvent extends HistoryEvent {
+
+ private double basalTotal;
+ private double bolusTotal;
+ private int totalYear;
+ private int totalMonth;
+ private int totalDay;
+
+ @Override
+ public void parse(ByteBuf byteBuf) {
+ basalTotal = byteBuf.readUInt32Decimal100();
+ bolusTotal = byteBuf.readUInt32Decimal100();
+ totalYear = BOCUtil.parseBOC(byteBuf.readByte()) * 100 + BOCUtil.parseBOC(byteBuf.readByte());
+ totalMonth = BOCUtil.parseBOC(byteBuf.readByte());
+ totalDay = BOCUtil.parseBOC(byteBuf.readByte());
+ }
+
+ public double getBasalTotal() {
+ return basalTotal;
+ }
+
+ public double getBolusTotal() {
+ return bolusTotal;
+ }
+
+ public int getTotalYear() {
+ return totalYear;
+ }
+
+ public int getTotalMonth() {
+ return totalMonth;
+ }
+
+ public int getTotalDay() {
+ return totalDay;
+ }
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsightLocal/app_layer/history/history_events/TubeFilledEvent.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsightLocal/app_layer/history/history_events/TubeFilledEvent.java
new file mode 100644
index 0000000000..217d362eb5
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsightLocal/app_layer/history/history_events/TubeFilledEvent.java
@@ -0,0 +1,17 @@
+package info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.history.history_events;
+
+import info.nightscout.androidaps.plugins.PumpInsightLocal.utils.ByteBuf;
+
+public class TubeFilledEvent extends HistoryEvent {
+
+ private double amount;
+
+ @Override
+ public void parse(ByteBuf byteBuf) {
+ amount = byteBuf.readUInt16Decimal();
+ }
+
+ public double getAmount() {
+ return amount;
+ }
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsightLocal/app_layer/parameter_blocks/ActiveBRProfileBlock.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsightLocal/app_layer/parameter_blocks/ActiveBRProfileBlock.java
new file mode 100644
index 0000000000..f40ffbe421
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsightLocal/app_layer/parameter_blocks/ActiveBRProfileBlock.java
@@ -0,0 +1,30 @@
+package info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.parameter_blocks;
+
+import info.nightscout.androidaps.plugins.PumpInsightLocal.descriptors.BasalProfile;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.ids.ActiveBasalProfileIDs;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.utils.ByteBuf;
+
+public class ActiveBRProfileBlock extends ParameterBlock {
+
+ private BasalProfile activeBasalProfile;
+
+ @Override
+ public void parse(ByteBuf byteBuf) {
+ activeBasalProfile = ActiveBasalProfileIDs.IDS.getType(byteBuf.readUInt16LE());
+ }
+
+ @Override
+ public ByteBuf getData() {
+ ByteBuf byteBuf = new ByteBuf(2);
+ byteBuf.putUInt16LE(ActiveBasalProfileIDs.IDS.getID(activeBasalProfile));
+ return byteBuf;
+ }
+
+ public BasalProfile getActiveBasalProfile() {
+ return activeBasalProfile;
+ }
+
+ public void setActiveBasalProfile(BasalProfile activeBasalProfile) {
+ this.activeBasalProfile = activeBasalProfile;
+ }
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsightLocal/app_layer/parameter_blocks/BRProfile1Block.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsightLocal/app_layer/parameter_blocks/BRProfile1Block.java
new file mode 100644
index 0000000000..99c9c1bd74
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsightLocal/app_layer/parameter_blocks/BRProfile1Block.java
@@ -0,0 +1,4 @@
+package info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.parameter_blocks;
+
+public class BRProfile1Block extends BRProfileBlock {
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsightLocal/app_layer/parameter_blocks/BRProfile1NameBlock.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsightLocal/app_layer/parameter_blocks/BRProfile1NameBlock.java
new file mode 100644
index 0000000000..670b889292
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsightLocal/app_layer/parameter_blocks/BRProfile1NameBlock.java
@@ -0,0 +1,4 @@
+package info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.parameter_blocks;
+
+public class BRProfile1NameBlock extends NameBlock {
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsightLocal/app_layer/parameter_blocks/BRProfile2Block.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsightLocal/app_layer/parameter_blocks/BRProfile2Block.java
new file mode 100644
index 0000000000..11a275196f
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsightLocal/app_layer/parameter_blocks/BRProfile2Block.java
@@ -0,0 +1,4 @@
+package info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.parameter_blocks;
+
+public class BRProfile2Block extends BRProfileBlock {
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsightLocal/app_layer/parameter_blocks/BRProfile2NameBlock.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsightLocal/app_layer/parameter_blocks/BRProfile2NameBlock.java
new file mode 100644
index 0000000000..0da19911a9
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsightLocal/app_layer/parameter_blocks/BRProfile2NameBlock.java
@@ -0,0 +1,4 @@
+package info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.parameter_blocks;
+
+public class BRProfile2NameBlock extends NameBlock {
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsightLocal/app_layer/parameter_blocks/BRProfile3Block.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsightLocal/app_layer/parameter_blocks/BRProfile3Block.java
new file mode 100644
index 0000000000..8c9875bfea
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsightLocal/app_layer/parameter_blocks/BRProfile3Block.java
@@ -0,0 +1,4 @@
+package info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.parameter_blocks;
+
+public class BRProfile3Block extends BRProfileBlock {
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsightLocal/app_layer/parameter_blocks/BRProfile3NameBlock.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsightLocal/app_layer/parameter_blocks/BRProfile3NameBlock.java
new file mode 100644
index 0000000000..1b63926131
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsightLocal/app_layer/parameter_blocks/BRProfile3NameBlock.java
@@ -0,0 +1,4 @@
+package info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.parameter_blocks;
+
+public class BRProfile3NameBlock extends NameBlock {
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsightLocal/app_layer/parameter_blocks/BRProfile4Block.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsightLocal/app_layer/parameter_blocks/BRProfile4Block.java
new file mode 100644
index 0000000000..2a22a34e63
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsightLocal/app_layer/parameter_blocks/BRProfile4Block.java
@@ -0,0 +1,4 @@
+package info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.parameter_blocks;
+
+public class BRProfile4Block extends BRProfileBlock {
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsightLocal/app_layer/parameter_blocks/BRProfile4NameBlock.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsightLocal/app_layer/parameter_blocks/BRProfile4NameBlock.java
new file mode 100644
index 0000000000..26d0a52fa3
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsightLocal/app_layer/parameter_blocks/BRProfile4NameBlock.java
@@ -0,0 +1,4 @@
+package info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.parameter_blocks;
+
+public class BRProfile4NameBlock extends NameBlock {
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsightLocal/app_layer/parameter_blocks/BRProfile5Block.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsightLocal/app_layer/parameter_blocks/BRProfile5Block.java
new file mode 100644
index 0000000000..ebb5fac320
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsightLocal/app_layer/parameter_blocks/BRProfile5Block.java
@@ -0,0 +1,4 @@
+package info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.parameter_blocks;
+
+public class BRProfile5Block extends BRProfileBlock {
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsightLocal/app_layer/parameter_blocks/BRProfile5NameBlock.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsightLocal/app_layer/parameter_blocks/BRProfile5NameBlock.java
new file mode 100644
index 0000000000..15df4436b7
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsightLocal/app_layer/parameter_blocks/BRProfile5NameBlock.java
@@ -0,0 +1,4 @@
+package info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.parameter_blocks;
+
+public class BRProfile5NameBlock extends NameBlock {
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsightLocal/app_layer/parameter_blocks/BRProfileBlock.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsightLocal/app_layer/parameter_blocks/BRProfileBlock.java
new file mode 100644
index 0000000000..2d6538dff3
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsightLocal/app_layer/parameter_blocks/BRProfileBlock.java
@@ -0,0 +1,50 @@
+package info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.parameter_blocks;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import info.nightscout.androidaps.plugins.PumpInsightLocal.descriptors.BasalProfileBlock;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.utils.ByteBuf;
+
+public abstract class BRProfileBlock extends ParameterBlock {
+
+ private List profileBlocks;
+
+ @Override
+ public void parse(ByteBuf byteBuf) {
+ profileBlocks = new ArrayList<>();
+ for (int i = 0; i < 24; i++) {
+ BasalProfileBlock basalProfileBlock = new BasalProfileBlock();
+ basalProfileBlock.setDuration(byteBuf.readUInt16LE());
+ profileBlocks.add(basalProfileBlock);
+ }
+ for (int i = 0; i < 24; i++) profileBlocks.get(i).setBasalAmount(byteBuf.readUInt16Decimal());
+ Iterator iterator = profileBlocks.iterator();
+ while (iterator.hasNext())
+ if (iterator.next().getDuration() == 0)
+ iterator.remove();
+ }
+
+ @Override
+ public ByteBuf getData() {
+ ByteBuf byteBuf = new ByteBuf(96);
+ for (int i = 0; i < 24; i++) {
+ if (profileBlocks.size() > i) byteBuf.putUInt16LE(profileBlocks.get(i).getDuration());
+ else byteBuf.putUInt16LE(0);
+ }
+ for (int i = 0; i < 24; i++) {
+ if (profileBlocks.size() > i) byteBuf.putUInt16Decimal(profileBlocks.get(i).getBasalAmount());
+ else byteBuf.putUInt16Decimal(0);
+ }
+ return byteBuf;
+ }
+
+ public List getProfileBlocks() {
+ return profileBlocks;
+ }
+
+ public void setProfileBlocks(List profileBlocks) {
+ this.profileBlocks = profileBlocks;
+ }
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsightLocal/app_layer/parameter_blocks/FactoryMaxBasalAmountBlock.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsightLocal/app_layer/parameter_blocks/FactoryMaxBasalAmountBlock.java
new file mode 100644
index 0000000000..638470a159
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsightLocal/app_layer/parameter_blocks/FactoryMaxBasalAmountBlock.java
@@ -0,0 +1,4 @@
+package info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.parameter_blocks;
+
+public class FactoryMaxBasalAmountBlock extends InsulinAmountLimitationBlock {
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsightLocal/app_layer/parameter_blocks/FactoryMaxBolusAmountBlock.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsightLocal/app_layer/parameter_blocks/FactoryMaxBolusAmountBlock.java
new file mode 100644
index 0000000000..7626546f71
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsightLocal/app_layer/parameter_blocks/FactoryMaxBolusAmountBlock.java
@@ -0,0 +1,4 @@
+package info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.parameter_blocks;
+
+public class FactoryMaxBolusAmountBlock extends InsulinAmountLimitationBlock {
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsightLocal/app_layer/parameter_blocks/FactoryMinBasalAmountBlock.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsightLocal/app_layer/parameter_blocks/FactoryMinBasalAmountBlock.java
new file mode 100644
index 0000000000..15da6dee8b
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsightLocal/app_layer/parameter_blocks/FactoryMinBasalAmountBlock.java
@@ -0,0 +1,4 @@
+package info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.parameter_blocks;
+
+public class FactoryMinBasalAmountBlock extends InsulinAmountLimitationBlock {
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsightLocal/app_layer/parameter_blocks/FactoryMinBolusAmountBlock.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsightLocal/app_layer/parameter_blocks/FactoryMinBolusAmountBlock.java
new file mode 100644
index 0000000000..43daa70db5
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsightLocal/app_layer/parameter_blocks/FactoryMinBolusAmountBlock.java
@@ -0,0 +1,4 @@
+package info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.parameter_blocks;
+
+public class FactoryMinBolusAmountBlock extends InsulinAmountLimitationBlock {
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsightLocal/app_layer/parameter_blocks/InsulinAmountLimitationBlock.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsightLocal/app_layer/parameter_blocks/InsulinAmountLimitationBlock.java
new file mode 100644
index 0000000000..837e8f561d
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsightLocal/app_layer/parameter_blocks/InsulinAmountLimitationBlock.java
@@ -0,0 +1,28 @@
+package info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.parameter_blocks;
+
+import info.nightscout.androidaps.plugins.PumpInsightLocal.utils.ByteBuf;
+
+public abstract class InsulinAmountLimitationBlock extends ParameterBlock {
+
+ private double amountLimitation;
+
+ @Override
+ public void parse(ByteBuf byteBuf) {
+ amountLimitation = byteBuf.readUInt16Decimal();
+ }
+
+ @Override
+ public ByteBuf getData() {
+ ByteBuf byteBuf = new ByteBuf(2);
+ byteBuf.putUInt16Decimal(amountLimitation);
+ return byteBuf;
+ }
+
+ public double getAmountLimitation() {
+ return this.amountLimitation;
+ }
+
+ public void setAmountLimitation(double amountLimitation) {
+ this.amountLimitation = amountLimitation;
+ }
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsightLocal/app_layer/parameter_blocks/MaxBasalAmountBlock.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsightLocal/app_layer/parameter_blocks/MaxBasalAmountBlock.java
new file mode 100644
index 0000000000..e7c4f5a089
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsightLocal/app_layer/parameter_blocks/MaxBasalAmountBlock.java
@@ -0,0 +1,4 @@
+package info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.parameter_blocks;
+
+public class MaxBasalAmountBlock extends InsulinAmountLimitationBlock {
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsightLocal/app_layer/parameter_blocks/MaxBolusAmountBlock.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsightLocal/app_layer/parameter_blocks/MaxBolusAmountBlock.java
new file mode 100644
index 0000000000..eae1404127
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsightLocal/app_layer/parameter_blocks/MaxBolusAmountBlock.java
@@ -0,0 +1,4 @@
+package info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.parameter_blocks;
+
+public class MaxBolusAmountBlock extends InsulinAmountLimitationBlock {
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsightLocal/app_layer/parameter_blocks/NameBlock.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsightLocal/app_layer/parameter_blocks/NameBlock.java
new file mode 100644
index 0000000000..af019bbbff
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsightLocal/app_layer/parameter_blocks/NameBlock.java
@@ -0,0 +1,28 @@
+package info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.parameter_blocks;
+
+import info.nightscout.androidaps.plugins.PumpInsightLocal.utils.ByteBuf;
+
+public abstract class NameBlock extends ParameterBlock {
+
+ private String name;
+
+ @Override
+ public void parse(ByteBuf byteBuf) {
+ name = byteBuf.readUTF16(40);
+ }
+
+ @Override
+ public ByteBuf getData() {
+ ByteBuf byteBuf = new ByteBuf(42);
+ byteBuf.putUTF16(name, 40);
+ return byteBuf;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsightLocal/app_layer/parameter_blocks/ParameterBlock.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsightLocal/app_layer/parameter_blocks/ParameterBlock.java
new file mode 100644
index 0000000000..1a64f0776e
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsightLocal/app_layer/parameter_blocks/ParameterBlock.java
@@ -0,0 +1,10 @@
+package info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.parameter_blocks;
+
+import info.nightscout.androidaps.plugins.PumpInsightLocal.utils.ByteBuf;
+
+public abstract class ParameterBlock {
+
+ public abstract void parse(ByteBuf byteBuf);
+ public abstract ByteBuf getData();
+
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsightLocal/app_layer/parameter_blocks/SystemIdentificationBlock.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsightLocal/app_layer/parameter_blocks/SystemIdentificationBlock.java
new file mode 100644
index 0000000000..fcc7f75447
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsightLocal/app_layer/parameter_blocks/SystemIdentificationBlock.java
@@ -0,0 +1,26 @@
+package info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.parameter_blocks;
+
+import info.nightscout.androidaps.plugins.PumpInsightLocal.descriptors.SystemIdentification;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.utils.ByteBuf;
+
+public class SystemIdentificationBlock extends ParameterBlock {
+
+ private SystemIdentification systemIdentification;
+
+ @Override
+ public void parse(ByteBuf byteBuf) {
+ systemIdentification = new SystemIdentification();
+ systemIdentification.setSerialNumber(byteBuf.readUTF16(18));
+ systemIdentification.setSystemIdAppendix(byteBuf.readUInt32LE());
+ systemIdentification.setManufacturingDate(byteBuf.readUTF16(22));
+ }
+
+ @Override
+ public ByteBuf getData() {
+ return null;
+ }
+
+ public SystemIdentification getSystemIdentification() {
+ return systemIdentification;
+ }
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsightLocal/app_layer/parameter_blocks/TBROverNotificationBlock.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsightLocal/app_layer/parameter_blocks/TBROverNotificationBlock.java
new file mode 100644
index 0000000000..26563b1d1f
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsightLocal/app_layer/parameter_blocks/TBROverNotificationBlock.java
@@ -0,0 +1,31 @@
+package info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.parameter_blocks;
+
+import info.nightscout.androidaps.plugins.PumpInsightLocal.utils.ByteBuf;
+
+public class TBROverNotificationBlock extends ParameterBlock {
+
+ private boolean enabled;
+ private int melody;
+
+ @Override
+ public void parse(ByteBuf byteBuf) {
+ enabled = byteBuf.readBoolean();
+ melody = byteBuf.readUInt16LE();
+ }
+
+ @Override
+ public ByteBuf getData() {
+ ByteBuf byteBuf = new ByteBuf(4);
+ byteBuf.putBoolean(enabled);
+ byteBuf.putUInt16LE(melody);
+ return byteBuf;
+ }
+
+ public boolean isEnabled() {
+ return enabled;
+ }
+
+ public void setEnabled(boolean enabled) {
+ this.enabled = enabled;
+ }
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsightLocal/app_layer/remote_control/CancelBolusMessage.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsightLocal/app_layer/remote_control/CancelBolusMessage.java
new file mode 100644
index 0000000000..92e72a41bf
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsightLocal/app_layer/remote_control/CancelBolusMessage.java
@@ -0,0 +1,26 @@
+package info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.remote_control;
+
+import info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.AppLayerMessage;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.Service;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.descriptors.MessagePriority;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.utils.ByteBuf;
+
+public class CancelBolusMessage extends AppLayerMessage {
+
+ private int bolusID;
+
+ public CancelBolusMessage() {
+ super(MessagePriority.HIGHEST, false, true, Service.REMOTE_CONTROL);
+ }
+
+ @Override
+ protected ByteBuf getData() {
+ ByteBuf byteBuf = new ByteBuf(2);
+ byteBuf.putUInt16LE(bolusID);
+ return byteBuf;
+ }
+
+ public void setBolusID(int bolusID) {
+ this.bolusID = bolusID;
+ }
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsightLocal/app_layer/remote_control/CancelTBRMessage.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsightLocal/app_layer/remote_control/CancelTBRMessage.java
new file mode 100644
index 0000000000..b331e846ac
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsightLocal/app_layer/remote_control/CancelTBRMessage.java
@@ -0,0 +1,12 @@
+package info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.remote_control;
+
+import info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.AppLayerMessage;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.Service;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.descriptors.MessagePriority;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.utils.ByteBuf;
+
+public class CancelTBRMessage extends AppLayerMessage {
+ public CancelTBRMessage() {
+ super(MessagePriority.HIGHER, false, false, Service.REMOTE_CONTROL);
+ }
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsightLocal/app_layer/remote_control/ChangeTBRMessage.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsightLocal/app_layer/remote_control/ChangeTBRMessage.java
new file mode 100644
index 0000000000..9dbda3ecb0
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsightLocal/app_layer/remote_control/ChangeTBRMessage.java
@@ -0,0 +1,33 @@
+package info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.remote_control;
+
+import info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.AppLayerMessage;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.Service;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.descriptors.MessagePriority;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.utils.ByteBuf;
+
+public class ChangeTBRMessage extends AppLayerMessage {
+
+ private int percentage;
+ private int duration;
+
+ public ChangeTBRMessage() {
+ super(MessagePriority.NORMAL, false, true, Service.REMOTE_CONTROL);
+ }
+
+ @Override
+ protected ByteBuf getData() {
+ ByteBuf byteBuf = new ByteBuf(6);
+ byteBuf.putUInt16LE(percentage);
+ byteBuf.putUInt16LE(duration);
+ byteBuf.putUInt16LE(31);
+ return byteBuf;
+ }
+
+ public void setPercentage(int percentage) {
+ this.percentage = percentage;
+ }
+
+ public void setDuration(int duration) {
+ this.duration = duration;
+ }
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsightLocal/app_layer/remote_control/ConfirmAlertMessage.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsightLocal/app_layer/remote_control/ConfirmAlertMessage.java
new file mode 100644
index 0000000000..dd56282834
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsightLocal/app_layer/remote_control/ConfirmAlertMessage.java
@@ -0,0 +1,26 @@
+package info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.remote_control;
+
+import info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.AppLayerMessage;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.Service;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.descriptors.MessagePriority;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.utils.ByteBuf;
+
+public class ConfirmAlertMessage extends AppLayerMessage {
+
+ private int alertID;
+
+ public ConfirmAlertMessage() {
+ super(MessagePriority.NORMAL, false, true, Service.REMOTE_CONTROL);
+ }
+
+ @Override
+ protected ByteBuf getData() {
+ ByteBuf byteBuf = new ByteBuf(2);
+ byteBuf.putUInt16LE(alertID);
+ return byteBuf;
+ }
+
+ public void setAlertID(int alertID) {
+ this.alertID = alertID;
+ }
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsightLocal/app_layer/remote_control/DeliverBolusMessage.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsightLocal/app_layer/remote_control/DeliverBolusMessage.java
new file mode 100644
index 0000000000..c2879beb96
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsightLocal/app_layer/remote_control/DeliverBolusMessage.java
@@ -0,0 +1,63 @@
+package info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.remote_control;
+
+import info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.AppLayerMessage;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.Service;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.descriptors.BolusType;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.descriptors.MessagePriority;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.ids.BolusTypeIDs;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.utils.ByteBuf;
+
+public class DeliverBolusMessage extends AppLayerMessage {
+
+ private BolusType bolusType;
+ private double immediateAmount;
+ private double extendedAmount;
+ private int duration;
+ private int bolusId;
+
+ public DeliverBolusMessage() {
+ super(MessagePriority.NORMAL, true, true, Service.REMOTE_CONTROL);
+ }
+
+ @Override
+ protected ByteBuf getData() {
+ ByteBuf byteBuf = new ByteBuf(22);
+ byteBuf.putUInt16LE(805);
+ byteBuf.putUInt16LE(BolusTypeIDs.IDS.getID(bolusType));
+ byteBuf.putUInt16LE(31);
+ byteBuf.putUInt16LE(0);
+ byteBuf.putUInt16Decimal(immediateAmount);
+ byteBuf.putUInt16Decimal(extendedAmount);
+ byteBuf.putUInt16LE(duration);
+ byteBuf.putUInt16LE(0);
+ byteBuf.putUInt16Decimal(immediateAmount);
+ byteBuf.putUInt16Decimal(extendedAmount);
+ byteBuf.putUInt16LE(duration);
+ return byteBuf;
+ }
+
+ @Override
+ protected void parse(ByteBuf byteBuf) throws Exception {
+ bolusId = byteBuf.readUInt16LE();
+ }
+
+ public void setBolusType(BolusType bolusType) {
+ this.bolusType = bolusType;
+ }
+
+ public void setImmediateAmount(double immediateAmount) {
+ this.immediateAmount = immediateAmount;
+ }
+
+ public void setExtendedAmount(double extendedAmount) {
+ this.extendedAmount = extendedAmount;
+ }
+
+ public void setDuration(int duration) {
+ this.duration = duration;
+ }
+
+ public int getBolusId() {
+ return bolusId;
+ }
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsightLocal/app_layer/remote_control/GetAvailableBolusTypesMessage.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsightLocal/app_layer/remote_control/GetAvailableBolusTypesMessage.java
new file mode 100644
index 0000000000..50395edcc1
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsightLocal/app_layer/remote_control/GetAvailableBolusTypesMessage.java
@@ -0,0 +1,28 @@
+package info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.remote_control;
+
+import info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.AppLayerMessage;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.Service;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.descriptors.AvailableBolusTypes;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.descriptors.MessagePriority;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.utils.ByteBuf;
+
+public class GetAvailableBolusTypesMessage extends AppLayerMessage {
+
+ private AvailableBolusTypes availableBolusTypes;
+
+ public GetAvailableBolusTypesMessage() {
+ super(MessagePriority.NORMAL, false, false, Service.REMOTE_CONTROL);
+ }
+
+ @Override
+ protected void parse(ByteBuf byteBuf) throws Exception {
+ availableBolusTypes = new AvailableBolusTypes();
+ availableBolusTypes.setStandardAvailable(byteBuf.readBoolean());
+ availableBolusTypes.setExtendedAvailable(byteBuf.readBoolean());
+ availableBolusTypes.setMultiwaveAvailable(byteBuf.readBoolean());
+ }
+
+ public AvailableBolusTypes getAvailableBolusTypes() {
+ return this.availableBolusTypes;
+ }
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsightLocal/app_layer/remote_control/SetDateTimeMessage.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsightLocal/app_layer/remote_control/SetDateTimeMessage.java
new file mode 100644
index 0000000000..5ceea4f168
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsightLocal/app_layer/remote_control/SetDateTimeMessage.java
@@ -0,0 +1,32 @@
+package info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.remote_control;
+
+import info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.AppLayerMessage;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.Service;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.descriptors.MessagePriority;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.descriptors.PumpTime;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.utils.ByteBuf;
+
+public class SetDateTimeMessage extends AppLayerMessage {
+
+ private PumpTime pumpTime;
+
+ public SetDateTimeMessage() {
+ super(MessagePriority.NORMAL, false, true, Service.CONFIGURATION);
+ }
+
+ @Override
+ protected ByteBuf getData() {
+ ByteBuf byteBuf = new ByteBuf(7);
+ byteBuf.putUInt16LE(pumpTime.getYear());
+ byteBuf.putUInt8((short) pumpTime.getMonth());
+ byteBuf.putUInt8((short) pumpTime.getDay());
+ byteBuf.putUInt8((short) pumpTime.getHour());
+ byteBuf.putUInt8((short) pumpTime.getMinute());
+ byteBuf.putUInt8((short) pumpTime.getSecond());
+ return byteBuf;
+ }
+
+ public void setPumpTime(PumpTime pumpTime) {
+ this.pumpTime = pumpTime;
+ }
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsightLocal/app_layer/remote_control/SetOperatingModeMessage.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsightLocal/app_layer/remote_control/SetOperatingModeMessage.java
new file mode 100644
index 0000000000..a217ab54f7
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsightLocal/app_layer/remote_control/SetOperatingModeMessage.java
@@ -0,0 +1,28 @@
+package info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.remote_control;
+
+import info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.AppLayerMessage;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.Service;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.descriptors.MessagePriority;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.descriptors.OperatingMode;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.ids.OperatingModeIDs;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.utils.ByteBuf;
+
+public class SetOperatingModeMessage extends AppLayerMessage {
+
+ private OperatingMode operatingMode;
+
+ public SetOperatingModeMessage() {
+ super(MessagePriority.HIGHEST, false, true, Service.REMOTE_CONTROL);
+ }
+
+ @Override
+ protected ByteBuf getData() {
+ ByteBuf byteBuf = new ByteBuf(2);
+ byteBuf.putUInt16LE(OperatingModeIDs.IDS.getID(operatingMode));
+ return byteBuf;
+ }
+
+ public void setOperatingMode(OperatingMode operatingMode) {
+ this.operatingMode = operatingMode;
+ }
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsightLocal/app_layer/remote_control/SetTBRMessage.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsightLocal/app_layer/remote_control/SetTBRMessage.java
new file mode 100644
index 0000000000..76959ed025
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsightLocal/app_layer/remote_control/SetTBRMessage.java
@@ -0,0 +1,33 @@
+package info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.remote_control;
+
+import info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.AppLayerMessage;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.Service;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.descriptors.MessagePriority;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.utils.ByteBuf;
+
+public class SetTBRMessage extends AppLayerMessage {
+
+ private int percentage;
+ private int duration;
+
+ public SetTBRMessage() {
+ super(MessagePriority.NORMAL, false, true, Service.REMOTE_CONTROL);
+ }
+
+ @Override
+ protected ByteBuf getData() {
+ ByteBuf byteBuf = new ByteBuf(6);
+ byteBuf.putUInt16LE(percentage);
+ byteBuf.putUInt16LE(duration);
+ byteBuf.putUInt16LE(31);
+ return byteBuf;
+ }
+
+ public void setPercentage(int percentage) {
+ this.percentage = percentage;
+ }
+
+ public void setDuration(int duration) {
+ this.duration = duration;
+ }
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsightLocal/app_layer/remote_control/SnoozeAlertMessage.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsightLocal/app_layer/remote_control/SnoozeAlertMessage.java
new file mode 100644
index 0000000000..2278ae84e8
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsightLocal/app_layer/remote_control/SnoozeAlertMessage.java
@@ -0,0 +1,26 @@
+package info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.remote_control;
+
+import info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.AppLayerMessage;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.Service;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.descriptors.MessagePriority;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.utils.ByteBuf;
+
+public class SnoozeAlertMessage extends AppLayerMessage {
+
+ private int alertID;
+
+ public SnoozeAlertMessage() {
+ super(MessagePriority.NORMAL, false, true, Service.REMOTE_CONTROL);
+ }
+
+ @Override
+ protected ByteBuf getData() {
+ ByteBuf byteBuf = new ByteBuf(2);
+ byteBuf.putUInt16LE(alertID);
+ return byteBuf;
+ }
+
+ public void setAlertID(int alertID) {
+ this.alertID = alertID;
+ }
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsightLocal/app_layer/status/GetActiveAlertMessage.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsightLocal/app_layer/status/GetActiveAlertMessage.java
new file mode 100644
index 0000000000..291726d35d
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsightLocal/app_layer/status/GetActiveAlertMessage.java
@@ -0,0 +1,54 @@
+package info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.status;
+
+import info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.AppLayerMessage;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.Service;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.descriptors.Alert;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.descriptors.MessagePriority;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.ids.AlertCategoryIDs;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.ids.AlertStatusIDs;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.ids.AlertTypeIDs;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.utils.ByteBuf;
+
+public class GetActiveAlertMessage extends AppLayerMessage {
+
+ private Alert alert;
+
+ public GetActiveAlertMessage() {
+ super(MessagePriority.NORMAL, true, false, Service.STATUS);
+ }
+
+ @Override
+ protected void parse(ByteBuf byteBuf) {
+ Alert alert = new Alert();
+ alert.setAlertId(byteBuf.readUInt16LE());
+ alert.setAlertCategory(AlertCategoryIDs.IDS.getType(byteBuf.readUInt16LE()));
+ alert.setAlertType(AlertTypeIDs.IDS.getType(byteBuf.readUInt16LE()));
+ alert.setAlertStatus(AlertStatusIDs.IDS.getType(byteBuf.readUInt16LE()));
+ if (alert.getAlertType() != null) {
+ switch (alert.getAlertType()) {
+ case WARNING_38:
+ byteBuf.shift(4);
+ alert.setProgrammedBolusAmount(byteBuf.readUInt16Decimal());
+ alert.setDeliveredBolusAmount(byteBuf.readUInt16Decimal());
+ break;
+ case REMINDER_07:
+ case WARNING_36:
+ byteBuf.shift(2);
+ alert.setTBRAmount(byteBuf.readUInt16LE());
+ alert.setTBRDuration(byteBuf.readUInt16LE());
+ break;
+ case WARNING_31:
+ alert.setCartridgeAmount(byteBuf.readUInt16Decimal());
+ break;
+ }
+ }
+ if (alert.getAlertCategory() != null
+ && alert.getAlertType() != null
+ && alert.getAlertStatus() != null)
+ this.alert = alert;
+ }
+
+ public Alert getAlert() {
+ return this.alert;
+ }
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsightLocal/app_layer/status/GetActiveBasalRateMessage.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsightLocal/app_layer/status/GetActiveBasalRateMessage.java
new file mode 100644
index 0000000000..b5aa73f2a7
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsightLocal/app_layer/status/GetActiveBasalRateMessage.java
@@ -0,0 +1,30 @@
+package info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.status;
+
+import info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.AppLayerMessage;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.Service;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.descriptors.ActiveBasalRate;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.descriptors.MessagePriority;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.ids.ActiveBasalProfileIDs;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.utils.ByteBuf;
+
+public class GetActiveBasalRateMessage extends AppLayerMessage {
+
+ private ActiveBasalRate activeBasalRate;
+
+ public GetActiveBasalRateMessage() {
+ super(MessagePriority.NORMAL, true, false, Service.STATUS);
+ }
+
+ @Override
+ protected void parse(ByteBuf byteBuf) {
+ ActiveBasalRate activeBasalRate = new ActiveBasalRate();
+ activeBasalRate.setActiveBasalProfile(ActiveBasalProfileIDs.IDS.getType(byteBuf.readUInt16LE()));
+ activeBasalRate.setActiveBasalProfileName(byteBuf.readUTF16(30));
+ activeBasalRate.setActiveBasalRate(byteBuf.readUInt16Decimal());
+ if (activeBasalRate.getActiveBasalProfile() != null) this.activeBasalRate = activeBasalRate;
+ }
+
+ public ActiveBasalRate getActiveBasalRate() {
+ return this.activeBasalRate;
+ }
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsightLocal/app_layer/status/GetActiveBolusesMessage.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsightLocal/app_layer/status/GetActiveBolusesMessage.java
new file mode 100644
index 0000000000..90cd93c127
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsightLocal/app_layer/status/GetActiveBolusesMessage.java
@@ -0,0 +1,40 @@
+package info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.status;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.AppLayerMessage;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.Service;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.descriptors.ActiveBolus;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.descriptors.MessagePriority;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.ids.ActiveBolusTypeIDs;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.utils.ByteBuf;
+
+public class GetActiveBolusesMessage extends AppLayerMessage {
+
+ private List activeBoluses;
+
+ public GetActiveBolusesMessage() {
+ super(MessagePriority.NORMAL, true, false, Service.STATUS);
+ }
+
+ @Override
+ protected void parse(ByteBuf byteBuf) {
+ activeBoluses = new ArrayList<>();
+ for (int i = 0; i < 3; i++) {
+ ActiveBolus activeBolus = new ActiveBolus();
+ activeBolus.setBolusID(byteBuf.readUInt16LE());
+ activeBolus.setBolusType(ActiveBolusTypeIDs.IDS.getType(byteBuf.readUInt16LE()));
+ byteBuf.shift(2);
+ byteBuf.shift(2);
+ activeBolus.setInitialAmount(byteBuf.readUInt16Decimal());
+ activeBolus.setRemainingAmount(byteBuf.readUInt16Decimal());
+ activeBolus.setRemainingDuration(byteBuf.readUInt16LE());
+ if (activeBolus.getBolusType() != null) activeBoluses.add(activeBolus);
+ }
+ }
+
+ public List getActiveBoluses() {
+ return this.activeBoluses;
+ }
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsightLocal/app_layer/status/GetActiveTBRMessage.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsightLocal/app_layer/status/GetActiveTBRMessage.java
new file mode 100644
index 0000000000..d839a5a394
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsightLocal/app_layer/status/GetActiveTBRMessage.java
@@ -0,0 +1,29 @@
+package info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.status;
+
+import info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.AppLayerMessage;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.Service;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.descriptors.ActiveTBR;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.descriptors.MessagePriority;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.utils.ByteBuf;
+
+public class GetActiveTBRMessage extends AppLayerMessage {
+
+ private ActiveTBR activeTBR;
+
+ public GetActiveTBRMessage() {
+ super(MessagePriority.NORMAL, true, false, Service.STATUS);
+ }
+
+ @Override
+ protected void parse(ByteBuf byteBuf) {
+ ActiveTBR activeTBR = new ActiveTBR();
+ activeTBR.setPercentage(byteBuf.readUInt16LE());
+ activeTBR.setRemainingDuration(byteBuf.readUInt16LE());
+ activeTBR.setInitialDuration(byteBuf.readUInt16LE());
+ if (activeTBR.getPercentage() != 100) this.activeTBR = activeTBR;
+ }
+
+ public ActiveTBR getActiveTBR() {
+ return this.activeTBR;
+ }
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsightLocal/app_layer/status/GetBatteryStatusMessage.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsightLocal/app_layer/status/GetBatteryStatusMessage.java
new file mode 100644
index 0000000000..d6d8668f56
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsightLocal/app_layer/status/GetBatteryStatusMessage.java
@@ -0,0 +1,30 @@
+package info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.status;
+
+import info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.AppLayerMessage;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.Service;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.descriptors.BatteryStatus;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.descriptors.MessagePriority;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.ids.BatteryTypeIDs;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.ids.SymbolStatusIDs;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.utils.ByteBuf;
+
+public class GetBatteryStatusMessage extends AppLayerMessage {
+
+ private BatteryStatus batteryStatus;
+
+ public GetBatteryStatusMessage() {
+ super(MessagePriority.NORMAL, false, false, Service.STATUS);
+ }
+
+ @Override
+ protected void parse(ByteBuf byteBuf) {
+ batteryStatus = new BatteryStatus();
+ batteryStatus.setBatteryType(BatteryTypeIDs.IDS.getType(byteBuf.readUInt16LE()));
+ batteryStatus.setBatteryAmount(byteBuf.readUInt16LE());
+ batteryStatus.setSymbolStatus(SymbolStatusIDs.IDS.getType(byteBuf.readUInt16LE()));
+ }
+
+ public BatteryStatus getBatteryStatus() {
+ return this.batteryStatus;
+ }
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsightLocal/app_layer/status/GetCartridgeStatusMessage.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsightLocal/app_layer/status/GetCartridgeStatusMessage.java
new file mode 100644
index 0000000000..c2c941e236
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsightLocal/app_layer/status/GetCartridgeStatusMessage.java
@@ -0,0 +1,31 @@
+package info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.status;
+
+import info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.AppLayerMessage;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.Service;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.descriptors.CartridgeStatus;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.descriptors.MessagePriority;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.ids.CartridgeTypeIDs;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.ids.SymbolStatusIDs;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.utils.ByteBuf;
+
+public class GetCartridgeStatusMessage extends AppLayerMessage {
+
+ private CartridgeStatus cartridgeStatus;
+
+ public GetCartridgeStatusMessage() {
+ super(MessagePriority.NORMAL, false, false, Service.STATUS);
+ }
+
+ @Override
+ protected void parse(ByteBuf byteBuf) {
+ cartridgeStatus = new CartridgeStatus();
+ cartridgeStatus.setInserted(byteBuf.readBoolean());
+ cartridgeStatus.setCartridgeType(CartridgeTypeIDs.IDS.getType(byteBuf.readUInt16LE()));
+ cartridgeStatus.setSymbolStatus(SymbolStatusIDs.IDS.getType(byteBuf.readUInt16LE()));
+ cartridgeStatus.setRemainingAmount(byteBuf.readUInt16Decimal());
+ }
+
+ public CartridgeStatus getCartridgeStatus() {
+ return this.cartridgeStatus;
+ }
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsightLocal/app_layer/status/GetDateTimeMessage.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsightLocal/app_layer/status/GetDateTimeMessage.java
new file mode 100644
index 0000000000..8d80a7e465
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsightLocal/app_layer/status/GetDateTimeMessage.java
@@ -0,0 +1,31 @@
+package info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.status;
+
+import info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.AppLayerMessage;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.Service;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.descriptors.MessagePriority;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.descriptors.PumpTime;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.utils.ByteBuf;
+
+public class GetDateTimeMessage extends AppLayerMessage {
+
+ private PumpTime pumpTime;
+
+ public GetDateTimeMessage() {
+ super(MessagePriority.NORMAL, true, false, Service.STATUS);
+ }
+
+ @Override
+ protected void parse(ByteBuf byteBuf) {
+ pumpTime = new PumpTime();
+ pumpTime.setYear(byteBuf.readUInt16LE());
+ pumpTime.setMonth(byteBuf.readUInt8());
+ pumpTime.setDay(byteBuf.readUInt8());
+ pumpTime.setHour(byteBuf.readUInt8());
+ pumpTime.setMinute(byteBuf.readUInt8());
+ pumpTime.setSecond(byteBuf.readUInt8());
+ }
+
+ public PumpTime getPumpTime() {
+ return this.pumpTime;
+ }
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsightLocal/app_layer/status/GetFirmwareVersionsMessage.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsightLocal/app_layer/status/GetFirmwareVersionsMessage.java
new file mode 100644
index 0000000000..ef97fc3861
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsightLocal/app_layer/status/GetFirmwareVersionsMessage.java
@@ -0,0 +1,39 @@
+package info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.status;
+
+import android.util.Log;
+
+import org.spongycastle.util.encoders.Hex;
+
+import info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.AppLayerMessage;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.Service;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.descriptors.FirmwareVersions;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.descriptors.MessagePriority;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.utils.ByteBuf;
+
+public class GetFirmwareVersionsMessage extends AppLayerMessage {
+
+ private FirmwareVersions firmwareVersions;
+
+ public GetFirmwareVersionsMessage() {
+ super(MessagePriority.NORMAL, false, false, Service.STATUS);
+ }
+
+ @Override
+ protected void parse(ByteBuf byteBuf) {
+ firmwareVersions = new FirmwareVersions();
+ firmwareVersions.setReleaseSWVersion(byteBuf.readASCII(13));
+ firmwareVersions.setUiProcSWVersion(byteBuf.readASCII(11));
+ firmwareVersions.setPcProcSWVersion(byteBuf.readASCII(11));
+ firmwareVersions.setMdTelProcSWVersion(byteBuf.readASCII(11));
+ firmwareVersions.setBtInfoPageVersion(byteBuf.readASCII(11));
+ firmwareVersions.setSafetyProcSWVersion(byteBuf.readASCII(11));
+ firmwareVersions.setConfigIndex(byteBuf.readUInt16LE());
+ firmwareVersions.setHistoryIndex(byteBuf.readUInt16LE());
+ firmwareVersions.setStateIndex(byteBuf.readUInt16LE());
+ firmwareVersions.setVocabularyIndex(byteBuf.readUInt16LE());
+ }
+
+ public FirmwareVersions getFirmwareVersions() {
+ return this.firmwareVersions;
+ }
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsightLocal/app_layer/status/GetOperatingModeMessage.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsightLocal/app_layer/status/GetOperatingModeMessage.java
new file mode 100644
index 0000000000..ebf7607801
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsightLocal/app_layer/status/GetOperatingModeMessage.java
@@ -0,0 +1,26 @@
+package info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.status;
+
+import info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.AppLayerMessage;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.Service;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.descriptors.MessagePriority;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.descriptors.OperatingMode;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.ids.OperatingModeIDs;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.utils.ByteBuf;
+
+public class GetOperatingModeMessage extends AppLayerMessage {
+
+ private OperatingMode operatingMode;
+
+ public GetOperatingModeMessage() {
+ super(MessagePriority.NORMAL, true, false, Service.STATUS);
+ }
+
+ @Override
+ protected void parse(ByteBuf byteBuf) {
+ this.operatingMode = OperatingModeIDs.IDS.getType(byteBuf.readUInt16LE());
+ }
+
+ public OperatingMode getOperatingMode() {
+ return this.operatingMode;
+ }
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsightLocal/app_layer/status/GetPumpStatusRegisterMessage.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsightLocal/app_layer/status/GetPumpStatusRegisterMessage.java
new file mode 100644
index 0000000000..2fd63c76fe
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsightLocal/app_layer/status/GetPumpStatusRegisterMessage.java
@@ -0,0 +1,60 @@
+package info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.status;
+
+import info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.AppLayerMessage;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.Service;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.descriptors.MessagePriority;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.utils.ByteBuf;
+
+public class GetPumpStatusRegisterMessage extends AppLayerMessage {
+
+ private boolean operatingModeChanged;
+ private boolean batteryStatusChanged;
+ private boolean cartridgeStatusChanged;
+ private boolean totalDailyDoseChanged;
+ private boolean activeBasalRateChanged;
+ private boolean activeTBRChanged;
+ private boolean activeBolusesChanged;
+
+ public GetPumpStatusRegisterMessage() {
+ super(MessagePriority.NORMAL, false, false, Service.STATUS);
+ }
+
+ @Override
+ protected void parse(ByteBuf byteBuf) {
+ operatingModeChanged = byteBuf.readBoolean();
+ batteryStatusChanged = byteBuf.readBoolean();
+ cartridgeStatusChanged = byteBuf.readBoolean();
+ totalDailyDoseChanged = byteBuf.readBoolean();
+ activeBasalRateChanged = byteBuf.readBoolean();
+ activeTBRChanged = byteBuf.readBoolean();
+ activeBolusesChanged = byteBuf.readBoolean();
+ }
+
+ public boolean isOperatingModeChanged() {
+ return this.operatingModeChanged;
+ }
+
+ public boolean isBatteryStatusChanged() {
+ return this.batteryStatusChanged;
+ }
+
+ public boolean isCartridgeStatusChanged() {
+ return this.cartridgeStatusChanged;
+ }
+
+ public boolean isTotalDailyDoseChanged() {
+ return this.totalDailyDoseChanged;
+ }
+
+ public boolean isActiveBasalRateChanged() {
+ return this.activeBasalRateChanged;
+ }
+
+ public boolean isActiveTBRChanged() {
+ return this.activeTBRChanged;
+ }
+
+ public boolean isActiveBolusesChanged() {
+ return this.activeBolusesChanged;
+ }
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsightLocal/app_layer/status/GetTotalDailyDoseMessage.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsightLocal/app_layer/status/GetTotalDailyDoseMessage.java
new file mode 100644
index 0000000000..1f208c97e0
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsightLocal/app_layer/status/GetTotalDailyDoseMessage.java
@@ -0,0 +1,28 @@
+package info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.status;
+
+import info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.AppLayerMessage;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.Service;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.descriptors.MessagePriority;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.descriptors.TotalDailyDose;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.utils.ByteBuf;
+
+public class GetTotalDailyDoseMessage extends AppLayerMessage {
+
+ private TotalDailyDose tdd;
+
+ public GetTotalDailyDoseMessage() {
+ super(MessagePriority.NORMAL, true, false, Service.STATUS);
+ }
+
+ @Override
+ protected void parse(ByteBuf byteBuf) {
+ tdd = new TotalDailyDose();
+ tdd.setBolus(byteBuf.readUInt32Decimal100());
+ tdd.setBasal(byteBuf.readUInt32Decimal100());
+ tdd.setBolusAndBasal(byteBuf.readUInt32Decimal100());
+ }
+
+ public TotalDailyDose getTDD() {
+ return this.tdd;
+ }
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsightLocal/app_layer/status/ResetPumpStatusRegisterMessage.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsightLocal/app_layer/status/ResetPumpStatusRegisterMessage.java
new file mode 100644
index 0000000000..f215165be5
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsightLocal/app_layer/status/ResetPumpStatusRegisterMessage.java
@@ -0,0 +1,63 @@
+package info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.status;
+
+import info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.AppLayerMessage;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.Service;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.descriptors.MessagePriority;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.utils.ByteBuf;
+
+public class ResetPumpStatusRegisterMessage extends AppLayerMessage {
+
+ private boolean operatingModeChanged;
+ private boolean batteryStatusChanged;
+ private boolean cartridgeStatusChanged;
+ private boolean totalDailyDoseChanged;
+ private boolean activeBasalRateChanged;
+ private boolean activeTBRChanged;
+ private boolean activeBolusesChanged;
+
+ public ResetPumpStatusRegisterMessage() {
+ super(MessagePriority.NORMAL, false, false, Service.STATUS);
+ }
+
+ @Override
+ protected ByteBuf getData() {
+ ByteBuf byteBuf = new ByteBuf(28);
+ byteBuf.putBoolean(operatingModeChanged);
+ byteBuf.putBoolean(batteryStatusChanged);
+ byteBuf.putBoolean(cartridgeStatusChanged);
+ byteBuf.putBoolean(totalDailyDoseChanged);
+ byteBuf.putBoolean(activeBasalRateChanged);
+ byteBuf.putBoolean(activeTBRChanged);
+ byteBuf.putBoolean(activeBolusesChanged);
+ for (int i = 0; i < 7; i++) byteBuf.putBoolean(false);
+ return byteBuf;
+ }
+
+ public void setOperatingModeChanged(boolean operatingModeChanged) {
+ this.operatingModeChanged = operatingModeChanged;
+ }
+
+ public void setBatteryStatusChanged(boolean batteryStatusChanged) {
+ this.batteryStatusChanged = batteryStatusChanged;
+ }
+
+ public void setCartridgeStatusChanged(boolean cartridgeStatusChanged) {
+ this.cartridgeStatusChanged = cartridgeStatusChanged;
+ }
+
+ public void setTotalDailyDoseChanged(boolean totalDailyDoseChanged) {
+ this.totalDailyDoseChanged = totalDailyDoseChanged;
+ }
+
+ public void setActiveBasalRateChanged(boolean activeBasalRateChanged) {
+ this.activeBasalRateChanged = activeBasalRateChanged;
+ }
+
+ public void setActiveTBRChanged(boolean activeTBRChanged) {
+ this.activeTBRChanged = activeTBRChanged;
+ }
+
+ public void setActiveBolusesChanged(boolean activeBolusesChanged) {
+ this.activeBolusesChanged = activeBolusesChanged;
+ }
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsightLocal/connection_service/ConfigurationMessageRequest.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsightLocal/connection_service/ConfigurationMessageRequest.java
new file mode 100644
index 0000000000..cb2703e3c7
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsightLocal/connection_service/ConfigurationMessageRequest.java
@@ -0,0 +1,33 @@
+package info.nightscout.androidaps.plugins.PumpInsightLocal.connection_service;
+
+import info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.AppLayerMessage;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.configuration.CloseConfigurationWriteSessionMessage;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.configuration.OpenConfigurationWriteSessionMessage;
+
+public class ConfigurationMessageRequest extends MessageRequest {
+
+ private MessageRequest openRequest;
+ private MessageRequest closeRequest;
+
+ public ConfigurationMessageRequest(T request, MessageRequest openRequest, MessageRequest closeRequest) {
+ super(request);
+ this.openRequest = openRequest;
+ this.closeRequest = closeRequest;
+ }
+
+ @Override
+ public T await() throws Exception {
+ openRequest.await();
+ T response = super.await();
+ closeRequest.await();
+ return response;
+ }
+
+ @Override
+ public T await(long timeout) throws Exception {
+ openRequest.await(timeout);
+ T response = super.await(timeout);
+ closeRequest.await(timeout);
+ return response;
+ }
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsightLocal/connection_service/InsightConnectionService.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsightLocal/connection_service/InsightConnectionService.java
new file mode 100644
index 0000000000..b4ee726a6b
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsightLocal/connection_service/InsightConnectionService.java
@@ -0,0 +1,780 @@
+package info.nightscout.androidaps.plugins.PumpInsightLocal.connection_service;
+
+import android.app.Service;
+import android.bluetooth.BluetoothAdapter;
+import android.bluetooth.BluetoothDevice;
+import android.bluetooth.BluetoothSocket;
+import android.content.Intent;
+import android.os.Binder;
+import android.os.IBinder;
+import android.os.PowerManager;
+import android.support.annotation.Nullable;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.spongycastle.crypto.InvalidCipherTextException;
+
+import java.io.IOException;
+import java.security.SecureRandom;
+import java.util.ArrayList;
+import java.util.List;
+
+import info.nightscout.androidaps.logging.L;
+import info.nightscout.androidaps.plugins.PumpCombo.ruffyscripter.BolusProgressReporter;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.AppLayerMessage;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.ReadParameterBlockMessage;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.configuration.CloseConfigurationWriteSessionMessage;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.configuration.OpenConfigurationWriteSessionMessage;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.configuration.WriteConfigurationBlockMessage;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.connection.ActivateServiceMessage;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.connection.BindMessage;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.connection.ConnectMessage;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.connection.DisconnectMessage;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.connection.ServiceChallengeMessage;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.parameter_blocks.SystemIdentificationBlock;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.status.GetFirmwareVersionsMessage;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.descriptors.FirmwareVersions;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.descriptors.InsightState;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.descriptors.SystemIdentification;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.exceptions.ConnectionFailedException;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.exceptions.ConnectionLostException;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.exceptions.DisconnectedException;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.exceptions.InsightException;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.exceptions.InvalidNonceException;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.exceptions.InvalidSatlCommandException;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.exceptions.ReceivedPacketInInvalidStateException;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.exceptions.TimeoutException;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.exceptions.TooChattyPumpException;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.exceptions.satl_errors.SatlCompatibleStateErrorException;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.exceptions.satl_errors.SatlDecryptVerifyFailedErrorException;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.exceptions.satl_errors.SatlIncompatibleVersionErrorException;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.exceptions.satl_errors.SatlInvalidCRCErrorException;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.exceptions.satl_errors.SatlInvalidCommIdErrorException;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.exceptions.satl_errors.SatlInvalidMacErrorException;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.exceptions.satl_errors.SatlInvalidMessageTypeErrorException;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.exceptions.satl_errors.SatlInvalidNonceErrorException;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.exceptions.satl_errors.SatlInvalidPacketErrorException;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.exceptions.satl_errors.SatlInvalidPayloadLengthErrorException;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.exceptions.satl_errors.SatlNoneErrorException;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.exceptions.satl_errors.SatlPairingRejectedException;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.exceptions.satl_errors.SatlUndefinedErrorException;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.exceptions.satl_errors.SatlWrongStateException;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.ids.ServiceIDs;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.satl.ConnectionRequest;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.satl.ConnectionResponse;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.satl.DataMessage;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.satl.ErrorMessage;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.satl.KeyRequest;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.satl.KeyResponse;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.satl.SatlMessage;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.satl.SynAckResponse;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.satl.SynRequest;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.satl.VerifyConfirmRequest;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.satl.VerifyConfirmResponse;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.satl.VerifyDisplayRequest;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.satl.VerifyDisplayResponse;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.utils.ByteBuf;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.utils.ConnectionEstablisher;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.utils.DelayedActionThread;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.utils.InputStreamReader;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.utils.Nonce;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.utils.OutputStreamWriter;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.utils.PairingDataStorage;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.utils.crypto.Cryptograph;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.utils.crypto.DerivedKeys;
+import info.nightscout.androidaps.plugins.PumpInsightLocal.utils.crypto.KeyPair;
+import info.nightscout.utils.SP;
+
+public class InsightConnectionService extends Service implements ConnectionEstablisher.Callback, InputStreamReader.Callback, OutputStreamWriter.Callback {
+
+ private static Logger log = LoggerFactory.getLogger(L.PUMPCOMM);
+
+ private static final int BUFFER_SIZE = 1024;
+ private static final long RESPONSE_TIMEOUT = 6000;
+
+ private List stateCallbacks = new ArrayList<>();
+ private final List