diff --git a/ISSUE_TEMPLATE.md b/ISSUE_TEMPLATE.md new file mode 100644 index 0000000000..db66ffec38 --- /dev/null +++ b/ISSUE_TEMPLATE.md @@ -0,0 +1,10 @@ +Reporting bugs +-------------- +- Note the precise time the problem occurred and describe the circumstances and steps that caused + the problem +- Note the Build version (found in the About dialog in the app, when pressing the three dots in the + upper-right corner). +- Obtain the app's log files, which can be found on the phone in + _/storage/emulated/0/Android/data/info.nightscout.androidaps/_ + See https://github.com/MilosKozak/AndroidAPS/wiki/Accessing-logfiles +- Open an issue at https://github.com/MilosKozak/AndroidAPS/issues/new \ No newline at end of file diff --git a/app/src/main/java/info/nightscout/androidaps/data/Iob.java b/app/src/main/java/info/nightscout/androidaps/data/Iob.java index ee70699604..762352782b 100644 --- a/app/src/main/java/info/nightscout/androidaps/data/Iob.java +++ b/app/src/main/java/info/nightscout/androidaps/data/Iob.java @@ -12,4 +12,26 @@ public class Iob { activityContrib += iob.activityContrib; return this; } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + Iob iob = (Iob) o; + + if (Double.compare(iob.iobContrib, iobContrib) != 0) return false; + return Double.compare(iob.activityContrib, activityContrib) == 0; + } + + @Override + public int hashCode() { + int result; + long temp; + temp = Double.doubleToLongBits(iobContrib); + result = (int) (temp ^ (temp >>> 32)); + temp = Double.doubleToLongBits(activityContrib); + result = 31 * result + (int) (temp ^ (temp >>> 32)); + return result; + } } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Common/SubscriberFragment.java b/app/src/main/java/info/nightscout/androidaps/plugins/Common/SubscriberFragment.java index 74abc837fe..5ca9232646 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/Common/SubscriberFragment.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/Common/SubscriberFragment.java @@ -2,9 +2,12 @@ package info.nightscout.androidaps.plugins.Common; import android.support.v4.app.Fragment; +import butterknife.Unbinder; import info.nightscout.androidaps.MainApp; abstract public class SubscriberFragment extends Fragment { + protected Unbinder unbinder; + @Override public void onPause() { super.onPause(); @@ -18,5 +21,12 @@ abstract public class SubscriberFragment extends Fragment { updateGUI(); } + @Override public void onDestroyView() { + super.onDestroyView(); + if (unbinder != null) + unbinder.unbind(); + } + + protected abstract void updateGUI(); } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Insulin/InsulinOrefBasePlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/Insulin/InsulinOrefBasePlugin.java index cbe5f2ff64..b91eefdc9c 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/Insulin/InsulinOrefBasePlugin.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/Insulin/InsulinOrefBasePlugin.java @@ -1,5 +1,7 @@ package info.nightscout.androidaps.plugins.Insulin; +import com.squareup.otto.Bus; + import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.R; import info.nightscout.androidaps.data.Iob; @@ -44,38 +46,53 @@ public abstract class InsulinOrefBasePlugin implements PluginBase, InsulinInterf return true; } + public Bus getBus() { + return MainApp.bus(); + } + @Override public double getDia() { double dia = getUserDefinedDia(); if(dia >= MIN_DIA){ return dia; } else { - if((System.currentTimeMillis() - lastWarned) > 60*1000) { - lastWarned = System.currentTimeMillis(); - Notification notification = new Notification(Notification.SHORT_DIA, String.format(MainApp.sResources.getString(R.string.dia_too_short), dia, MIN_DIA), Notification.URGENT); - MainApp.bus().post(new EventNewNotification(notification)); - } + sendShortDiaNotification(dia); return MIN_DIA; } } + void sendShortDiaNotification(double dia) { + if((System.currentTimeMillis() - lastWarned) > 60*1000) { + lastWarned = System.currentTimeMillis(); + Notification notification = new Notification(Notification.SHORT_DIA, String.format(this.getNotificationPattern(), dia, MIN_DIA), Notification.URGENT); + this.getBus().post(new EventNewNotification(notification)); + } + } + + public String getNotificationPattern() { + return MainApp.sResources.getString(R.string.dia_too_short); + } + public double getUserDefinedDia() { return MainApp.getConfigBuilder().getProfile() != null ? MainApp.getConfigBuilder().getProfile().getDia() : MIN_DIA; } + public Iob iobCalcForTreatment(Treatment treatment, long time) { + return this.iobCalcForTreatment(treatment, time, 0d); + } + @Override public Iob iobCalcForTreatment(Treatment treatment, long time, double dia) { Iob result = new Iob(); int peak = getPeak(); - if (treatment.insulin != 0d) { long bolusTime = treatment.date; double t = (time - bolusTime) / 1000d / 60d; - double td = getDia()*60; //getDIA() always > 5 + double td = getDia()*60; //getDIA() always >= MIN_DIA double tp = peak; // force the IOB to 0 if over DIA hours have passed diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/AbstractDanaRPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/AbstractDanaRPlugin.java new file mode 100644 index 0000000000..ea47303fb6 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/AbstractDanaRPlugin.java @@ -0,0 +1,557 @@ +package info.nightscout.androidaps.plugins.PumpDanaR; + +import android.support.annotation.Nullable; + +import org.json.JSONException; +import org.json.JSONObject; +import org.slf4j.Logger; + +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.Profile; +import info.nightscout.androidaps.data.ProfileStore; +import info.nightscout.androidaps.data.PumpEnactResult; +import info.nightscout.androidaps.db.ExtendedBolus; +import info.nightscout.androidaps.db.TemporaryBasal; +import info.nightscout.androidaps.interfaces.ConstraintsInterface; +import info.nightscout.androidaps.interfaces.DanaRInterface; +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.Overview.events.EventDismissNotification; +import info.nightscout.androidaps.plugins.Overview.events.EventNewNotification; +import info.nightscout.androidaps.plugins.Overview.notifications.Notification; +import info.nightscout.androidaps.plugins.ProfileNS.NSProfilePlugin; +import info.nightscout.androidaps.plugins.PumpDanaR.services.AbstractDanaRExecutionService; +import info.nightscout.utils.DateUtil; +import info.nightscout.utils.DecimalFormatter; +import info.nightscout.utils.Round; + +/** + * Created by mike on 28.01.2018. + */ + +public abstract class AbstractDanaRPlugin implements PluginBase, PumpInterface, DanaRInterface, ConstraintsInterface, ProfileInterface { + protected Logger log; + + protected boolean mPluginPumpEnabled = false; + protected boolean mPluginProfileEnabled = false; + protected boolean mFragmentPumpVisible = true; + + protected AbstractDanaRExecutionService sExecutionService; + + protected DanaRPump pump = DanaRPump.getInstance(); + protected boolean useExtendedBoluses = false; + + public PumpDescription pumpDescription = new PumpDescription(); + + @Override + public String getFragmentClass() { + return DanaRFragment.class.getName(); + } + + // Plugin base interface + @Override + public int getType() { + return PluginBase.PUMP; + } + + @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 mPluginProfileEnabled && mPluginPumpEnabled; + else if (type == PluginBase.PUMP) return mPluginPumpEnabled; + else if (type == PluginBase.CONSTRAINTS) return mPluginPumpEnabled; + return false; + } + + @Override + public boolean isVisibleInTabs(int type) { + if (type == PluginBase.PROFILE || type == PluginBase.CONSTRAINTS) return false; + else if (type == PluginBase.PUMP) return mFragmentPumpVisible; + return false; + } + + @Override + public boolean canBeHidden(int type) { + return true; + } + + @Override + public boolean hasFragment() { + return true; + } + + @Override + public boolean showInList(int type) { + return type == PUMP; + } + + @Override + public void setFragmentEnabled(int type, boolean fragmentEnabled) { + if (type == PluginBase.PROFILE) + mPluginProfileEnabled = fragmentEnabled; + else if (type == PluginBase.PUMP) + mPluginPumpEnabled = fragmentEnabled; + // if pump profile was enabled need to switch to another too + if (type == PluginBase.PUMP && !fragmentEnabled && mPluginProfileEnabled) { + setFragmentEnabled(PluginBase.PROFILE, false); + setFragmentVisible(PluginBase.PROFILE, false); + NSProfilePlugin.getPlugin().setFragmentEnabled(PluginBase.PROFILE, true); + NSProfilePlugin.getPlugin().setFragmentVisible(PluginBase.PROFILE, true); + } + } + + @Override + public void setFragmentVisible(int type, boolean fragmentVisible) { + if (type == PluginBase.PUMP) + mFragmentPumpVisible = fragmentVisible; + } + + @Override + public boolean isSuspended() { + return pump.pumpSuspended; + } + + @Override + public boolean isBusy() { + if (sExecutionService == null) return false; + return sExecutionService.isConnected() || sExecutionService.isConnecting(); + } + + // Pump interface + @Override + public PumpEnactResult setNewBasalProfile(Profile profile) { + PumpEnactResult result = new PumpEnactResult(); + + if (sExecutionService == null) { + log.error("setNewBasalProfile sExecutionService is null"); + result.comment = "setNewBasalProfile sExecutionService is null"; + return result; + } + 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)); + result.comment = MainApp.sResources.getString(R.string.pumpNotInitializedProfileNotSet); + return result; + } 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)); + result.comment = MainApp.sResources.getString(R.string.failedupdatebasalprofile); + return result; + } else { + MainApp.bus().post(new EventDismissNotification(Notification.PROFILE_NOT_SET_NOT_INITIALIZED)); + MainApp.bus().post(new EventDismissNotification(Notification.FAILED_UDPATE_PROFILE)); + Notification notification = new Notification(Notification.PROFILE_SET_OK, MainApp.sResources.getString(R.string.profile_set_ok), Notification.INFO, 60); + MainApp.bus().post(new EventNewNotification(notification)); + result.success = true; + result.enacted = true; + result.comment = "OK"; + return result; + } + } + + @Override + public boolean isThisProfileSet(Profile profile) { + if (!isInitialized()) + return true; // TODO: not sure what's better. so far TRUE to prevent too many SMS + 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((Integer) (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 new Date(pump.lastConnection); + } + + @Override + public double getBaseBasalRate() { + return pump.currentBasal; + } + + @Override + public void stopBolusDelivering() { + if (sExecutionService == null) { + log.error("stopBolusDelivering sExecutionService is null"); + return; + } + sExecutionService.bolusStop(); + } + + @Override + public PumpEnactResult setTempBasalPercent(Integer percent, Integer durationInMinutes, boolean enforceNew) { + 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().maxTempPercent) + percent = getPumpDescription().maxTempPercent; + TemporaryBasal runningTB = MainApp.getConfigBuilder().getRealTempBasalFromHistory(System.currentTimeMillis()); + if (runningTB != null && runningTB.percentRate == percent && !enforceNew) { + result.enacted = false; + result.success = true; + result.isTempCancel = false; + result.comment = MainApp.instance().getString(R.string.virtualpump_resultok); + result.duration = pump.tempBasalRemainingMin; + result.percent = pump.tempBasalPercent; + result.absolute = MainApp.getConfigBuilder().getTempBasalAbsoluteRateHistory(); + result.isPercent = true; + if (Config.logPumpActions) + log.debug("setTempBasalPercent: Correct value already set"); + return result; + } + int durationInHours = Math.max(durationInMinutes / 60, 1); + boolean connectionOK = sExecutionService.tempBasal(percent, durationInHours); + if (connectionOK && pump.isTempBasalInProgress && pump.tempBasalPercent == percent) { + result.enacted = true; + result.success = true; + result.comment = MainApp.instance().getString(R.string.virtualpump_resultok); + result.isTempCancel = false; + result.duration = pump.tempBasalRemainingMin; + result.percent = pump.tempBasalPercent; + result.absolute = MainApp.getConfigBuilder().getTempBasalAbsoluteRateHistory(); + 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.tempbasaldeliveryerror); + 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 + int durationInHalfHours = Math.max(durationInMinutes / 30, 1); + insulin = Round.roundTo(insulin, getPumpDescription().extendedBolusStep); + + PumpEnactResult result = new PumpEnactResult(); + ExtendedBolus runningEB = MainApp.getConfigBuilder().getExtendedBolusFromHistory(System.currentTimeMillis()); + if (runningEB != null && Math.abs(runningEB.insulin - insulin) < getPumpDescription().extendedBolusStep) { + result.enacted = false; + result.success = true; + result.comment = MainApp.instance().getString(R.string.virtualpump_resultok); + result.duration = pump.extendedBolusRemainingMinutes; + result.absolute = pump.extendedBolusAbsoluteRate; + result.isPercent = false; + result.isTempCancel = false; + if (Config.logPumpActions) + log.debug("setExtendedBolus: Correct extended bolus already set. Current: " + pump.extendedBolusAmount + " Asked: " + insulin); + return result; + } + boolean connectionOK = sExecutionService.extendedBolus(insulin, durationInHalfHours); + if (connectionOK && pump.isExtendedInProgress && Math.abs(pump.extendedBolusAmount - insulin) < getPumpDescription().extendedBolusStep) { + result.enacted = true; + result.success = true; + result.comment = MainApp.instance().getString(R.string.virtualpump_resultok); + result.isTempCancel = false; + result.duration = pump.extendedBolusRemainingMinutes; + result.absolute = pump.extendedBolusAbsoluteRate; + result.bolusDelivered = pump.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 cancelExtendedBolus() { + PumpEnactResult result = new PumpEnactResult(); + ExtendedBolus runningEB = MainApp.getConfigBuilder().getExtendedBolusFromHistory(System.currentTimeMillis()); + if (runningEB != null) { + sExecutionService.extendedBolusStop(); + result.enacted = true; + result.isTempCancel = true; + } + if (!pump.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; + } + } + + @Override + public void connect(String from) { + if (sExecutionService != null) { + sExecutionService.connect(); + pumpDescription.basalStep = pump.basalStep; + pumpDescription.bolusStep = pump.bolusStep; + } + } + + @Override + public boolean isConnected() { + return sExecutionService != null && sExecutionService.isConnected(); + } + + @Override + public boolean isConnecting() { + return sExecutionService != null && sExecutionService.isConnecting(); + } + + @Override + public void disconnect(String from) { + if (sExecutionService != null) sExecutionService.disconnect(from); + } + + @Override + public void stopConnecting() { + if (sExecutionService != null) sExecutionService.stopConnecting(); + } + + @Override + public void getPumpStatus() { + if (sExecutionService != null) sExecutionService.getPumpStatus(); + } + + @Override + public JSONObject getJSONStatus() { + if (pump.lastConnection + 5 * 60 * 1000L < System.currentTimeMillis()) { + return null; + } + JSONObject pumpjson = new JSONObject(); + JSONObject battery = new JSONObject(); + JSONObject status = new JSONObject(); + JSONObject extended = new JSONObject(); + try { + battery.put("percent", pump.batteryRemaining); + status.put("status", pump.pumpSuspended ? "suspended" : "normal"); + status.put("timestamp", DateUtil.toISOString(pump.lastConnection)); + extended.put("Version", BuildConfig.VERSION_NAME + "-" + BuildConfig.BUILDVERSION); + extended.put("PumpIOB", pump.iob); + if (pump.lastBolusTime.getTime() != 0) { + extended.put("LastBolus", pump.lastBolusTime.toLocaleString()); + extended.put("LastBolusAmount", pump.lastBolusAmount); + } + TemporaryBasal tb = MainApp.getConfigBuilder().getRealTempBasalFromHistory(System.currentTimeMillis()); + if (tb != null) { + extended.put("TempBasalAbsoluteRate", tb.tempBasalConvertedToAbsolute(System.currentTimeMillis())); + extended.put("TempBasalStart", DateUtil.dateAndTimeString(tb.date)); + extended.put("TempBasalRemaining", tb.getPlannedRemainingMinutes()); + } + ExtendedBolus eb = MainApp.getConfigBuilder().getExtendedBolusFromHistory(System.currentTimeMillis()); + if (eb != null) { + extended.put("ExtendedBolusAbsoluteRate", eb.absoluteRate()); + extended.put("ExtendedBolusStart", DateUtil.dateAndTimeString(eb.date)); + extended.put("ExtendedBolusRemaining", eb.getPlannedRemainingMinutes()); + } + extended.put("BaseBasalRate", getBaseBasalRate()); + try { + extended.put("ActiveProfile", MainApp.getConfigBuilder().getProfileName()); + } catch (Exception e) { + } + + pumpjson.put("battery", battery); + pumpjson.put("status", status); + pumpjson.put("extended", extended); + pumpjson.put("reservoir", (int) pump.reservoirRemainingUnits); + pumpjson.put("clock", DateUtil.toISOString(new Date())); + } catch (JSONException e) { + log.error("Unhandled exception", e); + } + return pumpjson; + } + + @Override + public String deviceID() { + return pump.serialNumber; + } + + @Override + public PumpDescription getPumpDescription() { + return pumpDescription; + } + + /** + * DanaR interface + */ + + @Override + public PumpEnactResult loadHistory(byte type) { + return sExecutionService.loadHistory(type); + } + + /** + * 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; + } + + @Override + public boolean isSMBModeEnabled() { + return true; + } + + @SuppressWarnings("PointlessBooleanExpression") + @Override + public Double applyBasalConstraints(Double absoluteRate) { + double origAbsoluteRate = absoluteRate; + if (pump != null) { + if (absoluteRate > pump.maxBasal) { + absoluteRate = pump.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().maxTempPercent) + percentRate = getPumpDescription().maxTempPercent; + 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 (pump != null) { + if (insulin > pump.maxBolus) { + insulin = pump.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 ProfileStore getProfile() { + if (pump.lastSettingsRead == 0) + return null; // no info now + return pump.createConvertedProfile(); + } + + @Override + public String getUnits() { + return pump.getUnits(); + } + + @Override + public String getProfileName() { + return pump.createConvertedProfileName(); + } + + // Reply for sms communicator + public String shortStatus(boolean veryShort) { + String ret = ""; + if (pump.lastConnection != 0) { + Long agoMsec = System.currentTimeMillis() - pump.lastConnection; + int agoMin = (int) (agoMsec / 60d / 1000d); + ret += "LastConn: " + agoMin + " minago\n"; + } + if (pump.lastBolusTime.getTime() != 0) { + ret += "LastBolus: " + DecimalFormatter.to2Decimal(pump.lastBolusAmount) + "U @" + android.text.format.DateFormat.format("HH:mm", pump.lastBolusTime) + "\n"; + } + if (MainApp.getConfigBuilder().isInHistoryRealTempBasalInProgress()) { + ret += "Temp: " + MainApp.getConfigBuilder().getRealTempBasalFromHistory(System.currentTimeMillis()).toStringFull() + "\n"; + } + if (MainApp.getConfigBuilder().isInHistoryExtendedBoluslInProgress()) { + ret += "Extended: " + MainApp.getConfigBuilder().getExtendedBolusFromHistory(System.currentTimeMillis()).toString() + "\n"; + } + if (!veryShort) { + ret += "TDD: " + DecimalFormatter.to0Decimal(pump.dailyTotalUnits) + " / " + pump.maxDailyTotalUnits + " U\n"; + } + ret += "IOB: " + pump.iob + "U\n"; + ret += "Reserv: " + DecimalFormatter.to0Decimal(pump.reservoirRemainingUnits) + "U\n"; + ret += "Batt: " + pump.batteryRemaining + "\n"; + return ret; + } + // TODO: daily total constraint + +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/BluetoothDevicePreference.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/BluetoothDevicePreference.java index 63e14f0921..e39fdcfdaa 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/BluetoothDevicePreference.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/BluetoothDevicePreference.java @@ -6,6 +6,7 @@ import android.preference.ListPreference; import android.util.AttributeSet; import java.util.Set; +import java.util.Vector; public class BluetoothDevicePreference extends ListPreference { @@ -13,25 +14,22 @@ public class BluetoothDevicePreference extends ListPreference { super(context, attrs); BluetoothAdapter bta = BluetoothAdapter.getDefaultAdapter(); - Integer size = 0; - if (bta != null) { - size += bta.getBondedDevices().size(); - } - CharSequence[] entries = new CharSequence[size]; - int i = 0; + Vector entries = new Vector(); if (bta != null) { Set pairedDevices = bta.getBondedDevices(); for (BluetoothDevice dev : pairedDevices) { - entries[i] = dev.getName(); - i++; + String name = dev.getName(); + if(name != null) { + entries.add(name); + } } } - setEntries(entries); - setEntryValues(entries); + setEntries(entries.toArray(new CharSequence[0])); + setEntryValues(entries.toArray(new CharSequence[0])); } public BluetoothDevicePreference(Context context) { this(context, null); } -} \ No newline at end of file +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/DanaRFragment.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/DanaRFragment.java index 8ac6bb306b..1ca54a7eb6 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/DanaRFragment.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/DanaRFragment.java @@ -21,6 +21,12 @@ import com.squareup.otto.Subscribe; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import java.util.Date; + +import butterknife.BindView; +import butterknife.ButterKnife; +import butterknife.OnClick; +import butterknife.Unbinder; import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.R; import info.nightscout.androidaps.events.EventExtendedBolusChange; @@ -49,27 +55,24 @@ public class DanaRFragment extends SubscriberFragment { } }; - TextView lastConnectionView; - TextView btConnectionView; - TextView lastBolusView; - TextView dailyUnitsView; - TextView basaBasalRateView; - TextView tempBasalView; - TextView extendedBolusView; - TextView batteryView; - TextView reservoirView; - TextView iobView; - TextView firmwareView; - TextView basalStepView; - TextView bolusStepView; - TextView serialNumberView; - TextView queueView; - Button viewProfileButton; - Button historyButton; - Button statsButton; + @BindView(R.id.danar_lastconnection) TextView lastConnectionView; + @BindView(R.id.danar_btconnection) TextView btConnectionView; + @BindView(R.id.danar_lastbolus) TextView lastBolusView; + @BindView(R.id.danar_dailyunits) TextView dailyUnitsView; + @BindView(R.id.danar_basabasalrate) TextView basaBasalRateView; + @BindView(R.id.danar_tempbasal) TextView tempBasalView; + @BindView(R.id.danar_extendedbolus) TextView extendedBolusView; + @BindView(R.id.danar_battery) TextView batteryView; + @BindView(R.id.danar_reservoir) TextView reservoirView; + @BindView(R.id.danar_iob) TextView iobView; + @BindView(R.id.danar_firmware) TextView firmwareView; + @BindView(R.id.danar_basalstep) TextView basalStepView; + @BindView(R.id.danar_bolusstep) TextView bolusStepView; + @BindView(R.id.danar_serialnumber) TextView serialNumberView; + @BindView(R.id.danar_queue) TextView queueView; - LinearLayout pumpStatusLayout; - TextView pumpStatusView; + @BindView(R.id.overview_pumpstatuslayout) LinearLayout pumpStatusLayout; + @BindView(R.id.overview_pumpstatus) TextView pumpStatusView; public DanaRFragment() { } @@ -91,61 +94,10 @@ public class DanaRFragment extends SubscriberFragment { Bundle savedInstanceState) { try { 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); - basalStepView = (TextView) view.findViewById(R.id.danar_basalstep); - bolusStepView = (TextView) view.findViewById(R.id.danar_bolusstep); - serialNumberView = (TextView) view.findViewById(R.id.danar_serialnumber); - queueView = (TextView) view.findViewById(R.id.danar_queue); + unbinder = ButterKnife.bind(this, view); - pumpStatusView = (TextView) view.findViewById(R.id.overview_pumpstatus); pumpStatusView.setBackgroundColor(MainApp.sResources.getColor(R.color.colorInitializingBorder)); - pumpStatusLayout = (LinearLayout) view.findViewById(R.id.overview_pumpstatuslayout); - 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) { - log.debug("Clicked connect to pump"); - ConfigBuilderPlugin.getCommandQueue().readStatus("Clicked connect to pump", null); - } - }); - - updateGUI(); return view; } catch (Exception e) { Crashlytics.logException(e); @@ -154,6 +106,26 @@ public class DanaRFragment extends SubscriberFragment { return null; } + @OnClick(R.id.danar_history) void onHistoryClick() { + startActivity(new Intent(getContext(), DanaRHistoryActivity.class)); + } + + @OnClick(R.id.danar_viewprofile) void onViewProfileClick() { + FragmentManager manager = getFragmentManager(); + ProfileViewDialog profileViewDialog = new ProfileViewDialog(); + profileViewDialog.show(manager, "ProfileViewDialog"); + } + + @OnClick(R.id.danar_stats) void onStatsClick() { + startActivity(new Intent(getContext(), DanaRStatsActivity.class)); + } + + @OnClick(R.id.danar_btconnection) void onBtConnectionClick() { + log.debug("Clicked connect to pump"); + DanaRPump.getInstance().lastConnection = 0; + ConfigBuilderPlugin.getCommandQueue().readStatus("Clicked connect to pump", null); + } + @Subscribe public void onStatusEvent(final EventPumpStatusChanged c) { Activity activity = getActivity(); @@ -212,8 +184,8 @@ public class DanaRFragment extends SubscriberFragment { @Override public void run() { DanaRPump pump = DanaRPump.getInstance(); - if (pump.lastConnection.getTime() != 0) { - Long agoMsec = System.currentTimeMillis() - pump.lastConnection.getTime(); + if (pump.lastConnection != 0) { + Long agoMsec = System.currentTimeMillis() - pump.lastConnection; 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); diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/DanaRPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/DanaRPlugin.java index 3a11ebe0a6..9a0be55897 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/DanaRPlugin.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/DanaRPlugin.java @@ -5,69 +5,30 @@ import android.content.Context; import android.content.Intent; import android.content.ServiceConnection; import android.os.IBinder; -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.DetailedBolusInfo; import info.nightscout.androidaps.data.PumpEnactResult; -import info.nightscout.androidaps.db.ExtendedBolus; import info.nightscout.androidaps.db.TemporaryBasal; import info.nightscout.androidaps.db.Treatment; import info.nightscout.androidaps.events.EventAppExit; import info.nightscout.androidaps.events.EventPreferenceChange; -import info.nightscout.androidaps.interfaces.ConstraintsInterface; -import info.nightscout.androidaps.interfaces.DanaRInterface; -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.data.Profile; -import info.nightscout.androidaps.data.ProfileStore; -import info.nightscout.androidaps.plugins.Overview.notifications.Notification; -import info.nightscout.androidaps.plugins.Overview.events.EventDismissNotification; -import info.nightscout.androidaps.plugins.Overview.events.EventNewNotification; -import info.nightscout.androidaps.plugins.ProfileNS.NSProfilePlugin; import info.nightscout.androidaps.plugins.PumpDanaR.services.DanaRExecutionService; -import info.nightscout.utils.DateUtil; -import info.nightscout.utils.DecimalFormatter; import info.nightscout.utils.Round; import info.nightscout.utils.SP; /** * Created by mike on 05.08.2016. */ -public class DanaRPlugin implements PluginBase, PumpInterface, DanaRInterface, ConstraintsInterface, ProfileInterface { - private static Logger log = LoggerFactory.getLogger(DanaRPlugin.class); - - @Override - public String getFragmentClass() { - return DanaRFragment.class.getName(); - } - - private static boolean fragmentPumpEnabled = false; - private static boolean fragmentProfileEnabled = false; - private static boolean fragmentPumpVisible = true; - - private static DanaRExecutionService sExecutionService; - - - private static DanaRPump pump = DanaRPump.getInstance(); - private static boolean useExtendedBoluses = false; +public class DanaRPlugin extends AbstractDanaRPlugin { private static DanaRPlugin plugin = null; @@ -77,9 +38,8 @@ public class DanaRPlugin implements PluginBase, PumpInterface, DanaRInterface, C return plugin; } - public static PumpDescription pumpDescription = new PumpDescription(); - public DanaRPlugin() { + log = LoggerFactory.getLogger(DanaRPlugin.class); useExtendedBoluses = SP.getBoolean("danar_useextended", false); Context context = MainApp.instance().getApplicationContext(); @@ -147,83 +107,17 @@ public class DanaRPlugin implements PluginBase, PumpInterface, DanaRInterface, C } // Plugin base interface - @Override - public int getType() { - return PluginBase.PUMP; - } - @Override public String getName() { return MainApp.instance().getString(R.string.danarpump); } - @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 type == PUMP; - } - - @Override - public void setFragmentEnabled(int type, boolean fragmentEnabled) { - if (type == PluginBase.PROFILE) - fragmentProfileEnabled = fragmentEnabled; - else if (type == PluginBase.PUMP) - fragmentPumpEnabled = fragmentEnabled; - // if pump profile was enabled need to switch to another too - if (type == PluginBase.PUMP && !fragmentEnabled && fragmentProfileEnabled) { - setFragmentEnabled(PluginBase.PROFILE, false); - setFragmentVisible(PluginBase.PROFILE, false); - NSProfilePlugin.getPlugin().setFragmentEnabled(PluginBase.PROFILE, true); - NSProfilePlugin.getPlugin().setFragmentVisible(PluginBase.PROFILE, true); - } - } - - @Override - public void setFragmentVisible(int type, boolean fragmentVisible) { - if (type == PluginBase.PUMP) - fragmentPumpVisible = fragmentVisible; - } - @Override public int getPreferencesId() { return R.xml.pref_danar; } + // Pump interface @Override public boolean isFakingTempsByExtendedBoluses() { return useExtendedBoluses; @@ -231,82 +125,7 @@ public class DanaRPlugin implements PluginBase, PumpInterface, DanaRInterface, C @Override public boolean isInitialized() { - return pump.lastConnection.getTime() > 0 && pump.isExtendedBolusEnabled && pump.maxBasal > 0; - } - - @Override - public boolean isSuspended() { - return pump.pumpSuspended; - } - - @Override - public boolean isBusy() { - if (sExecutionService == null) return false; - return sExecutionService.isConnected() || sExecutionService.isConnecting(); - } - - // Pump interface - @Override - public PumpEnactResult setNewBasalProfile(Profile profile) { - PumpEnactResult result = new PumpEnactResult(); - - if (sExecutionService == null) { - log.error("setNewBasalProfile sExecutionService is null"); - result.comment = "setNewBasalProfile sExecutionService is null"; - return result; - } - 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)); - result.comment = MainApp.sResources.getString(R.string.pumpNotInitializedProfileNotSet); - return result; - } 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)); - result.comment = MainApp.sResources.getString(R.string.failedupdatebasalprofile); - return result; - } else { - MainApp.bus().post(new EventDismissNotification(Notification.PROFILE_NOT_SET_NOT_INITIALIZED)); - MainApp.bus().post(new EventDismissNotification(Notification.FAILED_UDPATE_PROFILE)); - result.success = true; - result.enacted = true; - result.comment = "OK"; - return result; - } - } - - @Override - public boolean isThisProfileSet(Profile profile) { - if (!isInitialized()) - return true; // TODO: not sure what's better. so far TRUE to prevent too many SMS - 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((Integer) (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 pump.lastConnection; - } - - @Override - public double getBaseBasalRate() { - return pump.currentBasal; + return pump.lastConnection > 0 && pump.isExtendedBolusEnabled && pump.maxBasal > 0; } @Override @@ -316,7 +135,7 @@ public class DanaRPlugin implements PluginBase, PumpInterface, DanaRInterface, C if (detailedBolusInfo.insulin > 0 || detailedBolusInfo.carbs > 0) { Treatment t = new Treatment(); boolean connectionOK = false; - if (detailedBolusInfo.insulin > 0 || detailedBolusInfo.carbs > 0) connectionOK = sExecutionService.bolus(detailedBolusInfo.insulin, (int) detailedBolusInfo.carbs, t); + if (detailedBolusInfo.insulin > 0 || detailedBolusInfo.carbs > 0) connectionOK = sExecutionService.bolus(detailedBolusInfo.insulin, (int) detailedBolusInfo.carbs, detailedBolusInfo.carbTime, t); PumpEnactResult result = new PumpEnactResult(); result.success = connectionOK; result.bolusDelivered = t.insulin; @@ -339,15 +158,6 @@ public class DanaRPlugin implements PluginBase, PumpInterface, DanaRInterface, C } } - @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, boolean enforceNew) { @@ -500,100 +310,6 @@ public class DanaRPlugin implements PluginBase, PumpInterface, DanaRInterface, C return result; } - @Override - public PumpEnactResult setTempBasalPercent(Integer percent, Integer durationInMinutes, boolean enforceNew) { - 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().maxTempPercent) - percent = getPumpDescription().maxTempPercent; - TemporaryBasal runningTB = MainApp.getConfigBuilder().getRealTempBasalFromHistory(System.currentTimeMillis()); - if (runningTB != null && runningTB.percentRate == percent && !enforceNew) { - result.enacted = false; - result.success = true; - result.isTempCancel = false; - result.comment = MainApp.instance().getString(R.string.virtualpump_resultok); - result.duration = pump.tempBasalRemainingMin; - result.percent = pump.tempBasalPercent; - result.absolute = MainApp.getConfigBuilder().getTempBasalAbsoluteRateHistory(); - result.isPercent = true; - if (Config.logPumpActions) - log.debug("setTempBasalPercent: Correct value already set"); - return result; - } - int durationInHours = Math.max(durationInMinutes / 60, 1); - boolean connectionOK = sExecutionService.tempBasal(percent, durationInHours); - if (connectionOK && pump.isTempBasalInProgress && pump.tempBasalPercent == percent) { - result.enacted = true; - result.success = true; - result.comment = MainApp.instance().getString(R.string.virtualpump_resultok); - result.isTempCancel = false; - result.duration = pump.tempBasalRemainingMin; - result.percent = pump.tempBasalPercent; - result.absolute = MainApp.getConfigBuilder().getTempBasalAbsoluteRateHistory(); - 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.tempbasaldeliveryerror); - 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 - int durationInHalfHours = Math.max(durationInMinutes / 30, 1); - insulin = Round.roundTo(insulin, getPumpDescription().extendedBolusStep); - - PumpEnactResult result = new PumpEnactResult(); - ExtendedBolus runningEB = MainApp.getConfigBuilder().getExtendedBolusFromHistory(System.currentTimeMillis()); - if (runningEB != null && Math.abs(runningEB.insulin - insulin) < getPumpDescription().extendedBolusStep) { - result.enacted = false; - result.success = true; - result.comment = MainApp.instance().getString(R.string.virtualpump_resultok); - result.duration = pump.extendedBolusRemainingMinutes; - result.absolute = pump.extendedBolusAbsoluteRate; - result.isPercent = false; - result.isTempCancel = false; - if (Config.logPumpActions) - log.debug("setExtendedBolus: Correct extended bolus already set. Current: " + pump.extendedBolusAmount + " Asked: " + insulin); - return result; - } - boolean connectionOK = sExecutionService.extendedBolus(insulin, durationInHalfHours); - if (connectionOK && pump.isExtendedInProgress && Math.abs(pump.extendedBolusAmount - insulin) < getPumpDescription().extendedBolusStep) { - result.enacted = true; - result.success = true; - result.comment = MainApp.instance().getString(R.string.virtualpump_resultok); - result.isTempCancel = false; - result.duration = pump.extendedBolusRemainingMinutes; - result.absolute = pump.extendedBolusAbsoluteRate; - result.bolusDelivered = pump.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(boolean force) { if (MainApp.getConfigBuilder().isInHistoryRealTempBasalInProgress()) @@ -634,257 +350,8 @@ public class DanaRPlugin implements PluginBase, PumpInterface, DanaRInterface, C } } - @Override - public PumpEnactResult cancelExtendedBolus() { - PumpEnactResult result = new PumpEnactResult(); - ExtendedBolus runningEB = MainApp.getConfigBuilder().getExtendedBolusFromHistory(System.currentTimeMillis()); - if (runningEB != null) { - sExecutionService.extendedBolusStop(); - result.enacted = true; - result.isTempCancel = true; - } - if (!pump.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; - } - } - - @Override - public void connect(String from) { - if (sExecutionService != null) { - sExecutionService.connect(from); - pumpDescription.basalStep = pump.basalStep; - pumpDescription.bolusStep = pump.bolusStep; - } - } - - @Override - public boolean isConnected() { - return sExecutionService != null && sExecutionService.isConnected(); - } - - @Override - public boolean isConnecting() { - return sExecutionService != null && sExecutionService.isConnecting(); - } - - @Override - public void disconnect(String from) { - if (sExecutionService != null) sExecutionService.disconnect(from); - } - - @Override - public void stopConnecting() { - if (sExecutionService != null) sExecutionService.stopConnecting(); - } - - @Override - public void getPumpStatus() { - if (sExecutionService != null) sExecutionService.getPumpStatus(); - } - - @Override - public JSONObject getJSONStatus() { - if (pump.lastConnection.getTime() + 5 * 60 * 1000L < System.currentTimeMillis()) { - return null; - } - JSONObject pumpjson = new JSONObject(); - JSONObject battery = new JSONObject(); - JSONObject status = new JSONObject(); - JSONObject extended = new JSONObject(); - try { - battery.put("percent", pump.batteryRemaining); - status.put("status", pump.pumpSuspended ? "suspended" : "normal"); - status.put("timestamp", DateUtil.toISOString(pump.lastConnection)); - extended.put("Version", BuildConfig.VERSION_NAME + "-" + BuildConfig.BUILDVERSION); - extended.put("PumpIOB", pump.iob); - if (pump.lastBolusTime.getTime() != 0) { - extended.put("LastBolus", pump.lastBolusTime.toLocaleString()); - extended.put("LastBolusAmount", pump.lastBolusAmount); - } - TemporaryBasal tb = MainApp.getConfigBuilder().getRealTempBasalFromHistory(System.currentTimeMillis()); - if (tb != null) { - extended.put("TempBasalAbsoluteRate", tb.tempBasalConvertedToAbsolute(System.currentTimeMillis())); - extended.put("TempBasalStart", DateUtil.dateAndTimeString(tb.date)); - extended.put("TempBasalRemaining", tb.getPlannedRemainingMinutes()); - } - ExtendedBolus eb = MainApp.getConfigBuilder().getExtendedBolusFromHistory(System.currentTimeMillis()); - if (eb != null) { - extended.put("ExtendedBolusAbsoluteRate", eb.absoluteRate()); - extended.put("ExtendedBolusStart", DateUtil.dateAndTimeString(eb.date)); - extended.put("ExtendedBolusRemaining", eb.getPlannedRemainingMinutes()); - } - extended.put("BaseBasalRate", getBaseBasalRate()); - try { - extended.put("ActiveProfile", MainApp.getConfigBuilder().getProfileName()); - } catch (Exception e) { - } - - pumpjson.put("battery", battery); - pumpjson.put("status", status); - pumpjson.put("extended", extended); - pumpjson.put("reservoir", (int) pump.reservoirRemainingUnits); - pumpjson.put("clock", DateUtil.toISOString(new Date())); - } catch (JSONException e) { - log.error("Unhandled exception", e); - } - return pumpjson; - } - - @Override - public String deviceID() { - return pump.serialNumber; - } - - @Override - public PumpDescription getPumpDescription() { - return pumpDescription; - } - - /** - * DanaR interface - */ - - @Override - public PumpEnactResult loadHistory(byte type) { - return sExecutionService.loadHistory(type); - } - @Override public PumpEnactResult loadEvents() { return null; // no history, not needed } - - /** - * 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; - } - - @Override - public boolean isSMBModeEnabled() { - return true; - } - - @SuppressWarnings("PointlessBooleanExpression") - @Override - public Double applyBasalConstraints(Double absoluteRate) { - double origAbsoluteRate = absoluteRate; - if (pump != null) { - if (absoluteRate > pump.maxBasal) { - absoluteRate = pump.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().maxTempPercent) - percentRate = getPumpDescription().maxTempPercent; - 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 (pump != null) { - if (insulin > pump.maxBolus) { - insulin = pump.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 ProfileStore getProfile() { - if (pump.lastSettingsRead.getTime() == 0) - return null; // no info now - return pump.createConvertedProfile(); - } - - @Override - public String getUnits() { - return pump.getUnits(); - } - - @Override - public String getProfileName() { - return pump.createConvertedProfileName(); - } - - // Reply for sms communicator - public String shortStatus(boolean veryShort) { - String ret = ""; - if (pump.lastConnection.getTime() != 0) { - Long agoMsec = System.currentTimeMillis() - pump.lastConnection.getTime(); - int agoMin = (int) (agoMsec / 60d / 1000d); - ret += "LastConn: " + agoMin + " minago\n"; - } - if (pump.lastBolusTime.getTime() != 0) { - ret += "LastBolus: " + DecimalFormatter.to2Decimal(pump.lastBolusAmount) + "U @" + android.text.format.DateFormat.format("HH:mm", pump.lastBolusTime) + "\n"; - } - if (MainApp.getConfigBuilder().isInHistoryRealTempBasalInProgress()) { - ret += "Temp: " + MainApp.getConfigBuilder().getRealTempBasalFromHistory(System.currentTimeMillis()).toStringFull() + "\n"; - } - if (MainApp.getConfigBuilder().isInHistoryExtendedBoluslInProgress()) { - ret += "Extended: " + MainApp.getConfigBuilder().getExtendedBolusFromHistory(System.currentTimeMillis()).toString() + "\n"; - } - if (!veryShort) { - ret += "TDD: " + DecimalFormatter.to0Decimal(pump.dailyTotalUnits) + " / " + pump.maxDailyTotalUnits + " U\n"; - } - ret += "IOB: " + pump.iob + "U\n"; - ret += "Reserv: " + DecimalFormatter.to0Decimal(pump.reservoirRemainingUnits) + "U\n"; - ret += "Batt: " + pump.batteryRemaining + "\n"; - return ret; - } - // TODO: daily total constraint - } 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 9f88011c96..0e1a9ceb75 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 @@ -56,8 +56,8 @@ public class DanaRPump { public static final int CARBS = 14; public static final int PRIMECANNULA = 15; - public Date lastConnection = new Date(0); - public Date lastSettingsRead = new Date(0); + public long lastConnection = 0; + public long lastSettingsRead =0; // Info public String serialNumber = ""; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/SerialIOThread.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/SerialIOThread.java index a333faecea..2f377a566a 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/SerialIOThread.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/SerialIOThread.java @@ -13,12 +13,13 @@ import java.io.OutputStream; import info.nightscout.androidaps.Config; import info.nightscout.androidaps.plugins.PumpDanaR.comm.MessageBase; import info.nightscout.androidaps.plugins.PumpDanaR.comm.MessageHashTable; +import info.nightscout.androidaps.plugins.PumpDanaR.services.AbstractSerialIOThread; import info.nightscout.utils.CRC; /** * Created by mike on 17.07.2016. */ -public class SerialIOThread extends Thread { +public class SerialIOThread extends AbstractSerialIOThread { private static Logger log = LoggerFactory.getLogger(SerialIOThread.class); private InputStream mInputStream = null; @@ -28,10 +29,10 @@ public class SerialIOThread extends Thread { private boolean mKeepRunning = true; private byte[] mReadBuff = new byte[0]; - MessageBase processedMessage; + private MessageBase processedMessage; public SerialIOThread(BluetoothSocket rfcommSocket) { - super(SerialIOThread.class.toString()); + super(); mRfCommSocket = rfcommSocket; try { @@ -137,6 +138,7 @@ public class SerialIOThread extends Thread { } } + @Override public synchronized void sendMessage(MessageBase message) { if (!mRfCommSocket.isConnected()) { log.error("Socket not connected on sendMessage"); @@ -172,6 +174,7 @@ public class SerialIOThread extends Thread { } } + @Override public void disconnect(String reason) { mKeepRunning = false; try { 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 17f90a1ba7..fe0d280113 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 @@ -35,8 +35,8 @@ public class MsgInitConnStatusTime extends MessageBase { MainApp.getSpecificPlugin(DanaRKoreanPlugin.class).setFragmentVisible(PluginBase.PUMP, true); MainApp.getSpecificPlugin(DanaRPlugin.class).setFragmentEnabled(PluginBase.PUMP, false); MainApp.getSpecificPlugin(DanaRPlugin.class).setFragmentVisible(PluginBase.PUMP, false); - DanaRPump.getInstance().lastConnection = new Date(0); // mark not initialized + DanaRPump.getInstance().lastConnection = 0; // mark not initialized //If profile coming from pump, switch it as well if(MainApp.getSpecificPlugin(DanaRPlugin.class).isEnabled(PluginBase.PROFILE)){ (MainApp.getSpecificPlugin(DanaRPlugin.class)).setFragmentEnabled(PluginBase.PROFILE, false); 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 e1a7e45315..a47803c1b0 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 @@ -23,7 +23,7 @@ public class MsgSettingBasal extends MessageBase { pump.pumpProfiles[pump.activeProfile] = new double[24]; for (int index = 0; index < 24; index++) { int basal = intFromBuff(bytes, 2 * index, 2); - if (basal < DanaRPlugin.pumpDescription.basalMinimumRate) basal = 0; + if (basal < DanaRPlugin.getPlugin().pumpDescription.basalMinimumRate) basal = 0; pump.pumpProfiles[pump.activeProfile][index] = basal / 100d; } 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 2d54d4f4a2..5d7b4b65ac 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 @@ -6,10 +6,12 @@ import org.slf4j.LoggerFactory; import info.nightscout.androidaps.Config; import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.R; -import info.nightscout.androidaps.plugins.Overview.notifications.Notification; +import info.nightscout.androidaps.interfaces.PluginBase; import info.nightscout.androidaps.plugins.Overview.events.EventDismissNotification; import info.nightscout.androidaps.plugins.Overview.events.EventNewNotification; +import info.nightscout.androidaps.plugins.Overview.notifications.Notification; import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPump; +import info.nightscout.androidaps.plugins.PumpDanaRKorean.DanaRKoreanPlugin; /** * Created by mike on 13.12.2016. @@ -40,6 +42,11 @@ public class MsgSettingMeal extends MessageBase { log.debug("Is Config U/d: " + pump.isConfigUD); } + // DanaRKorean is not possible to set to 0.01 but it works when controlled from AAPS + if (DanaRKoreanPlugin.getPlugin().isEnabled(PluginBase.PUMP)) { + pump.basalStep = 0.01d; + } + if (pump.basalStep != 0.01d) { Notification notification = new Notification(Notification.WRONGBASALSTEP, MainApp.sResources.getString(R.string.danar_setbasalstep001), Notification.URGENT); MainApp.bus().post(new EventNewNotification(notification)); diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/services/AbstractDanaRExecutionService.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/services/AbstractDanaRExecutionService.java new file mode 100644 index 0000000000..d853c9abf1 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/services/AbstractDanaRExecutionService.java @@ -0,0 +1,225 @@ +package info.nightscout.androidaps.plugins.PumpDanaR.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.os.IBinder; +import android.os.SystemClock; + +import org.slf4j.Logger; + +import java.io.IOException; +import java.util.Set; +import java.util.UUID; + +import info.nightscout.androidaps.Config; +import info.nightscout.androidaps.MainApp; +import info.nightscout.androidaps.R; +import info.nightscout.androidaps.data.Profile; +import info.nightscout.androidaps.data.PumpEnactResult; +import info.nightscout.androidaps.db.Treatment; +import info.nightscout.androidaps.events.EventPumpStatusChanged; +import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPump; +import info.nightscout.androidaps.plugins.PumpDanaR.SerialIOThread; +import info.nightscout.androidaps.plugins.PumpDanaR.comm.MessageBase; +import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgBolusStop; +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.RecordTypes; +import info.nightscout.utils.SP; +import info.nightscout.utils.ToastUtils; + +/** + * Created by mike on 28.01.2018. + */ + +public abstract class AbstractDanaRExecutionService extends Service { + protected Logger log; + + protected String mDevName; + + protected BluetoothSocket mRfcommSocket; + protected BluetoothDevice mBTDevice; + + protected DanaRPump mDanaRPump = DanaRPump.getInstance(); + protected Treatment mBolusingTreatment = null; + + protected Boolean mConnectionInProgress = false; + + protected AbstractSerialIOThread mSerialIOThread; + + protected IBinder mBinder; + + protected final UUID SPP_UUID = UUID.fromString("00001101-0000-1000-8000-00805f9b34fb"); + + public abstract boolean updateBasalsInPump(final Profile profile); + + public abstract void connect(); + + public abstract void getPumpStatus(); + + public abstract PumpEnactResult loadEvents(); + + public abstract boolean bolus(double amount, int carbs, long carbtime, final Treatment t); + + public abstract boolean highTempBasal(int percent); // Rv2 only + + public abstract boolean tempBasal(int percent, int durationInHours); + + public abstract boolean tempBasalStop(); + + public abstract boolean extendedBolus(double insulin, int durationInHalfHours); + + public abstract boolean extendedBolusStop(); + + + protected 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 was disconnected " + device.getName());//Device was 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)); + } + } + } + }; + + @Override + public IBinder onBind(Intent intent) { + return mBinder; + } + + @Override + public int onStartCommand(Intent intent, int flags, int startId) { + return START_STICKY; + } + + public boolean isConnected() { + return mRfcommSocket != null && mRfcommSocket.isConnected(); + } + + public boolean isConnecting() { + return mConnectionInProgress; + } + + public void disconnect(String from) { + if (mSerialIOThread != null) + mSerialIOThread.disconnect(from); + } + + public void stopConnecting() { + if (mSerialIOThread != null) + mSerialIOThread.disconnect("stopConnecting"); + } + + protected void getBTSocketForSelectedPump() { + mDevName = 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 (mDevName.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)); + } + } + + public void bolusStop() { + if (Config.logDanaBTComm) + log.debug("bolusStop >>>>> @ " + (mBolusingTreatment == null ? "" : mBolusingTreatment.insulin)); + MsgBolusStop stop = new MsgBolusStop(); + stop.forced = true; + if (isConnected()) { + mSerialIOThread.sendMessage(stop); + while (!stop.stopped) { + mSerialIOThread.sendMessage(stop); + SystemClock.sleep(200); + } + } else { + stop.stopped = true; + } + } + + public PumpEnactResult loadHistory(byte type) { + PumpEnactResult result = new PumpEnactResult(); + if (!isConnected()) return result; + 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()); + SystemClock.sleep(400); + mSerialIOThread.sendMessage(msg); + while (!done.received && mRfcommSocket.isConnected()) { + SystemClock.sleep(100); + } + SystemClock.sleep(200); + mSerialIOThread.sendMessage(new MsgPCCommStop()); + result.success = true; + result.comment = "OK"; + return result; + } + + +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/services/AbstractSerialIOThread.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/services/AbstractSerialIOThread.java new file mode 100644 index 0000000000..1cca0b2512 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/services/AbstractSerialIOThread.java @@ -0,0 +1,13 @@ +package info.nightscout.androidaps.plugins.PumpDanaR.services; + +import info.nightscout.androidaps.plugins.PumpDanaR.comm.MessageBase; + +/** + * Created by mike on 28.01.2018. + */ + +public abstract class AbstractSerialIOThread extends Thread { + + public abstract void sendMessage(MessageBase message); + public abstract void disconnect(String reason); +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/services/DanaRExecutionService.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/services/DanaRExecutionService.java index 0aa4b176c7..63215464a8 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/services/DanaRExecutionService.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/services/DanaRExecutionService.java @@ -1,41 +1,33 @@ package info.nightscout.androidaps.plugins.PumpDanaR.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.SystemClock; import com.squareup.otto.Subscribe; -import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.io.IOException; 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.data.Profile; import info.nightscout.androidaps.data.PumpEnactResult; 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.data.Profile; import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin; import info.nightscout.androidaps.plugins.Overview.Dialogs.BolusProgressDialog; +import info.nightscout.androidaps.plugins.Overview.events.EventNewNotification; import info.nightscout.androidaps.plugins.Overview.events.EventOverviewBolusProgress; +import info.nightscout.androidaps.plugins.Overview.notifications.Notification; import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPlugin; import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPump; import info.nightscout.androidaps.plugins.PumpDanaR.SerialIOThread; @@ -45,18 +37,6 @@ import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgBolusStart; import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgBolusStartWithSpeed; 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; @@ -67,9 +47,9 @@ 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.MsgSettingMeal; 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; @@ -78,51 +58,18 @@ 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.EventDanaRNewStatus; -import info.nightscout.androidaps.plugins.Overview.notifications.Notification; -import info.nightscout.androidaps.plugins.Overview.events.EventNewNotification; import info.nightscout.androidaps.queue.Callback; import info.nightscout.utils.NSUpload; import info.nightscout.utils.SP; import info.nightscout.utils.ToastUtils; -public class DanaRExecutionService extends Service { - private static Logger log = LoggerFactory.getLogger(DanaRExecutionService.class); - - private String devName; - - private SerialIOThread mSerialIOThread; - private BluetoothSocket mRfcommSocket; - private BluetoothDevice mBTDevice; - - private IBinder mBinder = new LocalBinder(); - - private DanaRPump danaRPump = DanaRPump.getInstance(); - private Treatment bolusingTreatment = null; - - private static Boolean connectionInProgress = false; - - 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 was disconnected " + device.getName());//Device was 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 class DanaRExecutionService extends AbstractDanaRExecutionService{ public DanaRExecutionService() { + log = LoggerFactory.getLogger(DanaRExecutionService.class); + mBinder = new LocalBinder(); + registerBus(); MainApp.instance().getApplicationContext().registerReceiver(receiver, new IntentFilter(BluetoothDevice.ACTION_ACL_DISCONNECTED)); } @@ -133,17 +80,6 @@ public class DanaRExecutionService extends Service { } } - @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); @@ -154,49 +90,27 @@ public class DanaRExecutionService extends Service { } @Subscribe - public void onStatusEvent(EventAppExit event) { - if (Config.logFunctionCalls) - log.debug("EventAppExit received"); - + public void onStatusEvent(final EventPreferenceChange pch) { if (mSerialIOThread != null) - mSerialIOThread.disconnect("Application exit"); - - MainApp.instance().getApplicationContext().unregisterReceiver(receiver); - - stopSelf(); - if (Config.logFunctionCalls) - log.debug("EventAppExit finished"); + mSerialIOThread.disconnect("EventPreferenceChange"); } - 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)) { + public void connect() { + if (mDanaRPump.password != -1 && mDanaRPump.password != SP.getInt(R.string.key_danar_password, -1)) { ToastUtils.showToastInUiThread(MainApp.instance().getApplicationContext(), MainApp.sResources.getString(R.string.wrongpumppassword), R.raw.error); return; } - if (connectionInProgress) + if (mConnectionInProgress) return; new Thread(new Runnable() { @Override public void run() { - connectionInProgress = true; + mConnectionInProgress = true; getBTSocketForSelectedPump(); if (mRfcommSocket == null || mBTDevice == null) { - connectionInProgress = false; + mConnectionInProgress = false; return; // Device not found } @@ -217,48 +131,11 @@ public class DanaRExecutionService extends Service { MainApp.bus().post(new EventPumpStatusChanged(EventPumpStatusChanged.CONNECTED, 0)); } - connectionInProgress = false; + mConnectionInProgress = false; } }).start(); } - public void stopConnecting() { - if (mSerialIOThread != null) - mSerialIOThread.disconnect("stopConnecting"); - } - - 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"); - } - public void getPumpStatus() { try { MainApp.bus().post(new EventPumpStatusChanged(MainApp.sResources.getString(R.string.gettingpumpstatus))); @@ -268,7 +145,7 @@ public class DanaRExecutionService extends Service { MsgStatusBolusExtended exStatusMsg = new MsgStatusBolusExtended(); MsgCheckValue checkValue = new MsgCheckValue(); - if (danaRPump.isNewPump) { + if (mDanaRPump.isNewPump) { mSerialIOThread.sendMessage(checkValue); if (!checkValue.received) { return; @@ -283,8 +160,8 @@ public class DanaRExecutionService extends Service { mSerialIOThread.sendMessage(exStatusMsg); MainApp.bus().post(new EventPumpStatusChanged(MainApp.sResources.getString(R.string.gettingbolusstatus))); - Date now = new Date(); - if (danaRPump.lastSettingsRead.getTime() + 60 * 60 * 1000L < now.getTime() || !MainApp.getSpecificPlugin(DanaRPlugin.class).isInitialized()) { + long now = System.currentTimeMillis(); + if (mDanaRPump.lastSettingsRead + 60 * 60 * 1000L < now || !MainApp.getSpecificPlugin(DanaRPlugin.class).isInitialized()) { MainApp.bus().post(new EventPumpStatusChanged(MainApp.sResources.getString(R.string.gettingpumpsettings))); mSerialIOThread.sendMessage(new MsgSettingShippingInfo()); mSerialIOThread.sendMessage(new MsgSettingActiveProfile()); @@ -298,26 +175,26 @@ public class DanaRExecutionService extends Service { mSerialIOThread.sendMessage(new MsgSettingProfileRatiosAll()); MainApp.bus().post(new EventPumpStatusChanged(MainApp.sResources.getString(R.string.gettingpumptime))); mSerialIOThread.sendMessage(new MsgSettingPumpTime()); - long timeDiff = (danaRPump.pumpTime.getTime() - System.currentTimeMillis()) / 1000L; + long timeDiff = (mDanaRPump.pumpTime.getTime() - System.currentTimeMillis()) / 1000L; log.debug("Pump time difference: " + timeDiff + " seconds"); if (Math.abs(timeDiff) > 10) { mSerialIOThread.sendMessage(new MsgSetTime(new Date())); mSerialIOThread.sendMessage(new MsgSettingPumpTime()); - timeDiff = (danaRPump.pumpTime.getTime() - System.currentTimeMillis()) / 1000L; + timeDiff = (mDanaRPump.pumpTime.getTime() - System.currentTimeMillis()) / 1000L; log.debug("Pump time difference: " + timeDiff + " seconds"); } - danaRPump.lastSettingsRead = now; + mDanaRPump.lastSettingsRead = now; } - danaRPump.lastConnection = now; + mDanaRPump.lastConnection = now; MainApp.bus().post(new EventDanaRNewStatus()); MainApp.bus().post(new EventInitializationChanged()); NSUpload.uploadDeviceStatus(); - if (danaRPump.dailyTotalUnits > danaRPump.maxDailyTotalUnits * Constants.dailyLimitWarning) { - log.debug("Approaching daily limit: " + danaRPump.dailyTotalUnits + "/" + danaRPump.maxDailyTotalUnits); + if (mDanaRPump.dailyTotalUnits > mDanaRPump.maxDailyTotalUnits * Constants.dailyLimitWarning) { + log.debug("Approaching daily limit: " + mDanaRPump.dailyTotalUnits + "/" + mDanaRPump.maxDailyTotalUnits); Notification reportFail = new Notification(Notification.APPROACHING_DAILY_LIMIT, MainApp.sResources.getString(R.string.approachingdailylimit), Notification.URGENT); MainApp.bus().post(new EventNewNotification(reportFail)); - NSUpload.uploadError(MainApp.sResources.getString(R.string.approachingdailylimit) + ": " + danaRPump.dailyTotalUnits + "/" + danaRPump.maxDailyTotalUnits + "U"); + NSUpload.uploadError(MainApp.sResources.getString(R.string.approachingdailylimit) + ": " + mDanaRPump.dailyTotalUnits + "/" + mDanaRPump.maxDailyTotalUnits + "U"); } } catch (Exception e) { log.error("Unhandled exception", e); @@ -326,10 +203,10 @@ public class DanaRExecutionService extends Service { public boolean tempBasal(int percent, int durationInHours) { if (!isConnected()) return false; - if (danaRPump.isTempBasalInProgress) { + if (mDanaRPump.isTempBasalInProgress) { MainApp.bus().post(new EventPumpStatusChanged(MainApp.sResources.getString(R.string.stoppingtempbasal))); mSerialIOThread.sendMessage(new MsgSetTempBasalStop()); - waitMsec(500); + SystemClock.sleep(500); } MainApp.bus().post(new EventPumpStatusChanged(MainApp.sResources.getString(R.string.settingtempbasal))); mSerialIOThread.sendMessage(new MsgSetTempBasalStart(percent, durationInHours)); @@ -365,11 +242,16 @@ public class DanaRExecutionService extends Service { return true; } - public boolean bolus(double amount, int carbs, final Treatment t) { + @Override + public PumpEnactResult loadEvents() { + return null; + } + + public boolean bolus(double amount, int carbs, long carbtime, final Treatment t) { if (!isConnected()) return false; if (BolusProgressDialog.stopPressed) return false; - bolusingTreatment = t; + mBolusingTreatment = t; int preferencesSpeed = SP.getInt(R.string.key_danars_bolusspeed, 0); MessageBase start; if (preferencesSpeed == 0) @@ -379,7 +261,7 @@ public class DanaRExecutionService extends Service { MsgBolusStop stop = new MsgBolusStop(amount, t); if (carbs > 0) { - mSerialIOThread.sendMessage(new MsgSetCarbsEntry(System.currentTimeMillis(), carbs)); + mSerialIOThread.sendMessage(new MsgSetCarbsEntry(carbtime, carbs)); } MsgBolusProgress progress = new MsgBolusProgress(amount, t); // initialize static variables @@ -392,20 +274,20 @@ public class DanaRExecutionService extends Service { return false; } while (!stop.stopped && !start.failed) { - waitMsec(100); + SystemClock.sleep(100); if ((System.currentTimeMillis() - progress.lastReceive) > 15 * 1000L) { // if i didn't receive status for more than 15 sec expecting broken comm stop.stopped = true; stop.forced = true; log.debug("Communication stopped"); } } - waitMsec(300); + SystemClock.sleep(300); EventOverviewBolusProgress bolusingEvent = EventOverviewBolusProgress.getInstance(); bolusingEvent.t = t; bolusingEvent.percent = 99; - bolusingTreatment = null; + mBolusingTreatment = null; int speed = 12; switch (preferencesSpeed) { @@ -437,11 +319,11 @@ public class DanaRExecutionService extends Service { ConfigBuilderPlugin.getCommandQueue().independentConnect("bolusingInterrupted", new Callback() { @Override public void run() { - if (danaRPump.lastBolusTime.getTime() > System.currentTimeMillis() - 60 * 1000L) { // last bolus max 1 min old - t.insulin = danaRPump.lastBolusAmount; - log.debug("Used bolus amount from history: " + danaRPump.lastBolusAmount); + if (mDanaRPump.lastBolusTime.getTime() > System.currentTimeMillis() - 60 * 1000L) { // last bolus max 1 min old + t.insulin = mDanaRPump.lastBolusAmount; + log.debug("Used bolus amount from history: " + mDanaRPump.lastBolusAmount); } else { - log.debug("Bolus amount in history too old: " + danaRPump.lastBolusTime.toLocaleString()); + log.debug("Bolus amount in history too old: " + mDanaRPump.lastBolusTime.toLocaleString()); } synchronized (o) { o.notify(); @@ -460,22 +342,6 @@ public class DanaRExecutionService extends Service { 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) { if (!isConnected()) return false; MsgSetCarbsEntry msg = new MsgSetCarbsEntry(System.currentTimeMillis(), amount); @@ -483,51 +349,9 @@ public class DanaRExecutionService extends Service { return true; } - public PumpEnactResult loadHistory(byte type) { - PumpEnactResult result = new PumpEnactResult(); - if (!isConnected()) return result; - 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()); - result.success = true; - result.comment = "OK"; - return result; + @Override + public boolean highTempBasal(int percent) { + return false; } public boolean updateBasalsInPump(final Profile profile) { @@ -538,13 +362,25 @@ public class DanaRExecutionService extends Service { mSerialIOThread.sendMessage(msgSet); MsgSetActivateBasalProfile msgActivate = new MsgSetActivateBasalProfile((byte) 0); mSerialIOThread.sendMessage(msgActivate); - danaRPump.lastSettingsRead = new Date(0); // force read full settings + mDanaRPump.lastSettingsRead = 0; // force read full settings getPumpStatus(); MainApp.bus().post(new EventPumpStatusChanged(EventPumpStatusChanged.DISCONNECTING)); return true; } - private void waitMsec(long msecs) { - SystemClock.sleep(msecs); + @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"); } + } 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 e92febada6..58392e65f9 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 @@ -5,71 +5,31 @@ import android.content.Context; import android.content.Intent; import android.content.ServiceConnection; import android.os.IBinder; -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.DetailedBolusInfo; -import info.nightscout.androidaps.data.Profile; -import info.nightscout.androidaps.data.ProfileStore; import info.nightscout.androidaps.data.PumpEnactResult; -import info.nightscout.androidaps.db.ExtendedBolus; import info.nightscout.androidaps.db.TemporaryBasal; import info.nightscout.androidaps.db.Treatment; import info.nightscout.androidaps.events.EventAppExit; import info.nightscout.androidaps.events.EventPreferenceChange; -import info.nightscout.androidaps.interfaces.ConstraintsInterface; -import info.nightscout.androidaps.interfaces.DanaRInterface; -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.Overview.notifications.Notification; -import info.nightscout.androidaps.plugins.Overview.events.EventDismissNotification; -import info.nightscout.androidaps.plugins.Overview.events.EventNewNotification; -import info.nightscout.androidaps.plugins.ProfileNS.NSProfilePlugin; -import info.nightscout.androidaps.plugins.PumpDanaR.DanaRFragment; -import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPump; +import info.nightscout.androidaps.plugins.PumpDanaR.AbstractDanaRPlugin; import info.nightscout.androidaps.plugins.PumpDanaRKorean.services.DanaRKoreanExecutionService; -import info.nightscout.utils.DateUtil; -import info.nightscout.utils.DecimalFormatter; import info.nightscout.utils.Round; import info.nightscout.utils.SP; /** * Created by mike on 05.08.2016. */ -public class DanaRKoreanPlugin implements PluginBase, PumpInterface, DanaRInterface, ConstraintsInterface, ProfileInterface { - private static Logger log = LoggerFactory.getLogger(DanaRKoreanPlugin.class); - - @Override - public String getFragmentClass() { - return DanaRFragment.class.getName(); - } - - private static boolean fragmentPumpEnabled = false; - private static boolean fragmentProfileEnabled = false; - private static boolean fragmentPumpVisible = true; - - private static DanaRKoreanExecutionService sExecutionService; - - - private static DanaRPump pump = DanaRPump.getInstance(); - private boolean useExtendedBoluses = false; +public class DanaRKoreanPlugin extends AbstractDanaRPlugin { private static DanaRKoreanPlugin plugin = null; @@ -79,9 +39,8 @@ public class DanaRKoreanPlugin implements PluginBase, PumpInterface, DanaRInterf return plugin; } - public static PumpDescription pumpDescription = new PumpDescription(); - public DanaRKoreanPlugin() { + log = LoggerFactory.getLogger(DanaRKoreanPlugin.class); useExtendedBoluses = SP.getBoolean("danar_useextended", false); Context context = MainApp.instance().getApplicationContext(); @@ -149,83 +108,17 @@ public class DanaRKoreanPlugin implements PluginBase, PumpInterface, DanaRInterf } // Plugin base interface - @Override - public int getType() { - return PluginBase.PUMP; - } - @Override public String getName() { return MainApp.instance().getString(R.string.danarkoreanpump); } - @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 type == PUMP; - } - - @Override - public void setFragmentEnabled(int type, boolean fragmentEnabled) { - if (type == PluginBase.PROFILE) - fragmentProfileEnabled = fragmentEnabled; - else if (type == PluginBase.PUMP) - fragmentPumpEnabled = fragmentEnabled; - // if pump profile was enabled need to switch to another too - if (type == PluginBase.PUMP && !fragmentEnabled && fragmentProfileEnabled) { - setFragmentEnabled(PluginBase.PROFILE, false); - setFragmentVisible(PluginBase.PROFILE, false); - NSProfilePlugin.getPlugin().setFragmentEnabled(PluginBase.PROFILE, true); - NSProfilePlugin.getPlugin().setFragmentVisible(PluginBase.PROFILE, true); - } - } - - @Override - public void setFragmentVisible(int type, boolean fragmentVisible) { - if (type == PluginBase.PUMP) - fragmentPumpVisible = fragmentVisible; - } - @Override public int getPreferencesId() { return R.xml.pref_danarkorean; } + // Pump interface @Override public boolean isFakingTempsByExtendedBoluses() { return useExtendedBoluses; @@ -233,82 +126,7 @@ public class DanaRKoreanPlugin implements PluginBase, PumpInterface, DanaRInterf @Override public boolean isInitialized() { - return pump.lastConnection.getTime() > 0 && pump.maxBasal > 0 && !pump.isConfigUD && !pump.isEasyModeEnabled && pump.isExtendedBolusEnabled; - } - - @Override - public boolean isSuspended() { - return pump.pumpSuspended; - } - - @Override - public boolean isBusy() { - if (sExecutionService == null) return false; - return sExecutionService.isConnected() || sExecutionService.isConnecting(); - } - - // Pump interface - @Override - public PumpEnactResult setNewBasalProfile(Profile profile) { - PumpEnactResult result = new PumpEnactResult(); - - if (sExecutionService == null) { - log.error("setNewBasalProfile sExecutionService is null"); - result.comment = "setNewBasalProfile sExecutionService is null"; - return result; - } - 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)); - result.comment = MainApp.sResources.getString(R.string.pumpNotInitializedProfileNotSet); - return result; - } 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)); - result.comment = MainApp.sResources.getString(R.string.failedupdatebasalprofile); - return result; - } else { - MainApp.bus().post(new EventDismissNotification(Notification.PROFILE_NOT_SET_NOT_INITIALIZED)); - MainApp.bus().post(new EventDismissNotification(Notification.FAILED_UDPATE_PROFILE)); - result.success = true; - result.enacted = true; - result.comment = "OK"; - return result; - } - } - - @Override - public boolean isThisProfileSet(Profile profile) { - if (!isInitialized()) - return true; // TODO: not sure what's better. so far TRUE to prevent too many SMS - 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((Integer) (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 pump.lastConnection; - } - - @Override - public double getBaseBasalRate() { - return pump.currentBasal; + return pump.lastConnection > 0 && pump.maxBasal > 0 && !pump.isConfigUD && !pump.isEasyModeEnabled && pump.isExtendedBolusEnabled; } @Override @@ -318,7 +136,7 @@ public class DanaRKoreanPlugin implements PluginBase, PumpInterface, DanaRInterf if (detailedBolusInfo.insulin > 0 || detailedBolusInfo.carbs > 0) { Treatment t = new Treatment(); boolean connectionOK = false; - if (detailedBolusInfo.insulin > 0 || detailedBolusInfo.carbs > 0) connectionOK = sExecutionService.bolus(detailedBolusInfo.insulin, (int) detailedBolusInfo.carbs, t); + if (detailedBolusInfo.insulin > 0 || detailedBolusInfo.carbs > 0) connectionOK = sExecutionService.bolus(detailedBolusInfo.insulin, (int) detailedBolusInfo.carbs, detailedBolusInfo.carbTime, t); PumpEnactResult result = new PumpEnactResult(); result.success = connectionOK; result.bolusDelivered = t.insulin; @@ -341,15 +159,6 @@ public class DanaRKoreanPlugin implements PluginBase, PumpInterface, DanaRInterf } } - @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, boolean enforceNew) { @@ -502,100 +311,6 @@ public class DanaRKoreanPlugin implements PluginBase, PumpInterface, DanaRInterf return result; } - @Override - public PumpEnactResult setTempBasalPercent(Integer percent, Integer durationInMinutes, boolean enforceNew) { - 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().maxTempPercent) - percent = getPumpDescription().maxTempPercent; - TemporaryBasal runningTB = MainApp.getConfigBuilder().getRealTempBasalFromHistory(System.currentTimeMillis()); - if (runningTB != null && runningTB.percentRate == percent && enforceNew) { - result.enacted = false; - result.success = true; - result.isTempCancel = false; - result.comment = MainApp.instance().getString(R.string.virtualpump_resultok); - result.duration = pump.tempBasalRemainingMin; - result.percent = pump.tempBasalPercent; - result.absolute = MainApp.getConfigBuilder().getTempBasalAbsoluteRateHistory(); - result.isPercent = true; - if (Config.logPumpActions) - log.debug("setTempBasalPercent: Correct value already set"); - return result; - } - int durationInHours = Math.max(durationInMinutes / 60, 1); - boolean connectionOK = sExecutionService.tempBasal(percent, durationInHours); - if (connectionOK && pump.isTempBasalInProgress && pump.tempBasalPercent == percent) { - result.enacted = true; - result.success = true; - result.comment = MainApp.instance().getString(R.string.virtualpump_resultok); - result.isTempCancel = false; - result.duration = pump.tempBasalRemainingMin; - result.percent = pump.tempBasalPercent; - result.absolute = MainApp.getConfigBuilder().getTempBasalAbsoluteRateHistory(); - 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 - int durationInHalfHours = Math.max(durationInMinutes / 30, 1); - insulin = Round.roundTo(insulin, getPumpDescription().extendedBolusStep); - - PumpEnactResult result = new PumpEnactResult(); - ExtendedBolus runningEB = MainApp.getConfigBuilder().getExtendedBolusFromHistory(System.currentTimeMillis()); - if (runningEB != null && Math.abs(runningEB.insulin - insulin) < getPumpDescription().extendedBolusStep) { - result.enacted = false; - result.success = true; - result.comment = MainApp.instance().getString(R.string.virtualpump_resultok); - result.duration = pump.extendedBolusRemainingMinutes; - result.absolute = pump.extendedBolusAbsoluteRate; - result.isPercent = false; - result.isTempCancel = false; - if (Config.logPumpActions) - log.debug("setExtendedBolus: Correct extended bolus already set. Current: " + pump.extendedBolusAmount + " Asked: " + insulin); - return result; - } - boolean connectionOK = sExecutionService.extendedBolus(insulin, durationInHalfHours); - if (connectionOK && pump.isExtendedInProgress && Math.abs(pump.extendedBolusAmount - insulin) < getPumpDescription().extendedBolusStep) { - result.enacted = true; - result.success = true; - result.comment = MainApp.instance().getString(R.string.virtualpump_resultok); - result.isTempCancel = false; - result.duration = pump.extendedBolusRemainingMinutes; - result.absolute = pump.extendedBolusAbsoluteRate; - result.bolusDelivered = pump.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(boolean force) { if (MainApp.getConfigBuilder().isInHistoryRealTempBasalInProgress()) @@ -636,257 +351,8 @@ public class DanaRKoreanPlugin implements PluginBase, PumpInterface, DanaRInterf } } - @Override - public PumpEnactResult cancelExtendedBolus() { - PumpEnactResult result = new PumpEnactResult(); - ExtendedBolus runningEB = MainApp.getConfigBuilder().getExtendedBolusFromHistory(System.currentTimeMillis()); - if (runningEB != null) { - sExecutionService.extendedBolusStop(); - result.enacted = true; - result.isTempCancel = true; - } - if (!pump.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; - } - } - - @Override - public void connect(String from) { - if (sExecutionService != null) { - sExecutionService.connect(from); - pumpDescription.basalStep = pump.basalStep; - pumpDescription.bolusStep = pump.bolusStep; - } - } - - @Override - public boolean isConnected() { - return sExecutionService != null && sExecutionService.isConnected(); - } - - @Override - public boolean isConnecting() { - return sExecutionService != null && sExecutionService.isConnecting(); - } - - @Override - public void disconnect(String from) { - if (sExecutionService != null) sExecutionService.disconnect(from); - } - - @Override - public void stopConnecting() { - if (sExecutionService != null) sExecutionService.stopConnecting(); - } - - @Override - public void getPumpStatus() { - if (sExecutionService != null) sExecutionService.getPumpStatus(); - } - - @Override - public JSONObject getJSONStatus() { - if (pump.lastConnection.getTime() + 5 * 60 * 1000L < System.currentTimeMillis()) { - return null; - } - JSONObject pumpjson = new JSONObject(); - JSONObject battery = new JSONObject(); - JSONObject status = new JSONObject(); - JSONObject extended = new JSONObject(); - try { - battery.put("percent", pump.batteryRemaining); - status.put("status", pump.pumpSuspended ? "suspended" : "normal"); - status.put("timestamp", DateUtil.toISOString(pump.lastConnection)); - extended.put("Version", BuildConfig.VERSION_NAME + "-" + BuildConfig.BUILDVERSION); - extended.put("PumpIOB", pump.iob); - if (pump.lastBolusTime.getTime() != 0) { - extended.put("LastBolus", pump.lastBolusTime.toLocaleString()); - extended.put("LastBolusAmount", pump.lastBolusAmount); - } - TemporaryBasal tb = MainApp.getConfigBuilder().getRealTempBasalFromHistory(System.currentTimeMillis()); - if (tb != null) { - extended.put("TempBasalAbsoluteRate", tb.tempBasalConvertedToAbsolute(System.currentTimeMillis())); - extended.put("TempBasalStart", DateUtil.dateAndTimeString(tb.date)); - extended.put("TempBasalRemaining", tb.getPlannedRemainingMinutes()); - } - ExtendedBolus eb = MainApp.getConfigBuilder().getExtendedBolusFromHistory(System.currentTimeMillis()); - if (eb != null) { - extended.put("ExtendedBolusAbsoluteRate", eb.absoluteRate()); - extended.put("ExtendedBolusStart", DateUtil.dateAndTimeString(eb.date)); - extended.put("ExtendedBolusRemaining", eb.getPlannedRemainingMinutes()); - } - extended.put("BaseBasalRate", getBaseBasalRate()); - try { - extended.put("ActiveProfile", MainApp.getConfigBuilder().getProfileName()); - } catch (Exception e) { - } - - pumpjson.put("battery", battery); - pumpjson.put("status", status); - pumpjson.put("extended", extended); - pumpjson.put("reservoir", (int) pump.reservoirRemainingUnits); - pumpjson.put("clock", DateUtil.toISOString(new Date())); - } catch (JSONException e) { - log.error("Unhandled exception", e); - } - return pumpjson; - } - - @Override - public String deviceID() { - return pump.serialNumber; - } - - @Override - public PumpDescription getPumpDescription() { - return pumpDescription; - } - - /** - * DanaR interface - */ - - @Override - public PumpEnactResult loadHistory(byte type) { - return sExecutionService.loadHistory(type); - } - @Override public PumpEnactResult loadEvents() { return null; // no history, not needed } - - /** - * 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; - } - - @Override - public boolean isSMBModeEnabled() { - return true; - } - - @SuppressWarnings("PointlessBooleanExpression") - @Override - public Double applyBasalConstraints(Double absoluteRate) { - double origAbsoluteRate = absoluteRate; - if (pump != null) { - if (absoluteRate > pump.maxBasal) { - absoluteRate = pump.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().maxTempPercent) - percentRate = getPumpDescription().maxTempPercent; - 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 (pump != null) { - if (insulin > pump.maxBolus) { - insulin = pump.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 ProfileStore getProfile() { - if (pump.lastSettingsRead.getTime() == 0) - return null; // no info now - return pump.createConvertedProfile(); - } - - @Override - public String getUnits() { - return pump.getUnits(); - } - - @Override - public String getProfileName() { - return pump.createConvertedProfileName(); - } - - // Reply for sms communicator - public String shortStatus(boolean veryShort) { - String ret = ""; - if (pump.lastConnection.getTime() != 0) { - Long agoMsec = System.currentTimeMillis() - pump.lastConnection.getTime(); - int agoMin = (int) (agoMsec / 60d / 1000d); - ret += "LastConn: " + agoMin + " minago\n"; - } - if (pump.lastBolusTime.getTime() != 0) { - ret += "LastBolus: " + DecimalFormatter.to2Decimal(pump.lastBolusAmount) + "U @" + android.text.format.DateFormat.format("HH:mm", pump.lastBolusTime) + "\n"; - } - if (MainApp.getConfigBuilder().isInHistoryRealTempBasalInProgress()) { - ret += "Temp: " + MainApp.getConfigBuilder().getRealTempBasalFromHistory(System.currentTimeMillis()).toStringFull() + "\n"; - } - if (MainApp.getConfigBuilder().isInHistoryExtendedBoluslInProgress()) { - ret += "Extended: " + MainApp.getConfigBuilder().getExtendedBolusFromHistory(System.currentTimeMillis()).toString() + "\n"; - } - if (!veryShort) { - ret += "TDD: " + DecimalFormatter.to0Decimal(pump.dailyTotalUnits) + " / " + pump.maxDailyTotalUnits + " U\n"; - } - ret += "IOB: " + pump.iob + "U\n"; - ret += "Reserv: " + DecimalFormatter.to0Decimal(pump.reservoirRemainingUnits) + "U\n"; - ret += "Batt: " + pump.batteryRemaining + "\n"; - return ret; - } - // TODO: daily total constraint - } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRKorean/SerialIOThread.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRKorean/SerialIOThread.java index 8672afdcb0..9a8f3edb05 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRKorean/SerialIOThread.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRKorean/SerialIOThread.java @@ -13,13 +13,14 @@ import java.io.OutputStream; import info.nightscout.androidaps.Config; import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPump; import info.nightscout.androidaps.plugins.PumpDanaR.comm.MessageBase; +import info.nightscout.androidaps.plugins.PumpDanaR.services.AbstractSerialIOThread; import info.nightscout.androidaps.plugins.PumpDanaRKorean.comm.MessageHashTable_k; import info.nightscout.utils.CRC; /** * Created by mike on 17.07.2016. */ -public class SerialIOThread extends Thread { +public class SerialIOThread extends AbstractSerialIOThread { private static Logger log = LoggerFactory.getLogger(SerialIOThread.class); private InputStream mInputStream = null; @@ -29,10 +30,10 @@ public class SerialIOThread extends Thread { private boolean mKeepRunning = true; private byte[] mReadBuff = new byte[0]; - MessageBase processedMessage; + private MessageBase processedMessage; public SerialIOThread(BluetoothSocket rfcommSocket) { - super(SerialIOThread.class.toString()); + super(); mRfCommSocket = rfcommSocket; try { @@ -138,6 +139,7 @@ public class SerialIOThread extends Thread { } } + @Override public synchronized void sendMessage(MessageBase message) { if (!mRfCommSocket.isConnected()) { log.error("Socket not connected on sendMessage"); @@ -173,6 +175,7 @@ public class SerialIOThread extends Thread { } } + @Override public void disconnect(String reason) { mKeepRunning = false; try { diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRKorean/comm/MsgInitConnStatusTime_k.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRKorean/comm/MsgInitConnStatusTime_k.java index 641dce79f3..3cf47b656f 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRKorean/comm/MsgInitConnStatusTime_k.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRKorean/comm/MsgInitConnStatusTime_k.java @@ -37,7 +37,7 @@ public class MsgInitConnStatusTime_k extends MessageBase { MainApp.getSpecificPlugin(DanaRKoreanPlugin.class).setFragmentVisible(PluginBase.PUMP, false); MainApp.getSpecificPlugin(DanaRPlugin.class).setFragmentEnabled(PluginBase.PUMP, true); MainApp.getSpecificPlugin(DanaRPlugin.class).setFragmentVisible(PluginBase.PUMP, true); - DanaRPump.getInstance().lastConnection = new Date(0); // mark not initialized + DanaRPump.getInstance().lastConnection = 0; // mark not initialized //If profile coming from pump, switch it as well if (MainApp.getSpecificPlugin(DanaRKoreanPlugin.class).isEnabled(PluginBase.PROFILE)) { diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRKorean/comm/MsgSettingBasal_k.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRKorean/comm/MsgSettingBasal_k.java index 72a8be4e42..5c8b40b959 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRKorean/comm/MsgSettingBasal_k.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRKorean/comm/MsgSettingBasal_k.java @@ -24,7 +24,7 @@ public class MsgSettingBasal_k extends MessageBase { pump.pumpProfiles[pump.activeProfile] = new double[24]; for (int index = 0; index < 24; index++) { int basal = intFromBuff(bytes, 2 * index, 2); - if (basal < DanaRKoreanPlugin.pumpDescription.basalMinimumRate) basal = 0; + if (basal < DanaRKoreanPlugin.getPlugin().pumpDescription.basalMinimumRate) basal = 0; pump.pumpProfiles[pump.activeProfile][index] = basal / 100d; } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRKorean/services/DanaRKoreanExecutionService.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRKorean/services/DanaRKoreanExecutionService.java index 4efff4a5ad..6d1ccc132d 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRKorean/services/DanaRKoreanExecutionService.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRKorean/services/DanaRKoreanExecutionService.java @@ -1,58 +1,36 @@ package info.nightscout.androidaps.plugins.PumpDanaRKorean.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.SystemClock; import com.squareup.otto.Subscribe; -import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.io.IOException; 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.data.Profile; import info.nightscout.androidaps.data.PumpEnactResult; 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.data.Profile; import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin; import info.nightscout.androidaps.plugins.Overview.Dialogs.BolusProgressDialog; -import info.nightscout.androidaps.plugins.Overview.events.EventOverviewBolusProgress; +import info.nightscout.androidaps.plugins.Overview.events.EventNewNotification; +import info.nightscout.androidaps.plugins.Overview.notifications.Notification; 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.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.MsgSetCarbsEntry; import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgSetExtendedBolusStart; import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgSetExtendedBolusStop; @@ -68,56 +46,23 @@ import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgSettingPumpTime; import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgSettingShippingInfo; 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.EventDanaRNewStatus; +import info.nightscout.androidaps.plugins.PumpDanaR.services.AbstractDanaRExecutionService; import info.nightscout.androidaps.plugins.PumpDanaRKorean.DanaRKoreanPlugin; import info.nightscout.androidaps.plugins.PumpDanaRKorean.SerialIOThread; -import info.nightscout.androidaps.plugins.Overview.notifications.Notification; -import info.nightscout.androidaps.plugins.Overview.events.EventNewNotification; import info.nightscout.androidaps.plugins.PumpDanaRKorean.comm.MsgCheckValue_k; import info.nightscout.androidaps.plugins.PumpDanaRKorean.comm.MsgSettingBasal_k; import info.nightscout.androidaps.plugins.PumpDanaRKorean.comm.MsgStatusBasic_k; -import info.nightscout.androidaps.queue.Callback; import info.nightscout.utils.NSUpload; import info.nightscout.utils.SP; import info.nightscout.utils.ToastUtils; -public class DanaRKoreanExecutionService extends Service { - private static Logger log = LoggerFactory.getLogger(DanaRKoreanExecutionService.class); - - private String devName; - - private SerialIOThread mSerialIOThread; - private BluetoothSocket mRfcommSocket; - private BluetoothDevice mBTDevice; - - private IBinder mBinder = new LocalBinder(); - - private DanaRPump danaRPump = DanaRPump.getInstance(); - private Treatment bolusingTreatment = null; - - private static Boolean connectionInProgress = false; - - 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 was disconnected " + device.getName());//Device was 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 class DanaRKoreanExecutionService extends AbstractDanaRExecutionService { public DanaRKoreanExecutionService() { + log = LoggerFactory.getLogger(DanaRKoreanExecutionService.class); + mBinder = new LocalBinder(); + registerBus(); MainApp.instance().getApplicationContext().registerReceiver(receiver, new IntentFilter(BluetoothDevice.ACTION_ACL_DISCONNECTED)); } @@ -128,17 +73,6 @@ public class DanaRKoreanExecutionService extends Service { } } - @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); @@ -163,35 +97,28 @@ public class DanaRKoreanExecutionService extends Service { log.debug("EventAppExit finished"); } - public boolean isConnected() { - return mRfcommSocket != null && mRfcommSocket.isConnected(); - } - - public boolean isConnecting() { - return connectionInProgress; - } - - public void disconnect(String from) { + @Subscribe + public void onStatusEvent(final EventPreferenceChange pch) { if (mSerialIOThread != null) - mSerialIOThread.disconnect(from); + mSerialIOThread.disconnect("EventPreferenceChange"); } - public void connect(String from) { - if (danaRPump.password != -1 && danaRPump.password != SP.getInt(R.string.key_danar_password, -1)) { + public void connect() { + if (mDanaRPump.password != -1 && mDanaRPump.password != SP.getInt(R.string.key_danar_password, -1)) { ToastUtils.showToastInUiThread(MainApp.instance().getApplicationContext(), MainApp.sResources.getString(R.string.wrongpumppassword), R.raw.error); return; } - if (connectionInProgress) + if (mConnectionInProgress) return; new Thread(new Runnable() { @Override public void run() { - connectionInProgress = true; + mConnectionInProgress = true; getBTSocketForSelectedPump(); if (mRfcommSocket == null || mBTDevice == null) { - connectionInProgress = false; + mConnectionInProgress = false; return; // Device not found } @@ -212,48 +139,11 @@ public class DanaRKoreanExecutionService extends Service { MainApp.bus().post(new EventPumpStatusChanged(EventPumpStatusChanged.CONNECTED, 0)); } - connectionInProgress = false; + mConnectionInProgress = false; } }).start(); } - public void stopConnecting() { - if (mSerialIOThread != null) - mSerialIOThread.disconnect("stopConnecting"); - } - - 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"); - } - public void getPumpStatus() { try { MainApp.bus().post(new EventPumpStatusChanged(MainApp.sResources.getString(R.string.gettingpumpstatus))); @@ -263,7 +153,7 @@ public class DanaRKoreanExecutionService extends Service { MsgStatusBolusExtended exStatusMsg = new MsgStatusBolusExtended(); MsgCheckValue_k checkValue = new MsgCheckValue_k(); - if (danaRPump.isNewPump) { + if (mDanaRPump.isNewPump) { mSerialIOThread.sendMessage(checkValue); if (!checkValue.received) { return; @@ -278,8 +168,8 @@ public class DanaRKoreanExecutionService extends Service { mSerialIOThread.sendMessage(exStatusMsg); MainApp.bus().post(new EventPumpStatusChanged(MainApp.sResources.getString(R.string.gettingbolusstatus))); - Date now = new Date(); - if (danaRPump.lastSettingsRead.getTime() + 60 * 60 * 1000L < now.getTime() || !MainApp.getSpecificPlugin(DanaRKoreanPlugin.class).isInitialized()) { + long now = System.currentTimeMillis(); + if (mDanaRPump.lastSettingsRead + 60 * 60 * 1000L < now || !MainApp.getSpecificPlugin(DanaRKoreanPlugin.class).isInitialized()) { MainApp.bus().post(new EventPumpStatusChanged(MainApp.sResources.getString(R.string.gettingpumpsettings))); mSerialIOThread.sendMessage(new MsgSettingShippingInfo()); mSerialIOThread.sendMessage(new MsgSettingMeal()); @@ -290,39 +180,38 @@ public class DanaRKoreanExecutionService extends Service { mSerialIOThread.sendMessage(new MsgSettingProfileRatios()); MainApp.bus().post(new EventPumpStatusChanged(MainApp.sResources.getString(R.string.gettingpumptime))); mSerialIOThread.sendMessage(new MsgSettingPumpTime()); - long timeDiff = (danaRPump.pumpTime.getTime() - System.currentTimeMillis()) / 1000L; + long timeDiff = (mDanaRPump.pumpTime.getTime() - System.currentTimeMillis()) / 1000L; log.debug("Pump time difference: " + timeDiff + " seconds"); if (Math.abs(timeDiff) > 10) { mSerialIOThread.sendMessage(new MsgSetTime(new Date())); mSerialIOThread.sendMessage(new MsgSettingPumpTime()); - timeDiff = (danaRPump.pumpTime.getTime() - System.currentTimeMillis()) / 1000L; + timeDiff = (mDanaRPump.pumpTime.getTime() - System.currentTimeMillis()) / 1000L; log.debug("Pump time difference: " + timeDiff + " seconds"); } - danaRPump.lastSettingsRead = now; + mDanaRPump.lastSettingsRead = now; } - danaRPump.lastConnection = now; + mDanaRPump.lastConnection = now; MainApp.bus().post(new EventDanaRNewStatus()); MainApp.bus().post(new EventInitializationChanged()); NSUpload.uploadDeviceStatus(); - if (danaRPump.dailyTotalUnits > danaRPump.maxDailyTotalUnits * Constants.dailyLimitWarning) { - log.debug("Approaching daily limit: " + danaRPump.dailyTotalUnits + "/" + danaRPump.maxDailyTotalUnits); + if (mDanaRPump.dailyTotalUnits > mDanaRPump.maxDailyTotalUnits * Constants.dailyLimitWarning) { + log.debug("Approaching daily limit: " + mDanaRPump.dailyTotalUnits + "/" + mDanaRPump.maxDailyTotalUnits); Notification reportFail = new Notification(Notification.APPROACHING_DAILY_LIMIT, MainApp.sResources.getString(R.string.approachingdailylimit), Notification.URGENT); MainApp.bus().post(new EventNewNotification(reportFail)); - NSUpload.uploadError(MainApp.sResources.getString(R.string.approachingdailylimit) + ": " + danaRPump.dailyTotalUnits + "/" + danaRPump.maxDailyTotalUnits + "U"); + NSUpload.uploadError(MainApp.sResources.getString(R.string.approachingdailylimit) + ": " + mDanaRPump.dailyTotalUnits + "/" + mDanaRPump.maxDailyTotalUnits + "U"); } } catch (Exception e) { log.error("Unhandled exception", e); } - return; } public boolean tempBasal(int percent, int durationInHours) { if (!isConnected()) return false; - if (danaRPump.isTempBasalInProgress) { + if (mDanaRPump.isTempBasalInProgress) { MainApp.bus().post(new EventPumpStatusChanged(MainApp.sResources.getString(R.string.stoppingtempbasal))); mSerialIOThread.sendMessage(new MsgSetTempBasalStop()); - waitMsec(500); + SystemClock.sleep(500); } MainApp.bus().post(new EventPumpStatusChanged(MainApp.sResources.getString(R.string.settingtempbasal))); mSerialIOThread.sendMessage(new MsgSetTempBasalStart(percent, durationInHours)); @@ -358,16 +247,21 @@ public class DanaRKoreanExecutionService extends Service { return true; } - public boolean bolus(double amount, int carbs, final Treatment t) { + @Override + public PumpEnactResult loadEvents() { + return null; + } + + public boolean bolus(double amount, int carbs, long carbtime, final Treatment t) { if (!isConnected()) return false; if (BolusProgressDialog.stopPressed) return false; - bolusingTreatment = t; + mBolusingTreatment = t; MsgBolusStart start = new MsgBolusStart(amount); MsgBolusStop stop = new MsgBolusStop(amount, t); if (carbs > 0) { - mSerialIOThread.sendMessage(new MsgSetCarbsEntry(System.currentTimeMillis(), carbs)); + mSerialIOThread.sendMessage(new MsgSetCarbsEntry(carbtime, carbs)); } MsgBolusProgress progress = new MsgBolusProgress(amount, t); // initialize static variables @@ -380,37 +274,21 @@ public class DanaRKoreanExecutionService extends Service { return false; } while (!stop.stopped && !start.failed) { - waitMsec(100); + SystemClock.sleep(100); if ((System.currentTimeMillis() - progress.lastReceive) > 15 * 1000L) { // if i didn't receive status for more than 15 sec expecting broken comm stop.stopped = true; stop.forced = true; log.debug("Communication stopped"); } } - waitMsec(300); + SystemClock.sleep(300); - bolusingTreatment = null; + mBolusingTreatment = null; ConfigBuilderPlugin.getCommandQueue().readStatus("bolusOK", null); 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) { if (!isConnected()) return false; MsgSetCarbsEntry msg = new MsgSetCarbsEntry(System.currentTimeMillis(), amount); @@ -418,51 +296,9 @@ public class DanaRKoreanExecutionService extends Service { return true; } - public PumpEnactResult loadHistory(byte type) { - PumpEnactResult result = new PumpEnactResult(); - if (!isConnected()) return result; - 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()); - result.success = true; - result.comment = "OK"; - return result; + @Override + public boolean highTempBasal(int percent) { + return false; } public boolean updateBasalsInPump(final Profile profile) { @@ -471,13 +307,10 @@ public class DanaRKoreanExecutionService extends Service { double[] basal = DanaRPump.buildDanaRProfileRecord(profile); MsgSetSingleBasalProfile msgSet = new MsgSetSingleBasalProfile(basal); mSerialIOThread.sendMessage(msgSet); - danaRPump.lastSettingsRead = new Date(0); // force read full settings + mDanaRPump.lastSettingsRead = 0; // force read full settings getPumpStatus(); MainApp.bus().post(new EventPumpStatusChanged(EventPumpStatusChanged.DISCONNECTING)); return true; } - private void waitMsec(long msecs) { - SystemClock.sleep(msecs); - } } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/DanaRSPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/DanaRSPlugin.java index cfdbdeb5cd..9978880e08 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/DanaRSPlugin.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/DanaRSPlugin.java @@ -348,7 +348,7 @@ public class DanaRSPlugin implements PluginBase, PumpInterface, DanaRInterface, @Nullable @Override public ProfileStore getProfile() { - if (pump.lastSettingsRead.getTime() == 0) + if (pump.lastSettingsRead == 0) return null; // no info now return pump.createConvertedProfile(); } @@ -367,7 +367,7 @@ public class DanaRSPlugin implements PluginBase, PumpInterface, DanaRInterface, @Override public boolean isInitialized() { - return pump.lastConnection.getTime() > 0 && pump.maxBasal > 0; + return pump.lastConnection > 0 && pump.maxBasal > 0; } @Override @@ -438,7 +438,7 @@ public class DanaRSPlugin implements PluginBase, PumpInterface, DanaRInterface, @Override public Date lastDataTime() { - return pump.lastConnection; + return new Date(pump.lastConnection); } @Override @@ -753,7 +753,7 @@ public class DanaRSPlugin implements PluginBase, PumpInterface, DanaRInterface, @Override public JSONObject getJSONStatus() { - if (pump.lastConnection.getTime() + 5 * 60 * 1000L < System.currentTimeMillis()) { + if (pump.lastConnection + 5 * 60 * 1000L < System.currentTimeMillis()) { return null; } JSONObject pumpjson = new JSONObject(); @@ -812,8 +812,8 @@ public class DanaRSPlugin implements PluginBase, PumpInterface, DanaRInterface, @Override public String shortStatus(boolean veryShort) { String ret = ""; - if (pump.lastConnection.getTime() != 0) { - Long agoMsec = System.currentTimeMillis() - pump.lastConnection.getTime(); + if (pump.lastConnection != 0) { + Long agoMsec = System.currentTimeMillis() - pump.lastConnection; int agoMin = (int) (agoMsec / 60d / 1000d); ret += "LastConn: " + agoMin + " minago\n"; } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/services/DanaRSService.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/services/DanaRSService.java index 7790257640..1a1f74b645 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/services/DanaRSService.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/services/DanaRSService.java @@ -131,8 +131,8 @@ public class DanaRSService extends Service { MainApp.bus().post(new EventPumpStatusChanged(MainApp.sResources.getString(R.string.gettingtempbasalstatus))); bleComm.sendMessage(new DanaRS_Packet_Basal_Get_Temporary_Basal_State()); - Date now = new Date(); - if (danaRPump.lastSettingsRead.getTime() + 60 * 60 * 1000L < now.getTime() || !MainApp.getSpecificPlugin(DanaRSPlugin.class).isInitialized()) { + long now = System.currentTimeMillis(); + if (danaRPump.lastSettingsRead + 60 * 60 * 1000L < now || !MainApp.getSpecificPlugin(DanaRSPlugin.class).isInitialized()) { MainApp.bus().post(new EventPumpStatusChanged(MainApp.sResources.getString(R.string.gettingpumpsettings))); bleComm.sendMessage(new DanaRS_Packet_General_Get_Shipping_Information()); // serial no bleComm.sendMessage(new DanaRS_Packet_General_Get_Pump_Check()); // firmware @@ -357,7 +357,7 @@ public class DanaRSService extends Service { bleComm.sendMessage(msgSet); DanaRS_Packet_Basal_Set_Profile_Number msgActivate = new DanaRS_Packet_Basal_Set_Profile_Number(0); bleComm.sendMessage(msgActivate); - danaRPump.lastSettingsRead = new Date(0); // force read full settings + danaRPump.lastSettingsRead = 0; // force read full settings getPumpStatus(); MainApp.bus().post(new EventPumpStatusChanged(EventPumpStatusChanged.DISCONNECTING)); return true; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRv2/DanaRv2Plugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRv2/DanaRv2Plugin.java index 3e1aca22e0..34a5b2381b 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRv2/DanaRv2Plugin.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRv2/DanaRv2Plugin.java @@ -5,68 +5,31 @@ import android.content.Context; import android.content.Intent; import android.content.ServiceConnection; import android.os.IBinder; -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.DetailedBolusInfo; -import info.nightscout.androidaps.data.Profile; -import info.nightscout.androidaps.data.ProfileStore; import info.nightscout.androidaps.data.PumpEnactResult; -import info.nightscout.androidaps.db.ExtendedBolus; import info.nightscout.androidaps.db.TemporaryBasal; import info.nightscout.androidaps.db.Treatment; import info.nightscout.androidaps.events.EventAppExit; -import info.nightscout.androidaps.interfaces.ConstraintsInterface; -import info.nightscout.androidaps.interfaces.DanaRInterface; -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.ConfigBuilder.DetailedBolusInfoStorage; -import info.nightscout.androidaps.plugins.Overview.notifications.Notification; -import info.nightscout.androidaps.plugins.Overview.events.EventDismissNotification; -import info.nightscout.androidaps.plugins.Overview.events.EventNewNotification; -import info.nightscout.androidaps.plugins.ProfileNS.NSProfilePlugin; -import info.nightscout.androidaps.plugins.PumpDanaR.DanaRFragment; -import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPump; +import info.nightscout.androidaps.plugins.PumpDanaR.AbstractDanaRPlugin; import info.nightscout.androidaps.plugins.PumpDanaRv2.services.DanaRv2ExecutionService; -import info.nightscout.utils.DateUtil; -import info.nightscout.utils.DecimalFormatter; import info.nightscout.utils.Round; import info.nightscout.utils.SP; /** * Created by mike on 05.08.2016. */ -public class DanaRv2Plugin implements PluginBase, PumpInterface, DanaRInterface, ConstraintsInterface, ProfileInterface { - private static Logger log = LoggerFactory.getLogger(DanaRv2Plugin.class); - - @Override - public String getFragmentClass() { - return DanaRFragment.class.getName(); - } - - private static boolean fragmentPumpEnabled = false; - private static boolean fragmentProfileEnabled = false; - private static boolean fragmentPumpVisible = true; - - private static DanaRv2ExecutionService sExecutionService; - +public class DanaRv2Plugin extends AbstractDanaRPlugin { private static DanaRv2Plugin plugin = null; @@ -76,11 +39,10 @@ public class DanaRv2Plugin implements PluginBase, PumpInterface, DanaRInterface, return plugin; } - private static DanaRPump pump = DanaRPump.getInstance(); - - private static PumpDescription pumpDescription = new PumpDescription(); - private DanaRv2Plugin() { + log = LoggerFactory.getLogger(DanaRv2Plugin.class); + useExtendedBoluses = false; + Context context = MainApp.instance().getApplicationContext(); Intent intent = new Intent(context, DanaRv2ExecutionService.class); context.bindService(intent, mConnection, Context.BIND_AUTO_CREATE); @@ -134,78 +96,11 @@ public class DanaRv2Plugin implements PluginBase, PumpInterface, DanaRInterface, } // 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 type == PUMP; - } - - @Override - public void setFragmentEnabled(int type, boolean fragmentEnabled) { - if (type == PluginBase.PROFILE) - fragmentProfileEnabled = fragmentEnabled; - else if (type == PluginBase.PUMP) - fragmentPumpEnabled = fragmentEnabled; - // if pump profile was enabled need to switch to another too - if (type == PluginBase.PUMP && !fragmentEnabled && fragmentProfileEnabled) { - setFragmentEnabled(PluginBase.PROFILE, false); - setFragmentVisible(PluginBase.PROFILE, false); - NSProfilePlugin.getPlugin().setFragmentEnabled(PluginBase.PROFILE, true); - NSProfilePlugin.getPlugin().setFragmentVisible(PluginBase.PROFILE, true); - } - } - - @Override - public void setFragmentVisible(int type, boolean fragmentVisible) { - if (type == PluginBase.PUMP) - fragmentPumpVisible = fragmentVisible; - } - @Override public int getPreferencesId() { return R.xml.pref_danarv2; @@ -218,86 +113,10 @@ public class DanaRv2Plugin implements PluginBase, PumpInterface, DanaRInterface, @Override public boolean isInitialized() { - return pump.lastConnection.getTime() > 0 && pump.maxBasal > 0; - } - - @Override - public boolean isSuspended() { - return pump.pumpSuspended; - } - - @Override - public boolean isBusy() { - if (sExecutionService == null) return false; - return sExecutionService.isConnected() || sExecutionService.isConnecting(); + return pump.lastConnection > 0 && pump.maxBasal > 0; } // Pump interface - @Override - public PumpEnactResult setNewBasalProfile(Profile profile) { - PumpEnactResult result = new PumpEnactResult(); - - if (sExecutionService == null) { - log.error("setNewBasalProfile sExecutionService is null"); - result.comment = "setNewBasalProfile sExecutionService is null"; - return result; - } - 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)); - result.comment = MainApp.sResources.getString(R.string.pumpNotInitializedProfileNotSet); - return result; - } 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)); - result.comment = MainApp.sResources.getString(R.string.failedupdatebasalprofile); - return result; - } else { - MainApp.bus().post(new EventDismissNotification(Notification.PROFILE_NOT_SET_NOT_INITIALIZED)); - MainApp.bus().post(new EventDismissNotification(Notification.FAILED_UDPATE_PROFILE)); - Notification notification = new Notification(Notification.PROFILE_SET_OK, MainApp.sResources.getString(R.string.profile_set_ok), Notification.INFO, 60); - MainApp.bus().post(new EventNewNotification(notification)); - result.success = true; - result.enacted = true; - result.comment = "OK"; - return result; - } - } - - @Override - public boolean isThisProfileSet(Profile profile) { - if (!isInitialized()) - return true; // TODO: not sure what's better. so far TRUE to prevent too many SMS - 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((Integer) (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 pump.lastConnection; - } - - @Override - public double getBaseBasalRate() { - return pump.currentBasal; - } - @Override public PumpEnactResult deliverTreatment(DetailedBolusInfo detailedBolusInfo) { ConfigBuilderPlugin configBuilderPlugin = MainApp.getConfigBuilder(); @@ -513,49 +332,6 @@ public class DanaRv2Plugin implements PluginBase, PumpInterface, DanaRInterface, return result; } - @Override - public PumpEnactResult setExtendedBolus(Double insulin, Integer durationInMinutes) { - ConfigBuilderPlugin configBuilderPlugin = MainApp.getConfigBuilder(); - insulin = configBuilderPlugin.applyBolusConstraints(insulin); - // needs to be rounded - int durationInHalfHours = Math.max(durationInMinutes / 30, 1); - insulin = Round.roundTo(insulin, getPumpDescription().extendedBolusStep); - - PumpEnactResult result = new PumpEnactResult(); - ExtendedBolus runningEB = MainApp.getConfigBuilder().getExtendedBolusFromHistory(System.currentTimeMillis()); - if (runningEB != null && Math.abs(runningEB.insulin - insulin) < getPumpDescription().extendedBolusStep) { - result.enacted = false; - result.success = true; - result.comment = MainApp.instance().getString(R.string.virtualpump_resultok); - result.duration = pump.extendedBolusRemainingMinutes; - result.absolute = pump.extendedBolusAbsoluteRate; - result.isPercent = false; - result.isTempCancel = false; - if (Config.logPumpActions) - log.debug("setExtendedBolus: Correct extended bolus already set. Current: " + pump.extendedBolusAmount + " Asked: " + insulin); - return result; - } - boolean connectionOK = sExecutionService.extendedBolus(insulin, durationInHalfHours); - if (connectionOK && pump.isExtendedInProgress && Math.abs(pump.extendedBolusAmount - insulin) < getPumpDescription().extendedBolusStep) { - result.enacted = true; - result.success = true; - result.comment = MainApp.instance().getString(R.string.virtualpump_resultok); - result.isTempCancel = false; - result.duration = pump.extendedBolusRemainingMinutes; - result.absolute = pump.extendedBolusAbsoluteRate; - result.bolusDelivered = pump.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(boolean force) { PumpEnactResult result = new PumpEnactResult(); @@ -581,257 +357,8 @@ public class DanaRv2Plugin implements PluginBase, PumpInterface, DanaRInterface, } } - @Override - public PumpEnactResult cancelExtendedBolus() { - PumpEnactResult result = new PumpEnactResult(); - ExtendedBolus runningEB = MainApp.getConfigBuilder().getExtendedBolusFromHistory(System.currentTimeMillis()); - if (runningEB != null) { - sExecutionService.extendedBolusStop(); - result.enacted = true; - result.isTempCancel = true; - } - if (!pump.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; - } - } - - @Override - public void connect(String from) { - if (sExecutionService != null) { - sExecutionService.connect(from); - pumpDescription.basalStep = pump.basalStep; - pumpDescription.bolusStep = pump.bolusStep; - } - } - - @Override - public boolean isConnected() { - return sExecutionService != null && sExecutionService.isConnected(); - } - - @Override - public boolean isConnecting() { - return sExecutionService != null && sExecutionService.isConnecting(); - } - - @Override - public void disconnect(String from) { - if (sExecutionService != null) sExecutionService.disconnect(from); - } - - @Override - public void stopConnecting() { - if (sExecutionService != null) sExecutionService.stopConnecting(); - } - - @Override - public void getPumpStatus() { - if (sExecutionService != null) sExecutionService.getPumpStatus(); - } - - @Override - public JSONObject getJSONStatus() { - if (pump.lastConnection.getTime() + 5 * 60 * 1000L < System.currentTimeMillis()) { - return null; - } - JSONObject pumpjson = new JSONObject(); - JSONObject battery = new JSONObject(); - JSONObject status = new JSONObject(); - JSONObject extended = new JSONObject(); - try { - battery.put("percent", pump.batteryRemaining); - status.put("status", pump.pumpSuspended ? "suspended" : "normal"); - status.put("timestamp", DateUtil.toISOString(pump.lastConnection)); - extended.put("Version", BuildConfig.VERSION_NAME + "-" + BuildConfig.BUILDVERSION); - extended.put("PumpIOB", pump.iob); - if (pump.lastBolusTime.getTime() != 0) { - extended.put("LastBolus", pump.lastBolusTime.toLocaleString()); - extended.put("LastBolusAmount", pump.lastBolusAmount); - } - TemporaryBasal tb = MainApp.getConfigBuilder().getTempBasalFromHistory(System.currentTimeMillis()); - if (tb != null) { - extended.put("TempBasalAbsoluteRate", tb.tempBasalConvertedToAbsolute(System.currentTimeMillis())); - extended.put("TempBasalStart", DateUtil.dateAndTimeString(tb.date)); - extended.put("TempBasalRemaining", tb.getPlannedRemainingMinutes()); - } - ExtendedBolus eb = MainApp.getConfigBuilder().getExtendedBolusFromHistory(System.currentTimeMillis()); - if (eb != null) { - extended.put("ExtendedBolusAbsoluteRate", eb.absoluteRate()); - extended.put("ExtendedBolusStart", DateUtil.dateAndTimeString(eb.date)); - extended.put("ExtendedBolusRemaining", eb.getPlannedRemainingMinutes()); - } - extended.put("BaseBasalRate", getBaseBasalRate()); - try { - extended.put("ActiveProfile", MainApp.getConfigBuilder().getProfileName()); - } catch (Exception e) { - } - - pumpjson.put("battery", battery); - pumpjson.put("status", status); - pumpjson.put("extended", extended); - pumpjson.put("reservoir", (int) pump.reservoirRemainingUnits); - pumpjson.put("clock", DateUtil.toISOString(new Date())); - } catch (JSONException e) { - log.error("Unhandled exception", e); - } - return pumpjson; - } - - @Override - public String deviceID() { - return pump.serialNumber; - } - - @Override - public PumpDescription getPumpDescription() { - return pumpDescription; - } - - /** - * DanaR interface - */ - - @Override - public PumpEnactResult loadHistory(byte type) { - return sExecutionService.loadHistory(type); - } - @Override public PumpEnactResult loadEvents() { return sExecutionService.loadEvents(); } - - /** - * 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; - } - - @Override - public boolean isSMBModeEnabled() { - return true; - } - - @SuppressWarnings("PointlessBooleanExpression") - @Override - public Double applyBasalConstraints(Double absoluteRate) { - double origAbsoluteRate = absoluteRate; - if (pump != null) { - if (absoluteRate > pump.maxBasal) { - absoluteRate = pump.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().maxTempPercent) - percentRate = getPumpDescription().maxTempPercent; - 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 (pump != null) { - if (insulin > pump.maxBolus) { - insulin = pump.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 ProfileStore getProfile() { - if (pump.lastSettingsRead.getTime() == 0) - return null; // no info now - return pump.createConvertedProfile(); - } - - @Override - public String getUnits() { - return pump.getUnits(); - } - - @Override - public String getProfileName() { - return pump.createConvertedProfileName(); - } - - // Reply for sms communicator - public String shortStatus(boolean veryShort) { - String ret = ""; - if (pump.lastConnection.getTime() != 0) { - Long agoMsec = System.currentTimeMillis() - pump.lastConnection.getTime(); - int agoMin = (int) (agoMsec / 60d / 1000d); - ret += "LastConn: " + agoMin + " minago\n"; - } - if (pump.lastBolusTime.getTime() != 0) { - ret += "LastBolus: " + DecimalFormatter.to2Decimal(pump.lastBolusAmount) + "U @" + android.text.format.DateFormat.format("HH:mm", pump.lastBolusTime) + "\n"; - } - if (MainApp.getConfigBuilder().isInHistoryRealTempBasalInProgress()) { - ret += "Temp: " + MainApp.getConfigBuilder().getTempBasalFromHistory(System.currentTimeMillis()).toStringFull() + "\n"; - } - if (MainApp.getConfigBuilder().isInHistoryExtendedBoluslInProgress()) { - ret += "Extended: " + MainApp.getConfigBuilder().getExtendedBolusFromHistory(System.currentTimeMillis()).toString() + "\n"; - } - if (!veryShort) { - ret += "TDD: " + DecimalFormatter.to0Decimal(pump.dailyTotalUnits) + " / " + pump.maxDailyTotalUnits + " U\n"; - } - ret += "IOB: " + pump.iob + "U\n"; - ret += "Reserv: " + DecimalFormatter.to0Decimal(pump.reservoirRemainingUnits) + "U\n"; - ret += "Batt: " + pump.batteryRemaining + "\n"; - return ret; - } - // TODO: daily total constraint - } 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 index 343a176e56..a12e2085aa 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRv2/SerialIOThread.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRv2/SerialIOThread.java @@ -13,13 +13,14 @@ import java.io.OutputStream; import info.nightscout.androidaps.Config; import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPump; import info.nightscout.androidaps.plugins.PumpDanaR.comm.MessageBase; +import info.nightscout.androidaps.plugins.PumpDanaR.services.AbstractSerialIOThread; import info.nightscout.androidaps.plugins.PumpDanaRv2.comm.MessageHashTable_v2; import info.nightscout.utils.CRC; /** * Created by mike on 17.07.2016. */ -public class SerialIOThread extends Thread { +public class SerialIOThread extends AbstractSerialIOThread { private static Logger log = LoggerFactory.getLogger(SerialIOThread.class); private InputStream mInputStream = null; @@ -29,10 +30,10 @@ public class SerialIOThread extends Thread { private boolean mKeepRunning = true; private byte[] mReadBuff = new byte[0]; - MessageBase processedMessage; + private MessageBase processedMessage; public SerialIOThread(BluetoothSocket rfcommSocket) { - super(SerialIOThread.class.toString()); + super(); mRfCommSocket = rfcommSocket; try { @@ -138,6 +139,7 @@ public class SerialIOThread extends Thread { } } + @Override public synchronized void sendMessage(MessageBase message) { if (!mRfCommSocket.isConnected()) { log.error("Socket not connected on sendMessage"); @@ -173,6 +175,7 @@ public class SerialIOThread extends Thread { } } + @Override public void disconnect(String reason) { mKeepRunning = false; try { diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRv2/comm/MsgCheckValue_v2.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRv2/comm/MsgCheckValue_v2.java index 9869ef0895..60133d8d25 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRv2/comm/MsgCheckValue_v2.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRv2/comm/MsgCheckValue_v2.java @@ -40,6 +40,7 @@ public class MsgCheckValue_v2 extends MessageBase { pump.protocol = intFromBuff(bytes, 1, 1); pump.productCode = intFromBuff(bytes, 2, 1); if (pump.model != DanaRPump.EXPORT_MODEL) { + pump.lastConnection = 0; Notification notification = new Notification(Notification.WRONG_DRIVER, MainApp.sResources.getString(R.string.pumpdrivercorrected), Notification.NORMAL); MainApp.bus().post(new EventNewNotification(notification)); MainApp.getSpecificPlugin(DanaRPlugin.class).disconnect("Wrong Model"); @@ -48,7 +49,7 @@ public class MsgCheckValue_v2 extends MessageBase { MainApp.getSpecificPlugin(DanaRKoreanPlugin.class).setFragmentVisible(PluginBase.PUMP, true); MainApp.getSpecificPlugin(DanaRPlugin.class).setFragmentEnabled(PluginBase.PUMP, false); MainApp.getSpecificPlugin(DanaRPlugin.class).setFragmentVisible(PluginBase.PUMP, false); - DanaRPump.getInstance().lastConnection = new Date(0); // mark not initialized + DanaRPump.getInstance().lastConnection = 0; // mark not initialized //If profile coming from pump, switch it as well if(MainApp.getSpecificPlugin(DanaRPlugin.class).isEnabled(PluginBase.PROFILE)){ @@ -63,6 +64,7 @@ public class MsgCheckValue_v2 extends MessageBase { } if (pump.protocol != 2) { + pump.lastConnection = 0; Notification notification = new Notification(Notification.WRONG_DRIVER, MainApp.sResources.getString(R.string.pumpdrivercorrected), Notification.NORMAL); MainApp.bus().post(new EventNewNotification(notification)); DanaRKoreanPlugin.getPlugin().disconnect("Wrong Model"); diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRv2/services/DanaRv2ExecutionService.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRv2/services/DanaRv2ExecutionService.java index 71a2f9ac79..81b5837511 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRv2/services/DanaRv2ExecutionService.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRv2/services/DanaRv2ExecutionService.java @@ -1,52 +1,66 @@ 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.SystemClock; import com.squareup.otto.Subscribe; -import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.io.IOException; 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.data.Profile; import info.nightscout.androidaps.data.PumpEnactResult; 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.data.Profile; import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin; import info.nightscout.androidaps.plugins.Overview.Dialogs.BolusProgressDialog; -import info.nightscout.androidaps.plugins.Overview.notifications.Notification; import info.nightscout.androidaps.plugins.Overview.events.EventNewNotification; import info.nightscout.androidaps.plugins.Overview.events.EventOverviewBolusProgress; +import info.nightscout.androidaps.plugins.Overview.notifications.Notification; import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPump; -import info.nightscout.androidaps.plugins.PumpDanaR.comm.*; +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.MsgBolusStartWithSpeed; +import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgBolusStop; +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.events.EventDanaRNewStatus; +import info.nightscout.androidaps.plugins.PumpDanaR.services.AbstractDanaRExecutionService; import info.nightscout.androidaps.plugins.PumpDanaRv2.DanaRv2Plugin; import info.nightscout.androidaps.plugins.PumpDanaRv2.SerialIOThread; +import info.nightscout.androidaps.plugins.PumpDanaRv2.comm.MsgCheckValue_v2; import info.nightscout.androidaps.plugins.PumpDanaRv2.comm.MsgHistoryEvents_v2; import info.nightscout.androidaps.plugins.PumpDanaRv2.comm.MsgSetAPSTempBasalStart_v2; import info.nightscout.androidaps.plugins.PumpDanaRv2.comm.MsgSetHistoryEntry_v2; -import info.nightscout.androidaps.plugins.PumpDanaRv2.comm.MsgCheckValue_v2; import info.nightscout.androidaps.plugins.PumpDanaRv2.comm.MsgStatusBolusExtended_v2; import info.nightscout.androidaps.plugins.PumpDanaRv2.comm.MsgStatusTempBasal_v2; import info.nightscout.androidaps.queue.Callback; @@ -54,47 +68,16 @@ import info.nightscout.utils.NSUpload; 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 IBinder mBinder = new LocalBinder(); - - private DanaRPump danaRPump; - private Treatment bolusingTreatment = null; - - private static Boolean connectionInProgress = false; - - private static final UUID SPP_UUID = UUID.fromString("00001101-0000-1000-8000-00805f9b34fb"); +public class DanaRv2ExecutionService extends AbstractDanaRExecutionService { private long lastHistoryFetched = 0; - 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 was disconnected " + device.getName());//Device was 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() { + log = LoggerFactory.getLogger(DanaRv2ExecutionService.class); + mBinder = new LocalBinder(); + registerBus(); MainApp.instance().getApplicationContext().registerReceiver(receiver, new IntentFilter(BluetoothDevice.ACTION_ACL_DISCONNECTED)); - danaRPump = DanaRPump.getInstance(); } public class LocalBinder extends Binder { @@ -103,17 +86,6 @@ public class DanaRv2ExecutionService extends Service { } } - @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); @@ -138,35 +110,28 @@ public class DanaRv2ExecutionService extends Service { log.debug("EventAppExit finished"); } - public boolean isConnected() { - return mRfcommSocket != null && mRfcommSocket.isConnected(); - } - - public boolean isConnecting() { - return connectionInProgress; - } - - public void disconnect(String from) { + @Subscribe + public void onStatusEvent(final EventPreferenceChange pch) { if (mSerialIOThread != null) - mSerialIOThread.disconnect(from); + mSerialIOThread.disconnect("EventPreferenceChange"); } - public void connect(String from) { - if (danaRPump.password != -1 && danaRPump.password != SP.getInt(R.string.key_danar_password, -1)) { + public void connect() { + if (mDanaRPump.password != -1 && mDanaRPump.password != SP.getInt(R.string.key_danar_password, -1)) { ToastUtils.showToastInUiThread(MainApp.instance().getApplicationContext(), MainApp.sResources.getString(R.string.wrongpumppassword), R.raw.error); return; } - if (connectionInProgress) + if (mConnectionInProgress) return; new Thread(new Runnable() { @Override public void run() { - connectionInProgress = true; + mConnectionInProgress = true; getBTSocketForSelectedPump(); if (mRfcommSocket == null || mBTDevice == null) { - connectionInProgress = false; + mConnectionInProgress = false; return; // Device not found } @@ -187,48 +152,11 @@ public class DanaRv2ExecutionService extends Service { MainApp.bus().post(new EventPumpStatusChanged(EventPumpStatusChanged.CONNECTED, 0)); } - connectionInProgress = false; + mConnectionInProgress = false; } }).start(); } - public void stopConnecting() { - if (mSerialIOThread != null) - mSerialIOThread.disconnect("stopConnecting"); - } - - 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"); - } - public void getPumpStatus() { try { MainApp.bus().post(new EventPumpStatusChanged(MainApp.sResources.getString(R.string.gettingpumpstatus))); @@ -238,7 +166,7 @@ public class DanaRv2ExecutionService extends Service { MsgStatusBolusExtended_v2 exStatusMsg = new MsgStatusBolusExtended_v2(); MsgCheckValue_v2 checkValue = new MsgCheckValue_v2(); - if (danaRPump.isNewPump) { + if (mDanaRPump.isNewPump) { mSerialIOThread.sendMessage(checkValue); if (!checkValue.received) { return; @@ -253,8 +181,8 @@ public class DanaRv2ExecutionService extends Service { MainApp.bus().post(new EventPumpStatusChanged(MainApp.sResources.getString(R.string.gettingextendedbolusstatus))); mSerialIOThread.sendMessage(exStatusMsg); - Date now = new Date(); - if (danaRPump.lastSettingsRead.getTime() + 60 * 60 * 1000L < now.getTime() || !MainApp.getSpecificPlugin(DanaRv2Plugin.class).isInitialized()) { + long now = System.currentTimeMillis(); + if (mDanaRPump.lastSettingsRead + 60 * 60 * 1000L < now || !MainApp.getSpecificPlugin(DanaRv2Plugin.class).isInitialized()) { MainApp.bus().post(new EventPumpStatusChanged(MainApp.sResources.getString(R.string.gettingpumpsettings))); mSerialIOThread.sendMessage(new MsgSettingShippingInfo()); mSerialIOThread.sendMessage(new MsgSettingActiveProfile()); @@ -268,28 +196,28 @@ public class DanaRv2ExecutionService extends Service { mSerialIOThread.sendMessage(new MsgSettingProfileRatiosAll()); MainApp.bus().post(new EventPumpStatusChanged(MainApp.sResources.getString(R.string.gettingpumptime))); mSerialIOThread.sendMessage(new MsgSettingPumpTime()); - long timeDiff = (danaRPump.pumpTime.getTime() - System.currentTimeMillis()) / 1000L; + long timeDiff = (mDanaRPump.pumpTime.getTime() - System.currentTimeMillis()) / 1000L; log.debug("Pump time difference: " + timeDiff + " seconds"); if (Math.abs(timeDiff) > 10) { mSerialIOThread.sendMessage(new MsgSetTime(new Date())); mSerialIOThread.sendMessage(new MsgSettingPumpTime()); - timeDiff = (danaRPump.pumpTime.getTime() - System.currentTimeMillis()) / 1000L; + timeDiff = (mDanaRPump.pumpTime.getTime() - System.currentTimeMillis()) / 1000L; log.debug("Pump time difference: " + timeDiff + " seconds"); } - danaRPump.lastSettingsRead = now; + mDanaRPump.lastSettingsRead = now; } loadEvents(); - danaRPump.lastConnection = now; + mDanaRPump.lastConnection = now; MainApp.bus().post(new EventDanaRNewStatus()); MainApp.bus().post(new EventInitializationChanged()); NSUpload.uploadDeviceStatus(); - if (danaRPump.dailyTotalUnits > danaRPump.maxDailyTotalUnits * Constants.dailyLimitWarning) { - log.debug("Approaching daily limit: " + danaRPump.dailyTotalUnits + "/" + danaRPump.maxDailyTotalUnits); + if (mDanaRPump.dailyTotalUnits > mDanaRPump.maxDailyTotalUnits * Constants.dailyLimitWarning) { + log.debug("Approaching daily limit: " + mDanaRPump.dailyTotalUnits + "/" + mDanaRPump.maxDailyTotalUnits); Notification reportFail = new Notification(Notification.APPROACHING_DAILY_LIMIT, MainApp.sResources.getString(R.string.approachingdailylimit), Notification.URGENT); MainApp.bus().post(new EventNewNotification(reportFail)); - NSUpload.uploadError(MainApp.sResources.getString(R.string.approachingdailylimit) + ": " + danaRPump.dailyTotalUnits + "/" + danaRPump.maxDailyTotalUnits + "U"); + NSUpload.uploadError(MainApp.sResources.getString(R.string.approachingdailylimit) + ": " + mDanaRPump.dailyTotalUnits + "/" + mDanaRPump.maxDailyTotalUnits + "U"); } } catch (Exception e) { log.error("Unhandled exception", e); @@ -299,10 +227,10 @@ public class DanaRv2ExecutionService extends Service { public boolean tempBasal(int percent, int durationInHours) { if (!isConnected()) return false; - if (danaRPump.isTempBasalInProgress) { + if (mDanaRPump.isTempBasalInProgress) { MainApp.bus().post(new EventPumpStatusChanged(MainApp.sResources.getString(R.string.stoppingtempbasal))); mSerialIOThread.sendMessage(new MsgSetTempBasalStop()); - waitMsec(500); + SystemClock.sleep(500); } MainApp.bus().post(new EventPumpStatusChanged(MainApp.sResources.getString(R.string.settingtempbasal))); mSerialIOThread.sendMessage(new MsgSetTempBasalStart(percent, durationInHours)); @@ -314,10 +242,10 @@ public class DanaRv2ExecutionService extends Service { public boolean highTempBasal(int percent) { if (!isConnected()) return false; - if (danaRPump.isTempBasalInProgress) { + if (mDanaRPump.isTempBasalInProgress) { MainApp.bus().post(new EventPumpStatusChanged(MainApp.sResources.getString(R.string.stoppingtempbasal))); mSerialIOThread.sendMessage(new MsgSetTempBasalStop()); - waitMsec(500); + SystemClock.sleep(500); } MainApp.bus().post(new EventPumpStatusChanged(MainApp.sResources.getString(R.string.settingtempbasal))); mSerialIOThread.sendMessage(new MsgSetAPSTempBasalStart_v2(percent)); @@ -362,7 +290,7 @@ public class DanaRv2ExecutionService extends Service { if (BolusProgressDialog.stopPressed) return false; MainApp.bus().post(new EventPumpStatusChanged(MainApp.sResources.getString(R.string.startingbolus))); - bolusingTreatment = t; + mBolusingTreatment = t; final int preferencesSpeed = SP.getInt(R.string.key_danars_bolusspeed, 0); MessageBase start; if (preferencesSpeed == 0) @@ -390,7 +318,7 @@ public class DanaRv2ExecutionService extends Service { return false; } while (!stop.stopped && !start.failed) { - waitMsec(100); + SystemClock.sleep(100); if ((System.currentTimeMillis() - progress.lastReceive) > 15 * 1000L) { // if i didn't receive status for more than 15 sec expecting broken comm stop.stopped = true; stop.forced = true; @@ -403,7 +331,7 @@ public class DanaRv2ExecutionService extends Service { bolusingEvent.t = t; bolusingEvent.percent = 99; - bolusingTreatment = null; + mBolusingTreatment = null; int speed = 12; switch (preferencesSpeed) { case 0: @@ -440,14 +368,14 @@ public class DanaRv2ExecutionService extends Service { public void bolusStop() { if (Config.logDanaBTComm) - log.debug("bolusStop >>>>> @ " + (bolusingTreatment == null ? "" : bolusingTreatment.insulin)); + log.debug("bolusStop >>>>> @ " + (mBolusingTreatment == null ? "" : mBolusingTreatment.insulin)); MsgBolusStop stop = new MsgBolusStop(); stop.forced = true; if (isConnected()) { mSerialIOThread.sendMessage(stop); while (!stop.stopped) { mSerialIOThread.sendMessage(stop); - waitMsec(200); + SystemClock.sleep(200); } } else { stop.stopped = true; @@ -464,57 +392,10 @@ public class DanaRv2ExecutionService extends Service { return true; } - public PumpEnactResult loadHistory(byte type) { - PumpEnactResult result = new PumpEnactResult(); - if (!isConnected()) return result; - 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()); - result.success = true; - result.comment = "OK"; - return result; - } - public PumpEnactResult loadEvents() { if (!isConnected()) return new PumpEnactResult().success(false); - waitMsec(300); + SystemClock.sleep(300); MsgHistoryEvents_v2 msg; if (lastHistoryFetched == 0) { msg = new MsgHistoryEvents_v2(); @@ -525,9 +406,9 @@ public class DanaRv2ExecutionService extends Service { } mSerialIOThread.sendMessage(msg); while (!msg.done && mRfcommSocket.isConnected()) { - waitMsec(100); + SystemClock.sleep(100); } - waitMsec(200); + SystemClock.sleep(200); if (MsgHistoryEvents_v2.lastEventTimeLoaded != 0) lastHistoryFetched = MsgHistoryEvents_v2.lastEventTimeLoaded - 45 * 60 * 1000L; //always load last 45 min; else @@ -543,13 +424,10 @@ public class DanaRv2ExecutionService extends Service { mSerialIOThread.sendMessage(msgSet); MsgSetActivateBasalProfile msgActivate = new MsgSetActivateBasalProfile((byte) 0); mSerialIOThread.sendMessage(msgActivate); - danaRPump.lastSettingsRead = new Date(0); // force read full settings + mDanaRPump.lastSettingsRead = 0; // force read full settings getPumpStatus(); MainApp.bus().post(new EventPumpStatusChanged(EventPumpStatusChanged.DISCONNECTING)); return true; } - private void waitMsec(long msecs) { - SystemClock.sleep(msecs); - } } diff --git a/app/src/main/res/values-bg/strings.xml b/app/src/main/res/values-bg/strings.xml index dca1f6b0af..8c4ddb81e5 100644 --- a/app/src/main/res/values-bg/strings.xml +++ b/app/src/main/res/values-bg/strings.xml @@ -444,7 +444,6 @@ По подразбиране: 2\nBolus snooze се активира след като поставите болус за основно хранене, така Loop няма да пуснка/намаля базалите веднага след като сте се хранили. Примерът тук е с 2; така при 3 часа DIA това ще означава че bolus snooze ще бъде внимателно изместен 1.5 часа (3DIA/2). По подразбиране: 3.0\nТова е настройка на количеството на покачване на КЗ при усвояване на въглехидратите за всеки 5 минути. По подразбиране 3мг/дл/5мин. Това се отразява на това колко бързо се усвояват COB според алгоритъма, и как това се отразява в предвиждането на КЗ, когато тя не се покачва или пада с различен темп от очакваното. Внимание! Обикновено Вие не трябва да променяте тези стойности. Моля НАТИСНЕТЕ ТУК, прочетете текста и бъдете сигурни, че го РАЗБИРАТЕ преди да направите каквито и да е промени! - http://openaps.readthedocs.io/en/latest/docs/walkthrough/phase-3/beyond-low-glucose-suspend.html Позволени са само числа Позволени са числа между %1$s - %2$s Полето не може да бъде празно @@ -676,4 +675,64 @@ Настройки на часовник Задаване временни цели и въвеждане Лечения от часовник Android wear Контролиране от часовник + Closed Loop е позволен + Чете историята на помпата + Настройва базалният профил + Опитва се да възстанови връзката + Доставянето на болуса и проверката на историята на помпата са неуспешни, моля, проверете помпата и ако е доставен болус го добавете като запис през Careportal + Модифицирано приложение за изтегляне + Задайте стъпка на базала 0.01 Е/ч + Dexcom G5 приложение (модифицирано) + Качвай данните за КЗ в NS + В xDrip+ изберете 640g/Eversense за източник на данни + Изпращай данни за КЗ към xDrip+ + Аларма при липса на данни за КЗ + Аларма при недостъпна помпа + Командата се изпълнява в момента + Грешка при доставяне на удължен болус + Храна + Има данни за КЗ от избрания източник + ИНФО + Локални аларми + Loop разрешен + Максимален IOB е зададен правилно + Базалната стойност е заместена от минимално подържаната + Липсват данни за КЗ + Само отрицателни + Не + ]]> + КЗ от NS + NSClient има права за запис + Калкулиране на базален IOB + Калкулиране на КЗ + Калкулиране на Болус IOB + Калкулиране на COB + Калкулиране суперболус + Калкулиране на временни цели + Калкулиране на тенденция КЗ + Само положителни + Обработва се събитие + Помпата е недостъпна + Лимит за недостъпна помпа [мин] + Драйверът за помпата е коригиран + Оставащ инсулин + Стартира доставка на болус + Неподдържан фърмуер на помпата + Спешна аларма + Очаква края на болуса. Остават %d сек. + Показвай делта с още един десетичен знак + Показвай подробна делта + Да + Невалиден профил: %s + En + Използвай системни известия за аларми и съобщения + Внимание + Минимум: %3.1f U + Максимум: %3.1f U + Средно: %3.1f U + Нормално + Ниско + Няма достатъчно инсулин в резервоара + Празен + Обнови diff --git a/app/src/main/res/values-cs/strings.xml b/app/src/main/res/values-cs/strings.xml index f3559c9fa4..20f35204c6 100644 --- a/app/src/main/res/values-cs/strings.xml +++ b/app/src/main/res/values-cs/strings.xml @@ -275,7 +275,7 @@ Zapnout uzavřenou smyčku, zvyšovat max IOB nad 0 a snižovat cílovou glykémii Jeden týden úspěšného používání s běžným příjmem sacharidů Upravit bazály a koeficinty, když bude potřeba a povolit automatickou detekci citlivosti na inzulín - Povolit další fukce pro běžné používání jako AMA + Povolit další funkce pro běžné používání jako AMA Dosaženo limitu Aplikováno %.2fU Smyčka byla zakázána @@ -669,4 +669,113 @@ Fiasp Ultra rychlý - Oref Čekání na konec bolusu. Zbývá %d sek. + Povolit další funkce pro běžné používání jako SMB + Výchozí hodnota: 3 Toto je klíčová hodnota zabezpečení. Říká, že maximánlní nastavitelný bazál je trojnásobkem maximálního denního bazálu. Patrně to nebudete muset měnit, případně si přečtete o tématu \"3x max denní; 4x aktuální\" + Výchozí hodnota: 4 Toto je druhá klíčová hodnota. Říká, že maximální hodnota dočasného bazálu nikdy nebude větší, než čtyřnásobek aktuálního bazálu. Je to proto, aby se lidé nedostali do hodnot nebezpečných bazálu dříve, než pochpí jak OpenAPS pracuje. Znovy vychozí hodnota je 4 a většina lidí ji nidky nebude muset změnit. Pokud nestačí, obvykle je problém někde jinde. + Výchozí hodnota: 1.2 Toto je bezpečnostní nastavení pro detekci sensitivity. Říká, že autosens může zvýšit bazály, snížit ISF a snížit cílovou hodnotu glykémie o 20% + Výchozí hodnota: 0.7 Toto je bezpečnostní nastavení pro detekci sensitivity. Říká, že autosens může snížit bazály, zvýšit ISF a zvýšit cílovou hodnotu glykémie na 70% + Výchozí hodnota: zapnuto Toto nastavení říká, že autosens může měnit také cílové hodnoty glykémií. + Výchozí hodnota: 2 Toto nastavení říká, po jakou část z hodnoty DIA smyčka po bolusu čeká a nereaguje na změny glykémií (zde 3DIA/2 = 1,5h) + Výchozí hodnota: 3.0 Tato hodnota definuje minimální část strávených sacharidů za každých 5 min. Výchozí hodnota je 3mg/dl/5min. Tato hodnota ovlivňuje výpočet COB + Pozor! Za normálních okolností tyto hodnoty nemusíte měnit. Klikněte ZDE, PŘEČTĚTE si informace a UJISTĚTE se, že jim rozumíte dříve, než je začnete měnit. + Interval pro detekci senzitivity [h] + Počet hodin do minulosti pro detekci senzitivity + Jídlo + g + ]]> + kJ + En + Pr + Tuk + Příkaz je právě prováděn + Ovladač pumpy opraven + Pumpa nedostupná + Chybějící glykémie + Používat systémové notifikace pro výstrahy a oznámení + Místní výstrahy + Výstraha při nedostupných glykémiích + Výstraha při nedostupné pumpě + Limit pro nedostupnost pumpy [min] + Urgetní alarm + INFO + Bluetooth + Hlídač BT + Vypne na 1 sek bluetooth v telefonu, pokud se nedaří připojit k pumpě. Může to pomoci u telefonů, které mají problémy s BT + DexcomG5 aplikace (upravená) + Nahrávat data do NS + Nastavení nahrávání z G5 + Upravená aplikace pro stažení + Zobrazovat detailní změny + Zobrazovat rozdíl s jedním desetinným místem navíc + Nepodporovaný firmware v pumpě + Odesílat data do xDrip+ + V xDrip+ vyberte zdroj dat 640g/Eversense + Glykémie z NS + Hodnota bazálu nahrazena minimální možnou + Kalkulace glykémie + Kalkulace bolusového IOB + Kalkulace bazálního IOB + Kalkulace trendu + Kalkulace superbolusu + Ano + No + Pouze kladné + Pouze záporné + Kalkulace COB + Kalkulace s dočasným cílem + Smyčka povolena + APS vybráno + NSClient má povolení k zápisu + Uzavřená smyčka povolena + Maximální IOB nastaveno správně + Glykémie dostupné z vybraného zdroje + Bazální hodnoty nejsou zarovnané na celé hodiny: %s + Chybný profil: %s + Programování pumpy pro bolus + Obnovit + Stav + Aktivita + Žádné spojení %d min + %d%% (%d min zbývá) + Inicializace + Odpojeno + Vypnuto díky chybě + Vypnuto uživatelem + Beží + Rušení dočasného bazálu + Nastavování doč. bazálu (%d%% / %d min) + Bolus (%.1f U) + Obnovování + Nikdy + Požadovaná operace není pumpou podporována + Nebezpečné použití: extended nebo multiwave bolus je aktivní. Pumpa byla vypnuta jen na 6 hodin. Povolené jsou pouze normální bolusy. + Nebezpečné použití: pumpa má nastavený jiný bazální profil než první. Smyčka byla zakázána. Nastavete první profil a znovu načtěte. + Bolus stejné velikosti už byl během poslední minuty požadován. Jako preventivní ochrana před zdvojeným bolusem byla operace zakázána. + Teď + Načítáni historie pumpy + Výstrahy + Nastavení bazálního profilu + V zásobníku je málo inzulínu + Slabá baterie v pumpě + Pumpa hlásí chybu E%d: %s + Pokouším se obnovit spojení + Provádění bolusu a čtení historie selhalo. Zkontrolujte pumpu a zadejte bolus přes péči + Provádění bolusu selhalo. Zdá se, že žádný bolus nebyl podán. Zkontrolujte pumpu a případně pošlete bolus znovu. Jako bezpečnostní opatření podání bolusu není opakováno. + Pouze %.2f U z bolusu %.2f bylo podáno díky chybě. Zkontrolujte pumpu a proveďte nápravu. + Historie + Varování o ukončeném dočasném bazálu bylo potvrzeno. + Varování + Prázdný + Nízký + Normální + Průměr: %3.1f U + Maximum: %3.1f U + Minimum: %3.1f U + Pro přečtení historie chyb dlouze stiskněte tlačítko ALERTS. Varování: může to způsobit chybu, že pumpa bude odmítat všechny připojení a je pak vyžadováno stisknutí tlačítka na pumpě pro obnovení komunikace. + Je vyžadována aktualizace času na pumpě + Pro přečtení celkových denních dávek dlouze stikněte na pumpě tlačítko TDDS. Varování: může to způsobit chybu, že pumpa bude odmítat všechny připojení a je pak vyžadováno stisknutí tlačítka na pumpě pro obnovení komunikace. + Toto načte kompletní historii pumpy a stavy. Všechno v My Data a hodnoty bazálů. Bolusy a dočasné bazály budou přidány do ošetření, pokud neexistují. Může to způsobit duplicity díky nepřesnosti času v pumpě. Neporučuje se pokud používáte smyčku a je určeno pouze pro speciální připady. Varování: může to způsobit chybu, že pumpa bude odmítat všechny připojení a je pak vyžadováno stisknutí tlačítka na pumpě pro obnovení komunikace. + Opravdu chcete přečíst historii z pumpy a nést důsledky z toho vyplývající? + Nedostatek inzulínu pro takovýto bolus + Chyba spuštění extended bolusu diff --git a/app/src/main/res/values-de/strings.xml b/app/src/main/res/values-de/strings.xml index a0e32e76de..2981f94cfe 100644 --- a/app/src/main/res/values-de/strings.xml +++ b/app/src/main/res/values-de/strings.xml @@ -710,9 +710,6 @@ Aktivität %d%% (%d Min. verbleibend) Keine Verbindung zur Pumpe seit %d Min. - Bolusabgabe gestoppt - Bolusabgabe wird abgebrochen - Fehlerprotokol Status Keine Verbindung zur Pumpe Gestoppt (Benutzer) diff --git a/app/src/main/res/values-es/strings.xml b/app/src/main/res/values-es/strings.xml index fc0e8f8ce8..cdc7f74175 100644 --- a/app/src/main/res/values-es/strings.xml +++ b/app/src/main/res/values-es/strings.xml @@ -295,7 +295,7 @@ Corr Loop Inactivo Bolo Comida - Valor %s fuera de limites + Valor %s fuera de limites Botón Texto: Carbs: Validar: @@ -313,7 +313,7 @@ Fallo inicio basal temporal Basal temporal %.2fU/h para %d min iniciada correctamente Permitir comandos SMS remotos - Para parar basal temporal responder con codigo %s + Para parar basal temporal responder con codigo %s AndroidAPS iniciado Español NS solo subida (sinc. inactiva) @@ -325,27 +325,25 @@ Comando desconocido o respuesta incorrecta ¡Por favor asegurar que la cantidad coincide con la especificación del set de infusión! Para iniciar basal %.2fU/h responder con código %s - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " + "acciones" + "bomba virtual" + "tratamientos" + " objectivos temporales" + "objtemp" + "comunicacíon sms" + "Profil simple" + "Profiles" + "General" + "Objectivos" + "OAPS" + "LOOP" + "LP" + DANA + "conf" + CP Actividad - Por favo reinicia el teléfono o AndroidAPS desde ajustes de sistema, sino AndroidAPS no guardara registros (importantes para trazar y verificar que el algoritmo funciona correctamente) - Matriz de %d elementos. Valor actual: + Por favor reinicia el teléfono o AndroidAPS desde ajustes de sistema, sino AndroidAPS no guardara registros (importantes para trazar y verificar que el algoritmo funciona correctamente) + Matriz de %d elementos. Valor actual: Ratio Basal: Valor basal menor del mínimo. Perfil no fijado. Perfil Base @@ -362,7 +360,7 @@ Media Larga Delta Marca BAJO Batería Baja - %dmin antes + %dmin antes Usar característica AMA autosens Datos Autosens Factor porcentual para multiplicar el perfil base @@ -378,15 +376,430 @@ Media corta delta Bolo: Último BG: - %dmin antes + %dmin antes Bolo %.2fU enviado correctamente Rango Objetivo: Unidades: Sólo se permiten caracteres numéricos - Sólo se permiten dígitos en el rango %1$s - %2$s + Sólo se permiten dígitos en el rango %1$s - %2$s Este campo no puede estar vacío Número de teléfono inválido Esperando bomba Italian AndroidAPS + hollandes + Griego + Ruso + Sueco + Max U/h para el perfil base + "Max IOB basal OpenAPs puede emitir " + Para enviar calibracion %.2f responder con codigo %s + Entregaré %.2fU + Duración de acitividad de insulina + Errores + habilitar funciones adicionales para uso durante el día como SMB + %.2f limitado a %.\"f + no permitido el mando remoto + Para cancelar loop por %d minutos responde con codigo %s + Rellenar/Llenar + Llenar/Rellenar cantidad de insulina estándar + Tiempo en horas en el que el perfil será movido + mg/dl + mmol/l + DIA: + Editar Base-Basal: + Edidat Base-ISF: + Editar Base-IC: + CircadianPercentageProfile + Reloj + Abrir ajustes en reloj + Batería de la bomba descargada + DanaR Korean + BG: + MDI + MM640g + Avisos permanentes + DATOS CADUCADOS + OpenAPS AMA + Script debug + Renovar datos desde NS + DanaR Stats + Dosis diaria cumulativa + "Dosis diaria ampliada exponencialmente " + Base + Bolo + Dosis diaria + Fecha + Cuota + # Días + Peso + Probablemente impreciso usando bolo para llenar/rellenar! + Datos caducados pro favor pincha RELOAD + Basal total + Basal diaria *2 + CPP + Reloj + Tab titulo corto + Ajustes Delta + Usa siempre delta media corto en vez de delta simple + Recomendado si los datos de origen no filtrados como xDrip son inestables. + Ajustes avancados + Modelo: %02X Protocolo: %02X Codigo: %02X + Perfiles + max_daily_safety_multiplier + "Valor por defecte: 3 Esto es valor de seguridad establecido pos OpenAPS. Limita tu base al máximo de x3 de tu base máxima. No necesitas cambiar esto, pero debes tener en cuenta, que esto se esta discutiento sobre „3 x max diario; 4x actual“ pro razones de seguridad. " + current_basal_safety_multiplier + "Ajuste pro defecto: 4 Esto es la otra mitad de los ajustes de seguridad de OpenAPS y la otra mitad de \"3x max diario, 4x actual\". Esto significa, que tu base no puede ser mas alta que el numero que multiplica tu base. Esto es para evitar que las personas se encuentren en situaciones peligrosas por aumentar mucho la base sin entender el algoritmo del sistema. El ajuste por defecto es x4. La mayoría de las personas nunca tendra que cambiar estos ajustes, si no debe modificar otros ajustes en la terapia. " + autosens_max + "Ajuste por defecto: 1.2\nEsto es un multilicador para autosens (y pronto autotune) para poner un 20% limite máximo a la cota de autosens ratio, la que determina cuantos ajustes autosens puede hacer a la base, a cuanto puede ajustar ISF y a cuanto puede bajar el objective de glucosa. " + autosens_min + Ajuste pro defecto: 0.7\nEl otro lade de limitaciones de seguridad de autosens, limitando a cuanto puede bajar la base y a cuanto puede subir ISF y BG objectivos. + autosens_adjust_targets + Ajuste pro defcto: true\nEsto se usa para permitir autosens a ajustar objectivos BG en addicion a ISF y bases. + bolussnooze_dia_divisor + Ajuste pro defecto: 2 \nDormir bolo es iniciado después de proveder un bolo para comida, así el loop no interactuará con low temps cuando acabas de comer. El ajuste pro defecto es 2; quiere decir con el DIA de 3 h el bolo será dormido por fases por 1.5 h (3DIA/2). + 5_min_carb_impact + "Ajustes pro defecto: 3.0\nEsto es un ajuste pro defecto para la absorcion de carbohidratos pro 5 minutos. Por defecto se espera 3mg/dl/5min. Esto afecta la velocidad de reduccion de COB y cuanta absorcion se usa para calcular el BG futuro previsto, si la glucosa diminua mas de lo previsto o aumenta mas de lo previsto. " + "Atención!\nNormalment no tienes que editar los valores a continuacion. Por favor PINCHA AQUI y LEE el texto y PROCURA ENTENDER antes de cambiar alguno de los valores. " + http://openaps.readthedocs.io/en/latest/docs/walkthrough/phase-3/beyond-low-glucose-suspend.html + numero de telefonp incorrecto + Copiar al Clipboard + Copiado al clipboard + mostrar log + Calibracion + Calibracion + Mandar calibracion %.lf a xDrip? + xDrip+ no instalado + Calibracion mandada a xDrip + Calibracion remota no admitida + Mandar calibracion tiene que ser activada en xDrip. + xDrip no recibe calibraciones + no mostrar otra vez + Bomba parada. Pincha para aktualizar + bomba parada + recibir estado de bomba + iniciando base temporal + parando base temporal + iniciando bolo prolongado + parando bolo prolongado + actualizando cuota base + Desconectando + Efectuando + Ajustes bomba virtual + Subiendo estado a NS + Contrasena invalida + Contrasena para ajustes + desbloquear ajustes + llegando al limite de insulina diario + NSClient + NSCI + URL: + Autoscroll + Reiniciar + NSClient + Nightscout URL + Indica Nightscout URL + NS API secret + NS API secret + Indica NS API secret (min 12 chars) + Nombre aparato + Indica nombre aparato + Se usara para enteredBy field + entregar ahora + borrar cola + mostrar cola + Cola: + Estado: + Pausado + Borrar log + NSCLIENT no tiene derecho para editar. API secret incorrecto? + Ajustes reloj + mostrar detalles IOB + Separar IOB en bolo y base en el reloj + sin efecto - por favor controlar en móvil + no disponible + Edad paciente + Menor de edad + Adolescente + Adulto + Por favor elige edad del paciente para emplear limites de seguridad + Glimp + Aparato parece no soportar optimisacion de bateria whitelisting! + Por favor permita Permission + %s necesita optimisacion de bateria whitelisting para funcionar bien + Loop desactivado + desactivado (%d m) + Superbolus (%d m) + Loop menu + Desactivar loop por 1h + Desactivar loop por 2h + Desactivar loop por 3h + Desactivar loop por 10 h + Desconectar bomba por 30 min + Desconectar bomba por 1 h + Desconectar bomba por 2 h + Desconectar bomba por 3 h + Desconectar bomba por 10 h + Reiniciar + duracion incorrecta + Loop desactivado + Loop reiniciado + Tendencia 15 min + COB + Superbolo + Indica app start en NS + Aplicacion existente para aplicar ajustes. + DanaRv2 + Insulina + Insulina acción rápida + Novorapid, Novolog, Humalog + Fiasp + INS + Insulina acción rápida prolongada + activar superbolo en wizard + Activar función superbolo en wizard. No lo actives hasta que hayas aprendido lo que realmente hace. PUEDE CAUSAR SOBREDOSIS DE INSULINA usandolo sin precaucion! + IOB + COB + PRE + BAS + Firmware + Estado de bluetooth + Sobre + "Falta permitir SMS " + DEV + xDrip Status (reloj) + xDrip Statusline (reloj) + xds + Mostrar BGI + agregar BGI a status line + No upload to NS + Todos los datos mandados a NS son borrados. AAPS esta conectado to NS pero no hay cambios en NS + Nivel base + Nivel bolo + Bolo prolongado + "Objectivo temporal " + cancelar bolo prolongado + Edad sensor + Edad cánula + Edad insulina + horas + Tipo base + Falta ISF en perfil. Usando ajuste por defecto. + Falta IC en perfil. Usando ajuste por defecto. + Falta base en perfil. Usando ajuste por defecto. + "Falta objectivo en perfil. Usando ajuste por defecto. " + Perfil invalido !!! + CambioPerfil + Edad bateria bomba + Cambio bateria bomba + Opciones alama + Urgente alto + Alto + Bajo + Urgente bajo + Actualmente puesto a %f + Stale data + Urgent stale data + Stale data threshold [min] + Urgent stale data threshold [min] + Interval para autosens [h] + Horas en el pasado para detectar sensividad (tiempo de absorcion de carbohidratos no incluidos) + SEN + "Ignora evenos de cambio de perfil " + "Totos los cambios de perfil son ignorados y se usa siempre el perfil actual " + Bomba + OpenAPS + Aparato + Uploader + Deteccion sensividad + SENS + Sensitivity Oref0 + Sensitivity AAPS + Ajustes absorcion + Tiempo max absorcion comida [h] + Tiempo esperado en el que todos los carbohidratos son absorbados + mostrar bolo prolongado en % + SAGE + IAGE + CAGE + PBAGE + OAPS + UPLD + BAS + EXT + Pantalle proteccion + Cierre + Al activar autosens recuerda editar todos carbohidratos comidos. Si no, sensividad será calculada incorrectamente !!! + Sensitivity WeightedAverage + OK + Cancelar + necesita ser activado para mandar valores a la bomba! + Faltan perfiles! + Valores no guardados! + Resumen avisos + Mandar resumen de avisos como avisos de confirmacion por reloj. + Accu-Chek Combo + COMBO + Activar mensajes a otras aplicaciones (como xDrip). + Activar mensajes locales. + ACTIVITY Y FEEDBACK + CARBS Y BOLUS + CGM Y OPENAPS + PUMP + Valor base [U/h] + Duracion [min] + IOB Curve Peak Time + Peak Time [min] + Free-Peak Oref + Rapid-Acting Oref + Ultra-Rapid Oref + DIA de %s demasiado corto - usando %s! + ACTIVAR PERFIL + Fecha + INVALIDO + Esperando para conectar con bomba + Coneccion OK + Coneccion fuera de tiempo + CONECTANDO + aparato no enconrado + Deposito vacio + Alerta de control de BG + Insulina restante en deposito + DanaRS + Dana + Bomba sleccionada + Conectar bomba nueva + Velocidad bolo + Poner paso base a 0.01 U/h + Numero de serie + Porcientos + Cambio de tiepmo + Ojbectivo temporal por defecto + duracion comiendopronto + objectivo comiendopronto + duracion actividad + objectivo actividad + Prime + recibiendo estado de bolo prolongado + recibiendo estado bolo + recibiendo estado bolo temporal + recibiendo ah´justes bomba + recibiendo hora bomba + usar otra vez + Control desde reloj + editar y emitir abjectivos temp. y tratamientos por reloj + Fuera tiempo coneccion + comida + g + ]]> + kJ + En + Pr + Grasa + ]]> + Esperande terminar bolo. Faltan %d seg. + Processando + "Iniciando emisioin bolo " + Orden se esta efectuando en este momento + control de la bomba corigido + bomba no alcanzable + "Falta lectura BG " + Usa avisos del sistema para alarmas y avisos + Alarma local + Alarma si no llegan datos BG + Alarma si bomba no es alcanzable + Alarma urgente + INFO + Bluetooth + BT Watchdog + Apaga el bluetooth del móvil por un segundo si no hay coneccion con la bomba. Esto ayuda con algunos moviles con problemas de establecer coneccion bluetooth estable. + DexcomG5 App (patched) + Envias datos BG a NS + G5 upload ajustes + APK adaptada para bajar + "mostrar detalles delta " + mostrar delta con una plaza decimal mas + firmware de la bomba no apoyada + mandar BG a xDrip + En xDrip elige 640g/Eversense date source + NSClient BG + Valor base remplazado por valor mínimo + Calculacion BG + Calculacion bolo IOB + Calculacion base IOB + Calculacion tendencia + Calculacion superbolo + Si + No + Solo positivo + Solo negativo + Calculacion COB + Calculacion objectivo temporal + Loop activado + APS seleccionado + NSClient tiene permission de escribir + Modo cerrado activado + Máximo IOB puesto correctamente + BG adquirible del origen seleccionado + Valores base no asignados a las horas: %s + Perfil invalido: %s + Programando bomba para emitir bolo + Actualizar + TDDS + Estado + Actividad + Ninguna coneccnion por %d min + %d%% (%d min restan) + %.1f U (%s, %s) + Iniciando + Desconectado + Apagado por error + Apagado por usario + Funcionando + Cancelando TBR + Poniendo TBR (%d%% / %d min) + Emitiendo bolo (%.1f U) + Actualizando + Nunca + "Acción no disponible en la bomba " + Uso inseguro: bolo prolongado o multiwave activo. Modo Loop ha sido puesto a baja emision para solo 6 horas. Solo bolo normal se puede emitir en modo loop. + "Uso inseguro: la bomba usa base diferente a la primera. El loop ha sido apagado. Elige primero perfil en la bomba y acualiza. " + Un bolo de mismo valor ha sido dado durante el pasado minuto. Para evitar bolos dobles y asegurarse contra bugs esto no es permitido. + Ahora + Leiendo historia bomba + Alarmas + " Activando perfil base " + "Nivel del deposito bajo " + Bateria casi agotada + La bomba muesta el error E%d: %s + Para leer historial de los errores, pincha unos segundo el boton \"ALARMAS\" ATENCION: esto puede causar un bug. La bomba no vuelve a conectarse - necesitas pulsar un boton en la misma bomba para reiniciarse. Deberias evitar esto. + Para leer el hisorial TDD de la bomba pulsa el boton TDDS unso segundos. ATENCION: esto puede causar un bug. La bomba no vuelve a conectarse - necesitas pulsar un boton en la misma bomba para reiniciarse. Deberias evitar esto. + Mínimo: %3.1f U + Media: %3.1f U + Máximo: %3.1f U + Bajo + Vacio + Normal + Se necesita actualizar reloj de la bomba + Historial + Alerta + "Esto lee todo el historial y estado de la bomba, tus datos, la base. Bolos, basales temporales y tratamientos seran copiados y agregados si no existen ya. Esto puede causar duplicaciones, por que la hora de la bomba no es precisa. Es uso de esto con el loop normal solo deb ser usado en cirumstancisas especiales. Si de todas meneras quieres usar esto pulsa este boton unos segundos otra vez. ADVERTENCIA: esto puede causar un bug. La bomba no vuelve a conectarse - necesitas pulsar un boton en la misma bomba para reiniciarse. Deberias evitar esto. " + "Estas seguro, de que quieres leer todos los datos de la bomba y acceptar las consequencias de esta acción? " + TBR cancelada, advertencia acceptada + Emision del bolo fallado. Ningún bolo se ha emitido. Para asegurarse, por favor controle la bomba para evitar bolo doble. Para evitar bugs no se reinician bolos automaticamente. + "Solo %.2f U del bolo mandado de %.2f U ha sido emitido por causa de un error. Por favorn controla la bomba para confirmar y toma acciones apropiadas. " + "Fallo de emitir bolo y de controlar historical de la bomba.Por favor controla manualmente y crea un record en Careportal si el bolo ha sido emitido. " + Reestablecido coneccion fallada. + "No hay suficiente insulina en el deposito para emitir bolo. " + "Error al emitir bolo prolongado. " + bomba no alcanzable treshold [min] + TT + Versión no acceptada de Nightscout + Activar loop + Desactivar loop + Base: + Base temporal no emitida + Base temporal + Delta: + IOB: diff --git a/app/src/main/res/values-ko/strings.xml b/app/src/main/res/values-ko/strings.xml index 233d7ce73c..5d45e3eea6 100644 --- a/app/src/main/res/values-ko/strings.xml +++ b/app/src/main/res/values-ko/strings.xml @@ -129,9 +129,9 @@ APS 모드 Closed Loop Open Loop - Loop 비활성화됨 - Loop 비활성화하기 - Loop 활성화하기 + Loop 중지됨 + Loop 중지하기 + Loop 실행하기 새로운 제안이 있습니다 지원하지 않는 NSClient 버전입니다 지원하지 않는 Nightscout 버전입니다 @@ -183,7 +183,7 @@ 임시기초주입 확장식사주입 Nightscout 버전: - 보내기 + 전송하기 Missing 사용 보이기 @@ -251,13 +251,12 @@ Finger Sensor Manual - 임시 목표 - 임시 목표 취소 + 임시목표 + 임시목표 취소 DanaR 프로파일 설정 인슐린활동시간(DIA) [h] Duration of Insulin Activity 기초주입 프로파일 갱신 실패 - 과거기록 새로고침 업로드중 E bolus @@ -305,14 +304,15 @@ 필요하면 기초주입과 비율을 조절하고, auto-sens를 활성화한다. 평소의 탄수화물을 입력하면서 1주일동안 낮시간대에 loop를 성공적으로 사용해본다. AMA(Advanced Meal Assist)같은 낮시간대를 위한 추가적인 기능들을 실행하여 본다. + 낮시간대에 SMB(Super Micro Bolus)같은 추가기능을 활성화해 사용해본다. 허용된 제한값에 도달하였습니다 프로파일이 선택되지 않았습니다 Loop가 중지되었습니다. Loop가 실행되었습니다. Loop가 중지중입니다. Loop가 실행중입니다. - %.2f limited to %.2f - 값 %s 은 하드리밋(Hard Limit)를 벗어났습니다 + %.2f, %.2f으로 제한됨 + %s값이 하드리밋(Hard Limit)를 벗어났습니다 원격 기초주입설정이 허가되지 않았습니다 원격 명령이 허가되지 않았습니다 기초주입 %.2fU/h 을 실행하려면 %s 를 입력하고 답장하세요 @@ -384,20 +384,20 @@ MM640g 연속 알림 OLD DATA - %d분전 - %dmin ago + %d분전 + %dmin ago Local Profile OpenAPS AMA Short avg. delta Long avg. delta - Array of %d elements.\nActual value: + Array of %d elements.\nActual value: Autosens 정보 Script debug AMA autosens 기능 사용하기 NS에서 이벤트 새로고침 Eating Soon Activity - Remove record: + 기록 삭제: DanaR 통계 누적 일총량 지수가중 일총량 @@ -436,7 +436,7 @@ 단순델타값 대신 단기평균델타값을 항상 사용합니다. xDrip의 혈당데이터에 노이즈가 심할경우 유용합니다. 고급 설정 - Model: %02X Protocol: %02X Code: %02X + 모델: %02X 프로토콜: %02X 코드: %02X 프로파일 기본값: 3\n이 값은 중요한 OpenAPS 안전장치입니다. 이 값의 역할은 펌프에 설정되어 있는 최대기초주입량보다 3배를 초과할 수 없게 제한하는 것입니다. 이 값을 변경할 필요는 없을 것이지만, 안전을 위해 "3x max daily; 4x current"이 의미하는 바를 알고 있어야 합니다. 기본값: 4\n이 값은 "3x max daily; 4x current"의 나머지 절반에 해당하는 또 다른 중요한 OpenAPS 안전장치입니다. 이 값은 펌프에 설정된 최대기초주입량과 관계없이, 설정된 현재시간의 기초주입량에 이 값을 곱한 양을 초과할 수 없게됩니다. 이는 알고리즘의 작동 방식을 이해하기 전에 과도하게 높은 최대 기본을 설정하여 위험한 상황에 빠지지 않도록 보호하기 위한 것입니다. 다시한번, 기본 값은 4배인 것을 알아두세요; 일반적으로 이것을 조정할 필요는 전혀 없으며, 대신 이 안전장치를 변경해야할것처럼 생각이 된다면, 다른 설정을 변경해야 할 가능성이 더 큽니다. @@ -448,12 +448,12 @@ 주의!\n보통의 경우 아래의 값을 변경하면 안됩니다. 이 값들을 변경하기 전에 반드시 이곳을 클릭하고 글을 정독해서 확실하게 이해를 하여야 합니다. http://openaps.readthedocs.io/en/latest/docs/walkthrough/phase-3/beyond-low-glucose-suspend.html 숫자만 입력가능합니다. - 이 범위(%1$s - %2$s)안에 해당하는 숫자만 입력가능합니다. + 이 범위(%1$s - %2$s)안에 해당하는 숫자만 입력가능합니다. 필수 입력 항목입니다. 폰번호가 유효하지 않습니다 SMS폰번호가 유효하지 않습니다 - Copy To Clipboard - Copied to clipboard + 클립보드에 복사 + 클립보드에 복사되었습니다 로그 보기 보정 혈당 보정 @@ -475,7 +475,7 @@ 연결끊기중 실행중 가상펌프 설정 - Upload status to NS + NS에 상태 업로드하기 잘못된 비밀번호 설정 비밀번호 설정 잠금해제 @@ -483,7 +483,7 @@ 내장 NSClient NSCI URL: - Autoscroll + 자동스크롤 Restart 내장 NSClient Nightscout URL @@ -499,13 +499,13 @@ Show queue Queue: Status: - Paused + 일시중지 Clear log NSCLIENT이 쓰기 권한이 없습니다. 잘못된 API secret인지 확인해보세요 웨어 설정 IOB 자세하게 보여주기 워치페이스에 IOB를 식사주입IOB와 기초주입IOB로 나누어서 보여줍니다. - not successful - please check phone + 성공하지 못했습니다. 폰을 확인하세요 알수없음 나이 어린이 @@ -515,10 +515,9 @@ Glimp Device does not appear to support battery optimization whitelisting! 권한을 허용하세요. - %s needs battery optimalization whitelisting for proper performance Loop 일시중지 일시중지중 (%d분) - Superbolus (%d분) + 수퍼 식사주입 (%d분) Loop 메뉴 1시간동안 Loop 일시중지 2시간동안 Loop 일시중지 @@ -529,24 +528,24 @@ 2시간동안 펌프 일시중지 3시간동안 펌프 일시중지 10시간동안 펌프 일시중지 - 재시작 + 재실행 기간이 잘못되었습니다. - Loop가 일시중지되었습니다. - Loop가 재시작되었습니다. + Loop가 일시중지 되었습니다. + Loop가 재실행 되었습니다. 15분 추이 COB - Superbolus + 수퍼 식사주입 앱시작을 NS에 기록하기 설정을 적용하기위해 앱을 종료합니다. 다나Rv2 인슐린 Fast Acting Insulin - Novorapid, Novolog, Humalog - Fiasp + 노보래피드, 휴마로그, 에피드라 + 피아스프(Fiasp) INS Fast Acting Insulin Prolonged - 마법사에서 Superbolus 활성화하기 - 마법사에서 Superbolus 기능을 활성화합니다. 어떤 기능인지 확실히 알기전까지 활성화 하지 마세요. 제대로 알지 못하고 사용하면 일슐린이 과다 주입될 수 있습니다! + 마법사에서 수퍼 식사주입 활성화하기 + 마법사에서 수퍼 식사주입 기능을 활성화합니다. 어떤 기능인지 확실히 알기전까지 활성화 하지 마세요. 제대로 알지 못하고 사용하면 일슐린이 과다 주입될 수 있습니다! IOB COB PRE @@ -583,15 +582,15 @@ 펌프배터리사용기간 펌프 배터리 교체 알람 옵션 - Urgent high - High - Low - Urgent low + 위험 고혈당 + 고혈당 + 저혈당 + 위험 저혈당 Currently set to %f - Stale data - Urgent stale data - Stale data threshold [min] - Urgent stale data threshold [min] + 누락 데이터 + 위험 누락 데이터 + 누락 데이터 기준값[분] + 위험 누락 데이터 기준값[분] autosens 시간 [h] 민감도를 감지하기 위해 계산될 총 시간 (탄수화물 흡수 시간은 제외됩니다.) SEN @@ -603,8 +602,8 @@ Uploader 민감도 감지 SENS - Sensitivity Oref0 - Sensitivity AAPS + 민감도 Oref0 + 민감도 AAPS 흡수 설정 식사 최대 흡수 시간 [h] 식사로 섭취한 탄수화물이 모두 흡수될기까지 예상되는 시간 @@ -620,7 +619,7 @@ 화면 잠금 잠금 Autosense 기능을 켜면 모든 섭취된 탄수화물양을 입력하십시오. 그렇지 않으면 탄수화물 편차(deviations)가 민감도 변화로 잘못 인식될것입니다!! - Sensitivity WeightedAverage + 민감도 가중평균 OK Cancel needs to be activated to send values to the pump! @@ -636,13 +635,13 @@ 펌프 Basal value [U/h] Duration [min] - IOB Curve Peak Time - Peak Time [min] + IOB 커브 피크 시간 + 피크 시간[분] Free-Peak Oref Rapid-Acting Oref Ultra-Rapid Oref - "DIA of %s too short - using %s instead!" - ACTIVATE PROFILE + "DIA %s는 너무 짧습니다. 대신 %s을 사용하세요!" + 프로파일 활성화하기 Date INVALID 펌프연동 대기중 @@ -677,4 +676,60 @@ 워치로 작동하기 임시목표와 관리입력을 워치로 설정합니다. 연결시간초과 + 음식 + g + ]]> + kJ + En + Pr + Fat + ]]> + 식사주입 종료를 기다리고 있습니다. %d초 남았습니다. + 이벤트 처리중 + 식사주입을 시작합니다. + 명령을 지금 실행합니다. + 펌프 드라이버가 수정되었습니다. + 펌프에 연결할 수 없습니다. + 혈당 읽기가 누락되었습니다. + 경고와 알림시 시스템 알림 사용하기 + 자체 경고 기능 + 혈당 데이터 누락시 경고하기 + 펌프와 연결불가시 경고하기 + 펌프 연결불가 기준시간[분] + 긴급 알람 + 정보 + 블루투스 + 블루투스 감시기능 + 펌프에 연결이 되지 않을때 폰의 블루투스를 1초간 껐다 켭니다. 블루투스 스택이 정지되는 일부폰에 이 기능이 도움이 됩니다. + (패치된) DexcomG5 앱 + NS에 혈당데이터 업로드하기 + G5업로드 세팅 + Customized APK for download + 델타(혈당증분값) 자세히 보여주기 + 소수점 한자리 더 추가된 델타 보여주기 + 지원되지 않는 펌프 펌웨어 + 혈당 데이터를 xDrip+에 전송하기 + xDrip+ 데이터 소스에서 640g/Eversense을 선택하세요 + 지원되는 최소값으로 기초주입량이 대체되었습니다. + 혈당 계산 + 식사주입 IOB 계산 + 기초주입 IOB 계산 + 추세계산 + 수퍼 식사주입 계산 + + 아니오 + 양수만 + 음수만 + COB 계산 + 임시목표 계산 + Loop 활성화됨 + APS 선택됨 + NSClient가 쓰기권한이 있습니다 + Closed 모드가 활성화됨 + 최대 IOB가 바르게 설정됨 + 선택한 소스에서 혈당이 들어옵니다. + 기초주입값이 시간단위로 설정되지 않았습니다: %s + 유효하지 않은 프로파일: %s + 펌프 이력 + 확장식사주입 에러 diff --git a/app/src/main/res/values-nl/strings.xml b/app/src/main/res/values-nl/strings.xml index 1503c4ef05..61bd323d73 100644 --- a/app/src/main/res/values-nl/strings.xml +++ b/app/src/main/res/values-nl/strings.xml @@ -675,15 +675,12 @@ Bedieningen via horloge Ampull leeg Wachten op koppelen van de pomp - Storingen Wijzigingen van profiel Bluetooth Voeding Waarschuwing bij niet bereikbare pomp Een bolus met dezelfde hoeveelheid was gevraagd binnen de minuut. Om accidentiële of door bugs veroorzaakte dubbele bolussen te vermijden is deze bolus geannuleerd - estopt Bolus toediening wordt Vet - Bolus toediening gestopt Toon gedetaillieerde delta Niet ondersteune pomp firmware DexcomG5 App (aangepast) diff --git a/app/src/main/res/values-ro/strings.xml b/app/src/main/res/values-ro/strings.xml new file mode 100644 index 0000000000..ab81436cc5 --- /dev/null +++ b/app/src/main/res/values-ro/strings.xml @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/app/src/main/res/values/arrays.xml b/app/src/main/res/values/arrays.xml index ad6a2e1166..660f6ee00e 100644 --- a/app/src/main/res/values/arrays.xml +++ b/app/src/main/res/values/arrays.xml @@ -20,6 +20,7 @@ @string/el_lang @string/it_lang @string/ko_lang + @string/ro_lang @string/ru_lang @string/sv_lang @@ -33,6 +34,7 @@ el it ko + ro ru sv diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index f297e92588..9aacf6f744 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -209,6 +209,7 @@ Spanish Greek Italian + Romanian Russian Swedish Max U/hr a Temp Basal can be set to @@ -268,7 +269,6 @@ DIA [h] Duration of Insulin Activity Failed to update basal profile - Errors Reload Uploading E bolus @@ -454,9 +454,9 @@ Model: %02X Protocol: %02X Code: %02X Profile max_daily_safety_multiplier - Default value: 3\nThis is a key OpenAPS safety cap. What this does is limit your basals to be 3x (in this people) your biggest basal rate. You likely will not need to change this, but you should be aware that’s what is discussed about “3x max daily; 4x current” for safety caps. + Default value: 3 This is a key OpenAPS safety cap. What this does is limit your basals to be 3x (in this people) your biggest basal rate. You likely will not need to change this, but you should be aware that’s what is discussed about “3x max daily; 4x current” for safety caps. current_basal_safety_multiplier - Default value: 4\nThis is the other half of the key OpenAPS safety caps, and the other half of “3x max daily; 4x current” of the safety caps. This means your basal, regardless of max basal set on your pump, cannot be any higher than this number times the current level of your basal. This is to prevent people from getting into dangerous territory by setting excessively high max basals before understanding how the algorithm works. Again, the default is 4x; most people will never need to adjust this and are instead more likely to need to adjust other settings if they feel like they are “running into” this safety cap. + Default value: 4 This is the other half of the key OpenAPS safety caps, and the other half of “3x max daily; 4x current” of the safety caps. This means your basal, regardless of max basal set on your pump, cannot be any higher than this number times the current level of your basal. This is to prevent people from getting into dangerous territory by setting excessively high max basals before understanding how the algorithm works. Again, the default is 4x; most people will never need to adjust this and are instead more likely to need to adjust other settings if they feel like they are “running into” this safety cap. autosens_max Default value: 1.2\nThis is a multiplier cap for autosens (and soon autotune) to set a 20% max limit on how high the autosens ratio can be, which in turn determines how high autosens can adjust basals, how low it can adjust ISF, and how low it can set the BG target. autosens_min @@ -466,9 +466,9 @@ bolussnooze_dia_divisor Default value: 2\nBolus snooze is enacted after you do a meal bolus, so the loop won’t counteract with low temps when you’ve just eaten. The example here and default is 2; so a 3 hour DIA means that bolus snooze will be gradually phased out over 1.5 hours (3DIA/2). min_5m_carbimpact - Default value: 3.0\nThis is a setting for default carb absorption impact per 5 minutes. The default is an expected 3mg/dl/5min. This affects how fast COB are decayed, and how much carb absorption is assumed in calculating future predicted BG, when BG is falling more than expected, or not rising as much as expected. + Default value: 3.0 This is a setting for default carb absorption impact per 5 minutes. The default is an expected 3mg/dl/5min. This affects how fast COB are decayed, and how much carb absorption is assumed in calculating future predicted BG, when BG is falling more than expected, or not rising as much as expected. Attention!\nNormally you do not have to change these values below. Please CLICK HERE and READ the text and make sure you UNDERSTAND it before change any of these values. - http://openaps.readthedocs.io/en/latest/docs/walkthrough/phase-3/beyond-low-glucose-suspend.html + http://openaps.readthedocs.io/en/latest/docs/walkthrough/phase-3/beyond-low-glucose-suspend.html Only numeric digits are allowed. Only numeric digits within the range %1$s - %2$s are allowed. The field must not be empty @@ -783,7 +783,7 @@ Switches off the phone\'s bluetooth for one second if no connection to the pump is possible. This may help on some phones where the bluetooth stack freezes. DexcomG5 App (patched) Upload BG data to NS - dexcomg5_nsupload + dexcomg5_nsupload G5 upload settings Customized APK for download Show detailed delta @@ -820,7 +820,7 @@ Activity No connection for %d min %d%% (%d min remaining) - %.1f %s (%s) + %.1f %s (%s) Initializing Disconnected Suspended due to error @@ -855,7 +855,7 @@ History Warning Long press this button to force a full read of history and basal profile from the pump. This is generally not needed, since the pump\'s history is read continuously, but can be useful if the pump\'s date and time changed significantly or the pump was replaced. - This will read the full history and state of the pump. Everything in \"My Data\" and the basal rate. Boluses and TBRs will be added to Treatments if they don\'t already exist. This can cause entries to be duplicated because the pump\'s time is imprecise. Using this when normally looping with the pump is highly discouraged and reserved for special circumstances. If you still want to do this, long press this button again.\n\nWARNING: this can trigger a bug which causes the pump to reject all connection attempts and requires pressing a button on the pump to recover and should therefore be avoided. + This will read the full history and state of the pump. Everything in My Data and the basal rate. Boluses and TBRs will be added to Treatments if they don\'t already exist. This can cause entries to be duplicated because the pump\'s time is imprecise. Using this when normally looping with the pump is highly discouraged and reserved for special circumstances. If you still want to do this, long press this button again. WARNING: this can trigger a bug which causes the pump to reject all connection attempts and requires pressing a button on the pump to recover and should therefore be avoided. Are you really sure you want to read all pump data and take the consequences of this action? TBR CANCELLED warning was confirmed The pump could not be reached. No bolus was given diff --git a/app/src/test/java/info/nightscout/androidaps/plugins/Insulin/InsulinOrefBasePluginTest.java b/app/src/test/java/info/nightscout/androidaps/plugins/Insulin/InsulinOrefBasePluginTest.java new file mode 100644 index 0000000000..83e9442364 --- /dev/null +++ b/app/src/test/java/info/nightscout/androidaps/plugins/Insulin/InsulinOrefBasePluginTest.java @@ -0,0 +1,153 @@ +package info.nightscout.androidaps.plugins.Insulin; + +import org.junit.Before; +import org.junit.Test; + +import info.nightscout.androidaps.data.Iob; +import info.nightscout.androidaps.db.Treatment; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +/** + * Created by triplem on 07.01.18. + */ + +public class InsulinOrefBasePluginTest extends InsulinOrefBasePlugin { + + private int peak; + private double dia; + + private boolean shortDiaNotificationSend; + + @Before + public void setUp() throws Exception { + this.peak = 0; + this.dia = InsulinOrefBasePlugin.MIN_DIA; + this.shortDiaNotificationSend = false; + } + + @Test + public void testGetDia() throws Exception { + assertEquals(InsulinOrefBasePlugin.MIN_DIA, this.getDia(), 0); + + this.dia = InsulinOrefBasePlugin.MIN_DIA + 1; + assertEquals(InsulinOrefBasePlugin.MIN_DIA + 1, this.getDia(), 0); + + this.dia = InsulinOrefBasePlugin.MIN_DIA - 1; + assertEquals(InsulinOrefBasePlugin.MIN_DIA, this.getDia(), 0); + assertTrue(this.shortDiaNotificationSend); + } + + @Test + public void testIobCalcForTreatment() { + Treatment treatment = new Treatment(); + Iob expected = new Iob(); + + assertEquals(expected, this.iobCalcForTreatment(treatment, 0, 0d)); + + this.peak = 30; + this.dia = 4; + long time = System.currentTimeMillis(); + + // check directly after bolus + treatment.date = time; + treatment.insulin = 10d; + assertEquals(10d, this.iobCalcForTreatment(treatment, time).iobContrib, 0.1); + + // check after 1 hour + treatment.date = time - 1 * 60 * 60 * 1000; // 1 hour + treatment.insulin = 10d; + assertEquals(3.92, this.iobCalcForTreatment(treatment, time).iobContrib, 0.1); + + // check after 2 hour + treatment.date = time - 2 * 60 * 60 * 1000; // 1 hour + treatment.insulin = 10d; + assertEquals(0.77, this.iobCalcForTreatment(treatment, time).iobContrib, 0.1); + + // check after 3 hour + treatment.date = time - 3 * 60 * 60 * 1000; // 1 hour + treatment.insulin = 10d; + assertEquals(0.10, this.iobCalcForTreatment(treatment, time).iobContrib, 0.1); + + // check after dia + treatment.date = time - 4 * 60 * 60 * 1000; + treatment.insulin = 10d; + assertEquals(0d, this.iobCalcForTreatment(treatment, time).iobContrib, 0.1); + } + + + /** + * this method is implemented to allow tests of the iobCalcForTreatment calculation + * @return + */ + @Override + int getPeak() { + return this.peak; + } + + /** + * Userdefined Dia is implemented to allow tests of the getDia method + * + * @return + */ + public double getUserDefinedDia() { + return this.dia; + } + + void sendShortDiaNotification(double dia) { + this.shortDiaNotificationSend = true; + } + + + // the following methods are implemented, but not needed... + @Override + String commentStandardText() { + return null; + } + + @Override + public String getFragmentClass() { + return null; + } + + @Override + public int getId() { + return 0; + } + + @Override + public String getName() { + return null; + } + + @Override + public String getFriendlyName() { + return null; + } + + @Override + public boolean isEnabled(int type) { + return false; + } + + @Override + public boolean isVisibleInTabs(int type) { + return false; + } + + @Override + public void setFragmentEnabled(int type, boolean fragmentEnabled) { + + } + + @Override + public void setFragmentVisible(int type, boolean fragmentVisible) { + + } + + @Override + public int getPreferencesId() { + return 0; + } +} diff --git a/wear/src/main/java/info/nightscout/androidaps/watchfaces/BaseWatchFace.java b/wear/src/main/java/info/nightscout/androidaps/watchfaces/BaseWatchFace.java index ea5b41176b..fab81aafb9 100644 --- a/wear/src/main/java/info/nightscout/androidaps/watchfaces/BaseWatchFace.java +++ b/wear/src/main/java/info/nightscout/androidaps/watchfaces/BaseWatchFace.java @@ -70,7 +70,6 @@ public abstract class BaseWatchFace extends WatchFace implements SharedPreferen public boolean layoutSet = false; public boolean bIsRound = false; public int pointSize = 2; - public int missed_readings_alert_id = 818; public BgGraphBuilder bgGraphBuilder; public LineChartView chart; public ArrayList bgDataList = new ArrayList<>(); @@ -181,7 +180,6 @@ public abstract class BaseWatchFace extends WatchFace implements SharedPreferen } } ); - ListenerService.requestData(this); wakeLock.acquire(50); } @@ -638,8 +636,6 @@ public abstract class BaseWatchFace extends WatchFace implements SharedPreferen chart.setLineChartData(bgGraphBuilder.lineData()); chart.setViewportCalculationEnabled(true); chart.setMaximumViewport(chart.getMaximumViewport()); - } else { - ListenerService.requestData(this); } }