diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index ab45d3d4f5..5acc5124ae 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -116,11 +116,15 @@ android:name=".Services.DataService" android:exported="false" /> + 200) percent = 200; + if (percent > getPumpDescription().maxHighTempPercent) percent = getPumpDescription().maxHighTempPercent; if (getDanaRPump().isTempBasalInProgress && getDanaRPump().tempBasalPercent == percent) { result.enacted = false; result.success = true; @@ -811,7 +811,7 @@ public class DanaRPlugin implements PluginBase, PumpInterface, ConstraintsInterf public Integer applyBasalConstraints(Integer percentRate) { Integer origPercentRate = percentRate; if (percentRate < 0) percentRate = 0; - if (percentRate > 200) percentRate = 200; + if (percentRate > getPumpDescription().maxHighTempPercent) percentRate = getPumpDescription().maxHighTempPercent; if (!Objects.equals(percentRate, origPercentRate) && Config.logConstraintsChanges && !Objects.equals(origPercentRate, Constants.basalPercentOnlyForCheckLimit)) log.debug("Limiting percent rate " + origPercentRate + "% to " + percentRate + "%"); return percentRate; 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 0714e2eeee..586fcef4a5 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 @@ -16,6 +16,13 @@ import info.nightscout.utils.SP; * Created by mike on 04.07.2016. */ public class DanaRPump { + private static DanaRPump instance = null; + + public static DanaRPump getInstance() { + if (instance == null) instance = new DanaRPump(); + return instance; + } + public static final int UNITS_MGDL = 0; public static final int UNITS_MMOL = 1; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/History/DanaRHistoryActivity.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/History/DanaRHistoryActivity.java index bc925c27bd..126399c93a 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/History/DanaRHistoryActivity.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/History/DanaRHistoryActivity.java @@ -40,7 +40,7 @@ import info.nightscout.androidaps.R; import info.nightscout.androidaps.db.DanaRHistoryRecord; import info.nightscout.androidaps.events.EventPumpStatusChanged; import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin; -import info.nightscout.androidaps.plugins.PumpDanaR.Services.ExecutionService; +import info.nightscout.androidaps.plugins.PumpDanaR.services.DanaRExecutionService; import info.nightscout.androidaps.plugins.PumpDanaR.comm.RecordTypes; import info.nightscout.androidaps.plugins.PumpDanaR.events.EventDanaRSyncStatus; import info.nightscout.androidaps.plugins.NSClientInternal.data.NSProfile; @@ -52,7 +52,7 @@ public class DanaRHistoryActivity extends Activity { private static Logger log = LoggerFactory.getLogger(DanaRHistoryActivity.class); private boolean mBounded; - private static ExecutionService mExecutionService; + private static DanaRExecutionService mExecutionService; private Handler mHandler; private static HandlerThread mHandlerThread; @@ -95,7 +95,7 @@ public class DanaRHistoryActivity extends Activity { @Override public void onStart() { super.onStart(); - Intent intent = new Intent(this, ExecutionService.class); + Intent intent = new Intent(this, DanaRExecutionService.class); bindService(intent, mConnection, Context.BIND_AUTO_CREATE); } @@ -131,7 +131,7 @@ public class DanaRHistoryActivity extends Activity { public void onServiceConnected(ComponentName name, IBinder service) { log.debug("Service is connected"); mBounded = true; - ExecutionService.LocalBinder mLocalBinder = (ExecutionService.LocalBinder) service; + DanaRExecutionService.LocalBinder mLocalBinder = (DanaRExecutionService.LocalBinder) service; mExecutionService = mLocalBinder.getServiceInstance(); } }; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/History/DanaRStatsActivity.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/History/DanaRStatsActivity.java index 883330dd5b..e081a6801c 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/History/DanaRStatsActivity.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/History/DanaRStatsActivity.java @@ -52,7 +52,7 @@ import info.nightscout.androidaps.events.EventPumpStatusChanged; import info.nightscout.androidaps.interfaces.ProfileInterface; import info.nightscout.androidaps.plugins.ProfileCircadianPercentage.CircadianPercentageProfilePlugin; import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin; -import info.nightscout.androidaps.plugins.PumpDanaR.Services.ExecutionService; +import info.nightscout.androidaps.plugins.PumpDanaR.services.DanaRExecutionService; import info.nightscout.androidaps.plugins.PumpDanaR.comm.RecordTypes; import info.nightscout.androidaps.plugins.PumpDanaR.events.EventDanaRSyncStatus; import info.nightscout.utils.DecimalFormatter; @@ -63,7 +63,7 @@ public class DanaRStatsActivity extends Activity { private static Logger log = LoggerFactory.getLogger(DanaRStatsActivity.class); private boolean mBounded; - private static ExecutionService mExecutionService; + private static DanaRExecutionService mExecutionService; private Handler mHandler; private static HandlerThread mHandlerThread; @@ -89,7 +89,7 @@ public class DanaRStatsActivity extends Activity { @Override public void onStart() { super.onStart(); - Intent intent = new Intent(this, ExecutionService.class); + Intent intent = new Intent(this, DanaRExecutionService.class); bindService(intent, mConnection, Context.BIND_AUTO_CREATE); } @@ -140,7 +140,7 @@ public class DanaRStatsActivity extends Activity { public void onServiceConnected(ComponentName name, IBinder service) { log.debug("Service is connected"); mBounded = true; - ExecutionService.LocalBinder mLocalBinder = (ExecutionService.LocalBinder) service; + DanaRExecutionService.LocalBinder mLocalBinder = (DanaRExecutionService.LocalBinder) service; mExecutionService = mLocalBinder.getServiceInstance(); } }; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MessageOriginalNames.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MessageOriginalNames.java index 1ab166801d..3526479947 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MessageOriginalNames.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MessageOriginalNames.java @@ -11,10 +11,10 @@ import java.util.HashMap; public class MessageOriginalNames { private static Logger log = LoggerFactory.getLogger(MessageOriginalNames.class); - public static HashMap messageNames; + public static HashMap messageNames; static { - messageNames = new HashMap(); + messageNames = new HashMap<>(); messageNames.put(0x3001, "CMD_CONNECT"); messageNames.put(0x3002, "CMD_DISCONNECT"); @@ -150,8 +150,17 @@ public class MessageOriginalNames { messageNames.put(0xF0F3, "CMD_PUMP_TIMECHANGE_CLEAR"); messageNames.put(0x43F2, "CMD_HISTORY_DATEOVER_ALL"); messageNames.put(0x4300, "CMD_HISTORY_DATEOVER_DONE"); + + messageNames.put(0xE001, "CMD_PUMP_APSTEMP_VALUE"); + messageNames.put(0xE002, "CMD_PUMPSET_APSTEMP"); + messageNames.put(0xE003, "CMD_HISTORY_APSTEMP"); + + messageNames.put(0xE001, "CMD_PUMP_APSTEMP_VALUE"); + messageNames.put(0xE002, "CMD_PUMPSET_APSTEMP"); + messageNames.put(0xE003, "CMD_HISTORY_APSTEMP"); } + public static String getName(Integer command) { if (messageNames.containsKey(command)) return messageNames.get(command); diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgBolusProgress.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgBolusProgress.java index 2130561aeb..fd18407e5c 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgBolusProgress.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgBolusProgress.java @@ -1,5 +1,7 @@ package info.nightscout.androidaps.plugins.PumpDanaR.comm; +import com.squareup.otto.Bus; + import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgBolusStart.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgBolusStart.java index a5591746b0..0e6a3e814a 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgBolusStart.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgBolusStart.java @@ -3,6 +3,7 @@ package info.nightscout.androidaps.plugins.PumpDanaR.comm; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import info.nightscout.androidaps.BuildConfig; import info.nightscout.androidaps.Config; import info.nightscout.androidaps.MainApp; import info.nightscout.utils.HardLimits; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgBolusStop.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgBolusStop.java index 0d2c51bf7c..7040b84183 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgBolusStop.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgBolusStop.java @@ -1,5 +1,7 @@ package info.nightscout.androidaps.plugins.PumpDanaR.comm; +import com.squareup.otto.Bus; + import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgCheckValue.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgCheckValue.java index f63d49849b..c05029caff 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgCheckValue.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgCheckValue.java @@ -22,9 +22,9 @@ public class MsgCheckValue extends MessageBase { @Override public void handleMessage(byte[] bytes) { - DanaRPump pump = DanaRPlugin.getDanaRPump(); + DanaRPump pump = DanaRPump.getInstance(); - DanaRPlugin.getDanaRPump().isNewPump = true; + pump.isNewPump = true; log.debug("New firmware confirmed"); pump.model = intFromBuff(bytes, 0, 1); diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgInitConnStatusBasic.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgInitConnStatusBasic.java index 2a22fd86d9..e7f6032c00 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgInitConnStatusBasic.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgInitConnStatusBasic.java @@ -4,7 +4,6 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import info.nightscout.androidaps.Config; -import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPlugin; import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPump; public class MsgInitConnStatusBasic extends MessageBase { @@ -19,7 +18,7 @@ public class MsgInitConnStatusBasic extends MessageBase { if (bytes.length - 10 < 21) { return; } - DanaRPump pump = DanaRPlugin.getDanaRPump(); + DanaRPump pump = DanaRPump.getInstance(); pump.pumpSuspended = intFromBuff(bytes, 0, 1) == 1; pump.calculatorEnabled = intFromBuff(bytes, 1, 1) == 1; pump.dailyTotalUnits = intFromBuff(bytes, 2, 3) / 750d; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgInitConnStatusBolus.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgInitConnStatusBolus.java index 1b7a8dbe5c..b39929db5b 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgInitConnStatusBolus.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgInitConnStatusBolus.java @@ -6,7 +6,6 @@ import org.slf4j.LoggerFactory; import info.nightscout.androidaps.Config; import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.R; -import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPlugin; import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPump; import info.nightscout.androidaps.plugins.Overview.Notification; import info.nightscout.androidaps.plugins.Overview.events.EventDismissNotification; @@ -27,7 +26,7 @@ public class MsgInitConnStatusBolus extends MessageBase { if (bytes.length - 10 > 12) { return; } - DanaRPump pump = DanaRPlugin.getDanaRPump(); + DanaRPump pump = DanaRPump.getInstance(); int bolusConfig = intFromBuff(bytes, 0, 1); pump.isExtendedBolusEnabled = (bolusConfig & 0x01) != 0; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgInitConnStatusOption.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgInitConnStatusOption.java index 2009bddd40..560ed8b332 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgInitConnStatusOption.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgInitConnStatusOption.java @@ -4,7 +4,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import info.nightscout.androidaps.Config; -import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPlugin; +import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPump; /** * Created by mike on 28.05.2016. @@ -28,9 +28,9 @@ public class MsgInitConnStatusOption extends MessageBase { int lowReservoirAlarmBoundary = intFromBuff(bytes, 7, 1); //int none = intFromBuff(bytes, 8, 1); if (bytes.length >= 21) { - DanaRPlugin.getDanaRPump().password = intFromBuff(bytes, 9, 2) ^ 0x3463; + DanaRPump.getInstance().password = intFromBuff(bytes, 9, 2) ^ 0x3463; if (Config.logDanaMessageDetail) - log.debug("Pump password: " + DanaRPlugin.getDanaRPump().password); + log.debug("Pump password: " + DanaRPump.getInstance().password); } } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgInitConnStatusTime.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgInitConnStatusTime.java index 00b8379179..c12ca613d5 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgInitConnStatusTime.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgInitConnStatusTime.java @@ -11,6 +11,7 @@ import info.nightscout.androidaps.R; import info.nightscout.androidaps.events.EventRefreshGui; import info.nightscout.androidaps.interfaces.PluginBase; import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPlugin; +import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPump; import info.nightscout.androidaps.plugins.PumpDanaRKorean.DanaRKoreanPlugin; import info.nightscout.utils.ToastUtils; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgSetExtendedBolusStart.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgSetExtendedBolusStart.java index 9ef6b0136e..484078825e 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgSetExtendedBolusStart.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgSetExtendedBolusStart.java @@ -3,6 +3,7 @@ package info.nightscout.androidaps.plugins.PumpDanaR.comm; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import info.nightscout.androidaps.BuildConfig; import info.nightscout.androidaps.Config; import info.nightscout.androidaps.MainApp; import info.nightscout.utils.HardLimits; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgSetSingleBasalProfile.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgSetSingleBasalProfile.java index b56de8fd7a..32cd3745d8 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgSetSingleBasalProfile.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgSetSingleBasalProfile.java @@ -1,5 +1,7 @@ package info.nightscout.androidaps.plugins.PumpDanaR.comm; +import com.j256.ormlite.stmt.query.Not; + import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgSettingActiveProfile.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgSettingActiveProfile.java index b737073a43..20498e28e7 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgSettingActiveProfile.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgSettingActiveProfile.java @@ -4,7 +4,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import info.nightscout.androidaps.Config; -import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPlugin; +import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPump; /** * Created by mike on 05.07.2016. @@ -17,9 +17,9 @@ public class MsgSettingActiveProfile extends MessageBase { } public void handleMessage(byte[] bytes) { - DanaRPlugin.getDanaRPump().activeProfile = intFromBuff(bytes, 0, 1); + DanaRPump.getInstance().activeProfile = intFromBuff(bytes, 0, 1); if (Config.logDanaMessageDetail) - log.debug("Active profile number: " + DanaRPlugin.getDanaRPump().activeProfile); + log.debug("Active profile number: " + DanaRPump.getInstance().activeProfile); } } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgSettingBasal.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgSettingBasal.java index 82d003b434..e1a7e45315 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgSettingBasal.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgSettingBasal.java @@ -18,7 +18,7 @@ public class MsgSettingBasal extends MessageBase { } public void handleMessage(byte[] bytes) { - DanaRPump pump = DanaRPlugin.getDanaRPump(); + DanaRPump pump = DanaRPump.getInstance(); if (pump.pumpProfiles == null) pump.pumpProfiles = new double[4][]; pump.pumpProfiles[pump.activeProfile] = new double[24]; for (int index = 0; index < 24; index++) { @@ -29,7 +29,7 @@ public class MsgSettingBasal extends MessageBase { if (Config.logDanaMessageDetail) for (int index = 0; index < 24; index++) { - log.debug("Basal " + String.format("%02d", index) + "h: " + DanaRPlugin.getDanaRPump().pumpProfiles[DanaRPlugin.getDanaRPump().activeProfile][index]); + log.debug("Basal " + String.format("%02d", index) + "h: " + pump.pumpProfiles[pump.activeProfile][index]); } } } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgSettingBasalProfileAll.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgSettingBasalProfileAll.java index 6fab757486..24b5043769 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgSettingBasalProfileAll.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgSettingBasalProfileAll.java @@ -4,7 +4,6 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import info.nightscout.androidaps.Config; -import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPlugin; import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPump; @@ -22,8 +21,8 @@ public class MsgSettingBasalProfileAll extends MessageBase { } public void handleMessage(byte[] bytes) { - DanaRPump pump = DanaRPlugin.getDanaRPump(); - if (DanaRPlugin.getDanaRPump().basal48Enable) { + DanaRPump pump = DanaRPump.getInstance(); + if (pump.basal48Enable) { pump.pumpProfiles = new double[4][]; for (int profile = 0; profile < 4; profile++) { int position = intFromBuff(bytes, 107 * profile, 1); @@ -50,10 +49,10 @@ public class MsgSettingBasalProfileAll extends MessageBase { } if (Config.logDanaMessageDetail) { - if (DanaRPlugin.getDanaRPump().basal48Enable) { + if (pump.basal48Enable) { for (int profile = 0; profile < 4; profile++) { for (int index = 0; index < 24; index++) { - log.debug("Basal profile " + profile + ": " + String.format("%02d", index) + "h: " + DanaRPlugin.getDanaRPump().pumpProfiles[profile][index]); + log.debug("Basal profile " + profile + ": " + String.format("%02d", index) + "h: " + pump.pumpProfiles[profile][index]); } } } else { @@ -62,7 +61,7 @@ public class MsgSettingBasalProfileAll extends MessageBase { log.debug("Basal profile " + profile + ": " + String.format("%02d", (index / 2)) + ":" + String.format("%02d", (index % 2) * 30) + " : " + - DanaRPlugin.getDanaRPump().pumpProfiles[profile][index]); + pump.pumpProfiles[profile][index]); } } } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgSettingGlucose.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgSettingGlucose.java index 6c7b302abf..0f20c0843a 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgSettingGlucose.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgSettingGlucose.java @@ -4,7 +4,6 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import info.nightscout.androidaps.Config; -import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPlugin; import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPump; /** @@ -18,12 +17,13 @@ public class MsgSettingGlucose extends MessageBase { } public void handleMessage(byte[] bytes) { - DanaRPlugin.getDanaRPump().units = intFromBuff(bytes, 0, 1); - DanaRPlugin.getDanaRPump().easyBasalMode = intFromBuff(bytes, 1, 1); + DanaRPump pump = DanaRPump.getInstance(); + pump.units = intFromBuff(bytes, 0, 1); + pump.easyBasalMode = intFromBuff(bytes, 1, 1); if (Config.logDanaMessageDetail) { - log.debug("Pump units: " + (DanaRPlugin.getDanaRPump().units == DanaRPump.UNITS_MGDL ? "MGDL" : "MMOL")); - log.debug("Easy basal mode: " + DanaRPlugin.getDanaRPump().easyBasalMode); + log.debug("Pump units: " + (pump.units == DanaRPump.UNITS_MGDL ? "MGDL" : "MMOL")); + log.debug("Easy basal mode: " + pump.easyBasalMode); } } } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgSettingMaxValues.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgSettingMaxValues.java index 0f2de2fe0b..9279f2b1ba 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgSettingMaxValues.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgSettingMaxValues.java @@ -4,7 +4,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import info.nightscout.androidaps.Config; -import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPlugin; +import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPump; /** @@ -18,14 +18,15 @@ public class MsgSettingMaxValues extends MessageBase { } public void handleMessage(byte[] bytes) { - DanaRPlugin.getDanaRPump().maxBolus = intFromBuff(bytes, 0, 2) / 100d; - DanaRPlugin.getDanaRPump().maxBasal = intFromBuff(bytes, 2, 2) / 100d; - DanaRPlugin.getDanaRPump().maxDailyTotalUnits = intFromBuff(bytes, 4, 2) / 100; + DanaRPump pump = DanaRPump.getInstance(); + pump.maxBolus = intFromBuff(bytes, 0, 2) / 100d; + pump.maxBasal = intFromBuff(bytes, 2, 2) / 100d; + pump.maxDailyTotalUnits = intFromBuff(bytes, 4, 2) / 100; if (Config.logDanaMessageDetail) { - log.debug("Max bolus: " + DanaRPlugin.getDanaRPump().maxBolus); - log.debug("Max basal: " + DanaRPlugin.getDanaRPump().maxBasal); - log.debug("Total daily max units: " + DanaRPlugin.getDanaRPump().maxDailyTotalUnits); + log.debug("Max bolus: " + pump.maxBolus); + log.debug("Max basal: " + pump.maxBasal); + log.debug("Total daily max units: " + pump.maxDailyTotalUnits); } } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgSettingMeal.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgSettingMeal.java index 1c8e3c2fcb..b124641bf1 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgSettingMeal.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgSettingMeal.java @@ -4,7 +4,6 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import info.nightscout.androidaps.Config; -import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPlugin; import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPump; /** @@ -19,7 +18,7 @@ public class MsgSettingMeal extends MessageBase { } public void handleMessage(byte[] bytes) { - DanaRPump pump = DanaRPlugin.getDanaRPump(); + DanaRPump pump = DanaRPump.getInstance(); pump.basalStep = intFromBuff(bytes, 0, 1) / 100d; pump.bolusStep = intFromBuff(bytes, 1, 1) / 100d; boolean bolusEnabled = intFromBuff(bytes, 2, 1) == 1; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgSettingProfileRatios.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgSettingProfileRatios.java index 512c96990e..0b5150fc84 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgSettingProfileRatios.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgSettingProfileRatios.java @@ -4,7 +4,6 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import info.nightscout.androidaps.Config; -import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPlugin; import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPump; /** @@ -18,27 +17,28 @@ public class MsgSettingProfileRatios extends MessageBase { } public void handleMessage(byte[] bytes) { - if (DanaRPlugin.getDanaRPump().units == DanaRPump.UNITS_MGDL) { - DanaRPlugin.getDanaRPump().currentCIR = intFromBuff(bytes, 0, 2); - DanaRPlugin.getDanaRPump().currentCF = intFromBuff(bytes, 2, 2); - DanaRPlugin.getDanaRPump().currentAI = intFromBuff(bytes, 4, 2) / 100d; - DanaRPlugin.getDanaRPump().currentTarget = intFromBuff(bytes, 6, 2); - DanaRPlugin.getDanaRPump().currentAIDR = intFromBuff(bytes, 8, 1); + DanaRPump pump = DanaRPump.getInstance(); + if (pump.units == DanaRPump.UNITS_MGDL) { + pump.currentCIR = intFromBuff(bytes, 0, 2); + pump.currentCF = intFromBuff(bytes, 2, 2); + pump.currentAI = intFromBuff(bytes, 4, 2) / 100d; + pump.currentTarget = intFromBuff(bytes, 6, 2); + pump.currentAIDR = intFromBuff(bytes, 8, 1); } else { - DanaRPlugin.getDanaRPump().currentCIR = intFromBuff(bytes, 0, 2); - DanaRPlugin.getDanaRPump().currentCF = intFromBuff(bytes, 2, 2) / 100d; - DanaRPlugin.getDanaRPump().currentAI = intFromBuff(bytes, 4, 2) / 100d; - DanaRPlugin.getDanaRPump().currentTarget = intFromBuff(bytes, 6, 2) / 100d; - DanaRPlugin.getDanaRPump().currentAIDR = intFromBuff(bytes, 8, 1); + pump.currentCIR = intFromBuff(bytes, 0, 2); + pump.currentCF = intFromBuff(bytes, 2, 2) / 100d; + pump.currentAI = intFromBuff(bytes, 4, 2) / 100d; + pump.currentTarget = intFromBuff(bytes, 6, 2) / 100d; + pump.currentAIDR = intFromBuff(bytes, 8, 1); } if (Config.logDanaMessageDetail) { - log.debug("Pump units (saved): " + (DanaRPlugin.getDanaRPump().units == DanaRPump.UNITS_MGDL ? "MGDL" : "MMOL")); - log.debug("Current pump CIR: " + DanaRPlugin.getDanaRPump().currentCIR); - log.debug("Current pump CF: " + DanaRPlugin.getDanaRPump().currentCF); - log.debug("Current pump AI: " + DanaRPlugin.getDanaRPump().currentAI); - log.debug("Current pump target: " + DanaRPlugin.getDanaRPump().currentTarget); - log.debug("Current pump AIDR: " + DanaRPlugin.getDanaRPump().currentAIDR); + log.debug("Pump units (saved): " + (pump.units == DanaRPump.UNITS_MGDL ? "MGDL" : "MMOL")); + log.debug("Current pump CIR: " + pump.currentCIR); + log.debug("Current pump CF: " + pump.currentCF); + log.debug("Current pump AI: " + pump.currentAI); + log.debug("Current pump target: " + pump.currentTarget); + log.debug("Current pump AIDR: " + pump.currentAIDR); } } } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgSettingProfileRatiosAll.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgSettingProfileRatiosAll.java index aaadb2bd59..9dd5a0070d 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgSettingProfileRatiosAll.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgSettingProfileRatiosAll.java @@ -4,7 +4,6 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import info.nightscout.androidaps.Config; -import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPlugin; import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPump; /** @@ -18,38 +17,39 @@ public class MsgSettingProfileRatiosAll extends MessageBase { } public void handleMessage(byte[] bytes) { - if (DanaRPlugin.getDanaRPump().units == DanaRPump.UNITS_MGDL) { - DanaRPlugin.getDanaRPump().morningCIR = intFromBuff(bytes, 0, 2); - DanaRPlugin.getDanaRPump().morningCF = intFromBuff(bytes, 2, 2); - DanaRPlugin.getDanaRPump().afternoonCIR = intFromBuff(bytes, 4, 2); - DanaRPlugin.getDanaRPump().afternoonCF = intFromBuff(bytes, 6, 2); - DanaRPlugin.getDanaRPump().eveningCIR = intFromBuff(bytes, 8, 2); - DanaRPlugin.getDanaRPump().eveningCF = intFromBuff(bytes, 10, 2); - DanaRPlugin.getDanaRPump().nightCIR = intFromBuff(bytes, 12, 2); - DanaRPlugin.getDanaRPump().nightCF = intFromBuff(bytes, 14, 2); + DanaRPump pump = DanaRPump.getInstance(); + if (pump.units == DanaRPump.UNITS_MGDL) { + pump.morningCIR = intFromBuff(bytes, 0, 2); + pump.morningCF = intFromBuff(bytes, 2, 2); + pump.afternoonCIR = intFromBuff(bytes, 4, 2); + pump.afternoonCF = intFromBuff(bytes, 6, 2); + pump.eveningCIR = intFromBuff(bytes, 8, 2); + pump.eveningCF = intFromBuff(bytes, 10, 2); + pump.nightCIR = intFromBuff(bytes, 12, 2); + pump.nightCF = intFromBuff(bytes, 14, 2); } else { - DanaRPlugin.getDanaRPump().morningCIR = intFromBuff(bytes, 0, 2); - DanaRPlugin.getDanaRPump().morningCF = intFromBuff(bytes, 2, 2) / 100d; - DanaRPlugin.getDanaRPump().afternoonCIR = intFromBuff(bytes, 4, 2); - DanaRPlugin.getDanaRPump().afternoonCF = intFromBuff(bytes, 6, 2) / 100d; - DanaRPlugin.getDanaRPump().eveningCIR = intFromBuff(bytes, 8, 2); - DanaRPlugin.getDanaRPump().eveningCF = intFromBuff(bytes, 10, 2) / 100d; - DanaRPlugin.getDanaRPump().nightCIR = intFromBuff(bytes, 12, 2); - DanaRPlugin.getDanaRPump().nightCF = intFromBuff(bytes, 14, 2) / 100d; + pump.morningCIR = intFromBuff(bytes, 0, 2); + pump.morningCF = intFromBuff(bytes, 2, 2) / 100d; + pump.afternoonCIR = intFromBuff(bytes, 4, 2); + pump.afternoonCF = intFromBuff(bytes, 6, 2) / 100d; + pump.eveningCIR = intFromBuff(bytes, 8, 2); + pump.eveningCF = intFromBuff(bytes, 10, 2) / 100d; + pump.nightCIR = intFromBuff(bytes, 12, 2); + pump.nightCF = intFromBuff(bytes, 14, 2) / 100d; } if (Config.logDanaMessageDetail) { - log.debug("Pump units: " + (DanaRPlugin.getDanaRPump().units == DanaRPump.UNITS_MGDL ? "MGDL" : "MMOL")); - log.debug("Current pump morning CIR: " + DanaRPlugin.getDanaRPump().morningCIR); - log.debug("Current pump morning CF: " + DanaRPlugin.getDanaRPump().morningCF); - log.debug("Current pump afternoon CIR: " + DanaRPlugin.getDanaRPump().afternoonCIR); - log.debug("Current pump afternoon CF: " + DanaRPlugin.getDanaRPump().afternoonCF); - log.debug("Current pump evening CIR: " + DanaRPlugin.getDanaRPump().eveningCIR); - log.debug("Current pump evening CF: " + DanaRPlugin.getDanaRPump().eveningCF); - log.debug("Current pump night CIR: " + DanaRPlugin.getDanaRPump().nightCIR); - log.debug("Current pump night CF: " + DanaRPlugin.getDanaRPump().nightCF); + log.debug("Pump units: " + (pump.units == DanaRPump.UNITS_MGDL ? "MGDL" : "MMOL")); + log.debug("Current pump morning CIR: " + pump.morningCIR); + log.debug("Current pump morning CF: " + pump.morningCF); + log.debug("Current pump afternoon CIR: " + pump.afternoonCIR); + log.debug("Current pump afternoon CF: " + pump.afternoonCF); + log.debug("Current pump evening CIR: " + pump.eveningCIR); + log.debug("Current pump evening CF: " + pump.eveningCF); + log.debug("Current pump night CIR: " + pump.nightCIR); + log.debug("Current pump night CF: " + pump.nightCF); } - DanaRPlugin.getDanaRPump().createConvertedProfile(); + pump.createConvertedProfile(); } } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgSettingPumpTime.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgSettingPumpTime.java index 5344ae86b6..23f0e4560f 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgSettingPumpTime.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgSettingPumpTime.java @@ -6,7 +6,7 @@ import org.slf4j.LoggerFactory; import java.util.Date; import info.nightscout.androidaps.Config; -import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPlugin; +import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPump; public class MsgSettingPumpTime extends MessageBase { private static Logger log = LoggerFactory.getLogger(MsgSettingPumpTime.class); @@ -29,6 +29,6 @@ public class MsgSettingPumpTime extends MessageBase { if (Config.logDanaMessageDetail) log.debug("Pump time: " + time); - DanaRPlugin.getDanaRPump().pumpTime = time; + DanaRPump.getInstance().pumpTime = time; } } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgSettingShippingInfo.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgSettingShippingInfo.java index 797a82f80a..9670d92a88 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgSettingShippingInfo.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgSettingShippingInfo.java @@ -4,7 +4,6 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import info.nightscout.androidaps.Config; -import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPlugin; import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPump; /** @@ -18,7 +17,7 @@ public class MsgSettingShippingInfo extends MessageBase { } public void handleMessage(byte[] bytes) { - DanaRPump pump = DanaRPlugin.getDanaRPump(); + DanaRPump pump = DanaRPump.getInstance(); pump.serialNumber = stringFromBuff(bytes, 0, 10); pump.shippingDate = dateFromBuff(bytes, 10); pump.shippingCountry = asciiStringFromBuff(bytes, 13, 3); diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgStatus.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgStatus.java index 9e64f86363..fb75bfef0e 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgStatus.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgStatus.java @@ -4,7 +4,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import info.nightscout.androidaps.Config; -import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPlugin; +import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPump; public class MsgStatus extends MessageBase { private static Logger log = LoggerFactory.getLogger(MsgStatus.class); @@ -14,25 +14,26 @@ public class MsgStatus extends MessageBase { } public void handleMessage(byte[] bytes) { - DanaRPlugin.getDanaRPump().dailyTotalUnits = intFromBuff(bytes, 0, 3) / 750d; - DanaRPlugin.getDanaRPump().isExtendedInProgress = intFromBuff(bytes, 3, 1) == 1; - DanaRPlugin.getDanaRPump().extendedBolusMinutes = intFromBuff(bytes, 4, 2); - DanaRPlugin.getDanaRPump().extendedBolusAmount = intFromBuff(bytes, 6, 2) / 100d; + DanaRPump pump = DanaRPump.getInstance(); + pump.dailyTotalUnits = intFromBuff(bytes, 0, 3) / 750d; + pump.isExtendedInProgress = intFromBuff(bytes, 3, 1) == 1; + pump.extendedBolusMinutes = intFromBuff(bytes, 4, 2); + pump.extendedBolusAmount = intFromBuff(bytes, 6, 2) / 100d; Double lastBolusAmount = intFromBuff(bytes, 13, 2) / 100d; if (lastBolusAmount != 0d) { - DanaRPlugin.getDanaRPump().lastBolusTime = dateTimeFromBuff(bytes, 8); - DanaRPlugin.getDanaRPump().lastBolusAmount = lastBolusAmount; + pump.lastBolusTime = dateTimeFromBuff(bytes, 8); + pump.lastBolusAmount = lastBolusAmount; } - DanaRPlugin.getDanaRPump().iob = intFromBuff(bytes, 15, 2) / 100d; + pump.iob = intFromBuff(bytes, 15, 2) / 100d; if (Config.logDanaMessageDetail) { - log.debug("Daily total: " + DanaRPlugin.getDanaRPump().dailyTotalUnits); - log.debug("Is extended bolus running: " + DanaRPlugin.getDanaRPump().isExtendedInProgress); - log.debug("Extended bolus min: " + DanaRPlugin.getDanaRPump().extendedBolusMinutes); - log.debug("Extended bolus amount: " + DanaRPlugin.getDanaRPump().extendedBolusAmount); - log.debug("Last bolus time: " + DanaRPlugin.getDanaRPump().lastBolusTime); - log.debug("Last bolus amount: " + DanaRPlugin.getDanaRPump().lastBolusAmount); - log.debug("IOB: " + DanaRPlugin.getDanaRPump().iob); + log.debug("Daily total: " + pump.dailyTotalUnits); + log.debug("Is extended bolus running: " + pump.isExtendedInProgress); + log.debug("Extended bolus min: " + pump.extendedBolusMinutes); + log.debug("Extended bolus amount: " + pump.extendedBolusAmount); + log.debug("Last bolus time: " + pump.lastBolusTime); + log.debug("Last bolus amount: " + pump.lastBolusAmount); + log.debug("IOB: " + pump.iob); } } } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgStatusBasic.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgStatusBasic.java index c50fac371a..ba8374f383 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgStatusBasic.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgStatusBasic.java @@ -4,7 +4,6 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import info.nightscout.androidaps.Config; -import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPlugin; import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPump; @@ -16,7 +15,7 @@ public class MsgStatusBasic extends MessageBase { } public void handleMessage(byte[] bytes) { - DanaRPump pump = DanaRPlugin.getDanaRPump(); + DanaRPump pump = DanaRPump.getInstance(); pump.pumpSuspended = intFromBuff(bytes, 0, 1) == 1; pump.calculatorEnabled = intFromBuff(bytes, 1, 1) == 1; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgStatusBolusExtended.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgStatusBolusExtended.java index de0749c292..691811efc3 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgStatusBolusExtended.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgStatusBolusExtended.java @@ -35,13 +35,14 @@ public class MsgStatusBolusExtended extends MessageBase { Date extendedBolusStart = isExtendedInProgress ? getDateFromSecAgo(extendedBolusSoFarInSecs) : new Date(0); int extendedBolusRemainingMinutes = extendedBolusMinutes - extendedBolusSoFarInMinutes; - DanaRPlugin.getDanaRPump().isExtendedInProgress = isExtendedInProgress; - DanaRPlugin.getDanaRPump().extendedBolusMinutes = extendedBolusMinutes; - DanaRPlugin.getDanaRPump().extendedBolusAmount = extendedBolusAmount; - DanaRPlugin.getDanaRPump().extendedBolusSoFarInMinutes = extendedBolusSoFarInMinutes; - DanaRPlugin.getDanaRPump().extendedBolusAbsoluteRate = extendedBolusAbsoluteRate; - DanaRPlugin.getDanaRPump().extendedBolusStart = extendedBolusStart; - DanaRPlugin.getDanaRPump().extendedBolusRemainingMinutes = extendedBolusRemainingMinutes; + DanaRPump pump = DanaRPump.getInstance(); + pump.isExtendedInProgress = isExtendedInProgress; + pump.extendedBolusMinutes = extendedBolusMinutes; + pump.extendedBolusAmount = extendedBolusAmount; + pump.extendedBolusSoFarInMinutes = extendedBolusSoFarInMinutes; + pump.extendedBolusAbsoluteRate = extendedBolusAbsoluteRate; + pump.extendedBolusStart = extendedBolusStart; + pump.extendedBolusRemainingMinutes = extendedBolusRemainingMinutes; updateExtendedBolusInDB(); @@ -62,25 +63,25 @@ public class MsgStatusBolusExtended extends MessageBase { } public static void updateExtendedBolusInDB() { - DanaRPlugin DanaRPlugin = (DanaRPlugin) MainApp.getSpecificPlugin(DanaRPlugin.class); - DanaRPump danaRPump = DanaRPlugin.getDanaRPump(); + DanaRPlugin danaRPlugin = (DanaRPlugin) MainApp.getSpecificPlugin(DanaRPlugin.class); + DanaRPump pump = DanaRPump.getInstance(); Date now = new Date(); try { - if (DanaRPlugin.isExtendedBoluslInProgress()) { - TempBasal extendedBolus = DanaRPlugin.getExtendedBolus(); - if (danaRPump.isExtendedInProgress) { - if (extendedBolus.absolute != danaRPump.extendedBolusAbsoluteRate) { + if (danaRPlugin.isExtendedBoluslInProgress()) { + TempBasal extendedBolus = danaRPlugin.getExtendedBolus(); + if (pump.isExtendedInProgress) { + if (extendedBolus.absolute != pump.extendedBolusAbsoluteRate) { // Close current extended extendedBolus.timeEnd = now; MainApp.getDbHelper().getDaoTempBasals().update(extendedBolus); // Create new TempBasal newExtended = new TempBasal(); newExtended.timeStart = now; - newExtended.absolute = danaRPump.extendedBolusAbsoluteRate; + newExtended.absolute = pump.extendedBolusAbsoluteRate; newExtended.isAbsolute = true; - newExtended.duration = danaRPump.extendedBolusMinutes; + newExtended.duration = pump.extendedBolusMinutes; newExtended.isExtended = true; MainApp.getDbHelper().getDaoTempBasals().create(newExtended); MainApp.bus().post(new EventTempBasalChange()); @@ -92,13 +93,13 @@ public class MsgStatusBolusExtended extends MessageBase { MainApp.bus().post(new EventTempBasalChange()); } } else { - if (danaRPump.isExtendedInProgress) { + if (pump.isExtendedInProgress) { // Create new TempBasal newExtended = new TempBasal(); newExtended.timeStart = now; - newExtended.absolute = danaRPump.extendedBolusAbsoluteRate; + newExtended.absolute = pump.extendedBolusAbsoluteRate; newExtended.isAbsolute = true; - newExtended.duration = danaRPump.extendedBolusMinutes; + newExtended.duration = pump.extendedBolusMinutes; newExtended.isExtended = true; MainApp.getDbHelper().getDaoTempBasals().create(newExtended); MainApp.bus().post(new EventTempBasalChange()); diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgStatusProfile.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgStatusProfile.java index 7a703d468a..70b67c3b77 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgStatusProfile.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgStatusProfile.java @@ -4,7 +4,6 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import info.nightscout.androidaps.Config; -import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPlugin; import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPump; /** @@ -18,25 +17,26 @@ public class MsgStatusProfile extends MessageBase { } public void handleMessage(byte[] bytes) { - if (DanaRPlugin.getDanaRPump().units == DanaRPump.UNITS_MGDL) { - DanaRPlugin.getDanaRPump().currentCIR = intFromBuff(bytes, 0, 2); - DanaRPlugin.getDanaRPump().currentCF = intFromBuff(bytes, 2, 2); - DanaRPlugin.getDanaRPump().currentAI = intFromBuff(bytes, 4, 2) / 100d; - DanaRPlugin.getDanaRPump().currentTarget = intFromBuff(bytes, 6, 2); + DanaRPump pump = DanaRPump.getInstance(); + if (pump.units == DanaRPump.UNITS_MGDL) { + pump.currentCIR = intFromBuff(bytes, 0, 2); + pump.currentCF = intFromBuff(bytes, 2, 2); + pump.currentAI = intFromBuff(bytes, 4, 2) / 100d; + pump.currentTarget = intFromBuff(bytes, 6, 2); } else { - DanaRPlugin.getDanaRPump().currentCIR = intFromBuff(bytes, 0, 2); - DanaRPlugin.getDanaRPump().currentCF = intFromBuff(bytes, 2, 2) / 100d; - DanaRPlugin.getDanaRPump().currentAI = intFromBuff(bytes, 4, 2) / 100d; - DanaRPlugin.getDanaRPump().currentTarget = intFromBuff(bytes, 6, 2) / 100d; + pump.currentCIR = intFromBuff(bytes, 0, 2); + pump.currentCF = intFromBuff(bytes, 2, 2) / 100d; + pump.currentAI = intFromBuff(bytes, 4, 2) / 100d; + pump.currentTarget = intFromBuff(bytes, 6, 2) / 100d; } if (Config.logDanaMessageDetail) { - log.debug("Pump units (saved): " + (DanaRPlugin.getDanaRPump().units == DanaRPump.UNITS_MGDL ? "MGDL" : "MMOL")); - log.debug("Current pump CIR: " + DanaRPlugin.getDanaRPump().currentCIR); - log.debug("Current pump CF: " + DanaRPlugin.getDanaRPump().currentCF); - log.debug("Current pump AI: " + DanaRPlugin.getDanaRPump().currentAI); - log.debug("Current pump target: " + DanaRPlugin.getDanaRPump().currentTarget); - log.debug("Current pump AIDR: " + DanaRPlugin.getDanaRPump().currentAIDR); + log.debug("Pump units (saved): " + (pump.units == DanaRPump.UNITS_MGDL ? "MGDL" : "MMOL")); + log.debug("Current pump CIR: " + pump.currentCIR); + log.debug("Current pump CF: " + pump.currentCF); + log.debug("Current pump AI: " + pump.currentAI); + log.debug("Current pump target: " + pump.currentTarget); + log.debug("Current pump AIDR: " + pump.currentAIDR); } } } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgStatusTempBasal.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgStatusTempBasal.java index 1a2e21c004..1db0ea29ee 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgStatusTempBasal.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgStatusTempBasal.java @@ -30,11 +30,12 @@ public class MsgStatusTempBasal extends MessageBase { int tempBasalRemainingMin = (tempBasalTotalSec - tempBasalRunningSeconds) / 60; Date tempBasalStart = isTempBasalInProgress ? getDateFromTempBasalSecAgo(tempBasalRunningSeconds) : new Date(0); - DanaRPlugin.getDanaRPump().isTempBasalInProgress = isTempBasalInProgress; - DanaRPlugin.getDanaRPump().tempBasalPercent = tempBasalPercent; - DanaRPlugin.getDanaRPump().tempBasalRemainingMin = tempBasalRemainingMin; - DanaRPlugin.getDanaRPump().tempBasalTotalSec = tempBasalTotalSec; - DanaRPlugin.getDanaRPump().tempBasalStart = tempBasalStart; + DanaRPump pump = DanaRPump.getInstance(); + pump.isTempBasalInProgress = isTempBasalInProgress; + pump.tempBasalPercent = tempBasalPercent; + pump.tempBasalRemainingMin = tempBasalRemainingMin; + pump.tempBasalTotalSec = tempBasalTotalSec; + pump.tempBasalStart = tempBasalStart; updateTempBasalInDB(); @@ -54,7 +55,7 @@ public class MsgStatusTempBasal extends MessageBase { public static void updateTempBasalInDB() { DanaRPlugin DanaRPlugin = (DanaRPlugin) MainApp.getSpecificPlugin(DanaRPlugin.class); - DanaRPump danaRPump = DanaRPlugin.getDanaRPump(); + DanaRPump danaRPump = DanaRPump.getInstance(); Date now = new Date(); try { diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/Services/ExecutionService.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/services/DanaRExecutionService.java similarity index 98% rename from app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/Services/ExecutionService.java rename to app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/services/DanaRExecutionService.java index 54aae17687..2fd71f462e 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/Services/ExecutionService.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/services/DanaRExecutionService.java @@ -1,4 +1,4 @@ -package info.nightscout.androidaps.plugins.PumpDanaR.Services; +package info.nightscout.androidaps.plugins.PumpDanaR.services; import android.app.Service; import android.bluetooth.BluetoothAdapter; @@ -83,8 +83,8 @@ import info.nightscout.androidaps.plugins.NSClientInternal.data.NSProfile; import info.nightscout.utils.SP; import info.nightscout.utils.ToastUtils; -public class ExecutionService extends Service { - private static Logger log = LoggerFactory.getLogger(ExecutionService.class); +public class DanaRExecutionService extends Service { + private static Logger log = LoggerFactory.getLogger(DanaRExecutionService.class); private String devName; @@ -120,18 +120,18 @@ public class ExecutionService extends Service { } }; - public ExecutionService() { + public DanaRExecutionService() { registerBus(); MainApp.instance().getApplicationContext().registerReceiver(receiver, new IntentFilter(BluetoothDevice.ACTION_ACL_DISCONNECTED)); danaRPump = DanaRPlugin.getDanaRPump(); PowerManager powerManager = (PowerManager) MainApp.instance().getApplicationContext().getSystemService(Context.POWER_SERVICE); - mWakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "ExecutionService"); + mWakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "DanaRExecutionService"); } public class LocalBinder extends Binder { - public ExecutionService getServiceInstance() { - return ExecutionService.this; + public DanaRExecutionService getServiceInstance() { + return DanaRExecutionService.this; } } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRKorean/DanaRKoreanPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRKorean/DanaRKoreanPlugin.java index 726e1b95ab..84dfa7fd71 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRKorean/DanaRKoreanPlugin.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRKorean/DanaRKoreanPlugin.java @@ -36,7 +36,7 @@ import info.nightscout.androidaps.interfaces.ProfileInterface; import info.nightscout.androidaps.interfaces.PumpDescription; import info.nightscout.androidaps.interfaces.PumpInterface; import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin; -import info.nightscout.androidaps.plugins.PumpDanaRKorean.Services.ExecutionService; +import info.nightscout.androidaps.plugins.PumpDanaRKorean.services.DanaRKoreanExecutionService; import info.nightscout.androidaps.plugins.ProfileNS.NSProfilePlugin; import info.nightscout.androidaps.plugins.Overview.Notification; import info.nightscout.androidaps.plugins.Overview.events.EventDismissNotification; @@ -61,7 +61,7 @@ public class DanaRKoreanPlugin implements PluginBase, PumpInterface, Constraints static boolean fragmentProfileEnabled = false; static boolean fragmentPumpVisible = true; - public static ExecutionService sExecutionService; + public static DanaRKoreanExecutionService sExecutionService; private static DanaRKoreanPump sDanaRKoreanPump = new DanaRKoreanPump(); @@ -80,7 +80,7 @@ public class DanaRKoreanPlugin implements PluginBase, PumpInterface, Constraints useExtendedBoluses = sharedPreferences.getBoolean("danar_useextended", false); Context context = MainApp.instance().getApplicationContext(); - Intent intent = new Intent(context, ExecutionService.class); + Intent intent = new Intent(context, DanaRKoreanExecutionService.class); context.bindService(intent, mConnection, Context.BIND_AUTO_CREATE); MainApp.bus().register(this); @@ -120,7 +120,7 @@ public class DanaRKoreanPlugin implements PluginBase, PumpInterface, Constraints public void onServiceConnected(ComponentName name, IBinder service) { log.debug("Service is connected"); - ExecutionService.LocalBinder mLocalBinder = (ExecutionService.LocalBinder) service; + DanaRKoreanExecutionService.LocalBinder mLocalBinder = (DanaRKoreanExecutionService.LocalBinder) service; sExecutionService = mLocalBinder.getServiceInstance(); } }; @@ -567,7 +567,7 @@ public class DanaRKoreanPlugin implements PluginBase, PumpInterface, Constraints log.error("setTempBasalPercent: Invalid input"); return result; } - if (percent > 200) percent = 200; + if (percent > getPumpDescription().maxHighTempPercent) percent = getPumpDescription().maxHighTempPercent; if (getDanaRPump().isTempBasalInProgress && getDanaRPump().tempBasalPercent == percent) { result.enacted = false; result.success = true; @@ -812,7 +812,7 @@ public class DanaRKoreanPlugin implements PluginBase, PumpInterface, Constraints public Integer applyBasalConstraints(Integer percentRate) { Integer origPercentRate = percentRate; if (percentRate < 0) percentRate = 0; - if (percentRate > 200) percentRate = 200; + if (percentRate > getPumpDescription().maxHighTempPercent) percentRate = getPumpDescription().maxHighTempPercent; if (!Objects.equals(percentRate, origPercentRate) && Config.logConstraintsChanges && !Objects.equals(origPercentRate, Constants.basalPercentOnlyForCheckLimit)) log.debug("Limiting percent rate " + origPercentRate + "% to " + percentRate + "%"); return percentRate; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRKorean/History/DanaRHistoryActivity.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRKorean/History/DanaRHistoryActivity.java index adbbf09e75..06eacc31dc 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRKorean/History/DanaRHistoryActivity.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRKorean/History/DanaRHistoryActivity.java @@ -43,7 +43,7 @@ import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin; import info.nightscout.androidaps.plugins.PumpDanaR.History.DanaRNSHistorySync; import info.nightscout.androidaps.plugins.PumpDanaR.comm.RecordTypes; import info.nightscout.androidaps.plugins.PumpDanaR.events.EventDanaRSyncStatus; -import info.nightscout.androidaps.plugins.PumpDanaRKorean.Services.ExecutionService; +import info.nightscout.androidaps.plugins.PumpDanaRKorean.services.DanaRKoreanExecutionService; import info.nightscout.androidaps.plugins.NSClientInternal.data.NSProfile; import info.nightscout.utils.DateUtil; import info.nightscout.utils.DecimalFormatter; @@ -53,7 +53,7 @@ public class DanaRHistoryActivity extends Activity { private static Logger log = LoggerFactory.getLogger(DanaRHistoryActivity.class); private boolean mBounded; - private static ExecutionService mExecutionService; + private static DanaRKoreanExecutionService mExecutionService; private Handler mHandler; private static HandlerThread mHandlerThread; @@ -96,7 +96,7 @@ public class DanaRHistoryActivity extends Activity { @Override public void onStart() { super.onStart(); - Intent intent = new Intent(this, ExecutionService.class); + Intent intent = new Intent(this, DanaRKoreanExecutionService.class); bindService(intent, mConnection, Context.BIND_AUTO_CREATE); } @@ -132,7 +132,7 @@ public class DanaRHistoryActivity extends Activity { public void onServiceConnected(ComponentName name, IBinder service) { log.debug("Service is connected"); mBounded = true; - ExecutionService.LocalBinder mLocalBinder = (ExecutionService.LocalBinder) service; + DanaRKoreanExecutionService.LocalBinder mLocalBinder = (DanaRKoreanExecutionService.LocalBinder) service; mExecutionService = mLocalBinder.getServiceInstance(); } }; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRKorean/History/DanaRStatsActivity.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRKorean/History/DanaRStatsActivity.java index dc0e513913..2c34f52da0 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRKorean/History/DanaRStatsActivity.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRKorean/History/DanaRStatsActivity.java @@ -54,7 +54,7 @@ import info.nightscout.androidaps.plugins.ProfileCircadianPercentage.CircadianPe import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin; import info.nightscout.androidaps.plugins.PumpDanaR.comm.RecordTypes; import info.nightscout.androidaps.plugins.PumpDanaR.events.EventDanaRSyncStatus; -import info.nightscout.androidaps.plugins.PumpDanaRKorean.Services.ExecutionService; +import info.nightscout.androidaps.plugins.PumpDanaRKorean.services.DanaRKoreanExecutionService; import info.nightscout.utils.DecimalFormatter; import info.nightscout.utils.SafeParse; import info.nightscout.utils.ToastUtils; @@ -63,7 +63,7 @@ public class DanaRStatsActivity extends Activity { private static Logger log = LoggerFactory.getLogger(DanaRStatsActivity.class); private boolean mBounded; - private static ExecutionService mExecutionService; + private static DanaRKoreanExecutionService mExecutionService; private Handler mHandler; private static HandlerThread mHandlerThread; @@ -89,7 +89,7 @@ public class DanaRStatsActivity extends Activity { @Override public void onStart() { super.onStart(); - Intent intent = new Intent(this, ExecutionService.class); + Intent intent = new Intent(this, DanaRKoreanExecutionService.class); bindService(intent, mConnection, Context.BIND_AUTO_CREATE); } @@ -140,7 +140,7 @@ public class DanaRStatsActivity extends Activity { public void onServiceConnected(ComponentName name, IBinder service) { log.debug("Service is connected"); mBounded = true; - ExecutionService.LocalBinder mLocalBinder = (ExecutionService.LocalBinder) service; + DanaRKoreanExecutionService.LocalBinder mLocalBinder = (DanaRKoreanExecutionService.LocalBinder) service; mExecutionService = mLocalBinder.getServiceInstance(); } }; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRKorean/Services/ExecutionService.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRKorean/services/DanaRKoreanExecutionService.java similarity index 98% rename from app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRKorean/Services/ExecutionService.java rename to app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRKorean/services/DanaRKoreanExecutionService.java index 83cae228f0..b858cae1a8 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRKorean/Services/ExecutionService.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRKorean/services/DanaRKoreanExecutionService.java @@ -1,4 +1,4 @@ -package info.nightscout.androidaps.plugins.PumpDanaRKorean.Services; +package info.nightscout.androidaps.plugins.PumpDanaRKorean.services; import android.app.Service; import android.bluetooth.BluetoothAdapter; @@ -79,8 +79,8 @@ import info.nightscout.androidaps.plugins.Overview.events.EventNewNotification; import info.nightscout.utils.SP; import info.nightscout.utils.ToastUtils; -public class ExecutionService extends Service { - private static Logger log = LoggerFactory.getLogger(ExecutionService.class); +public class DanaRKoreanExecutionService extends Service { + private static Logger log = LoggerFactory.getLogger(DanaRKoreanExecutionService.class); private String devName; @@ -116,18 +116,18 @@ public class ExecutionService extends Service { } }; - public ExecutionService() { + public DanaRKoreanExecutionService() { registerBus(); MainApp.instance().getApplicationContext().registerReceiver(receiver, new IntentFilter(BluetoothDevice.ACTION_ACL_DISCONNECTED)); danaRKoreanPump = DanaRKoreanPlugin.getDanaRPump(); PowerManager powerManager = (PowerManager) MainApp.instance().getApplicationContext().getSystemService(Context.POWER_SERVICE); - mWakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "ExecutionService"); + mWakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "DanaRKoreanExecutionService"); } public class LocalBinder extends Binder { - public ExecutionService getServiceInstance() { - return ExecutionService.this; + public DanaRKoreanExecutionService getServiceInstance() { + return DanaRKoreanExecutionService.this; } } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRv2/DanaRv2Fragment.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRv2/DanaRv2Fragment.java new file mode 100644 index 0000000000..ddf7371f4b --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRv2/DanaRv2Fragment.java @@ -0,0 +1,248 @@ +package info.nightscout.androidaps.plugins.PumpDanaRv2; + + +import android.annotation.SuppressLint; +import android.app.Activity; +import android.content.Intent; +import android.os.Bundle; +import android.os.Handler; +import android.os.HandlerThread; +import android.support.v4.app.Fragment; +import android.support.v4.app.FragmentManager; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.Button; +import android.widget.TextView; + +import com.squareup.otto.Subscribe; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.Date; + +import info.nightscout.androidaps.MainApp; +import info.nightscout.androidaps.R; +import info.nightscout.androidaps.events.EventPumpStatusChanged; +import info.nightscout.androidaps.events.EventTempBasalChange; +import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPump; +import info.nightscout.androidaps.plugins.PumpDanaR.Dialogs.ProfileViewDialog; +import info.nightscout.androidaps.plugins.PumpDanaR.events.EventDanaRNewStatus; +import info.nightscout.androidaps.plugins.PumpDanaRv2.History.DanaRHistoryActivity; +import info.nightscout.androidaps.plugins.PumpDanaRv2.History.DanaRStatsActivity; +import info.nightscout.utils.DateUtil; +import info.nightscout.utils.DecimalFormatter; +import info.nightscout.utils.SetWarnColor; + +public class DanaRv2Fragment extends Fragment { + private static Logger log = LoggerFactory.getLogger(DanaRv2Fragment.class); + + private static DanaRv2Plugin danaRPlugin; + + public static DanaRv2Plugin getPlugin() { + if (danaRPlugin == null) { + danaRPlugin = new DanaRv2Plugin(); + } + return danaRPlugin; + } + + private static Handler sHandler; + private static HandlerThread sHandlerThread; + + private Handler loopHandler = new Handler(); + private Runnable refreshLoop = null; + + TextView lastConnectionView; + TextView btConnectionView; + TextView lastBolusView; + TextView dailyUnitsView; + TextView basaBasalRateView; + TextView tempBasalView; + TextView extendedBolusView; + TextView batteryView; + TextView reservoirView; + TextView iobView; + TextView firmwareView; + Button viewProfileButton; + Button historyButton; + Button statsButton; + + + public DanaRv2Fragment() { + if (sHandlerThread == null) { + sHandlerThread = new HandlerThread(DanaRv2Fragment.class.getSimpleName()); + sHandlerThread.start(); + sHandler = new Handler(sHandlerThread.getLooper()); + } + } + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + if (refreshLoop == null) { + refreshLoop = new Runnable() { + @Override + public void run() { + updateGUI(); + loopHandler.postDelayed(refreshLoop, 60 * 1000L); + } + }; + loopHandler.postDelayed(refreshLoop, 60 * 1000L); + } + } + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, + Bundle savedInstanceState) { + View view = inflater.inflate(R.layout.danar_fragment, container, false); + btConnectionView = (TextView) view.findViewById(R.id.danar_btconnection); + lastConnectionView = (TextView) view.findViewById(R.id.danar_lastconnection); + lastBolusView = (TextView) view.findViewById(R.id.danar_lastbolus); + dailyUnitsView = (TextView) view.findViewById(R.id.danar_dailyunits); + basaBasalRateView = (TextView) view.findViewById(R.id.danar_basabasalrate); + tempBasalView = (TextView) view.findViewById(R.id.danar_tempbasal); + extendedBolusView = (TextView) view.findViewById(R.id.danar_extendedbolus); + batteryView = (TextView) view.findViewById(R.id.danar_battery); + reservoirView = (TextView) view.findViewById(R.id.danar_reservoir); + iobView = (TextView) view.findViewById(R.id.danar_iob); + firmwareView = (TextView) view.findViewById(R.id.danar_firmware); + viewProfileButton = (Button) view.findViewById(R.id.danar_viewprofile); + historyButton = (Button) view.findViewById(R.id.danar_history); + statsButton = (Button) view.findViewById(R.id.danar_stats); + + + viewProfileButton.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + FragmentManager manager = getFragmentManager(); + ProfileViewDialog profileViewDialog = new ProfileViewDialog(); + profileViewDialog.show(manager, "ProfileViewDialog"); + } + }); + + historyButton.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + startActivity(new Intent(getContext(), DanaRHistoryActivity.class)); + } + }); + + statsButton.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + startActivity(new Intent(getContext(), DanaRStatsActivity.class)); + } + }); + + btConnectionView.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + sHandler.post(new Runnable() { + @Override + public void run() { + DanaRv2Plugin.sExecutionService.connect("Connect request from GUI"); + } + } + ); + } + }); + + updateGUI(); + return view; + } + + @Override + public void onPause() { + super.onPause(); + MainApp.bus().unregister(this); + } + + @Override + public void onResume() { + super.onResume(); + MainApp.bus().register(this); + } + + @Subscribe + public void onStatusEvent(final EventPumpStatusChanged c) { + Activity activity = getActivity(); + if (activity != null) { + activity.runOnUiThread( + new Runnable() { + @Override + public void run() { + if (c.sStatus == EventPumpStatusChanged.CONNECTING) + btConnectionView.setText("{fa-bluetooth-b spin} " + c.sSecondsElapsed + "s"); + else if (c.sStatus == EventPumpStatusChanged.CONNECTED) + btConnectionView.setText("{fa-bluetooth}"); + else if (c.sStatus == EventPumpStatusChanged.DISCONNECTED) + btConnectionView.setText("{fa-bluetooth-b}"); + } + } + ); + } + } + + @Subscribe + public void onStatusEvent(final EventDanaRNewStatus s) { + updateGUI(); + } + + @Subscribe + public void onStatusEvent(final EventTempBasalChange s) { + updateGUI(); + } + + // GUI functions + private void updateGUI() { + Activity activity = getActivity(); + if (activity != null && basaBasalRateView != null) + activity.runOnUiThread(new Runnable() { + @SuppressLint("SetTextI18n") + @Override + public void run() { + DanaRPump pump = DanaRv2Plugin.getDanaRPump(); + if (pump.lastConnection.getTime() != 0) { + Long agoMsec = new Date().getTime() - pump.lastConnection.getTime(); + int agoMin = (int) (agoMsec / 60d / 1000d); + lastConnectionView.setText(DateUtil.timeString(pump.lastConnection) + " (" + String.format(MainApp.sResources.getString(R.string.minago), agoMin) + ")"); + SetWarnColor.setColor(lastConnectionView, agoMin, 16d, 31d); + } + if (pump.lastBolusTime.getTime() != 0) { + Long agoMsec = new Date().getTime() - pump.lastBolusTime.getTime(); + double agoHours = agoMsec / 60d / 60d / 1000d; + if (agoHours < 6) // max 6h back + lastBolusView.setText(DateUtil.timeString(pump.lastBolusTime) + " (" + DecimalFormatter.to1Decimal(agoHours) + " " + MainApp.sResources.getString(R.string.hoursago) + ") " + DecimalFormatter.to2Decimal(getPlugin().getDanaRPump().lastBolusAmount) + " U"); + else lastBolusView.setText(""); + } + + dailyUnitsView.setText(DecimalFormatter.to0Decimal(pump.dailyTotalUnits) + " / " + pump.maxDailyTotalUnits + " U"); + SetWarnColor.setColor(dailyUnitsView, pump.dailyTotalUnits, pump.maxDailyTotalUnits * 0.75d, pump.maxDailyTotalUnits * 0.9d); + basaBasalRateView.setText("( " + (pump.activeProfile + 1) + " ) " + DecimalFormatter.to2Decimal(getPlugin().getBaseBasalRate()) + " U/h"); + if (getPlugin().isTempBasalInProgress()) { + tempBasalView.setText(getPlugin().getTempBasal().toString()); + } else { + tempBasalView.setText(""); + } + if (getPlugin().isExtendedBoluslInProgress()) { + extendedBolusView.setText(getPlugin().getExtendedBolus().toString()); + } else { + extendedBolusView.setText(""); + } + reservoirView.setText(DecimalFormatter.to0Decimal(pump.reservoirRemainingUnits) + " / 300 U"); + SetWarnColor.setColorInverse(reservoirView, pump.reservoirRemainingUnits, 50d, 20d); + batteryView.setText("{fa-battery-" + (pump.batteryRemaining / 25) + "}"); + SetWarnColor.setColorInverse(batteryView, pump.batteryRemaining, 51d, 26d); + iobView.setText(pump.iob + " U"); + if (pump.isNewPump) { + firmwareView.setText(String.format(MainApp.sResources.getString(R.string.danar_model), pump.model, pump.protocol, pump.productCode)); + } else { + firmwareView.setText("OLD"); + } + } + }); + + } + +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRv2/DanaRv2Plugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRv2/DanaRv2Plugin.java new file mode 100644 index 0000000000..2f54681f28 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRv2/DanaRv2Plugin.java @@ -0,0 +1,753 @@ +package info.nightscout.androidaps.plugins.PumpDanaRv2; + +import android.content.ComponentName; +import android.content.Context; +import android.content.Intent; +import android.content.ServiceConnection; +import android.content.SharedPreferences; +import android.os.IBinder; +import android.preference.PreferenceManager; +import android.support.annotation.Nullable; + +import com.squareup.otto.Subscribe; + +import org.json.JSONException; +import org.json.JSONObject; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.Date; +import java.util.Objects; + +import info.nightscout.androidaps.BuildConfig; +import info.nightscout.androidaps.Config; +import info.nightscout.androidaps.Constants; +import info.nightscout.androidaps.MainApp; +import info.nightscout.androidaps.R; +import info.nightscout.androidaps.data.PumpEnactResult; +import info.nightscout.androidaps.db.TempBasal; +import info.nightscout.androidaps.db.Treatment; +import info.nightscout.androidaps.events.EventAppExit; +import info.nightscout.androidaps.interfaces.ConstraintsInterface; +import info.nightscout.androidaps.interfaces.InsulinInterface; +import info.nightscout.androidaps.interfaces.PluginBase; +import info.nightscout.androidaps.interfaces.ProfileInterface; +import info.nightscout.androidaps.interfaces.PumpDescription; +import info.nightscout.androidaps.interfaces.PumpInterface; +import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin; +import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPump; +import info.nightscout.androidaps.plugins.NSClientInternal.data.NSProfile; +import info.nightscout.androidaps.plugins.ProfileNS.NSProfilePlugin; +import info.nightscout.androidaps.plugins.Overview.Notification; +import info.nightscout.androidaps.plugins.Overview.events.EventDismissNotification; +import info.nightscout.androidaps.plugins.Overview.events.EventNewNotification; +import info.nightscout.androidaps.plugins.PumpDanaRv2.services.DanaRv2ExecutionService; +import info.nightscout.utils.DateUtil; +import info.nightscout.utils.DecimalFormatter; +import info.nightscout.utils.Round; + +/** + * Created by mike on 05.08.2016. + */ +public class DanaRv2Plugin implements PluginBase, PumpInterface, ConstraintsInterface, ProfileInterface { + private static Logger log = LoggerFactory.getLogger(DanaRv2Plugin.class); + + @Override + public String getFragmentClass() { + return DanaRv2Fragment.class.getName(); + } + + static boolean fragmentPumpEnabled = false; + static boolean fragmentProfileEnabled = false; + static boolean fragmentPumpVisible = false; + + public static DanaRv2ExecutionService sExecutionService; + + + private static DanaRPump sDanaRPump = DanaRPump.getInstance(); + + public static PumpDescription pumpDescription = new PumpDescription(); + + public static DanaRPump getDanaRPump() { + return sDanaRPump; + } + + public DanaRv2Plugin() { + SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(MainApp.instance().getApplicationContext()); + + Context context = MainApp.instance().getApplicationContext(); + Intent intent = new Intent(context, DanaRv2ExecutionService.class); + context.bindService(intent, mConnection, Context.BIND_AUTO_CREATE); + MainApp.bus().register(this); + + pumpDescription.isBolusCapable = true; // TODO: use description in setTempBasalAbsolute + pumpDescription.bolusStep = 0.05d; + + pumpDescription.isExtendedBolusCapable = true; + pumpDescription.extendedBolusStep = 0.05d; + + pumpDescription.isTempBasalCapable = true; + pumpDescription.lowTempBasalStyle = PumpDescription.PERCENT; + pumpDescription.highTempBasalStyle = PumpDescription.PERCENT; + pumpDescription.maxHighTempPercent = 500; + pumpDescription.maxHighTempAbsolute = 0; + pumpDescription.lowTempPercentStep = 10; + pumpDescription.lowTempAbsoluteStep = 0; + pumpDescription.lowTempPercentDuration = 30; + pumpDescription.lowTempAbsoluteDuration = 30; + pumpDescription.highTempPercentStep = 10; + pumpDescription.highTempAbsoluteStep = 0; + pumpDescription.highTempPercentDuration = 15; + pumpDescription.highTempAbsoluteDuration = 0; + + pumpDescription.isSetBasalProfileCapable = true; + pumpDescription.basalStep = 0.01d; + pumpDescription.basalMinimumRate = 0.04d; + + pumpDescription.isRefillingCapable = true; + } + + ServiceConnection mConnection = new ServiceConnection() { + + public void onServiceDisconnected(ComponentName name) { + log.debug("Service is disconnected"); + sExecutionService = null; + } + + public void onServiceConnected(ComponentName name, IBinder service) { + log.debug("Service is connected"); + DanaRv2ExecutionService.LocalBinder mLocalBinder = (DanaRv2ExecutionService.LocalBinder) service; + sExecutionService = mLocalBinder.getServiceInstance(); + } + }; + + @SuppressWarnings("UnusedParameters") + @Subscribe + public void onStatusEvent(final EventAppExit e) { + MainApp.instance().getApplicationContext().unbindService(mConnection); + } + + // Plugin base interface + @Override + public int getType() { + return PluginBase.PUMP; + } + + @Override + public String getName() { + return MainApp.instance().getString(R.string.danarv2pump); + } + + @Override + public String getNameShort() { + String name = MainApp.sResources.getString(R.string.danarpump_shortname); + if (!name.trim().isEmpty()) { + //only if translation exists + return name; + } + // use long name as fallback + return getName(); + } + + @Override + public boolean isEnabled(int type) { + if (type == PluginBase.PROFILE) return fragmentProfileEnabled && fragmentPumpEnabled; + else if (type == PluginBase.PUMP) return fragmentPumpEnabled; + else if (type == PluginBase.CONSTRAINTS) return fragmentPumpEnabled; + return false; + } + + @Override + public boolean isVisibleInTabs(int type) { + if (type == PluginBase.PROFILE || type == PluginBase.CONSTRAINTS) return false; + else if (type == PluginBase.PUMP) return fragmentPumpVisible; + return false; + } + + @Override + public boolean canBeHidden(int type) { + return true; + } + + @Override + public boolean hasFragment() { + return true; + } + + @Override + public boolean showInList(int type) { + return true; + } + + @Override + public void setFragmentEnabled(int type, boolean fragmentEnabled) { + if (type == PluginBase.PROFILE) + this.fragmentProfileEnabled = fragmentEnabled; + else if (type == PluginBase.PUMP) + this.fragmentPumpEnabled = fragmentEnabled; + // if pump profile was enabled need to switch to another too + if (type == PluginBase.PUMP && !fragmentEnabled && this.fragmentProfileEnabled) { + setFragmentEnabled(PluginBase.PROFILE, false); + setFragmentVisible(PluginBase.PROFILE, false); + MainApp.getSpecificPlugin(NSProfilePlugin.class).setFragmentEnabled(PluginBase.PROFILE, true); + MainApp.getSpecificPlugin(NSProfilePlugin.class).setFragmentVisible(PluginBase.PROFILE, true); + } + } + + @Override + public void setFragmentVisible(int type, boolean fragmentVisible) { + if (type == PluginBase.PUMP) + this.fragmentPumpVisible = fragmentVisible; + } + + @Override + public boolean isInitialized() { + return getDanaRPump().lastConnection.getTime() > 0 && getDanaRPump().isExtendedBolusEnabled; + } + + @Override + public boolean isSuspended() { + return getDanaRPump().pumpSuspended; + } + + @Override + public boolean isBusy() { + if (sExecutionService == null) return false; + return sExecutionService.isConnected() || sExecutionService.isConnecting(); + } + + // Pump interface + @Override + public boolean isTempBasalInProgress() { + return getTempBasal() != null; //TODO: crosscheck here + } + + @Override + public boolean isExtendedBoluslInProgress() { + return getExtendedBolus() != null; //TODO: crosscheck here + } + + @Override + public int setNewBasalProfile(NSProfile profile) { + if (sExecutionService == null) { + log.error("setNewBasalProfile sExecutionService is null"); + return FAILED; + } + if (!isInitialized()) { + log.error("setNewBasalProfile not initialized"); + Notification notification = new Notification(Notification.PROFILE_NOT_SET_NOT_INITIALIZED, MainApp.sResources.getString(R.string.pumpNotInitializedProfileNotSet), Notification.URGENT); + MainApp.bus().post(new EventNewNotification(notification)); + return FAILED; + } else { + MainApp.bus().post(new EventDismissNotification(Notification.PROFILE_NOT_SET_NOT_INITIALIZED)); + } + if (!sExecutionService.updateBasalsInPump(profile)) { + Notification notification = new Notification(Notification.FAILED_UDPATE_PROFILE, MainApp.sResources.getString(R.string.failedupdatebasalprofile), Notification.URGENT); + MainApp.bus().post(new EventNewNotification(notification)); + return FAILED; + } else { + MainApp.bus().post(new EventDismissNotification(Notification.PROFILE_NOT_SET_NOT_INITIALIZED)); + MainApp.bus().post(new EventDismissNotification(Notification.FAILED_UDPATE_PROFILE)); + return SUCCESS; + } + } + + @Override + public boolean isThisProfileSet(NSProfile profile) { + if (!isInitialized()) + return true; // TODO: not sure what's better. so far TRUE to prevent too many SMS + DanaRPump pump = getDanaRPump(); + if (pump.pumpProfiles == null) + return true; // TODO: not sure what's better. so far TRUE to prevent too many SMS + int basalValues = pump.basal48Enable ? 48 : 24; + int basalIncrement = pump.basal48Enable ? 30 * 60 : 60 * 60; + for (int h = 0; h < basalValues; h++) { + Double pumpValue = pump.pumpProfiles[pump.activeProfile][h]; + Double profileValue = profile.getBasal(h * basalIncrement); + if (profileValue == null) return true; + if (Math.abs(pumpValue - profileValue) > getPumpDescription().basalStep) { + log.debug("Diff found. Hour: " + h + " Pump: " + pumpValue + " Profile: " + profileValue); + return false; + } + } + return true; + } + + @Override + public Date lastDataTime() { + return getDanaRPump().lastConnection; + } + + @Override + public void refreshDataFromPump(String reason) { + if (!isConnected() && !isConnecting()) { + doConnect(reason); + } + } + + @Override + public double getBaseBasalRate() { + return getDanaRPump().currentBasal; + } + + @Override + public double getTempBasalAbsoluteRate() { + TempBasal tb = getTempBasal(); + if (tb != null) { + Double baseRate = getBaseBasalRate(); + Double tempRate = baseRate * (tb.percent / 100d); + return tempRate; + } + return 0; + } + + @Override + public double getTempBasalRemainingMinutes() { + if (isTempBasalInProgress()) + return getTempBasal().getPlannedRemainingMinutes(); + return 0; + } + + public TempBasal getTempBasal(Date time) { + return MainApp.getConfigBuilder().getActiveTempBasals().getTempBasal(time); + } + + @Override + public TempBasal getTempBasal() { + return MainApp.getConfigBuilder().getActiveTempBasals().getTempBasal(new Date()); + } + + @Override + public TempBasal getExtendedBolus() { + return MainApp.getConfigBuilder().getActiveTempBasals().getExtendedBolus(new Date()); + } + + @Override + public PumpEnactResult deliverTreatment(InsulinInterface insulinType, Double insulin, Integer carbs, Context context) { + ConfigBuilderPlugin configBuilderPlugin = MainApp.getConfigBuilder(); + insulin = configBuilderPlugin.applyBolusConstraints(insulin); + if (insulin > 0 || carbs > 0) { + Treatment t = new Treatment(insulinType); + boolean connectionOK = false; + if (insulin > 0 || carbs > 0) connectionOK = sExecutionService.bolus(insulin, carbs, t); + PumpEnactResult result = new PumpEnactResult(); + result.success = connectionOK; + result.bolusDelivered = t.insulin; + result.carbsDelivered = carbs; + result.comment = MainApp.instance().getString(R.string.virtualpump_resultok); + if (Config.logPumpActions) + log.debug("deliverTreatment: OK. Asked: " + insulin + " Delivered: " + result.bolusDelivered); + return result; + } else { + PumpEnactResult result = new PumpEnactResult(); + result.success = false; + result.bolusDelivered = 0d; + result.carbsDelivered = 0; + result.comment = MainApp.instance().getString(R.string.danar_invalidinput); + log.error("deliverTreatment: Invalid input"); + return result; + } + } + + @Override + public void stopBolusDelivering() { + if (sExecutionService == null) { + log.error("stopBolusDelivering sExecutionService is null"); + return; + } + sExecutionService.bolusStop(); + } + + // This is called from APS + @Override + public PumpEnactResult setTempBasalAbsolute(Double absoluteRate, Integer durationInMinutes) { + // Recheck pump status if older than 30 min + if (getDanaRPump().lastConnection.getTime() + 30 * 60 * 1000L < new Date().getTime()) { + doConnect("setTempBasalAbsolute old data"); + } + + PumpEnactResult result = new PumpEnactResult(); + + ConfigBuilderPlugin configBuilderPlugin = MainApp.getConfigBuilder(); + absoluteRate = configBuilderPlugin.applyBasalConstraints(absoluteRate); + + final boolean doTempOff = getBaseBasalRate() - absoluteRate == 0d; + final boolean doLowTemp = absoluteRate < getBaseBasalRate(); + final boolean doHighTemp = absoluteRate > getBaseBasalRate(); + + if (doTempOff) { + // If temp in progress + if (isTempBasalInProgress()) { + if (Config.logPumpActions) + log.debug("setTempBasalAbsolute: Stopping temp basal (doTempOff)"); + return cancelTempBasal(); + } + result.success = true; + result.enacted = false; + result.percent = 100; + result.isPercent = true; + result.isTempCancel = true; + if (Config.logPumpActions) + log.debug("setTempBasalAbsolute: doTempOff OK"); + return result; + } + + if (doLowTemp || doHighTemp) { + Integer percentRate = Double.valueOf(absoluteRate / getBaseBasalRate() * 100).intValue(); + if (percentRate < 100) percentRate = Round.ceilTo((double) percentRate, 10d).intValue(); + else percentRate = Round.floorTo((double) percentRate, 10d).intValue(); + if (percentRate > getPumpDescription().maxHighTempPercent) + percentRate = getPumpDescription().maxHighTempPercent; + // Check if some temp is already in progress + if (isTempBasalInProgress()) { + // Correct basal already set ? + if (getTempBasal().percent == percentRate) { + result.success = true; + result.percent = percentRate; + result.absolute = getTempBasalAbsoluteRate(); + result.enacted = false; + result.duration = ((Double) getTempBasalRemainingMinutes()).intValue(); + result.isPercent = true; + result.isTempCancel = false; + if (Config.logPumpActions) + log.debug("setTempBasalAbsolute: Correct temp basal already set (doLowTemp || doHighTemp)"); + return result; + } else { + if (Config.logPumpActions) + log.debug("setTempBasalAbsolute: Stopping temp basal (doLowTemp || doHighTemp)"); + result = cancelTempBasal(); + // Check for proper result + if (!result.success) { + log.error("setTempBasalAbsolute: Failed to stop previous temp basal (doLowTemp || doHighTemp)"); + return result; + } + } + } + // Convert duration from minutes to hours + if (Config.logPumpActions) + log.debug("setTempBasalAbsolute: Setting temp basal " + percentRate + "% for " + durationInMinutes + " mins (doLowTemp || doHighTemp)"); + return setTempBasalPercent(percentRate, durationInMinutes); + } + // We should never end here + log.error("setTempBasalAbsolute: Internal error"); + result.success = false; + result.comment = "Internal error"; + return result; + } + + @Override + public PumpEnactResult setTempBasalPercent(Integer percent, Integer durationInMinutes) { + PumpEnactResult result = new PumpEnactResult(); + ConfigBuilderPlugin configBuilderPlugin = MainApp.getConfigBuilder(); + percent = configBuilderPlugin.applyBasalConstraints(percent); + if (percent < 0) { + result.isTempCancel = false; + result.enacted = false; + result.success = false; + result.comment = MainApp.instance().getString(R.string.danar_invalidinput); + log.error("setTempBasalPercent: Invalid input"); + return result; + } + if (percent > getPumpDescription().maxHighTempPercent) + percent = getPumpDescription().maxHighTempPercent; + if (getDanaRPump().isTempBasalInProgress && getDanaRPump().tempBasalPercent == percent) { + result.enacted = false; + result.success = true; + result.isTempCancel = false; + result.comment = MainApp.instance().getString(R.string.virtualpump_resultok); + result.duration = getDanaRPump().tempBasalRemainingMin; + result.percent = getDanaRPump().tempBasalPercent; + result.isPercent = true; + if (Config.logPumpActions) + log.debug("setTempBasalPercent: Correct value already set"); + return result; + } + int durationInHours = Math.max(durationInMinutes / 60, 1); + boolean connectionOK = false; + if (percent < 100) connectionOK = sExecutionService.tempBasal(percent, durationInHours); + else connectionOK =sExecutionService.highTempBasal(percent); + if (connectionOK && getDanaRPump().isTempBasalInProgress && getDanaRPump().tempBasalPercent == percent) { + result.enacted = true; + result.success = true; + result.comment = MainApp.instance().getString(R.string.virtualpump_resultok); + result.isTempCancel = false; + result.duration = getDanaRPump().tempBasalRemainingMin; + result.percent = getDanaRPump().tempBasalPercent; + result.isPercent = true; + if (Config.logPumpActions) + log.debug("setTempBasalPercent: OK"); + return result; + } + result.enacted = false; + result.success = false; + result.comment = MainApp.instance().getString(R.string.danar_valuenotsetproperly); + log.error("setTempBasalPercent: Failed to set temp basal"); + return result; + } + + @Override + public PumpEnactResult setExtendedBolus(Double insulin, Integer durationInMinutes) { + ConfigBuilderPlugin configBuilderPlugin = MainApp.getConfigBuilder(); + insulin = configBuilderPlugin.applyBolusConstraints(insulin); + // needs to be rounded + insulin = Round.roundTo(insulin, getPumpDescription().extendedBolusStep); + + PumpEnactResult result = new PumpEnactResult(); + if (getDanaRPump().isExtendedInProgress && Math.abs(getDanaRPump().extendedBolusAmount - insulin) < getPumpDescription().extendedBolusStep) { + result.enacted = false; + result.success = true; + result.comment = MainApp.instance().getString(R.string.virtualpump_resultok); + result.duration = getDanaRPump().extendedBolusRemainingMinutes; + result.absolute = getDanaRPump().extendedBolusAbsoluteRate; + result.isPercent = false; + result.isTempCancel = false; + if (Config.logPumpActions) + log.debug("setExtendedBolus: Correct extended bolus already set. Current: " + getDanaRPump().extendedBolusAmount + " Asked: " + insulin); + return result; + } + int durationInHalfHours = Math.max(durationInMinutes / 30, 1); + boolean connectionOK = sExecutionService.extendedBolus(insulin, durationInHalfHours); + if (connectionOK && getDanaRPump().isExtendedInProgress && Math.abs(getDanaRPump().extendedBolusAmount - insulin) < getPumpDescription().extendedBolusStep) { + result.enacted = true; + result.success = true; + result.comment = MainApp.instance().getString(R.string.virtualpump_resultok); + result.isTempCancel = false; + result.duration = getDanaRPump().extendedBolusRemainingMinutes; + result.absolute = getDanaRPump().extendedBolusAbsoluteRate; + result.bolusDelivered = getDanaRPump().extendedBolusAmount; + result.isPercent = false; + if (Config.logPumpActions) + log.debug("setExtendedBolus: OK"); + return result; + } + result.enacted = false; + result.success = false; + result.comment = MainApp.instance().getString(R.string.danar_valuenotsetproperly); + log.error("setExtendedBolus: Failed to extended bolus"); + return result; + } + + @Override + public PumpEnactResult cancelTempBasal() { + PumpEnactResult result = new PumpEnactResult(); + if (getDanaRPump().isTempBasalInProgress) { + sExecutionService.tempBasalStop(); + result.enacted = true; + result.isTempCancel = true; + } + if (!getDanaRPump().isTempBasalInProgress) { + result.success = true; + result.isTempCancel = true; + result.comment = MainApp.instance().getString(R.string.virtualpump_resultok); + if (Config.logPumpActions) + log.debug("cancelRealTempBasal: OK"); + return result; + } else { + result.success = false; + result.comment = MainApp.instance().getString(R.string.danar_valuenotsetproperly); + result.isTempCancel = true; + log.error("cancelRealTempBasal: Failed to cancel temp basal"); + return result; + } + } + + @Override + public PumpEnactResult cancelExtendedBolus() { + PumpEnactResult result = new PumpEnactResult(); + if (getDanaRPump().isExtendedInProgress) { + sExecutionService.extendedBolusStop(); + result.enacted = true; + result.isTempCancel = true; + } + if (!getDanaRPump().isExtendedInProgress) { + result.success = true; + result.comment = MainApp.instance().getString(R.string.virtualpump_resultok); + if (Config.logPumpActions) + log.debug("cancelExtendedBolus: OK"); + return result; + } else { + result.success = false; + result.comment = MainApp.instance().getString(R.string.danar_valuenotsetproperly); + log.error("cancelExtendedBolus: Failed to cancel extended bolus"); + return result; + } + } + + public static void doConnect(String from) { + if (sExecutionService != null) sExecutionService.connect(from); + } + + public static boolean isConnected() { + return sExecutionService != null && sExecutionService.isConnected(); + } + + public static boolean isConnecting() { + return sExecutionService != null && sExecutionService.isConnecting(); + } + + public static void doDisconnect(String from) { + if (sExecutionService != null) sExecutionService.disconnect(from); + } + + @Override + public JSONObject getJSONStatus() { + if (getDanaRPump().lastConnection.getTime() + 5 * 60 * 1000L < new Date().getTime()) { + return null; + } + JSONObject pump = new JSONObject(); + JSONObject battery = new JSONObject(); + JSONObject status = new JSONObject(); + JSONObject extended = new JSONObject(); + try { + battery.put("percent", getDanaRPump().batteryRemaining); + status.put("status", getDanaRPump().pumpSuspended ? "suspended" : "normal"); + status.put("timestamp", DateUtil.toISOString(getDanaRPump().lastConnection)); + extended.put("Version", BuildConfig.VERSION_NAME + "-" + BuildConfig.BUILDVERSION); + extended.put("PumpIOB", getDanaRPump().iob); + extended.put("LastBolus", getDanaRPump().lastBolusTime.toLocaleString()); + extended.put("LastBolusAmount", getDanaRPump().lastBolusAmount); + TempBasal tb = getTempBasal(); + if (tb != null) { + extended.put("TempBasalAbsoluteRate", getTempBasalAbsoluteRate()); + extended.put("TempBasalStart", tb.timeStart.toLocaleString()); + extended.put("TempBasalRemaining", tb.getPlannedRemainingMinutes()); + extended.put("IsExtended", tb.isExtended); + } + extended.put("BaseBasalRate", getBaseBasalRate()); + try { + extended.put("ActiveProfile", MainApp.getConfigBuilder().getActiveProfile().getProfile().getActiveProfile()); + } catch (Exception e) { + } + + pump.put("battery", battery); + pump.put("status", status); + pump.put("extended", extended); + pump.put("reservoir", (int) getDanaRPump().reservoirRemainingUnits); + pump.put("clock", DateUtil.toISOString(new Date())); + } catch (JSONException e) { + e.printStackTrace(); + } + return pump; + } + + @Override + public String deviceID() { + return getDanaRPump().serialNumber; + } + + @Override + public PumpDescription getPumpDescription() { + return pumpDescription; + } + + /** + * Constraint interface + */ + + @Override + public boolean isLoopEnabled() { + return true; + } + + @Override + public boolean isClosedModeEnabled() { + return true; + } + + @Override + public boolean isAutosensModeEnabled() { + return true; + } + + @Override + public boolean isAMAModeEnabled() { + return true; + } + + @SuppressWarnings("PointlessBooleanExpression") + @Override + public Double applyBasalConstraints(Double absoluteRate) { + double origAbsoluteRate = absoluteRate; + if (getDanaRPump() != null) { + if (absoluteRate > getDanaRPump().maxBasal) { + absoluteRate = getDanaRPump().maxBasal; + if (Config.logConstraintsChanges && origAbsoluteRate != Constants.basalAbsoluteOnlyForCheckLimit) + log.debug("Limiting rate " + origAbsoluteRate + "U/h by pump constraint to " + absoluteRate + "U/h"); + } + } + return absoluteRate; + } + + @SuppressWarnings("PointlessBooleanExpression") + @Override + public Integer applyBasalConstraints(Integer percentRate) { + Integer origPercentRate = percentRate; + if (percentRate < 0) percentRate = 0; + if (percentRate > getPumpDescription().maxHighTempPercent) + percentRate = getPumpDescription().maxHighTempPercent; + if (!Objects.equals(percentRate, origPercentRate) && Config.logConstraintsChanges && !Objects.equals(origPercentRate, Constants.basalPercentOnlyForCheckLimit)) + log.debug("Limiting percent rate " + origPercentRate + "% to " + percentRate + "%"); + return percentRate; + } + + @SuppressWarnings("PointlessBooleanExpression") + @Override + public Double applyBolusConstraints(Double insulin) { + double origInsulin = insulin; + if (getDanaRPump() != null) { + if (insulin > getDanaRPump().maxBolus) { + insulin = getDanaRPump().maxBolus; + if (Config.logConstraintsChanges && origInsulin != Constants.bolusOnlyForCheckLimit) + log.debug("Limiting bolus " + origInsulin + "U by pump constraint to " + insulin + "U"); + } + } + return insulin; + } + + @Override + public Integer applyCarbsConstraints(Integer carbs) { + return carbs; + } + + @Override + public Double applyMaxIOBConstraints(Double maxIob) { + return maxIob; + } + + @Nullable + @Override + public NSProfile getProfile() { + DanaRPump pump = getDanaRPump(); + if (pump.lastSettingsRead.getTime() == 0) + return null; // no info now + return pump.createConvertedProfile(); + } + + // Reply for sms communicator + public String shortStatus(boolean veryShort) { + String ret = ""; + if (getDanaRPump().lastConnection.getTime() != 0) { + Long agoMsec = new Date().getTime() - getDanaRPump().lastConnection.getTime(); + int agoMin = (int) (agoMsec / 60d / 1000d); + ret += "LastConn: " + agoMin + " minago\n"; + } + if (getDanaRPump().lastBolusTime.getTime() != 0) { + ret += "LastBolus: " + DecimalFormatter.to2Decimal(getDanaRPump().lastBolusAmount) + "U @" + android.text.format.DateFormat.format("HH:mm", getDanaRPump().lastBolusTime) + "\n"; + } + if (isTempBasalInProgress()) { + ret += "Temp: " + getTempBasal().toString() + "\n"; + } + if (isExtendedBoluslInProgress()) { + ret += "Extended: " + getExtendedBolus().toString() + "\n"; + } + if (!veryShort) { + ret += "TDD: " + DecimalFormatter.to0Decimal(getDanaRPump().dailyTotalUnits) + " / " + getDanaRPump().maxDailyTotalUnits + " U\n"; + } + ret += "IOB: " + getDanaRPump().iob + "U\n"; + ret += "Reserv: " + DecimalFormatter.to0Decimal(getDanaRPump().reservoirRemainingUnits) + "U\n"; + ret += "Batt: " + getDanaRPump().batteryRemaining + "\n"; + return ret; + } + // TODO: daily total constraint + +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRv2/History/DanaRHistoryActivity.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRv2/History/DanaRHistoryActivity.java new file mode 100644 index 0000000000..aac00e6eba --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRv2/History/DanaRHistoryActivity.java @@ -0,0 +1,448 @@ +package info.nightscout.androidaps.plugins.PumpDanaRv2.History; + +import android.app.Activity; +import android.content.ComponentName; +import android.content.Context; +import android.content.Intent; +import android.content.ServiceConnection; +import android.os.Bundle; +import android.os.Handler; +import android.os.HandlerThread; +import android.os.IBinder; +import android.support.v7.widget.CardView; +import android.support.v7.widget.LinearLayoutManager; +import android.support.v7.widget.RecyclerView; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.AdapterView; +import android.widget.ArrayAdapter; +import android.widget.Button; +import android.widget.Spinner; +import android.widget.TextView; + +import com.j256.ormlite.dao.Dao; +import com.j256.ormlite.stmt.PreparedQuery; +import com.j256.ormlite.stmt.QueryBuilder; +import com.j256.ormlite.stmt.Where; +import com.squareup.otto.Subscribe; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.sql.SQLException; +import java.util.ArrayList; +import java.util.List; + +import info.nightscout.androidaps.Constants; +import info.nightscout.androidaps.MainApp; +import info.nightscout.androidaps.R; +import info.nightscout.androidaps.db.DanaRHistoryRecord; +import info.nightscout.androidaps.events.EventPumpStatusChanged; +import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin; +import info.nightscout.androidaps.plugins.PumpDanaR.History.DanaRNSHistorySync; +import info.nightscout.androidaps.plugins.PumpDanaR.comm.RecordTypes; +import info.nightscout.androidaps.plugins.PumpDanaR.events.EventDanaRSyncStatus; +import info.nightscout.androidaps.plugins.NSClientInternal.data.NSProfile; +import info.nightscout.androidaps.plugins.PumpDanaRv2.services.DanaRv2ExecutionService; +import info.nightscout.utils.DateUtil; +import info.nightscout.utils.DecimalFormatter; +import info.nightscout.utils.ToastUtils; + +public class DanaRHistoryActivity extends Activity { + private static Logger log = LoggerFactory.getLogger(DanaRHistoryActivity.class); + + private boolean mBounded; + private static DanaRv2ExecutionService mExecutionService; + + private Handler mHandler; + private static HandlerThread mHandlerThread; + + static NSProfile profile = null; + + Spinner historyTypeSpinner; + TextView statusView; + Button reloadButton; + Button syncButton; + RecyclerView recyclerView; + LinearLayoutManager llm; + + static byte showingType = RecordTypes.RECORD_TYPE_ALARM; + List historyList = new ArrayList<>(); + + public static class TypeList { + public byte type; + String name; + + public TypeList(byte type, String name) { + this.type = type; + this.name = name; + } + + @Override + public String toString() { + return name; + } + } + + public DanaRHistoryActivity() { + super(); + mHandlerThread = new HandlerThread(DanaRHistoryActivity.class.getSimpleName()); + mHandlerThread.start(); + this.mHandler = new Handler(mHandlerThread.getLooper()); + } + + + @Override + public void onStart() { + super.onStart(); + Intent intent = new Intent(this, DanaRv2ExecutionService.class); + bindService(intent, mConnection, Context.BIND_AUTO_CREATE); + } + + @Override + protected void onResume() { + super.onResume(); + MainApp.bus().register(this); + } + + @Override + protected void onPause() { + super.onPause(); + MainApp.bus().unregister(this); + } + + @Override + public void onStop() { + super.onStop(); + if (mBounded) { + unbindService(mConnection); + mBounded = false; + } + } + + ServiceConnection mConnection = new ServiceConnection() { + + public void onServiceDisconnected(ComponentName name) { + log.debug("Service is disconnected"); + mBounded = false; + mExecutionService = null; + } + + public void onServiceConnected(ComponentName name, IBinder service) { + log.debug("Service is connected"); + mBounded = true; + DanaRv2ExecutionService.LocalBinder mLocalBinder = (DanaRv2ExecutionService.LocalBinder) service; + mExecutionService = mLocalBinder.getServiceInstance(); + } + }; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.danar_historyactivity); + + historyTypeSpinner = (Spinner) findViewById(R.id.danar_historytype); + statusView = (TextView) findViewById(R.id.danar_historystatus); + reloadButton = (Button) findViewById(R.id.danar_historyreload); + syncButton = (Button) findViewById(R.id.danar_historysync); + recyclerView = (RecyclerView) findViewById(R.id.danar_history_recyclerview); + + recyclerView.setHasFixedSize(true); + llm = new LinearLayoutManager(this); + recyclerView.setLayoutManager(llm); + + RecyclerViewAdapter adapter = new RecyclerViewAdapter(historyList); + recyclerView.setAdapter(adapter); + + statusView.setVisibility(View.GONE); + + // Types + + ArrayList typeList = new ArrayList<>(); + typeList.add(new TypeList(RecordTypes.RECORD_TYPE_ALARM, getString(R.string.danar_history_alarm))); + typeList.add(new TypeList(RecordTypes.RECORD_TYPE_BASALHOUR, getString(R.string.danar_history_basalhours))); + typeList.add(new TypeList(RecordTypes.RECORD_TYPE_BOLUS, getString(R.string.danar_history_bolus))); + typeList.add(new TypeList(RecordTypes.RECORD_TYPE_CARBO, getString(R.string.danar_history_carbohydrates))); + typeList.add(new TypeList(RecordTypes.RECORD_TYPE_DAILY, getString(R.string.danar_history_dailyinsulin))); + typeList.add(new TypeList(RecordTypes.RECORD_TYPE_GLUCOSE, getString(R.string.danar_history_glucose))); + + ArrayAdapter spinnerAdapter = new ArrayAdapter<>(this, + android.R.layout.simple_spinner_item, typeList); + spinnerAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); + historyTypeSpinner.setAdapter(spinnerAdapter); + + reloadButton.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + if (mExecutionService.isConnected() || mExecutionService.isConnecting()) { + ToastUtils.showToastInUiThread(MainApp.instance().getApplicationContext(), getString(R.string.pumpbusy)); + return; + } + mHandler.post(new Runnable() { + @Override + public void run() { + TypeList selected = (TypeList) historyTypeSpinner.getSelectedItem(); + runOnUiThread(new Runnable() { + @Override + public void run() { + reloadButton.setVisibility(View.GONE); + syncButton.setVisibility(View.GONE); + statusView.setVisibility(View.VISIBLE); + } + }); + clearCardView(); + mExecutionService.loadHistory(selected.type); + loadDataFromDB(selected.type); + runOnUiThread(new Runnable() { + @Override + public void run() { + reloadButton.setVisibility(View.VISIBLE); + syncButton.setVisibility(View.VISIBLE); + statusView.setVisibility(View.GONE); + } + }); + } + }); + } + }); + + syncButton.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + mHandler.post(new Runnable() { + @Override + public void run() { + runOnUiThread(new Runnable() { + @Override + public void run() { + reloadButton.setVisibility(View.GONE); + syncButton.setVisibility(View.GONE); + statusView.setVisibility(View.VISIBLE); + } + }); + DanaRNSHistorySync sync = new DanaRNSHistorySync(historyList); + sync.sync(DanaRNSHistorySync.SYNC_ALL); + runOnUiThread(new Runnable() { + @Override + public void run() { + reloadButton.setVisibility(View.VISIBLE); + syncButton.setVisibility(View.VISIBLE); + statusView.setVisibility(View.GONE); + } + }); + } + }); + } + }); + + historyTypeSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() { + @Override + public void onItemSelected(AdapterView parent, View view, int position, long id) { + TypeList selected = (TypeList) historyTypeSpinner.getSelectedItem(); + loadDataFromDB(selected.type); + showingType = selected.type; + } + + @Override + public void onNothingSelected(AdapterView parent) { + clearCardView(); + } + }); + profile = ConfigBuilderPlugin.getActiveProfile().getProfile(); + if (profile == null) { + ToastUtils.showToastInUiThread(MainApp.instance().getApplicationContext(), MainApp.sResources.getString(R.string.noprofile)); + finish(); + } + } + + public static class RecyclerViewAdapter extends RecyclerView.Adapter { + + List historyList; + + RecyclerViewAdapter(List historyList) { + this.historyList = historyList; + } + + @Override + public HistoryViewHolder onCreateViewHolder(ViewGroup viewGroup, int viewType) { + View v = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.danar_history_item, viewGroup, false); + return new HistoryViewHolder(v); + } + + @Override + public void onBindViewHolder(HistoryViewHolder holder, int position) { + DanaRHistoryRecord record = historyList.get(position); + holder.time.setText(DateUtil.dateAndTimeString(record.getRecordDate())); + holder.value.setText(DecimalFormatter.to2Decimal(record.getRecordValue())); + holder.stringvalue.setText(record.getStringRecordValue()); + holder.bolustype.setText(record.getBolusType()); + holder.duration.setText(DecimalFormatter.to0Decimal(record.getRecordDuration())); + holder.alarm.setText(record.getRecordAlarm()); + switch (showingType) { + case RecordTypes.RECORD_TYPE_ALARM: + holder.time.setVisibility(View.VISIBLE); + holder.value.setVisibility(View.VISIBLE); + holder.stringvalue.setVisibility(View.GONE); + holder.bolustype.setVisibility(View.GONE); + holder.duration.setVisibility(View.GONE); + holder.dailybasal.setVisibility(View.GONE); + holder.dailybolus.setVisibility(View.GONE); + holder.dailytotal.setVisibility(View.GONE); + holder.alarm.setVisibility(View.VISIBLE); + break; + case RecordTypes.RECORD_TYPE_BOLUS: + holder.time.setVisibility(View.VISIBLE); + holder.value.setVisibility(View.VISIBLE); + holder.stringvalue.setVisibility(View.GONE); + holder.bolustype.setVisibility(View.VISIBLE); + holder.duration.setVisibility(View.VISIBLE); + holder.dailybasal.setVisibility(View.GONE); + holder.dailybolus.setVisibility(View.GONE); + holder.dailytotal.setVisibility(View.GONE); + holder.alarm.setVisibility(View.GONE); + break; + case RecordTypes.RECORD_TYPE_DAILY: + holder.dailybasal.setText(DecimalFormatter.to2Decimal(record.getRecordDailyBasal()) + "U"); + holder.dailybolus.setText(DecimalFormatter.to2Decimal(record.getRecordDailyBolus()) + "U"); + holder.dailytotal.setText(DecimalFormatter.to2Decimal(record.getRecordDailyBolus() + record.getRecordDailyBasal()) + "U"); + holder.time.setText(DateUtil.dateString(record.getRecordDate())); + holder.time.setVisibility(View.VISIBLE); + holder.value.setVisibility(View.GONE); + holder.stringvalue.setVisibility(View.GONE); + holder.bolustype.setVisibility(View.GONE); + holder.duration.setVisibility(View.GONE); + holder.dailybasal.setVisibility(View.VISIBLE); + holder.dailybolus.setVisibility(View.VISIBLE); + holder.dailytotal.setVisibility(View.VISIBLE); + holder.alarm.setVisibility(View.GONE); + break; + case RecordTypes.RECORD_TYPE_GLUCOSE: + holder.value.setText(NSProfile.toUnitsString(record.getRecordValue(), record.getRecordValue() * Constants.MGDL_TO_MMOLL, profile.getUnits())); + // rest is the same + case RecordTypes.RECORD_TYPE_CARBO: + case RecordTypes.RECORD_TYPE_BASALHOUR: + case RecordTypes.RECORD_TYPE_ERROR: + case RecordTypes.RECORD_TYPE_PRIME: + case RecordTypes.RECORD_TYPE_REFILL: + case RecordTypes.RECORD_TYPE_TB: + holder.time.setVisibility(View.VISIBLE); + holder.value.setVisibility(View.VISIBLE); + holder.stringvalue.setVisibility(View.GONE); + holder.bolustype.setVisibility(View.GONE); + holder.duration.setVisibility(View.GONE); + holder.dailybasal.setVisibility(View.GONE); + holder.dailybolus.setVisibility(View.GONE); + holder.dailytotal.setVisibility(View.GONE); + holder.alarm.setVisibility(View.GONE); + break; + case RecordTypes.RECORD_TYPE_SUSPEND: + holder.time.setVisibility(View.VISIBLE); + holder.value.setVisibility(View.GONE); + holder.stringvalue.setVisibility(View.VISIBLE); + holder.bolustype.setVisibility(View.GONE); + holder.duration.setVisibility(View.GONE); + holder.dailybasal.setVisibility(View.GONE); + holder.dailybolus.setVisibility(View.GONE); + holder.dailytotal.setVisibility(View.GONE); + holder.alarm.setVisibility(View.GONE); + break; + } + } + + @Override + public int getItemCount() { + return historyList.size(); + } + + @Override + public void onAttachedToRecyclerView(RecyclerView recyclerView) { + super.onAttachedToRecyclerView(recyclerView); + } + + public static class HistoryViewHolder extends RecyclerView.ViewHolder { + CardView cv; + TextView time; + TextView value; + TextView bolustype; + TextView stringvalue; + TextView duration; + TextView dailybasal; + TextView dailybolus; + TextView dailytotal; + TextView alarm; + + HistoryViewHolder(View itemView) { + super(itemView); + cv = (CardView) itemView.findViewById(R.id.danar_history_cardview); + time = (TextView) itemView.findViewById(R.id.danar_history_time); + value = (TextView) itemView.findViewById(R.id.danar_history_value); + bolustype = (TextView) itemView.findViewById(R.id.danar_history_bolustype); + stringvalue = (TextView) itemView.findViewById(R.id.danar_history_stringvalue); + duration = (TextView) itemView.findViewById(R.id.danar_history_duration); + dailybasal = (TextView) itemView.findViewById(R.id.danar_history_dailybasal); + dailybolus = (TextView) itemView.findViewById(R.id.danar_history_dailybolus); + dailytotal = (TextView) itemView.findViewById(R.id.danar_history_dailytotal); + alarm = (TextView) itemView.findViewById(R.id.danar_history_alarm); + } + } + } + + private void loadDataFromDB(byte type) { + try { + Dao dao = MainApp.getDbHelper().getDaoDanaRHistory(); + QueryBuilder queryBuilder = dao.queryBuilder(); + queryBuilder.orderBy("recordDate", false); + Where where = queryBuilder.where(); + where.eq("recordCode", type); + queryBuilder.limit(200L); + PreparedQuery preparedQuery = queryBuilder.prepare(); + historyList = dao.query(preparedQuery); + } catch (SQLException e) { + e.printStackTrace(); + historyList = new ArrayList<>(); + } + runOnUiThread(new Runnable() { + @Override + public void run() { + recyclerView.swapAdapter(new RecyclerViewAdapter(historyList), false); + } + }); + } + + private void clearCardView() { + historyList = new ArrayList<>(); + runOnUiThread(new Runnable() { + @Override + public void run() { + recyclerView.swapAdapter(new RecyclerViewAdapter(historyList), false); + } + }); + } + + @Subscribe + public void onStatusEvent(final EventDanaRSyncStatus s) { + log.debug("EventDanaRSyncStatus: " + s.message); + runOnUiThread( + new Runnable() { + @Override + public void run() { + statusView.setText(s.message); + } + }); + } + + @Subscribe + public void onStatusEvent(final EventPumpStatusChanged c) { + runOnUiThread( + new Runnable() { + @Override + public void run() { + statusView.setText(c.textStatus()); + } + } + ); + } + + +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRv2/History/DanaRStatsActivity.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRv2/History/DanaRStatsActivity.java new file mode 100644 index 0000000000..75b8c5388b --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRv2/History/DanaRStatsActivity.java @@ -0,0 +1,561 @@ +package info.nightscout.androidaps.plugins.PumpDanaRv2.History; + +import android.app.Activity; +import android.content.ComponentName; +import android.content.Context; +import android.content.Intent; +import android.content.ServiceConnection; +import android.content.SharedPreferences; +import android.graphics.Color; +import android.graphics.Rect; +import android.os.Bundle; +import android.os.Handler; +import android.os.HandlerThread; +import android.os.IBinder; +import android.preference.PreferenceManager; +import android.support.v7.widget.LinearLayoutManager; +import android.text.TextUtils; +import android.view.KeyEvent; +import android.view.MotionEvent; +import android.view.View; +import android.view.WindowManager; +import android.view.inputmethod.EditorInfo; +import android.view.inputmethod.InputMethodManager; +import android.widget.Button; +import android.widget.EditText; +import android.widget.TableLayout; +import android.widget.TableRow; +import android.widget.TextView; + +import com.j256.ormlite.dao.Dao; +import com.j256.ormlite.stmt.PreparedQuery; +import com.j256.ormlite.stmt.QueryBuilder; +import com.j256.ormlite.stmt.Where; +import com.squareup.otto.Subscribe; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.sql.SQLException; +import java.text.DateFormat; +import java.text.DecimalFormat; +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Date; +import java.util.List; + +import info.nightscout.androidaps.MainApp; +import info.nightscout.androidaps.R; +import info.nightscout.androidaps.db.DanaRHistoryRecord; +import info.nightscout.androidaps.events.EventPumpStatusChanged; +import info.nightscout.androidaps.interfaces.ProfileInterface; +import info.nightscout.androidaps.plugins.ProfileCircadianPercentage.CircadianPercentageProfilePlugin; +import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin; +import info.nightscout.androidaps.plugins.PumpDanaR.comm.RecordTypes; +import info.nightscout.androidaps.plugins.PumpDanaR.events.EventDanaRSyncStatus; +import info.nightscout.androidaps.plugins.PumpDanaRv2.services.DanaRv2ExecutionService; +import info.nightscout.utils.DecimalFormatter; +import info.nightscout.utils.SafeParse; +import info.nightscout.utils.ToastUtils; + +public class DanaRStatsActivity extends Activity { + private static Logger log = LoggerFactory.getLogger(DanaRStatsActivity.class); + + private boolean mBounded; + private static DanaRv2ExecutionService mExecutionService; + + private Handler mHandler; + private static HandlerThread mHandlerThread; + + TextView statusView, statsMessage, totalBaseBasal2; + EditText totalBaseBasal; + Button reloadButton; + LinearLayoutManager llm; + TableLayout tl, ctl, etl; + String TBB; + double magicNumber; + DecimalFormat decimalFormat; + + List historyList = new ArrayList<>(); + + public DanaRStatsActivity() { + super(); + mHandlerThread = new HandlerThread(DanaRStatsActivity.class.getSimpleName()); + mHandlerThread.start(); + this.mHandler = new Handler(mHandlerThread.getLooper()); + } + + @Override + public void onStart() { + super.onStart(); + Intent intent = new Intent(this, DanaRv2ExecutionService.class); + bindService(intent, mConnection, Context.BIND_AUTO_CREATE); + } + + @Override + protected void onResume() { + super.onResume(); + MainApp.bus().register(this); + } + + @Override + protected void onPause() { + super.onPause(); + MainApp.bus().unregister(this); + } + + @Override + public void onStop() { + super.onStop(); + if (mBounded) { + unbindService(mConnection); + mBounded = false; + } + } + + @Override + public boolean dispatchTouchEvent(MotionEvent event) { + if (event.getAction() == MotionEvent.ACTION_DOWN) { + View myView = getCurrentFocus(); + if (myView instanceof EditText) { + Rect rect = new Rect(); + myView.getGlobalVisibleRect(rect); + if (!rect.contains((int) event.getRawX(), (int) event.getRawY())) { + myView.clearFocus(); + } + } + } + return super.dispatchTouchEvent(event); + } + + ServiceConnection mConnection = new ServiceConnection() { + + public void onServiceDisconnected(ComponentName name) { + log.debug("Service is disconnected"); + mBounded = false; + mExecutionService = null; + } + + public void onServiceConnected(ComponentName name, IBinder service) { + log.debug("Service is connected"); + mBounded = true; + DanaRv2ExecutionService.LocalBinder mLocalBinder = (DanaRv2ExecutionService.LocalBinder) service; + mExecutionService = mLocalBinder.getServiceInstance(); + } + }; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.danar_statsactivity); + getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_PAN); + statusView = (TextView) findViewById(R.id.danar_stats_connection_status); + reloadButton = (Button) findViewById(R.id.danar_statsreload); + totalBaseBasal = (EditText) findViewById(R.id.danar_stats_editTotalBaseBasal); + totalBaseBasal2 = (TextView) findViewById(R.id.danar_stats_editTotalBaseBasal2); + statsMessage = (TextView) findViewById(R.id.danar_stats_Message); + + statusView.setVisibility(View.GONE); + statsMessage.setVisibility(View.GONE); + + totalBaseBasal2.setEnabled(false); + totalBaseBasal2.setClickable(false); + totalBaseBasal2.setFocusable(false); + totalBaseBasal2.setInputType(0); + + decimalFormat = new DecimalFormat("0.000"); + llm = new LinearLayoutManager(this); + + final SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(this); + TBB = preferences.getString("TBB", "10.00"); + totalBaseBasal.setText(TBB); + + ProfileInterface pi = ConfigBuilderPlugin.getActiveProfile(); + if (pi != null && pi instanceof CircadianPercentageProfilePlugin) { + double cppTBB = ((CircadianPercentageProfilePlugin) pi).baseBasalSum(); + totalBaseBasal.setText(decimalFormat.format(cppTBB)); + SharedPreferences.Editor edit = preferences.edit(); + edit.putString("TBB", totalBaseBasal.getText().toString()); + edit.commit(); + TBB = preferences.getString("TBB", ""); + } + + // stats table + tl = (TableLayout) findViewById(R.id.main_table); + TableRow tr_head = new TableRow(this); + tr_head.setBackgroundColor(Color.DKGRAY); + tr_head.setLayoutParams(new TableLayout.LayoutParams( + TableLayout.LayoutParams.MATCH_PARENT, + TableLayout.LayoutParams.WRAP_CONTENT)); + + TextView label_date = new TextView(this); + label_date.setText(getString(R.string.danar_stats_date)); + label_date.setTextColor(Color.WHITE); + tr_head.addView(label_date); + + TextView label_basalrate = new TextView(this); + label_basalrate.setText(getString(R.string.danar_stats_basalrate)); + label_basalrate.setTextColor(Color.WHITE); + tr_head.addView(label_basalrate); + + TextView label_bolus = new TextView(this); + label_bolus.setText(getString(R.string.danar_stats_bolus)); + label_bolus.setTextColor(Color.WHITE); + tr_head.addView(label_bolus); + + TextView label_tdd = new TextView(this); + label_tdd.setText(getString(R.string.danar_stats_tdd)); + label_tdd.setTextColor(Color.WHITE); + tr_head.addView(label_tdd); + + TextView label_ratio = new TextView(this); + label_ratio.setText(getString(R.string.danar_stats_ratio)); + label_ratio.setTextColor(Color.WHITE); + tr_head.addView(label_ratio); + + // add stats headers to tables + tl.addView(tr_head, new TableLayout.LayoutParams( + TableLayout.LayoutParams.MATCH_PARENT, + TableLayout.LayoutParams.WRAP_CONTENT)); + + // cumulative table + ctl = (TableLayout) findViewById(R.id.cumulative_table); + TableRow ctr_head = new TableRow(this); + ctr_head.setBackgroundColor(Color.DKGRAY); + ctr_head.setLayoutParams(new TableLayout.LayoutParams( + TableLayout.LayoutParams.MATCH_PARENT, + TableLayout.LayoutParams.WRAP_CONTENT)); + + TextView label_cum_amount_days = new TextView(this); + label_cum_amount_days.setText(getString(R.string.danar_stats_amount_days)); + label_cum_amount_days.setTextColor(Color.WHITE); + ctr_head.addView(label_cum_amount_days); + + TextView label_cum_tdd = new TextView(this); + label_cum_tdd.setText(getString(R.string.danar_stats_tdd)); + label_cum_tdd.setTextColor(Color.WHITE); + ctr_head.addView(label_cum_tdd); + + TextView label_cum_ratio = new TextView(this); + label_cum_ratio.setText(getString(R.string.danar_stats_ratio)); + label_cum_ratio.setTextColor(Color.WHITE); + ctr_head.addView(label_cum_ratio); + + // add cummulative headers to tables + ctl.addView(ctr_head, new TableLayout.LayoutParams( + TableLayout.LayoutParams.MATCH_PARENT, + TableLayout.LayoutParams.WRAP_CONTENT)); + + // expontial table + etl = (TableLayout) findViewById(R.id.expweight_table); + TableRow etr_head = new TableRow(this); + etr_head.setBackgroundColor(Color.DKGRAY); + etr_head.setLayoutParams(new TableLayout.LayoutParams( + TableLayout.LayoutParams.MATCH_PARENT, + TableLayout.LayoutParams.WRAP_CONTENT)); + + TextView label_exp_weight = new TextView(this); + label_exp_weight.setText(getString(R.string.danar_stats_weight)); + label_exp_weight.setTextColor(Color.WHITE); + etr_head.addView(label_exp_weight); + + TextView label_exp_tdd = new TextView(this); + label_exp_tdd.setText(getString(R.string.danar_stats_tdd)); + label_exp_tdd.setTextColor(Color.WHITE); + etr_head.addView(label_exp_tdd); + + TextView label_exp_ratio = new TextView(this); + label_exp_ratio.setText(getString(R.string.danar_stats_ratio)); + label_exp_ratio.setTextColor(Color.WHITE); + etr_head.addView(label_exp_ratio); + + // add expontial headers to tables + etl.addView(etr_head, new TableLayout.LayoutParams( + TableLayout.LayoutParams.MATCH_PARENT, + TableLayout.LayoutParams.WRAP_CONTENT)); + + reloadButton.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + if (mExecutionService.isConnected() || mExecutionService.isConnecting()) { + ToastUtils.showToastInUiThread(MainApp.instance().getApplicationContext(), getString(R.string.pumpbusy)); + return; + } + mHandler.post(new Runnable() { + @Override + public void run() { + runOnUiThread(new Runnable() { + @Override + public void run() { + reloadButton.setVisibility(View.GONE); + statusView.setVisibility(View.VISIBLE); + statsMessage.setVisibility(View.VISIBLE); + statsMessage.setText(getString(R.string.danar_stats_warning_Message)); + } + }); + mExecutionService.loadHistory(RecordTypes.RECORD_TYPE_DAILY); + loadDataFromDB(RecordTypes.RECORD_TYPE_DAILY); + runOnUiThread(new Runnable() { + @Override + public void run() { + reloadButton.setVisibility(View.VISIBLE); + statusView.setVisibility(View.GONE); + statsMessage.setVisibility(View.GONE); + } + }); + } + }); + } + }); + + totalBaseBasal.setOnEditorActionListener(new TextView.OnEditorActionListener() { + @Override + public boolean onEditorAction(TextView v, int actionId, KeyEvent event) { + if (actionId == EditorInfo.IME_ACTION_DONE) { + totalBaseBasal.clearFocus(); + return true; + } + return false; + } + }); + + totalBaseBasal.setOnFocusChangeListener(new View.OnFocusChangeListener() { + @Override + public void onFocusChange(View v, boolean hasFocus) { + if (hasFocus) { + totalBaseBasal.getText().clear(); + } else { + SharedPreferences.Editor edit = preferences.edit(); + edit.putString("TBB", totalBaseBasal.getText().toString()); + edit.commit(); + TBB = preferences.getString("TBB", ""); + loadDataFromDB(RecordTypes.RECORD_TYPE_DAILY); + InputMethodManager imm = (InputMethodManager) getSystemService(INPUT_METHOD_SERVICE); + imm.hideSoftInputFromWindow(totalBaseBasal.getWindowToken(), 0); + } + } + }); + + loadDataFromDB(RecordTypes.RECORD_TYPE_DAILY); + } + + private void loadDataFromDB(byte type) { + try { + Dao dao = MainApp.getDbHelper().getDaoDanaRHistory(); + QueryBuilder queryBuilder = dao.queryBuilder(); + queryBuilder.orderBy("recordDate", false); + Where where = queryBuilder.where(); + where.eq("recordCode", type); + queryBuilder.limit(10L); + PreparedQuery preparedQuery = queryBuilder.prepare(); + historyList = dao.query(preparedQuery); + } catch (SQLException e) { + e.printStackTrace(); + historyList = new ArrayList<>(); + } + runOnUiThread(new Runnable() { + @Override + public void run() { + cleanTable(tl); + cleanTable(ctl); + cleanTable(etl); + DateFormat df = new SimpleDateFormat("dd.MM."); + + if (TextUtils.isEmpty(TBB)) { + totalBaseBasal.setError("Please Enter Total Base Basal"); + return; + } else { + magicNumber = SafeParse.stringToDouble(TBB); + } + + magicNumber *= 2; + totalBaseBasal2.setText(decimalFormat.format(magicNumber)); + + int i = 0; + double sum = 0d; + double weighted03 = 0d; + double weighted05 = 0d; + double weighted07 = 0d; + + for (DanaRHistoryRecord record : historyList) { + double tdd = record.getRecordDailyBolus() + record.getRecordDailyBasal(); + + // Create the table row + TableRow tr = new TableRow(DanaRStatsActivity.this); + if (i % 2 != 0) tr.setBackgroundColor(Color.DKGRAY); + tr.setId(100 + i); + tr.setLayoutParams(new TableLayout.LayoutParams( + TableLayout.LayoutParams.MATCH_PARENT, + TableLayout.LayoutParams.WRAP_CONTENT)); + + // Here create the TextView dynamically + TextView labelDATE = new TextView(DanaRStatsActivity.this); + labelDATE.setId(200 + i); + labelDATE.setText(df.format(new Date(record.getRecordDate()))); + labelDATE.setTextColor(Color.WHITE); + tr.addView(labelDATE); + + TextView labelBASAL = new TextView(DanaRStatsActivity.this); + labelBASAL.setId(300 + i); + labelBASAL.setText(DecimalFormatter.to2Decimal(record.getRecordDailyBasal()) + " U"); + labelBASAL.setTextColor(Color.WHITE); + tr.addView(labelBASAL); + + TextView labelBOLUS = new TextView(DanaRStatsActivity.this); + labelBOLUS.setId(400 + i); + labelBOLUS.setText(DecimalFormatter.to2Decimal(record.getRecordDailyBolus()) + " U"); + labelBOLUS.setTextColor(Color.WHITE); + tr.addView(labelBOLUS); + + TextView labelTDD = new TextView(DanaRStatsActivity.this); + labelTDD.setId(500 + i); + labelTDD.setText(DecimalFormatter.to2Decimal(tdd) + " U"); + labelTDD.setTextColor(Color.WHITE); + tr.addView(labelTDD); + + TextView labelRATIO = new TextView(DanaRStatsActivity.this); + labelRATIO.setId(600 + i); + labelRATIO.setText(Math.round(100 * tdd / magicNumber) + " %"); + labelRATIO.setTextColor(Color.WHITE); + tr.addView(labelRATIO); + + // add stats rows to tables + tl.addView(tr, new TableLayout.LayoutParams( + TableLayout.LayoutParams.MATCH_PARENT, + TableLayout.LayoutParams.WRAP_CONTENT)); + + sum = sum + tdd; + i++; + + // Create the cumtable row + TableRow ctr = new TableRow(DanaRStatsActivity.this); + if (i % 2 == 0) ctr.setBackgroundColor(Color.DKGRAY); + ctr.setId(700 + i); + ctr.setLayoutParams(new TableLayout.LayoutParams( + TableLayout.LayoutParams.MATCH_PARENT, + TableLayout.LayoutParams.WRAP_CONTENT)); + + // Here create the TextView dynamically + TextView labelDAYS = new TextView(DanaRStatsActivity.this); + labelDAYS.setId(800 + i); + labelDAYS.setText("" + i); + labelDAYS.setTextColor(Color.WHITE); + ctr.addView(labelDAYS); + + TextView labelCUMTDD = new TextView(DanaRStatsActivity.this); + labelCUMTDD.setId(900 + i); + labelCUMTDD.setText(DecimalFormatter.to2Decimal(sum / i) + " U"); + labelCUMTDD.setTextColor(Color.WHITE); + ctr.addView(labelCUMTDD); + + TextView labelCUMRATIO = new TextView(DanaRStatsActivity.this); + labelCUMRATIO.setId(1000 + i); + labelCUMRATIO.setText(Math.round(100 * sum / i / magicNumber) + " %"); + labelCUMRATIO.setTextColor(Color.WHITE); + ctr.addView(labelCUMRATIO); + + // add cummulative rows to tables + ctl.addView(ctr, new TableLayout.LayoutParams( + TableLayout.LayoutParams.MATCH_PARENT, + TableLayout.LayoutParams.WRAP_CONTENT)); + } + + if (historyList.size() < 3 || !(df.format(new Date(historyList.get(0).getRecordDate())).equals(df.format(new Date(System.currentTimeMillis() - 1000 * 60 * 60 * 24))))) { + statsMessage.setVisibility(View.VISIBLE); + statsMessage.setText(getString(R.string.danar_stats_olddata_Message)); + + } else { + tl.setBackgroundColor(Color.TRANSPARENT); + } + + Collections.reverse(historyList); + + i = 0; + + for (DanaRHistoryRecord record : historyList) { + double tdd = record.getRecordDailyBolus() + record.getRecordDailyBasal(); + if (i == 0) { + weighted03 = tdd; + weighted05 = tdd; + weighted07 = tdd; + + } else { + weighted07 = (weighted07 * 0.3 + tdd * 0.7); + weighted05 = (weighted05 * 0.5 + tdd * 0.5); + weighted03 = (weighted03 * 0.7 + tdd * 0.3); + } + i++; + } + + // Create the exptable row + TableRow etr = new TableRow(DanaRStatsActivity.this); + if (i % 2 != 0) etr.setBackgroundColor(Color.DKGRAY); + etr.setId(1100 + i); + etr.setLayoutParams(new TableLayout.LayoutParams( + TableLayout.LayoutParams.MATCH_PARENT, + TableLayout.LayoutParams.WRAP_CONTENT)); + + // Here create the TextView dynamically + TextView labelWEIGHT = new TextView(DanaRStatsActivity.this); + labelWEIGHT.setId(1200 + i); + labelWEIGHT.setText("0.3\n" + "0.5\n" + "0.7"); + labelWEIGHT.setTextColor(Color.WHITE); + etr.addView(labelWEIGHT); + + TextView labelEXPTDD = new TextView(DanaRStatsActivity.this); + labelEXPTDD.setId(1300 + i); + labelEXPTDD.setText(DecimalFormatter.to2Decimal(weighted03) + + " U\n" + DecimalFormatter.to2Decimal(weighted05) + + " U\n" + DecimalFormatter.to2Decimal(weighted07) + " U"); + labelEXPTDD.setTextColor(Color.WHITE); + etr.addView(labelEXPTDD); + + TextView labelEXPRATIO = new TextView(DanaRStatsActivity.this); + labelEXPRATIO.setId(1400 + i); + labelEXPRATIO.setText(Math.round(100 * weighted03 / magicNumber) + " %\n" + + Math.round(100 * weighted05 / magicNumber) + " %\n" + + Math.round(100 * weighted07 / magicNumber) + " %"); + labelEXPRATIO.setTextColor(Color.WHITE); + etr.addView(labelEXPRATIO); + + // add exponentail rows to tables + etl.addView(etr, new TableLayout.LayoutParams( + TableLayout.LayoutParams.MATCH_PARENT, + TableLayout.LayoutParams.WRAP_CONTENT)); + } + }); + } + + private void cleanTable(TableLayout table) { + int childCount = table.getChildCount(); + // Remove all rows except the first one + if (childCount > 1) { + table.removeViews(1, childCount - 1); + } + } + + @Subscribe + public void onStatusEvent(final EventDanaRSyncStatus s) { + log.debug("EventDanaRSyncStatus: " + s.message); + runOnUiThread( + new Runnable() { + @Override + public void run() { + statusView.setText(s.message); + } + }); + } + + @Subscribe + public void onStatusEvent(final EventPumpStatusChanged c) { + runOnUiThread( + new Runnable() { + @Override + public void run() { + statusView.setText(c.textStatus()); + } + } + ); + } +} \ No newline at end of file diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRv2/SerialIOThread.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRv2/SerialIOThread.java new file mode 100644 index 0000000000..dced6d9485 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRv2/SerialIOThread.java @@ -0,0 +1,228 @@ +package info.nightscout.androidaps.plugins.PumpDanaRv2; + +import android.bluetooth.BluetoothSocket; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.util.concurrent.Executors; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.ScheduledFuture; +import java.util.concurrent.TimeUnit; + +import info.nightscout.androidaps.Config; +import info.nightscout.androidaps.plugins.PumpDanaR.comm.MessageBase; +import info.nightscout.androidaps.plugins.PumpDanaRv2.comm.MessageHashTable; +import info.nightscout.utils.CRC; + +/** + * Created by mike on 17.07.2016. + */ +public class SerialIOThread extends Thread { + private static Logger log = LoggerFactory.getLogger(SerialIOThread.class); + + private InputStream mInputStream = null; + private OutputStream mOutputStream = null; + private BluetoothSocket mRfCommSocket; + + private static final ScheduledExecutorService worker = Executors.newSingleThreadScheduledExecutor(); + private static ScheduledFuture scheduledDisconnection = null; + + private boolean mKeepRunning = true; + private byte[] mReadBuff = new byte[0]; + + MessageBase processedMessage; + + public SerialIOThread(BluetoothSocket rfcommSocket) { + super(SerialIOThread.class.toString()); + + mRfCommSocket = rfcommSocket; + try { + mOutputStream = mRfCommSocket.getOutputStream(); + mInputStream = mRfCommSocket.getInputStream(); + } catch (IOException e) { + e.printStackTrace(); + } + this.start(); + } + + @Override + public final void run() { + try { + while (mKeepRunning) { + int availableBytes = mInputStream.available(); + // Ask for 1024 byte (or more if available) + byte[] newData = new byte[Math.max(1024, availableBytes)]; + int gotBytes = mInputStream.read(newData); + // When we are here there is some new data available + appendToBuffer(newData, gotBytes); + + // process all messages we already got + while (mReadBuff.length > 3) { // 3rd byte is packet size. continue only if we an determine packet size + byte[] extractedBuff = cutMessageFromBuffer(); + if (extractedBuff == null) break; // message is not complete in buffer (wrong packet calls disconnection) + + int command = (extractedBuff[5] & 0xFF) | ((extractedBuff[4] << 8) & 0xFF00); + + MessageBase message; + if (processedMessage != null && processedMessage.getCommand() == command) { + message = processedMessage; + } else { + // get it from hash table + message = MessageHashTable.findMessage(command); + } + + if (Config.logDanaMessageDetail) + log.debug("<<<<< " + message.getMessageName() + " " + message.toHexString(extractedBuff)); + + // process the message content + message.received = true; + message.handleMessage(extractedBuff); + synchronized (message) { + message.notify(); + } + scheduleDisconnection(); + } + } + } catch (Exception e) { + if (Config.logDanaSerialEngine && e.getMessage().indexOf("bt socket closed") < 0) + log.error("Thread exception: ", e); + mKeepRunning = false; + } + disconnect("EndOfLoop"); + } + + void appendToBuffer(byte[] newData, int gotBytes) { + // add newData to mReadBuff + byte[] newReadBuff = new byte[mReadBuff.length + gotBytes]; + System.arraycopy(mReadBuff, 0, newReadBuff, 0, mReadBuff.length); + System.arraycopy(newData, 0, newReadBuff, mReadBuff.length, gotBytes); + mReadBuff = newReadBuff; + } + + byte[] cutMessageFromBuffer() { + if (mReadBuff[0] == (byte) 0x7E && mReadBuff[1] == (byte) 0x7E) { + int length = (mReadBuff[2] & 0xFF) + 7; + // Check if we have enough data + if (mReadBuff.length < length) { + return null; + } + if (mReadBuff[length - 2] != (byte) 0x2E || mReadBuff[length - 1] != (byte) 0x2E) { + log.error("wrong packet lenght=" + length + " data " + MessageBase.toHexString(mReadBuff)); + disconnect("wrong packet"); + return null; + } + + short crc = CRC.getCrc16(mReadBuff, 3, length - 7); + byte crcByte0 = (byte) (crc >> 8 & 0xFF); + byte crcByte1 = (byte) (crc & 0xFF); + + byte crcByte0received = mReadBuff[length - 4]; + byte crcByte1received = mReadBuff[length - 3]; + + if (crcByte0 != crcByte0received || crcByte1 != crcByte1received) { + log.error("CRC Error" + String.format("%02x ", crcByte0) + String.format("%02x ", crcByte1) + String.format("%02x ", crcByte0received) + String.format("%02x ", crcByte1received)); + disconnect("crc error"); + return null; + } + // Packet is verified here. extract data + byte[] extractedBuff = new byte[length]; + System.arraycopy(mReadBuff, 0, extractedBuff, 0, length); + // remove extracted data from read buffer + byte[] unprocessedData = new byte[mReadBuff.length - length]; + System.arraycopy(mReadBuff, length, unprocessedData, 0, unprocessedData.length); + mReadBuff = unprocessedData; + return extractedBuff; + } else { + log.error("Wrong beginning of packet len=" + mReadBuff.length + " " + MessageBase.toHexString(mReadBuff)); + disconnect("Wrong beginning of packet"); + return null; + } + } + + public synchronized void sendMessage(MessageBase message) { + if (!mRfCommSocket.isConnected()) { + log.error("Socket not connected on sendMessage"); + return; + } + processedMessage = message; + + byte[] messageBytes = message.getRawMessageBytes(); + if (Config.logDanaSerialEngine) + log.debug(">>>>> " + message.getMessageName() + " " + message.toHexString(messageBytes)); + + try { + mOutputStream.write(messageBytes); + } catch (Exception e) { + log.error("sendMessage write exception: ", e); + e.printStackTrace(); + } + + synchronized (message) { + try { + message.wait(5000); + } catch (InterruptedException e) { + log.error("sendMessage InterruptedException", e); + e.printStackTrace(); + } + } + + try { + Thread.sleep(200); + } catch (InterruptedException e) { + } + if (!message.received) { + log.warn("Reply not received " + message.getMessageName()); + if (message.getCommand() == 0xF0F1) { + DanaRv2Plugin.getDanaRPump().isNewPump = false; + log.debug("Old firmware detected"); + } + } + scheduleDisconnection(); + } + + public void scheduleDisconnection() { + class DisconnectRunnable implements Runnable { + public void run() { + disconnect("scheduleDisconnection"); + scheduledDisconnection = null; + } + } + // prepare task for execution in 5 sec + // cancel waiting task to prevent sending multiple disconnections + if (scheduledDisconnection != null) + scheduledDisconnection.cancel(false); + Runnable task = new DisconnectRunnable(); + final int sec = 5; + scheduledDisconnection = worker.schedule(task, sec, TimeUnit.SECONDS); + } + + public void disconnect(String reason) { + mKeepRunning = false; + try { + mInputStream.close(); + } catch (Exception e) { + if (Config.logDanaSerialEngine) log.debug(e.getMessage()); + } + try { + mOutputStream.close(); + } catch (Exception e) { + if (Config.logDanaSerialEngine) log.debug(e.getMessage()); + } + try { + mRfCommSocket.close(); + } catch (Exception e) { + if (Config.logDanaSerialEngine) log.debug(e.getMessage()); + } + try { + System.runFinalization(); + } catch (Exception e) { + if (Config.logDanaSerialEngine) log.debug(e.getMessage()); + } + if (Config.logDanaSerialEngine) log.debug("Disconnected: " + reason); + } + +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRv2/comm/MessageHashTable.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRv2/comm/MessageHashTable.java new file mode 100644 index 0000000000..270b108c71 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRv2/comm/MessageHashTable.java @@ -0,0 +1,140 @@ +package info.nightscout.androidaps.plugins.PumpDanaRv2.comm; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.HashMap; + +import info.nightscout.androidaps.plugins.PumpDanaR.comm.MessageBase; +import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgBolusProgress; +import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgBolusStart; +import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgBolusStop; +import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgCheckValue; +import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgError; +import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgHistoryAlarm; +import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgHistoryAll; +import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgHistoryAllDone; +import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgHistoryBasalHour; +import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgHistoryBolus; +import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgHistoryCarbo; +import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgHistoryDailyInsulin; +import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgHistoryDone; +import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgHistoryError; +import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgHistoryGlucose; +import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgHistoryNew; +import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgHistoryNewDone; +import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgHistoryRefill; +import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgHistorySuspend; +import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgInitConnStatusBasic; +import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgInitConnStatusBolus; +import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgInitConnStatusOption; +import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgInitConnStatusTime; +import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgPCCommStart; +import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgPCCommStop; +import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgSetActivateBasalProfile; +import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgSetBasalProfile; +import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgSetCarbsEntry; +import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgSetExtendedBolusStart; +import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgSetExtendedBolusStop; +import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgSetSingleBasalProfile; +import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgSetTempBasalStart; +import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgSetTempBasalStop; +import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgSettingActiveProfile; +import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgSettingBasal; +import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgSettingBasalProfileAll; +import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgSettingGlucose; +import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgSettingMaxValues; +import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgSettingMeal; +import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgSettingProfileRatios; +import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgSettingProfileRatiosAll; +import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgSettingPumpTime; +import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgSettingShippingInfo; +import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgSettingUserOptions; +import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgStatus; +import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgStatusBasic; +import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgStatusBolusExtended; +import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgStatusProfile; +import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgStatusTempBasal; + + +/** + * Created by mike on 28.05.2016. + */ +public class MessageHashTable { + private static Logger log = LoggerFactory.getLogger(MessageHashTable.class); + + public static HashMap messages = null; + + static { + if (messages == null) { + messages = new HashMap(); + put(new MsgBolusStop()); // 0x0101 CMD_MEALINS_STOP + put(new MsgBolusStart()); // 0x0102 CMD_MEALINS_START_DATA + put(new MsgBolusProgress()); // 0x0202 CMD_PUMP_THIS_REMAINDER_MEAL_INS + put(new MsgStatusProfile()); // 0x0204 CMD_PUMP_CALCULATION_SETTING + put(new MsgStatusTempBasal()); // 0x0205 CMD_PUMP_EXERCISE_MODE + put(new MsgStatusBolusExtended()); // 0x0207 CMD_PUMP_EXPANS_INS_I + put(new MsgStatusBasic()); // 0x020A CMD_PUMP_INITVIEW_I + put(new MsgStatus()); // 0x020B CMD_PUMP_STATUS + put(new MsgInitConnStatusTime()); // 0x0301 CMD_PUMPINIT_TIME_INFO + put(new MsgInitConnStatusBolus()); // 0x0302 CMD_PUMPINIT_BOLUS_INFO + put(new MsgInitConnStatusBasic()); // 0x0303 CMD_PUMPINIT_INIT_INFO + put(new MsgInitConnStatusOption()); // 0x0304 CMD_PUMPINIT_OPTION + put(new MsgSetTempBasalStart()); // 0x0401 CMD_PUMPSET_EXERCISE_S + put(new MsgSetCarbsEntry()); // 0x0402 CMD_PUMPSET_HIS_S + put(new MsgSetTempBasalStop()); // 0x0403 CMD_PUMPSET_EXERCISE_STOP + put(new MsgSetExtendedBolusStop()); // 0x0406 CMD_PUMPSET_EXPANS_INS_STOP + put(new MsgSetExtendedBolusStart()); // 0x0407 CMD_PUMPSET_EXPANS_INS_S + put(new MsgError()); // 0x0601 CMD_PUMPOWAY_SYSTEM_STATUS + put(new MsgPCCommStart()); // 0x3001 CMD_CONNECT + put(new MsgPCCommStop()); // 0x3002 CMD_DISCONNECT + put(new MsgHistoryBolus()); // 0x3101 CMD_HISTORY_MEAL_INS + put(new MsgHistoryDailyInsulin()); // 0x3102 CMD_HISTORY_DAY_INS + put(new MsgHistoryGlucose()); // 0x3104 CMD_HISTORY_GLUCOSE + put(new MsgHistoryAlarm()); // 0x3105 CMD_HISTORY_ALARM + put(new MsgHistoryError()); // 0x3106 CMD_HISTORY_ERROR + put(new MsgHistoryCarbo()); // 0x3107 CMD_HISTORY_CARBOHY + put(new MsgHistoryRefill()); // 0x3108 CMD_HISTORY_REFILL + put(new MsgHistorySuspend()); // 0x3109 CMD_HISTORY_SUSPEND + put(new MsgHistoryBasalHour()); // 0x310A CMD_HISTORY_BASAL_HOUR + put(new MsgHistoryDone()); // 0x31F1 CMD_HISTORY_DONT_USED + put(new MsgSettingBasal()); // 0x3202 CMD_SETTING_V_BASAL_INS_I + put(new MsgSettingMeal()); // 0x3203 CMD_SETTING_V_MEAL_SETTING_I + put(new MsgSettingProfileRatios()); // 0x3204 CMD_SETTING_V_CCC_I + put(new MsgSettingMaxValues()); // 0x3205 CMD_SETTING_V_MAX_VALUE_I + put(new MsgSettingBasalProfileAll()); // 0x3206 CMD_SETTING_V_BASAL_PROFILE_ALL + put(new MsgSettingShippingInfo()); // 0x3207 CMD_SETTING_V_SHIPPING_I + put(new MsgSettingGlucose()); // 0x3209 CMD_SETTING_V_GLUCOSEandEASY + put(new MsgSettingPumpTime()); // 0x320A CMD_SETTING_V_TIME_I + put(new MsgSettingUserOptions()); // 0x320B CMD_SETTING_V_USER_OPTIONS + put(new MsgSettingActiveProfile()); // 0x320C CMD_SETTING_V_PROFILE_NUMBER + put(new MsgSettingProfileRatiosAll()); // 0x320D CMD_SETTING_V_CIR_CF_VALUE + put(new MsgSetSingleBasalProfile()); // 0x3302 CMD_SETTING_BASAL_INS_S + put(new MsgSetBasalProfile()); // 0x3306 CMD_SETTING_BASAL_PROFILE_S + put(new MsgSetActivateBasalProfile()); // 0x330C CMD_SETTING_PROFILE_NUMBER_S + put(new MsgHistoryAllDone()); // 0x41F1 CMD_HISTORY_ALL_DONE + put(new MsgHistoryAll()); // 0x41F2 CMD_HISTORY_ALL + put(new MsgHistoryNewDone()); // 0x42F1 CMD_HISTORY_NEW_DONE + put(new MsgHistoryNew()); // 0x42F2 CMD_HISTORY_NEW + put(new MsgCheckValue()); // 0xF0F1 CMD_PUMP_CHECK_VALUE + put(new MsgStatusAPSTempBasal()); // 0xE001 CMD_PUMP_APSTEMP_VALUE + put(new MsgSetAPSTempBasalStart()); // 0xE002 CMD_PUMPSET_APSTEMP + put(new MsgHistoryEvents()); // 0xE003 CMD_HISTORY_EVENTS + } + } + + public static void put(MessageBase message) { + int command = message.getCommand(); + //String name = MessageOriginalNames.getName(command); + messages.put(command, message); + //log.debug(String.format("%04x ", command) + " " + name); + } + + public static MessageBase findMessage(Integer command) { + if (messages.containsKey(command)) { + return messages.get(command); + } else { + return new MessageBase(); + } + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRv2/comm/MsgCheckValue.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRv2/comm/MsgCheckValue.java new file mode 100644 index 0000000000..1b44c604aa --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRv2/comm/MsgCheckValue.java @@ -0,0 +1,70 @@ +package info.nightscout.androidaps.plugins.PumpDanaRv2.comm; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import info.nightscout.androidaps.Config; +import info.nightscout.androidaps.MainApp; +import info.nightscout.androidaps.R; +import info.nightscout.androidaps.events.EventRefreshGui; +import info.nightscout.androidaps.interfaces.PluginBase; +import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPlugin; +import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPump; +import info.nightscout.androidaps.plugins.PumpDanaR.comm.MessageBase; +import info.nightscout.androidaps.plugins.PumpDanaRKorean.DanaRKoreanPlugin; +import info.nightscout.androidaps.plugins.PumpDanaRv2.DanaRv2Plugin; +import info.nightscout.utils.ToastUtils; + +/** + * Created by mike on 30.06.2016. + */ +public class MsgCheckValue extends MessageBase { + private static Logger log = LoggerFactory.getLogger(MsgCheckValue.class); + + public MsgCheckValue() { + SetCommand(0xF0F1); + } + + @Override + public void handleMessage(byte[] bytes) { + DanaRPump pump = DanaRPump.getInstance(); + + pump.isNewPump = true; + log.debug("New firmware confirmed"); + + pump.model = intFromBuff(bytes, 0, 1); + pump.protocol = intFromBuff(bytes, 1, 1); + pump.productCode = intFromBuff(bytes, 2, 1); + if (pump.model != DanaRPump.EXPORT_MODEL) { + ToastUtils.showToastInUiThread(MainApp.instance().getApplicationContext(), MainApp.sResources.getString(R.string.wrongpumpdriverselected), R.raw.error); + ((DanaRv2Plugin) MainApp.getSpecificPlugin(DanaRv2Plugin.class)).doDisconnect("Wrong Model"); + log.debug("Wrong model selected"); + } + + if (pump.protocol != 2) { + ToastUtils.showToastInUiThread(MainApp.instance().getApplicationContext(),MainApp.sResources.getString(R.string.wrongpumpdriverselected), R.raw.error); + ((DanaRv2Plugin)MainApp.getSpecificPlugin(DanaRKoreanPlugin.class)).doDisconnect("Wrong Model"); + log.debug("Wrong model selected. Switching to non APS DanaR"); + (MainApp.getSpecificPlugin(DanaRv2Plugin.class)).setFragmentEnabled(PluginBase.PUMP, false); + (MainApp.getSpecificPlugin(DanaRv2Plugin.class)).setFragmentVisible(PluginBase.PUMP, false); + (MainApp.getSpecificPlugin(DanaRPlugin.class)).setFragmentEnabled(PluginBase.PUMP, true); + (MainApp.getSpecificPlugin(DanaRPlugin.class)).setFragmentVisible(PluginBase.PUMP, true); + + //If profile coming from pump, switch it as well + if(MainApp.getSpecificPlugin(DanaRv2Plugin.class).isEnabled(PluginBase.PROFILE)){ + (MainApp.getSpecificPlugin(DanaRv2Plugin.class)).setFragmentEnabled(PluginBase.PROFILE, false); + (MainApp.getSpecificPlugin(DanaRPlugin.class)).setFragmentEnabled(PluginBase.PROFILE, true); + } + + MainApp.getConfigBuilder().storeSettings(); + MainApp.bus().post(new EventRefreshGui(false)); + return; + } + if (Config.logDanaMessageDetail) { + log.debug("Model: " + String.format("%02X ", pump.model)); + log.debug("Protocol: " + String.format("%02X ", pump.protocol)); + log.debug("Product Code: " + String.format("%02X ", pump.productCode)); + } + } + +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRv2/comm/MsgHistoryEvents.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRv2/comm/MsgHistoryEvents.java new file mode 100644 index 0000000000..ea3a9e2fee --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRv2/comm/MsgHistoryEvents.java @@ -0,0 +1,95 @@ +package info.nightscout.androidaps.plugins.PumpDanaRv2.comm; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.Date; +import java.util.GregorianCalendar; + +import info.nightscout.androidaps.plugins.PumpDanaR.comm.MessageBase; +import info.nightscout.utils.DateUtil; + +public class MsgHistoryEvents extends MessageBase { + private static Logger log = LoggerFactory.getLogger(MsgHistoryEvents.class); + public boolean done; + + public MsgHistoryEvents(Date from) { + SetCommand(0xE003); + GregorianCalendar gfrom = new GregorianCalendar(); + gfrom.setTimeInMillis(from.getTime()); + AddParamDate(gfrom); + done = false; + } + + public MsgHistoryEvents() { + SetCommand(0xE003); + AddParamByte((byte) 0); + AddParamByte((byte) 1); + AddParamByte((byte) 1); + AddParamByte((byte) 0); + AddParamByte((byte) 0); + done = false; + } + + @Override + public void handleMessage(byte[] bytes) { + byte recordCode = (byte) intFromBuff(bytes, 0, 1); + + // Last record + if (recordCode == (byte) 0xFF) { + done = true; + return; + } + + Date datetime = dateTimeFromBuff(bytes, 1); // 5 bytes + int param1 = intFromBuff(bytes, 6, 2); + int param2 = intFromBuff(bytes, 8, 2); + + switch (recordCode) { + case 1: + log.debug("EVENT TEMPSTART (" + recordCode + ") " + DateUtil.dateAndTimeString(datetime) + " Ratio: " + param1 + "% Duration: " + param2 + "min"); + break; + case 2: + log.debug("EVENT TEMPSTOP (" + recordCode + ") " + DateUtil.dateAndTimeString(datetime)); + break; + case 3: + log.debug("EVENT EXTENDEDSTART (" + recordCode + ") " + DateUtil.dateAndTimeString(datetime) + " Amount: " + (param1 / 100d) + "U Duration: " + param2 + "min"); + break; + case 4: + log.debug("EVENT EXTENDEDSTOP (" + recordCode + ") " + DateUtil.dateAndTimeString(datetime) + " Delivered: " + (param1 / 100d) + "U RealDuration: " + param2 + "min"); + break; + case 5: + log.debug("EVENT BOLUS (" + recordCode + ") " + DateUtil.dateAndTimeString(datetime) + " Bolus: " + (param1 / 100d) + "U Duration: " + param2 + "min"); + break; + case 6: + log.debug("EVENT DUALBOLUS (" + recordCode + ") " + DateUtil.dateAndTimeString(datetime) + " Bolus: " + (param1 / 100d) + "U Duration: " + param2 + "min"); + break; + case 7: + log.debug("EVENT DUALEXTENDEDSTART (" + recordCode + ") " + DateUtil.dateAndTimeString(datetime) + " Amount: " + (param1 / 100d) + "U Duration: " + param2 + "min"); + break; + case 8: + log.debug("EVENT DUALEXTENDEDSTOP (" + recordCode + ") " + DateUtil.dateAndTimeString(datetime) + " Delivered: " + (param1 / 100d) + "U RealDuration: " + param2 + "min"); + break; + case 9: + log.debug("EVENT SUSPENDON (" + recordCode + ") " + DateUtil.dateAndTimeString(datetime)); + break; + case 10: + log.debug("EVENT SUSPENDOFF (" + recordCode + ") " + DateUtil.dateAndTimeString(datetime)); + break; + case 11: + log.debug("EVENT REFILL (" + recordCode + ") " + DateUtil.dateAndTimeString(datetime) + " Amount: " + param1 + "U"); + break; + case 12: + log.debug("EVENT PRIME (" + recordCode + ") " + DateUtil.dateAndTimeString(datetime) + " Amount: " + param1 + "U"); + break; + case 13: + log.debug("EVENT PROFILECHANGE (" + recordCode + ") " + DateUtil.dateAndTimeString(datetime) + " No: " + param1 + "U CurrentRate: " + param2 + "U/h"); + break; + default: + log.debug("Event: " + recordCode + " " + DateUtil.dateAndTimeString(datetime) + " Param1: " + param1 + " Param2: " + param2); + break; + } + + return; + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRv2/comm/MsgSetAPSTempBasalStart.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRv2/comm/MsgSetAPSTempBasalStart.java new file mode 100644 index 0000000000..e366f76441 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRv2/comm/MsgSetAPSTempBasalStart.java @@ -0,0 +1,41 @@ +package info.nightscout.androidaps.plugins.PumpDanaRv2.comm; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import info.nightscout.androidaps.Config; +import info.nightscout.androidaps.plugins.PumpDanaR.comm.MessageBase; + +public class MsgSetAPSTempBasalStart extends MessageBase { + private static Logger log = LoggerFactory.getLogger(MsgSetAPSTempBasalStart.class); + + public MsgSetAPSTempBasalStart() { + SetCommand(0xE002); + } + + public MsgSetAPSTempBasalStart(int percent) { + this(); + + //HARDCODED LIMITS + if (percent < 0) percent = 0; + if (percent > 500) percent = 500; + + AddParamInt(percent); + + if (Config.logDanaMessageDetail) + log.debug("APS Temp basal start percent: " + percent + " duration 15 min"); + } + + public void handleMessage(byte[] bytes) { + int result = intFromBuff(bytes, 0, 1); + if (result != 1) { + failed = true; + log.debug("Set APS temp basal start result: " + result + " FAILED!!!"); + } else { + if (Config.logDanaMessageDetail) + log.debug("Set APS temp basal start result: " + result); + } + } + + +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRv2/comm/MsgStatusAPSTempBasal.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRv2/comm/MsgStatusAPSTempBasal.java new file mode 100644 index 0000000000..40e8b2f7d8 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRv2/comm/MsgStatusAPSTempBasal.java @@ -0,0 +1,34 @@ +package info.nightscout.androidaps.plugins.PumpDanaRv2.comm; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import info.nightscout.androidaps.Config; +import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPump; +import info.nightscout.androidaps.plugins.PumpDanaR.comm.MessageBase; + +public class MsgStatusAPSTempBasal extends MessageBase { + private static Logger log = LoggerFactory.getLogger(MsgStatusAPSTempBasal.class); + + public MsgStatusAPSTempBasal() { + SetCommand(0xE001); + } + + public void handleMessage(byte[] bytes) { + double iob = intFromBuff(bytes, 0, 2) / 100d; + int tempBasalPercent = intFromBuff(bytes, 2, 2); + + DanaRPump pump = DanaRPump.getInstance(); + pump.isTempBasalInProgress = tempBasalPercent != 100; + pump.tempBasalPercent = tempBasalPercent; + pump.iob = iob; + + + if (Config.logDanaMessageDetail) { + log.debug("Is APS temp basal running: " + pump.isTempBasalInProgress); + log.debug("Current APS temp basal percent: " + tempBasalPercent); + log.debug("Current pump IOB: " + iob); + } + } + +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRv2/comm/MsgStatusBolusExtended.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRv2/comm/MsgStatusBolusExtended.java new file mode 100644 index 0000000000..83a8454f81 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRv2/comm/MsgStatusBolusExtended.java @@ -0,0 +1,113 @@ +package info.nightscout.androidaps.plugins.PumpDanaRv2.comm; + +import android.support.annotation.NonNull; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.sql.SQLException; +import java.util.Date; + +import info.nightscout.androidaps.Config; +import info.nightscout.androidaps.MainApp; +import info.nightscout.androidaps.db.TempBasal; +import info.nightscout.androidaps.events.EventTempBasalChange; +import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPump; +import info.nightscout.androidaps.plugins.PumpDanaR.comm.MessageBase; +import info.nightscout.androidaps.plugins.PumpDanaRv2.DanaRv2Plugin; + +public class MsgStatusBolusExtended extends MessageBase { + private static Logger log = LoggerFactory.getLogger(MsgStatusBolusExtended.class); + + public MsgStatusBolusExtended() { + SetCommand(0x0207); + } + + public void handleMessage(byte[] bytes) { + boolean isExtendedInProgress = intFromBuff(bytes, 0, 1) == 1; + int extendedBolusHalfHours = intFromBuff(bytes, 1, 1); + int extendedBolusMinutes = extendedBolusHalfHours * 30; + + double extendedBolusAmount = intFromBuff(bytes, 2, 2) / 100d; + int extendedBolusSoFarInSecs = intFromBuff(bytes, 4, 3); + + int extendedBolusSoFarInMinutes = extendedBolusSoFarInSecs / 60; + double extendedBolusAbsoluteRate = isExtendedInProgress ? extendedBolusAmount / extendedBolusMinutes * 60 : 0d; + Date extendedBolusStart = isExtendedInProgress ? getDateFromSecAgo(extendedBolusSoFarInSecs) : new Date(0); + int extendedBolusRemainingMinutes = extendedBolusMinutes - extendedBolusSoFarInMinutes; + + DanaRPump pump = DanaRPump.getInstance(); + pump.isExtendedInProgress = isExtendedInProgress; + pump.extendedBolusMinutes = extendedBolusMinutes; + pump.extendedBolusAmount = extendedBolusAmount; + pump.extendedBolusSoFarInMinutes = extendedBolusSoFarInMinutes; + pump.extendedBolusAbsoluteRate = extendedBolusAbsoluteRate; + pump.extendedBolusStart = extendedBolusStart; + pump.extendedBolusRemainingMinutes = extendedBolusRemainingMinutes; + + updateExtendedBolusInDB(); + + if (Config.logDanaMessageDetail) { + log.debug("Is extended bolus running: " + isExtendedInProgress); + log.debug("Extended bolus min: " + extendedBolusMinutes); + log.debug("Extended bolus amount: " + extendedBolusAmount); + log.debug("Extended bolus so far in minutes: " + extendedBolusSoFarInMinutes); + log.debug("Extended bolus absolute rate: " + extendedBolusAbsoluteRate); + log.debug("Extended bolus start: " + extendedBolusStart); + log.debug("Extended bolus remaining minutes: " + extendedBolusRemainingMinutes); + } + } + + @NonNull + private Date getDateFromSecAgo(int tempBasalAgoSecs) { + return new Date((long) (Math.ceil(new Date().getTime() / 1000d) - tempBasalAgoSecs) * 1000); + } + + public static void updateExtendedBolusInDB() { + DanaRv2Plugin danaRPlugin = (DanaRv2Plugin) MainApp.getSpecificPlugin(DanaRv2Plugin.class); + DanaRPump pump = DanaRPump.getInstance(); + Date now = new Date(); + + try { + + if (danaRPlugin.isExtendedBoluslInProgress()) { + TempBasal extendedBolus = danaRPlugin.getExtendedBolus(); + if (pump.isExtendedInProgress) { + if (extendedBolus.absolute != pump.extendedBolusAbsoluteRate) { + // Close current extended + extendedBolus.timeEnd = now; + MainApp.getDbHelper().getDaoTempBasals().update(extendedBolus); + // Create new + TempBasal newExtended = new TempBasal(); + newExtended.timeStart = now; + newExtended.absolute = pump.extendedBolusAbsoluteRate; + newExtended.isAbsolute = true; + newExtended.duration = pump.extendedBolusMinutes; + newExtended.isExtended = true; + MainApp.getDbHelper().getDaoTempBasals().create(newExtended); + MainApp.bus().post(new EventTempBasalChange()); + } + } else { + // Close curent temp basal + extendedBolus.timeEnd = now; + MainApp.getDbHelper().getDaoTempBasals().update(extendedBolus); + MainApp.bus().post(new EventTempBasalChange()); + } + } else { + if (pump.isExtendedInProgress) { + // Create new + TempBasal newExtended = new TempBasal(); + newExtended.timeStart = now; + newExtended.absolute = pump.extendedBolusAbsoluteRate; + newExtended.isAbsolute = true; + newExtended.duration = pump.extendedBolusMinutes; + newExtended.isExtended = true; + MainApp.getDbHelper().getDaoTempBasals().create(newExtended); + MainApp.bus().post(new EventTempBasalChange()); + } + } + } catch (SQLException e) { + e.printStackTrace(); + } + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRv2/comm/MsgStatusTempBasal.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRv2/comm/MsgStatusTempBasal.java new file mode 100644 index 0000000000..844d303bb4 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRv2/comm/MsgStatusTempBasal.java @@ -0,0 +1,104 @@ +package info.nightscout.androidaps.plugins.PumpDanaRv2.comm; + +import android.support.annotation.NonNull; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.sql.SQLException; +import java.util.Date; + +import info.nightscout.androidaps.Config; +import info.nightscout.androidaps.MainApp; +import info.nightscout.androidaps.db.TempBasal; +import info.nightscout.androidaps.events.EventTempBasalChange; +import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPump; +import info.nightscout.androidaps.plugins.PumpDanaR.comm.MessageBase; +import info.nightscout.androidaps.plugins.PumpDanaRv2.DanaRv2Plugin; + +public class MsgStatusTempBasal extends MessageBase { + private static Logger log = LoggerFactory.getLogger(MsgStatusTempBasal.class); + + public MsgStatusTempBasal() { + SetCommand(0x0205); + } + + public void handleMessage(byte[] bytes) { + boolean isTempBasalInProgress = intFromBuff(bytes, 0, 1) == 1; + int tempBasalPercent = intFromBuff(bytes, 1, 1); + int tempBasalTotalSec = intFromBuff(bytes, 2, 1) * 60 * 60; + int tempBasalRunningSeconds = intFromBuff(bytes, 3, 3); + int tempBasalRemainingMin = (tempBasalTotalSec - tempBasalRunningSeconds) / 60; + Date tempBasalStart = isTempBasalInProgress ? getDateFromTempBasalSecAgo(tempBasalRunningSeconds) : new Date(0); + + DanaRPump pump = DanaRPump.getInstance(); + pump.isTempBasalInProgress = isTempBasalInProgress; + pump.tempBasalPercent = tempBasalPercent; + pump.tempBasalRemainingMin = tempBasalRemainingMin; + pump.tempBasalTotalSec = tempBasalTotalSec; + pump.tempBasalStart = tempBasalStart; + + updateTempBasalInDB(); + + if (Config.logDanaMessageDetail) { + log.debug("Is temp basal running: " + isTempBasalInProgress); + log.debug("Current temp basal percent: " + tempBasalPercent); + log.debug("Current temp basal remaining min: " + tempBasalRemainingMin); + log.debug("Current temp basal total sec: " + tempBasalTotalSec); + log.debug("Current temp basal start: " + tempBasalStart); + } + } + + @NonNull + private Date getDateFromTempBasalSecAgo(int tempBasalAgoSecs) { + return new Date((long) (Math.ceil(new Date().getTime() / 1000d) - tempBasalAgoSecs) * 1000); + } + + public static void updateTempBasalInDB() { + DanaRv2Plugin danaRPlugin = (DanaRv2Plugin) MainApp.getSpecificPlugin(DanaRv2Plugin.class); + DanaRPump danaRPump = DanaRPump.getInstance(); + Date now = new Date(); + + try { + + if (danaRPlugin.isTempBasalInProgress()) { + TempBasal tempBasal = danaRPlugin.getTempBasal(); + if (danaRPump.isTempBasalInProgress) { + if (tempBasal.percent != danaRPump.tempBasalPercent) { + // Close current temp basal + tempBasal.timeEnd = now; + MainApp.getDbHelper().getDaoTempBasals().update(tempBasal); + // Create new + TempBasal newTempBasal = new TempBasal(); + newTempBasal.timeStart = now; + newTempBasal.percent = danaRPump.tempBasalPercent; + newTempBasal.isAbsolute = false; + newTempBasal.duration = danaRPump.tempBasalTotalSec / 60; + newTempBasal.isExtended = false; + MainApp.getDbHelper().getDaoTempBasals().create(newTempBasal); + MainApp.bus().post(new EventTempBasalChange()); + } + } else { + // Close current temp basal + tempBasal.timeEnd = now; + MainApp.getDbHelper().getDaoTempBasals().update(tempBasal); + MainApp.bus().post(new EventTempBasalChange()); + } + } else { + if (danaRPump.isTempBasalInProgress) { + // Create new + TempBasal newTempBasal = new TempBasal(); + newTempBasal.timeStart = now; + newTempBasal.percent = danaRPump.tempBasalPercent; + newTempBasal.isAbsolute = false; + newTempBasal.duration = danaRPump.tempBasalTotalSec / 60; + newTempBasal.isExtended = false; + MainApp.getDbHelper().getDaoTempBasals().create(newTempBasal); + MainApp.bus().post(new EventTempBasalChange()); + } + } + } catch (SQLException e) { + e.printStackTrace(); + } + } +} 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 new file mode 100644 index 0000000000..43297bc486 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRv2/services/DanaRv2ExecutionService.java @@ -0,0 +1,559 @@ +package info.nightscout.androidaps.plugins.PumpDanaRv2.services; + +import android.app.Service; +import android.bluetooth.BluetoothAdapter; +import android.bluetooth.BluetoothDevice; +import android.bluetooth.BluetoothSocket; +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; +import android.content.IntentFilter; +import android.os.Binder; +import android.os.IBinder; +import android.os.PowerManager; + +import com.squareup.otto.Subscribe; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.IOException; +import java.util.Calendar; +import java.util.Date; +import java.util.Set; +import java.util.UUID; + +import info.nightscout.androidaps.Config; +import info.nightscout.androidaps.Constants; +import info.nightscout.androidaps.MainApp; +import info.nightscout.androidaps.R; +import info.nightscout.androidaps.db.Treatment; +import info.nightscout.androidaps.events.EventAppExit; +import info.nightscout.androidaps.events.EventInitializationChanged; +import info.nightscout.androidaps.events.EventPreferenceChange; +import info.nightscout.androidaps.events.EventPumpStatusChanged; +import info.nightscout.androidaps.interfaces.PluginBase; +import info.nightscout.androidaps.plugins.NSClientInternal.data.NSProfile; +import info.nightscout.androidaps.plugins.Overview.Notification; +import info.nightscout.androidaps.plugins.Overview.events.EventNewNotification; +import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPump; +import info.nightscout.androidaps.plugins.PumpDanaR.comm.MessageBase; +import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgBolusProgress; +import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgBolusStart; +import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgBolusStop; +import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgCheckValue; +import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgHistoryAlarm; +import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgHistoryBasalHour; +import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgHistoryBolus; +import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgHistoryCarbo; +import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgHistoryDailyInsulin; +import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgHistoryDone; +import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgHistoryError; +import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgHistoryGlucose; +import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgHistoryRefill; +import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgHistorySuspend; +import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgPCCommStart; +import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgPCCommStop; +import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgSetActivateBasalProfile; +import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgSetBasalProfile; +import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgSetCarbsEntry; +import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgSetExtendedBolusStart; +import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgSetExtendedBolusStop; +import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgSetTempBasalStart; +import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgSetTempBasalStop; +import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgSetTime; +import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgSettingActiveProfile; +import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgSettingBasal; +import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgSettingGlucose; +import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgSettingMaxValues; +import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgSettingMeal; +import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgSettingProfileRatios; +import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgSettingProfileRatiosAll; +import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgSettingPumpTime; +import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgSettingShippingInfo; +import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgStatus; +import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgStatusBasic; +import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgStatusBolusExtended; +import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgStatusTempBasal; +import info.nightscout.androidaps.plugins.PumpDanaR.comm.RecordTypes; +import info.nightscout.androidaps.plugins.PumpDanaR.events.EventDanaRBolusStart; +import info.nightscout.androidaps.plugins.PumpDanaR.events.EventDanaRNewStatus; +import info.nightscout.androidaps.plugins.PumpDanaRv2.DanaRv2Plugin; +import info.nightscout.androidaps.plugins.PumpDanaRv2.SerialIOThread; +import info.nightscout.androidaps.plugins.PumpDanaRv2.comm.MsgHistoryEvents; +import info.nightscout.androidaps.plugins.PumpDanaRv2.comm.MsgSetAPSTempBasalStart; +import info.nightscout.androidaps.plugins.PumpDanaRv2.comm.MsgStatusAPSTempBasal; +import info.nightscout.utils.SP; +import info.nightscout.utils.ToastUtils; + +public class DanaRv2ExecutionService extends Service { + private static Logger log = LoggerFactory.getLogger(DanaRv2ExecutionService.class); + + private String devName; + + private SerialIOThread mSerialIOThread; + private BluetoothSocket mRfcommSocket; + private BluetoothDevice mBTDevice; + + private PowerManager.WakeLock mWakeLock; + private IBinder mBinder = new LocalBinder(); + + private DanaRPump danaRPump; + private Treatment bolusingTreatment = null; + + private static Boolean connectionInProgress = false; + private static final Object connectionLock = new Object(); + + private static final UUID SPP_UUID = UUID.fromString("00001101-0000-1000-8000-00805f9b34fb"); + + private BroadcastReceiver receiver = new BroadcastReceiver() { + @Override + public void onReceive(Context context, Intent intent) { + BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE); + String action = intent.getAction(); + if (BluetoothDevice.ACTION_ACL_DISCONNECTED.equals(action)) { + log.debug("Device has disconnected " + device.getName());//Device has disconnected + if (mBTDevice != null && mBTDevice.getName() != null && mBTDevice.getName().equals(device.getName())) { + if (mSerialIOThread != null) { + mSerialIOThread.disconnect("BT disconnection broadcast"); + } + MainApp.bus().post(new EventPumpStatusChanged(EventPumpStatusChanged.DISCONNECTED)); + } + } + } + }; + + public DanaRv2ExecutionService() { + registerBus(); + MainApp.instance().getApplicationContext().registerReceiver(receiver, new IntentFilter(BluetoothDevice.ACTION_ACL_DISCONNECTED)); + danaRPump = DanaRv2Plugin.getDanaRPump(); + + PowerManager powerManager = (PowerManager) MainApp.instance().getApplicationContext().getSystemService(Context.POWER_SERVICE); + mWakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "DanaRv2ExecutionService"); + } + + public class LocalBinder extends Binder { + public DanaRv2ExecutionService getServiceInstance() { + return DanaRv2ExecutionService.this; + } + } + + @Override + public IBinder onBind(Intent intent) { + return mBinder; + } + + @Override + public int onStartCommand(Intent intent, int flags, int startId) { + + return START_STICKY; + } + + private void registerBus() { + try { + MainApp.bus().unregister(this); + } catch (RuntimeException x) { + // Ignore + } + MainApp.bus().register(this); + } + + @Subscribe + public void onStatusEvent(EventAppExit event) { + if (Config.logFunctionCalls) + log.debug("EventAppExit received"); + + if (mSerialIOThread != null) + mSerialIOThread.disconnect("Application exit"); + + MainApp.instance().getApplicationContext().unregisterReceiver(receiver); + + stopSelf(); + if (Config.logFunctionCalls) + log.debug("EventAppExit finished"); + } + + public boolean isConnected() { + return mRfcommSocket != null && mRfcommSocket.isConnected(); + } + + public boolean isConnecting() { + return connectionInProgress; + } + + public void disconnect(String from) { + if (mSerialIOThread != null) + mSerialIOThread.disconnect(from); + } + + public void connect(String from) { + if (danaRPump.password != -1 && danaRPump.password != SP.getInt(R.string.key_danar_password, -1)) { + ToastUtils.showToastInUiThread(MainApp.instance().getApplicationContext(), MainApp.sResources.getString(R.string.wrongpumppassword), R.raw.error); + return; + } + while (isConnected() || isConnecting()) { + if (Config.logDanaBTComm) + log.debug("already connected/connecting from: " + from); + waitMsec(3000); + } + final long maxConnectionTime = 5 * 60 * 1000L; // 5 min + synchronized (connectionLock) { + //log.debug("entering connection while loop"); + connectionInProgress = true; + mWakeLock.acquire(); + getBTSocketForSelectedPump(); + if (mRfcommSocket == null || mBTDevice == null) + return; // Device not found + long startTime = new Date().getTime(); + while (!isConnected() && startTime + maxConnectionTime >= new Date().getTime()) { + long secondsElapsed = (new Date().getTime() - startTime) / 1000L; + MainApp.bus().post(new EventPumpStatusChanged(EventPumpStatusChanged.CONNECTING, (int) secondsElapsed)); + if (Config.logDanaBTComm) + log.debug("connect waiting " + secondsElapsed + "sec from: " + from); + try { + mRfcommSocket.connect(); + } catch (IOException e) { + //e.printStackTrace(); + if (e.getMessage().contains("socket closed")) { + e.printStackTrace(); + break; + } + } + waitMsec(1000); + + if (isConnected()) { + if (mSerialIOThread != null) { + mSerialIOThread.disconnect("Recreate SerialIOThread"); + } + mSerialIOThread = new SerialIOThread(mRfcommSocket); + MainApp.bus().post(new EventPumpStatusChanged(EventPumpStatusChanged.CONNECTED, 0)); + if (!getPumpStatus()) { + mSerialIOThread.disconnect("getPumpStatus failed"); + waitMsec(3000); + if (!MainApp.getSpecificPlugin(DanaRv2Plugin.class).isEnabled(PluginBase.PUMP)) + return; + getBTSocketForSelectedPump(); + startTime = new Date().getTime(); + } + } + } + if (!isConnected()) { + MainApp.bus().post(new EventPumpStatusChanged(EventPumpStatusChanged.DISCONNECTED)); + log.error("Pump connection timed out"); + } + connectionInProgress = false; + mWakeLock.release(); + } + } + + private void getBTSocketForSelectedPump() { + devName = SP.getString(MainApp.sResources.getString(R.string.key_danar_bt_name), ""); + BluetoothAdapter bluetoothAdapter = BluetoothAdapter.getDefaultAdapter(); + + if (bluetoothAdapter != null) { + Set bondedDevices = bluetoothAdapter.getBondedDevices(); + + for (BluetoothDevice device : bondedDevices) { + if (devName.equals(device.getName())) { + mBTDevice = device; + try { + mRfcommSocket = mBTDevice.createRfcommSocketToServiceRecord(SPP_UUID); + } catch (IOException e) { + log.error("Error creating socket: ", e); + } + break; + } + } + } else { + ToastUtils.showToastInUiThread(MainApp.instance().getApplicationContext(), MainApp.sResources.getString(R.string.nobtadapter)); + } + if (mBTDevice == null) { + ToastUtils.showToastInUiThread(MainApp.instance().getApplicationContext(), MainApp.sResources.getString(R.string.devicenotfound)); + } + } + + @Subscribe + public void onStatusEvent(final EventPreferenceChange pch) { + if (mSerialIOThread != null) + mSerialIOThread.disconnect("EventPreferenceChange"); + } + + private boolean getPumpStatus() { + try { + MainApp.bus().post(new EventPumpStatusChanged(MainApp.sResources.getString(R.string.gettingpumpstatus))); + MsgStatus statusMsg = new MsgStatus(); + MsgStatusBasic statusBasicMsg = new MsgStatusBasic(); + MsgStatusTempBasal tempStatusMsg = new MsgStatusTempBasal(); + MsgStatusBolusExtended exStatusMsg = new MsgStatusBolusExtended(); + MsgCheckValue checkValue = new MsgCheckValue(); + + if (danaRPump.isNewPump) { + mSerialIOThread.sendMessage(checkValue); + if (!checkValue.received) { + return false; + } + } + + mSerialIOThread.sendMessage(tempStatusMsg); // do this before statusBasic because here is temp duration + mSerialIOThread.sendMessage(exStatusMsg); + mSerialIOThread.sendMessage(statusMsg); + mSerialIOThread.sendMessage(statusBasicMsg); + + if (!statusMsg.received) { + mSerialIOThread.sendMessage(statusMsg); + } + if (!statusBasicMsg.received) { + mSerialIOThread.sendMessage(statusBasicMsg); + } + if (!tempStatusMsg.received) { + // Load of status of current basal rate failed, give one more try + mSerialIOThread.sendMessage(tempStatusMsg); + } + if (!exStatusMsg.received) { + // Load of status of current extended bolus failed, give one more try + mSerialIOThread.sendMessage(exStatusMsg); + } + + // Check we have really current status of pump + if (!statusMsg.received || !statusBasicMsg.received || !tempStatusMsg.received || !exStatusMsg.received) { + waitMsec(10 * 1000); + log.debug("getPumpStatus failed"); + return false; + } + + Date now = new Date(); + if (danaRPump.lastSettingsRead.getTime() + 60 * 60 * 1000L < now.getTime() || !((DanaRv2Plugin)MainApp.getSpecificPlugin(DanaRv2Plugin.class)).isInitialized()) { + mSerialIOThread.sendMessage(new MsgSettingShippingInfo()); + mSerialIOThread.sendMessage(new MsgSettingActiveProfile()); + mSerialIOThread.sendMessage(new MsgSettingMeal()); + mSerialIOThread.sendMessage(new MsgSettingBasal()); + //0x3201 + mSerialIOThread.sendMessage(new MsgSettingMaxValues()); + mSerialIOThread.sendMessage(new MsgSettingGlucose()); + mSerialIOThread.sendMessage(new MsgSettingPumpTime()); + mSerialIOThread.sendMessage(new MsgSettingActiveProfile()); + mSerialIOThread.sendMessage(new MsgSettingProfileRatios()); + mSerialIOThread.sendMessage(new MsgSettingProfileRatiosAll()); + mSerialIOThread.sendMessage(new MsgSetTime(new Date())); + danaRPump.lastSettingsRead = now; + } + + loadEvents(); + + danaRPump.lastConnection = now; + MainApp.bus().post(new EventDanaRNewStatus()); + MainApp.bus().post(new EventInitializationChanged()); + MainApp.getConfigBuilder().uploadDeviceStatus(); + if (danaRPump.dailyTotalUnits > danaRPump.maxDailyTotalUnits * Constants.dailyLimitWarning ) { + log.debug("Approaching daily limit: " + danaRPump.dailyTotalUnits + "/" + danaRPump.maxDailyTotalUnits); + Notification reportFail = new Notification(Notification.APPROACHING_DAILY_LIMIT, MainApp.sResources.getString(R.string.approachingdailylimit), Notification.URGENT); + MainApp.bus().post(new EventNewNotification(reportFail)); + MainApp.getConfigBuilder().uploadError(MainApp.sResources.getString(R.string.approachingdailylimit) + ": " + danaRPump.dailyTotalUnits + "/" + danaRPump.maxDailyTotalUnits + "U"); + } + } catch (Exception e) { + e.printStackTrace(); + } + return true; + } + + public boolean tempBasal(int percent, int durationInHours) { + connect("tempBasal"); + if (!isConnected()) return false; + MainApp.bus().post(new EventPumpStatusChanged(MainApp.sResources.getString(R.string.settingtempbasal))); + mSerialIOThread.sendMessage(new MsgSetTempBasalStart(percent, durationInHours)); + mSerialIOThread.sendMessage(new MsgStatusTempBasal()); + MainApp.bus().post(new EventPumpStatusChanged(EventPumpStatusChanged.DISCONNECTING)); + return true; + } + + public boolean highTempBasal(int percent) { + connect("highTempBasal"); + if (!isConnected()) return false; + MainApp.bus().post(new EventPumpStatusChanged(MainApp.sResources.getString(R.string.settingtempbasal))); + mSerialIOThread.sendMessage(new MsgSetAPSTempBasalStart(percent)); + mSerialIOThread.sendMessage(new MsgStatusAPSTempBasal()); + mSerialIOThread.sendMessage(new MsgStatusTempBasal()); + MainApp.bus().post(new EventPumpStatusChanged(EventPumpStatusChanged.DISCONNECTING)); + return true; + } + + public boolean tempBasalStop() { + connect("tempBasalStop"); + if (!isConnected()) return false; + MainApp.bus().post(new EventPumpStatusChanged(MainApp.sResources.getString(R.string.stoppingtempbasal))); + mSerialIOThread.sendMessage(new MsgSetTempBasalStop()); + mSerialIOThread.sendMessage(new MsgStatusTempBasal()); + MainApp.bus().post(new EventPumpStatusChanged(EventPumpStatusChanged.DISCONNECTING)); + return true; + } + + public boolean extendedBolus(double insulin, int durationInHalfHours) { + connect("extendedBolus"); + if (!isConnected()) return false; + MainApp.bus().post(new EventPumpStatusChanged(MainApp.sResources.getString(R.string.settingextendedbolus))); + mSerialIOThread.sendMessage(new MsgSetExtendedBolusStart(insulin, (byte) (durationInHalfHours & 0xFF))); + mSerialIOThread.sendMessage(new MsgStatusBolusExtended()); + MainApp.bus().post(new EventPumpStatusChanged(EventPumpStatusChanged.DISCONNECTING)); + return true; + } + + public boolean extendedBolusStop() { + connect("extendedBolusStop"); + if (!isConnected()) return false; + MainApp.bus().post(new EventPumpStatusChanged(MainApp.sResources.getString(R.string.stoppingextendedbolus))); + mSerialIOThread.sendMessage(new MsgSetExtendedBolusStop()); + mSerialIOThread.sendMessage(new MsgStatusBolusExtended()); + MainApp.bus().post(new EventPumpStatusChanged(EventPumpStatusChanged.DISCONNECTING)); + return true; + } + + public boolean bolus(Double amount, int carbs, Treatment t) { + bolusingTreatment = t; + MsgBolusStart start = new MsgBolusStart(amount); + MsgBolusStop stop = new MsgBolusStop(amount, t); + + connect("bolus"); + if (!isConnected()) return false; + + if (carbs > 0) { + Calendar time = Calendar.getInstance(); + mSerialIOThread.sendMessage(new MsgSetCarbsEntry(time, carbs)); + } + MsgBolusProgress progress = new MsgBolusProgress(amount, t); // initialize static variables + MainApp.bus().post(new EventDanaRBolusStart()); + + if (!stop.stopped) { + mSerialIOThread.sendMessage(start); + } else { + t.insulin = 0d; + return false; + } + while (!stop.stopped && !start.failed) { + waitMsec(100); + if ((new Date().getTime() - progress.lastReceive) > 5 * 1000L) { // if i didn't receive status for more than 5 sec expecting broken comm + stop.stopped = true; + stop.forced = true; + log.debug("Communication stopped"); + } + } + waitMsec(300); + bolusingTreatment = null; + getPumpStatus(); + return true; + } + + public void bolusStop() { + if (Config.logDanaBTComm) + log.debug("bolusStop >>>>> @ " + (bolusingTreatment == null ? "" : bolusingTreatment.insulin)); + MsgBolusStop stop = new MsgBolusStop(); + stop.forced = true; + if (isConnected()) { + mSerialIOThread.sendMessage(stop); + while (!stop.stopped) { + mSerialIOThread.sendMessage(stop); + waitMsec(200); + } + } else { + stop.stopped = true; + } + } + + public boolean carbsEntry(int amount) { + connect("carbsEntry"); + if (!isConnected()) return false; + Calendar time = Calendar.getInstance(); + MsgSetCarbsEntry msg = new MsgSetCarbsEntry(time, amount); + mSerialIOThread.sendMessage(msg); + return true; + } + + public boolean loadHistory(byte type) { + connect("loadHistory"); + if (!isConnected()) return false; + MessageBase msg = null; + switch (type) { + case RecordTypes.RECORD_TYPE_ALARM: + msg = new MsgHistoryAlarm(); + break; + case RecordTypes.RECORD_TYPE_BASALHOUR: + msg = new MsgHistoryBasalHour(); + break; + case RecordTypes.RECORD_TYPE_BOLUS: + msg = new MsgHistoryBolus(); + break; + case RecordTypes.RECORD_TYPE_CARBO: + msg = new MsgHistoryCarbo(); + break; + case RecordTypes.RECORD_TYPE_DAILY: + msg = new MsgHistoryDailyInsulin(); + break; + case RecordTypes.RECORD_TYPE_ERROR: + msg = new MsgHistoryError(); + break; + case RecordTypes.RECORD_TYPE_GLUCOSE: + msg = new MsgHistoryGlucose(); + break; + case RecordTypes.RECORD_TYPE_REFILL: + msg = new MsgHistoryRefill(); + break; + case RecordTypes.RECORD_TYPE_SUSPEND: + msg = new MsgHistorySuspend(); + break; + } + MsgHistoryDone done = new MsgHistoryDone(); + mSerialIOThread.sendMessage(new MsgPCCommStart()); + waitMsec(400); + mSerialIOThread.sendMessage(msg); + while (!done.received && mRfcommSocket.isConnected()) { + waitMsec(100); + } + waitMsec(200); + mSerialIOThread.sendMessage(new MsgPCCommStop()); + return true; + } + + public boolean loadEvents() { + if (!isConnected()) return false; + MsgHistoryEvents msg = new MsgHistoryEvents(); + mSerialIOThread.sendMessage(msg); + while (!msg.done && mRfcommSocket.isConnected()) { + waitMsec(100); + } + waitMsec(200); + return true; + } + + public boolean updateBasalsInPump(final NSProfile profile) { + connect("updateBasalsInPump"); + if (!isConnected()) return false; + MainApp.bus().post(new EventPumpStatusChanged(MainApp.sResources.getString(R.string.updatingbasalrates))); + double[] basal = buildDanaRProfileRecord(profile); + MsgSetBasalProfile msgSet = new MsgSetBasalProfile((byte) 0, basal); + mSerialIOThread.sendMessage(msgSet); + MsgSetActivateBasalProfile msgActivate = new MsgSetActivateBasalProfile((byte) 0); + mSerialIOThread.sendMessage(msgActivate); + danaRPump.lastSettingsRead = new Date(0); // force read full settings + getPumpStatus(); + MainApp.bus().post(new EventPumpStatusChanged(EventPumpStatusChanged.DISCONNECTING)); + return true; + } + + private double[] buildDanaRProfileRecord(NSProfile nsProfile) { + double[] record = new double[24]; + for (Integer hour = 0; hour < 24; hour++) { + double value = nsProfile.getBasal(hour * 60 * 60); + if (Config.logDanaMessageDetail) + log.debug("NS basal value for " + hour + ":00 is " + value); + record[hour] = value; + } + return record; + } + + private void waitMsec(long msecs) { + try { + Thread.sleep(msecs); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } +} diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 8a868dfef3..caf6a2af05 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -598,4 +598,5 @@ Last connection Bluetooh status About + DanaRv2 diff --git a/app/src/main/res/xml/pref_danarprofile.xml b/app/src/main/res/xml/pref_danarprofile.xml index 68be80566a..9129735748 100644 --- a/app/src/main/res/xml/pref_danarprofile.xml +++ b/app/src/main/res/xml/pref_danarprofile.xml @@ -4,7 +4,7 @@ android:key="DanaRProfile" android:title="@string/danarprofile"> + + + + + + + + + \ No newline at end of file