Merge remote-tracking branch 'ns/dev' into dev
This commit is contained in:
commit
cb2d623923
283 changed files with 4346 additions and 1254 deletions
|
@ -100,6 +100,7 @@ def allCommitted = { ->
|
|||
|
||||
tasks.matching { it instanceof Test }.all {
|
||||
testLogging.events = ["failed", "skipped", "started"]
|
||||
// testLogging.events = ["failed", "skipped", "started", "standard_out"] use to display stdout in travis
|
||||
testLogging.exceptionFormat = "full"
|
||||
}
|
||||
|
||||
|
|
|
@ -1,220 +0,0 @@
|
|||
package info.nightscout.androidaps.plugins.sensitivity;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.collection.LongSparseArray;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Singleton;
|
||||
|
||||
import dagger.android.HasAndroidInjector;
|
||||
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.db.CareportalEvent;
|
||||
import info.nightscout.androidaps.db.ProfileSwitch;
|
||||
import info.nightscout.androidaps.interfaces.IobCobCalculatorInterface;
|
||||
import info.nightscout.androidaps.interfaces.PluginDescription;
|
||||
import info.nightscout.androidaps.interfaces.PluginType;
|
||||
import info.nightscout.androidaps.interfaces.ProfileFunction;
|
||||
import info.nightscout.androidaps.logging.AAPSLogger;
|
||||
import info.nightscout.androidaps.logging.LTag;
|
||||
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.AutosensResult;
|
||||
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.IobCobCalculatorPlugin;
|
||||
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.data.AutosensData;
|
||||
import info.nightscout.androidaps.utils.DateUtil;
|
||||
import info.nightscout.androidaps.utils.resources.ResourceHelper;
|
||||
import info.nightscout.androidaps.utils.sharedPreferences.SP;
|
||||
|
||||
/**
|
||||
* Created by mike on 24.06.2017.
|
||||
*/
|
||||
|
||||
@Singleton
|
||||
public class SensitivityAAPSPlugin extends AbstractSensitivityPlugin {
|
||||
|
||||
private final ProfileFunction profileFunction;
|
||||
private final DateUtil dateUtil;
|
||||
|
||||
@Inject
|
||||
public SensitivityAAPSPlugin(
|
||||
HasAndroidInjector injector,
|
||||
AAPSLogger aapsLogger,
|
||||
ResourceHelper resourceHelper,
|
||||
SP sp,
|
||||
ProfileFunction profileFunction,
|
||||
DateUtil dateUtil
|
||||
) {
|
||||
super(new PluginDescription()
|
||||
.mainType(PluginType.SENSITIVITY)
|
||||
.pluginIcon(R.drawable.ic_generic_icon)
|
||||
.pluginName(R.string.sensitivityaaps)
|
||||
.shortName(R.string.sensitivity_shortname)
|
||||
.preferencesId(R.xml.pref_absorption_aaps)
|
||||
.description(R.string.description_sensitivity_aaps),
|
||||
injector, aapsLogger, resourceHelper, sp
|
||||
);
|
||||
this.profileFunction = profileFunction;
|
||||
this.dateUtil = dateUtil;
|
||||
}
|
||||
|
||||
@NonNull @Override
|
||||
public AutosensResult detectSensitivity(IobCobCalculatorInterface iobCobCalculatorPlugin, long fromTime, long toTime) {
|
||||
LongSparseArray<AutosensData> autosensDataTable = iobCobCalculatorPlugin.getAutosensDataTable();
|
||||
|
||||
String age = getSp().getString(R.string.key_age, "");
|
||||
int defaultHours = 24;
|
||||
if (age.equals(getResourceHelper().gs(R.string.key_adult))) defaultHours = 24;
|
||||
if (age.equals(getResourceHelper().gs(R.string.key_teenage))) defaultHours = 4;
|
||||
if (age.equals(getResourceHelper().gs(R.string.key_child))) defaultHours = 4;
|
||||
int hoursForDetection = getSp().getInt(R.string.key_openapsama_autosens_period, defaultHours);
|
||||
|
||||
Profile profile = profileFunction.getProfile();
|
||||
|
||||
if (profile == null) {
|
||||
getAapsLogger().error("No profile");
|
||||
return new AutosensResult();
|
||||
}
|
||||
|
||||
if (autosensDataTable == null || autosensDataTable.size() < 4) {
|
||||
getAapsLogger().debug(LTag.AUTOSENS, "No autosens data available. lastDataTime=" + iobCobCalculatorPlugin.lastDataTime());
|
||||
return new AutosensResult();
|
||||
}
|
||||
|
||||
AutosensData current = iobCobCalculatorPlugin.getAutosensData(toTime); // this is running inside lock already
|
||||
if (current == null) {
|
||||
getAapsLogger().debug(LTag.AUTOSENS, "No autosens data available. toTime: " + dateUtil.dateAndTimeString(toTime) + " lastDataTime: " + iobCobCalculatorPlugin.lastDataTime());
|
||||
return new AutosensResult();
|
||||
}
|
||||
|
||||
|
||||
List<CareportalEvent> siteChanges = MainApp.getDbHelper().getCareportalEventsFromTime(fromTime, CareportalEvent.SITECHANGE, true);
|
||||
List<ProfileSwitch> profileSwitches = MainApp.getDbHelper().getProfileSwitchEventsFromTime(fromTime, true);
|
||||
|
||||
List<Double> deviationsArray = new ArrayList<>();
|
||||
String pastSensitivity = "";
|
||||
int index = 0;
|
||||
while (index < autosensDataTable.size()) {
|
||||
AutosensData autosensData = autosensDataTable.valueAt(index);
|
||||
|
||||
if (autosensData.time < fromTime) {
|
||||
index++;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (autosensData.time > toTime) {
|
||||
index++;
|
||||
continue;
|
||||
}
|
||||
|
||||
// reset deviations after site change
|
||||
if (new CareportalEvent(getInjector()).isEvent5minBack(siteChanges, autosensData.time)) {
|
||||
deviationsArray.clear();
|
||||
pastSensitivity += "(SITECHANGE)";
|
||||
}
|
||||
|
||||
// reset deviations after profile switch
|
||||
if (new ProfileSwitch(getInjector()).isEvent5minBack(profileSwitches, autosensData.time, true)) {
|
||||
deviationsArray.clear();
|
||||
pastSensitivity += "(PROFILESWITCH)";
|
||||
}
|
||||
|
||||
double deviation = autosensData.deviation;
|
||||
|
||||
//set positive deviations to zero if bg < 80
|
||||
if (autosensData.bg < 80 && deviation > 0)
|
||||
deviation = 0;
|
||||
|
||||
if (autosensData.validDeviation)
|
||||
if (autosensData.time > toTime - hoursForDetection * 60 * 60 * 1000L)
|
||||
deviationsArray.add(deviation);
|
||||
if (deviationsArray.size() > hoursForDetection * 60 / 5)
|
||||
deviationsArray.remove(0);
|
||||
|
||||
|
||||
pastSensitivity += autosensData.pastSensitivity;
|
||||
int secondsFromMidnight = Profile.secondsFromMidnight(autosensData.time);
|
||||
if (secondsFromMidnight % 3600 < 2.5 * 60 || secondsFromMidnight % 3600 > 57.5 * 60) {
|
||||
pastSensitivity += "(" + Math.round(secondsFromMidnight / 3600d) + ")";
|
||||
}
|
||||
index++;
|
||||
}
|
||||
|
||||
Double[] deviations = new Double[deviationsArray.size()];
|
||||
deviations = deviationsArray.toArray(deviations);
|
||||
|
||||
double sens = profile.getIsfMgdl();
|
||||
|
||||
String ratioLimit = "";
|
||||
String sensResult = "";
|
||||
|
||||
getAapsLogger().debug(LTag.AUTOSENS, "Records: " + index + " " + pastSensitivity);
|
||||
|
||||
Arrays.sort(deviations);
|
||||
|
||||
double percentile = IobCobCalculatorPlugin.Companion.percentile(deviations, 0.50);
|
||||
double basalOff = percentile * (60.0 / 5.0) / sens;
|
||||
double ratio = 1 + (basalOff / profile.getMaxDailyBasal());
|
||||
|
||||
if (percentile < 0) { // sensitive
|
||||
sensResult = "Excess insulin sensitivity detected";
|
||||
} else if (percentile > 0) { // resistant
|
||||
sensResult = "Excess insulin resistance detected";
|
||||
} else {
|
||||
sensResult = "Sensitivity normal";
|
||||
}
|
||||
|
||||
getAapsLogger().debug(LTag.AUTOSENS, sensResult);
|
||||
|
||||
AutosensResult output = fillResult(ratio, current.cob, pastSensitivity, ratioLimit,
|
||||
sensResult, deviationsArray.size());
|
||||
|
||||
getAapsLogger().debug(LTag.AUTOSENS, "Sensitivity to: "
|
||||
+ dateUtil.dateAndTimeString(toTime) +
|
||||
" ratio: " + output.ratio
|
||||
+ " mealCOB: " + current.cob);
|
||||
getAapsLogger().debug(LTag.AUTOSENS, "Sensitivity to: deviations " + Arrays.toString(deviations));
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
@NonNull @Override public SensitivityType getId() {
|
||||
return SensitivityType.SENSITIVITY_AAPS;
|
||||
}
|
||||
|
||||
@NonNull @Override public JSONObject configuration() {
|
||||
JSONObject c = new JSONObject();
|
||||
try {
|
||||
c.put(getResourceHelper().gs(R.string.key_absorption_maxtime), getSp().getDouble(R.string.key_absorption_maxtime, Constants.DEFAULT_MAX_ABSORPTION_TIME));
|
||||
c.put(getResourceHelper().gs(R.string.key_openapsama_autosens_period), getSp().getInt(R.string.key_openapsama_autosens_period, 24));
|
||||
c.put(getResourceHelper().gs(R.string.key_openapsama_autosens_max), getSp().getDouble(R.string.key_openapsama_autosens_max, 1.2));
|
||||
c.put(getResourceHelper().gs(R.string.key_openapsama_autosens_min), getSp().getDouble(R.string.key_openapsama_autosens_min, 0.7));
|
||||
} catch (JSONException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return c;
|
||||
}
|
||||
|
||||
@Override public void applyConfiguration(@NonNull JSONObject configuration) {
|
||||
try {
|
||||
if (configuration.has(getResourceHelper().gs(R.string.key_absorption_maxtime)))
|
||||
getSp().putDouble(R.string.key_absorption_maxtime, configuration.getDouble(getResourceHelper().gs(R.string.key_absorption_maxtime)));
|
||||
if (configuration.has(getResourceHelper().gs(R.string.key_openapsama_autosens_period)))
|
||||
getSp().putDouble(R.string.key_openapsama_autosens_period, configuration.getDouble(getResourceHelper().gs(R.string.key_openapsama_autosens_period)));
|
||||
if (configuration.has(getResourceHelper().gs(R.string.key_openapsama_autosens_max)))
|
||||
getSp().getDouble(R.string.key_openapsama_autosens_max, configuration.getDouble(getResourceHelper().gs(R.string.key_openapsama_autosens_max)));
|
||||
if (configuration.has(getResourceHelper().gs(R.string.key_openapsama_autosens_min)))
|
||||
getSp().getDouble(R.string.key_openapsama_autosens_min, configuration.getDouble(getResourceHelper().gs(R.string.key_openapsama_autosens_min)));
|
||||
} catch (JSONException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,161 @@
|
|||
package info.nightscout.androidaps.plugins.sensitivity
|
||||
|
||||
import dagger.android.HasAndroidInjector
|
||||
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.db.CareportalEvent
|
||||
import info.nightscout.androidaps.db.ProfileSwitch
|
||||
import info.nightscout.androidaps.interfaces.IobCobCalculatorInterface
|
||||
import info.nightscout.androidaps.interfaces.PluginDescription
|
||||
import info.nightscout.androidaps.interfaces.PluginType
|
||||
import info.nightscout.androidaps.interfaces.ProfileFunction
|
||||
import info.nightscout.androidaps.interfaces.SensitivityInterface.SensitivityType
|
||||
import info.nightscout.androidaps.logging.AAPSLogger
|
||||
import info.nightscout.androidaps.logging.LTag
|
||||
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.AutosensResult
|
||||
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.IobCobCalculatorPlugin.Companion.percentile
|
||||
import info.nightscout.androidaps.utils.DateUtil
|
||||
import info.nightscout.androidaps.utils.resources.ResourceHelper
|
||||
import info.nightscout.androidaps.utils.sharedPreferences.SP
|
||||
import org.json.JSONException
|
||||
import org.json.JSONObject
|
||||
import java.util.*
|
||||
import javax.inject.Inject
|
||||
import javax.inject.Singleton
|
||||
import kotlin.math.roundToInt
|
||||
|
||||
@Singleton
|
||||
open class SensitivityAAPSPlugin @Inject constructor(
|
||||
injector: HasAndroidInjector?,
|
||||
aapsLogger: AAPSLogger?,
|
||||
resourceHelper: ResourceHelper?,
|
||||
sp: SP?,
|
||||
private val profileFunction: ProfileFunction,
|
||||
private val dateUtil: DateUtil
|
||||
) : AbstractSensitivityPlugin(PluginDescription()
|
||||
.mainType(PluginType.SENSITIVITY)
|
||||
.pluginIcon(R.drawable.ic_generic_icon)
|
||||
.pluginName(R.string.sensitivityaaps)
|
||||
.shortName(R.string.sensitivity_shortname)
|
||||
.preferencesId(R.xml.pref_absorption_aaps)
|
||||
.description(R.string.description_sensitivity_aaps),
|
||||
injector!!, aapsLogger!!, resourceHelper!!, sp!!
|
||||
) {
|
||||
|
||||
override fun detectSensitivity(plugin: IobCobCalculatorInterface, fromTime: Long, toTime: Long): AutosensResult {
|
||||
val autosensDataTable = plugin.getAutosensDataTable()
|
||||
val age = sp.getString(R.string.key_age, "")
|
||||
var defaultHours = 24
|
||||
if (age == resourceHelper.gs(R.string.key_adult)) defaultHours = 24
|
||||
if (age == resourceHelper.gs(R.string.key_teenage)) defaultHours = 4
|
||||
if (age == resourceHelper.gs(R.string.key_child)) defaultHours = 4
|
||||
val hoursForDetection = sp.getInt(R.string.key_openapsama_autosens_period, defaultHours)
|
||||
val profile = profileFunction.getProfile()
|
||||
if (profile == null) {
|
||||
aapsLogger.error("No profile")
|
||||
return AutosensResult()
|
||||
}
|
||||
if (autosensDataTable.size() < 4) {
|
||||
aapsLogger.debug(LTag.AUTOSENS, "No autosens data available. lastDataTime=" + plugin.lastDataTime())
|
||||
return AutosensResult()
|
||||
}
|
||||
val current = plugin.getAutosensData(toTime) // this is running inside lock already
|
||||
if (current == null) {
|
||||
aapsLogger.debug(LTag.AUTOSENS, "No autosens data available. toTime: " + dateUtil.dateAndTimeString(toTime) + " lastDataTime: " + plugin.lastDataTime())
|
||||
return AutosensResult()
|
||||
}
|
||||
val siteChanges = MainApp.getDbHelper().getCareportalEventsFromTime(fromTime, CareportalEvent.SITECHANGE, true)
|
||||
val profileSwitches = MainApp.getDbHelper().getProfileSwitchEventsFromTime(fromTime, true)
|
||||
val deviationsArray: MutableList<Double> = ArrayList()
|
||||
var pastSensitivity = ""
|
||||
var index = 0
|
||||
while (index < autosensDataTable.size()) {
|
||||
val autosensData = autosensDataTable.valueAt(index)
|
||||
if (autosensData.time < fromTime) {
|
||||
index++
|
||||
continue
|
||||
}
|
||||
if (autosensData.time > toTime) {
|
||||
index++
|
||||
continue
|
||||
}
|
||||
|
||||
// reset deviations after site change
|
||||
if (CareportalEvent(injector).isEvent5minBack(siteChanges, autosensData.time)) {
|
||||
deviationsArray.clear()
|
||||
pastSensitivity += "(SITECHANGE)"
|
||||
}
|
||||
|
||||
// reset deviations after profile switch
|
||||
if (ProfileSwitch(injector).isEvent5minBack(profileSwitches, autosensData.time, true)) {
|
||||
deviationsArray.clear()
|
||||
pastSensitivity += "(PROFILESWITCH)"
|
||||
}
|
||||
var deviation = autosensData.deviation
|
||||
|
||||
//set positive deviations to zero if bg < 80
|
||||
if (autosensData.bg < 80 && deviation > 0) deviation = 0.0
|
||||
if (autosensData.validDeviation) if (autosensData.time > toTime - hoursForDetection * 60 * 60 * 1000L) deviationsArray.add(deviation)
|
||||
if (deviationsArray.size > hoursForDetection * 60 / 5) deviationsArray.removeAt(0)
|
||||
pastSensitivity += autosensData.pastSensitivity
|
||||
val secondsFromMidnight = Profile.secondsFromMidnight(autosensData.time)
|
||||
if (secondsFromMidnight % 3600 < 2.5 * 60 || secondsFromMidnight % 3600 > 57.5 * 60) {
|
||||
pastSensitivity += "(" + (secondsFromMidnight / 3600.0).roundToInt() + ")"
|
||||
}
|
||||
index++
|
||||
}
|
||||
val deviations = Array(deviationsArray.size) { i -> deviationsArray[i] }
|
||||
val sens = profile.isfMgdl
|
||||
val ratioLimit = ""
|
||||
val sensResult: String
|
||||
aapsLogger.debug(LTag.AUTOSENS, "Records: $index $pastSensitivity")
|
||||
Arrays.sort(deviations)
|
||||
val percentile = percentile(deviations, 0.50)
|
||||
val basalOff = percentile * (60.0 / 5.0) / sens
|
||||
val ratio = 1 + basalOff / profile.maxDailyBasal
|
||||
sensResult = when {
|
||||
percentile < 0 -> "Excess insulin sensitivity detected"
|
||||
percentile > 0 -> "Excess insulin resistance detected"
|
||||
else -> "Sensitivity normal"
|
||||
|
||||
}
|
||||
aapsLogger.debug(LTag.AUTOSENS, sensResult)
|
||||
val output = fillResult(ratio, current.cob, pastSensitivity, ratioLimit,
|
||||
sensResult, deviationsArray.size)
|
||||
aapsLogger.debug(LTag.AUTOSENS, "Sensitivity to: "
|
||||
+ dateUtil.dateAndTimeString(toTime) +
|
||||
" ratio: " + output.ratio
|
||||
+ " mealCOB: " + current.cob)
|
||||
aapsLogger.debug(LTag.AUTOSENS, "Sensitivity to: deviations " + deviations.contentToString())
|
||||
return output
|
||||
}
|
||||
|
||||
override val id: SensitivityType
|
||||
get() = SensitivityType.SENSITIVITY_AAPS
|
||||
|
||||
override fun configuration(): JSONObject {
|
||||
val c = JSONObject()
|
||||
try {
|
||||
c.put(resourceHelper.gs(R.string.key_absorption_maxtime), sp.getDouble(R.string.key_absorption_maxtime, Constants.DEFAULT_MAX_ABSORPTION_TIME))
|
||||
c.put(resourceHelper.gs(R.string.key_openapsama_autosens_period), sp.getInt(R.string.key_openapsama_autosens_period, 24))
|
||||
c.put(resourceHelper.gs(R.string.key_openapsama_autosens_max), sp.getDouble(R.string.key_openapsama_autosens_max, 1.2))
|
||||
c.put(resourceHelper.gs(R.string.key_openapsama_autosens_min), sp.getDouble(R.string.key_openapsama_autosens_min, 0.7))
|
||||
} catch (e: JSONException) {
|
||||
e.printStackTrace()
|
||||
}
|
||||
return c
|
||||
}
|
||||
|
||||
override fun applyConfiguration(configuration: JSONObject) {
|
||||
try {
|
||||
if (configuration.has(resourceHelper.gs(R.string.key_absorption_maxtime))) sp.putDouble(R.string.key_absorption_maxtime, configuration.getDouble(resourceHelper.gs(R.string.key_absorption_maxtime)))
|
||||
if (configuration.has(resourceHelper.gs(R.string.key_openapsama_autosens_period))) sp.putDouble(R.string.key_openapsama_autosens_period, configuration.getDouble(resourceHelper.gs(R.string.key_openapsama_autosens_period)))
|
||||
if (configuration.has(resourceHelper.gs(R.string.key_openapsama_autosens_max))) sp.getDouble(R.string.key_openapsama_autosens_max, configuration.getDouble(resourceHelper.gs(R.string.key_openapsama_autosens_max)))
|
||||
if (configuration.has(resourceHelper.gs(R.string.key_openapsama_autosens_min))) sp.getDouble(R.string.key_openapsama_autosens_min, configuration.getDouble(resourceHelper.gs(R.string.key_openapsama_autosens_min)))
|
||||
} catch (e: JSONException) {
|
||||
e.printStackTrace()
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,286 +0,0 @@
|
|||
package info.nightscout.androidaps.plugins.sensitivity;
|
||||
|
||||
import androidx.collection.LongSparseArray;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Singleton;
|
||||
|
||||
import dagger.android.HasAndroidInjector;
|
||||
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.db.CareportalEvent;
|
||||
import info.nightscout.androidaps.db.ProfileSwitch;
|
||||
import info.nightscout.androidaps.interfaces.IobCobCalculatorInterface;
|
||||
import info.nightscout.androidaps.interfaces.PluginDescription;
|
||||
import info.nightscout.androidaps.interfaces.PluginType;
|
||||
import info.nightscout.androidaps.interfaces.ProfileFunction;
|
||||
import info.nightscout.androidaps.logging.AAPSLogger;
|
||||
import info.nightscout.androidaps.logging.LTag;
|
||||
import info.nightscout.androidaps.plugins.aps.openAPSSMB.SMBDefaults;
|
||||
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.AutosensResult;
|
||||
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.IobCobCalculatorPlugin;
|
||||
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.data.AutosensData;
|
||||
import info.nightscout.androidaps.utils.DateUtil;
|
||||
import info.nightscout.androidaps.utils.resources.ResourceHelper;
|
||||
import info.nightscout.androidaps.utils.sharedPreferences.SP;
|
||||
|
||||
|
||||
/**
|
||||
* Created by mike on 19.06.2018.
|
||||
*/
|
||||
@Singleton
|
||||
public class SensitivityOref1Plugin extends AbstractSensitivityPlugin {
|
||||
|
||||
private final ProfileFunction profileFunction;
|
||||
private final DateUtil dateUtil;
|
||||
|
||||
@Inject
|
||||
public SensitivityOref1Plugin(
|
||||
HasAndroidInjector injector,
|
||||
AAPSLogger aapsLogger,
|
||||
ResourceHelper resourceHelper,
|
||||
SP sp,
|
||||
ProfileFunction profileFunction,
|
||||
DateUtil dateUtil
|
||||
) {
|
||||
super(new PluginDescription()
|
||||
.mainType(PluginType.SENSITIVITY)
|
||||
.pluginIcon(R.drawable.ic_generic_icon)
|
||||
.pluginName(R.string.sensitivityoref1)
|
||||
.shortName(R.string.sensitivity_shortname)
|
||||
.enableByDefault(true)
|
||||
.preferencesId(R.xml.pref_absorption_oref1)
|
||||
.description(R.string.description_sensitivity_oref1)
|
||||
.setDefault(),
|
||||
injector, aapsLogger, resourceHelper, sp
|
||||
);
|
||||
this.profileFunction = profileFunction;
|
||||
this.dateUtil = dateUtil;
|
||||
}
|
||||
|
||||
@NonNull @Override
|
||||
public AutosensResult detectSensitivity(IobCobCalculatorInterface iobCobCalculatorPlugin, long fromTime, long toTime) {
|
||||
// todo this method is called from the IobCobCalculatorPlugin, which leads to a circular
|
||||
// dependency, this should be avoided
|
||||
LongSparseArray<AutosensData> autosensDataTable = iobCobCalculatorPlugin.getAutosensDataTable();
|
||||
|
||||
Profile profile = profileFunction.getProfile();
|
||||
|
||||
if (profile == null) {
|
||||
getAapsLogger().error("No profile");
|
||||
return new AutosensResult();
|
||||
}
|
||||
|
||||
if (autosensDataTable == null || autosensDataTable.size() < 4) {
|
||||
getAapsLogger().debug(LTag.AUTOSENS, "No autosens data available. lastDataTime=" + iobCobCalculatorPlugin.lastDataTime());
|
||||
return new AutosensResult();
|
||||
}
|
||||
|
||||
// the current
|
||||
AutosensData current = iobCobCalculatorPlugin.getAutosensData(toTime); // this is running inside lock already
|
||||
if (current == null) {
|
||||
getAapsLogger().debug(LTag.AUTOSENS, "No autosens data available. toTime: " + dateUtil.dateAndTimeString(toTime) + " lastDataTime: " + iobCobCalculatorPlugin.lastDataTime());
|
||||
return new AutosensResult();
|
||||
}
|
||||
|
||||
List<CareportalEvent> siteChanges = MainApp.getDbHelper().getCareportalEventsFromTime(fromTime, CareportalEvent.SITECHANGE, true);
|
||||
List<ProfileSwitch> profileSwitches = MainApp.getDbHelper().getProfileSwitchEventsFromTime(fromTime, true);
|
||||
|
||||
//[0] = 8 hour
|
||||
//[1] = 24 hour
|
||||
//Deviationshour has DeviationsArray
|
||||
List<ArrayList<Double>> deviationsHour = Arrays.asList(new ArrayList<>(), new ArrayList<>());
|
||||
List<String> pastSensitivityArray = Arrays.asList("", "");
|
||||
List<String> sensResultArray = Arrays.asList("", "");
|
||||
List<Double> ratioArray = Arrays.asList(0d, 0d);
|
||||
List<Double> deviationCategory = Arrays.asList(96d, 288d);
|
||||
List<String> ratioLimitArray = Arrays.asList("", "");
|
||||
List<Double> hoursDetection = Arrays.asList(8d, 24d);
|
||||
|
||||
|
||||
int index = 0;
|
||||
while (index < autosensDataTable.size()) {
|
||||
AutosensData autosensData = autosensDataTable.valueAt(index);
|
||||
|
||||
if (autosensData.time < fromTime) {
|
||||
index++;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (autosensData.time > toTime) {
|
||||
index++;
|
||||
continue;
|
||||
}
|
||||
int hoursegment = 0;
|
||||
//hoursegment = 0 = 8 hour
|
||||
//hoursegment = 1 = 24 hour
|
||||
while (hoursegment < deviationsHour.size()) {
|
||||
ArrayList<Double> deviationsArray = deviationsHour.get(hoursegment);
|
||||
String pastSensitivity = pastSensitivityArray.get(hoursegment);
|
||||
|
||||
// reset deviations after site change
|
||||
if (new CareportalEvent(getInjector()).isEvent5minBack(siteChanges, autosensData.time)) {
|
||||
deviationsArray.clear();
|
||||
pastSensitivity += "(SITECHANGE)";
|
||||
}
|
||||
|
||||
// reset deviations after profile switch
|
||||
if (new ProfileSwitch(getInjector()).isEvent5minBack(profileSwitches, autosensData.time, true)) {
|
||||
deviationsArray.clear();
|
||||
pastSensitivity += "(PROFILESWITCH)";
|
||||
}
|
||||
|
||||
double deviation = autosensData.deviation;
|
||||
|
||||
//set positive deviations to zero if bg < 80
|
||||
if (autosensData.bg < 80 && deviation > 0)
|
||||
deviation = 0;
|
||||
|
||||
if (autosensData.validDeviation)
|
||||
if (autosensData.time > toTime - hoursDetection.get(hoursegment) * 60 * 60 * 1000L)
|
||||
deviationsArray.add(deviation);
|
||||
|
||||
|
||||
deviationsArray.addAll(autosensData.extraDeviation);
|
||||
|
||||
if (deviationsArray.size() > deviationCategory.get(hoursegment)) {
|
||||
deviationsArray.remove(0);
|
||||
}
|
||||
|
||||
pastSensitivity += autosensData.pastSensitivity;
|
||||
int secondsFromMidnight = Profile.secondsFromMidnight(autosensData.time);
|
||||
|
||||
if (secondsFromMidnight % 3600 < 2.5 * 60 || secondsFromMidnight % 3600 > 57.5 * 60) {
|
||||
pastSensitivity += "(" + Math.round(secondsFromMidnight / 3600d) + ")";
|
||||
}
|
||||
|
||||
//Update the data back to the parent
|
||||
deviationsHour.set(hoursegment, deviationsArray);
|
||||
pastSensitivityArray.set(hoursegment, pastSensitivity);
|
||||
hoursegment++;
|
||||
}
|
||||
index++;
|
||||
}
|
||||
|
||||
// when we have less than 8h/24 worth of deviation data, add up to 90m of zero deviations
|
||||
// this dampens any large sensitivity changes detected based on too little data, without ignoring them completely
|
||||
|
||||
for (int i = 0; i < deviationsHour.size(); i++) {
|
||||
ArrayList<Double> deviations = deviationsHour.get(i);
|
||||
getAapsLogger().debug(LTag.AUTOSENS, "Using most recent " + deviations.size() + " deviations");
|
||||
if (deviations.size() < deviationCategory.get(i)) {
|
||||
int pad = (int) Math.round((1 - (double) deviations.size() / deviationCategory.get(i)) * 18);
|
||||
getAapsLogger().debug(LTag.AUTOSENS, "Adding " + pad + " more zero deviations");
|
||||
for (int d = 0; d < pad; d++) {
|
||||
deviations.add(0d);
|
||||
}
|
||||
}
|
||||
//Update the data back to the parent
|
||||
deviationsHour.set(i, deviations);
|
||||
|
||||
}
|
||||
|
||||
int hourused = 0;
|
||||
while (hourused < deviationsHour.size()) {
|
||||
ArrayList deviationsArray = deviationsHour.get(hourused);
|
||||
String pastSensitivity = pastSensitivityArray.get(hourused);
|
||||
String sensResult = "(8 hours) ";
|
||||
if (hourused == 1) sensResult = "(24 hours) ";
|
||||
String ratioLimit = "";
|
||||
|
||||
Double[] deviations = new Double[deviationsArray.size()];
|
||||
deviations = (Double[]) deviationsArray.toArray(deviations);
|
||||
|
||||
double sens = profile.getIsfMgdl();
|
||||
|
||||
|
||||
getAapsLogger().debug(LTag.AUTOSENS, "Records: " + index + " " + pastSensitivity);
|
||||
|
||||
Arrays.sort(deviations);
|
||||
double pSensitive = IobCobCalculatorPlugin.Companion.percentile(deviations, 0.50);
|
||||
double pResistant = IobCobCalculatorPlugin.Companion.percentile(deviations, 0.50);
|
||||
|
||||
double basalOff = 0;
|
||||
|
||||
if (pSensitive < 0) { // sensitive
|
||||
basalOff = pSensitive * (60.0 / 5) / sens;
|
||||
sensResult += "Excess insulin sensitivity detected";
|
||||
} else if (pResistant > 0) { // resistant
|
||||
basalOff = pResistant * (60.0 / 5) / sens;
|
||||
sensResult += "Excess insulin resistance detected";
|
||||
} else {
|
||||
sensResult += "Sensitivity normal";
|
||||
}
|
||||
|
||||
getAapsLogger().debug(LTag.AUTOSENS, sensResult);
|
||||
|
||||
double ratio = 1 + (basalOff / profile.getMaxDailyBasal());
|
||||
|
||||
//Update the data back to the parent
|
||||
sensResultArray.set(hourused, sensResult);
|
||||
ratioArray.set(hourused, ratio);
|
||||
ratioLimitArray.set(hourused, ratioLimit);
|
||||
hourused++;
|
||||
}
|
||||
|
||||
int key = 1;
|
||||
String comparison = " 8 h ratio " + ratioArray.get(0) + " vs 24h ratio " + ratioArray.get(1);
|
||||
//use 24 hour ratio by default
|
||||
//if the 8 hour ratio is less than the 24 hour ratio, the 8 hour ratio is used
|
||||
if (ratioArray.get(0) < ratioArray.get(1)) {
|
||||
key = 0;
|
||||
}
|
||||
//String message = hoursDetection.get(key) + " of sensitivity used";
|
||||
AutosensResult output = fillResult(ratioArray.get(key), current.cob, pastSensitivityArray.get(key), ratioLimitArray.get(key),
|
||||
sensResultArray.get(key) + comparison, deviationsHour.get(key).size());
|
||||
|
||||
getAapsLogger().debug(LTag.AUTOSENS, "Sensitivity to: "
|
||||
+ dateUtil.dateAndTimeString(toTime) +
|
||||
" ratio: " + output.ratio
|
||||
+ " mealCOB: " + current.cob);
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
@NonNull @Override public JSONObject configuration() {
|
||||
JSONObject c = new JSONObject();
|
||||
try {
|
||||
c.put(getResourceHelper().gs(R.string.key_openapsama_min_5m_carbimpact), getSp().getDouble(R.string.key_openapsama_min_5m_carbimpact, SMBDefaults.min_5m_carbimpact));
|
||||
c.put(getResourceHelper().gs(R.string.key_absorption_cutoff), getSp().getDouble(R.string.key_absorption_cutoff, Constants.DEFAULT_MAX_ABSORPTION_TIME));
|
||||
c.put(getResourceHelper().gs(R.string.key_openapsama_autosens_max), getSp().getDouble(R.string.key_openapsama_autosens_max, 1.2));
|
||||
c.put(getResourceHelper().gs(R.string.key_openapsama_autosens_min), getSp().getDouble(R.string.key_openapsama_autosens_min, 0.7));
|
||||
} catch (JSONException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return c;
|
||||
}
|
||||
|
||||
@Override public void applyConfiguration(@NonNull JSONObject configuration) {
|
||||
try {
|
||||
if (configuration.has(getResourceHelper().gs(R.string.key_openapsama_min_5m_carbimpact)))
|
||||
getSp().putDouble(R.string.key_openapsama_min_5m_carbimpact, configuration.getDouble(getResourceHelper().gs(R.string.key_openapsama_min_5m_carbimpact)));
|
||||
if (configuration.has(getResourceHelper().gs(R.string.key_absorption_cutoff)))
|
||||
getSp().putDouble(R.string.key_absorption_cutoff, configuration.getDouble(getResourceHelper().gs(R.string.key_absorption_cutoff)));
|
||||
if (configuration.has(getResourceHelper().gs(R.string.key_openapsama_autosens_max)))
|
||||
getSp().getDouble(R.string.key_openapsama_autosens_max, configuration.getDouble(getResourceHelper().gs(R.string.key_openapsama_autosens_max)));
|
||||
if (configuration.has(getResourceHelper().gs(R.string.key_openapsama_autosens_min)))
|
||||
getSp().getDouble(R.string.key_openapsama_autosens_min, configuration.getDouble(getResourceHelper().gs(R.string.key_openapsama_autosens_min)));
|
||||
} catch (JSONException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
@NonNull @Override public SensitivityType getId() {
|
||||
return SensitivityType.SENSITIVITY_OREF1;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,228 @@
|
|||
package info.nightscout.androidaps.plugins.sensitivity
|
||||
|
||||
import dagger.android.HasAndroidInjector
|
||||
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.db.CareportalEvent
|
||||
import info.nightscout.androidaps.db.ProfileSwitch
|
||||
import info.nightscout.androidaps.interfaces.IobCobCalculatorInterface
|
||||
import info.nightscout.androidaps.interfaces.PluginDescription
|
||||
import info.nightscout.androidaps.interfaces.PluginType
|
||||
import info.nightscout.androidaps.interfaces.ProfileFunction
|
||||
import info.nightscout.androidaps.interfaces.SensitivityInterface.SensitivityType
|
||||
import info.nightscout.androidaps.logging.AAPSLogger
|
||||
import info.nightscout.androidaps.logging.LTag
|
||||
import info.nightscout.androidaps.plugins.aps.openAPSSMB.SMBDefaults
|
||||
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.AutosensResult
|
||||
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.IobCobCalculatorPlugin.Companion.percentile
|
||||
import info.nightscout.androidaps.utils.DateUtil
|
||||
import info.nightscout.androidaps.utils.resources.ResourceHelper
|
||||
import info.nightscout.androidaps.utils.sharedPreferences.SP
|
||||
import org.json.JSONException
|
||||
import org.json.JSONObject
|
||||
import java.util.*
|
||||
import javax.inject.Inject
|
||||
import javax.inject.Singleton
|
||||
import kotlin.math.roundToInt
|
||||
|
||||
@Singleton
|
||||
open class SensitivityOref1Plugin @Inject constructor(
|
||||
injector: HasAndroidInjector?,
|
||||
aapsLogger: AAPSLogger?,
|
||||
resourceHelper: ResourceHelper?,
|
||||
sp: SP?,
|
||||
private val profileFunction: ProfileFunction,
|
||||
private val dateUtil: DateUtil
|
||||
) : AbstractSensitivityPlugin(PluginDescription()
|
||||
.mainType(PluginType.SENSITIVITY)
|
||||
.pluginIcon(R.drawable.ic_generic_icon)
|
||||
.pluginName(R.string.sensitivityoref1)
|
||||
.shortName(R.string.sensitivity_shortname)
|
||||
.enableByDefault(true)
|
||||
.preferencesId(R.xml.pref_absorption_oref1)
|
||||
.description(R.string.description_sensitivity_oref1)
|
||||
.setDefault(),
|
||||
injector!!, aapsLogger!!, resourceHelper!!, sp!!
|
||||
) {
|
||||
|
||||
override fun detectSensitivity(plugin: IobCobCalculatorInterface, fromTime: Long, toTime: Long): AutosensResult {
|
||||
// todo this method is called from the IobCobCalculatorPlugin, which leads to a circular
|
||||
// dependency, this should be avoided
|
||||
val autosensDataTable = plugin.getAutosensDataTable()
|
||||
val profile = profileFunction.getProfile()
|
||||
if (profile == null) {
|
||||
aapsLogger.error("No profile")
|
||||
return AutosensResult()
|
||||
}
|
||||
if (autosensDataTable.size() < 4) {
|
||||
aapsLogger.debug(LTag.AUTOSENS, "No autosens data available. lastDataTime=" + plugin.lastDataTime())
|
||||
return AutosensResult()
|
||||
}
|
||||
|
||||
// the current
|
||||
val current = plugin.getAutosensData(toTime) // this is running inside lock already
|
||||
if (current == null) {
|
||||
aapsLogger.debug(LTag.AUTOSENS, "No autosens data available. toTime: " + dateUtil.dateAndTimeString(toTime) + " lastDataTime: " + plugin.lastDataTime())
|
||||
return AutosensResult()
|
||||
}
|
||||
val siteChanges = MainApp.getDbHelper().getCareportalEventsFromTime(fromTime, CareportalEvent.SITECHANGE, true)
|
||||
val profileSwitches = MainApp.getDbHelper().getProfileSwitchEventsFromTime(fromTime, true)
|
||||
|
||||
//[0] = 8 hour
|
||||
//[1] = 24 hour
|
||||
//deviationsHour has DeviationsArray
|
||||
val deviationsHour = mutableListOf(ArrayList<Double>(), ArrayList<Double>())
|
||||
val pastSensitivityArray = mutableListOf("", "")
|
||||
val sensResultArray = mutableListOf("", "")
|
||||
val ratioArray = mutableListOf(0.0, 0.0)
|
||||
val deviationCategory = listOf(96.0, 288.0)
|
||||
val ratioLimitArray = mutableListOf("", "")
|
||||
val hoursDetection = listOf(8.0, 24.0)
|
||||
var index = 0
|
||||
while (index < autosensDataTable.size()) {
|
||||
val autosensData = autosensDataTable.valueAt(index)
|
||||
if (autosensData.time < fromTime) {
|
||||
index++
|
||||
continue
|
||||
}
|
||||
if (autosensData.time > toTime) {
|
||||
index++
|
||||
continue
|
||||
}
|
||||
var hourSegment = 0
|
||||
//hourSegment = 0 = 8 hour
|
||||
//hourSegment = 1 = 24 hour
|
||||
while (hourSegment < deviationsHour.size) {
|
||||
val deviationsArray = deviationsHour[hourSegment]
|
||||
var pastSensitivity = pastSensitivityArray[hourSegment]
|
||||
|
||||
// reset deviations after site change
|
||||
if (CareportalEvent(injector).isEvent5minBack(siteChanges, autosensData.time)) {
|
||||
deviationsArray.clear()
|
||||
pastSensitivity += "(SITECHANGE)"
|
||||
}
|
||||
|
||||
// reset deviations after profile switch
|
||||
if (ProfileSwitch(injector).isEvent5minBack(profileSwitches, autosensData.time, true)) {
|
||||
deviationsArray.clear()
|
||||
pastSensitivity += "(PROFILESWITCH)"
|
||||
}
|
||||
var deviation = autosensData.deviation
|
||||
|
||||
//set positive deviations to zero if bg < 80
|
||||
if (autosensData.bg < 80 && deviation > 0) deviation = 0.0
|
||||
if (autosensData.validDeviation) if (autosensData.time > toTime - hoursDetection[hourSegment] * 60 * 60 * 1000L) deviationsArray.add(deviation)
|
||||
deviationsArray.addAll(autosensData.extraDeviation)
|
||||
if (deviationsArray.size > deviationCategory[hourSegment]) {
|
||||
deviationsArray.removeAt(0)
|
||||
}
|
||||
pastSensitivity += autosensData.pastSensitivity
|
||||
val secondsFromMidnight = Profile.secondsFromMidnight(autosensData.time)
|
||||
if (secondsFromMidnight % 3600 < 2.5 * 60 || secondsFromMidnight % 3600 > 57.5 * 60) {
|
||||
pastSensitivity += "(" + (secondsFromMidnight / 3600.0).roundToInt() + ")"
|
||||
}
|
||||
|
||||
//Update the data back to the parent
|
||||
deviationsHour[hourSegment] = deviationsArray
|
||||
pastSensitivityArray[hourSegment] = pastSensitivity
|
||||
hourSegment++
|
||||
}
|
||||
index++
|
||||
}
|
||||
|
||||
// when we have less than 8h/24 worth of deviation data, add up to 90m of zero deviations
|
||||
// this dampens any large sensitivity changes detected based on too little data, without ignoring them completely
|
||||
for (i in deviationsHour.indices) {
|
||||
val deviations = deviationsHour[i]
|
||||
aapsLogger.debug(LTag.AUTOSENS, "Using most recent " + deviations.size + " deviations")
|
||||
if (deviations.size < deviationCategory[i]) {
|
||||
val pad = ((1 - deviations.size.toDouble() / deviationCategory[i]) * 18).roundToInt()
|
||||
aapsLogger.debug(LTag.AUTOSENS, "Adding $pad more zero deviations")
|
||||
for (d in 0 until pad) {
|
||||
deviations.add(0.0)
|
||||
}
|
||||
}
|
||||
//Update the data back to the parent
|
||||
deviationsHour[i] = deviations
|
||||
}
|
||||
var hourUsed = 0
|
||||
while (hourUsed < deviationsHour.size) {
|
||||
val deviationsArray: ArrayList<Double> = deviationsHour[hourUsed]
|
||||
val pastSensitivity = pastSensitivityArray[hourUsed]
|
||||
var sensResult = "(8 hours) "
|
||||
if (hourUsed == 1) sensResult = "(24 hours) "
|
||||
val ratioLimit = ""
|
||||
val deviations: Array<Double> = Array(deviationsArray.size) { i -> deviationsArray[i] }
|
||||
val sens = profile.isfMgdl
|
||||
aapsLogger.debug(LTag.AUTOSENS, "Records: $index $pastSensitivity")
|
||||
Arrays.sort(deviations)
|
||||
val pSensitive = percentile(deviations, 0.50)
|
||||
val pResistant = percentile(deviations, 0.50)
|
||||
var basalOff = 0.0
|
||||
when {
|
||||
pSensitive < 0 -> { // sensitive
|
||||
basalOff = pSensitive * (60.0 / 5) / sens
|
||||
sensResult += "Excess insulin sensitivity detected"
|
||||
}
|
||||
|
||||
pResistant > 0 -> { // resistant
|
||||
basalOff = pResistant * (60.0 / 5) / sens
|
||||
sensResult += "Excess insulin resistance detected"
|
||||
}
|
||||
|
||||
else -> sensResult += "Sensitivity normal"
|
||||
}
|
||||
aapsLogger.debug(LTag.AUTOSENS, sensResult)
|
||||
val ratio = 1 + basalOff / profile.maxDailyBasal
|
||||
|
||||
//Update the data back to the parent
|
||||
sensResultArray[hourUsed] = sensResult
|
||||
ratioArray[hourUsed] = ratio
|
||||
ratioLimitArray[hourUsed] = ratioLimit
|
||||
hourUsed++
|
||||
}
|
||||
var key = 1
|
||||
val comparison = " 8 h ratio " + ratioArray[0] + " vs 24h ratio " + ratioArray[1]
|
||||
//use 24 hour ratio by default
|
||||
//if the 8 hour ratio is less than the 24 hour ratio, the 8 hour ratio is used
|
||||
if (ratioArray[0] < ratioArray[1]) {
|
||||
key = 0
|
||||
}
|
||||
//String message = hoursDetection.get(key) + " of sensitivity used";
|
||||
val output = fillResult(ratioArray[key], current.cob, pastSensitivityArray[key], ratioLimitArray[key], sensResultArray[key] + comparison, deviationsHour[key].size)
|
||||
aapsLogger.debug(LTag.AUTOSENS, "Sensitivity to: "
|
||||
+ dateUtil.dateAndTimeString(toTime) +
|
||||
" ratio: " + output.ratio
|
||||
+ " mealCOB: " + current.cob)
|
||||
return output
|
||||
}
|
||||
|
||||
override fun configuration(): JSONObject {
|
||||
val c = JSONObject()
|
||||
try {
|
||||
c.put(resourceHelper.gs(R.string.key_openapsama_min_5m_carbimpact), sp.getDouble(R.string.key_openapsama_min_5m_carbimpact, SMBDefaults.min_5m_carbimpact))
|
||||
c.put(resourceHelper.gs(R.string.key_absorption_cutoff), sp.getDouble(R.string.key_absorption_cutoff, Constants.DEFAULT_MAX_ABSORPTION_TIME))
|
||||
c.put(resourceHelper.gs(R.string.key_openapsama_autosens_max), sp.getDouble(R.string.key_openapsama_autosens_max, 1.2))
|
||||
c.put(resourceHelper.gs(R.string.key_openapsama_autosens_min), sp.getDouble(R.string.key_openapsama_autosens_min, 0.7))
|
||||
} catch (e: JSONException) {
|
||||
e.printStackTrace()
|
||||
}
|
||||
return c
|
||||
}
|
||||
|
||||
override fun applyConfiguration(configuration: JSONObject) {
|
||||
try {
|
||||
if (configuration.has(resourceHelper.gs(R.string.key_openapsama_min_5m_carbimpact))) sp.putDouble(R.string.key_openapsama_min_5m_carbimpact, configuration.getDouble(resourceHelper.gs(R.string.key_openapsama_min_5m_carbimpact)))
|
||||
if (configuration.has(resourceHelper.gs(R.string.key_absorption_cutoff))) sp.putDouble(R.string.key_absorption_cutoff, configuration.getDouble(resourceHelper.gs(R.string.key_absorption_cutoff)))
|
||||
if (configuration.has(resourceHelper.gs(R.string.key_openapsama_autosens_max))) sp.getDouble(R.string.key_openapsama_autosens_max, configuration.getDouble(resourceHelper.gs(R.string.key_openapsama_autosens_max)))
|
||||
if (configuration.has(resourceHelper.gs(R.string.key_openapsama_autosens_min))) sp.getDouble(R.string.key_openapsama_autosens_min, configuration.getDouble(resourceHelper.gs(R.string.key_openapsama_autosens_min)))
|
||||
} catch (e: JSONException) {
|
||||
e.printStackTrace()
|
||||
}
|
||||
}
|
||||
|
||||
override val id: SensitivityType
|
||||
get() = SensitivityType.SENSITIVITY_OREF1
|
||||
}
|
|
@ -1,240 +0,0 @@
|
|||
package info.nightscout.androidaps.plugins.sensitivity;
|
||||
|
||||
import androidx.collection.LongSparseArray;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Singleton;
|
||||
|
||||
import dagger.android.HasAndroidInjector;
|
||||
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.db.CareportalEvent;
|
||||
import info.nightscout.androidaps.db.ProfileSwitch;
|
||||
import info.nightscout.androidaps.interfaces.IobCobCalculatorInterface;
|
||||
import info.nightscout.androidaps.interfaces.PluginDescription;
|
||||
import info.nightscout.androidaps.interfaces.PluginType;
|
||||
import info.nightscout.androidaps.interfaces.ProfileFunction;
|
||||
import info.nightscout.androidaps.logging.AAPSLogger;
|
||||
import info.nightscout.androidaps.logging.LTag;
|
||||
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.AutosensResult;
|
||||
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.data.AutosensData;
|
||||
import info.nightscout.androidaps.utils.DateUtil;
|
||||
import info.nightscout.androidaps.utils.resources.ResourceHelper;
|
||||
import info.nightscout.androidaps.utils.sharedPreferences.SP;
|
||||
|
||||
/**
|
||||
* Created by mike on 24.06.2017.
|
||||
*/
|
||||
@Singleton
|
||||
public class SensitivityWeightedAveragePlugin extends AbstractSensitivityPlugin {
|
||||
|
||||
private final SP sp;
|
||||
private final DateUtil dateUtil;
|
||||
private final ProfileFunction profileFunction;
|
||||
|
||||
@Inject
|
||||
public SensitivityWeightedAveragePlugin(
|
||||
HasAndroidInjector injector,
|
||||
AAPSLogger aapsLogger,
|
||||
ResourceHelper resourceHelper,
|
||||
SP sp,
|
||||
ProfileFunction profileFunction,
|
||||
DateUtil dateUtil
|
||||
) {
|
||||
super(new PluginDescription()
|
||||
.mainType(PluginType.SENSITIVITY)
|
||||
.pluginIcon(R.drawable.ic_generic_icon)
|
||||
.pluginName(R.string.sensitivityweightedaverage)
|
||||
.shortName(R.string.sensitivity_shortname)
|
||||
.preferencesId(R.xml.pref_absorption_aaps)
|
||||
.description(R.string.description_sensitivity_weighted_average),
|
||||
injector, aapsLogger, resourceHelper, sp
|
||||
);
|
||||
this.sp = sp;
|
||||
this.dateUtil = dateUtil;
|
||||
this.profileFunction = profileFunction;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AutosensResult detectSensitivity(IobCobCalculatorInterface iobCobCalculatorPlugin, long fromTime, long toTime) {
|
||||
LongSparseArray<AutosensData> autosensDataTable = iobCobCalculatorPlugin.getAutosensDataTable();
|
||||
|
||||
String age = sp.getString(R.string.key_age, "");
|
||||
int defaultHours = 24;
|
||||
if (age.equals(getResourceHelper().gs(R.string.key_adult))) defaultHours = 24;
|
||||
if (age.equals(getResourceHelper().gs(R.string.key_teenage))) defaultHours = 4;
|
||||
if (age.equals(getResourceHelper().gs(R.string.key_child))) defaultHours = 4;
|
||||
int hoursForDetection = sp.getInt(R.string.key_openapsama_autosens_period, defaultHours);
|
||||
|
||||
if (autosensDataTable == null || autosensDataTable.size() < 4) {
|
||||
getAapsLogger().debug(LTag.AUTOSENS, "No autosens data available. lastDataTime=" + iobCobCalculatorPlugin.lastDataTime());
|
||||
return new AutosensResult();
|
||||
}
|
||||
|
||||
AutosensData current = iobCobCalculatorPlugin.getAutosensData(toTime); // this is running inside lock already
|
||||
if (current == null) {
|
||||
getAapsLogger().debug(LTag.AUTOSENS, "No autosens data available. toTime: " + dateUtil.dateAndTimeString(toTime) + " lastDataTime: " + iobCobCalculatorPlugin.lastDataTime());
|
||||
return new AutosensResult();
|
||||
}
|
||||
|
||||
|
||||
Profile profile = profileFunction.getProfile();
|
||||
if (profile == null) {
|
||||
getAapsLogger().debug(LTag.AUTOSENS, "No profile available");
|
||||
return new AutosensResult();
|
||||
}
|
||||
|
||||
List<CareportalEvent> siteChanges = MainApp.getDbHelper().getCareportalEventsFromTime(fromTime, CareportalEvent.SITECHANGE, true);
|
||||
List<ProfileSwitch> profileSwitches = MainApp.getDbHelper().getProfileSwitchEventsFromTime(fromTime, true);
|
||||
|
||||
String pastSensitivity = "";
|
||||
int index = 0;
|
||||
LongSparseArray<Double> data = new LongSparseArray<>();
|
||||
|
||||
while (index < autosensDataTable.size()) {
|
||||
AutosensData autosensData = autosensDataTable.valueAt(index);
|
||||
|
||||
if (autosensData.time < fromTime) {
|
||||
index++;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (autosensData.time > toTime) {
|
||||
index++;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (autosensData.time < toTime - hoursForDetection * 60 * 60 * 1000L) {
|
||||
index++;
|
||||
continue;
|
||||
}
|
||||
|
||||
// reset deviations after site change
|
||||
if (new CareportalEvent(getInjector()).isEvent5minBack(siteChanges, autosensData.time)) {
|
||||
data.clear();
|
||||
pastSensitivity += "(SITECHANGE)";
|
||||
}
|
||||
|
||||
// reset deviations after profile switch
|
||||
if (new ProfileSwitch(getInjector()).isEvent5minBack(profileSwitches, autosensData.time, true)) {
|
||||
data.clear();
|
||||
pastSensitivity += "(PROFILESWITCH)";
|
||||
}
|
||||
|
||||
double deviation = autosensData.deviation;
|
||||
|
||||
//set positive deviations to zero if bg < 80
|
||||
if (autosensData.bg < 80 && deviation > 0)
|
||||
deviation = 0;
|
||||
|
||||
//data.append(autosensData.time);
|
||||
long reverseWeight = (toTime - autosensData.time) / (5 * 60 * 1000L);
|
||||
if (autosensData.validDeviation)
|
||||
data.append(reverseWeight, deviation);
|
||||
//weights += reverseWeight;
|
||||
//weightedsum += reverseWeight * (autosensData.validDeviation ? autosensData.deviation : 0d);
|
||||
|
||||
|
||||
pastSensitivity += autosensData.pastSensitivity;
|
||||
int secondsFromMidnight = Profile.secondsFromMidnight(autosensData.time);
|
||||
if (secondsFromMidnight % 3600 < 2.5 * 60 || secondsFromMidnight % 3600 > 57.5 * 60) {
|
||||
pastSensitivity += "(" + Math.round(secondsFromMidnight / 3600d) + ")";
|
||||
}
|
||||
index++;
|
||||
}
|
||||
|
||||
if (data.size() == 0) {
|
||||
getAapsLogger().debug(LTag.AUTOSENS, "Data size: " + data.size() + " fromTime: " + dateUtil.dateAndTimeString(fromTime) + " toTime: " + dateUtil.dateAndTimeString(toTime));
|
||||
return new AutosensResult();
|
||||
} else {
|
||||
getAapsLogger().debug(LTag.AUTOSENS, "Data size: " + data.size() + " fromTime: " + dateUtil.dateAndTimeString(fromTime) + " toTime: " + dateUtil.dateAndTimeString(toTime));
|
||||
}
|
||||
|
||||
double weightedsum = 0;
|
||||
double weights = 0;
|
||||
|
||||
long hightestWeight = data.keyAt(data.size() - 1);
|
||||
for (int i = 0; i < data.size(); i++) {
|
||||
long reversedWeigth = data.keyAt(i);
|
||||
double value = data.valueAt(i);
|
||||
double weight = (hightestWeight - reversedWeigth) / 2.0;
|
||||
weights += weight;
|
||||
weightedsum += weight * value;
|
||||
}
|
||||
|
||||
if (weights == 0) {
|
||||
return new AutosensResult();
|
||||
}
|
||||
|
||||
double sens = profile.getIsfMgdl();
|
||||
|
||||
String ratioLimit = "";
|
||||
String sensResult;
|
||||
|
||||
getAapsLogger().debug(LTag.AUTOSENS, "Records: " + index + " " + pastSensitivity);
|
||||
|
||||
double average = weightedsum / weights;
|
||||
double basalOff = average * (60 / 5.0) / sens;
|
||||
double ratio = 1 + (basalOff / profile.getMaxDailyBasal());
|
||||
|
||||
if (average < 0) { // sensitive
|
||||
sensResult = "Excess insulin sensitivity detected";
|
||||
} else if (average > 0) { // resistant
|
||||
sensResult = "Excess insulin resistance detected";
|
||||
} else {
|
||||
sensResult = "Sensitivity normal";
|
||||
}
|
||||
|
||||
getAapsLogger().debug(LTag.AUTOSENS, sensResult);
|
||||
|
||||
AutosensResult output = fillResult(ratio, current.cob, pastSensitivity, ratioLimit,
|
||||
sensResult, data.size());
|
||||
|
||||
getAapsLogger().debug(LTag.AUTOSENS, "Sensitivity to: "
|
||||
+ dateUtil.dateAndTimeString(toTime) +
|
||||
" ratio: " + output.ratio
|
||||
+ " mealCOB: " + current.cob);
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
@NonNull @Override public SensitivityType getId() {
|
||||
return SensitivityType.SENSITIVITY_WEIGHTED;
|
||||
}
|
||||
|
||||
@NonNull @Override public JSONObject configuration() {
|
||||
JSONObject c = new JSONObject();
|
||||
try {
|
||||
c.put(getResourceHelper().gs(R.string.key_absorption_maxtime), getSp().getDouble(R.string.key_absorption_maxtime, Constants.DEFAULT_MAX_ABSORPTION_TIME));
|
||||
c.put(getResourceHelper().gs(R.string.key_openapsama_autosens_period), getSp().getInt(R.string.key_openapsama_autosens_period, 24));
|
||||
c.put(getResourceHelper().gs(R.string.key_openapsama_autosens_max), getSp().getDouble(R.string.key_openapsama_autosens_max, 1.2));
|
||||
c.put(getResourceHelper().gs(R.string.key_openapsama_autosens_min), getSp().getDouble(R.string.key_openapsama_autosens_min, 0.7));
|
||||
} catch (JSONException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return c;
|
||||
}
|
||||
|
||||
@Override public void applyConfiguration(@NonNull JSONObject configuration) {
|
||||
try {
|
||||
if (configuration.has(getResourceHelper().gs(R.string.key_absorption_maxtime)))
|
||||
getSp().putDouble(R.string.key_absorption_maxtime, configuration.getDouble(getResourceHelper().gs(R.string.key_absorption_maxtime)));
|
||||
if (configuration.has(getResourceHelper().gs(R.string.key_openapsama_autosens_period)))
|
||||
getSp().putDouble(R.string.key_openapsama_autosens_period, configuration.getDouble(getResourceHelper().gs(R.string.key_openapsama_autosens_period)));
|
||||
if (configuration.has(getResourceHelper().gs(R.string.key_openapsama_autosens_max)))
|
||||
getSp().getDouble(R.string.key_openapsama_autosens_max, configuration.getDouble(getResourceHelper().gs(R.string.key_openapsama_autosens_max)));
|
||||
if (configuration.has(getResourceHelper().gs(R.string.key_openapsama_autosens_min)))
|
||||
getSp().getDouble(R.string.key_openapsama_autosens_min, configuration.getDouble(getResourceHelper().gs(R.string.key_openapsama_autosens_min)));
|
||||
} catch (JSONException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,181 @@
|
|||
package info.nightscout.androidaps.plugins.sensitivity
|
||||
|
||||
import androidx.collection.LongSparseArray
|
||||
import dagger.android.HasAndroidInjector
|
||||
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.db.CareportalEvent
|
||||
import info.nightscout.androidaps.db.ProfileSwitch
|
||||
import info.nightscout.androidaps.interfaces.IobCobCalculatorInterface
|
||||
import info.nightscout.androidaps.interfaces.PluginDescription
|
||||
import info.nightscout.androidaps.interfaces.PluginType
|
||||
import info.nightscout.androidaps.interfaces.ProfileFunction
|
||||
import info.nightscout.androidaps.interfaces.SensitivityInterface.SensitivityType
|
||||
import info.nightscout.androidaps.logging.AAPSLogger
|
||||
import info.nightscout.androidaps.logging.LTag
|
||||
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.AutosensResult
|
||||
import info.nightscout.androidaps.utils.DateUtil
|
||||
import info.nightscout.androidaps.utils.resources.ResourceHelper
|
||||
import info.nightscout.androidaps.utils.sharedPreferences.SP
|
||||
import org.json.JSONException
|
||||
import org.json.JSONObject
|
||||
import javax.inject.Inject
|
||||
import javax.inject.Singleton
|
||||
import kotlin.math.roundToInt
|
||||
|
||||
@Singleton
|
||||
open class SensitivityWeightedAveragePlugin @Inject constructor(
|
||||
injector: HasAndroidInjector,
|
||||
aapsLogger: AAPSLogger,
|
||||
resourceHelper: ResourceHelper,
|
||||
sp: SP,
|
||||
private val profileFunction: ProfileFunction,
|
||||
private val dateUtil: DateUtil
|
||||
) : AbstractSensitivityPlugin(PluginDescription()
|
||||
.mainType(PluginType.SENSITIVITY)
|
||||
.pluginIcon(R.drawable.ic_generic_icon)
|
||||
.pluginName(R.string.sensitivityweightedaverage)
|
||||
.shortName(R.string.sensitivity_shortname)
|
||||
.preferencesId(R.xml.pref_absorption_aaps)
|
||||
.description(R.string.description_sensitivity_weighted_average),
|
||||
injector, aapsLogger, resourceHelper, sp
|
||||
) {
|
||||
|
||||
override fun detectSensitivity(plugin: IobCobCalculatorInterface, fromTime: Long, toTime: Long): AutosensResult {
|
||||
val autosensDataTable = plugin.getAutosensDataTable()
|
||||
val age = sp.getString(R.string.key_age, "")
|
||||
var defaultHours = 24
|
||||
if (age == resourceHelper.gs(R.string.key_adult)) defaultHours = 24
|
||||
if (age == resourceHelper.gs(R.string.key_teenage)) defaultHours = 4
|
||||
if (age == resourceHelper.gs(R.string.key_child)) defaultHours = 4
|
||||
val hoursForDetection = sp.getInt(R.string.key_openapsama_autosens_period, defaultHours)
|
||||
if (autosensDataTable.size() < 4) {
|
||||
aapsLogger.debug(LTag.AUTOSENS, "No autosens data available. lastDataTime=" + plugin.lastDataTime())
|
||||
return AutosensResult()
|
||||
}
|
||||
val current = plugin.getAutosensData(toTime) // this is running inside lock already
|
||||
if (current == null) {
|
||||
aapsLogger.debug(LTag.AUTOSENS, "No autosens data available. toTime: " + dateUtil.dateAndTimeString(toTime) + " lastDataTime: " + plugin.lastDataTime())
|
||||
return AutosensResult()
|
||||
}
|
||||
val profile = profileFunction.getProfile()
|
||||
if (profile == null) {
|
||||
aapsLogger.debug(LTag.AUTOSENS, "No profile available")
|
||||
return AutosensResult()
|
||||
}
|
||||
val siteChanges = MainApp.getDbHelper().getCareportalEventsFromTime(fromTime, CareportalEvent.SITECHANGE, true)
|
||||
val profileSwitches = MainApp.getDbHelper().getProfileSwitchEventsFromTime(fromTime, true)
|
||||
var pastSensitivity = ""
|
||||
var index = 0
|
||||
val data = LongSparseArray<Double>()
|
||||
while (index < autosensDataTable.size()) {
|
||||
val autosensData = autosensDataTable.valueAt(index)
|
||||
if (autosensData.time < fromTime) {
|
||||
index++
|
||||
continue
|
||||
}
|
||||
if (autosensData.time > toTime) {
|
||||
index++
|
||||
continue
|
||||
}
|
||||
if (autosensData.time < toTime - hoursForDetection * 60 * 60 * 1000L) {
|
||||
index++
|
||||
continue
|
||||
}
|
||||
|
||||
// reset deviations after site change
|
||||
if (CareportalEvent(injector).isEvent5minBack(siteChanges, autosensData.time)) {
|
||||
data.clear()
|
||||
pastSensitivity += "(SITECHANGE)"
|
||||
}
|
||||
|
||||
// reset deviations after profile switch
|
||||
if (ProfileSwitch(injector).isEvent5minBack(profileSwitches, autosensData.time, true)) {
|
||||
data.clear()
|
||||
pastSensitivity += "(PROFILESWITCH)"
|
||||
}
|
||||
var deviation = autosensData.deviation
|
||||
|
||||
//set positive deviations to zero if bg < 80
|
||||
if (autosensData.bg < 80 && deviation > 0) deviation = 0.0
|
||||
|
||||
//data.append(autosensData.time);
|
||||
val reverseWeight = (toTime - autosensData.time) / (5 * 60 * 1000L)
|
||||
if (autosensData.validDeviation) data.append(reverseWeight, deviation)
|
||||
pastSensitivity += autosensData.pastSensitivity
|
||||
val secondsFromMidnight = Profile.secondsFromMidnight(autosensData.time)
|
||||
if (secondsFromMidnight % 3600 < 2.5 * 60 || secondsFromMidnight % 3600 > 57.5 * 60) {
|
||||
pastSensitivity += "(" + (secondsFromMidnight / 3600.0).roundToInt() + ")"
|
||||
}
|
||||
index++
|
||||
}
|
||||
if (data.size() == 0) {
|
||||
aapsLogger.debug(LTag.AUTOSENS, "Data size: " + data.size() + " fromTime: " + dateUtil.dateAndTimeString(fromTime) + " toTime: " + dateUtil.dateAndTimeString(toTime))
|
||||
return AutosensResult()
|
||||
} else {
|
||||
aapsLogger.debug(LTag.AUTOSENS, "Data size: " + data.size() + " fromTime: " + dateUtil.dateAndTimeString(fromTime) + " toTime: " + dateUtil.dateAndTimeString(toTime))
|
||||
}
|
||||
var weightedSum = 0.0
|
||||
var weights = 0.0
|
||||
val highestWeight = data.keyAt(data.size() - 1)
|
||||
for (i in 0 until data.size()) {
|
||||
val reversedWeight = data.keyAt(i)
|
||||
val value = data.valueAt(i)
|
||||
val weight = (highestWeight - reversedWeight) / 2.0
|
||||
weights += weight
|
||||
weightedSum += weight * value
|
||||
}
|
||||
if (weights == 0.0) {
|
||||
return AutosensResult()
|
||||
}
|
||||
val sens = profile.isfMgdl
|
||||
val ratioLimit = ""
|
||||
val sensResult: String
|
||||
aapsLogger.debug(LTag.AUTOSENS, "Records: $index $pastSensitivity")
|
||||
val average = weightedSum / weights
|
||||
val basalOff = average * (60 / 5.0) / sens
|
||||
val ratio = 1 + basalOff / profile.maxDailyBasal
|
||||
sensResult = when {
|
||||
average < 0 -> "Excess insulin sensitivity detected"
|
||||
average > 0 -> "Excess insulin resistance detected"
|
||||
else -> "Sensitivity normal"
|
||||
}
|
||||
aapsLogger.debug(LTag.AUTOSENS, sensResult)
|
||||
val output = fillResult(ratio, current.cob, pastSensitivity, ratioLimit,
|
||||
sensResult, data.size())
|
||||
aapsLogger.debug(LTag.AUTOSENS, "Sensitivity to: "
|
||||
+ dateUtil.dateAndTimeString(toTime) +
|
||||
" ratio: " + output.ratio
|
||||
+ " mealCOB: " + current.cob)
|
||||
return output
|
||||
}
|
||||
|
||||
override val id: SensitivityType
|
||||
get() = SensitivityType.SENSITIVITY_WEIGHTED
|
||||
|
||||
override fun configuration(): JSONObject {
|
||||
val c = JSONObject()
|
||||
try {
|
||||
c.put(resourceHelper.gs(R.string.key_absorption_maxtime), sp.getDouble(R.string.key_absorption_maxtime, Constants.DEFAULT_MAX_ABSORPTION_TIME))
|
||||
c.put(resourceHelper.gs(R.string.key_openapsama_autosens_period), sp.getInt(R.string.key_openapsama_autosens_period, 24))
|
||||
c.put(resourceHelper.gs(R.string.key_openapsama_autosens_max), sp.getDouble(R.string.key_openapsama_autosens_max, 1.2))
|
||||
c.put(resourceHelper.gs(R.string.key_openapsama_autosens_min), sp.getDouble(R.string.key_openapsama_autosens_min, 0.7))
|
||||
} catch (e: JSONException) {
|
||||
e.printStackTrace()
|
||||
}
|
||||
return c
|
||||
}
|
||||
|
||||
override fun applyConfiguration(configuration: JSONObject) {
|
||||
try {
|
||||
if (configuration.has(resourceHelper.gs(R.string.key_absorption_maxtime))) sp.putDouble(R.string.key_absorption_maxtime, configuration.getDouble(resourceHelper.gs(R.string.key_absorption_maxtime)))
|
||||
if (configuration.has(resourceHelper.gs(R.string.key_openapsama_autosens_period))) sp.putDouble(R.string.key_openapsama_autosens_period, configuration.getDouble(resourceHelper.gs(R.string.key_openapsama_autosens_period)))
|
||||
if (configuration.has(resourceHelper.gs(R.string.key_openapsama_autosens_max))) sp.getDouble(R.string.key_openapsama_autosens_max, configuration.getDouble(resourceHelper.gs(R.string.key_openapsama_autosens_max)))
|
||||
if (configuration.has(resourceHelper.gs(R.string.key_openapsama_autosens_min))) sp.getDouble(R.string.key_openapsama_autosens_min, configuration.getDouble(resourceHelper.gs(R.string.key_openapsama_autosens_min)))
|
||||
} catch (e: JSONException) {
|
||||
e.printStackTrace()
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,40 +0,0 @@
|
|||
package info.nightscout.androidaps.services;
|
||||
|
||||
public interface Intents {
|
||||
// NSClient -> App
|
||||
String ACTION_NEW_TREATMENT = "info.nightscout.client.NEW_TREATMENT";
|
||||
String ACTION_CHANGED_TREATMENT = "info.nightscout.client.CHANGED_TREATMENT";
|
||||
String ACTION_REMOVED_TREATMENT = "info.nightscout.client.REMOVED_TREATMENT";
|
||||
String ACTION_NEW_PROFILE = "info.nightscout.client.NEW_PROFILE";
|
||||
String ACTION_NEW_SGV = "info.nightscout.client.NEW_SGV";
|
||||
String ACTION_NEW_MBG = "info.nightscout.client.NEW_MBG";
|
||||
String ACTION_NEW_CAL = "info.nightscout.client.NEW_CAL";
|
||||
|
||||
// xDrip -> App
|
||||
String ACTION_NEW_BG_ESTIMATE = "com.eveningoutpost.dexdrip.BgEstimate";
|
||||
String EXTRA_BG_ESTIMATE = "com.eveningoutpost.dexdrip.Extras.BgEstimate";
|
||||
String EXTRA_BG_SLOPE = "com.eveningoutpost.dexdrip.Extras.BgSlope";
|
||||
String EXTRA_BG_SLOPE_NAME = "com.eveningoutpost.dexdrip.Extras.BgSlopeName";
|
||||
String EXTRA_SENSOR_BATTERY = "com.eveningoutpost.dexdrip.Extras.SensorBattery";
|
||||
String EXTRA_TIMESTAMP = "com.eveningoutpost.dexdrip.Extras.Time";
|
||||
String EXTRA_RAW = "com.eveningoutpost.dexdrip.Extras.Raw";
|
||||
String XDRIP_DATA_SOURCE_DESCRIPTION = "com.eveningoutpost.dexdrip.Extras.SourceDesc";
|
||||
|
||||
|
||||
String ACTION_NEW_BG_ESTIMATE_NO_DATA = "com.eveningoutpost.dexdrip.BgEstimateNoData";
|
||||
|
||||
String NS_EMULATOR = "com.eveningoutpost.dexdrip.NS_EMULATOR";
|
||||
|
||||
String ACTION_REMOTE_CALIBRATION = "com.eveningoutpost.dexdrip.NewCalibration";
|
||||
|
||||
String GLIMP_BG = "it.ct.glicemia.ACTION_GLUCOSE_MEASURED";
|
||||
|
||||
String DEXCOM_BG = "com.dexcom.cgm.EXTERNAL_BROADCAST";
|
||||
String EVERSENSE_BG = "com.senseonics.AndroidAPSEventSubscriber.BROADCAST";
|
||||
|
||||
String POCTECH_BG = "com.china.poctech.data";
|
||||
String TOMATO_BG = "com.fanqies.tomatofn.BgEstimate";
|
||||
|
||||
// Broadcast status
|
||||
String AAPS_BROADCAST = "info.nightscout.androidaps.status";
|
||||
}
|
|
@ -0,0 +1,38 @@
|
|||
package info.nightscout.androidaps.services
|
||||
|
||||
@Suppress("unused")
|
||||
interface Intents {
|
||||
|
||||
companion object {
|
||||
|
||||
// NSClient -> App
|
||||
const val ACTION_NEW_TREATMENT = "info.nightscout.client.NEW_TREATMENT"
|
||||
const val ACTION_CHANGED_TREATMENT = "info.nightscout.client.CHANGED_TREATMENT"
|
||||
const val ACTION_REMOVED_TREATMENT = "info.nightscout.client.REMOVED_TREATMENT"
|
||||
const val ACTION_NEW_PROFILE = "info.nightscout.client.NEW_PROFILE"
|
||||
const val ACTION_NEW_SGV = "info.nightscout.client.NEW_SGV"
|
||||
const val ACTION_NEW_MBG = "info.nightscout.client.NEW_MBG"
|
||||
const val ACTION_NEW_CAL = "info.nightscout.client.NEW_CAL"
|
||||
|
||||
// xDrip -> App
|
||||
const val ACTION_NEW_BG_ESTIMATE = "com.eveningoutpost.dexdrip.BgEstimate"
|
||||
const val EXTRA_BG_ESTIMATE = "com.eveningoutpost.dexdrip.Extras.BgEstimate"
|
||||
const val EXTRA_BG_SLOPE = "com.eveningoutpost.dexdrip.Extras.BgSlope"
|
||||
const val EXTRA_BG_SLOPE_NAME = "com.eveningoutpost.dexdrip.Extras.BgSlopeName"
|
||||
const val EXTRA_SENSOR_BATTERY = "com.eveningoutpost.dexdrip.Extras.SensorBattery"
|
||||
const val EXTRA_TIMESTAMP = "com.eveningoutpost.dexdrip.Extras.Time"
|
||||
const val EXTRA_RAW = "com.eveningoutpost.dexdrip.Extras.Raw"
|
||||
const val XDRIP_DATA_SOURCE_DESCRIPTION = "com.eveningoutpost.dexdrip.Extras.SourceDesc"
|
||||
const val ACTION_NEW_BG_ESTIMATE_NO_DATA = "com.eveningoutpost.dexdrip.BgEstimateNoData"
|
||||
const val NS_EMULATOR = "com.eveningoutpost.dexdrip.NS_EMULATOR"
|
||||
const val ACTION_REMOTE_CALIBRATION = "com.eveningoutpost.dexdrip.NewCalibration"
|
||||
const val GLIMP_BG = "it.ct.glicemia.ACTION_GLUCOSE_MEASURED"
|
||||
const val DEXCOM_BG = "com.dexcom.cgm.EXTERNAL_BROADCAST"
|
||||
const val EVERSENSE_BG = "com.senseonics.AndroidAPSEventSubscriber.BROADCAST"
|
||||
const val POCTECH_BG = "com.china.poctech.data"
|
||||
const val TOMATO_BG = "com.fanqies.tomatofn.BgEstimate"
|
||||
|
||||
// Broadcast status
|
||||
const val AAPS_BROADCAST = "info.nightscout.androidaps.status"
|
||||
}
|
||||
}
|
|
@ -1,5 +1,6 @@
|
|||
package info.nightscout.androidaps.setupwizard;
|
||||
|
||||
// keep in java, it's easier
|
||||
public interface SWNumberValidator {
|
||||
boolean isValid(double value);
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package info.nightscout.androidaps.setupwizard;
|
||||
|
||||
// keep in java, it's easier
|
||||
public interface SWTextValidator {
|
||||
boolean isValid(String text);
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package info.nightscout.androidaps.setupwizard;
|
||||
|
||||
// keep in java, it's easier
|
||||
public interface SWValidator {
|
||||
boolean isValid();
|
||||
}
|
||||
|
|
|
@ -1,248 +0,0 @@
|
|||
package info.nightscout.androidaps.utils;
|
||||
/*
|
||||
* Copyright (C) 2008 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import android.os.SystemClock;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
|
||||
import java.net.DatagramPacket;
|
||||
import java.net.DatagramSocket;
|
||||
import java.net.InetAddress;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Singleton;
|
||||
|
||||
import info.nightscout.androidaps.logging.AAPSLogger;
|
||||
import info.nightscout.androidaps.logging.LTag;
|
||||
import info.nightscout.androidaps.logging.StacktraceLoggerWrapper;
|
||||
|
||||
/**
|
||||
* {@hide}
|
||||
* <p>
|
||||
* Simple SNTP client class for retrieving network time.
|
||||
* <p>
|
||||
* Sample usage:
|
||||
* <pre>SntpClient client = new SntpClient();
|
||||
* if (client.requestTime("time.foo.com")) {
|
||||
* long now = client.getNtpTime() + SystemClock.elapsedRealtime() - client.getNtpTimeReference();
|
||||
* }
|
||||
* </pre>
|
||||
*/
|
||||
@Singleton
|
||||
public class SntpClient {
|
||||
private final AAPSLogger aapsLogger;
|
||||
private final DateUtil dateUtil;
|
||||
|
||||
//private final int REFERENCE_TIME_OFFSET = 16;
|
||||
private final int ORIGINATE_TIME_OFFSET = 24;
|
||||
private final int RECEIVE_TIME_OFFSET = 32;
|
||||
private final int TRANSMIT_TIME_OFFSET = 40;
|
||||
private final int NTP_PACKET_SIZE = 48;
|
||||
|
||||
private final int NTP_PORT = 123;
|
||||
private final int NTP_MODE_CLIENT = 3;
|
||||
private final int NTP_VERSION = 3;
|
||||
|
||||
@Inject
|
||||
public SntpClient(
|
||||
AAPSLogger aapsLogger,
|
||||
DateUtil dateUtil
|
||||
) {
|
||||
this.aapsLogger = aapsLogger;
|
||||
this.dateUtil = dateUtil;
|
||||
}
|
||||
|
||||
// Number of seconds between Jan 1, 1900 and Jan 1, 1970
|
||||
// 70 years plus 17 leap days
|
||||
private final long OFFSET_1900_TO_1970 = ((365L * 70L) + 17L) * 24L * 60L * 60L;
|
||||
|
||||
// system time computed from NTP server response
|
||||
private long mNtpTime;
|
||||
|
||||
// value of SystemClock.elapsedRealtime() corresponding to mNtpTime
|
||||
private long mNtpTimeReference;
|
||||
|
||||
// round trip time in milliseconds
|
||||
private long mRoundTripTime;
|
||||
|
||||
public static abstract class Callback implements Runnable {
|
||||
public boolean networkConnected = false;
|
||||
public boolean success = false;
|
||||
public long time = 0;
|
||||
}
|
||||
|
||||
public synchronized void ntpTime(final Callback callback, boolean isConnected) {
|
||||
callback.networkConnected = isConnected;
|
||||
if (callback.networkConnected) {
|
||||
new Thread(() -> doNtpTime(callback)).start();
|
||||
} else {
|
||||
callback.run();
|
||||
}
|
||||
}
|
||||
|
||||
void doNtpTime(final Callback callback) {
|
||||
aapsLogger.debug("Time detection started");
|
||||
callback.success = requestTime("time.google.com", 5000);
|
||||
callback.time = getNtpTime() + SystemClock.elapsedRealtime() - getNtpTimeReference();
|
||||
aapsLogger.debug("Time detection ended: " + callback.success + " " + dateUtil.dateAndTimeString(getNtpTime()));
|
||||
callback.run();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends an SNTP request to the given host and processes the response.
|
||||
*
|
||||
* @param host host name of the server.
|
||||
* @param timeout network timeout in milliseconds.
|
||||
* @return true if the transaction was successful.
|
||||
*/
|
||||
private synchronized boolean requestTime(String host, int timeout) {
|
||||
try {
|
||||
DatagramSocket socket = new DatagramSocket();
|
||||
socket.setSoTimeout(timeout);
|
||||
InetAddress address = InetAddress.getByName(host);
|
||||
byte[] buffer = new byte[NTP_PACKET_SIZE];
|
||||
DatagramPacket request = new DatagramPacket(buffer, buffer.length, address, NTP_PORT);
|
||||
|
||||
// set mode = 3 (client) and version = 3
|
||||
// mode is in low 3 bits of first byte
|
||||
// version is in bits 3-5 of first byte
|
||||
buffer[0] = NTP_MODE_CLIENT | (NTP_VERSION << 3);
|
||||
|
||||
// get current time and write it to the request packet
|
||||
long requestTime = System.currentTimeMillis();
|
||||
long requestTicks = SystemClock.elapsedRealtime();
|
||||
writeTimeStamp(buffer, TRANSMIT_TIME_OFFSET, requestTime);
|
||||
|
||||
socket.send(request);
|
||||
|
||||
// read the response
|
||||
DatagramPacket response = new DatagramPacket(buffer, buffer.length);
|
||||
socket.receive(response);
|
||||
long responseTicks = SystemClock.elapsedRealtime();
|
||||
long responseTime = requestTime + (responseTicks - requestTicks);
|
||||
socket.close();
|
||||
|
||||
// extract the results
|
||||
long originateTime = readTimeStamp(buffer, ORIGINATE_TIME_OFFSET);
|
||||
long receiveTime = readTimeStamp(buffer, RECEIVE_TIME_OFFSET);
|
||||
long transmitTime = readTimeStamp(buffer, TRANSMIT_TIME_OFFSET);
|
||||
long roundTripTime = responseTicks - requestTicks - (transmitTime - receiveTime);
|
||||
// receiveTime = originateTime + transit + skew
|
||||
// responseTime = transmitTime + transit - skew
|
||||
// clockOffset = ((receiveTime - originateTime) + (transmitTime - responseTime))/2
|
||||
// = ((originateTime + transit + skew - originateTime) +
|
||||
// (transmitTime - (transmitTime + transit - skew)))/2
|
||||
// = ((transit + skew) + (transmitTime - transmitTime - transit + skew))/2
|
||||
// = (transit + skew - transit + skew)/2
|
||||
// = (2 * skew)/2 = skew
|
||||
long clockOffset = ((receiveTime - originateTime) + (transmitTime - responseTime)) / 2;
|
||||
// if (Config.LOGD) Log.d(TAG, "round trip: " + roundTripTime + " ms");
|
||||
// if (Config.LOGD) Log.d(TAG, "clock offset: " + clockOffset + " ms");
|
||||
|
||||
// save our results - use the times on this side of the network latency
|
||||
// (response rather than request time)
|
||||
mNtpTime = responseTime + clockOffset;
|
||||
mNtpTimeReference = responseTicks;
|
||||
mRoundTripTime = roundTripTime;
|
||||
} catch (Exception e) {
|
||||
aapsLogger.debug("request time failed: " + e);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the time computed from the NTP transaction.
|
||||
*
|
||||
* @return time value computed from NTP server response.
|
||||
*/
|
||||
private long getNtpTime() {
|
||||
return mNtpTime;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the reference clock value (value of SystemClock.elapsedRealtime())
|
||||
* corresponding to the NTP time.
|
||||
*
|
||||
* @return reference clock corresponding to the NTP time.
|
||||
*/
|
||||
private long getNtpTimeReference() {
|
||||
return mNtpTimeReference;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the round trip time of the NTP transaction
|
||||
*
|
||||
* @return round trip time in milliseconds.
|
||||
*/
|
||||
public long getRoundTripTime() {
|
||||
return mRoundTripTime;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads an unsigned 32 bit big endian number from the given offset in the buffer.
|
||||
*/
|
||||
private long read32(byte[] buffer, int offset) {
|
||||
byte b0 = buffer[offset];
|
||||
byte b1 = buffer[offset + 1];
|
||||
byte b2 = buffer[offset + 2];
|
||||
byte b3 = buffer[offset + 3];
|
||||
|
||||
// convert signed bytes to unsigned values
|
||||
int i0 = ((b0 & 0x80) == 0x80 ? (b0 & 0x7F) + 0x80 : b0);
|
||||
int i1 = ((b1 & 0x80) == 0x80 ? (b1 & 0x7F) + 0x80 : b1);
|
||||
int i2 = ((b2 & 0x80) == 0x80 ? (b2 & 0x7F) + 0x80 : b2);
|
||||
int i3 = ((b3 & 0x80) == 0x80 ? (b3 & 0x7F) + 0x80 : b3);
|
||||
|
||||
return ((long) i0 << 24) + ((long) i1 << 16) + ((long) i2 << 8) + (long) i3;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads the NTP time stamp at the given offset in the buffer and returns
|
||||
* it as a system time (milliseconds since January 1, 1970).
|
||||
*/
|
||||
private long readTimeStamp(byte[] buffer, int offset) {
|
||||
long seconds = read32(buffer, offset);
|
||||
long fraction = read32(buffer, offset + 4);
|
||||
return ((seconds - OFFSET_1900_TO_1970) * 1000) + ((fraction * 1000L) / 0x100000000L);
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes system time (milliseconds since January 1, 1970) as an NTP time stamp
|
||||
* at the given offset in the buffer.
|
||||
*/
|
||||
private void writeTimeStamp(byte[] buffer, int offset, long time) {
|
||||
long seconds = time / 1000L;
|
||||
long milliseconds = time - seconds * 1000L;
|
||||
seconds += OFFSET_1900_TO_1970;
|
||||
|
||||
// write seconds in big endian format
|
||||
buffer[offset++] = (byte) (seconds >> 24);
|
||||
buffer[offset++] = (byte) (seconds >> 16);
|
||||
buffer[offset++] = (byte) (seconds >> 8);
|
||||
buffer[offset++] = (byte) (seconds >> 0);
|
||||
|
||||
long fraction = milliseconds * 0x100000000L / 1000L;
|
||||
// write fraction in big endian format
|
||||
buffer[offset++] = (byte) (fraction >> 24);
|
||||
buffer[offset++] = (byte) (fraction >> 16);
|
||||
buffer[offset++] = (byte) (fraction >> 8);
|
||||
// low order bits should be random data
|
||||
buffer[offset++] = (byte) (Math.random() * 255.0);
|
||||
}
|
||||
}
|
214
app/src/main/java/info/nightscout/androidaps/utils/SntpClient.kt
Normal file
214
app/src/main/java/info/nightscout/androidaps/utils/SntpClient.kt
Normal file
|
@ -0,0 +1,214 @@
|
|||
package info.nightscout.androidaps.utils
|
||||
|
||||
import android.os.SystemClock
|
||||
import javax.inject.Singleton
|
||||
import javax.inject.Inject
|
||||
import info.nightscout.androidaps.logging.AAPSLogger
|
||||
import java.lang.Exception
|
||||
import java.net.DatagramPacket
|
||||
import java.net.DatagramSocket
|
||||
import java.net.InetAddress
|
||||
|
||||
/*
|
||||
* Copyright (C) 2008 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/ /**
|
||||
* {@hide}
|
||||
*
|
||||
*
|
||||
* Simple SNTP client class for retrieving network time.
|
||||
*
|
||||
*
|
||||
* Sample usage:
|
||||
* <pre>SntpClient client = new SntpClient();
|
||||
* if (client.requestTime("time.foo.com")) {
|
||||
* long now = client.getNtpTime() + SystemClock.elapsedRealtime() - client.getNtpTimeReference();
|
||||
* }
|
||||
</pre> *
|
||||
*/
|
||||
@Singleton
|
||||
class SntpClient @Inject constructor(
|
||||
private val aapsLogger: AAPSLogger,
|
||||
private val dateUtil: DateUtil
|
||||
) {
|
||||
|
||||
companion object {
|
||||
//private final int REFERENCE_TIME_OFFSET = 16;
|
||||
private const val ORIGINATE_TIME_OFFSET = 24
|
||||
private const val RECEIVE_TIME_OFFSET = 32
|
||||
private const val TRANSMIT_TIME_OFFSET = 40
|
||||
private const val NTP_PACKET_SIZE = 48
|
||||
private const val NTP_PORT = 123
|
||||
private const val NTP_MODE_CLIENT = 3
|
||||
private const val NTP_VERSION = 3
|
||||
|
||||
// Number of seconds between Jan 1, 1900 and Jan 1, 1970
|
||||
// 70 years plus 17 leap days
|
||||
private const val OFFSET_1900_TO_1970 = (365L * 70L + 17L) * 24L * 60L * 60L
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the time computed from the NTP transaction.
|
||||
*
|
||||
* @return time value computed from NTP server response.
|
||||
*/
|
||||
// system time computed from NTP server response
|
||||
private var ntpTime: Long = 0
|
||||
|
||||
/**
|
||||
* Returns the reference clock value (value of SystemClock.elapsedRealtime())
|
||||
* corresponding to the NTP time.
|
||||
*
|
||||
* @return reference clock corresponding to the NTP time.
|
||||
*/
|
||||
// value of SystemClock.elapsedRealtime() corresponding to mNtpTime
|
||||
private var ntpTimeReference: Long = 0
|
||||
|
||||
/**
|
||||
* Returns the round trip time of the NTP transaction
|
||||
*
|
||||
* @return round trip time in milliseconds.
|
||||
*/
|
||||
// round trip time in milliseconds
|
||||
private var roundTripTime: Long = 0
|
||||
|
||||
abstract class Callback : Runnable {
|
||||
|
||||
var networkConnected = false
|
||||
var success = false
|
||||
var time: Long = 0
|
||||
}
|
||||
|
||||
@Synchronized fun ntpTime(callback: Callback, isConnected: Boolean) {
|
||||
callback.networkConnected = isConnected
|
||||
if (callback.networkConnected) {
|
||||
Thread { doNtpTime(callback) }.start()
|
||||
} else {
|
||||
callback.run()
|
||||
}
|
||||
}
|
||||
|
||||
fun doNtpTime(callback: Callback) {
|
||||
aapsLogger.debug("Time detection started")
|
||||
callback.success = requestTime("time.google.com", 5000)
|
||||
callback.time = ntpTime + SystemClock.elapsedRealtime() - ntpTimeReference
|
||||
aapsLogger.debug("Time detection ended: " + callback.success + " " + dateUtil.dateAndTimeString(ntpTime))
|
||||
callback.run()
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends an SNTP request to the given host and processes the response.
|
||||
*
|
||||
* @param host host name of the server.
|
||||
* @param timeout network timeout in milliseconds.
|
||||
* @return true if the transaction was successful.
|
||||
*/
|
||||
@Suppress("SameParameterValue")
|
||||
@Synchronized private fun requestTime(host: String, timeout: Int): Boolean {
|
||||
try {
|
||||
val socket = DatagramSocket()
|
||||
socket.soTimeout = timeout
|
||||
val address = InetAddress.getByName(host)
|
||||
val buffer = ByteArray(NTP_PACKET_SIZE)
|
||||
val request = DatagramPacket(buffer, buffer.size, address, NTP_PORT)
|
||||
|
||||
// set mode = 3 (client) and version = 3
|
||||
// mode is in low 3 bits of first byte
|
||||
// version is in bits 3-5 of first byte
|
||||
buffer[0] = (NTP_MODE_CLIENT or (NTP_VERSION shl 3)).toByte()
|
||||
|
||||
// get current time and write it to the request packet
|
||||
val requestTime = System.currentTimeMillis()
|
||||
val requestTicks = SystemClock.elapsedRealtime()
|
||||
writeTimeStamp(buffer, TRANSMIT_TIME_OFFSET, requestTime)
|
||||
socket.send(request)
|
||||
|
||||
// read the response
|
||||
val response = DatagramPacket(buffer, buffer.size)
|
||||
socket.receive(response)
|
||||
val responseTicks = SystemClock.elapsedRealtime()
|
||||
val responseTime = requestTime + (responseTicks - requestTicks)
|
||||
socket.close()
|
||||
|
||||
// extract the results
|
||||
val originateTime = readTimeStamp(buffer, ORIGINATE_TIME_OFFSET)
|
||||
val receiveTime = readTimeStamp(buffer, RECEIVE_TIME_OFFSET)
|
||||
val transmitTime = readTimeStamp(buffer, TRANSMIT_TIME_OFFSET)
|
||||
val roundTripTime = responseTicks - requestTicks - (transmitTime - receiveTime)
|
||||
val clockOffset = (receiveTime - originateTime + (transmitTime - responseTime)) / 2
|
||||
|
||||
// save our results - use the times on this side of the network latency
|
||||
// (response rather than request time)
|
||||
ntpTime = responseTime + clockOffset
|
||||
ntpTimeReference = responseTicks
|
||||
this.roundTripTime = roundTripTime
|
||||
} catch (e: Exception) {
|
||||
aapsLogger.debug("request time failed: $e")
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads an unsigned 32 bit big endian number from the given offset in the buffer.
|
||||
*/
|
||||
private fun read32(buffer: ByteArray, offset: Int): Long {
|
||||
val b0 = buffer[offset]
|
||||
val b1 = buffer[offset + 1]
|
||||
val b2 = buffer[offset + 2]
|
||||
val b3 = buffer[offset + 3]
|
||||
|
||||
// convert signed bytes to unsigned values
|
||||
val i0 = if (b0.toInt() and 0x80 == 0x80) (b0.toInt() and 0x7F) + 0x80 else b0.toInt()
|
||||
val i1 = if (b1.toInt() and 0x80 == 0x80) (b1.toInt() and 0x7F) + 0x80 else b1.toInt()
|
||||
val i2 = if (b2.toInt() and 0x80 == 0x80) (b2.toInt() and 0x7F) + 0x80 else b2.toInt()
|
||||
val i3 = if (b3.toInt() and 0x80 == 0x80) (b3.toInt() and 0x7F) + 0x80 else b3.toInt()
|
||||
return (i0.toLong() shl 24) + (i1.toLong() shl 16) + (i2.toLong() shl 8) + i3.toLong()
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads the NTP time stamp at the given offset in the buffer and returns
|
||||
* it as a system time (milliseconds since January 1, 1970).
|
||||
*/
|
||||
private fun readTimeStamp(buffer: ByteArray, offset: Int): Long {
|
||||
val seconds = read32(buffer, offset)
|
||||
val fraction = read32(buffer, offset + 4)
|
||||
return (seconds - OFFSET_1900_TO_1970) * 1000 + fraction * 1000L / 0x100000000L
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes system time (milliseconds since January 1, 1970) as an NTP time stamp
|
||||
* at the given offset in the buffer.
|
||||
*/
|
||||
@Suppress("SameParameterValue")
|
||||
private fun writeTimeStamp(buffer: ByteArray, offsetParam: Int, time: Long) {
|
||||
var offset = offsetParam
|
||||
var seconds = time / 1000L
|
||||
val milliseconds = time - seconds * 1000L
|
||||
seconds += OFFSET_1900_TO_1970
|
||||
|
||||
// write seconds in big endian format
|
||||
buffer[offset++] = (seconds shr 24).toByte()
|
||||
buffer[offset++] = (seconds shr 16).toByte()
|
||||
buffer[offset++] = (seconds shr 8).toByte()
|
||||
buffer[offset++] = (seconds shr 0).toByte()
|
||||
val fraction = milliseconds * 0x100000000L / 1000L
|
||||
// write fraction in big endian format
|
||||
buffer[offset++] = (fraction shr 24).toByte()
|
||||
buffer[offset++] = (fraction shr 16).toByte()
|
||||
buffer[offset++] = (fraction shr 8).toByte()
|
||||
// low order bits should be random data
|
||||
buffer[offset] = (Math.random() * 255.0).toInt().toByte()
|
||||
}
|
||||
}
|
|
@ -2,7 +2,6 @@
|
|||
<resources>
|
||||
<!-- <string name="fi_lang" translatable="false">Finnish</string> -->
|
||||
<!-- <string name="he_lang" translatable="false">Hebrew</string> -->
|
||||
<!-- <string name="ga_lang" translatable="false">Irish</string> -->
|
||||
<!-- <string name="ja_lang" translatable="false">Japanese</string> -->
|
||||
<string name="treatmentssafety_title">Behandelings veiligheid</string>
|
||||
<string name="treatmentssafety_maxbolus_title">Maks toelaatbare Bolus [U]</string>
|
||||
|
|
|
@ -2,7 +2,6 @@
|
|||
<resources>
|
||||
<!-- <string name="fi_lang" translatable="false">Finnish</string> -->
|
||||
<!-- <string name="he_lang" translatable="false">Hebrew</string> -->
|
||||
<!-- <string name="ga_lang" translatable="false">Irish</string> -->
|
||||
<!-- <string name="ja_lang" translatable="false">Japanese</string> -->
|
||||
<string name="treatmentssafety_title">Настройки на сигурността</string>
|
||||
<string name="treatmentssafety_maxbolus_title">Максимален инсулин при болус [единици]</string>
|
||||
|
|
|
@ -2,7 +2,6 @@
|
|||
<resources>
|
||||
<!-- <string name="fi_lang" translatable="false">Finnish</string> -->
|
||||
<!-- <string name="he_lang" translatable="false">Hebrew</string> -->
|
||||
<!-- <string name="ga_lang" translatable="false">Irish</string> -->
|
||||
<!-- <string name="ja_lang" translatable="false">Japanese</string> -->
|
||||
<!-- SMS Communicator & OTP Authenticator -->
|
||||
</resources>
|
||||
|
|
|
@ -2,7 +2,6 @@
|
|||
<resources>
|
||||
<!-- <string name="fi_lang" translatable="false">Finnish</string> -->
|
||||
<!-- <string name="he_lang" translatable="false">Hebrew</string> -->
|
||||
<!-- <string name="ga_lang" translatable="false">Irish</string> -->
|
||||
<!-- <string name="ja_lang" translatable="false">Japanese</string> -->
|
||||
<string name="treatmentssafety_title">Bezpečnost zadání ošetřeni</string>
|
||||
<string name="treatmentssafety_maxbolus_title">Maximální povolený bolus [U]</string>
|
||||
|
|
|
@ -2,7 +2,6 @@
|
|||
<resources>
|
||||
<!-- <string name="fi_lang" translatable="false">Finnish</string> -->
|
||||
<!-- <string name="he_lang" translatable="false">Hebrew</string> -->
|
||||
<!-- <string name="ga_lang" translatable="false">Irish</string> -->
|
||||
<!-- <string name="ja_lang" translatable="false">Japanese</string> -->
|
||||
<!-- SMS Communicator & OTP Authenticator -->
|
||||
</resources>
|
||||
|
|
|
@ -2,7 +2,6 @@
|
|||
<resources>
|
||||
<!-- <string name="fi_lang" translatable="false">Finnish</string> -->
|
||||
<!-- <string name="he_lang" translatable="false">Hebrew</string> -->
|
||||
<!-- <string name="ga_lang" translatable="false">Irish</string> -->
|
||||
<!-- <string name="ja_lang" translatable="false">Japanese</string> -->
|
||||
<string name="treatmentssafety_title">Sicherheitseinstellungen der Behandlungen</string>
|
||||
<string name="treatmentssafety_maxbolus_title">Max. erlaubter Bolus [IE]</string>
|
||||
|
|
|
@ -2,7 +2,6 @@
|
|||
<resources>
|
||||
<!-- <string name="fi_lang" translatable="false">Finnish</string> -->
|
||||
<!-- <string name="he_lang" translatable="false">Hebrew</string> -->
|
||||
<!-- <string name="ga_lang" translatable="false">Irish</string> -->
|
||||
<!-- <string name="ja_lang" translatable="false">Japanese</string> -->
|
||||
<string name="treatmentssafety_title">Ασφάλεια Θεραπειών</string>
|
||||
<string name="treatmentssafety_maxbolus_title">Μέγιστο Επιτρεπτό bolus[U]</string>
|
||||
|
|
|
@ -2,7 +2,6 @@
|
|||
<resources>
|
||||
<!-- <string name="fi_lang" translatable="false">Finnish</string> -->
|
||||
<!-- <string name="he_lang" translatable="false">Hebrew</string> -->
|
||||
<!-- <string name="ga_lang" translatable="false">Irish</string> -->
|
||||
<!-- <string name="ja_lang" translatable="false">Japanese</string> -->
|
||||
<string name="treatmentssafety_title">Seguridad tratamientos</string>
|
||||
<string name="treatmentssafety_maxbolus_title">Máximo Bolo permitido [U]</string>
|
||||
|
|
|
@ -2,7 +2,6 @@
|
|||
<resources>
|
||||
<!-- <string name="fi_lang" translatable="false">Finnish</string> -->
|
||||
<!-- <string name="he_lang" translatable="false">Hebrew</string> -->
|
||||
<!-- <string name="ga_lang" translatable="false">Irish</string> -->
|
||||
<!-- <string name="ja_lang" translatable="false">Japanese</string> -->
|
||||
<string name="treatmentssafety_title">Traitements de sécurité</string>
|
||||
<string name="treatmentssafety_maxbolus_title">Maximum Bolus autorisé [U]</string>
|
||||
|
|
|
@ -2,7 +2,6 @@
|
|||
<resources>
|
||||
<!-- <string name="fi_lang" translatable="false">Finnish</string> -->
|
||||
<!-- <string name="he_lang" translatable="false">Hebrew</string> -->
|
||||
<!-- <string name="ga_lang" translatable="false">Irish</string> -->
|
||||
<!-- <string name="ja_lang" translatable="false">Japanese</string> -->
|
||||
<string name="nav_preferences_plugin">%1$s Sainroghanna</string>
|
||||
<string name="nav_preferences">Sainroghanna</string>
|
||||
|
|
|
@ -2,7 +2,6 @@
|
|||
<resources>
|
||||
<!-- <string name="fi_lang" translatable="false">Finnish</string> -->
|
||||
<!-- <string name="he_lang" translatable="false">Hebrew</string> -->
|
||||
<!-- <string name="ga_lang" translatable="false">Irish</string> -->
|
||||
<!-- <string name="ja_lang" translatable="false">Japanese</string> -->
|
||||
<!-- SMS Communicator & OTP Authenticator -->
|
||||
</resources>
|
||||
|
|
|
@ -2,7 +2,6 @@
|
|||
<resources>
|
||||
<!-- <string name="fi_lang" translatable="false">Finnish</string> -->
|
||||
<!-- <string name="he_lang" translatable="false">Hebrew</string> -->
|
||||
<!-- <string name="ga_lang" translatable="false">Irish</string> -->
|
||||
<!-- <string name="ja_lang" translatable="false">Japanese</string> -->
|
||||
<string name="treatmentssafety_title">Sicurezza trattamenti</string>
|
||||
<string name="treatmentssafety_maxbolus_title">Max bolo consentito [U]</string>
|
||||
|
|
|
@ -1,24 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<string name="alert_r7_description"><![CDATA[כמות: <b>%1$d%%</b>\nמשך: <b>%2$s ש\'</b>]]></string>
|
||||
<string name="alert_w31_description"><![CDATA[תכולת מיכל: <b>%1$s U</b>]]></string>
|
||||
<string name="alert_w32_description">החלף סוללה.</string>
|
||||
<string name="alert_w33_description">קבע זמן/תאריך.</string>
|
||||
<string name="alert_w34_description">צור קשר עם תמיכת Accu-Chek.</string>
|
||||
<string name="alert_w36_description"><![CDATA[<b>%1$d%%</b><br/>משך: <b>%2$s שעות</b>]]></string>
|
||||
<string name="alert_w38_description"><![CDATA[כמות מתוכננת: <b>%1$s U</b><br/>כמות שניתנה: <b>%2$s U</b>]]></string>
|
||||
<string name="alert_m20_description">הכנס מיכל.</string>
|
||||
<string name="alert_m21_description">החלף מיכל.</string>
|
||||
<string name="alert_m22_description">החלף סוללה.</string>
|
||||
<string name="alert_m23_description">בדוק סטטוס משאבה.</string>
|
||||
<string name="alert_m24_description">החלף פרפרית.</string>
|
||||
<string name="alert_m25_description">צור קשר עם תמיכת Accu-Chek.</string>
|
||||
<string name="alert_m26_description">החלף מיכל.</string>
|
||||
<string name="alert_m27_description">הפעילו מחדש את הורדת הנתונים.</string>
|
||||
<string name="alert_m28_description">בדוק סטטוס משאבה.</string>
|
||||
<string name="alert_m29_description">קבע סוג סוללה.</string>
|
||||
<string name="alert_m30_description">קבע סוג מיכל.</string>
|
||||
<string name="alert_e6_description">החלף סוללה ומיכל.</string>
|
||||
<string name="alert_e10_description">החלף מיכל.</string>
|
||||
<string name="alert_e13_description">שנה שפה.</string>
|
||||
</resources>
|
|
@ -2,7 +2,6 @@
|
|||
<resources>
|
||||
<!-- <string name="fi_lang" translatable="false">Finnish</string> -->
|
||||
<!-- <string name="he_lang" translatable="false">Hebrew</string> -->
|
||||
<!-- <string name="ga_lang" translatable="false">Irish</string> -->
|
||||
<!-- <string name="ja_lang" translatable="false">Japanese</string> -->
|
||||
<string name="treatmentssafety_title">בטיחות טיפולים</string>
|
||||
<string name="treatmentssafety_maxbolus_title">בולוס מקסימלי מותר [U]</string>
|
||||
|
|
|
@ -2,7 +2,6 @@
|
|||
<resources>
|
||||
<!-- <string name="fi_lang" translatable="false">Finnish</string> -->
|
||||
<!-- <string name="he_lang" translatable="false">Hebrew</string> -->
|
||||
<!-- <string name="ga_lang" translatable="false">Irish</string> -->
|
||||
<!-- <string name="ja_lang" translatable="false">Japanese</string> -->
|
||||
<string name="treatmentssafety_title">관리 안전설정</string>
|
||||
<string name="treatmentssafety_maxbolus_title">최대 허용 Bolus [U]</string>
|
||||
|
|
|
@ -2,7 +2,6 @@
|
|||
<resources>
|
||||
<!-- <string name="fi_lang" translatable="false">Finnish</string> -->
|
||||
<!-- <string name="he_lang" translatable="false">Hebrew</string> -->
|
||||
<!-- <string name="ga_lang" translatable="false">Irish</string> -->
|
||||
<!-- <string name="ja_lang" translatable="false">Japanese</string> -->
|
||||
<string name="treatmentssafety_title">Terapijos saugumas</string>
|
||||
<string name="treatmentssafety_maxbolus_title">Maksimalus leistinas bolusas [U]</string>
|
||||
|
|
|
@ -2,7 +2,6 @@
|
|||
<resources>
|
||||
<!-- <string name="fi_lang" translatable="false">Finnish</string> -->
|
||||
<!-- <string name="he_lang" translatable="false">Hebrew</string> -->
|
||||
<!-- <string name="ga_lang" translatable="false">Irish</string> -->
|
||||
<!-- <string name="ja_lang" translatable="false">Japanese</string> -->
|
||||
<string name="treatmentssafety_title">Behandelingen veiligheid</string>
|
||||
<string name="treatmentssafety_maxbolus_title">Max toegestane bolus [E]</string>
|
||||
|
|
|
@ -2,7 +2,6 @@
|
|||
<resources>
|
||||
<!-- <string name="fi_lang" translatable="false">Finnish</string> -->
|
||||
<!-- <string name="he_lang" translatable="false">Hebrew</string> -->
|
||||
<!-- <string name="ga_lang" translatable="false">Irish</string> -->
|
||||
<!-- <string name="ja_lang" translatable="false">Japanese</string> -->
|
||||
<string name="treatmentssafety_title">Sikkerhet ved behandlinger</string>
|
||||
<string name="treatmentssafety_maxbolus_title">Maks tillat bolus [U]</string>
|
||||
|
|
|
@ -2,7 +2,6 @@
|
|||
<resources>
|
||||
<!-- <string name="fi_lang" translatable="false">Finnish</string> -->
|
||||
<!-- <string name="he_lang" translatable="false">Hebrew</string> -->
|
||||
<!-- <string name="ga_lang" translatable="false">Irish</string> -->
|
||||
<!-- <string name="ja_lang" translatable="false">Japanese</string> -->
|
||||
<string name="treatmentssafety_title">Bezpieczeństwo leczenia</string>
|
||||
<string name="treatmentssafety_maxbolus_title">Maks. dopuszczalny bolus [U]</string>
|
||||
|
|
|
@ -2,7 +2,6 @@
|
|||
<resources>
|
||||
<!-- <string name="fi_lang" translatable="false">Finnish</string> -->
|
||||
<!-- <string name="he_lang" translatable="false">Hebrew</string> -->
|
||||
<!-- <string name="ga_lang" translatable="false">Irish</string> -->
|
||||
<!-- <string name="ja_lang" translatable="false">Japanese</string> -->
|
||||
<string name="treatmentssafety_title">Segurança do Tratamento</string>
|
||||
<string name="treatmentssafety_maxbolus_title">Máximo bolus permitido [U]</string>
|
||||
|
|
|
@ -2,7 +2,6 @@
|
|||
<resources>
|
||||
<!-- <string name="fi_lang" translatable="false">Finnish</string> -->
|
||||
<!-- <string name="he_lang" translatable="false">Hebrew</string> -->
|
||||
<!-- <string name="ga_lang" translatable="false">Irish</string> -->
|
||||
<!-- <string name="ja_lang" translatable="false">Japanese</string> -->
|
||||
<string name="treatmentssafety_title">Segurança de Tratamentos</string>
|
||||
<string name="treatmentssafety_maxbolus_title">Max bolus permitido [U]</string>
|
||||
|
@ -538,7 +537,7 @@
|
|||
<string name="overview_buttons_selection">Botões</string>
|
||||
<string name="show_calibration_button_summary">Enviar calibrações para o xDrip+ ou abrir sistema de calibração do G5</string>
|
||||
<string name="show_cgm_button_summary">Abre xDrip+, botão retorcer volta ao AAPS</string>
|
||||
<string name="carb_increment_button_message">Número de carboidratos a adicionar quando o botão é premido</string>
|
||||
<string name="carb_increment_button_message">Número de hidratos de carbono a adicionar quando o botão é premido</string>
|
||||
<string name="insulin_increment_button_message">Unidades de insulina a adicionar quando o botão é premido</string>
|
||||
<string name="error_starting_cgm">Não foi possível lançar aplicação de monitorização contínua. Por favor verifique que está instalada.</string>
|
||||
<string name="overview_cgm">CGM</string>
|
||||
|
|
|
@ -2,7 +2,6 @@
|
|||
<resources>
|
||||
<!-- <string name="fi_lang" translatable="false">Finnish</string> -->
|
||||
<!-- <string name="he_lang" translatable="false">Hebrew</string> -->
|
||||
<!-- <string name="ga_lang" translatable="false">Irish</string> -->
|
||||
<!-- <string name="ja_lang" translatable="false">Japanese</string> -->
|
||||
<string name="treatmentssafety_title">Setări siguranță tratament</string>
|
||||
<string name="treatmentssafety_maxbolus_title">Bolus maxim admis [U]</string>
|
||||
|
|
|
@ -2,7 +2,6 @@
|
|||
<resources>
|
||||
<!-- <string name="fi_lang" translatable="false">Finnish</string> -->
|
||||
<!-- <string name="he_lang" translatable="false">Hebrew</string> -->
|
||||
<!-- <string name="ga_lang" translatable="false">Irish</string> -->
|
||||
<!-- <string name="ja_lang" translatable="false">Japanese</string> -->
|
||||
<string name="treatmentssafety_title">Безопасность терапии</string>
|
||||
<string name="treatmentssafety_maxbolus_title">Макс разрешенный болюс [U] ед.</string>
|
||||
|
@ -903,4 +902,8 @@ Context | Edit Context</string>
|
|||
<string name="cannula">Катетер помпы</string>
|
||||
<string name="userentry">Запись пользователя</string>
|
||||
<string name="common_values">Введите максимальные значения вашего приема пищи \n</string>
|
||||
<string name="summary_email_for_crash_report">Этот адрес электронной почты будет привязан к отчетам о сбоях, чтобы мы могли связаться с вами в экстренных случаях. Это опция.</string>
|
||||
<string name="email_address">Адрес электронной почты</string>
|
||||
<string name="privacy_settings">Настройки конфиденцальности</string>
|
||||
<string name="privacy_summary">Вы можете указать дополнительно адрес электронной почты, если хотите получать уведомления о сбоях приложения; что является не автоматизированной рассылкой, а способом связи с разработчиками в опасных ситуациях.</string>
|
||||
</resources>
|
||||
|
|
|
@ -2,7 +2,6 @@
|
|||
<resources>
|
||||
<!-- <string name="fi_lang" translatable="false">Finnish</string> -->
|
||||
<!-- <string name="he_lang" translatable="false">Hebrew</string> -->
|
||||
<!-- <string name="ga_lang" translatable="false">Irish</string> -->
|
||||
<!-- <string name="ja_lang" translatable="false">Japanese</string> -->
|
||||
<string name="treatmentssafety_title">Bezpečnosť zadania ošetrenia</string>
|
||||
<string name="treatmentssafety_maxbolus_title">Maximálny povolený bolus [JI]</string>
|
||||
|
|
|
@ -2,7 +2,6 @@
|
|||
<resources>
|
||||
<!-- <string name="fi_lang" translatable="false">Finnish</string> -->
|
||||
<!-- <string name="he_lang" translatable="false">Hebrew</string> -->
|
||||
<!-- <string name="ga_lang" translatable="false">Irish</string> -->
|
||||
<!-- <string name="ja_lang" translatable="false">Japanese</string> -->
|
||||
<!-- SMS Communicator & OTP Authenticator -->
|
||||
</resources>
|
||||
|
|
|
@ -2,7 +2,6 @@
|
|||
<resources>
|
||||
<!-- <string name="fi_lang" translatable="false">Finnish</string> -->
|
||||
<!-- <string name="he_lang" translatable="false">Hebrew</string> -->
|
||||
<!-- <string name="ga_lang" translatable="false">Irish</string> -->
|
||||
<!-- <string name="ja_lang" translatable="false">Japanese</string> -->
|
||||
<string name="treatmentssafety_title">Säkerhetsbegränsningar</string>
|
||||
<string name="treatmentssafety_maxbolus_title">Max tillåten bolus [U]</string>
|
||||
|
|
|
@ -1,5 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<string name="alert_r7_description"><![CDATA[Miktar: <b>%1$d%%</b>\nSüre: </b>%2$s st.</b>]]></string>
|
||||
<string name="alert_w36_description"><![CDATA[Miktar: <b>%1$d%%</b><br/>Süre: <b>%2$s st.</b>]]></string>
|
||||
</resources>
|
|
@ -2,7 +2,6 @@
|
|||
<resources>
|
||||
<!-- <string name="fi_lang" translatable="false">Finnish</string> -->
|
||||
<!-- <string name="he_lang" translatable="false">Hebrew</string> -->
|
||||
<!-- <string name="ga_lang" translatable="false">Irish</string> -->
|
||||
<!-- <string name="ja_lang" translatable="false">Japanese</string> -->
|
||||
<string name="treatmentssafety_title">Tedavilerin güvenlik ayarları</string>
|
||||
<string name="treatmentssafety_maxbolus_title">Max izin verilen bolus [U]</string>
|
||||
|
|
|
@ -1,5 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<string name="alert_r7_description"><![CDATA[总数: <b>%1$d%%</b>\nDuration: <b>%2$s h</b>]]></string>
|
||||
<string name="alert_w36_description"><![CDATA[总数: <b>%1$d%%</b><br/>Duration: <b>%2$s h</b>]]></string>
|
||||
</resources>
|
|
@ -2,7 +2,6 @@
|
|||
<resources>
|
||||
<!-- <string name="fi_lang" translatable="false">Finnish</string> -->
|
||||
<!-- <string name="he_lang" translatable="false">Hebrew</string> -->
|
||||
<!-- <string name="ga_lang" translatable="false">Irish</string> -->
|
||||
<!-- <string name="ja_lang" translatable="false">Japanese</string> -->
|
||||
<string name="treatmentssafety_title">治疗安全</string>
|
||||
<string name="treatmentssafety_maxbolus_title">允许的最大大剂量值[U]</string>
|
||||
|
|
|
@ -32,6 +32,7 @@
|
|||
<item>@string/nl_lang</item>
|
||||
<item>@string/es_lang</item>
|
||||
<item>@string/el_lang</item>
|
||||
<item>@string/ga_lang</item>
|
||||
<item>@string/it_lang</item>
|
||||
<item>@string/ko_lang</item>
|
||||
<item>@string/lt_lang</item>
|
||||
|
@ -46,6 +47,7 @@
|
|||
<item>@string/tr_lang</item>
|
||||
<item>@string/zh_lang</item>
|
||||
</string-array>
|
||||
|
||||
<string-array name="languagesValues" translatable="false">
|
||||
<item>default</item>
|
||||
<item>en</item>
|
||||
|
@ -57,6 +59,7 @@
|
|||
<item>nl</item>
|
||||
<item>es</item>
|
||||
<item>el</item>
|
||||
<item>ga</item>
|
||||
<item>it</item>
|
||||
<item>ko</item>
|
||||
<item>lt</item>
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
<string name="el_lang" translatable="false">Greek</string>
|
||||
<!-- <string name="he_lang" translatable="false">Hebrew</string> -->
|
||||
<string name="zh_lang" translatable="false">Chinese</string>
|
||||
<!-- <string name="ga_lang" translatable="false">Irish</string> -->
|
||||
<string name="ga_lang" translatable="false">Irish</string>
|
||||
<string name="it_lang" translatable="false">Italian</string>
|
||||
<!-- <string name="ja_lang" translatable="false">Japanese</string> -->
|
||||
<string name="ko_lang" translatable="false">Korean</string>
|
||||
|
@ -28,6 +28,11 @@
|
|||
<string name="tr_lang" translatable="false">Turkish</string>
|
||||
|
||||
<string name="key_email_for_crash_report" translatable="false">email_for_crash_report</string>
|
||||
<string name="key_smscommunicator_settings" translatable="false">smscommunicator</string>
|
||||
<string name="key_open_humans_settings" translatable="false">open_humans</string>
|
||||
<string name="key_protection_settings" translatable="false">protection</string>
|
||||
<string name="key_absorption_category_settings" translatable="false">absorption_category_settings</string>
|
||||
<string name="key_insulin_oref_peak_settings" translatable="false">insulin_oref_peak_settings</string>
|
||||
|
||||
<string name="treatmentssafety_title">Treatments safety</string>
|
||||
<string name="treatmentssafety_maxbolus_title">Max allowed bolus [U]</string>
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||
|
||||
<PreferenceCategory
|
||||
android:key="@string/key_absorption_settings"
|
||||
android:title="@string/absorptionsettings_title"
|
||||
app:initialExpandedChildrenCount="0">
|
||||
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||
|
||||
<PreferenceCategory
|
||||
android:key="@string/key_absorption_category_settings"
|
||||
android:title="@string/absorptionsettings_title"
|
||||
app:initialExpandedChildrenCount="0">
|
||||
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
xmlns:validate="http://schemas.android.com/apk/res-auto">
|
||||
|
||||
<PreferenceCategory
|
||||
android:key="@string/key_localalert_settings"
|
||||
android:title="@string/localalertsettings_title"
|
||||
app:initialExpandedChildrenCount="0">
|
||||
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||
|
||||
<PreferenceCategory
|
||||
android:key="@string/key_bgsource_upload_settings"
|
||||
android:title="@string/bgsource_upload"
|
||||
app:initialExpandedChildrenCount="0">
|
||||
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||
|
||||
<PreferenceCategory
|
||||
android:key="@string/key_dexcom_settings"
|
||||
android:title="@string/bgsource_upload"
|
||||
app:initialExpandedChildrenCount="0">
|
||||
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
xmlns:validate="http://schemas.android.com/apk/res-auto">
|
||||
|
||||
<PreferenceCategory
|
||||
android:key="@string/key_data_choices_settings"
|
||||
android:title="@string/data_choices"
|
||||
app:initialExpandedChildrenCount="0">
|
||||
|
||||
|
|
|
@ -3,8 +3,9 @@
|
|||
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||
|
||||
<PreferenceCategory
|
||||
app:initialExpandedChildrenCount="0"
|
||||
android:title="@string/configbuilder_general">
|
||||
android:key="@string/key_configbuilder_general_settings"
|
||||
android:title="@string/configbuilder_general"
|
||||
app:initialExpandedChildrenCount="0">
|
||||
|
||||
<ListPreference
|
||||
android:defaultValue="mg/dl"
|
||||
|
@ -27,7 +28,9 @@
|
|||
android:summary="@string/patient_name_summary"
|
||||
/>
|
||||
|
||||
<PreferenceCategory android:title="@string/protection">
|
||||
<PreferenceCategory
|
||||
android:key="@string/key_protection_settings"
|
||||
android:title="@string/protection">
|
||||
|
||||
<Preference
|
||||
android:inputType="textPassword"
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
xmlns:validate="http://schemas.android.com/apk/res-auto">
|
||||
|
||||
<PreferenceCategory
|
||||
android:key="@string/key_insulin_oref_peak_settings"
|
||||
android:title="@string/insulin_oref_peak"
|
||||
app:initialExpandedChildrenCount="0">
|
||||
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
xmlns:validate="http://schemas.android.com/apk/res-auto">
|
||||
|
||||
<PreferenceCategory
|
||||
android:key="@string/key_loop_settings"
|
||||
app:initialExpandedChildrenCount="0"
|
||||
android:title="@string/loop">
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||
|
||||
<PreferenceCategory
|
||||
android:key="maintenance"
|
||||
android:key="@string/key_maintenance_settings"
|
||||
android:title="@string/maintenance_settings"
|
||||
app:initialExpandedChildrenCount="0">
|
||||
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
xmlns:validate="http://schemas.android.com/apk/res-auto">
|
||||
|
||||
<PreferenceCategory
|
||||
android:key="@string/key_nsclientinternal_settings"
|
||||
android:title="@string/nsclientinternal_title"
|
||||
app:initialExpandedChildrenCount="0">
|
||||
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
xmlns:validate="http://schemas.android.com/apk/res-auto">
|
||||
|
||||
<PreferenceCategory
|
||||
android:key="@string/key_openapsma_settings"
|
||||
android:title="@string/openapsama"
|
||||
app:initialExpandedChildrenCount="0">
|
||||
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
xmlns:validate="http://schemas.android.com/apk/res-auto">
|
||||
|
||||
<PreferenceCategory
|
||||
android:key="@string/key_openapssmb_settings"
|
||||
android:title="@string/openapssmb"
|
||||
app:initialExpandedChildrenCount="0">
|
||||
|
||||
|
|
|
@ -1,7 +1,11 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<androidx.preference.PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:validate="http://schemas.android.com/apk/res-auto">
|
||||
|
||||
<PreferenceCategory android:title="@string/open_humans">
|
||||
<PreferenceCategory
|
||||
android:key="@string/key_open_humans_settings"
|
||||
android:title="@string/open_humans">
|
||||
|
||||
<CheckBoxPreference
|
||||
android:defaultValue="true"
|
||||
|
@ -15,4 +19,4 @@
|
|||
|
||||
</PreferenceCategory>
|
||||
|
||||
</PreferenceScreen>
|
||||
</androidx.preference.PreferenceScreen>
|
|
@ -4,6 +4,7 @@
|
|||
xmlns:validate="http://schemas.android.com/apk/res-auto">
|
||||
|
||||
<PreferenceCategory
|
||||
android:key="@string/key_overview_settings"
|
||||
android:title="@string/overview"
|
||||
app:initialExpandedChildrenCount="0">
|
||||
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||
|
||||
<PreferenceCategory
|
||||
android:key="@string/key_pump_settings"
|
||||
android:title="@string/pump"
|
||||
app:initialExpandedChildrenCount="0">
|
||||
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
xmlns:validate="http://schemas.android.com/apk/res-auto">
|
||||
|
||||
<PreferenceCategory
|
||||
android:key="@string/key_treatmentssafety_settings"
|
||||
android:title="@string/treatmentssafety_title"
|
||||
app:initialExpandedChildrenCount="0">
|
||||
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
xmlns:validate="http://schemas.android.com/apk/res-auto">
|
||||
|
||||
<PreferenceCategory
|
||||
android:key="@string/key_smscommunicator_settings"
|
||||
android:title="@string/smscommunicator"
|
||||
app:initialExpandedChildrenCount="0">
|
||||
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
xmlns:validate="http://schemas.android.com/apk/res-auto">
|
||||
|
||||
<PreferenceCategory
|
||||
android:key="@string/key_tidepool_settings"
|
||||
android:title="@string/tidepool"
|
||||
app:initialExpandedChildrenCount="0">
|
||||
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||
|
||||
<PreferenceCategory
|
||||
android:key="@string/key_virtualpump_settings"
|
||||
android:title="@string/virtualpump_settings"
|
||||
app:initialExpandedChildrenCount="0">
|
||||
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||
|
||||
<PreferenceCategory
|
||||
android:key="@string/key_wear_settings"
|
||||
android:title="@string/wear_settings"
|
||||
app:initialExpandedChildrenCount="0">
|
||||
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||
|
||||
<PreferenceCategory
|
||||
android:key="@string/key_xdripstatus_settings"
|
||||
android:title="@string/xdripstatus_settings"
|
||||
app:initialExpandedChildrenCount="0">
|
||||
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
<string name="automation_missing_trigger">Merci de spécifier au moins un déclencheur.</string>
|
||||
<string name="automation_missing_action">Merci de spécifier au moins une action.</string>
|
||||
<string name="alarm_message">Alarme: %1$s</string>
|
||||
<string name="alarm_short">Alarme:</string>
|
||||
<string name="message_short">Mess :</string>
|
||||
<string name="alreadyenabled">Déjà activé</string>
|
||||
<string name="alreadydisabled">Déjà désactivé</string>
|
||||
|
@ -88,6 +89,7 @@
|
|||
<string name="glucose_u">Glycémie [%1$s] :</string>
|
||||
<string name="lastboluslabel">Lors du dernier Bolus</string>
|
||||
<string name="lastboluscompared">Heure du dernier bolus %1$s il y a %2$s min</string>
|
||||
<string name="triggercoblabel">GA</string>
|
||||
<string name="cobcompared">GA %1$s %2$.0f</string>
|
||||
<string name="iob_u">IA [U]:</string>
|
||||
<string name="distance_short">Dist [m]:</string>
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
<string name="automation_missing_trigger">Specifica almeno un trigger.</string>
|
||||
<string name="automation_missing_action">Specifica almeno un\'azione.</string>
|
||||
<string name="alarm_message">Allarme: %1$s</string>
|
||||
<string name="alarm_short">Allarme:</string>
|
||||
<string name="message_short">Msg:</string>
|
||||
<string name="alreadyenabled">Già abilitato</string>
|
||||
<string name="alreadydisabled">Già disabilitato</string>
|
||||
|
@ -88,6 +89,7 @@
|
|||
<string name="glucose_u">Glicemia [%1$s]:</string>
|
||||
<string name="lastboluslabel">Ultimo bolo</string>
|
||||
<string name="lastboluscompared">Ora ultimo bolo %1$s %2$s min fa</string>
|
||||
<string name="triggercoblabel">COB</string>
|
||||
<string name="cobcompared">COB %1$s %2$.0f</string>
|
||||
<string name="iob_u">IOB [U]:</string>
|
||||
<string name="distance_short">Dist [m]:</string>
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
<string name="automation_missing_trigger">Oppgi minst en trigger.</string>
|
||||
<string name="automation_missing_action">Oppgi minst en aksjon.</string>
|
||||
<string name="alarm_message">Alarm: %1$s</string>
|
||||
<string name="alarm_short">Alarm:</string>
|
||||
<string name="message_short">Meld:</string>
|
||||
<string name="alreadyenabled">Allerede aktivert</string>
|
||||
<string name="alreadydisabled">Allerede avslått</string>
|
||||
|
@ -88,6 +89,7 @@
|
|||
<string name="glucose_u">Glukose [%1$s]:</string>
|
||||
<string name="lastboluslabel">Siste bolus</string>
|
||||
<string name="lastboluscompared">Siste bolus for %1$s %2$s min siden</string>
|
||||
<string name="triggercoblabel">COB</string>
|
||||
<string name="cobcompared">COB %1$s %2$.0f</string>
|
||||
<string name="iob_u">IOB [U]:</string>
|
||||
<string name="distance_short">Dist [m]:</string>
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
<string name="automation_missing_trigger">Especifique pelo menos um gatilho.</string>
|
||||
<string name="automation_missing_action">Especifique pelo menos uma acção.</string>
|
||||
<string name="alarm_message">Alarme: %1$s</string>
|
||||
<string name="alarm_short">Alarme:</string>
|
||||
<string name="message_short">Mnsg:</string>
|
||||
<string name="alreadyenabled">Já activado</string>
|
||||
<string name="alreadydisabled">Já desativado</string>
|
||||
|
@ -88,6 +89,7 @@
|
|||
<string name="glucose_u">Glicose [%1$s]:</string>
|
||||
<string name="lastboluslabel">Último bolus atrás</string>
|
||||
<string name="lastboluscompared">Última vez do bolus %1$s %2$s atrás</string>
|
||||
<string name="triggercoblabel">COB</string>
|
||||
<string name="cobcompared">COB %1$s %2$.0f</string>
|
||||
<string name="iob_u">IOB [U]:</string>
|
||||
<string name="distance_short">Dist [m]:</string>
|
||||
|
|
|
@ -109,6 +109,7 @@
|
|||
<string name="preconditions">Preconditions:</string>
|
||||
<string name="automation_event">Automation event</string>
|
||||
<string name="reorder_label">Reorder</string>
|
||||
<string name="key_automation_settings" translatable="false">automation_settings</string>
|
||||
|
||||
|
||||
</resources>
|
|
@ -3,6 +3,7 @@
|
|||
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||
|
||||
<PreferenceCategory
|
||||
android:key="@string/key_automation_settings"
|
||||
android:title="@string/automation"
|
||||
app:initialExpandedChildrenCount="0">
|
||||
|
||||
|
|
|
@ -2,14 +2,14 @@
|
|||
|
||||
buildscript {
|
||||
ext {
|
||||
kotlin_version = '1.4.30'
|
||||
kotlin_version = '1.4.31'
|
||||
coreVersion = '1.3.2'
|
||||
rxjava_version = '2.2.21'
|
||||
rxandroid_version = '2.1.1'
|
||||
rxkotlin_version = '2.4.0'
|
||||
room_version = '2.2.6'
|
||||
lifecycle_version = '2.3.0'
|
||||
dagger_version = '2.32'
|
||||
dagger_version = '2.33'
|
||||
coroutinesVersion = '1.4.1'
|
||||
activityVersion = '1.2.0'
|
||||
fragmentktx_version = '1.3.0'
|
||||
|
@ -25,7 +25,7 @@ buildscript {
|
|||
work_version = '2.5.0'
|
||||
|
||||
junit_version = '4.13.2'
|
||||
mockitoVersion = '3.7.7'
|
||||
mockitoVersion = '3.8.0'
|
||||
powermockVersion = '2.0.9'
|
||||
dexmakerVersion = "1.2"
|
||||
retrofit2Version = '2.9.0'
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
<string name="description_pump_combo">Integração para bombas Accu-Chek Combo, requer ter o ruffy instalado</string>
|
||||
<string name="combo_programming_bolus">A programar bomba para administrar bólus</string>
|
||||
<string name="combo_pump_state_label">Estado</string>
|
||||
<string name="combo_pump_activity_label">Actividade</string>
|
||||
<string name="combo_no_pump_connection">Sem conexão há %1$d min</string>
|
||||
<string name="combo_tbr_remaining">%1$d%% (%2$d min restantes)</string>
|
||||
<string name="combo_pump_state_initializing">A iniciar</string>
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
<string name="description_pump_combo">Интеграция с помпой Accu-Chek Combo, требует наличия утилиты Ruffy</string>
|
||||
<string name="combo_programming_bolus">Помпа программируется для болюса</string>
|
||||
<string name="combo_pump_state_label">Состояние</string>
|
||||
<string name="combo_pump_activity_label">Нагрузка</string>
|
||||
<string name="combo_no_pump_connection">Нет связи в течение %1$d мин</string>
|
||||
<string name="combo_tbr_remaining">%1$d%% (%2$d мин осталось)</string>
|
||||
<string name="combo_pump_state_initializing">Инициализация</string>
|
||||
|
|
|
@ -1,9 +0,0 @@
|
|||
package info.nightscout.androidaps.db;
|
||||
|
||||
public interface DbObjectBase {
|
||||
|
||||
long getDate();
|
||||
|
||||
long getPumpId();
|
||||
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
package info.nightscout.androidaps.db
|
||||
|
||||
interface DbObjectBase {
|
||||
|
||||
val date: Long
|
||||
val pumpId: Long
|
||||
}
|
|
@ -1,13 +0,0 @@
|
|||
package info.nightscout.androidaps.interfaces;
|
||||
|
||||
import info.nightscout.androidaps.data.PumpEnactResult;
|
||||
|
||||
/**
|
||||
* Created by mike on 12.06.2017.
|
||||
*/
|
||||
|
||||
public interface DanaRInterface {
|
||||
PumpEnactResult loadHistory(byte type); // for history browser
|
||||
PumpEnactResult loadEvents(); // events history to build treatments from
|
||||
PumpEnactResult setUserOptions(); // like AnyDana does
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
package info.nightscout.androidaps.interfaces
|
||||
|
||||
import info.nightscout.androidaps.data.PumpEnactResult
|
||||
|
||||
interface DanaRInterface {
|
||||
|
||||
fun loadHistory(type: Byte): PumpEnactResult // for history browser
|
||||
fun loadEvents(): PumpEnactResult // events history to build treatments from
|
||||
fun setUserOptions(): PumpEnactResult // like AnyDana does
|
||||
}
|
|
@ -139,12 +139,12 @@ public class DateUtil {
|
|||
hours -= 12;
|
||||
if ((m.group(3).equals(" p.m.") || m.group(3).equals(" PM") || m.group(3).equals("PM")) && !(m.group(1).equals("12")))
|
||||
hours += 12;
|
||||
Calendar c = Calendar.getInstance();
|
||||
c.set(Calendar.HOUR_OF_DAY, hours);
|
||||
c.set(Calendar.MINUTE, minutes);
|
||||
c.set(Calendar.SECOND, 0);
|
||||
c.set(Calendar.MILLISECOND, 0);
|
||||
retval = c.getTimeInMillis();
|
||||
DateTime t = new DateTime()
|
||||
.withHourOfDay(hours)
|
||||
.withMinuteOfHour(minutes)
|
||||
.withSecondOfMinute(0)
|
||||
.withMillisOfSecond(0);
|
||||
retval = t.getMillis();
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
|
|
@ -69,6 +69,40 @@
|
|||
<string name="pairing">Сдвояване</string>
|
||||
<string name="yes">Да</string>
|
||||
<string name="no">Не</string>
|
||||
<string name="loopdisabled">LOOP Е СПРЯН ОТ ОГРАНИЧЕНИЯТА</string>
|
||||
<string name="bolusdelivered">Болус от %1$.2fЕ доставен успешно</string>
|
||||
<string name="virtualpump_resultok">ОК</string>
|
||||
<string name="novalidbasalrate">Няма валиден базал в помпата</string>
|
||||
<string name="limitingmaxiob">Ограничаване на макс. IOB до %1$.1f Е поради %2$s</string>
|
||||
<string name="unsafeusage">опасно използване</string>
|
||||
<string name="pump_unreachable">Помпата е недостъпна</string>
|
||||
<string name="extended_bolus">Удължен болус</string>
|
||||
<string name="pump_time_updated">Актуализирано време на помпата</string>
|
||||
<string name="exit">Изход</string>
|
||||
<string name="serial_number">Сериен номер</string>
|
||||
<string name="removerecord">Премахни</string>
|
||||
<string name="loopisdisabled">APS е изключен</string>
|
||||
<string name="alarm">Аларма</string>
|
||||
<string name="disableloop">Изключи Loop</string>
|
||||
<string name="enableloop">Включи Loop</string>
|
||||
<string name="resumeloop">Възстанови loop</string>
|
||||
<string name="suspendloop">Изключи APS</string>
|
||||
<string name="duration_min_label">Продължителност [мин.]</string>
|
||||
<string name="notification">Известие</string>
|
||||
<string name="noprofile">Още не е зареден профила от NS</string>
|
||||
<string name="exists">съществува</string>
|
||||
<string name="notexists">не съществува</string>
|
||||
<string name="glucose">Кръвна захар</string>
|
||||
<string name="iob">IOB</string>
|
||||
<string name="cob">СОВ</string>
|
||||
<string name="name_short">Име:</string>
|
||||
<string name="time">Време</string>
|
||||
<string name="ns_wifi_ssids">WiFi име</string>
|
||||
<string name="loading">Зареждане…</string>
|
||||
<string name="event_time_label">Време</string>
|
||||
<string name="notes_label">Бележки</string>
|
||||
<string name="remove_button">Изтрий</string>
|
||||
<string name="addnew">Добави нов</string>
|
||||
<!-- Constraints-->
|
||||
<string name="limitingbasalratio">Ограничаване на макс. базална стойност до %1$.2f Е/ч поради %2$s</string>
|
||||
<string name="pumplimit">лимит на помпата</string>
|
||||
|
@ -258,6 +292,13 @@
|
|||
<!-- Permissions -->
|
||||
<string name="alert_dialog_storage_permission_text">Рестартирайте телефона или AndroidAPS от системните настройки \nили Android APS няма да записва проблемите (което е важно за работата на алгоритъма)!</string>
|
||||
<!-- WeekdayPicker -->
|
||||
<string name="monday_short">П</string>
|
||||
<string name="tuesday_short">Вт</string>
|
||||
<string name="wednesday_short">Ср</string>
|
||||
<string name="thursday_short">Ч</string>
|
||||
<string name="friday_short">П</string>
|
||||
<string name="saturday_short">С</string>
|
||||
<string name="sunday_short">Н</string>
|
||||
<plurals name="minutes">
|
||||
<item quantity="one">%1$d минутa</item>
|
||||
<item quantity="other">%1$d минути</item>
|
||||
|
|
24
core/src/main/res/values-bg-rBG/validator.xml
Normal file
24
core/src/main/res/values-bg-rBG/validator.xml
Normal file
|
@ -0,0 +1,24 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<string name="error_only_numeric_digits_allowed">Позволени са само числа.</string>
|
||||
<string name="error_only_numeric_digits_range_allowed">Позволени са числа между %1$s - %2$s.</string>
|
||||
<string name="error_this_field_cannot_contain_special_character">Полето не може да съдържа никакви специални символи</string>
|
||||
<string name="error_only_standard_letters_are_allowed">Разрешени са само стандартни букви</string>
|
||||
<string name="error_field_must_not_be_empty">Полето не може да бъде празно</string>
|
||||
<string name="error_email_address_not_valid">Имейл адресът не е валиден</string>
|
||||
<string name="error_creditcard_number_not_valid">Номер на кредитна карта е невалиден</string>
|
||||
<string name="error_phone_not_valid">Телефонният номер не е валиден</string>
|
||||
<string name="error_domain_not_valid">Името на домейн не е валидно</string>
|
||||
<string name="error_ip_not_valid">IP адресът е невалиден</string>
|
||||
<string name="error_url_not_valid">Url адресът не е валиден</string>
|
||||
<string name="error_notvalid_personname">Не е валидно първото или последното име.</string>
|
||||
<string name="error_notvalid_personfullname">Невалидно име.</string>
|
||||
<string name="error_date_not_valid">Невалиден формат</string>
|
||||
<string name="error_mustbe4digitnumber">Трябва да е 4 цифрено число</string>
|
||||
<string name="error_mustbe6digitnumber">Трябва да е 6 цифрено число</string>
|
||||
<string name="error_mustbe12hexadidits">Трябва да са 12 символа между ABCDEF0123456789</string>
|
||||
<string name="error_mustbe8hexadidits">Трябва да са 8 символа между ABCDEF0123456789</string>
|
||||
<string name="error_mustbe4hexadidits">Трябва да са 4 символа между ABCDEF0123456789</string>
|
||||
<string name="error_not_a_minimum_length">Не е с минималната дължина</string>
|
||||
<string name="error_pin_not_valid">Пин трябва да бъде 3 до 6 цифри, не същите или в серия</string>
|
||||
</resources>
|
24
core/src/main/res/values-cs-rCZ/validator.xml
Normal file
24
core/src/main/res/values-cs-rCZ/validator.xml
Normal file
|
@ -0,0 +1,24 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<string name="error_only_numeric_digits_allowed">Jsou povoleny pouze číslice.</string>
|
||||
<string name="error_only_numeric_digits_range_allowed">Povolena jsou pouze čísla v rozsahu %1$s - %2$s.</string>
|
||||
<string name="error_this_field_cannot_contain_special_character">Toto pole nesmí obsahovat speciální znaky</string>
|
||||
<string name="error_only_standard_letters_are_allowed">Jsou povolena pouze standardní písmena</string>
|
||||
<string name="error_field_must_not_be_empty">Toto pole nesmí být prázdné</string>
|
||||
<string name="error_email_address_not_valid">E-mailová adresa je neplatná</string>
|
||||
<string name="error_creditcard_number_not_valid">Číslo kreditní karty není platné</string>
|
||||
<string name="error_phone_not_valid">Neplatné telefonní číslo</string>
|
||||
<string name="error_domain_not_valid">Název domény není platný</string>
|
||||
<string name="error_ip_not_valid">IP adresa není platná</string>
|
||||
<string name="error_url_not_valid">Adresa Url není platná</string>
|
||||
<string name="error_notvalid_personname">Neplatné jméno nebo příjmení.</string>
|
||||
<string name="error_notvalid_personfullname">Není platné celé jméno.</string>
|
||||
<string name="error_date_not_valid">Formát není platný</string>
|
||||
<string name="error_mustbe4digitnumber">Musí být čtyřmístné číslo</string>
|
||||
<string name="error_mustbe6digitnumber">Musí být šestimístné číslo</string>
|
||||
<string name="error_mustbe12hexadidits">Musí být 12 znaků ABCDEF0123456789</string>
|
||||
<string name="error_mustbe8hexadidits">Musí být 8 znaků ABCDEF0123456789</string>
|
||||
<string name="error_mustbe4hexadidits">Musí obsahovat 4 znaky ABCDEF0123456789</string>
|
||||
<string name="error_not_a_minimum_length">Není splněna minimální délka</string>
|
||||
<string name="error_pin_not_valid">Pin by měl být 3 až 6 číslic, které nesmí být stejné nebo v sériích</string>
|
||||
</resources>
|
|
@ -80,6 +80,29 @@
|
|||
<string name="pump_time_updated">Mise à jour de l\'heure de la pompe</string>
|
||||
<string name="exit">Quitter</string>
|
||||
<string name="serial_number">Numéro de série</string>
|
||||
<string name="removerecord">Supprimer l\'enregistrement</string>
|
||||
<string name="loopisdisabled">La Boucle est désactivée</string>
|
||||
<string name="alarm">Alarme</string>
|
||||
<string name="disableloop">Désactiver la Boucle</string>
|
||||
<string name="enableloop">Activer la Boucle</string>
|
||||
<string name="resumeloop">Reprendre la boucle</string>
|
||||
<string name="suspendloop">Suspendre la boucle</string>
|
||||
<string name="duration_min_label">Durée [min]</string>
|
||||
<string name="notification">Notification</string>
|
||||
<string name="noprofile">Pas encore de profil téléchargé depuis NS</string>
|
||||
<string name="exists">existe</string>
|
||||
<string name="notexists">n\'existe pas</string>
|
||||
<string name="glucose">Glycémie</string>
|
||||
<string name="iob">IA</string>
|
||||
<string name="cob">GA</string>
|
||||
<string name="name_short">Nom :</string>
|
||||
<string name="time">Heure</string>
|
||||
<string name="ns_wifi_ssids">SSID WiFi</string>
|
||||
<string name="loading">Chargement…</string>
|
||||
<string name="event_time_label">Heure événement</string>
|
||||
<string name="notes_label">Notes</string>
|
||||
<string name="remove_button">Supprimer</string>
|
||||
<string name="addnew">Ajouter</string>
|
||||
<!-- Constraints-->
|
||||
<string name="limitingbasalratio">Limiter le débit de basal max à %1$.2f U/h à cause de %2$s</string>
|
||||
<string name="pumplimit">Limite de la pompe</string>
|
||||
|
|
|
@ -80,6 +80,29 @@
|
|||
<string name="pump_time_updated">Ora del micro aggiornata</string>
|
||||
<string name="exit">Esci</string>
|
||||
<string name="serial_number">Numero seriale</string>
|
||||
<string name="removerecord">Rimuovi record</string>
|
||||
<string name="loopisdisabled">Il loop è disabilitato</string>
|
||||
<string name="alarm">Allarme</string>
|
||||
<string name="disableloop">Disabilita loop</string>
|
||||
<string name="enableloop">Abilita loop</string>
|
||||
<string name="resumeloop">Riprendi loop</string>
|
||||
<string name="suspendloop">Sospendi loop</string>
|
||||
<string name="duration_min_label">Durata [min]</string>
|
||||
<string name="notification">Notifica</string>
|
||||
<string name="noprofile">Nessun profilo ancora caricato da NS</string>
|
||||
<string name="exists">esiste</string>
|
||||
<string name="notexists">non esiste</string>
|
||||
<string name="glucose">Glicemia</string>
|
||||
<string name="iob">IOB</string>
|
||||
<string name="cob">COB</string>
|
||||
<string name="name_short">Nome:</string>
|
||||
<string name="time">Tempo</string>
|
||||
<string name="ns_wifi_ssids">WiFi SSID</string>
|
||||
<string name="loading">Caricamento…</string>
|
||||
<string name="event_time_label">Ora evento</string>
|
||||
<string name="notes_label">Note</string>
|
||||
<string name="remove_button">Rimuovi</string>
|
||||
<string name="addnew">Aggiungi nuovo</string>
|
||||
<!-- Constraints-->
|
||||
<string name="limitingbasalratio">Limitazione max velocità basale a %1$.2f U/h a causa di: %2$s</string>
|
||||
<string name="pumplimit">limite micro</string>
|
||||
|
|
24
core/src/main/res/values-it-rIT/validator.xml
Normal file
24
core/src/main/res/values-it-rIT/validator.xml
Normal file
|
@ -0,0 +1,24 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<string name="error_only_numeric_digits_allowed">Sono consentite solo cifre numeriche.</string>
|
||||
<string name="error_only_numeric_digits_range_allowed">Sono consentite solo cifre numeriche nel range %1$s - %2$s.</string>
|
||||
<string name="error_this_field_cannot_contain_special_character">Questo campo non può contenere alcun carattere speciale</string>
|
||||
<string name="error_only_standard_letters_are_allowed">Sono consentite solo lettere standard</string>
|
||||
<string name="error_field_must_not_be_empty">Il campo non deve essere vuoto</string>
|
||||
<string name="error_email_address_not_valid">Indirizzo email non valido</string>
|
||||
<string name="error_creditcard_number_not_valid">Il numero della carta di credito non è valido</string>
|
||||
<string name="error_phone_not_valid">Numero di telefono non valido</string>
|
||||
<string name="error_domain_not_valid">Nome dominio non valido</string>
|
||||
<string name="error_ip_not_valid">Indirizzo IP non valido</string>
|
||||
<string name="error_url_not_valid">L\'URL non è valido</string>
|
||||
<string name="error_notvalid_personname">Nome o Cognome non valido.</string>
|
||||
<string name="error_notvalid_personfullname">Nome completo non valido.</string>
|
||||
<string name="error_date_not_valid">Formato non valido</string>
|
||||
<string name="error_mustbe4digitnumber">Deve essere un numero di 4 cifre</string>
|
||||
<string name="error_mustbe6digitnumber">Deve essere un numero di 6 cifre</string>
|
||||
<string name="error_mustbe12hexadidits">Devono essere 12 caratteri tra ABCDEF0123456789</string>
|
||||
<string name="error_mustbe8hexadidits">Devono essere 8 caratteri tra ABCDEF0123456789</string>
|
||||
<string name="error_mustbe4hexadidits">Devono essere 4 caratteri tra ABCDEF0123456789</string>
|
||||
<string name="error_not_a_minimum_length">Lunghezza minima non soddisfatta</string>
|
||||
<string name="error_pin_not_valid">Il PIN deve contenere da 3 a 6 cifre, non uguali o in serie</string>
|
||||
</resources>
|
24
core/src/main/res/values-iw-rIL/validator.xml
Normal file
24
core/src/main/res/values-iw-rIL/validator.xml
Normal file
|
@ -0,0 +1,24 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<string name="error_only_numeric_digits_allowed">ניתן להשתמש רק בתוים מספריים.</string>
|
||||
<string name="error_only_numeric_digits_range_allowed">מותר להשתמש רק בתוים מספריים בטווח %1$s עד %2$s. </string>
|
||||
<string name="error_this_field_cannot_contain_special_character">שדה זה לא יכול להכיל תוים מיוחדים</string>
|
||||
<string name="error_only_standard_letters_are_allowed">ניתן להשתמש רק באותיות אנגליות רגילות</string>
|
||||
<string name="error_field_must_not_be_empty">שדה זה לא יכול להיות ריק</string>
|
||||
<string name="error_email_address_not_valid">כתובת הדוא\"ל אינה תקינה</string>
|
||||
<string name="error_creditcard_number_not_valid">מספר כרטיס האשראי לא תקין</string>
|
||||
<string name="error_phone_not_valid">מספר הטלפון אינו תקין</string>
|
||||
<string name="error_domain_not_valid">שם הדומיין לא תקין</string>
|
||||
<string name="error_ip_not_valid">כתובת ה-IP אינה תקינה</string>
|
||||
<string name="error_url_not_valid">כתובת ה-URL אינה תקינה</string>
|
||||
<string name="error_notvalid_personname">השם הפרטי או שם המשפחה לא תקינים.</string>
|
||||
<string name="error_notvalid_personfullname">השם המלא אינו תקין.</string>
|
||||
<string name="error_date_not_valid">הפורמט אינו תקין</string>
|
||||
<string name="error_mustbe4digitnumber">חייב להיות מספר ארבע ספרתי</string>
|
||||
<string name="error_mustbe6digitnumber">חייב להיות מספר שש ספרתי</string>
|
||||
<string name="error_mustbe12hexadidits">חייב להיות באורך 12 תוים, מהתוים הבאים: ABCDEF0123456789</string>
|
||||
<string name="error_mustbe8hexadidits">חייב להיות באורך 8 תוים, מהתוים הבאים: ABCDEF0123456789</string>
|
||||
<string name="error_mustbe4hexadidits">חייב להיות באורך 4 תוים, מהתוים הבאים: ABCDEF0123456789</string>
|
||||
<string name="error_not_a_minimum_length">לא באורך המינימלי</string>
|
||||
<string name="error_pin_not_valid">קוד ה-PIN חייב להיות באורך 3 עד 6 תוים, לא זהים ולא בסדר</string>
|
||||
</resources>
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue