Merge pull request #25 from jotomo/combo-scripter-v2

feb 4
This commit is contained in:
Simon Pauwels 2018-02-04 20:11:14 +01:00 committed by GitHub
commit bf8ff5a718
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
43 changed files with 2041 additions and 2399 deletions

10
ISSUE_TEMPLATE.md Normal file
View file

@ -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

View file

@ -13,7 +13,7 @@ import info.nightscout.androidaps.db.Source;
* Created by mike on 29.05.2017.
*/
public class DetailedBolusInfo implements Cloneable {
public class DetailedBolusInfo {
public long date = System.currentTimeMillis();
public String eventType = CareportalEvent.MEALBOLUS;
public double insulin = 0;

View file

@ -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;
}
}

View file

@ -13,7 +13,7 @@ import info.nightscout.androidaps.R;
import info.nightscout.utils.DecimalFormatter;
import info.nightscout.utils.Round;
public class PumpEnactResult extends Object {
public class PumpEnactResult {
private static Logger log = LoggerFactory.getLogger(PumpEnactResult.class);
public boolean success = false; // request was processed successfully (but possible no change was needed)

View file

@ -1,14 +1,12 @@
package info.nightscout.androidaps.interfaces;
import android.support.annotation.NonNull;
import org.json.JSONObject;
import java.util.Date;
import info.nightscout.androidaps.data.DetailedBolusInfo;
import info.nightscout.androidaps.data.PumpEnactResult;
import info.nightscout.androidaps.data.Profile;
import info.nightscout.androidaps.data.PumpEnactResult;
/**
* Created by mike on 04.06.2016.

View file

@ -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();
}

View file

@ -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

View file

@ -52,7 +52,6 @@ import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
import info.nightscout.androidaps.Config;
import info.nightscout.androidaps.Constants;

View file

@ -4,6 +4,9 @@ import android.os.SystemClock;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import com.crashlytics.android.answers.Answers;
import com.crashlytics.android.answers.CustomEvent;
import org.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -610,6 +613,10 @@ public class ComboPlugin implements PluginBase, PumpInterface, ConstraintsInterf
Notification notification = new Notification(Notification.COMBO_PUMP_ALARM, MainApp.sResources.getString(R.string.combo_error_updating_treatment_record), Notification.URGENT);
MainApp.bus().post(new EventNewNotification(notification));
}
Answers.getInstance().logCustom(new CustomEvent("ComboBolusToDbError")
.putCustomAttribute("buildversion", BuildConfig.BUILDVERSION)
.putCustomAttribute("version", BuildConfig.VERSION)
.putCustomAttribute("issue", "record with same timestamp existed and was overridden"));
return false;
}
} catch (Exception e) {
@ -617,6 +624,10 @@ public class ComboPlugin implements PluginBase, PumpInterface, ConstraintsInterf
if (dbi.isSMB) {
Notification notification = new Notification(Notification.COMBO_PUMP_ALARM, MainApp.sResources.getString(R.string.combo_error_updating_treatment_record), Notification.URGENT);
MainApp.bus().post(new EventNewNotification(notification));
Answers.getInstance().logCustom(new CustomEvent("ComboBolusToDbError")
.putCustomAttribute("buildversion", BuildConfig.BUILDVERSION)
.putCustomAttribute("version", BuildConfig.VERSION)
.putCustomAttribute("issue", "adding record caused exception"));
}
return false;
}

View file

@ -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
}

View file

@ -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,21 +14,18 @@ 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<CharSequence> entries = new Vector<CharSequence>();
if (bta != null) {
Set<BluetoothDevice> 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) {

View file

@ -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);

View file

@ -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
}

View file

@ -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 = "";

View file

@ -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 {

View file

@ -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);

View file

@ -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;
}

View file

@ -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));

View file

@ -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<BluetoothDevice> 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;
}
}

View file

@ -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);
}

View file

@ -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<BluetoothDevice> 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");
}
}

View file

@ -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
}

View file

@ -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 {

View file

@ -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)) {

View file

@ -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;
}

View file

@ -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<BluetoothDevice> 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);
}
}

View file

@ -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";
}

View file

@ -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;

View file

@ -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
}

View file

@ -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 {

View file

@ -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");

View file

@ -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<BluetoothDevice> 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);
}
}

View file

@ -444,7 +444,6 @@
<string name="openapsama_bolussnooze_dia_divisor_summary">По подразбиране: 2\nBolus snooze се активира след като поставите болус за основно хранене, така Loop няма да пуснка/намаля базалите веднага след като сте се хранили. Примерът тук е с 2; така при 3 часа DIA това ще означава че bolus snooze ще бъде внимателно изместен 1.5 часа (3DIA/2).</string>
<string name="openapsama_min_5m_carbimpact_summary">По подразбиране: 3.0\nТова е настройка на количеството на покачване на КЗ при усвояване на въглехидратите за всеки 5 минути. По подразбиране 3мг/дл/5мин. Това се отразява на това колко бързо се усвояват COB според алгоритъма, и как това се отразява в предвиждането на КЗ, когато тя не се покачва или пада с различен темп от очакваното.</string>
<string name="openapsama_link_to_preferncejson_doc_txt">Внимание! Обикновено Вие не трябва да променяте тези стойности. Моля НАТИСНЕТЕ ТУК, прочетете текста и бъдете сигурни, че го РАЗБИРАТЕ преди да направите каквито и да е промени!</string>
<string name="openapsama_link_to_preferncejson_doc">http://openaps.readthedocs.io/en/latest/docs/walkthrough/phase-3/beyond-low-glucose-suspend.html</string>
<string name="error_only_numeric_digits_allowed">Позволени са само числа</string>
<string name="error_only_numeric_digits_range_allowed" formatted="false">Позволени са числа между %1$s - %2$s</string>
<string name="error_field_must_not_be_empty">Полето не може да бъде празно</string>
@ -676,4 +675,64 @@
<string name="wear_settings">Настройки на часовник</string>
<string name="wearcontrol_summary">Задаване временни цели и въвеждане Лечения от часовник Android wear</string>
<string name="wearcontrol_title">Контролиране от часовник</string>
<string name="closedmodeenabled">Closed Loop е позволен</string>
<string name="combo_activity_reading_pump_history">Чете историята на помпата</string>
<string name="combo_activity_setting_basal_profile">Настройва базалният профил</string>
<string name="combo_error_bolus_recovery_progress">Опитва се да възстанови връзката</string>
<string name="combo_error_bolus_verification_failed">Доставянето на болуса и проверката на историята на помпата са неуспешни, моля, проверете помпата и ако е доставен болус го добавете като запис през Careportal</string>
<string name="customapp">Модифицирано приложение за изтегляне</string>
<string name="danar_setbasalstep001">Задайте стъпка на базала 0.01 Е</string>
<string name="DexcomG5">Dexcom G5 приложение (модифицирано)</string>
<string name="dexcomg5_nsupload_title">Качвай данните за КЗ в NS</string>
<string name="dexcomg5_xdripupload_summary">В xDrip+ изберете 640g/Eversense за източник на данни</string>
<string name="dexcomg5_xdripupload_title">Изпращай данни за КЗ към xDrip+</string>
<string name="enable_missed_bg_readings_alert">Аларма при липса на данни за КЗ</string>
<string name="enable_pump_unreachable_alert">Аларма при недостъпна помпа</string>
<string name="executingrightnow">Командата се изпълнява в момента</string>
<string name="extendedbolusdeliveryerror">Грешка при доставяне на удължен болус</string>
<string name="food">Храна</string>
<string name="hasbgdata">Има данни за КЗ от избрания източник</string>
<string name="info">ИНФО</string>
<string name="localalertsettings_title">Локални аларми</string>
<string name="loopenabled">Loop разрешен</string>
<string name="maxiobset">Максимален IOB е зададен правилно</string>
<string name="minimalbasalvaluereplaced">Базалната стойност е заместена от минимално подържаната</string>
<string name="missed_bg_readings">Липсват данни за КЗ</string>
<string name="negativeonly">Само отрицателни</string>
<string name="no">Не</string>
<string name="none"><![CDATA[<празно>]]></string>
<string name="nsclientbg">КЗ от NS</string>
<string name="nsclienthaswritepermission">NSClient има права за запис</string>
<string name="overview_editquickwizard_usebasaliob">Калкулиране на базален IOB</string>
<string name="overview_editquickwizard_usebg">Калкулиране на КЗ</string>
<string name="overview_editquickwizard_usebolusiob">Калкулиране на Болус IOB</string>
<string name="overview_editquickwizard_usecob">Калкулиране на COB</string>
<string name="overview_editquickwizard_usesuperbolus">Калкулиране суперболус</string>
<string name="overview_editquickwizard_usetemptarget">Калкулиране на временни цели</string>
<string name="overview_editquickwizard_usetrend">Калкулиране на тенденция КЗ</string>
<string name="positiveonly">Само положителни</string>
<string name="processinghistory">Обработва се събитие</string>
<string name="pump_unreachable">Помпата е недостъпна</string>
<string name="pump_unreachable_threshold">Лимит за недостъпна помпа [мин]</string>
<string name="pumpdrivercorrected">Драйверът за помпата е коригиран</string>
<string name="remaininsulinalert">Оставащ инсулин</string>
<string name="startingbolus">Стартира доставка на болус</string>
<string name="unsupportedfirmware">Неподдържан фърмуер на помпата</string>
<string name="urgent_alarm">Спешна аларма</string>
<string name="waitingforestimatedbolusend" formatted="false">Очаква края на болуса. Остават %d сек.</string>
<string name="wear_detailed_delta_summary">Показвай делта с още един десетичен знак</string>
<string name="wear_detailed_delta_title">Показвай подробна делта</string>
<string name="yes">Да</string>
<string name="zerovalueinprofile" formatted="false">Невалиден профил: %s</string>
<string name="shortenergy">En</string>
<string name="raise_notifications_as_android_notifications">Използвай системни известия за аларми и съобщения</string>
<string name="combo_warning">Внимание</string>
<string name="combo_tdd_minimum" formatted="false">Минимум: %3.1f U</string>
<string name="combo_tdd_maximum" formatted="false">Максимум: %3.1f U</string>
<string name="combo_tdd_average" formatted="false">Средно: %3.1f U</string>
<string name="combo_reservoir_normal">Нормално</string>
<string name="combo_reservoir_low">Ниско</string>
<string name="combo_reservoir_level_insufficient_for_bolus">Няма достатъчно инсулин в резервоара</string>
<string name="combo_reservoir_empty">Празен</string>
<string name="combo_refresh">Обнови</string>
</resources>

View file

@ -275,7 +275,7 @@
<string name="objectives_4_objective">Zapnout uzavřenou smyčku, zvyšovat max IOB nad 0 a snižovat cílovou glykémii</string>
<string name="objectives_5_gate">Jeden týden úspěšného používání s běžným příjmem sacharidů</string>
<string name="objectives_5_objective">Upravit bazály a koeficinty, když bude potřeba a povolit automatickou detekci citlivosti na inzulín</string>
<string name="objectives_6_objective">Povolit další fukce pro běžné používání jako AMA</string>
<string name="objectives_6_objective">Povolit další funkce pro běžné používání jako AMA</string>
<string name="youareonallowedlimit">Dosaženo limitu</string>
<string name="bolusdelivering" formatted="false">Aplikováno %.2fU</string>
<string name="smscommunicator_loophasbeendisabled">Smyčka byla zakázána</string>
@ -669,4 +669,113 @@
<string name="ultrafastactinginsulincomment">Fiasp</string>
<string name="ultrarapid_oref">Ultra rychlý - Oref</string>
<string name="waitingforestimatedbolusend" formatted="false">Čekání na konec bolusu. Zbývá %d sek.</string>
<string name="objectives_7_objective">Povolit další funkce pro běžné používání jako SMB</string>
<string name="openapsama_max_daily_safety_multiplier_summary">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í\"</string>
<string name="openapsama_current_basal_safety_multiplier_summary">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.</string>
<string name="openapsama_autosens_max_summary">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%</string>
<string name="openapsama_autosens_min_summary">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%</string>
<string name="openapsama_autosens_adjusttargets_summary">Výchozí hodnota: zapnuto Toto nastavení říká, že autosens může měnit také cílové hodnoty glykémií.</string>
<string name="openapsama_bolussnooze_dia_divisor_summary">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)</string>
<string name="openapsama_min_5m_carbimpact_summary">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</string>
<string name="openapsama_link_to_preferncejson_doc_txt">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.</string>
<string name="openapsama_autosens_period">Interval pro detekci senzitivity [h]</string>
<string name="openapsama_autosens_period_summary">Počet hodin do minulosti pro detekci senzitivity</string>
<string name="food">Jídlo</string>
<string name="shortgramm">g</string>
<string name="none"><![CDATA[<prázdný>]]></string>
<string name="shortkilojoul">kJ</string>
<string name="shortenergy">En</string>
<string name="shortprotein">Pr</string>
<string name="shortfat">Tuk</string>
<string name="executingrightnow">Příkaz je právě prováděn</string>
<string name="pumpdrivercorrected">Ovladač pumpy opraven</string>
<string name="pump_unreachable">Pumpa nedostupná</string>
<string name="missed_bg_readings">Chybějící glykémie</string>
<string name="raise_notifications_as_android_notifications">Používat systémové notifikace pro výstrahy a oznámení</string>
<string name="localalertsettings_title">Místní výstrahy</string>
<string name="enable_missed_bg_readings_alert">Výstraha při nedostupných glykémiích</string>
<string name="enable_pump_unreachable_alert">Výstraha při nedostupné pumpě</string>
<string name="pump_unreachable_threshold">Limit pro nedostupnost pumpy [min]</string>
<string name="urgent_alarm">Urgetní alarm</string>
<string name="info">INFO</string>
<string name="bluetooth">Bluetooth</string>
<string name="btwatchdog_title">Hlídač BT</string>
<string name="btwatchdog_summary">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</string>
<string name="DexcomG5">DexcomG5 aplikace (upravená)</string>
<string name="dexcomg5_nsupload_title">Nahrávat data do NS</string>
<string name="dexcomg5_upload">Nastavení nahrávání z G5</string>
<string name="customapp">Upravená aplikace pro stažení</string>
<string name="wear_detailed_delta_title">Zobrazovat detailní změny</string>
<string name="wear_detailed_delta_summary">Zobrazovat rozdíl s jedním desetinným místem navíc</string>
<string name="unsupportedfirmware">Nepodporovaný firmware v pumpě</string>
<string name="dexcomg5_xdripupload_title">Odesílat data do xDrip+</string>
<string name="dexcomg5_xdripupload_summary">V xDrip+ vyberte zdroj dat 640g/Eversense</string>
<string name="nsclientbg">Glykémie z NS</string>
<string name="minimalbasalvaluereplaced">Hodnota bazálu nahrazena minimální možnou</string>
<string name="overview_editquickwizard_usebg">Kalkulace glykémie</string>
<string name="overview_editquickwizard_usebolusiob">Kalkulace bolusového IOB</string>
<string name="overview_editquickwizard_usebasaliob">Kalkulace bazálního IOB</string>
<string name="overview_editquickwizard_usetrend">Kalkulace trendu</string>
<string name="overview_editquickwizard_usesuperbolus">Kalkulace superbolusu</string>
<string name="yes">Ano</string>
<string name="no">No</string>
<string name="positiveonly">Pouze kladné</string>
<string name="negativeonly">Pouze záporné</string>
<string name="overview_editquickwizard_usecob">Kalkulace COB</string>
<string name="overview_editquickwizard_usetemptarget">Kalkulace s dočasným cílem</string>
<string name="loopenabled">Smyčka povolena</string>
<string name="apsselected">APS vybráno</string>
<string name="nsclienthaswritepermission">NSClient má povolení k zápisu</string>
<string name="closedmodeenabled">Uzavřená smyčka povolena</string>
<string name="maxiobset">Maximální IOB nastaveno správně</string>
<string name="hasbgdata">Glykémie dostupné z vybraného zdroje</string>
<string name="basalprofilenotaligned" formatted="false">Bazální hodnoty nejsou zarovnané na celé hodiny: %s</string>
<string name="zerovalueinprofile" formatted="false">Chybný profil: %s</string>
<string name="combo_programming_bolus">Programování pumpy pro bolus</string>
<string name="combo_refresh">Obnovit</string>
<string name="combo_pump_state_label">Stav</string>
<string name="combo_pump_activity_label">Aktivita</string>
<string name="combo_no_pump_connection" formatted="false">Žádné spojení %d min</string>
<string name="combo_tbr_remaining" formatted="false">%d%% (%d min zbývá)</string>
<string name="combo_pump_action_initializing">Inicializace</string>
<string name="combo_pump_state_disconnected">Odpojeno</string>
<string name="combo_pump_state_suspended_due_to_error">Vypnuto díky chybě</string>
<string name="combo_pump_state_suspended_by_user">Vypnuto uživatelem</string>
<string name="combo_pump_state_running">Beží</string>
<string name="combo_pump_action_cancelling_tbr">Rušení dočasného bazálu</string>
<string name="combo_pump_action_setting_tbr" formatted="false">Nastavování doč. bazálu (%d%% / %d min)</string>
<string name="combo_pump_action_bolusing" formatted="false">Bolus (%.1f U)</string>
<string name="combo_pump_action_refreshing">Obnovování</string>
<string name="combo_pump_never_connected">Nikdy</string>
<string name="combo_pump_unsupported_operation">Požadovaná operace není pumpou podporována</string>
<string name="combo_low_suspend_forced_notification">Nebezpečné použití: extended nebo multiwave bolus je aktivní. Pumpa byla vypnuta jen na 6 hodin. Povolené jsou pouze normální bolusy.</string>
<string name="combo_force_disabled_notification">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.</string>
<string name="bolus_frequency_exceeded">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.</string>
<string name="combo_pump_connected_now">Teď</string>
<string name="combo_activity_reading_pump_history">Načítáni historie pumpy</string>
<string name="combo_pump_alerts">Výstrahy</string>
<string name="combo_activity_setting_basal_profile">Nastavení bazálního profilu</string>
<string name="combo_pump_cartridge_low_warrning">V zásobníku je málo inzulínu</string>
<string name="combo_pump_battery_low_warrning">Slabá baterie v pumpě</string>
<string name="combo_is_in_error_state" formatted="false">Pumpa hlásí chybu E%d: %s</string>
<string name="combo_error_bolus_recovery_progress">Pokouším se obnovit spojení</string>
<string name="combo_error_bolus_verification_failed">Provádění bolusu a čtení historie selhalo. Zkontrolujte pumpu a zadejte bolus přes péči</string>
<string name="combo_error_no_bolus_delivered">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.</string>
<string name="combo_error_partial_bolus_delivered" formatted="false">Pouze %.2f U z bolusu %.2f bylo podáno díky chybě. Zkontrolujte pumpu a proveďte nápravu.</string>
<string name="combo_history">Historie</string>
<string name="combo_pump_tbr_cancelled_warrning">Varování o ukončeném dočasném bazálu bylo potvrzeno.</string>
<string name="combo_warning">Varování</string>
<string name="combo_reservoir_empty">Prázdný</string>
<string name="combo_reservoir_low">Nízký</string>
<string name="combo_reservoir_normal">Normální</string>
<string name="combo_tdd_average" formatted="false">Průměr: %3.1f U</string>
<string name="combo_tdd_maximum" formatted="false">Maximum: %3.1f U</string>
<string name="combo_tdd_minimum" formatted="false">Minimum: %3.1f U</string>
<string name="combo_no_alert_data_note">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.</string>
<string name="combo_notification_check_time_date">Je vyžadována aktualizace času na pumpě</string>
<string name="combo_no_tdd_data_note">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.</string>
<string name="combo_read_full_history_warning">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.</string>
<string name="combo_read_full_history_confirmation">Opravdu chcete přečíst historii z pumpy a nést důsledky z toho vyplývající?</string>
<string name="combo_reservoir_level_insufficient_for_bolus">Nedostatek inzulínu pro takovýto bolus</string>
<string name="extendedbolusdeliveryerror">Chyba spuštění extended bolusu</string>
</resources>

View file

@ -710,9 +710,6 @@
<string name="combo_pump_activity_label">Aktivität</string>
<string name="combo_tbr_remaining">%d%% (%d Min. verbleibend)</string>
<string name="combo_no_pump_connection">Keine Verbindung zur Pumpe seit %d Min.</string>
<string name="bolusstopped">Bolusabgabe gestoppt</string>
<string name="bolusstopping">Bolusabgabe wird abgebrochen</string>
<string name="pump_errors_history">Fehlerprotokol</string>
<string name="combo_pump_state_label">Status</string>
<string name="combo_pump_state_disconnected">Keine Verbindung zur Pumpe</string>
<string name="combo_pump_state_suspended_by_user">Gestoppt (Benutzer)</string>
@ -726,7 +723,7 @@
<string name="alert_dialog_storage_permission_text">Bitte starte dein Telefon neu oder starte AndroidAPS in den System-Einstellungen neu. Andernfalls wird AndroidAPS nicht protokolliert (wichtig zum Nachverfolgen und Verifizieren, dass der Algorithmus korrekt funktioniert)</string>
<string name="pump_tempbasal_label">TBR</string>
<string name="combo_last_bolus">%.1f %s (%s)</string>
<string name="bolus_frequency_exceeded">Ein gleich großer Bolus wurde in der letzten Minute angefordert. Dies ist nicht zulässig, um ungewollte Doppelboli zu verhindern und vor eventuellen Bugs zu schützen.</string>
<string name="bolus_frequency_exceeded">Ein gleich großer Bolus wurde in den letzten zwei Minuten angefordert. Dies ist nicht zulässig, um ungewollte Doppelboli zu verhindern und vor eventuellen Bugs zu schützen.</string>
<string name="combo_activity_reading_pump_history">Historie wird gelesen</string>
<string name="combo_activity_setting_basal_profile">Basalratenprofil wird aktualisiert</string>
<string name="combo_error_bolus_recovery_progress">Verbindung wird wieder hergestellt</string>
@ -753,7 +750,7 @@
<string name="combo_is_in_error_state">Die Pumpe zeigt einen Fehler an E%d: %s</string>
<string name="combo_force_disabled_notification">Unsichere Verwendung: In der Pumpe ist nicht das erste Basalratenprofil gewählt. Der Loop wird deaktiviert bis dies korrigiert ist.</string>
<string name="combo_low_suspend_forced_notification">Unsichere Verwendung: Ein erweiterter oder Multiwave-Bolus ist aktiv. Der Loop wird für die nächsten 6 Stunden kein zusätzliches Insulin abgeben.</string>
<string name="combo_no_alert_data_note">Um die Fehlerhistorie der Pumpe zu lesen, drücke lange auf ALARME.\nWARNUNG: Es gibt einen bekannten Fehler in der Pumpe, der dazu führt, dass die Pumpe nach dieser Aktion erst wieder Verbindungen annimmt, wenn auf der Pumpe selbst eine Taste gedrückt wird. Aus diesem Grund sollte diese Aktion nicht durchgeführt werden.</string>
<string name="combo_no_alert_data_note">Um die Fehlerhistorie der Pumpe zu lesen, drücke lange auf ALARME.</string>
<string name="combo_notification_check_time_date">Bitte aktualisiere die Uhrzeit der Pumpe</string>
<string name="combo_no_tdd_data_note">Um die TDD-Statistik der Pumpe zu lesen, drücken Sie den TDDS Knopf lange.\nWARNUNG: Es gibt einen bekannten Fehler in der Pumpe der dazu führt, dass die Pumpe nach dieser Aktion erst wieder Verbindungen annimmt, wenn auf der Pumpe selbst ein Konpf gedrückt wird. Aus diesem Grund sollte diese Aktion nicht durchgeführt werden.</string>
<string name="combo_read_full_history_warning">Dies wird den gesamten Speicher und den Status der Pumpe auslesen sowie alle Einträge in „Meine Daten“ und die Basalrate. Boli und TBR werden unter Behandlungen gespeichert, sofern sie nicht bereits vorhanden sind. Dies kann zu doppelten Einträgen führen, wenn die Uhrzeit der Pumpe abweicht. Das Auslesen des Speichers ist normaler Weise für das Loopen unnötig und nur für besondere Umstände vorgesehen. Wenn Du es dennoch tun willst, drücke noch einmal länger den Button. ACHTUNG: Dies kann einen Fehler auslösen, der dazu führt, dass die Pumpe keine Verbindungsversuche mehr akzeptiert. Erst die Betätigung einer Taste an der Pumpe beendet diesen Zustand. Nach Möglichkeit sollte daher das Auslesen vermieden werden.</string>

View file

@ -295,7 +295,7 @@
<string name="correctionbous">Corr</string>
<string name="disabledloop">Loop Inactivo</string>
<string name="mealbolus">Bolo Comida</string>
<string name="openapsma_valueoutofrange">Valor %s fuera de limites</string>
<string name="openapsma_valueoutofrange" formatted="false">Valor %s fuera de limites</string>
<string name="overview_editquickwizard_buttontext">Botón Texto:</string>
<string name="overview_editquickwizard_carbs">Carbs:</string>
<string name="overview_editquickwizard_valid">Validar:</string>
@ -313,7 +313,7 @@
<string name="smscommunicator_tempbasalfailed">Fallo inicio basal temporal</string>
<string formatted="false" name="smscommunicator_tempbasalset">Basal temporal %.2fU/h para %d min iniciada correctamente</string>
<string name="smscommunicator_remotecommandsallowed">Permitir comandos SMS remotos</string>
<string name="smscommunicator_basalstopreplywithcode">Para parar basal temporal responder con codigo %s</string>
<string name="smscommunicator_basalstopreplywithcode" formatted="false">Para parar basal temporal responder con codigo %s</string>
<string name="androidaps_start">AndroidAPS iniciado</string>
<string name="es_lang">Español</string>
<string name="ns_upload_only">NS solo subida (sinc. inactiva)</string>
@ -325,27 +325,25 @@
<string name="smscommunicator_unknowncommand">Comando desconocido o respuesta incorrecta</string>
<string name="fillwarning">¡Por favor asegurar que la cantidad coincide con la especificación del set de infusión!</string>
<string formatted="false" name="smscommunicator_basalreplywithcode">Para iniciar basal %.2fU/h responder con código %s</string>
<string name="actions_shortname">" "</string>
<string name="wear_shortname">" "</string>
<string name="virtualpump_shortname">" "</string>
<string name="treatments_shortname">" "</string>
<string name="temptargetrange_shortname">" "</string>
<string name="tempbasals_shortname">" "</string>
<string name="smscommunicator_shortname">" "</string>
<string name="simpleprofile_shortname">" "</string>
<string name="profileviewer_shortname">" "</string>
<string name="overview_shortname">" "</string>
<string name="objectives_shortname">" "</string>
<string name="oaps_shortname">" "</string>
<string name="loop_shortname">" "</string>
<string name="localprofile_shortname">" "</string>
<string name="danarpump_shortname">" "</string>
<string name="configbuilder_shortname">" "</string>
<string name="circadian_percentage_profile_shortname">" "</string>
<string name="careportal_shortname">" "</string>
<string name="actions_shortname">"acciones"</string>
<string name="virtualpump_shortname">"bomba virtual"</string>
<string name="treatments_shortname">"tratamientos"</string>
<string name="temptargetrange_shortname">" objectivos temporales"</string>
<string name="tempbasals_shortname">"objtemp"</string>
<string name="smscommunicator_shortname">"comunicacíon sms"</string>
<string name="simpleprofile_shortname">"Profil simple"</string>
<string name="profileviewer_shortname">"Profiles"</string>
<string name="overview_shortname">"General"</string>
<string name="objectives_shortname">"Objectivos"</string>
<string name="oaps_shortname">"OAPS"</string>
<string name="loop_shortname">"LOOP"</string>
<string name="localprofile_shortname">"LP"</string>
<string name="danarpump_shortname">DANA</string>
<string name="configbuilder_shortname">"conf"</string>
<string name="careportal_shortname">CP</string>
<string name="activity">Actividad</string>
<string name="alert_dialog_storage_permission_text">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)</string>
<string name="array_of_elements">Matriz de %d elementos. Valor actual:</string>
<string name="alert_dialog_storage_permission_text">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)</string>
<string name="array_of_elements" formatted="false">Matriz de %d elementos. Valor actual:</string>
<string name="basal_rate">Ratio Basal:</string>
<string name="basalvaluebelowminimum">Valor basal menor del mínimo. Perfil no fijado.</string>
<string name="base_profile_label">Perfil Base</string>
@ -362,7 +360,7 @@
<string name="long_avgdelta">Media Larga Delta</string>
<string name="low_mark">Marca BAJO</string>
<string name="lowbattery">Batería Baja</string>
<string name="minago">%dmin antes</string>
<string name="minago" formatted="false">%dmin antes</string>
<string name="openapsama_useautosens">Usar característica AMA autosens</string>
<string name="openapsma_autosensdata_label">Datos Autosens</string>
<string name="percentagefactor_hint">Factor porcentual para multiplicar el perfil base</string>
@ -378,15 +376,430 @@
<string name="short_avgdelta">Media corta delta</string>
<string name="sms_bolus">Bolo:</string>
<string name="sms_lastbg">Último BG:</string>
<string name="sms_minago">%dmin antes</string>
<string name="sms_minago" formatted="false">%dmin antes</string>
<string name="smscommunicator_bolusdelivered">Bolo %.2fU enviado correctamente</string>
<string name="target_range">Rango Objetivo:</string>
<string name="units">Unidades:</string>
<string name="error_only_numeric_digits_allowed">Sólo se permiten caracteres numéricos</string>
<string name="error_only_numeric_digits_range_allowed">Sólo se permiten dígitos en el rango %1$s - %2$s</string>
<string name="error_only_numeric_digits_range_allowed" formatted="false">Sólo se permiten dígitos en el rango %1$s - %2$s</string>
<string name="error_field_must_not_be_empty">Este campo no puede estar vacío</string>
<string name="error_phone_not_valid">Número de teléfono inválido</string>
<string name="waitingforpump">Esperando bomba</string>
<string name="it_lang">Italian</string>
<string name="app_name">AndroidAPS</string>
<string name="nl_lang">hollandes</string>
<string name="el_lang">Griego</string>
<string name="ru_lang">Ruso</string>
<string name="sv_lang">Sueco</string>
<string name="openapsma_maxbasal_title">Max U/h para el perfil base</string>
<string name="openapsma_maxiob_title">"Max IOB basal OpenAPs puede emitir "</string>
<string name="smscommunicator_calibrationreplywithcode" formatted="false">Para enviar calibracion %.2f responder con codigo %s</string>
<string name="bolusrequested" formatted="false">Entregaré %.2fU</string>
<string name="danarprofile_dia_summary">Duración de acitividad de insulina</string>
<string name="pump_errors_history">Errores</string>
<string name="objectives_7_objective">habilitar funciones adicionales para uso durante el día como SMB</string>
<string name="openapsma_valuelimitedto" formatted="false">%.2f limitado a %.\"f</string>
<string name="smscommunicator_remotecommandnotallowed">no permitido el mando remoto</string>
<string name="smscommunicator_suspendreplywithcode" formatted="false">Para cancelar loop por %d minutos responde con codigo %s</string>
<string name="primefill">Rellenar/Llenar</string>
<string name="fillbolus_title">Llenar/Rellenar cantidad de insulina estándar</string>
<string name="timeshift_hint">Tiempo en horas en el que el perfil será movido</string>
<string name="mgdl">mg/dl</string>
<string name="mmol">mmol/l</string>
<string name="dia">DIA:</string>
<string name="edit_base_basal">Editar Base-Basal:</string>
<string name="edit_base_isf">Edidat Base-ISF:</string>
<string name="edit_base_ic">Editar Base-IC:</string>
<string name="circadian_percentage_profile">CircadianPercentageProfile</string>
<string name="wear">Reloj</string>
<string name="open_settings_on_wear">Abrir ajustes en reloj</string>
<string name="batterydischarged">Batería de la bomba descargada</string>
<string name="danarkoreanpump">DanaR Korean</string>
<string name="sms_actualbg">BG:</string>
<string name="mdi">MDI</string>
<string name="MM640g">MM640g</string>
<string name="ongoingnotificaction">Avisos permanentes</string>
<string name="old_data">DATOS CADUCADOS</string>
<string name="openapsama">OpenAPS AMA</string>
<string name="openapsma_scriptdebugdata_label">Script debug</string>
<string name="refresheventsfromnightscout">Renovar datos desde NS</string>
<string name="danar_stats">DanaR Stats</string>
<string name="danar_stats_cumulative_tdd">Dosis diaria cumulativa</string>
<string name="danar_stats_expweight">"Dosis diaria ampliada exponencialmente "</string>
<string name="danar_stats_basalrate">Base</string>
<string name="danar_stats_bolus">Bolo</string>
<string name="danar_stats_tdd">Dosis diaria</string>
<string name="danar_stats_date">Fecha</string>
<string name="danar_stats_ratio">Cuota</string>
<string name="danar_stats_amount_days"># Días</string>
<string name="danar_stats_weight">Peso</string>
<string name="danar_stats_warning_Message">Probablemente impreciso usando bolo para llenar/rellenar!</string>
<string name="danar_stats_olddata_Message">Datos caducados pro favor pincha RELOAD</string>
<string name="danar_stats_tbb">Basal total</string>
<string name="danar_stats_tbb2">Basal diaria *2</string>
<string name="circadian_percentage_profile_shortname">CPP</string>
<string name="wear_shortname">Reloj</string>
<string name="short_tabtitles">Tab titulo corto</string>
<string name="prefs_delta_title">Ajustes Delta</string>
<string name="always_use_shortavg">Usa siempre delta media corto en vez de delta simple</string>
<string name="always_use_shortavg_summary">Recomendado si los datos de origen no filtrados como xDrip son inestables.</string>
<string name="advancedsettings_title">Ajustes avancados</string>
<string name="danar_model" formatted="false">Modelo: %02X Protocolo: %02X Codigo: %02X</string>
<string name="profile">Perfiles</string>
<string name="openapsama_max_daily_safety_multiplier" translatable="false">max_daily_safety_multiplier</string>
<string name="openapsama_max_daily_safety_multiplier_summary">"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. "</string>
<string name="openapsama_current_basal_safety_multiplier" translatable="false">current_basal_safety_multiplier</string>
<string name="openapsama_current_basal_safety_multiplier_summary">"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. "</string>
<string name="openapsama_autosens_max" translatable="false">autosens_max</string>
<string name="openapsama_autosens_max_summary">"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. "</string>
<string name="openapsama_autosens_min" translatable="false">autosens_min</string>
<string name="openapsama_autosens_min_summary">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.</string>
<string name="openapsama_autosens_adjusttargets" translatable="false">autosens_adjust_targets</string>
<string name="openapsama_autosens_adjusttargets_summary">Ajuste pro defcto: true\nEsto se usa para permitir autosens a ajustar objectivos BG en addicion a ISF y bases.</string>
<string name="openapsama_bolussnooze_dia_divisor" translatable="false">bolussnooze_dia_divisor</string>
<string name="openapsama_bolussnooze_dia_divisor_summary">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).</string>
<string name="openapsama_min_5m_carbimpact" translatable="false">5_min_carb_impact</string>
<string name="openapsama_min_5m_carbimpact_summary">"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. "</string>
<string name="openapsama_link_to_preferncejson_doc_txt">"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. "</string>
<string name="openapsama_link_to_preferncejson_doc">http://openaps.readthedocs.io/en/latest/docs/walkthrough/phase-3/beyond-low-glucose-suspend.html</string>
<string name="smscommunicator_invalidphonennumber">numero de telefonp incorrecto</string>
<string name="copy_to_clipboard">Copiar al Clipboard</string>
<string name="copied_to_clipboard">Copiado al clipboard</string>
<string name="nav_show_logcat">mostrar log</string>
<string name="overview_calibration">Calibracion</string>
<string name="overview_calibration_bg_label">Calibracion</string>
<string name="send_calibration" formatted="false">Mandar calibracion %.lf a xDrip?</string>
<string name="xdripnotinstalled">xDrip+ no instalado</string>
<string name="calibrationsent">Calibracion mandada a xDrip</string>
<string name="smscommunicator_remotecalibrationnotallowed">Calibracion remota no admitida</string>
<string name="smscommunicator_calibrationsent">Mandar calibracion tiene que ser activada en xDrip.</string>
<string name="smscommunicator_calibrationfailed">xDrip no recibe calibraciones</string>
<string name="dont_show_again">no mostrar otra vez</string>
<string name="pumpsuspendedclicktorefresh">Bomba parada. Pincha para aktualizar</string>
<string name="pumpsuspended">bomba parada</string>
<string name="gettingpumpstatus">recibir estado de bomba</string>
<string name="settingtempbasal">iniciando base temporal</string>
<string name="stoppingtempbasal">parando base temporal</string>
<string name="settingextendedbolus">iniciando bolo prolongado</string>
<string name="stoppingextendedbolus">parando bolo prolongado</string>
<string name="updatingbasalrates">actualizando cuota base</string>
<string name="disconnecting">Desconectando</string>
<string name="executing">Efectuando</string>
<string name="virtualpump_settings">Ajustes bomba virtual</string>
<string name="virtualpump_uploadstatus_title">Subiendo estado a NS</string>
<string name="wrongpassword">Contrasena invalida</string>
<string name="settings_password">Contrasena para ajustes</string>
<string name="unlock_settings">desbloquear ajustes</string>
<string name="approachingdailylimit">llegando al limite de insulina diario</string>
<string name="nsclientinternal">NSClient</string>
<string name="nsclientinternal_shortname">NSCI</string>
<string name="nsclientinternal_url">URL:</string>
<string name="nsclientinternal_autoscroll">Autoscroll</string>
<string name="restart">Reiniciar</string>
<string name="nsclientinternal_title">NSClient</string>
<string name="nsclientinternal_url_title">Nightscout URL</string>
<string name="nsclientinternal_url_dialogmessage">Indica Nightscout URL</string>
<string name="nsclientinternal_secret_title">NS API secret</string>
<string name="nsclientinternal_secret_dialogtitle">NS API secret</string>
<string name="nsclientinternal_secret_dialogmessage">Indica NS API secret (min 12 chars)</string>
<string name="nsclientinternal_devicename_title">Nombre aparato</string>
<string name="nsclientinternal_devicename_dialogtitle">Indica nombre aparato</string>
<string name="nsclientinternal_devicename_dialogmessage">Se usara para enteredBy field</string>
<string name="deliver_now">entregar ahora</string>
<string name="clear_queue">borrar cola</string>
<string name="show_queue">mostrar cola</string>
<string name="queue">Cola:</string>
<string name="status">Estado:</string>
<string name="paused">Pausado</string>
<string name="clearlog">Borrar log</string>
<string name="nowritepermission">NSCLIENT no tiene derecho para editar. API secret incorrecto?</string>
<string name="wear_settings">Ajustes reloj</string>
<string name="wear_detailedIOB_title">mostrar detalles IOB</string>
<string name="wear_detailedIOB_summary">Separar IOB en bolo y base en el reloj</string>
<string name="nosuccess">sin efecto - por favor controlar en móvil</string>
<string name="notavailable">no disponible</string>
<string name="patientage">Edad paciente</string>
<string name="child">Menor de edad</string>
<string name="teenage">Adolescente</string>
<string name="adult">Adulto</string>
<string name="patientage_summary">Por favor elige edad del paciente para emplear limites de seguridad</string>
<string name="Glimp">Glimp</string>
<string name="batteryoptimalizationerror">Aparato parece no soportar optimisacion de bateria whitelisting!</string>
<string name="pleaseallowpermission">Por favor permita Permission</string>
<string name="needwhitelisting" formatted="false">%s necesita optimisacion de bateria whitelisting para funcionar bien</string>
<string name="loopsuspended">Loop desactivado</string>
<string name="loopsuspendedfor" formatted="false">desactivado (%d m)</string>
<string name="loopsuperbolusfor" formatted="false">Superbolus (%d m)</string>
<string name="loopmenu">Loop menu</string>
<string name="suspendloopfor1h">Desactivar loop por 1h</string>
<string name="suspendloopfor2h">Desactivar loop por 2h</string>
<string name="suspendloopfor3h">Desactivar loop por 3h</string>
<string name="suspendloopfor10h">Desactivar loop por 10 h</string>
<string name="disconnectpumpfor30m">Desconectar bomba por 30 min</string>
<string name="disconnectpumpfor1h">Desconectar bomba por 1 h</string>
<string name="disconnectpumpfor2h">Desconectar bomba por 2 h</string>
<string name="disconnectpumpfor3h">Desconectar bomba por 3 h</string>
<string name="disconnectpumpfor10h">Desconectar bomba por 10 h</string>
<string name="resume">Reiniciar</string>
<string name="smscommunicator_wrongduration">duracion incorrecta</string>
<string name="smscommunicator_loopsuspended">Loop desactivado</string>
<string name="smscommunicator_loopresumed">Loop reiniciado</string>
<string name="treatments_wizard_bgtrend_label">Tendencia 15 min</string>
<string name="treatments_wizard_cob_label">COB</string>
<string name="superbolus">Superbolo</string>
<string name="ns_logappstartedevent">Indica app start en NS</string>
<string name="restartingapp">Aplicacion existente para aplicar ajustes.</string>
<string name="danarv2pump">DanaRv2</string>
<string name="configbuilder_insulin">Insulina</string>
<string name="fastactinginsulin">Insulina acción rápida</string>
<string name="fastactinginsulincomment">Novorapid, Novolog, Humalog</string>
<string name="ultrafastactinginsulincomment">Fiasp</string>
<string name="insulin_shortname">INS</string>
<string name="fastactinginsulinprolonged">Insulina acción rápida prolongada</string>
<string name="enablesuperbolus">activar superbolo en wizard</string>
<string name="enablesuperbolus_summary">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!</string>
<string name="iob">IOB</string>
<string name="cob">COB</string>
<string name="predictionshortlabel">PRE</string>
<string name="basalshortlabel">BAS</string>
<string name="virtualpump_firmware_label">Firmware</string>
<string name="danar_bluetooth_status">Estado de bluetooth</string>
<string name="nav_about">Sobre</string>
<string name="smscommunicator_missingsmspermission">"Falta permitir SMS "</string>
<string name="dev">DEV</string>
<string name="xdripstatus_settings">xDrip Status (reloj)</string>
<string name="xdripstatus">xDrip Statusline (reloj)</string>
<string name="xdripstatus_shortname">xds</string>
<string name="wear_showbgi_title">Mostrar BGI</string>
<string name="wear_showbgi_summary">agregar BGI a status line</string>
<string name="ns_noupload">No upload to NS</string>
<string name="ns_noupload_summary">Todos los datos mandados a NS son borrados. AAPS esta conectado to NS pero no hay cambios en NS</string>
<string name="basal_step">Nivel base</string>
<string name="bolus_step">Nivel bolo</string>
<string name="extendedbolus">Bolo prolongado</string>
<string name="temptarget">"Objectivo temporal "</string>
<string name="overview_extendedbolus_cancel_button">cancelar bolo prolongado</string>
<string name="careportal_sensorage_label">Edad sensor</string>
<string name="careportal_canulaage_label">Edad cánula</string>
<string name="careportal_insulinage_label">Edad insulina</string>
<string name="hours">horas</string>
<string name="overview_newtempbasal_basaltype_label">Tipo base</string>
<string name="isfmissing">Falta ISF en perfil. Usando ajuste por defecto.</string>
<string name="icmissing">Falta IC en perfil. Usando ajuste por defecto.</string>
<string name="basalmissing">Falta base en perfil. Usando ajuste por defecto.</string>
<string name="targetmissing">"Falta objectivo en perfil. Usando ajuste por defecto. "</string>
<string name="invalidprofile">Perfil invalido !!!</string>
<string name="profileswitch">CambioPerfil</string>
<string name="careportal_pbage_label">Edad bateria bomba</string>
<string name="careportal_pumpbatterychange">Cambio bateria bomba</string>
<string name="ns_alarmoptions">Opciones alama</string>
<string name="nsalarm_urgenthigh">Urgente alto</string>
<string name="nsalarm_high">Alto</string>
<string name="nsalarm_low">Bajo</string>
<string name="nsalarm_urgentlow">Urgente bajo</string>
<string name="nsalarm_summary" formatted="false">Actualmente puesto a %f</string>
<string name="nsalarm_staledata">Stale data</string>
<string name="nsalarm_urgentstaledata">Urgent stale data</string>
<string name="nsalarm_staledatavalue_label">Stale data threshold [min]</string>
<string name="nsalarm_urgent_staledatavalue_label">Urgent stale data threshold [min]</string>
<string name="openapsama_autosens_period">Interval para autosens [h]</string>
<string name="openapsama_autosens_period_summary">Horas en el pasado para detectar sensividad (tiempo de absorcion de carbohidratos no incluidos)</string>
<string name="ratio_short">SEN</string>
<string name="do_not_track_profile_switch">"Ignora evenos de cambio de perfil "</string>
<string name="do_not_track_profile_switch_summary">"Totos los cambios de perfil son ignorados y se usa siempre el perfil actual "</string>
<string name="pump">Bomba</string>
<string name="openaps">OpenAPS</string>
<string name="device">Aparato</string>
<string name="uploader">Uploader</string>
<string name="configbuilder_sensitivity">Deteccion sensividad</string>
<string name="sensitivity_shortname">SENS</string>
<string name="sensitivityoref0">Sensitivity Oref0</string>
<string name="sensitivityaaps">Sensitivity AAPS</string>
<string name="absorptionsettings_title">Ajustes absorcion</string>
<string name="absorption_maxtime_title">Tiempo max absorcion comida [h]</string>
<string name="absorption_maxtime_summary">Tiempo esperado en el que todos los carbohidratos son absorbados</string>
<string name="danar_visualizeextendedaspercentage_title" formatted="false">mostrar bolo prolongado en %</string>
<string name="careportal_sensorage_label_short">SAGE</string>
<string name="careportal_insulinage_label_short">IAGE</string>
<string name="careportal_canulaage_label_short">CAGE</string>
<string name="careportal_pbage_label_short">PBAGE</string>
<string name="openaps_short">OAPS</string>
<string name="uploader_short">UPLD</string>
<string name="basal_short">BAS</string>
<string name="virtualpump_extendedbolus_label_short">EXT</string>
<string name="lock_screen">Pantalle proteccion</string>
<string name="lock_screen_short">Cierre</string>
<string name="sensitivity_warning">Al activar autosens recuerda editar todos carbohidratos comidos. Si no, sensividad será calculada incorrectamente !!!</string>
<string name="sensitivityweightedaverage">Sensitivity WeightedAverage</string>
<string name="mdtp_ok">OK</string>
<string name="mdtp_cancel">Cancelar</string>
<string name="cpp_sync_setting_missing">necesita ser activado para mandar valores a la bomba!</string>
<string name="cpp_notloadedplugins">Faltan perfiles!</string>
<string name="cpp_valuesnotstored">Valores no guardados!</string>
<string name="wear_overviewnotifications">Resumen avisos</string>
<string name="wear_overviewnotifications_summary">Mandar resumen de avisos como avisos de confirmacion por reloj.</string>
<string name="combopump" translatable="false">Accu-Chek Combo</string>
<string name="combopump_shortname" translatable="false">COMBO</string>
<string name="ns_localbroadcasts">Activar mensajes a otras aplicaciones (como xDrip).</string>
<string name="ns_localbroadcasts_title">Activar mensajes locales.</string>
<string name="careportal_activity_label">ACTIVITY Y FEEDBACK</string>
<string name="careportal_carbsandbolus_label">CARBS Y BOLUS</string>
<string name="careportal_cgm_label">CGM Y OPENAPS</string>
<string name="careportal_pump_label">PUMP</string>
<string name="overview_newtempbasal_basalabsolute">Valor base [U/h]</string>
<string name="careportal_newnstreatment_duration_min_label">Duracion [min]</string>
<string name="insulin_oref_peak">IOB Curve Peak Time</string>
<string name="insulin_peak_time">Peak Time [min]</string>
<string name="free_peak_oref">Free-Peak Oref</string>
<string name="rapid_acting_oref">Rapid-Acting Oref</string>
<string name="ultrarapid_oref">Ultra-Rapid Oref</string>
<string name="dia_too_short" formatted="false">DIA de %s demasiado corto - usando %s!</string>
<string name="activate_profile">ACTIVAR PERFIL</string>
<string name="date">Fecha</string>
<string name="invalid">INVALIDO</string>
<string name="waitingforpairing">Esperando para conectar con bomba</string>
<string name="pairingok">Coneccion OK</string>
<string name="pairingtimedout">Coneccion fuera de tiempo</string>
<string name="pairing">CONECTANDO</string>
<string name="danars_nodeviceavailable">aparato no enconrado</string>
<string name="emptyreservoir">Deposito vacio</string>
<string name="bloodsugarmeasurementalert">Alerta de control de BG</string>
<string name="remaininsulinalert">Insulina restante en deposito</string>
<string name="danarspump">DanaRS</string>
<string name="danarspump_shortname">Dana</string>
<string name="selectedpump">Bomba sleccionada</string>
<string name="pairpump">Conectar bomba nueva</string>
<string name="bolusspeed">Velocidad bolo</string>
<string name="danar_setbasalstep001">Poner paso base a 0.01 U/h</string>
<string name="serialnumber">Numero de serie</string>
<string name="careportal_newnstreatment_percentage_label">Porcientos</string>
<string name="careportal_newnstreatment_timeshift_label">Cambio de tiepmo</string>
<string name="default_temptargets">Ojbectivo temporal por defecto</string>
<string name="eatingsoon_duration">duracion comiendopronto</string>
<string name="eatingsoon_target">objectivo comiendopronto</string>
<string name="activity_duration">duracion actividad</string>
<string name="activity_target">objectivo actividad</string>
<string name="danar_history_prime">Prime</string>
<string name="gettingextendedbolusstatus">recibiendo estado de bolo prolongado</string>
<string name="gettingbolusstatus">recibiendo estado bolo</string>
<string name="gettingtempbasalstatus">recibiendo estado bolo temporal</string>
<string name="gettingpumpsettings">recibiendo ah´justes bomba</string>
<string name="gettingpumptime">recibiendo hora bomba</string>
<string name="reuse">usar otra vez</string>
<string name="wearcontrol_title">Control desde reloj</string>
<string name="wearcontrol_summary">editar y emitir abjectivos temp. y tratamientos por reloj</string>
<string name="connectiontimedout">Fuera tiempo coneccion</string>
<string name="food">comida</string>
<string name="shortgramm">g</string>
<string name="none"><![CDATA[<none>]]></string>
<string name="shortkilojoul">kJ</string>
<string name="shortenergy">En</string>
<string name="shortprotein">Pr</string>
<string name="shortfat">Grasa</string>
<string name="active"><![CDATA[<Active>]]></string>
<string name="waitingforestimatedbolusend" formatted="false">Esperande terminar bolo. Faltan %d seg.</string>
<string name="processinghistory">Processando</string>
<string name="startingbolus">"Iniciando emisioin bolo "</string>
<string name="executingrightnow">Orden se esta efectuando en este momento</string>
<string name="pumpdrivercorrected">control de la bomba corigido</string>
<string name="pump_unreachable">bomba no alcanzable</string>
<string name="missed_bg_readings">"Falta lectura BG "</string>
<string name="raise_notifications_as_android_notifications">Usa avisos del sistema para alarmas y avisos</string>
<string name="localalertsettings_title">Alarma local</string>
<string name="enable_missed_bg_readings_alert">Alarma si no llegan datos BG</string>
<string name="enable_pump_unreachable_alert">Alarma si bomba no es alcanzable</string>
<string name="urgent_alarm">Alarma urgente</string>
<string name="info">INFO</string>
<string name="bluetooth">Bluetooth</string>
<string name="btwatchdog_title">BT Watchdog</string>
<string name="btwatchdog_summary">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.</string>
<string name="DexcomG5">DexcomG5 App (patched)</string>
<string name="dexcomg5_nsupload_title">Envias datos BG a NS</string>
<string name="dexcomg5_upload">G5 upload ajustes</string>
<string name="customapp">APK adaptada para bajar</string>
<string name="wear_detailed_delta_title">"mostrar detalles delta "</string>
<string name="wear_detailed_delta_summary">mostrar delta con una plaza decimal mas</string>
<string name="unsupportedfirmware">firmware de la bomba no apoyada</string>
<string name="dexcomg5_xdripupload_title">mandar BG a xDrip</string>
<string name="dexcomg5_xdripupload_summary">En xDrip elige 640g/Eversense date source</string>
<string name="nsclientbg">NSClient BG</string>
<string name="minimalbasalvaluereplaced">Valor base remplazado por valor mínimo</string>
<string name="overview_editquickwizard_usebg">Calculacion BG</string>
<string name="overview_editquickwizard_usebolusiob">Calculacion bolo IOB</string>
<string name="overview_editquickwizard_usebasaliob">Calculacion base IOB</string>
<string name="overview_editquickwizard_usetrend">Calculacion tendencia</string>
<string name="overview_editquickwizard_usesuperbolus">Calculacion superbolo</string>
<string name="yes">Si</string>
<string name="no">No</string>
<string name="positiveonly">Solo positivo</string>
<string name="negativeonly">Solo negativo</string>
<string name="overview_editquickwizard_usecob">Calculacion COB</string>
<string name="overview_editquickwizard_usetemptarget">Calculacion objectivo temporal</string>
<string name="loopenabled">Loop activado</string>
<string name="apsselected">APS seleccionado</string>
<string name="nsclienthaswritepermission">NSClient tiene permission de escribir</string>
<string name="closedmodeenabled">Modo cerrado activado</string>
<string name="maxiobset">Máximo IOB puesto correctamente</string>
<string name="hasbgdata">BG adquirible del origen seleccionado</string>
<string name="basalprofilenotaligned" formatted="false">Valores base no asignados a las horas: %s</string>
<string name="zerovalueinprofile" formatted="false">Perfil invalido: %s</string>
<string name="combo_programming_bolus">Programando bomba para emitir bolo</string>
<string name="combo_refresh">Actualizar</string>
<string name="combo_tdds">TDDS</string>
<string name="combo_pump_state_label">Estado</string>
<string name="combo_pump_activity_label">Actividad</string>
<string name="combo_no_pump_connection" formatted="false">Ninguna coneccnion por %d min</string>
<string name="combo_tbr_remaining" formatted="false">%d%% (%d min restan)</string>
<string name="combo_last_bolus" formatted="false">%.1f U (%s, %s)</string>
<string name="combo_pump_action_initializing">Iniciando</string>
<string name="combo_pump_state_disconnected">Desconectado</string>
<string name="combo_pump_state_suspended_due_to_error">Apagado por error</string>
<string name="combo_pump_state_suspended_by_user">Apagado por usario</string>
<string name="combo_pump_state_running">Funcionando</string>
<string name="combo_pump_action_cancelling_tbr">Cancelando TBR</string>
<string name="combo_pump_action_setting_tbr" formatted="false">Poniendo TBR (%d%% / %d min)</string>
<string name="combo_pump_action_bolusing" formatted="false">Emitiendo bolo (%.1f U)</string>
<string name="combo_pump_action_refreshing">Actualizando</string>
<string name="combo_pump_never_connected">Nunca</string>
<string name="combo_pump_unsupported_operation">"Acción no disponible en la bomba "</string>
<string name="combo_low_suspend_forced_notification">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.</string>
<string name="combo_force_disabled_notification">"Uso inseguro: la bomba usa base diferente a la primera. El loop ha sido apagado. Elige primero perfil en la bomba y acualiza. "</string>
<string name="bolus_frequency_exceeded">Un bolo de mismo valor ha sido dado durante el pasado minuto. Para evitar bolos dobles y asegurarse contra bugs esto no es permitido.</string>
<string name="combo_pump_connected_now">Ahora</string>
<string name="combo_activity_reading_pump_history">Leiendo historia bomba</string>
<string name="combo_pump_alerts">Alarmas</string>
<string name="combo_activity_setting_basal_profile">" Activando perfil base "</string>
<string name="combo_pump_cartridge_low_warrning">"Nivel del deposito bajo "</string>
<string name="combo_pump_battery_low_warrning">Bateria casi agotada</string>
<string name="combo_is_in_error_state" formatted="false">La bomba muesta el error E%d: %s</string>
<string name="combo_no_alert_data_note">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.</string>
<string name="combo_no_tdd_data_note">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.</string>
<string name="combo_tdd_minimum" formatted="false">Mínimo: %3.1f U</string>
<string name="combo_tdd_average" formatted="false">Media: %3.1f U</string>
<string name="combo_tdd_maximum" formatted="false">Máximo: %3.1f U</string>
<string name="combo_reservoir_low">Bajo</string>
<string name="combo_reservoir_empty">Vacio</string>
<string name="combo_reservoir_normal">Normal</string>
<string name="combo_notification_check_time_date">Se necesita actualizar reloj de la bomba</string>
<string name="combo_history">Historial</string>
<string name="combo_warning">Alerta</string>
<string name="combo_read_full_history_warning">"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. "</string>
<string name="combo_read_full_history_confirmation">"Estas seguro, de que quieres leer todos los datos de la bomba y acceptar las consequencias de esta acción? "</string>
<string name="combo_pump_tbr_cancelled_warrning">TBR cancelada, advertencia acceptada</string>
<string name="combo_error_no_bolus_delivered">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.</string>
<string name="combo_error_partial_bolus_delivered" formatted="false">"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. "</string>
<string name="combo_error_bolus_verification_failed">"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. "</string>
<string name="combo_error_bolus_recovery_progress">Reestablecido coneccion fallada.</string>
<string name="combo_reservoir_level_insufficient_for_bolus">"No hay suficiente insulina en el deposito para emitir bolo. "</string>
<string name="extendedbolusdeliveryerror">"Error al emitir bolo prolongado. "</string>
<string name="pump_unreachable_threshold">bomba no alcanzable treshold [min]</string>
<string name="treatments_wizard_tt_label">TT</string>
<string name="unsupportednsversion">Versión no acceptada de Nightscout</string>
<string name="enableloop">Activar loop</string>
<string name="disableloop">Desactivar loop</string>
<string name="sms_basal">Base:</string>
<string name="tempbasaldeliveryerror">Base temporal no emitida</string>
<string name="tempbasal">Base temporal</string>
<string name="sms_delta">Delta:</string>
<string name="sms_iob">IOB:</string>
</resources>

View file

@ -129,9 +129,9 @@
<string name="apsmode_title">APS 모드</string>
<string name="closedloop">Closed Loop</string>
<string name="openloop">Open Loop</string>
<string name="disabledloop">Loop 비활성화</string>
<string name="disableloop">Loop 비활성화하기</string>
<string name="enableloop">Loop 활성화하기</string>
<string name="disabledloop">Loop 중지</string>
<string name="disableloop">Loop 중지하기</string>
<string name="enableloop">Loop 실행하기</string>
<string name="openloop_newsuggestion">새로운 제안이 있습니다</string>
<string name="unsupportedclientver">지원하지 않는 NSClient 버전입니다</string>
<string name="unsupportednsversion">지원하지 않는 Nightscout 버전입니다</string>
@ -183,7 +183,7 @@
<string name="overview_tempbasal_button">임시기초주입</string>
<string name="overview_extendedbolus_button">확장식사주입</string>
<string name="configbuilder_nightscoutversion_label">Nightscout 버전:</string>
<string name="send">보내</string>
<string name="send">전송하</string>
<string name="missing">Missing</string>
<string name="enabled">사용</string>
<string name="visible">보이기</string>
@ -251,13 +251,12 @@
<string name="glucosetype_finger">Finger</string>
<string name="glucosetype_sensor">Sensor</string>
<string name="manual">Manual</string>
<string name="careportal_temporarytarget">임시 목표</string>
<string name="careportal_temporarytargetcancel">임시 목표 취소</string>
<string name="careportal_temporarytarget">임시목표</string>
<string name="careportal_temporarytargetcancel">임시목표 취소</string>
<string name="danarprofile">DanaR 프로파일 설정</string>
<string name="danarprofile_dia">인슐린활동시간(DIA) [h]</string>
<string name="danarprofile_dia_summary">Duration of Insulin Activity</string>
<string name="failedupdatebasalprofile">기초주입 프로파일 갱신 실패</string>
<string name="danar_history">과거기록</string>
<string name="danar_historyreload">새로고침</string>
<string name="uploading">업로드중</string>
<string name="danar_ebolus">E bolus</string>
@ -305,14 +304,15 @@
<string name="objectives_5_objective">필요하면 기초주입과 비율을 조절하고, auto-sens를 활성화한다.</string>
<string name="objectives_5_gate">평소의 탄수화물을 입력하면서 1주일동안 낮시간대에 loop를 성공적으로 사용해본다.</string>
<string name="objectives_6_objective">AMA(Advanced Meal Assist)같은 낮시간대를 위한 추가적인 기능들을 실행하여 본다.</string>
<string name="objectives_7_objective">낮시간대에 SMB(Super Micro Bolus)같은 추가기능을 활성화해 사용해본다.</string>
<string name="youareonallowedlimit">허용된 제한값에 도달하였습니다</string>
<string name="noprofileselected">프로파일이 선택되지 않았습니다</string>
<string name="smscommunicator_loophasbeendisabled">Loop가 중지되었습니다.</string>
<string name="smscommunicator_loophasbeenenabled">Loop가 실행되었습니다.</string>
<string name="smscommunicator_loopisdisabled">Loop가 중지중입니다.</string>
<string name="smscommunicator_loopisenabled">Loop가 실행중입니다.</string>
<string name="openapsma_valuelimitedto" formatted="false">%.2f limited to %.2f</string>
<string name="openapsma_valueoutofrange" formatted="false">값 %s 은 하드리밋(Hard Limit)를 벗어났습니다</string>
<string name="openapsma_valuelimitedto" formatted="false">%.2f, %.2f으로 제한됨</string>
<string name="openapsma_valueoutofrange" formatted="false">%s값이 하드리밋(Hard Limit)를 벗어났습니다</string>
<string name="smscommunicator_remotebasalnotallowed">원격 기초주입설정이 허가되지 않았습니다</string>
<string name="smscommunicator_remotecommandnotallowed">원격 명령이 허가되지 않았습니다</string>
<string name="smscommunicator_basalreplywithcode" formatted="false">기초주입 %.2fU/h 을 실행하려면 %s 를 입력하고 답장하세요</string>
@ -384,20 +384,20 @@
<string name="MM640g">MM640g</string>
<string name="ongoingnotificaction">연속 알림</string>
<string name="old_data">OLD DATA</string>
<string name="minago">%d분전</string>
<string name="sms_minago">%dmin ago</string>
<string name="minago" formatted="false">%d분전</string>
<string name="sms_minago" formatted="false">%dmin ago</string>
<string name="localprofile">Local Profile</string>
<string name="openapsama">OpenAPS AMA</string>
<string name="short_avgdelta">Short avg. delta</string>
<string name="long_avgdelta">Long avg. delta</string>
<string name="array_of_elements">Array of %d elements.\nActual value:</string>
<string name="array_of_elements" formatted="false">Array of %d elements.\nActual value:</string>
<string name="openapsma_autosensdata_label">Autosens 정보</string>
<string name="openapsma_scriptdebugdata_label">Script debug</string>
<string name="openapsama_useautosens">AMA autosens 기능 사용하기</string>
<string name="refresheventsfromnightscout">NS에서 이벤트 새로고침</string>
<string name="eatingsoon">Eating Soon</string>
<string name="activity">Activity</string>
<string name="removerecord">Remove record:</string>
<string name="removerecord">기록 삭제:</string>
<string name="danar_stats">DanaR 통계</string>
<string name="danar_stats_cumulative_tdd">누적 일총량</string>
<string name="danar_stats_expweight">지수가중 일총량</string>
@ -436,7 +436,7 @@
<string name="always_use_shortavg">단순델타값 대신 단기평균델타값을 항상 사용합니다.</string>
<string name="always_use_shortavg_summary">xDrip의 혈당데이터에 노이즈가 심할경우 유용합니다.</string>
<string name="advancedsettings_title">고급 설정</string>
<string name="danar_model" formatted="false">Model: %02X Protocol: %02X Code: %02X</string>
<string name="danar_model" formatted="false">모델: %02X 프로토콜: %02X 코드: %02X</string>
<string name="profile">프로파일</string>
<string name="openapsama_max_daily_safety_multiplier_summary">기본값: 3\n이 값은 중요한 OpenAPS 안전장치입니다. 이 값의 역할은 펌프에 설정되어 있는 최대기초주입량보다 3배를 초과할 수 없게 제한하는 것입니다. 이 값을 변경할 필요는 없을 것이지만, 안전을 위해 "3x max daily; 4x current"이 의미하는 바를 알고 있어야 합니다.</string>
<string name="openapsama_current_basal_safety_multiplier_summary">기본값: 4\n이 값은 "3x max daily; 4x current"의 나머지 절반에 해당하는 또 다른 중요한 OpenAPS 안전장치입니다. 이 값은 펌프에 설정된 최대기초주입량과 관계없이, 설정된 현재시간의 기초주입량에 이 값을 곱한 양을 초과할 수 없게됩니다. 이는 알고리즘의 작동 방식을 이해하기 전에 과도하게 높은 최대 기본을 설정하여 위험한 상황에 빠지지 않도록 보호하기 위한 것입니다. 다시한번, 기본 값은 4배인 것을 알아두세요; 일반적으로 이것을 조정할 필요는 전혀 없으며, 대신 이 안전장치를 변경해야할것처럼 생각이 된다면, 다른 설정을 변경해야 할 가능성이 더 큽니다.</string>
@ -448,12 +448,12 @@
<string name="openapsama_link_to_preferncejson_doc_txt">주의!\n보통의 경우 아래의 값을 변경하면 안됩니다. 이 값들을 변경하기 전에 반드시 이곳을 클릭하고 글을 정독해서 확실하게 이해를 하여야 합니다.</string>
<string name="openapsama_link_to_preferncejson_doc">http://openaps.readthedocs.io/en/latest/docs/walkthrough/phase-3/beyond-low-glucose-suspend.html</string>
<string name="error_only_numeric_digits_allowed">숫자만 입력가능합니다.</string>
<string name="error_only_numeric_digits_range_allowed">이 범위(%1$s - %2$s)안에 해당하는 숫자만 입력가능합니다.</string>
<string name="error_only_numeric_digits_range_allowed" formatted="false">이 범위(%1$s - %2$s)안에 해당하는 숫자만 입력가능합니다.</string>
<string name="error_field_must_not_be_empty">필수 입력 항목입니다.</string>
<string name="error_phone_not_valid">폰번호가 유효하지 않습니다</string>
<string name="smscommunicator_invalidphonennumber">SMS폰번호가 유효하지 않습니다</string>
<string name="copy_to_clipboard">Copy To Clipboard</string>
<string name="copied_to_clipboard">Copied to clipboard</string>
<string name="copy_to_clipboard">클립보드에 복사</string>
<string name="copied_to_clipboard">클립보드에 복사되었습니다</string>
<string name="nav_show_logcat">로그 보기</string>
<string name="overview_calibration">보정</string>
<string name="overview_calibration_bg_label">혈당 보정</string>
@ -475,7 +475,7 @@
<string name="disconnecting">연결끊기중</string>
<string name="executing">실행중</string>
<string name="virtualpump_settings">가상펌프 설정</string>
<string name="virtualpump_uploadstatus_title">Upload status to NS</string>
<string name="virtualpump_uploadstatus_title">NS에 상태 업로드하기</string>
<string name="wrongpassword">잘못된 비밀번호</string>
<string name="settings_password">설정 비밀번호</string>
<string name="unlock_settings">설정 잠금해제</string>
@ -483,7 +483,7 @@
<string name="nsclientinternal">내장 NSClient</string>
<string name="nsclientinternal_shortname">NSCI</string>
<string name="nsclientinternal_url">URL:</string>
<string name="nsclientinternal_autoscroll">Autoscroll</string>
<string name="nsclientinternal_autoscroll">자동스크롤</string>
<string name="restart">Restart</string>
<string name="nsclientinternal_title">내장 NSClient</string>
<string name="nsclientinternal_url_title">Nightscout URL</string>
@ -499,13 +499,13 @@
<string name="show_queue">Show queue</string>
<string name="queue">Queue:</string>
<string name="status">Status:</string>
<string name="paused">Paused</string>
<string name="paused">일시중지</string>
<string name="clearlog">Clear log</string>
<string name="nowritepermission">NSCLIENT이 쓰기 권한이 없습니다. 잘못된 API secret인지 확인해보세요</string>
<string name="wear_settings">웨어 설정</string>
<string name="wear_detailedIOB_title">IOB 자세하게 보여주기</string>
<string name="wear_detailedIOB_summary">워치페이스에 IOB를 식사주입IOB와 기초주입IOB로 나누어서 보여줍니다.</string>
<string name="nosuccess">not successful - please check phone</string>
<string name="nosuccess">성공하지 못했습니다. 폰을 확인하세요</string>
<string name="notavailable">알수없음</string>
<string name="patientage">나이</string>
<string name="child">어린이</string>
@ -515,10 +515,9 @@
<string name="Glimp">Glimp</string>
<string name="batteryoptimalizationerror">Device does not appear to support battery optimization whitelisting!</string>
<string name="pleaseallowpermission">권한을 허용하세요.</string>
<string name="needwhitelisting">%s needs battery optimalization whitelisting for proper performance</string>
<string name="loopsuspended">Loop 일시중지</string>
<string name="loopsuspendedfor" formatted="false">일시중지중 (%d분)</string>
<string name="loopsuperbolusfor" formatted="false">Superbolus (%d분)</string>
<string name="loopsuperbolusfor" formatted="false">수퍼 식사주입 (%d분)</string>
<string name="loopmenu">Loop 메뉴</string>
<string name="suspendloopfor1h">1시간동안 Loop 일시중지</string>
<string name="suspendloopfor2h">2시간동안 Loop 일시중지</string>
@ -529,24 +528,24 @@
<string name="disconnectpumpfor2h">2시간동안 펌프 일시중지</string>
<string name="disconnectpumpfor3h">3시간동안 펌프 일시중지</string>
<string name="disconnectpumpfor10h">10시간동안 펌프 일시중지</string>
<string name="resume">시작</string>
<string name="resume">실행</string>
<string name="smscommunicator_wrongduration">기간이 잘못되었습니다.</string>
<string name="smscommunicator_loopsuspended">Loop가 일시중지되었습니다.</string>
<string name="smscommunicator_loopresumed">Loop가 재시작되었습니다.</string>
<string name="smscommunicator_loopsuspended">Loop가 일시중지 되었습니다.</string>
<string name="smscommunicator_loopresumed">Loop가 재실행 되었습니다.</string>
<string name="treatments_wizard_bgtrend_label">15분 추이</string>
<string name="treatments_wizard_cob_label">COB</string>
<string name="superbolus">Superbolus</string>
<string name="superbolus">수퍼 식사주입</string>
<string name="ns_logappstartedevent">앱시작을 NS에 기록하기</string>
<string name="restartingapp">설정을 적용하기위해 앱을 종료합니다.</string>
<string name="danarv2pump">다나Rv2</string>
<string name="configbuilder_insulin">인슐린</string>
<string name="fastactinginsulin">Fast Acting Insulin</string>
<string name="fastactinginsulincomment">Novorapid, Novolog, Humalog</string>
<string name="ultrafastactinginsulincomment">Fiasp</string>
<string name="fastactinginsulincomment">노보래피드, 휴마로그, 에피드라</string>
<string name="ultrafastactinginsulincomment">피아스프(Fiasp)</string>
<string name="insulin_shortname">INS</string>
<string name="fastactinginsulinprolonged">Fast Acting Insulin Prolonged</string>
<string name="enablesuperbolus">마법사에서 Superbolus 활성화하기</string>
<string name="enablesuperbolus_summary">마법사에서 Superbolus 기능을 활성화합니다. 어떤 기능인지 확실히 알기전까지 활성화 하지 마세요. 제대로 알지 못하고 사용하면 일슐린이 과다 주입될 수 있습니다!</string>
<string name="enablesuperbolus">마법사에서 수퍼 식사주입 활성화하기</string>
<string name="enablesuperbolus_summary">마법사에서 수퍼 식사주입 기능을 활성화합니다. 어떤 기능인지 확실히 알기전까지 활성화 하지 마세요. 제대로 알지 못하고 사용하면 일슐린이 과다 주입될 수 있습니다!</string>
<string name="iob">IOB</string>
<string name="cob">COB</string>
<string name="predictionshortlabel">PRE</string>
@ -583,15 +582,15 @@
<string name="careportal_pbage_label">펌프배터리사용기간</string>
<string name="careportal_pumpbatterychange">펌프 배터리 교체</string>
<string name="ns_alarmoptions">알람 옵션</string>
<string name="nsalarm_urgenthigh">Urgent high</string>
<string name="nsalarm_high">High</string>
<string name="nsalarm_low">Low</string>
<string name="nsalarm_urgentlow">Urgent low</string>
<string name="nsalarm_urgenthigh">위험 고혈당</string>
<string name="nsalarm_high">고혈당</string>
<string name="nsalarm_low">저혈당</string>
<string name="nsalarm_urgentlow">위험 저혈당</string>
<string name="nsalarm_summary" formatted="false">Currently set to %f</string>
<string name="nsalarm_staledata">Stale data</string>
<string name="nsalarm_urgentstaledata">Urgent stale data</string>
<string name="nsalarm_staledatavalue_label">Stale data threshold [min]</string>
<string name="nsalarm_urgent_staledatavalue_label">Urgent stale data threshold [min]</string>
<string name="nsalarm_staledata">누락 데이터</string>
<string name="nsalarm_urgentstaledata">위험 누락 데이터</string>
<string name="nsalarm_staledatavalue_label">누락 데이터 기준값[분]</string>
<string name="nsalarm_urgent_staledatavalue_label">위험 누락 데이터 기준값[분]</string>
<string name="openapsama_autosens_period">autosens 시간 [h]</string>
<string name="openapsama_autosens_period_summary">민감도를 감지하기 위해 계산될 총 시간 (탄수화물 흡수 시간은 제외됩니다.)</string>
<string name="ratio_short">SEN</string>
@ -603,8 +602,8 @@
<string name="uploader">Uploader</string>
<string name="configbuilder_sensitivity">민감도 감지</string>
<string name="sensitivity_shortname">SENS</string>
<string name="sensitivityoref0">Sensitivity Oref0</string>
<string name="sensitivityaaps">Sensitivity AAPS</string>
<string name="sensitivityoref0">민감도 Oref0</string>
<string name="sensitivityaaps">민감도 AAPS</string>
<string name="absorptionsettings_title">흡수 설정</string>
<string name="absorption_maxtime_title">식사 최대 흡수 시간 [h]</string>
<string name="absorption_maxtime_summary">식사로 섭취한 탄수화물이 모두 흡수될기까지 예상되는 시간</string>
@ -620,7 +619,7 @@
<string name="lock_screen">화면 잠금</string>
<string name="lock_screen_short">잠금</string>
<string name="sensitivity_warning">Autosense 기능을 켜면 모든 섭취된 탄수화물양을 입력하십시오. 그렇지 않으면 탄수화물 편차(deviations)가 민감도 변화로 잘못 인식될것입니다!!</string>
<string name="sensitivityweightedaverage">Sensitivity WeightedAverage</string>
<string name="sensitivityweightedaverage">민감도 가중평균</string>
<string name="mdtp_ok">OK</string>
<string name="mdtp_cancel">Cancel</string>
<string name="cpp_sync_setting_missing">needs to be activated to send values to the pump!</string>
@ -636,13 +635,13 @@
<string name="careportal_pump_label">펌프</string>
<string name="overview_newtempbasal_basalabsolute">Basal value [U/h]</string>
<string name="careportal_newnstreatment_duration_min_label">Duration [min]</string>
<string name="insulin_oref_peak">IOB Curve Peak Time</string>
<string name="insulin_peak_time">Peak Time [min]</string>
<string name="insulin_oref_peak">IOB 커브 피크 시간</string>
<string name="insulin_peak_time">피크 시간[분]</string>
<string name="free_peak_oref">Free-Peak Oref</string>
<string name="rapid_acting_oref">Rapid-Acting Oref</string>
<string name="ultrarapid_oref">Ultra-Rapid Oref</string>
<string name="dia_too_short" formatted="false">"DIA of %s too short - using %s instead!"</string>
<string name="activate_profile">ACTIVATE PROFILE</string>
<string name="dia_too_short" formatted="false">"DIA %s는 너무 짧습니다. 대신 %s을 사용하세요!"</string>
<string name="activate_profile">프로파일 활성화하기</string>
<string name="date">Date</string>
<string name="invalid">INVALID</string>
<string name="waitingforpairing">펌프연동 대기중</string>
@ -677,4 +676,60 @@
<string name="wearcontrol_title">워치로 작동하기</string>
<string name="wearcontrol_summary">임시목표와 관리입력을 워치로 설정합니다.</string>
<string name="connectiontimedout">연결시간초과</string>
<string name="food">음식</string>
<string name="shortgramm">g</string>
<string name="none"><![CDATA[<none>]]></string>
<string name="shortkilojoul">kJ</string>
<string name="shortenergy">En</string>
<string name="shortprotein">Pr</string>
<string name="shortfat">Fat</string>
<string name="active"><![CDATA[<Active>]]></string>
<string name="waitingforestimatedbolusend" formatted="false">식사주입 종료를 기다리고 있습니다. %d초 남았습니다.</string>
<string name="processinghistory">이벤트 처리중</string>
<string name="startingbolus">식사주입을 시작합니다.</string>
<string name="executingrightnow">명령을 지금 실행합니다.</string>
<string name="pumpdrivercorrected">펌프 드라이버가 수정되었습니다.</string>
<string name="pump_unreachable">펌프에 연결할 수 없습니다.</string>
<string name="missed_bg_readings">혈당 읽기가 누락되었습니다.</string>
<string name="raise_notifications_as_android_notifications">경고와 알림시 시스템 알림 사용하기</string>
<string name="localalertsettings_title">자체 경고 기능</string>
<string name="enable_missed_bg_readings_alert">혈당 데이터 누락시 경고하기</string>
<string name="enable_pump_unreachable_alert">펌프와 연결불가시 경고하기</string>
<string name="pump_unreachable_threshold">펌프 연결불가 기준시간[분]</string>
<string name="urgent_alarm">긴급 알람</string>
<string name="info">정보</string>
<string name="bluetooth">블루투스</string>
<string name="btwatchdog_title">블루투스 감시기능</string>
<string name="btwatchdog_summary">펌프에 연결이 되지 않을때 폰의 블루투스를 1초간 껐다 켭니다. 블루투스 스택이 정지되는 일부폰에 이 기능이 도움이 됩니다.</string>
<string name="DexcomG5">(패치된) DexcomG5 앱</string>
<string name="dexcomg5_nsupload_title">NS에 혈당데이터 업로드하기</string>
<string name="dexcomg5_upload">G5업로드 세팅</string>
<string name="customapp">Customized APK for download</string>
<string name="wear_detailed_delta_title">델타(혈당증분값) 자세히 보여주기</string>
<string name="wear_detailed_delta_summary">소수점 한자리 더 추가된 델타 보여주기</string>
<string name="unsupportedfirmware">지원되지 않는 펌프 펌웨어</string>
<string name="dexcomg5_xdripupload_title">혈당 데이터를 xDrip+에 전송하기</string>
<string name="dexcomg5_xdripupload_summary">xDrip+ 데이터 소스에서 640g/Eversense을 선택하세요</string>
<string name="minimalbasalvaluereplaced">지원되는 최소값으로 기초주입량이 대체되었습니다.</string>
<string name="overview_editquickwizard_usebg">혈당 계산</string>
<string name="overview_editquickwizard_usebolusiob">식사주입 IOB 계산</string>
<string name="overview_editquickwizard_usebasaliob">기초주입 IOB 계산</string>
<string name="overview_editquickwizard_usetrend">추세계산</string>
<string name="overview_editquickwizard_usesuperbolus">수퍼 식사주입 계산</string>
<string name="yes"></string>
<string name="no">아니오</string>
<string name="positiveonly">양수만</string>
<string name="negativeonly">음수만</string>
<string name="overview_editquickwizard_usecob">COB 계산</string>
<string name="overview_editquickwizard_usetemptarget">임시목표 계산</string>
<string name="loopenabled">Loop 활성화됨</string>
<string name="apsselected">APS 선택됨</string>
<string name="nsclienthaswritepermission">NSClient가 쓰기권한이 있습니다</string>
<string name="closedmodeenabled">Closed 모드가 활성화됨</string>
<string name="maxiobset">최대 IOB가 바르게 설정됨</string>
<string name="hasbgdata">선택한 소스에서 혈당이 들어옵니다.</string>
<string name="basalprofilenotaligned" formatted="false">기초주입값이 시간단위로 설정되지 않았습니다: %s</string>
<string name="zerovalueinprofile" formatted="false">유효하지 않은 프로파일: %s</string>
<string name="danar_history">펌프 이력</string>
<string name="extendedbolusdeliveryerror">확장식사주입 에러</string>
</resources>

View file

@ -675,15 +675,12 @@
<string name="wearcontrol_title">Bedieningen via horloge</string>
<string name="emptyreservoir">Ampull leeg</string>
<string name="waitingforpairing">Wachten op koppelen van de pomp</string>
<string name="pump_errors_history">Storingen</string>
<string name="profileswitch">Wijzigingen van profiel</string>
<string name="bluetooth">Bluetooth</string>
<string name="food">Voeding</string>
<string name="enable_pump_unreachable_alert">Waarschuwing bij niet bereikbare pomp</string>
<string name="bolus_frequency_exceeded">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</string>
<string name="bolusstopping">estopt Bolus toediening wordt</string>
<string name="shortfat">Vet</string>
<string name="bolusstopped">Bolus toediening gestopt</string>
<string name="wear_detailed_delta_title">Toon gedetaillieerde delta</string>
<string name="unsupportedfirmware">Niet ondersteune pomp firmware</string>
<string name="DexcomG5">DexcomG5 App (aangepast)</string>
@ -771,7 +768,7 @@
<string name="combo_activity_setting_basal_profile">Instellen van basaal profiel</string>
<string name="combo_activity_reading_pump_history">Lezen van pomp historiek</string>
<string name="combo_read_full_history_confirmation">Ben je zeker dat je alle data van de pomp wil ophalen en de consequenties hiervan wil dragen?</string>
<string name="combo_no_alert_data_note">Om de pomp fouthistoriek op te halen, druk lang op de Storingen knop OPGELET: dit kan een bug veroorzaken waardoor de pomp alle verbindingen verbreekt en het vereist is op een knop op de pomp te duwen, dit wordt daarom afgeraden.</string>
<string name="combo_no_alert_data_note">Om de pomp fouthistoriek op te halen, druk lang op de Storingen knop.</string>
<string name="combo_error_partial_bolus_delivered">Maar %.2f E van de gevraagde %.2f E zijn toegediend door een storing. Gelieve op de pomp te controleren en het gepaste gevolg uit te voeren.</string>
<string name="combo_no_tdd_data_note">"Om de TTD van de pomp op te halen, lang duwen op de TDDS knop OPGELET: dit kan een bug veroorzaken waardoor de pomp alle verbindingen verbreekt en het vereist is op een knop op de pomp te duwen, dit wordt daarom afgeraden."</string>
<string name="combo_error_bolus_verification_failed">Toedienen en controleren van de bolus in de pomp historiek is mislukt, controleer de pomp en creëer een manuele bolus in het Careportal tabblad</string>

View file

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name"></string>
</resources>

View file

@ -20,6 +20,7 @@
<item>@string/el_lang</item>
<item>@string/it_lang</item>
<item>@string/ko_lang</item>
<item>@string/ro_lang</item>
<item>@string/ru_lang</item>
<item>@string/sv_lang</item>
</string-array>
@ -33,6 +34,7 @@
<item>el</item>
<item>it</item>
<item>ko</item>
<item>ro</item>
<item>ru</item>
<item>sv</item>
</string-array>

View file

@ -209,6 +209,7 @@
<string name="es_lang">Spanish</string>
<string name="el_lang">Greek</string>
<string name="it_lang">Italian</string>
<string name="ro_lang">Romanian</string>
<string name="ru_lang">Russian</string>
<string name="sv_lang">Swedish</string>
<string name="openapsma_maxbasal_title">Max U/hr a Temp Basal can be set to</string>
@ -268,7 +269,6 @@
<string name="danarprofile_dia">DIA [h]</string>
<string name="danarprofile_dia_summary">Duration of Insulin Activity</string>
<string name="failedupdatebasalprofile">Failed to update basal profile</string>
<string name="pump_errors_history">Errors</string>
<string name="danar_historyreload">Reload</string>
<string name="uploading">Uploading</string>
<string name="danar_ebolus">E bolus</string>
@ -454,9 +454,9 @@
<string name="danar_model" formatted="false">Model: %02X Protocol: %02X Code: %02X</string>
<string name="profile">Profile</string>
<string name="openapsama_max_daily_safety_multiplier" translatable="false">max_daily_safety_multiplier</string>
<string name="openapsama_max_daily_safety_multiplier_summary">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 thats what is discussed about “3x max daily; 4x current” for safety caps.</string>
<string name="openapsama_max_daily_safety_multiplier_summary">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 thats what is discussed about “3x max daily; 4x current” for safety caps.</string>
<string name="openapsama_current_basal_safety_multiplier" translatable="false">current_basal_safety_multiplier</string>
<string name="openapsama_current_basal_safety_multiplier_summary">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.</string>
<string name="openapsama_current_basal_safety_multiplier_summary">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.</string>
<string name="openapsama_autosens_max" translatable="false">autosens_max</string>
<string name="openapsama_autosens_max_summary">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.</string>
<string name="openapsama_autosens_min" translatable="false">autosens_min</string>
@ -466,9 +466,9 @@
<string name="openapsama_bolussnooze_dia_divisor" translatable="false">bolussnooze_dia_divisor</string>
<string name="openapsama_bolussnooze_dia_divisor_summary">Default value: 2\nBolus snooze is enacted after you do a meal bolus, so the loop wont counteract with low temps when youve 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).</string>
<string name="openapsama_min_5m_carbimpact" translatable="false">min_5m_carbimpact</string>
<string name="openapsama_min_5m_carbimpact_summary">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.</string>
<string name="openapsama_min_5m_carbimpact_summary">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.</string>
<string name="openapsama_link_to_preferncejson_doc_txt">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.</string>
<string name="openapsama_link_to_preferncejson_doc">http://openaps.readthedocs.io/en/latest/docs/walkthrough/phase-3/beyond-low-glucose-suspend.html</string>
<string name="openapsama_link_to_preferncejson_doc" translatable="false">http://openaps.readthedocs.io/en/latest/docs/walkthrough/phase-3/beyond-low-glucose-suspend.html</string>
<string name="error_only_numeric_digits_allowed">Only numeric digits are allowed.</string>
<string name="error_only_numeric_digits_range_allowed">Only numeric digits within the range %1$s - %2$s are allowed.</string>
<string name="error_field_must_not_be_empty">The field must not be empty</string>
@ -783,7 +783,7 @@
<string name="btwatchdog_summary">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.</string>
<string name="DexcomG5">DexcomG5 App (patched)</string>
<string name="dexcomg5_nsupload_title">Upload BG data to NS</string>
<string name="key_dexcomg5_nsupload">dexcomg5_nsupload</string>
<string name="key_dexcomg5_nsupload" translatable="false">dexcomg5_nsupload</string>
<string name="dexcomg5_upload">G5 upload settings</string>
<string name="customapp">Customized APK for download</string>
<string name="wear_detailed_delta_title">Show detailed delta</string>
@ -820,7 +820,7 @@
<string name="combo_pump_activity_label">Activity</string>
<string name="combo_no_pump_connection">No connection for %d min</string>
<string name="combo_tbr_remaining">%d%% (%d min remaining)</string>
<string name="combo_last_bolus">%.1f %s (%s)</string>
<string name="combo_last_bolus" translatable="false">%.1f %s (%s)</string>
<string name="combo_pump_state_initializing">Initializing</string>
<string name="combo_pump_state_disconnected">Disconnected</string>
<string name="combo_pump_state_suspended_due_to_error">Suspended due to error</string>
@ -855,10 +855,10 @@
<string name="combo_history">History</string>
<string name="combo_warning">Warning</string>
<string name="combo_read_full_history_info">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.</string>
<string name="combo_read_full_history_warning">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.</string>
<string name="combo_read_full_history_warning">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.</string>
<string name="combo_read_full_history_confirmation">Are you really sure you want to read all pump data and take the consequences of this action?</string>
<string name="combo_pump_tbr_cancelled_warrning">TBR CANCELLED warning was confirmed</string>
<string name="combo_error_no_connection_no_bolus_delivered">The pump could\'nt be reached. No bolus was given</string>
<string name="combo_error_no_connection_no_bolus_delivered">The pump could not be reached. No bolus was given</string>
<string name="combo_error_no_bolus_delivered">Bolus delivery failed. It appears no bolus was delivered. To be sure, please check the pump to avoid a double bolus and then bolus again. To guard against bugs, boluses are not automatically retried.</string>
<string name="combo_error_partial_bolus_delivered">Only %.2f U of the requested bolus of %.2f U was delivered due to an error. Please check the pump to verify this and take appropriate actions.</string>
<string name="combo_error_bolus_verification_failed">Delivering the bolus and verifying the pump\'s history failed, please check the pump and manually create a bolus record using the Careportal tab if a bolus was delivered.</string>
@ -867,7 +867,7 @@
<string name="extendedbolusdeliveryerror">Extended bolus delivery error</string>
<string name="pump_basebasalrate">%.2f U/h</string>
<string name="combo_actvity_reading_basal_profile">Reading basal profile</string>
<string name="combo_bolus_rejected_due_to_pump_history_change">The pump history has changed after the bolus calculation was performed. The bolus was not delivered. Please recalculate if a bolus is still needed. If the same bolus amount is required, please wait a minute since boluses with the same amount are blocked when requested with less than tow minutes between them for safety (regardless of whether they were administered or not).</string>
<string name="combo_bolus_rejected_due_to_pump_history_change">The pump history has changed after the bolus calculation was performed. The bolus was not delivered. Please recalculate if a bolus is still needed. If the same bolus amount is required, please wait two minutes since boluses with the same amount are blocked when requested with less than two minutes between them for safety (regardless of whether they were administered or not).</string>
<string name="combo_error_updating_treatment_record">Bolus successfully delivered, but adding the treatment entry failed. This can happen if two small boluses of the same size are administered within the last two minutes. Please check the pump history and treatment entries and use the Careportal to add missing entries. Make sure not to add any entries for the exact same minute and same amount.</string>
<string name="combo_high_temp_rejected_due_to_pump_history_changes">Rejecting high temp since calculation didn\'t consider recently changed pump history</string>
<string name="combo_activity_checking_pump_state">Refreshing pump state</string>

View file

@ -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;
}
}

View file

@ -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<BgWatchData> 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);
}
}