Merge branch 'dev' into bw

This commit is contained in:
Milos Kozak 2019-08-27 21:36:51 +02:00 committed by GitHub
commit b9c965ac95
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
58 changed files with 953 additions and 471 deletions

View file

@ -109,7 +109,7 @@ android {
targetSdkVersion 28
multiDexEnabled true
versionCode 1500
version "2.4-dev-b"
version "2.4-dev-d"
buildConfigField "String", "VERSION", '"' + version + '"'
buildConfigField "String", "BUILDVERSION", '"' + generateGitBuild() + '-' + generateDate() + '"'
buildConfigField "String", "REMOTE", '"' + generateGitRemote() + '"'

View file

@ -153,8 +153,7 @@
<!-- Service processing incomming data -->
<service
android:name=".services.DataService"
android:exported="false"
android:permission="android.permission.BIND_JOB_SERVICE"/>
android:exported="false" />
<service
android:name=".services.LocationService"
android:exported="false" />
@ -173,7 +172,7 @@
<service
android:name=".plugins.pump.danaRS.services.DanaRSService"
android:enabled="true"
android:exported="false" />
android:exported="true" />
<service
android:name=".plugins.general.wear.wearintegration.WatchUpdaterService"
android:exported="true">
@ -240,11 +239,11 @@
<service
android:name=".plugins.general.nsclient.services.NSClientService"
android:enabled="true"
android:exported="false" />
android:exported="true" />
<service
android:name=".services.AlarmSoundService"
android:enabled="true"
android:exported="false" />
android:exported="true" />
<service
android:name=".plugins.general.overview.notifications.DismissNotificationService"
android:exported="false" />
@ -285,7 +284,7 @@
<service
android:name=".plugins.pump.medtronic.service.RileyLinkMedtronicService"
android:enabled="true"
android:exported="false" />
android:exported="true" />
<activity android:name=".plugins.pump.common.dialog.RileyLinkBLEScanActivity">
<intent-filter>
<action android:name="info.nightscout.androidaps.plugins.PumpCommon.dialog.RileyLinkBLEScanActivity" />

View file

@ -50,6 +50,11 @@ public class Constants {
public static final double defaultHypoTTmgdl = 120d;
public static final double defaultHypoTTmmol = 6.5d;
public static final double MIN_TT_MGDL = 72d;
public static final double MAX_TT_MGDL = 180d;
public static final double MIN_TT_MMOL = 4d;
public static final double MAX_TT_MMOL = 10d;
//NSClientInternal
public static final int MAX_LOG_LINES = 100;

View file

@ -165,17 +165,18 @@ public class Profile {
final JSONObject o = array.getJSONObject(index);
long tas = 0;
try {
tas = getShitfTimeSecs((int) o.getLong("timeAsSeconds"));
} catch (JSONException e) {
String time = o.getString("time");
tas = getShitfTimeSecs(DateUtil.toSeconds(time));
} catch (JSONException e) {
//log.debug(">>>>>>>>>>>> Used recalculated timeAsSecons: " + time + " " + tas);
tas = getShitfTimeSecs((int) o.getLong("timeAsSeconds"));
}
double value = o.getDouble("value") * multiplier;
sparse.put(tas, value);
} catch (JSONException e) {
} catch (Exception e) {
log.error("Unhandled exception", e);
log.error(json.toString());
FabricPrivacy.logException(e);
}
}

View file

@ -15,19 +15,15 @@ import info.nightscout.androidaps.plugins.bus.RxBus
import info.nightscout.androidaps.utils.DateUtil
import info.nightscout.androidaps.utils.FabricPrivacy
import info.nightscout.androidaps.utils.HtmlHelper
import info.nightscout.androidaps.utils.plusAssign
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.disposables.CompositeDisposable
import io.reactivex.disposables.Disposable
import kotlinx.android.synthetic.main.loop_fragment.*
class LoopFragment : Fragment() {
private var disposable: CompositeDisposable = CompositeDisposable()
operator fun CompositeDisposable.plusAssign(disposable: Disposable) {
add(disposable)
}
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?): View? {
return inflater.inflate(R.layout.loop_fragment, container, false)
@ -40,10 +36,9 @@ class LoopFragment : Fragment() {
loop_lastrun.text = MainApp.gs(R.string.executing)
Thread { LoopPlugin.getPlugin().invoke("Loop button", true) }.start()
}
updateGUI()
}
@Synchronized
override fun onResume() {
super.onResume()
disposable += RxBus
@ -64,14 +59,19 @@ class LoopFragment : Fragment() {
}, {
FabricPrivacy.logException(it)
})
updateGUI()
}
@Synchronized
override fun onPause() {
super.onPause()
disposable.clear()
}
@Synchronized
fun updateGUI() {
if (loop_request == null) return
LoopPlugin.lastRun?.let {
loop_request.text = it.request?.toSpanned() ?: ""
loop_constraintsprocessed.text = it.constraintsProcessed?.toSpanned() ?: ""
@ -96,7 +96,9 @@ class LoopFragment : Fragment() {
}
}
@Synchronized
private fun clearGUI() {
if (loop_request == null) return
loop_request.text = ""
loop_constraints.text = ""
loop_constraintsprocessed.text = ""

View file

@ -416,7 +416,7 @@ public class LoopPlugin extends PluginBase {
.setAutoCancel(true)
.setPriority(Notification.PRIORITY_HIGH)
.setCategory(Notification.CATEGORY_ALARM)
.setVisibility(Notification.VISIBILITY_PUBLIC);
.setVisibility(NotificationCompat.VISIBILITY_PUBLIC);
if (SP.getBoolean("wearcontrol", false)) {
builder.setLocalOnly(true);
}

View file

@ -15,9 +15,9 @@ import info.nightscout.androidaps.plugins.bus.RxBus
import info.nightscout.androidaps.utils.DateUtil
import info.nightscout.androidaps.utils.FabricPrivacy
import info.nightscout.androidaps.utils.JSONFormatter
import info.nightscout.androidaps.utils.plusAssign
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.disposables.CompositeDisposable
import io.reactivex.disposables.Disposable
import kotlinx.android.synthetic.main.openapsama_fragment.*
import org.json.JSONArray
import org.json.JSONException
@ -27,10 +27,6 @@ class OpenAPSAMAFragment : Fragment() {
private val log = LoggerFactory.getLogger(L.APS)
private var disposable: CompositeDisposable = CompositeDisposable()
operator fun CompositeDisposable.plusAssign(disposable: Disposable) {
add(disposable)
}
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?): View? {
return inflater.inflate(R.layout.openapsama_fragment, container, false)
@ -42,10 +38,9 @@ class OpenAPSAMAFragment : Fragment() {
openapsma_run.setOnClickListener {
OpenAPSAMAPlugin.getPlugin().invoke("OpenAPSAMA button", false)
}
updateGUI()
}
@Synchronized
override fun onResume() {
super.onResume()
@ -65,14 +60,19 @@ class OpenAPSAMAFragment : Fragment() {
}, {
FabricPrivacy.logException(it)
})
updateGUI()
}
@Synchronized
override fun onPause() {
super.onPause()
disposable.clear()
}
@Synchronized
private fun updateGUI() {
if (openapsma_result == null) return
OpenAPSAMAPlugin.getPlugin().lastAPSResult?.let { lastAPSResult ->
openapsma_result.text = JSONFormatter.format(lastAPSResult.json)
openapsma_request.text = lastAPSResult.toSpanned()

View file

@ -13,9 +13,9 @@ import info.nightscout.androidaps.plugins.bus.RxBus
import info.nightscout.androidaps.utils.DateUtil
import info.nightscout.androidaps.utils.FabricPrivacy
import info.nightscout.androidaps.utils.JSONFormatter
import info.nightscout.androidaps.utils.plusAssign
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.disposables.CompositeDisposable
import io.reactivex.disposables.Disposable
import kotlinx.android.synthetic.main.openapsama_fragment.*
import org.slf4j.LoggerFactory
@ -23,10 +23,6 @@ class OpenAPSMAFragment : Fragment() {
private val log = LoggerFactory.getLogger(L.APS)
private var disposable: CompositeDisposable = CompositeDisposable()
operator fun CompositeDisposable.plusAssign(disposable: Disposable) {
add(disposable)
}
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?): View? {
return inflater.inflate(R.layout.openapsma_fragment, container, false)
@ -39,9 +35,9 @@ class OpenAPSMAFragment : Fragment() {
OpenAPSMAPlugin.getPlugin().invoke("OpenAPSMA button", false)
}
updateGUI()
}
@Synchronized
override fun onResume() {
super.onResume()
@ -61,14 +57,18 @@ class OpenAPSMAFragment : Fragment() {
}, {
FabricPrivacy.logException(it)
})
updateGUI()
}
@Synchronized
override fun onPause() {
super.onPause()
disposable.clear()
}
fun updateGUI() {
@Synchronized
private fun updateGUI() {
if (openapsma_result == null) return
OpenAPSMAPlugin.getPlugin().lastAPSResult?.let { lastAPSResult ->
openapsma_result.text = JSONFormatter.format(lastAPSResult.json)
openapsma_request.text = lastAPSResult.toSpanned()
@ -85,7 +85,9 @@ class OpenAPSMAFragment : Fragment() {
}
}
@Synchronized
private fun updateResultGUI(text: String) {
if (openapsma_result == null) return
openapsma_result.text = text
openapsma_glucosestatus.text = ""
openapsma_currenttemp.text = ""

View file

@ -1,5 +1,6 @@
package info.nightscout.androidaps.plugins.aps.openAPSSMB
import android.annotation.SuppressLint
import android.os.Bundle
import android.text.TextUtils
import android.view.LayoutInflater
@ -15,9 +16,9 @@ import info.nightscout.androidaps.plugins.bus.RxBus
import info.nightscout.androidaps.utils.DateUtil
import info.nightscout.androidaps.utils.FabricPrivacy
import info.nightscout.androidaps.utils.JSONFormatter
import info.nightscout.androidaps.utils.plusAssign
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.disposables.CompositeDisposable
import io.reactivex.disposables.Disposable
import kotlinx.android.synthetic.main.openapsama_fragment.*
import org.json.JSONArray
import org.json.JSONException
@ -27,10 +28,6 @@ class OpenAPSSMBFragment : Fragment() {
private val log = LoggerFactory.getLogger(L.APS)
private var disposable: CompositeDisposable = CompositeDisposable()
operator fun CompositeDisposable.plusAssign(disposable: Disposable) {
add(disposable)
}
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?): View? {
return inflater.inflate(R.layout.openapsama_fragment, container, false)
@ -42,10 +39,9 @@ class OpenAPSSMBFragment : Fragment() {
openapsma_run.setOnClickListener {
OpenAPSSMBPlugin.getPlugin().invoke("OpenAPSSMB button", false)
}
updateGUI()
}
@Synchronized
override fun onResume() {
super.onResume()
disposable += RxBus
@ -64,14 +60,19 @@ class OpenAPSSMBFragment : Fragment() {
}, {
FabricPrivacy.logException(it)
})
updateGUI()
}
@Synchronized
override fun onPause() {
super.onPause()
disposable.clear()
}
@Synchronized
fun updateGUI() {
if (openapsma_result == null) return
val plugin = OpenAPSSMBPlugin.getPlugin()
plugin.lastAPSResult?.let { lastAPSResult ->
openapsma_result.text = JSONFormatter.format(lastAPSResult.json)
@ -85,6 +86,7 @@ class OpenAPSSMBFragment : Fragment() {
openapsma_iobdata.text = TextUtils.concat(String.format(MainApp.gs(R.string.array_of_elements), iobArray.length()) + "\n", JSONFormatter.format(iobArray.getString(0)))
} catch (e: JSONException) {
log.error("Unhandled exception", e)
@SuppressLint("SetTextl18n")
openapsma_iobdata.text = "JSONException see log for details"
}
@ -103,7 +105,9 @@ class OpenAPSSMBFragment : Fragment() {
}
}
@Synchronized
private fun updateResultGUI(text: String) {
if (openapsma_result == null) return
openapsma_result.text = text
openapsma_glucosestatus.text = ""
openapsma_currenttemp.text = ""

View file

@ -44,10 +44,9 @@ class ConfigBuilderFragment : Fragment() {
unlock.visibility = View.GONE
}, null)
}
updateGUI()
}
@Synchronized
override fun onResume() {
super.onResume()
disposable.add(RxBus
@ -58,13 +57,16 @@ class ConfigBuilderFragment : Fragment() {
}, {
FabricPrivacy.logException(it)
}))
updateGUI()
}
@Synchronized
override fun onPause() {
super.onPause()
disposable.clear()
}
@Synchronized
private fun updateGUI() {
createViewsForPlugins(R.string.configbuilder_profile, R.string.configbuilder_profile_description, PluginType.PROFILE, MainApp.getSpecificPluginsVisibleInListByInterface(ProfileInterface::class.java, PluginType.PROFILE))
createViewsForPlugins(R.string.configbuilder_insulin, R.string.configbuilder_insulin_description, PluginType.INSULIN, MainApp.getSpecificPluginsVisibleInListByInterface(InsulinInterface::class.java, PluginType.INSULIN))

View file

@ -16,6 +16,7 @@ public class AutomationEvent {
private Trigger trigger = new TriggerConnector();
private List<Action> actions = new ArrayList<>();
private String title;
private boolean enabled = true;
public void setTitle(String title) {
this.title = title;
@ -33,6 +34,14 @@ public class AutomationEvent {
return actions;
}
public boolean isEnabled() {
return enabled;
}
public void setEnabled(boolean newState) {
enabled = newState;
}
public TriggerConnector getPreconditions() {
TriggerConnector trigger = new TriggerConnector(TriggerConnector.Type.AND);
for (Action action : actions) {
@ -55,6 +64,7 @@ public class AutomationEvent {
try {
// title
o.put("title", title);
o.put("enabled", enabled);
// trigger
o.put("trigger", trigger.toJSON());
// actions
@ -72,11 +82,9 @@ public class AutomationEvent {
public AutomationEvent fromJSON(String data) {
try {
JSONObject d = new JSONObject(data);
// title
title = d.optString("title", "");
// trigger
enabled = d.optBoolean("enabled", true);
trigger = Trigger.instantiate(d.getString("trigger"));
// actions
JSONArray array = d.getJSONArray("actions");
actions.clear();
for (int i = 0; i < array.length(); i++) {

View file

@ -12,9 +12,9 @@ import info.nightscout.androidaps.plugins.general.automation.dialogs.EditEventDi
import info.nightscout.androidaps.plugins.general.automation.events.EventAutomationDataChanged
import info.nightscout.androidaps.plugins.general.automation.events.EventAutomationUpdateGui
import info.nightscout.androidaps.utils.FabricPrivacy
import info.nightscout.androidaps.utils.plusAssign
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.disposables.CompositeDisposable
import io.reactivex.disposables.Disposable
import kotlinx.android.synthetic.main.automation_fragment.*
class AutomationFragment : Fragment() {
@ -22,10 +22,6 @@ class AutomationFragment : Fragment() {
private var disposable: CompositeDisposable = CompositeDisposable()
private var eventListAdapter: EventListAdapter? = null
operator fun CompositeDisposable.plusAssign(disposable: Disposable) {
add(disposable)
}
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
return inflater.inflate(R.layout.automation_fragment, container, false)
}
@ -48,19 +44,14 @@ class AutomationFragment : Fragment() {
}
@Synchronized
override fun onResume() {
super.onResume()
disposable += RxBus
.toObservable(EventAutomationUpdateGui::class.java)
.observeOn(AndroidSchedulers.mainThread())
.subscribe({
eventListAdapter?.notifyDataSetChanged()
val sb = StringBuilder()
for (l in AutomationPlugin.executionLog) {
sb.append(l)
sb.append("\n")
}
automation_logView.text = sb.toString()
updateGui()
}, {
FabricPrivacy.logException(it)
})
@ -72,11 +63,25 @@ class AutomationFragment : Fragment() {
}, {
FabricPrivacy.logException(it)
})
updateGui()
}
@Synchronized
override fun onPause() {
super.onPause()
disposable.clear()
}
@Synchronized
private fun updateGui() {
if (eventListAdapter == null) return
eventListAdapter?.notifyDataSetChanged()
val sb = StringBuilder()
for (l in AutomationPlugin.executionLog) {
sb.append(l)
sb.append("\n")
}
automation_logView.text = sb.toString()
}
}

View file

@ -21,12 +21,8 @@ import info.nightscout.androidaps.plugins.general.automation.triggers.*
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.events.EventAutosensCalculationFinished
import info.nightscout.androidaps.queue.Callback
import info.nightscout.androidaps.services.LocationService
import info.nightscout.androidaps.utils.DateUtil
import info.nightscout.androidaps.utils.FabricPrivacy
import info.nightscout.androidaps.utils.SP
import info.nightscout.androidaps.utils.T
import info.nightscout.androidaps.utils.*
import io.reactivex.disposables.CompositeDisposable
import io.reactivex.disposables.Disposable
import io.reactivex.schedulers.Schedulers
import org.json.JSONArray
import org.json.JSONException
@ -60,10 +56,6 @@ object AutomationPlugin : PluginBase(PluginDescription()
}
}
operator fun CompositeDisposable.plusAssign(disposable: Disposable) {
add(disposable)
}
override fun onStart() {
val context = MainApp.instance().applicationContext
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
@ -131,6 +123,7 @@ object AutomationPlugin : PluginBase(PluginDescription()
loopHandler.removeCallbacks(refreshLoop)
val context = MainApp.instance().applicationContext
context.stopService(Intent(context, LocationService::class.java))
super.onStop()
}
private fun storeToSP() {
@ -171,7 +164,7 @@ object AutomationPlugin : PluginBase(PluginDescription()
if (L.isEnabled(L.AUTOMATION))
log.debug("processActions")
for (event in automationEvents) {
if (event.trigger.shouldRun() && event.preconditions.shouldRun()) {
if (event.isEnabled() && event.trigger.shouldRun() && event.preconditions.shouldRun()) {
val actions = event.actions
for (action in actions) {
action.doAction(object : Callback() {

View file

@ -5,6 +5,7 @@ import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.CheckBox;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;
@ -20,8 +21,10 @@ import java.util.List;
import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.R;
import info.nightscout.androidaps.plugins.bus.RxBus;
import info.nightscout.androidaps.plugins.general.automation.actions.Action;
import info.nightscout.androidaps.plugins.general.automation.dialogs.EditEventDialog;
import info.nightscout.androidaps.plugins.general.automation.events.EventAutomationDataChanged;
import info.nightscout.androidaps.plugins.general.automation.triggers.TriggerConnector;
class EventListAdapter extends RecyclerView.Adapter<EventListAdapter.ViewHolder> {
@ -51,6 +54,7 @@ class EventListAdapter extends RecyclerView.Adapter<EventListAdapter.ViewHolder>
public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
final AutomationEvent event = mEventList.get(position);
holder.eventTitle.setText(event.getTitle());
holder.enabled.setChecked(event.isEnabled());
holder.iconLayout.removeAllViews();
// trigger icons
@ -77,6 +81,13 @@ class EventListAdapter extends RecyclerView.Adapter<EventListAdapter.ViewHolder>
addImage(res, holder.context, holder.iconLayout);
}
// enabled event
holder.enabled.setOnCheckedChangeListener((buttonView, isChecked) -> {
event.setEnabled(isChecked);
notifyDataSetChanged();
RxBus.INSTANCE.send(new EventAutomationDataChanged());
});
// remove event
holder.iconTrash.setOnClickListener(v -> {
mEventList.remove(event);
@ -107,6 +118,7 @@ class EventListAdapter extends RecyclerView.Adapter<EventListAdapter.ViewHolder>
final TextView eventTitle;
final Context context;
final ImageView iconTrash;
final CheckBox enabled;
ViewHolder(View view, Context context) {
super(view);
@ -115,6 +127,7 @@ class EventListAdapter extends RecyclerView.Adapter<EventListAdapter.ViewHolder>
rootLayout = view.findViewById(R.id.rootLayout);
iconLayout = view.findViewById(R.id.iconLayout);
iconTrash = view.findViewById(R.id.iconTrash);
enabled = view.findViewById(R.id.automation_enabled);
}
}
}

View file

@ -15,8 +15,8 @@ import info.nightscout.androidaps.data.PumpEnactResult;
import info.nightscout.androidaps.db.Source;
import info.nightscout.androidaps.db.TempTarget;
import info.nightscout.androidaps.plugins.general.automation.elements.ComparatorExists;
import info.nightscout.androidaps.plugins.general.automation.elements.InputBg;
import info.nightscout.androidaps.plugins.general.automation.elements.InputDuration;
import info.nightscout.androidaps.plugins.general.automation.elements.InputTempTarget;
import info.nightscout.androidaps.plugins.general.automation.elements.LabelWithElement;
import info.nightscout.androidaps.plugins.general.automation.elements.LayoutBuilder;
import info.nightscout.androidaps.plugins.general.automation.triggers.TriggerTempTarget;
@ -27,7 +27,7 @@ import info.nightscout.androidaps.utils.JsonHelper;
public class ActionStartTempTarget extends Action {
String reason = "";
InputBg value = new InputBg();
InputTempTarget value = new InputTempTarget();
InputDuration duration = new InputDuration(0, InputDuration.TimeUnit.MINUTES);
private TempTarget tempTarget;

View file

@ -11,27 +11,10 @@ import info.nightscout.androidaps.plugins.configBuilder.ProfileFunctions;
import info.nightscout.androidaps.utils.NumberPicker;
public class InputBg extends Element {
final TextWatcher textWatcher = new TextWatcher() {
@Override
public void afterTextChanged(Editable s) {
if (units.equals(Constants.MMOL)) {
value = Math.max(value, 4d);
value = Math.min(value, 15d);
} else {
value = Math.max(value, 72d);
value = Math.min(value, 270d);
}
}
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
}
};
static final int MMOL_MIN = 3;
static final int MMOL_MAX = 20;
static final int MGDL_MIN = 54;
static final int MGDL_MAX = 360;
private String units = Constants.MGDL;
private double value;
@ -43,6 +26,10 @@ public class InputBg extends Element {
public InputBg() {
super();
setUnits(ProfileFunctions.getInstance().getProfileUnits());
if (getUnits().equals(Constants.MMOL))
value = MMOL_MIN;
else
value = MGDL_MIN;
}
public InputBg(InputBg another) {
@ -55,7 +42,7 @@ public class InputBg extends Element {
@Override
public void addToLayout(LinearLayout root) {
NumberPicker numberPicker = new NumberPicker(root.getContext(), null);
numberPicker.setParams(value, minValue, maxValue, step, decimalFormat, true, null, textWatcher);
numberPicker.setParams(value, minValue, maxValue, step, decimalFormat, true, null, null);
numberPicker.setOnValueChangedListener(value -> this.value = value);
root.addView(numberPicker);
}
@ -68,21 +55,18 @@ public class InputBg extends Element {
// set default initial value
if (units.equals(Constants.MMOL)) {
// mmol
minValue = 2;
maxValue = 30;
minValue = MMOL_MIN;
maxValue = MMOL_MAX;
step = 0.1;
decimalFormat = new DecimalFormat("0.0");
} else {
// mg/dL
minValue = 40;
maxValue = 540;
minValue = MGDL_MIN;
maxValue = MGDL_MAX;
step = 1;
decimalFormat = new DecimalFormat("0");
}
// make sure that value is in range
textWatcher.afterTextChanged(null);
this.units = units;
return this;
}

View file

@ -21,19 +21,6 @@ import info.nightscout.androidaps.utils.NumberPicker;
public class InputDelta extends Element {
private Comparator.Compare compare = Comparator.Compare.IS_EQUAL;
final TextWatcher textWatcher = new TextWatcher() {
@Override
public void afterTextChanged(Editable s) {
}
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
}
};
public enum DeltaType {
DELTA,
@ -122,7 +109,7 @@ public class InputDelta extends Element {
spinner.setSelection(this.deltaType.ordinal());
// root.addView(spinner);
numberPicker = new NumberPicker(root.getContext(), null);
numberPicker.setParams(value, minValue, maxValue, step, decimalFormat, true, null, textWatcher);
numberPicker.setParams(value, minValue, maxValue, step, decimalFormat, true, null, null);
numberPicker.setOnValueChangedListener(value -> this.value = value);
LinearLayout l = new LinearLayout(root.getContext());
l.setOrientation(LinearLayout.VERTICAL);

View file

@ -0,0 +1,77 @@
package info.nightscout.androidaps.plugins.general.automation.elements;
import android.widget.LinearLayout;
import java.text.DecimalFormat;
import info.nightscout.androidaps.Constants;
import info.nightscout.androidaps.plugins.configBuilder.ProfileFunctions;
import info.nightscout.androidaps.utils.NumberPicker;
public class InputTempTarget extends Element {
private String units = Constants.MGDL;
private double value;
double minValue;
private double maxValue;
private double step;
private DecimalFormat decimalFormat;
public InputTempTarget() {
super();
setUnits(ProfileFunctions.getInstance().getProfileUnits());
if (getUnits().equals(Constants.MMOL))
value = Constants.MIN_TT_MMOL;
else
value = Constants.MIN_TT_MGDL;
}
public InputTempTarget(InputTempTarget another) {
super();
value = another.getValue();
setUnits(another.getUnits());
}
@Override
public void addToLayout(LinearLayout root) {
NumberPicker numberPicker = new NumberPicker(root.getContext(), null);
numberPicker.setParams(value, minValue, maxValue, step, decimalFormat, true, null, null);
numberPicker.setOnValueChangedListener(value -> this.value = value);
root.addView(numberPicker);
}
public String getUnits() {
return units;
}
public InputTempTarget setUnits(String units) {
// set default initial value
if (units.equals(Constants.MMOL)) {
// mmol
minValue = Constants.MIN_TT_MMOL;
maxValue = Constants.MAX_TT_MMOL;
step = 0.1;
decimalFormat = new DecimalFormat("0.0");
} else {
// mg/dL
minValue = Constants.MIN_TT_MGDL;
maxValue = Constants.MAX_TT_MGDL;
step = 1;
decimalFormat = new DecimalFormat("0");
}
this.units = units;
return this;
}
public InputTempTarget setValue(double value) {
this.value = value;
return this;
}
public double getValue() {
return value;
}
}

View file

@ -33,15 +33,15 @@ import info.nightscout.androidaps.utils.T;
public class TriggerDelta extends Trigger {
private static Logger log = LoggerFactory.getLogger(L.AUTOMATION);
private double minValue = 0d;
private double maxValue = 1d;
private double step = 1;
private DecimalFormat decimalFormat = new DecimalFormat("1");
private final int MMOL_MAX = 4;
private final int MGDL_MAX = 72;
private String units;
private DeltaType deltaType;
private InputDelta value = new InputDelta( (double) minValue,(double) minValue, (double) maxValue, step, decimalFormat, deltaType);
private Comparator comparator = new Comparator();
private InputDelta value;
private Comparator comparator;
public TriggerDelta() {
super();
@ -62,6 +62,16 @@ public class TriggerDelta extends Trigger {
return value.getValue();
}
private void initializer() {
this.deltaType = DeltaType.DELTA;
comparator = new Comparator();
if (units.equals(Constants.MMOL))
value = new InputDelta(0, -MMOL_MAX, MMOL_MAX, 0.1d, new DecimalFormat("0.1"), DeltaType.DELTA);
else
value = new InputDelta(0, -MGDL_MAX, MGDL_MAX, 0.1d, new DecimalFormat("1"), DeltaType.DELTA);
}
public DeltaType getType() {
return deltaType;
}
@ -150,7 +160,7 @@ public class TriggerDelta extends Trigger {
@Override
public Optional<Integer> icon() {
return Optional.of(R.drawable.icon_auto_delta);
return Optional.of(R.drawable.icon_auto_delta);
}
@Override
@ -169,23 +179,6 @@ public class TriggerDelta extends Trigger {
return this;
}
void initializer(){
if (this.units.equals(Constants.MMOL)) {
this.maxValue = 4d;
this.minValue = -4d;
this.step = 0.1d;
this.decimalFormat = new DecimalFormat("0.1");
this.deltaType = DeltaType.DELTA;
} else {
this.maxValue = 72d;
this.minValue = -72d;
this.step = 1d;
this.deltaType = DeltaType.DELTA;
}
value = new InputDelta( (double) minValue,(double) minValue, (double) maxValue, step, decimalFormat, deltaType);
}
TriggerDelta lastRun(long lastRun) {
this.lastRun = lastRun;
return this;
@ -201,7 +194,7 @@ public class TriggerDelta extends Trigger {
new LayoutBuilder()
.add(new StaticLabel(R.string.deltalabel))
.add(comparator)
.add(new LabelWithElement(MainApp.gs(R.string.deltalabel) + ": ", "", value))
.add(new LabelWithElement(MainApp.gs(R.string.deltalabel_u, getUnits()) + ": ", "", value))
.build(root);
}

View file

@ -263,17 +263,17 @@ public class NewNSTreatmentDialog extends DialogFragment implements View.OnClick
if (sensorRadioButton.isChecked()) meterRadioButton.setChecked(true);
}
};
editBg = (NumberPicker) view.findViewById(R.id.careportal_newnstreatment_bginput);
editTemptarget = (NumberPicker) view.findViewById(R.id.careportal_newnstreatment_temptarget);
editBg = view.findViewById(R.id.careportal_newnstreatment_bginput);
editTemptarget = view.findViewById(R.id.careportal_newnstreatment_temptarget);
if (profile == null) {
editBg.setParams(bg, 0d, 500d, 0.1d, new DecimalFormat("0.0"), false, view.findViewById(R.id.ok), bgTextWatcher);
editTemptarget.setParams(bg, 0d, 500d, 0.1d, new DecimalFormat("0.0"), false, view.findViewById(R.id.ok));
editBg.setParams(bg, 0d, 500d, 0.1d, new DecimalFormat("0"), false, view.findViewById(R.id.ok), bgTextWatcher);
editTemptarget.setParams(Constants.MIN_TT_MGDL, Constants.MIN_TT_MGDL, Constants.MAX_TT_MGDL, 0.1d, new DecimalFormat("0.0"), false, view.findViewById(R.id.ok));
} else if (units.equals(Constants.MMOL)) {
editBg.setParams(bg, 0d, 30d, 0.1d, new DecimalFormat("0.0"), false, view.findViewById(R.id.ok), bgTextWatcher);
editTemptarget.setParams(bg, 0d, 30d, 0.1d, new DecimalFormat("0.0"), false, view.findViewById(R.id.ok));
editTemptarget.setParams(Constants.MIN_TT_MMOL, Constants.MIN_TT_MMOL, Constants.MAX_TT_MMOL, 0.1d, new DecimalFormat("0.0"), false, view.findViewById(R.id.ok));
} else {
editBg.setParams(bg, 0d, 500d, 1d, new DecimalFormat("0"), false, view.findViewById(R.id.ok), bgTextWatcher);
editTemptarget.setParams(bg, 0d, 500d, 1d, new DecimalFormat("0"), false, view.findViewById(R.id.ok));
editTemptarget.setParams(Constants.MIN_TT_MGDL, Constants.MIN_TT_MGDL, Constants.MAX_TT_MGDL, 1d, new DecimalFormat("0"), false, view.findViewById(R.id.ok));
}
sensorRadioButton.setOnCheckedChangeListener((buttonView, isChecked) -> {

View file

@ -113,6 +113,7 @@ public class NSClientPlugin extends PluginBase {
context.unbindService(mConnection);
nsClientReceiverDelegate.unregisterReceivers();
super.onStop();
}
@Subscribe

View file

@ -71,6 +71,7 @@ public class OverviewPlugin extends PluginBase {
@Override
protected void onStop() {
MainApp.bus().unregister(this);
super.onStop();
}
@Subscribe

View file

@ -31,7 +31,7 @@ public class DummyService extends Service {
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
super.onStartCommand(intent, flags, startId);
startForeground(PersistentNotificationPlugin.ONGOING_NOTIFICATION_ID, PersistentNotificationPlugin.getPlugin().updateNotification());
startForeground(PersistentNotificationPlugin.ONGOING_NOTIFICATION_ID, PersistentNotificationPlugin.getPlugin().getLastNotification());
return START_STICKY;
}
@ -48,8 +48,7 @@ public class DummyService extends Service {
super.onCreate();
// TODO: I guess this was moved here in order to adhere to the 5 seconds rule to call "startForeground" after a Service was called as Foreground service?
// As onCreate() is not called every time a service is started, copied to onStartCommand().
Notification notification = PersistentNotificationPlugin.getPlugin().updateNotification();
startForeground(PersistentNotificationPlugin.ONGOING_NOTIFICATION_ID, notification);
startForeground(PersistentNotificationPlugin.ONGOING_NOTIFICATION_ID, PersistentNotificationPlugin.getPlugin().getLastNotification());
MainApp.bus().register(this);
}

View file

@ -55,14 +55,13 @@ public class PersistentNotificationPlugin extends PluginBase {
private Notification notification;
public static PersistentNotificationPlugin getPlugin() {
if (plugin == null) plugin = new PersistentNotificationPlugin(MainApp.instance());
if (plugin == null) plugin = new PersistentNotificationPlugin();
return plugin;
}
public static final String CHANNEL_ID = "AndroidAPS-Ongoing";
public static final int ONGOING_NOTIFICATION_ID = 4711;
private final Context ctx;
/// For Android Auto
/// Intents are not declared in manifest and not consumed, this is intentionally because actually we can't do anything with
@ -76,7 +75,7 @@ public class PersistentNotificationPlugin extends PluginBase {
/// End Android Auto
private PersistentNotificationPlugin(Context ctx) {
private PersistentNotificationPlugin() {
super(new PluginDescription()
.mainType(PluginType.GENERAL)
.neverVisible(true)
@ -86,22 +85,21 @@ public class PersistentNotificationPlugin extends PluginBase {
.showInList(false)
.description(R.string.description_persistent_notification)
);
this.ctx = ctx;
}
@Override
protected void onStart() {
super.onStart();
createNotificationChannel(); // make sure channels exist before triggering updates through the bus
MainApp.bus().register(this);
triggerNotificationUpdate();
super.onStart();
triggerNotificationUpdate(true);
}
private void createNotificationChannel() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
NotificationManager mNotificationManager =
(NotificationManager) ctx.getSystemService(Context.NOTIFICATION_SERVICE);
(NotificationManager) MainApp.instance().getSystemService(Context.NOTIFICATION_SERVICE);
@SuppressLint("WrongConstant") NotificationChannel channel = new NotificationChannel(CHANNEL_ID,
CHANNEL_ID,
NotificationManager.IMPORTANCE_HIGH);
@ -113,23 +111,26 @@ public class PersistentNotificationPlugin extends PluginBase {
protected void onStop() {
MainApp.bus().unregister(this);
MainApp.instance().stopService(new Intent(MainApp.instance(), DummyService.class));
super.onStop();
}
private void triggerNotificationUpdate() {
private void triggerNotificationUpdate(boolean boot) {
updateNotification(boot);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
MainApp.instance().startForegroundService(new Intent(MainApp.instance(), DummyService.class));
else
MainApp.instance().startService(new Intent(MainApp.instance(), DummyService.class));
}
@Nonnull
public Notification updateNotification() {
String line1 = null;
private void updateNotification(boolean boot) {
String line1;
String line2 = null;
String line3 = null;
NotificationCompat.CarExtender.UnreadConversation.Builder unreadConversationBuilder = null;
if (ConfigBuilderPlugin.getPlugin().getActiveProfileInterface() != null && ProfileFunctions.getInstance().isProfileValid("Notification")) {
if (boot) {
line1 = MainApp.gs(R.string.loading);
} else if (ConfigBuilderPlugin.getPlugin().getActiveProfileInterface() != null && ProfileFunctions.getInstance().isProfileValid("Notification")) {
String line1_aa;
String units = ProfileFunctions.getInstance().getProfileUnits();
@ -185,7 +186,7 @@ public class PersistentNotificationPlugin extends PluginBase {
.setPackage(PACKAGE);
PendingIntent msgReadPendingIntent =
PendingIntent.getBroadcast(ctx,
PendingIntent.getBroadcast(MainApp.instance(),
ONGOING_NOTIFICATION_ID,
msgReadIntent,
PendingIntent.FLAG_UPDATE_CURRENT);
@ -197,7 +198,7 @@ public class PersistentNotificationPlugin extends PluginBase {
.setPackage(PACKAGE);
PendingIntent msgReplyPendingIntent = PendingIntent.getBroadcast(
ctx,
MainApp.instance(),
ONGOING_NOTIFICATION_ID,
msgReplyIntent,
PendingIntent.FLAG_UPDATE_CURRENT);
@ -215,18 +216,20 @@ public class PersistentNotificationPlugin extends PluginBase {
/// Add dot to produce a "more natural sounding result"
unreadConversationBuilder.addMessage(line3_aa);
/// End Android Auto
} else {
line1 = MainApp.gs(R.string.noprofileset);
}
NotificationCompat.Builder builder = new NotificationCompat.Builder(ctx, CHANNEL_ID);
NotificationCompat.Builder builder = new NotificationCompat.Builder(MainApp.instance(), CHANNEL_ID);
builder.setOngoing(true);
builder.setOnlyAlertOnce(true);
builder.setCategory(NotificationCompat.CATEGORY_STATUS);
builder.setSmallIcon(MainApp.getNotificationIcon());
Bitmap largeIcon = BitmapFactory.decodeResource(ctx.getResources(), MainApp.getIcon());
Bitmap largeIcon = BitmapFactory.decodeResource(MainApp.instance().getResources(), MainApp.getIcon());
builder.setLargeIcon(largeIcon);
builder.setContentTitle(line1 != null ? line1 : MainApp.gs(R.string.noprofileset));
builder.setContentText(line2 != null ? line2 : MainApp.gs(R.string.noprofileset));
builder.setSubText(line3 != null ? line3 : MainApp.gs(R.string.noprofileset));
if (line1 != null) builder.setContentTitle(line1);
if (line2 != null) builder.setContentText(line2);
if (line3 != null) builder.setSubText(line3);
/// Android Auto
if (unreadConversationBuilder != null) {
builder.extend(new NotificationCompat.CarExtender()
@ -235,9 +238,9 @@ public class PersistentNotificationPlugin extends PluginBase {
/// End Android Auto
Intent resultIntent = new Intent(ctx, MainActivity.class);
Intent resultIntent = new Intent(MainApp.instance(), MainActivity.class);
TaskStackBuilder stackBuilder = TaskStackBuilder.create(ctx);
TaskStackBuilder stackBuilder = TaskStackBuilder.create(MainApp.instance());
stackBuilder.addParentStack(MainActivity.class);
stackBuilder.addNextIntent(resultIntent);
PendingIntent resultPendingIntent =
@ -247,12 +250,11 @@ public class PersistentNotificationPlugin extends PluginBase {
);
builder.setContentIntent(resultPendingIntent);
NotificationManager mNotificationManager =
(NotificationManager) ctx.getSystemService(Context.NOTIFICATION_SERVICE);
(NotificationManager) MainApp.instance().getSystemService(Context.NOTIFICATION_SERVICE);
android.app.Notification notification = builder.build();
mNotificationManager.notify(ONGOING_NOTIFICATION_ID, notification);
this.notification = notification;
return notification;
}
private String deltastring(double deltaMGDL, double deltaMMOL, String units) {
@ -279,48 +281,50 @@ public class PersistentNotificationPlugin extends PluginBase {
public Notification getLastNotification() {
if (notification != null) return notification;
else return new Notification();
else {
throw new IllegalStateException("Notification is null");
}
}
@Subscribe
public void onStatusEvent(final EventPreferenceChange ev) {
triggerNotificationUpdate();
triggerNotificationUpdate(false);
}
@Subscribe
public void onStatusEvent(final EventTreatmentChange ev) {
triggerNotificationUpdate();
triggerNotificationUpdate(false);
}
@Subscribe
public void onStatusEvent(final EventTempBasalChange ev) {
triggerNotificationUpdate();
triggerNotificationUpdate(false);
}
@Subscribe
public void onStatusEvent(final EventExtendedBolusChange ev) {
triggerNotificationUpdate();
triggerNotificationUpdate(false);
}
@Subscribe
public void onStatusEvent(final EventAutosensCalculationFinished ev) {
triggerNotificationUpdate();
triggerNotificationUpdate(false);
}
@Subscribe
public void onStatusEvent(final EventNewBasalProfile ev) {
triggerNotificationUpdate();
triggerNotificationUpdate(false);
}
@Subscribe
public void onStatusEvent(final EventInitializationChanged ev) {
triggerNotificationUpdate();
triggerNotificationUpdate(false);
}
@Subscribe
public void onStatusEvent(final EventRefreshOverview ev) {
triggerNotificationUpdate();
triggerNotificationUpdate(false);
}
}

View file

@ -98,6 +98,7 @@ public class SmsCommunicatorPlugin extends PluginBase {
@Override
protected void onStop() {
MainApp.bus().unregister(this);
super.onStop();
}
@Subscribe

View file

@ -16,17 +16,12 @@ import info.nightscout.androidaps.utils.FabricPrivacy
import info.nightscout.androidaps.utils.SP
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.disposables.CompositeDisposable
import io.reactivex.disposables.Disposable
import kotlinx.android.synthetic.main.tidepool_fragment.*
class TidepoolFragment : Fragment() {
private var disposable: CompositeDisposable = CompositeDisposable()
operator fun CompositeDisposable.plusAssign(disposable: Disposable) {
add(disposable)
}
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
return inflater.inflate(R.layout.tidepool_fragment, container, false)
}
@ -39,6 +34,7 @@ class TidepoolFragment : Fragment() {
tidepool_resertstart.setOnClickListener { SP.putLong(R.string.key_tidepool_last_end, 0) }
}
@Synchronized
override fun onResume() {
super.onResume()
disposable.add(RxBus
@ -46,16 +42,17 @@ class TidepoolFragment : Fragment() {
.observeOn(AndroidSchedulers.mainThread())
.subscribe({
TidepoolPlugin.updateLog()
tidepool_log.text = TidepoolPlugin.textLog
tidepool_status.text = TidepoolUploader.connectionStatus.name
tidepool_log.text = TidepoolPlugin.textLog
tidepool_logscrollview.fullScroll(ScrollView.FOCUS_DOWN)
tidepool_log?.text = TidepoolPlugin.textLog
tidepool_status?.text = TidepoolUploader.connectionStatus.name
tidepool_log?.text = TidepoolPlugin.textLog
tidepool_logscrollview?.fullScroll(ScrollView.FOCUS_DOWN)
}, {
FabricPrivacy.logException(it)
})
)
}
@Synchronized
override fun onPause() {
super.onPause()
disposable.clear()

View file

@ -1,6 +1,5 @@
package info.nightscout.androidaps.plugins.general.tidepool
import android.text.Html
import android.text.Spanned
import info.nightscout.androidaps.Constants
import info.nightscout.androidaps.MainApp
@ -23,7 +22,6 @@ import info.nightscout.androidaps.receivers.ChargingStateReceiver
import info.nightscout.androidaps.receivers.NetworkChangeReceiver
import info.nightscout.androidaps.utils.*
import io.reactivex.disposables.CompositeDisposable
import io.reactivex.disposables.Disposable
import io.reactivex.schedulers.Schedulers
import org.slf4j.LoggerFactory
import java.util.*
@ -43,10 +41,6 @@ object TidepoolPlugin : PluginBase(PluginDescription()
private val listLog = ArrayList<EventTidepoolStatus>()
var textLog: Spanned = HtmlHelper.fromHtml("")
operator fun CompositeDisposable.plusAssign(disposable: Disposable) {
add(disposable)
}
override fun onStart() {
super.onStart()
disposable += RxBus

View file

@ -91,6 +91,7 @@ public class WearPlugin extends PluginBase {
protected void onStop() {
MainApp.bus().unregister(this);
disposable.clear();
super.onStop();
}
private void sendDataToWatch(boolean status, boolean basals, boolean bgValue) {

View file

@ -90,9 +90,9 @@ class NSProfileFragment : Fragment() {
}
}
}
updateGUI()
}
@Synchronized
override fun onResume() {
super.onResume()
disposable.add(RxBus
@ -104,14 +104,18 @@ class NSProfileFragment : Fragment() {
FabricPrivacy.logException(it)
})
)
updateGUI()
}
@Synchronized
override fun onPause() {
super.onPause()
disposable.clear()
}
@Synchronized
fun updateGUI() {
if (profileview_noprofile == null) return
profileview_noprofile.visibility = View.VISIBLE
NSProfilePlugin.getPlugin().profile?.let { profileStore ->

View file

@ -65,6 +65,7 @@ public class NSProfilePlugin extends PluginBase implements ProfileInterface {
@Override
protected void onStop() {
MainApp.bus().unregister(this);
super.onStop();
}
public void handleNewData(Intent intent) {

View file

@ -100,6 +100,7 @@ public abstract class PumpPluginAbstract extends PluginBase implements PumpInter
serviceRunning = false;
MainApp.bus().unregister(this);
super.onStop();
}

View file

@ -27,13 +27,9 @@ import info.nightscout.androidaps.plugins.pump.danaRKorean.DanaRKoreanPlugin
import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin
import info.nightscout.androidaps.plugins.treatments.fragments.ProfileViewerDialog
import info.nightscout.androidaps.queue.events.EventQueueChanged
import info.nightscout.androidaps.utils.DateUtil
import info.nightscout.androidaps.utils.FabricPrivacy
import info.nightscout.androidaps.utils.SetWarnColor
import info.nightscout.androidaps.utils.T
import info.nightscout.androidaps.utils.*
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.disposables.CompositeDisposable
import io.reactivex.disposables.Disposable
import kotlinx.android.synthetic.main.danar_fragment.*
import org.slf4j.LoggerFactory
@ -41,10 +37,6 @@ class DanaRFragment : Fragment() {
private val log = LoggerFactory.getLogger(L.PUMP)
private var disposable: CompositeDisposable = CompositeDisposable()
operator fun CompositeDisposable.plusAssign(disposable: Disposable) {
add(disposable)
}
private val loopHandler = Handler()
private lateinit var refreshLoop: Runnable
@ -84,9 +76,9 @@ class DanaRFragment : Fragment() {
DanaRPump.getInstance().lastConnection = 0
ConfigBuilderPlugin.getPlugin().commandQueue.readStatus("Clicked connect to pump", null)
}
updateGUI()
}
@Synchronized
override fun onResume() {
super.onResume()
MainApp.bus().register(this)
@ -95,8 +87,10 @@ class DanaRFragment : Fragment() {
.toObservable(EventDanaRNewStatus::class.java)
.observeOn(AndroidSchedulers.mainThread())
.subscribe({ updateGUI() }, { FabricPrivacy.logException(it) })
updateGUI()
}
@Synchronized
override fun onPause() {
super.onPause()
disposable.clear()
@ -105,12 +99,12 @@ class DanaRFragment : Fragment() {
}
@Subscribe
public fun onStatusEvent(c: EventPumpStatusChanged) {
fun onStatusEvent(c: EventPumpStatusChanged) {
activity?.runOnUiThread {
when {
c.sStatus == EventPumpStatusChanged.CONNECTING -> danar_btconnection.text = "{fa-bluetooth-b spin} " + c.sSecondsElapsed + "s"
c.sStatus == EventPumpStatusChanged.CONNECTED -> danar_btconnection.text = "{fa-bluetooth}"
c.sStatus == EventPumpStatusChanged.DISCONNECTED -> danar_btconnection.text = "{fa-bluetooth-b}"
c.sStatus == EventPumpStatusChanged.CONNECTING -> danar_btconnection?.text = "{fa-bluetooth-b spin} " + c.sSecondsElapsed + "s"
c.sStatus == EventPumpStatusChanged.CONNECTED -> danar_btconnection?.text = "{fa-bluetooth}"
c.sStatus == EventPumpStatusChanged.DISCONNECTED -> danar_btconnection?.text = "{fa-bluetooth-b}"
}
if (c.textStatus() != "") {
dana_pumpstatus.text = c.textStatus()
@ -123,20 +117,22 @@ class DanaRFragment : Fragment() {
}
@Subscribe
public fun onStatusEvent(s: EventTempBasalChange) =
fun onStatusEvent(s: EventTempBasalChange) =
activity?.runOnUiThread { updateGUI() }
@Subscribe
public fun onStatusEvent(s: EventExtendedBolusChange) =
fun onStatusEvent(s: EventExtendedBolusChange) =
activity?.runOnUiThread { updateGUI() }
@Subscribe
public fun onStatusEvent(s: EventQueueChanged) =
fun onStatusEvent(s: EventQueueChanged) =
activity?.runOnUiThread { updateGUI() }
// GUI functions
@Synchronized
internal fun updateGUI() {
if (danar_dailyunits == null) return
val pump = DanaRPump.getInstance()
val plugin: PumpInterface = ConfigBuilderPlugin.getPlugin().activePump ?: return
if (pump.lastConnection != 0L) {

View file

@ -65,6 +65,7 @@ public class DanaRPlugin extends AbstractDanaRPlugin {
context.unbindService(mConnection);
MainApp.bus().unregister(this);
super.onStop();
}
private ServiceConnection mConnection = new ServiceConnection() {

View file

@ -68,6 +68,7 @@ public class DanaRKoreanPlugin extends AbstractDanaRPlugin {
context.unbindService(mConnection);
MainApp.bus().unregister(this);
super.onStop();
}
private ServiceConnection mConnection = new ServiceConnection() {

View file

@ -123,6 +123,7 @@ public class DanaRSPlugin extends PluginBase implements PumpInterface, DanaRInte
context.unbindService(mConnection);
MainApp.bus().unregister(this);
super.onStop();
}
@Override

View file

@ -71,6 +71,7 @@ public class DanaRv2Plugin extends AbstractDanaRPlugin {
context.unbindService(mConnection);
MainApp.bus().unregister(this);
super.onStop();
}
private ServiceConnection mConnection = new ServiceConnection() {

View file

@ -35,13 +35,9 @@ import info.nightscout.androidaps.plugins.pump.medtronic.util.MedtronicUtil
import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin
import info.nightscout.androidaps.queue.Callback
import info.nightscout.androidaps.queue.events.EventQueueChanged
import info.nightscout.androidaps.utils.DateUtil
import info.nightscout.androidaps.utils.FabricPrivacy
import info.nightscout.androidaps.utils.SetWarnColor
import info.nightscout.androidaps.utils.T
import info.nightscout.androidaps.utils.*
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.disposables.CompositeDisposable
import io.reactivex.disposables.Disposable
import kotlinx.android.synthetic.main.medtronic_fragment.*
import org.slf4j.LoggerFactory
@ -50,10 +46,6 @@ class MedtronicFragment : Fragment() {
private val log = LoggerFactory.getLogger(L.PUMP)
private var disposable: CompositeDisposable = CompositeDisposable()
operator fun CompositeDisposable.plusAssign(disposable: Disposable) {
add(disposable)
}
private val loopHandler = Handler()
private lateinit var refreshLoop: Runnable
@ -94,7 +86,7 @@ class MedtronicFragment : Fragment() {
MedtronicPumpPlugin.getPlugin().resetStatusState()
ConfigBuilderPlugin.getPlugin().commandQueue.readStatus("Clicked refresh", object : Callback() {
override fun run() {
activity?.runOnUiThread { medtronic_refresh.isEnabled = true }
activity?.runOnUiThread { medtronic_refresh?.isEnabled = true }
}
})
}
@ -107,8 +99,6 @@ class MedtronicFragment : Fragment() {
MedtronicUtil.displayNotConfiguredDialog(context)
}
}
updateGUI()
}
@Synchronized
@ -141,6 +131,8 @@ class MedtronicFragment : Fragment() {
MedtronicUtil.getPumpStatus().verifyConfiguration()
updateGUI()
}, { FabricPrivacy.logException(it) })
updateGUI()
}
@Synchronized

View file

@ -1062,6 +1062,21 @@ public class MedtronicPumpPlugin extends PumpPluginAbstract implements PumpInter
}
@Override
public PumpEnactResult setTempBasalPercent(Integer percent, Integer durationInMinutes, Profile profile,
boolean enforceNew) {
if (percent==0) {
return setTempBasalAbsolute(0.0d, durationInMinutes, profile, enforceNew);
} else {
double absoluteValue = profile.getBasal() * (percent /100.0d);
getMDTPumpStatus();
absoluteValue = pumpStatusLocal.pumpType.determineCorrectBasalSize(absoluteValue);
LOG.warn("setTempBasalPercent [MedtronicPumpPlugin] - You are trying to use setTempBasalPercent with percent other then 0% (%d). This will start setTempBasalAbsolute, with calculated value (%.3f). Result might not be 100% correct.", percent, absoluteValue);
return setTempBasalAbsolute(absoluteValue, durationInMinutes, profile, enforceNew);
}
}
private void finishAction(String overviewKey) {
if (overviewKey != null)

View file

@ -128,6 +128,7 @@ public class VirtualPumpPlugin extends PluginBase implements PumpInterface {
@Override
protected void onStop() {
MainApp.bus().unregister(this);
super.onStop();
}
@Subscribe

View file

@ -110,6 +110,7 @@ public class TreatmentsPlugin extends PluginBase implements TreatmentsInterface
@Override
protected void onStop() {
MainApp.bus().register(this);
super.onStop();
}
public TreatmentService getService() {
@ -294,14 +295,19 @@ public class TreatmentsPlugin extends PluginBase implements TreatmentsInterface
}
/**
* Returns all Treatments after specified timestamp. Also returns invalid entries (required to
* map "Fill Canulla" entries to history (and not to add double bolus for it)
*
* @param fromTimestamp
* @return
*/
@Override
public List<Treatment> getTreatmentsFromHistoryAfterTimestamp(long fromTimestamp) {
List<Treatment> in5minback = new ArrayList<>();
long time = System.currentTimeMillis();
synchronized (treatments) {
for (Treatment t : treatments) {
if (!t.isValid)
continue;
if (t.date <= time && t.date >= fromTimestamp)
in5minback.add(t);
}

View file

@ -1,9 +1,8 @@
package info.nightscout.androidaps.receivers;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import androidx.legacy.content.WakefulBroadcastReceiver;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -11,16 +10,15 @@ import org.slf4j.LoggerFactory;
import info.nightscout.androidaps.logging.L;
import info.nightscout.androidaps.services.DataService;
public class DataReceiver extends BroadcastReceiver {
public class DataReceiver extends WakefulBroadcastReceiver {
private static Logger log = LoggerFactory.getLogger(L.DATASERVICE);
@Override
public void onReceive(Context context, Intent intent) {
if (L.isEnabled(L.DATASERVICE))
log.debug("onReceive " + intent);
// Explicitly specify that GcmIntentService will handle the intent.
ComponentName comp = new ComponentName(context.getPackageName(),
DataService.class.getName());
DataService.enqueueWork(context, intent.setComponent(comp));
startWakefulService(context, new Intent(context, DataService.class)
.setAction(intent.getAction())
.putExtras(intent));
}
}

View file

@ -1,13 +1,10 @@
package info.nightscout.androidaps.services;
import android.content.Context;
import android.app.IntentService;
import android.content.Intent;
import android.os.Bundle;
import android.provider.Telephony;
import androidx.annotation.NonNull;
import androidx.core.app.JobIntentService;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
@ -19,16 +16,15 @@ import info.nightscout.androidaps.R;
import info.nightscout.androidaps.db.CareportalEvent;
import info.nightscout.androidaps.events.EventNsFood;
import info.nightscout.androidaps.events.EventNsTreatment;
import info.nightscout.androidaps.logging.BundleLogger;
import info.nightscout.androidaps.logging.L;
import info.nightscout.androidaps.plugins.general.nsclient.data.NSDeviceStatus;
import info.nightscout.androidaps.plugins.general.nsclient.data.NSMbg;
import info.nightscout.androidaps.plugins.general.nsclient.data.NSSettingsStatus;
import info.nightscout.androidaps.plugins.general.overview.events.EventNewNotification;
import info.nightscout.androidaps.plugins.general.overview.notifications.Notification;
import info.nightscout.androidaps.plugins.general.smsCommunicator.SmsCommunicatorPlugin;
import info.nightscout.androidaps.plugins.profile.ns.NSProfilePlugin;
import info.nightscout.androidaps.plugins.pump.danaR.activities.DanaRNSHistorySync;
import info.nightscout.androidaps.plugins.general.smsCommunicator.SmsCommunicatorPlugin;
import info.nightscout.androidaps.plugins.source.SourceDexcomPlugin;
import info.nightscout.androidaps.plugins.source.SourceEversensePlugin;
import info.nightscout.androidaps.plugins.source.SourceGlimpPlugin;
@ -38,30 +34,21 @@ import info.nightscout.androidaps.plugins.source.SourcePoctechPlugin;
import info.nightscout.androidaps.plugins.source.SourceTomatoPlugin;
import info.nightscout.androidaps.plugins.source.SourceXdripPlugin;
import info.nightscout.androidaps.receivers.DataReceiver;
import info.nightscout.androidaps.logging.BundleLogger;
import info.nightscout.androidaps.utils.JsonHelper;
import info.nightscout.androidaps.utils.SP;
public class DataService extends JobIntentService {
public class DataService extends IntentService {
private Logger log = LoggerFactory.getLogger(L.DATASERVICE);
// Service unique ID
static final int SERVICE_JOB_ID = 4378;
// Enqueuing work in to this service.
public static void enqueueWork(Context context, Intent work) {
enqueueWork(context, DataService.class, SERVICE_JOB_ID, work);
public DataService() {
super("DataService");
registerBus();
}
@Override
public void onDestroy() {
super.onDestroy();
if (L.isEnabled(L.DATASERVICE))
log.debug("All work complete");
}
@Override
protected void onHandleWork(@NonNull Intent intent) {
protected void onHandleIntent(final Intent intent) {
if (L.isEnabled(L.DATASERVICE)) {
log.debug("onHandleIntent " + intent);
log.debug("onHandleIntent " + BundleLogger.log(intent.getExtras()));
@ -113,7 +100,7 @@ public class DataService extends JobIntentService {
Intents.ACTION_REMOVED_TREATMENT.equals(action) ||
Intents.ACTION_NEW_CAL.equals(action) ||
Intents.ACTION_NEW_MBG.equals(action))
) {
) {
handleNewDataFromNSClient(intent);
} else if (Telephony.Sms.Intents.SMS_RECEIVED_ACTION.equals(action)) {
SmsCommunicatorPlugin.getPlugin().handleNewData(intent);
@ -121,6 +108,22 @@ public class DataService extends JobIntentService {
if (L.isEnabled(L.DATASERVICE))
log.debug("onHandleIntent exit " + intent);
DataReceiver.completeWakefulIntent(intent);
}
@Override
public void onDestroy() {
super.onDestroy();
MainApp.bus().unregister(this);
}
private void registerBus() {
try {
MainApp.bus().unregister(this);
} catch (RuntimeException x) {
// Ignore
}
MainApp.bus().register(this);
}
private void handleNewDataFromNSClient(Intent intent) {

View file

@ -11,10 +11,14 @@ import android.os.IBinder;
import androidx.core.app.ActivityCompat;
import com.squareup.otto.Subscribe;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.R;
import info.nightscout.androidaps.events.EventAppExit;
import info.nightscout.androidaps.events.EventLocationChange;
import info.nightscout.androidaps.logging.L;
import info.nightscout.androidaps.plugins.bus.RxBus;
@ -80,12 +84,14 @@ public class LocationService extends Service {
super.onStartCommand(intent, flags, startId);
if (L.isEnabled(L.LOCATION))
log.debug("onStartCommand");
startForeground(PersistentNotificationPlugin.ONGOING_NOTIFICATION_ID, PersistentNotificationPlugin.getPlugin().updateNotification());
startForeground(PersistentNotificationPlugin.ONGOING_NOTIFICATION_ID, PersistentNotificationPlugin.getPlugin().getLastNotification());
return START_STICKY;
}
@Override
public void onCreate() {
super.onCreate();
startForeground(PersistentNotificationPlugin.ONGOING_NOTIFICATION_ID, PersistentNotificationPlugin.getPlugin().getLastNotification());
if (L.isEnabled(L.LOCATION))
log.debug("onCreate");
@ -119,6 +125,7 @@ public class LocationService extends Service {
} catch (IllegalArgumentException ex) {
log.error("network provider does not exist, " + ex.getMessage());
}
MainApp.bus().register(this);
}
@Override
@ -136,6 +143,15 @@ public class LocationService extends Service {
log.error("fail to remove location listener, ignore", ex);
}
}
MainApp.bus().unregister(this);
}
@Subscribe
public void onStatusEvent(EventAppExit event) {
if (L.isEnabled(L.CORE))
log.debug("EventAppExit received");
stopSelf();
}
private void initializeLocationManager() {

View file

@ -3,6 +3,7 @@ package info.nightscout.androidaps.utils;
import android.Manifest;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.ActivityNotFoundException;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
@ -29,6 +30,8 @@ public class AndroidPermission {
public static final int CASE_BATTERY = 0x4;
public static final int CASE_PHONE_STATE = 0x5;
private static boolean permission_battery_optimization_failed = false;
@SuppressLint("BatteryLife")
private static void askForPermission(Activity activity, String[] permission, Integer requestCode) {
boolean test = false;
@ -45,10 +48,15 @@ public class AndroidPermission {
ActivityCompat.requestPermissions(activity, permission, requestCode);
}
if (testBattery) {
Intent i = new Intent();
i.setAction(Settings.ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS);
i.setData(Uri.parse("package:" + activity.getPackageName()));
activity.startActivityForResult(i, CASE_BATTERY);
try {
Intent i = new Intent();
i.setAction(Settings.ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS);
i.setData(Uri.parse("package:" + activity.getPackageName()));
activity.startActivityForResult(i, CASE_BATTERY);
} catch (ActivityNotFoundException e) {
permission_battery_optimization_failed = true;
OKDialog.show(activity, MainApp.gs(R.string.permission), MainApp.gs(R.string.alert_dialog_permission_battery_optimization_failed), activity::recreate);
}
}
}
@ -60,9 +68,11 @@ public class AndroidPermission {
public static boolean permissionNotGranted(Context context, String permission) {
boolean selfCheck = ContextCompat.checkSelfPermission(context, permission) == PackageManager.PERMISSION_GRANTED;
if (permission.equals(Manifest.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS)) {
PowerManager powerManager = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
String packageName = context.getPackageName();
selfCheck = selfCheck && powerManager.isIgnoringBatteryOptimizations(packageName);
if (!permission_battery_optimization_failed) {
PowerManager powerManager = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
String packageName = context.getPackageName();
selfCheck = selfCheck && powerManager.isIgnoringBatteryOptimizations(packageName);
}
}
return !selfCheck;
}

View file

@ -0,0 +1,9 @@
package info.nightscout.androidaps.utils
import io.reactivex.disposables.CompositeDisposable
import io.reactivex.disposables.Disposable
operator fun CompositeDisposable.plusAssign(disposable: Disposable) {
add(disposable)
}

View file

@ -0,0 +1,199 @@
package info.nightscout.androidaps.utils;
import android.text.InputType;
import android.text.SpannableStringBuilder;
import android.text.Spanned;
import android.text.method.NumberKeyListener;
import android.view.KeyEvent;
class DigitsKeyListenerWithComma extends NumberKeyListener {
/**
* The characters that are used.
*
* @see KeyEvent#getMatch
* @see #getAcceptedChars
*/
private static final char[][] CHARACTERS = new char[][]{
new char[]{'0', '1', '2', '3', '4', '5', '6', '7', '8', '9'},
new char[]{'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '-'},
new char[]{'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '.', ','},
new char[]{'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '-', '.', ','},
};
private char[] mAccepted;
private boolean mSign;
private boolean mDecimal;
private static final int SIGN = 1;
private static final int DECIMAL = 2;
private static DigitsKeyListenerWithComma[] sInstance = new DigitsKeyListenerWithComma[4];
@Override
protected char[] getAcceptedChars() {
return mAccepted;
}
/**
* Allocates a DigitsKeyListener that accepts the digits 0 through 9.
*/
public DigitsKeyListenerWithComma() {
this(false, false);
}
/**
* Allocates a DigitsKeyListener that accepts the digits 0 through 9,
* plus the minus sign (only at the beginning) and/or decimal point
* (only one per field) if specified.
*/
public DigitsKeyListenerWithComma(boolean sign, boolean decimal) {
mSign = sign;
mDecimal = decimal;
int kind = (sign ? SIGN : 0) | (decimal ? DECIMAL : 0);
mAccepted = CHARACTERS[kind];
}
/**
* Returns a DigitsKeyListener that accepts the digits 0 through 9.
*/
public static DigitsKeyListenerWithComma getInstance() {
return getInstance(false, false);
}
/**
* Returns a DigitsKeyListener that accepts the digits 0 through 9,
* plus the minus sign (only at the beginning) and/or decimal point
* (only one per field) if specified.
*/
public static DigitsKeyListenerWithComma getInstance(boolean sign, boolean decimal) {
int kind = (sign ? SIGN : 0) | (decimal ? DECIMAL : 0);
if (sInstance[kind] != null)
return sInstance[kind];
sInstance[kind] = new DigitsKeyListenerWithComma(sign, decimal);
return sInstance[kind];
}
/**
* Returns a DigitsKeyListener that accepts only the characters
* that appear in the specified String. Note that not all characters
* may be available on every keyboard.
*/
public static DigitsKeyListenerWithComma getInstance(String accepted) {
// TODO: do we need a cache of these to avoid allocating?
DigitsKeyListenerWithComma dim = new DigitsKeyListenerWithComma();
dim.mAccepted = new char[accepted.length()];
accepted.getChars(0, accepted.length(), dim.mAccepted, 0);
return dim;
}
public int getInputType() {
int contentType = InputType.TYPE_CLASS_NUMBER;
if (mSign) {
contentType |= InputType.TYPE_NUMBER_FLAG_SIGNED;
}
if (mDecimal) {
contentType |= InputType.TYPE_NUMBER_FLAG_DECIMAL;
}
return contentType;
}
@Override
public CharSequence filter(CharSequence source, int start, int end,
Spanned dest, int dstart, int dend) {
CharSequence out = super.filter(source, start, end, dest, dstart, dend);
if (mSign == false && mDecimal == false) {
return out;
}
if (out != null) {
source = out;
start = 0;
end = out.length();
}
int sign = -1;
int decimal = -1;
int dlen = dest.length();
/*
* Find out if the existing text has '-' or '.' characters.
*/
for (int i = 0; i < dstart; i++) {
char c = dest.charAt(i);
if (c == '-') {
sign = i;
} else if (c == '.' || c == ',') {
decimal = i;
}
}
for (int i = dend; i < dlen; i++) {
char c = dest.charAt(i);
if (c == '-') {
return ""; // Nothing can be inserted in front of a '-'.
} else if (c == '.' || c == ',') {
decimal = i;
}
}
/*
* If it does, we must strip them out from the source.
* In addition, '-' must be the very first character,
* and nothing can be inserted before an existing '-'.
* Go in reverse order so the offsets are stable.
*/
SpannableStringBuilder stripped = null;
for (int i = end - 1; i >= start; i--) {
char c = source.charAt(i);
boolean strip = false;
if (c == '-') {
if (i != start || dstart != 0) {
strip = true;
} else if (sign >= 0) {
strip = true;
} else {
sign = i;
}
} else if (c == '.' || c == ',') {
if (decimal >= 0) {
strip = true;
} else {
decimal = i;
}
}
if (strip) {
if (end == start + 1) {
return ""; // Only one character, and it was stripped.
}
if (stripped == null) {
stripped = new SpannableStringBuilder(source, start, end);
}
stripped.delete(i - start, i + 1 - start);
}
}
if (stripped != null) {
return stripped;
} else if (out != null) {
return out;
} else {
return null;
}
}
}

View file

@ -183,7 +183,8 @@ public class NumberPicker extends LinearLayout implements View.OnKeyListener,
}
setParams(initValue, minValue, maxValue, step, formater, allowZero, okButton);
this.textWatcher = textWatcher;
editText.addTextChangedListener(textWatcher);
if (textWatcher != null)
editText.addTextChangedListener(textWatcher);
}
public void setParams(Double initValue, Double minValue, Double maxValue, Double step, NumberFormat formater, boolean allowZero, Button okButton) {
@ -196,7 +197,7 @@ public class NumberPicker extends LinearLayout implements View.OnKeyListener,
callValueChangedListener();
this.okButton = okButton;
editText.setKeyListener(DigitsKeyListener.getInstance(minValue < 0, step != Math.rint(step)));
editText.setKeyListener(DigitsKeyListenerWithComma.getInstance(minValue < 0, step != Math.rint(step)));
if (textWatcher != null)
editText.removeTextChangedListener(textWatcher);

View file

@ -80,6 +80,7 @@ public class TimeListEdit {
private void buildView() {
layout = view.findViewById(resLayoutId);
layout.removeAllViewsInLayout();
textlabel = new TextView(context);
textlabel.setText(label);
@ -235,8 +236,8 @@ public class TimeListEdit {
if (i == 0) next = ONEHOURINSECONDS;
fillSpinner(timeSpinner, secondFromMidnight(i), previous, next);
editText1.setParams(value1(i), min, max, step, formatter, false, view.findViewById(R.id.localprofile_save));
editText2.setParams(value2(i), min, max, step, formatter, false, view.findViewById(R.id.localprofile_save));
editText1.setParams(value1(i), min, max, step, formatter, false,null);
editText2.setParams(value2(i), min, max, step, formatter, false, null);
if (data2 == null) {
editText2.setVisibility(View.GONE);
@ -350,7 +351,7 @@ public class TimeListEdit {
data1.put(index, newObject1);
if (data2 != null) {
JSONObject newObject2 = new JSONObject();
newObject1.put("time", time);
newObject2.put("time", time);
newObject2.put("timeAsSeconds", timeAsSeconds);
newObject2.put("value", value2);
data2.put(index, newObject2);

View file

@ -11,6 +11,27 @@
android:background="@color/ribbonDefault"
android:padding="8dp">
<CheckBox
android:id="@+id/automation_enabled"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentStart="true"
android:layout_alignParentTop="true" />
<TextView
android:id="@+id/viewEventTitle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignTop="@+id/automation_enabled"
android:layout_alignBottom="@+id/automation_enabled"
android:layout_centerVertical="true"
android:layout_marginTop="6dp"
android:layout_toStartOf="@+id/iconTrash"
android:layout_toEndOf="@id/automation_enabled"
android:text="Title"
android:textAlignment="viewStart"
android:textStyle="bold" />
<ImageView
android:id="@+id/iconTrash"
android:layout_width="wrap_content"
@ -22,25 +43,11 @@
android:src="@drawable/ic_trash_outline" />
<LinearLayout
android:layout_width="wrap_content"
android:id="@+id/iconLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentStart="true"
android:layout_alignParentTop="true"
android:layout_toStartOf="@id/iconTrash"
android:orientation="vertical"
app:layout_constraintTop_toTopOf="parent">
android:layout_below="@id/automation_enabled"
android:orientation="horizontal" />
<TextView
android:id="@+id/viewEventTitle"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<LinearLayout
android:id="@+id/iconLayout"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal" />
</LinearLayout>
</RelativeLayout>

View file

@ -1,197 +1,194 @@
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".plugins.profile.local.LocalProfileFragment">
<ScrollView
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
android:layout_height="wrap_content"
android:orientation="vertical">
<TextView
android:id="@+id/invalidprofile"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_horizontal"
android:text="@string/invalidprofile"
android:textAppearance="?android:attr/textAppearanceLarge"
android:textColor="@android:color/holo_red_light"
android:textStyle="bold" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/linearBlockBackground"
android:layout_marginStart="10dp"
android:text="@string/units"
android:textAppearance="?android:attr/textAppearanceMedium" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center_horizontal"
android:orientation="horizontal">
<RadioButton
android:id="@+id/localprofile_mgdl"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/mgdl" />
<RadioButton
android:id="@+id/localprofile_mmol"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/mmol" />
</LinearLayout>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/linearBlockBackground"
android:layout_marginStart="10dp"
android:text="@string/dia"
android:textAppearance="?android:attr/textAppearanceMedium" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_horizontal"
android:orientation="horizontal"
android:paddingTop="5dp"
android:textAppearance="?android:attr/textAppearanceSmall">
<!-- dummy to align with TimeListEdits added dynamically -->
<Spinner
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginEnd="10dp"
android:minWidth="80dp"
android:visibility="invisible"/>
<info.nightscout.androidaps.utils.NumberPicker
android:id="@+id/localprofile_dia"
android:layout_width="130dp"
android:layout_height="40dp"
android:layout_marginEnd="5dp"
android:layout_marginBottom="10dp"/>
<!-- dummy to align with TimeListEdits added dynamically -->
<ImageView
android:id="@+id/timelistedit_add"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginStart="15dp"
android:src="@drawable/add"
android:visibility="invisible"/>
<!-- dummy to align with TimeListEdits added dynamically -->
<ImageView
android:id="@+id/timelistedit_remove"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginStart="15dp"
android:src="@drawable/remove"
android:visibility="invisible"/>
</LinearLayout>
<LinearLayout
android:id="@+id/localprofile_ic"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginBottom="10dp"
android:orientation="vertical" />
<LinearLayout
android:id="@+id/localprofile_isf"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginBottom="10dp"
android:orientation="vertical" />
<LinearLayout
android:id="@+id/localprofile_basal"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginBottom="10dp"
android:orientation="vertical" />
<LinearLayout
android:id="@+id/localprofile_target"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginBottom="10dp"
android:orientation="vertical">
<TextView
android:id="@+id/invalidprofile"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_horizontal"
android:text="@string/invalidprofile"
android:textAppearance="?android:attr/textAppearanceLarge"
android:textColor="@android:color/holo_red_light"
android:textStyle="bold" />
</LinearLayout>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/linearBlockBackground"
android:layout_marginLeft="10px"
android:text="@string/units"
android:textAppearance="?android:attr/textAppearanceMedium" />
<Button
android:id="@+id/localprofile_profileswitch"
style="?android:attr/buttonStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:layout_marginBottom="3dp"
android:layout_marginLeft="10dp"
android:layout_marginRight="10dp"
android:layout_marginTop="3dp"
android:layout_weight="1"
android:paddingLeft="10dp"
android:paddingRight="10dp"
android:text="@string/activate_profile"
android:drawableStart="@drawable/icon_local_activate" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center_horizontal"
android:orientation="horizontal">
<RadioButton
android:id="@+id/localprofile_mgdl"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/mgdl" />
<RadioButton
android:id="@+id/localprofile_mmol"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/mmol" />
</LinearLayout>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/linearBlockBackground"
android:layout_marginLeft="10px"
android:text="@string/dia"
android:textAppearance="?android:attr/textAppearanceMedium" />
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_horizontal"
android:orientation="horizontal"
android:paddingTop="5dp"
android:textAppearance="?android:attr/textAppearanceSmall">
<!-- dummy to align with TimeListEdits added dynamically -->
<Spinner
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginRight="10dp"
android:minWidth="80dp"
android:visibility="invisible"/>
<info.nightscout.androidaps.utils.NumberPicker
android:id="@+id/localprofile_dia"
android:layout_width="130dp"
android:layout_height="40dp"
android:layout_marginRight="5dp"
android:layout_marginBottom="10dp"/>
<!-- dummy to align with TimeListEdits added dynamically -->
<ImageView
android:id="@+id/timelistedit_add"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginLeft="15dp"
android:src="@drawable/add"
android:visibility="invisible"/>
<!-- dummy to align with TimeListEdits added dynamically -->
<ImageView
android:id="@+id/timelistedit_remove"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginLeft="15dp"
android:src="@drawable/remove"
android:visibility="invisible"/>
</LinearLayout>
<LinearLayout
android:id="@+id/localprofile_ic"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginBottom="10dp"
android:orientation="vertical" />
<LinearLayout
android:id="@+id/localprofile_isf"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginBottom="10dp"
android:orientation="vertical" />
<LinearLayout
android:id="@+id/localprofile_basal"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginBottom="10dp"
android:orientation="vertical" />
<LinearLayout
android:id="@+id/localprofile_target"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginBottom="10dp"
android:orientation="vertical">
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:orientation="horizontal">
<Button
android:id="@+id/localprofile_profileswitch"
android:id="@+id/localprofile_reset"
style="?android:attr/buttonStyle"
android:layout_width="wrap_content"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:layout_marginBottom="3dp"
android:layout_marginLeft="10dp"
android:layout_marginRight="10dp"
android:layout_marginTop="3dp"
android:layout_marginRight="10dp"
android:layout_marginBottom="3dp"
android:layout_weight="1"
android:drawableStart="@drawable/icon_local_reset"
android:paddingLeft="10dp"
android:paddingRight="10dp"
android:text="@string/activate_profile"
android:drawableLeft="@drawable/icon_local_activate" />
android:text="@string/reset" />
<LinearLayout
android:layout_width="wrap_content"
<Button
android:id="@+id/localprofile_save"
style="?android:attr/buttonStyle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:orientation="horizontal">
<Button
android:id="@+id/localprofile_reset"
style="?android:attr/buttonStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:layout_marginBottom="3dp"
android:layout_marginLeft="10dp"
android:layout_marginRight="10dp"
android:layout_marginTop="3dp"
android:layout_weight="1"
android:paddingLeft="10dp"
android:paddingRight="10dp"
android:text="@string/reset"
android:drawableLeft="@drawable/icon_local_reset" />
<Button
android:id="@+id/localprofile_save"
style="?android:attr/buttonStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:layout_marginBottom="3dp"
android:layout_marginLeft="10dp"
android:layout_marginRight="10dp"
android:layout_marginTop="3dp"
android:layout_weight="1"
android:paddingLeft="10dp"
android:paddingRight="10dp"
android:text="@string/save"
android:drawableLeft="@drawable/icon_local_save" />
</LinearLayout>
android:layout_marginLeft="10dp"
android:layout_marginTop="3dp"
android:layout_marginRight="10dp"
android:layout_marginBottom="3dp"
android:layout_weight="1"
android:drawableStart="@drawable/icon_local_save"
android:paddingLeft="10dp"
android:paddingRight="10dp"
android:text="@string/save" />
</LinearLayout>
</ScrollView>
</LinearLayout>
</ScrollView>
</FrameLayout>

View file

@ -4,4 +4,12 @@
<string name="connection_failed">Αποτυχία σύνδεσης</string>
<string name="connection_lost">Απώλεια σύνδεσης</string>
<string name="pairing_rejected">Σύζευξη απορρίφθηκε</string>
<string name="socket_creation_failed">Αποτυχία δημιουργίας σύνδεσης</string>
<string name="timeout">Τέλος χρονικού ορίου</string>
<string name="maximum_number_of_bolus_type_already_running">Μέγιστος αριθμός τύπων bolus ήδη τρέχει</string>
<string name="no_active_tbr_to_cancel">Μη ενεργός TBR για ακύρωση</string>
<string name="no_active_tbr_to_change">Μη ενεργός TBR για αλλαγή</string>
<string name="no_such_bolus_to_cancel">Όχι τέτοιο bolus για ακύρωση</string>
<string name="pump_already_in_that_state_exception">Η αντλία είναι ήδη σε αυτό το στάδιο</string>
<string name="run_mode_not_allowed">Δεν επιτρέπεται το στάδιο Run</string>
</resources>

View file

@ -146,6 +146,7 @@
<string name="openapsma_lastenact_label">Τελευταία εφαρμογή</string>
<string name="ok">ΟΚ</string>
<string name="cancel">Ακύρωση</string>
<string name="close">Κλείσιμο</string>
<string name="noapsselected">ΔΕΝ ΕΠΙΛΕΧΘΗΚΕ APS Ή ΒΡΕΘΗΚΕ ΑΠΟΤΕΛΕΣΜΑ</string>
<string name="safety">Ασφάλεια</string>
<string name="openapsma_disabled">Προσθήκη απενεργοποιημένη</string>
@ -830,6 +831,7 @@
<string name="insight_incompatible">Μη συμβατό</string>
<string name="second">δευτερόλεπτο</string>
<string name="minute">λεπτό</string>
<string name="format_hours">%1$.2f h</string>
<string name="hour">ώρα</string>
<string name="day">ημέρα</string>
<string name="week">εβδομάδα</string>
@ -1079,6 +1081,7 @@
<string name="speederror">Σφάλμα ταχύτητας</string>
<string name="insulinlimitviolation">Υπέρβαση του ορίου ινσουλίνης</string>
<string name="loop_openmode_min_change">Ελάχιστο αίτημα για αλλαγή [%]</string>
<string name="loop_openmode_min_change_summary">Το Ανοιχτό κύκλωμα θα εμφανίσει νέο μήνυμα αλλαγής μόνο αν η αλλαγή είναι μεγαλύτερη από αυτήν τη τιμή %. Προεπιλεγμένη τιμή 20%</string>
<string name="pairfirst">Παρακαλώ συνδέστε την αντλία στο τηλέφωνο!</string>
<string name="searching_for_devices">Αναζήτηση συσκευών…</string>
<string name="please_wait">Περιμένετε…</string>
@ -1188,6 +1191,7 @@
<string name="automation_short">Αυτόματο</string>
<string name="automation">Αυτοματισμός</string>
<string name="profile_total">== ∑ %1$s U</string>
<string name="profile_ins_units_per_hour">U/h</string>
<string name="profile_carbs_per_unit">g/U</string>
<string name="profile_per_unit">/U</string>
<string name="dexcom_lognssensorchange_title">Αλλαγή αρχείου αισθητήρα σε NS</string>
@ -1234,7 +1238,14 @@
<string name="condition">Κατάσταση:</string>
<string name="action">Ενέργεια:</string>
<string name="iob_u">ΙΟΒ [U]:</string>
<string name="glucose_u">Γλυκόζη [%1$s]:</string>
<string name="delete_short">ΔΙΑΓΡ</string>
<string name="add_short">Προσθ</string>
<string name="copy_short">Αντιγραφή</string>
<string name="addnew">Προσθήκη νέου</string>
<string name="versionChecker">Έλεγχος Έκδοσης</string>
<string name="signature_verifier">Έλεγχος υπογραφής</string>
<string name="running_invalid_version">Διαπιστώσαμε ότι εκτελείτε μη έγκυρη έκδοση. Κύκλωμα απενεργοποιήθηκε!</string>
<string name="old_version">παλιά έκδοση</string>
<string name="very_old_version">πολύ παλιά έκδοση</string>
<string name="new_version_warning">Νέα έκδοση για τουλάχιστον %1$d ημέρες διαθέσιμη! Επιστροφή σε LGS μετά από 60 ημέρες, το κύκλωμα θα απενεργοποιηθεί μετά από 90 ημέρες</string>
@ -1243,9 +1254,52 @@
<string name="dexcom_app_patched">Εφαρμογή Dexcom (τροποποιημένη)</string>
<string name="dexcom_short">DXCM</string>
<string name="description_source_dexcom">Λάβετε τις τιμές BG από την εφαρμογή του Dexcom.</string>
<string name="notification">Ειδοποίηση</string>
<string name="notification_message">Ειδοποίηση: %1$s</string>
<string name="message_short">Μην:</string>
<string name="profilepercentage">Προφίλ ποσοστό</string>
<string name="percent_u">Ποσοστό [%]:</string>
<string name="startprofile">Έναρξη προφίλ %1$d%% για %2$d λεπτά</string>
<string name="startprofileforever">Έναρξη προφίλ %1$d%%</string>
<string name="exists">υπάρχει</string>
<string name="notexists">δεν υπάρχει</string>
<string name="temptargetcompared">Προσ. στόχος %1$s</string>
<string name="wifissidcompared">WiFi SSID %1$s %2$s</string>
<string name="autosenscompared">Autosens %1$s %2$s %%</string>
<string name="autosenslabel">Autosens %</string>
<string name="deltacompared">%3$s %1$s %2$s</string>
<string name="deltalabel">Διαφορά BG</string>
<string name="currentlocation">Τρέχουσα θέση</string>
<string name="location">Τοποθεσία</string>
<string name="latitude_short">Lat:</string>
<string name="longitude_short">Lon:</string>
<string name="distance_short">Αποστ [m]:</string>
<string name="name_short">Όνομα:</string>
<string name="locationis">Η τοποθεσία είναι %1$s</string>
<string name="lastboluslabel">Τελευταίο Bolus</string>
<string name="lastboluscompared">Τελευταίο bolus %1$s %2$s λεπτά πριν</string>
<string name="triggercoblabel">COB</string>
<string name="cobcompared">COB %1$s %2$.0f</string>
<string name="taskname">Όνομα εργασίας</string>
<string name="eventname">Όνομα συμβάντος</string>
<string name="edit_short">Επεξεργασία</string>
<string name="please_choose_an_action_type">Επιλέξτε έναν τύπο δράσης:</string>
<string name="please_choose_a_trigger_type">Επιλέξτε έναν τύπο ενεργοποίησης:</string>
<string name="if_label">Αν:</string>
<string name="then_label">Έπειτα:</string>
<string name="triggers">Ενεργοποιήσεις:</string>
<string name="remove_label">ΜΕΤΑΚΙΝΗΣΗ</string>
<string name="preconditions">Προϋποθέσεις:</string>
<!-- Pump Abstract -->
<string name="pump_operation_not_supported_by_pump_driver">Η λειτουργία δεν υποστηρίζεται από την αντλία ή/και οδηγό.</string>
<string name="pump_operation_not_yet_supported_by_pump">Η λειτουργία δεν υποστηρίζεται ΑΚΟΜΑ από την αντλία.</string>
<!-- Medtronic (MDT) - Base -->
<string name="description_pump_medtronic">Η ολοκλήρωση της αντλίας για τη Medtronic, απαιτεί τη συσκευή RileyLink και το συγκεκριμένο μοντέλο αντλίας</string>
<!-- MDT Configuration -->
<string name="medtronic_serial_number">Σειριακός Αριθμός Αντλίας</string>
<string name="medtronic_pump_type">Τύπος Αντλίας</string>
<string name="medtronic_pump_frequency">Συχνότητα Αντλίας</string>
<string name="medtronic_pump_bolus_delay">Η καθυστέρηση πριν το bolus ξεκίνησε (s)</string>
<string name="medtronic_pump_max_bolus">Μέγιστο Bolus στην αντλία (U)</string>
<string name="medtronic_pump_max_basal">Μέγιστος Βασικός στην αντλία (U/h)</string>
<string name="medtronic_pump_encoding">Αποκωδικοποίηση Medtronic</string>
@ -1299,16 +1353,67 @@
<!-- RL State -->
<string name="rileylink_state_bt_init">Επαναφορά Bluetooth…</string>
<string name="rileylink_state_bt_error">Σφάλμα Bluetooth</string>
<string name="rileylink_state_bt_ready">Bluetooth Έτοιμο</string>
<string name="rileylink_state_not_started">Δεν ξεκίνησε</string>
<string name="rileylink_state_rl_init">Αρχικοποίηση του RileyLink…</string>
<string name="rileylink_state_rl_error">RileyLink Σφάλμα</string>
<string name="rileylink_state_pc_tune_up">Ρύθμιση του RileyLink και της αντλίας</string>
<string name="rileylink_state_pc_error">Πρόβλημα σύνδεσης με την Αντλία</string>
<string name="rileylink_state_connected">Συνδέθηκε</string>
<!-- RL Errors -->
<string name="rileylink_error_not_rl">Η συσκευή δεν είναι RileyLink</string>
<string name="rileylink_error_unreachable">Το RileyLink μη προσπελάσιμο</string>
<string name="rileylink_error_bt_disabled">Bluetooth απενεργοποιημένο</string>
<string name="rileylink_error_no_bt_adapter">Δεν υπάρχει προσαρμογέας Bluetooth</string>
<string name="rileylink_error_tuneup_failed">TuneUp απέτυχε</string>
<string name="rileylink_error_pump_unreachable">Η αντλία δεν είναι διαθέσιμη</string>
<string name="rileylink_error_pod_unreachable">Το Pod δεν είναι διαθέσιμο</string>
<string name="rileylink_error_address_not_set_short">Μη ορισμένο</string>
<!-- RL Target Device -->
<string name="rileylink_target_device_medtronic">Αντλία Medtronic</string>
<string name="rileylink_target_device_omnipod">Omnipod</string>
<!-- MDT Errors -->
<string name="medtronic_errors">Σφάλματα</string>
<string name="medtronic_error_serial_not_set">Δεν ορίστηκε # Serial.</string>
<string name="medtronic_error_serial_invalid">Serial # μη έγκυρο.</string>
<string name="medtronic_error_pump_type_not_set">Δεν ορίστηκε Τύπος Αντλίας.</string>
<string name="medtronic_error_pump_type_invalid">Τύπος Αντλίας δεν υποστηρίζεται.</string>
<string name="medtronic_error_pump_frequency_not_set">Δεν ορίστηκε Συχνότητα Αντλίας.</string>
<string name="medtronic_error_pump_frequency_invalid">Συχνότητα Αντλίας δεν υποστηρίζεται.</string>
<string name="medtronic_error_rileylink_address_invalid">Διεύθυνση RileyLink μη έγκυρη.</string>
<string name="medtronic_error_pump_type_set_differs_from_detected">Ο τύπος αντλίας που ανιχνεύτηκε δεν είναι ο ίδιος με αυτόν που ορίστηκε.</string>
<string name="medtronic_error_pump_basal_profiles_not_enabled">Τα προφίλ βασικού δεν είναι ενεργοποιημένα στην αντλία.</string>
<string name="medtronic_error_pump_incorrect_basal_profile_selected">Το βασικό προφίλ που ορίστηκε στην αντλία είναι λάθoς (πρέπει να είναι STD).</string>
<string name="medtronic_error_pump_wrong_tbr_type_set">Λάθος τύπος TBR ορίστηκε στην αντλία (πρέπει να είναι Absolute).</string>
<string name="medtronic_error_pump_wrong_max_bolus_set">Λάθος μέγιστο bolus ορίστηκε στην αντλία (πρέπει να είναι %1$.2f).</string>
<string name="medtronic_error_pump_wrong_max_basal_set">Λάθος μέγιστο Βασικού ορίστηκε στην αντλία (πρέπει να είναι %1$.2f).</string>
<string name="medtronic_error_operation_not_possible_no_configuration">Λειτουργία δεν είναι δυνατή. \n\n Χρειάζεται να ρυθμίσετε την αντλία Medtronic πρώτα, προτού να μπορέσετε να χρησιμοποιήσετε αυτή την λειτουργία.</string>
<string name="medtronic_error_pump_24h_time_change_requested">Απαιτήθηκε αλλαγή ώρας πάνω από 24h.</string>
<!-- MDT History -->
<string name="medtronic_history_group_basal">Βασικοί</string>
<string name="medtronic_history_group_configuration">Ρύθμιση παραμέτρων</string>
<string name="medtronic_history_group_notification">Ειδοποιήσεις</string>
<string name="medtronic_history_group_statistic">Στατιστικά</string>
<string name="medtronic_history_group_unknown">Άγνωστα</string>
<string name="medtronic_history_group_all">Όλα</string>
<string name="medtronic_pump_history">Ιστορικό Αντλίας Medtronic</string>
<!-- MDT Pump Status -->
<string name="medtronic_pump_status_never_contacted">Ποτέ δεν επικοινωνήσατε</string>
<string name="medtronic_pump_status_waking_up">Ξύπνημα</string>
<string name="medtronic_pump_status_error_comm">Σφάλμα με επικοινωνία</string>
<string name="medtronic_pump_status_timeout_comm">Λήξη χρόνου επικοινωνίας</string>
<string name="medtronic_pump_status_problem_contacting">Πρόβλημα επικοινωνίας με Αντλία</string>
<string name="medtronic_pump_status_pump_unreachable">Η αντλία δεν είναι διαθέσιμη</string>
<string name="medtronic_pump_status_invalid_config">Μη έγκυρη παραμετροποίηση</string>
<string name="medtronic_pump_status_active">Ενεργή</string>
<string name="medtronic_pump_status_sleeping">Sleeping</string>
<!-- <string name="medtronic_cmd_profile_not_set">Remote Basal profile setting is not supported. Please modify Basal profile on your pump manually.</string> -->
<string name="medtronic_cmd_cancel_bolus_not_supported">Ακυρώσατε τον Bolus, αφού είχε ήδη σταλεί στην αντλία. Επειδή η αντλία Medtronic δεν υποστηρίζει ακύρωση, θα χρειαστεί να ακυρωθεί χειροκίνητα. Βάλτε την αντλία σε αναστολή λειτουργίας και μετά κάντε Συνέχιση (αν θέλετε να ακυρώσετε ακόμα). Η εφαρμογή θα πάρει τις αλλαγές, στην επόμενη ενημέρωση (σε λιγότερο από 5 λεπτά).</string>
<string name="medtronic_cmd_cant_read_tbr">Αδυναμία ανάγνωσης τρέχοντος TBR.</string>
<string name="medtronic_cmd_cant_cancel_tbr_stop_op">Αδυναμία ακύρωσης τρέχοντος TBR. Αναστολή λειτουργίας.</string>
<string name="medtronic_cmd_set_profile_pattern_overflow">Η δημιουργία προφίλ απέτυχε, επειδή ακολουθώντας πρότυπα, έχετε υπερβολικά μεγάλο βασικό ρυθμό: %1$s</string>
<string name="medtronic_cmd_bolus_could_not_be_delivered">Το Bolus δεν μπορεί να χορηγηθεί.</string>
<string name="medtronic_cmd_bolus_could_not_be_delivered_no_insulin">Το Bolus δεν μπορεί να παραδοθεί διότι η διαθέσιμη ποσότητα ινσουλίνης (%1$.2f) είναι μικρότερη από αυτήν που ζητείται (%2$.2f).</string>
<string name="medtronic_cmd_tbr_could_not_be_delivered">TBR δεν μπορεί να μπει.</string>
<string name="medtronic_cmd_cant_cancel_tbr">Αδυναμία ακύρωσης τρέχοντος TBR.</string>
<string name="medtronic_cmd_basal_profile_could_not_be_set">Το Βασικό Προφίλ δεν μπορεί να τοποθετηθεί.</string>
@ -1327,6 +1432,9 @@
<string name="pump_no_connection_h">Αποσυνδεδεμένο για %1$d ώρες %2$d λεπτά</string>
<string name="pump_no_connection_d">Αποσυνδεδεμένο για %1$d μέρες %2$d ώρες</string>
<string name="insulinFromCob"><![CDATA[Ινσουλίνη COB: <font color=\'%1$s\'>%2$.1fg %3$.2f</font>]]></string>
<string name="bolusconstraintappliedwarning"><![CDATA[<font color=\'%1$s\'>Bolus constraint applied: %2$.2fU to %3$.2fU</font>]]></string>
<string name="slowabsorptiondetected"><![CDATA[<font color=\'%1$s\'>!!!!! Μικρή απορρόφηση υδατανθράκων ανιχνεύτηκε: %2$d%% της ώρας. Τσεκάρετε τους υπολογισμούς σας. COB μπορεί να είναι κλειστό</font>]]></string>
<string name="reservoirvalue">%1$.0f / %2$d U</string>
<plurals name="objective_days">
<item quantity="one">%1$d ημέρα</item>
<item quantity="other">%1$d ημέρες</item>

View file

@ -146,6 +146,7 @@
<string name="openapsma_lastenact_label">Ostatnie działanie</string>
<string name="ok">OK</string>
<string name="cancel">Anuluj</string>
<string name="close">Zamknij</string>
<string name="noapsselected">NIE WYBRANO APS LUB NIE UZYSKANO WYNIKU</string>
<string name="safety">Zabezpieczenia</string>
<string name="openapsma_disabled">Wtyczka jest wyłączona</string>
@ -831,6 +832,7 @@
<string name="insight_incompatible">Niekompatybilny</string>
<string name="second">sekunda</string>
<string name="minute">minuta</string>
<string name="format_hours">%1$.2f h</string>
<string name="hour">godzina</string>
<string name="day">dzień</string>
<string name="week">tydzień</string>
@ -1190,6 +1192,7 @@
<string name="automation_short">Auto</string>
<string name="automation">Automatyzacja</string>
<string name="profile_total">== ∑ %1$s U</string>
<string name="profile_ins_units_per_hour">U/h</string>
<string name="profile_carbs_per_unit">g/U</string>
<string name="profile_per_unit">/U</string>
<string name="dexcom_lognssensorchange_title">Prześlij zmianę sensora do NS</string>
@ -1247,7 +1250,6 @@
<string name="old_version">stara wersja</string>
<string name="very_old_version">bardzo stara wersja</string>
<string name="new_version_warning">Nowa wersja dostępna co najmniej %1$d dni! Powrót do LGS (zawieszania podawania bazy przy niskim poziomie) po 60 dniach, pętla zostanie wyłączona po 90 dniach</string>
<string name="scale_insulin_activity">Graficzny wykres aktywności insuliny [U/min]</string>
<string name="twohours">2 h</string>
<string name="formatinsulinunits">%1$.2fU</string>
<string name="dexcom_app_patched">Apka Dexcom (spatchowana)</string>
@ -1412,6 +1414,7 @@
<string name="medtronic_cmd_cant_cancel_tbr_stop_op">Nie udało się anulować aktualnej dawki tymczasowej (TBR). Operacja zatrzymania.</string>
<string name="medtronic_cmd_set_profile_pattern_overflow">Ustawienia Profilu nie powiodły się ponieważ następująca wartość jest za duża: %1$s</string>
<string name="medtronic_cmd_bolus_could_not_be_delivered">Nie udało się dostarczyć bolusa.</string>
<string name="medtronic_cmd_bolus_could_not_be_delivered_no_insulin">Bolus nie mógł być dostarczony ponieważ Ilość dostępnej insuliny (%1$.2f) jest mniejsza niż wymagany bolus (%2$.2f).</string>
<string name="medtronic_cmd_tbr_could_not_be_delivered">Nie udało się ustawić dawki tymczasowej (TBR).</string>
<string name="medtronic_cmd_cant_cancel_tbr">Nie udało się anulować bazy tymczasowej (TBR).</string>
<string name="medtronic_cmd_basal_profile_could_not_be_set">Profil bazy nie został ustawiony.</string>
@ -1432,6 +1435,7 @@
<string name="insulinFromCob"><![CDATA[Insulina COB: <font color=\'%1$s\'>%2$.1fg %3$.2fU</font>]]></string>
<string name="bolusconstraintappliedwarning"><![CDATA[<font color=\'%1$s\'>Wprowadzono ograniczenie bolusa: %2$.2fU to %3$.2fU</font>]]></string>
<string name="slowabsorptiondetected"><![CDATA[<font color=\'%1$s\'>!!!!! Wykryto powolne wchłanianie węglowodanów: %2$d%% czasu. Sprawdź ponownie swoje obliczenia. COB mogą się znacznie różnić !!!!!</font>]]></string>
<string name="reservoirvalue">%1$.0f / %2$d U</string>
<plurals name="objective_days">
<item quantity="one">%1$d dzień</item>
<item quantity="few">%1$d dni</item>

View file

@ -38,6 +38,7 @@
<string name="danar_bt_name_title">DanaR Bluetooth device</string>
<string name="ns_sync_use_absolute_title">Always use basal absolute values</string>
<string name="alert_dialog_storage_permission_text">Please reboot your phone or restart AndroidAPS from the System Settings \notherwise Android APS will not have logging (important to track and verify that the algorithms are working correctly)!</string>
<string name="alert_dialog_permission_battery_optimization_failed">This device does not appear to support battery optimization whitelisting - you may experience performance issues.</string>
<string name="description_actions">Some buttons to quickly access common features</string>
<string name="description_careportal">Enter advanced log book entries.</string>
@ -1462,6 +1463,7 @@
<string name="autosenslabel">Autosens %</string>
<string name="deltacompared">%3$s %1$s %2$s</string>
<string name="deltalabel">BG difference</string>
<string name="deltalabel_u">BG difference [%1$s]</string>
<string name="currentlocation">Current Location</string>
<string name="location">Location</string>
<string name="latitude_short">Lat:</string>
@ -1670,6 +1672,7 @@
<string name="key_boluswizard_percentage" translatable="false">boluswizard_percentage</string>
<string name="partialboluswizard">Deliver this part of bolus wizard result [%]</string>
<string name="deliverpartofboluswizard">Bolus wizard performs calculation but only this part of calculated insulin is delivered. Useful with SMB algorithm.</string>
<string name="loading">Loading ...</string>
<plurals name="objective_days">
<item quantity="one">%1$d day</item>

View file

@ -22,7 +22,7 @@ public class AutomationEventTest {
event.addAction(new ActionLoopEnable());
// export to json
final String eventJsonExpected = "{\"trigger\":\"{\\\"data\\\":{\\\"connectorType\\\":\\\"AND\\\",\\\"triggerList\\\":[\\\"{\\\\\\\"data\\\\\\\":{\\\\\\\"connectorType\\\\\\\":\\\\\\\"AND\\\\\\\",\\\\\\\"triggerList\\\\\\\":[]},\\\\\\\"type\\\\\\\":\\\\\\\"info.nightscout.androidaps.plugins.general.automation.triggers.TriggerConnector\\\\\\\"}\\\"]},\\\"type\\\":\\\"info.nightscout.androidaps.plugins.general.automation.triggers.TriggerConnector\\\"}\",\"title\":\"Test\",\"actions\":[\"{\\\"type\\\":\\\"info.nightscout.androidaps.plugins.general.automation.actions.ActionLoopEnable\\\"}\"]}";
final String eventJsonExpected = "{\"trigger\":\"{\\\"data\\\":{\\\"connectorType\\\":\\\"AND\\\",\\\"triggerList\\\":[\\\"{\\\\\\\"data\\\\\\\":{\\\\\\\"connectorType\\\\\\\":\\\\\\\"AND\\\\\\\",\\\\\\\"triggerList\\\\\\\":[]},\\\\\\\"type\\\\\\\":\\\\\\\"info.nightscout.androidaps.plugins.general.automation.triggers.TriggerConnector\\\\\\\"}\\\"]},\\\"type\\\":\\\"info.nightscout.androidaps.plugins.general.automation.triggers.TriggerConnector\\\"}\",\"title\":\"Test\",\"actions\":[\"{\\\"type\\\":\\\"info.nightscout.androidaps.plugins.general.automation.actions.ActionLoopEnable\\\"}\"],\"enabled\":true}";
Assert.assertEquals(eventJsonExpected, event.toJSON());
// clone

View file

@ -16,8 +16,8 @@ import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.R;
import info.nightscout.androidaps.db.TempTarget;
import info.nightscout.androidaps.plugins.configBuilder.ProfileFunctions;
import info.nightscout.androidaps.plugins.general.automation.elements.InputBg;
import info.nightscout.androidaps.plugins.general.automation.elements.InputDuration;
import info.nightscout.androidaps.plugins.general.automation.elements.InputTempTarget;
import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin;
import info.nightscout.androidaps.queue.Callback;
import info.nightscout.androidaps.utils.SP;
@ -40,7 +40,7 @@ public class ActionStartTempTargetTest {
public void shortDescriptionTest() {
actionStartTempTarget = new ActionStartTempTarget();
actionStartTempTarget.reason = "Test";
actionStartTempTarget.value = new InputBg().setValue(100).setUnits(Constants.MGDL);
actionStartTempTarget.value = new InputTempTarget().setValue(100).setUnits(Constants.MGDL);
actionStartTempTarget.duration = new InputDuration(30, InputDuration.TimeUnit.MINUTES);
Assert.assertEquals("Start temp target: 100mg/dl@null(Test)", actionStartTempTarget.shortDescription());
}
@ -70,7 +70,7 @@ public class ActionStartTempTargetTest {
public void toJSONTest() {
actionStartTempTarget = new ActionStartTempTarget();
actionStartTempTarget.reason = "Test";
actionStartTempTarget.value = new InputBg().setValue(100).setUnits(Constants.MGDL);
actionStartTempTarget.value = new InputTempTarget().setValue(100).setUnits(Constants.MGDL);
actionStartTempTarget.duration = new InputDuration(30, InputDuration.TimeUnit.MINUTES);
Assert.assertEquals("{\"data\":{\"reason\":\"Test\",\"durationInMinutes\":30,\"units\":\"mg/dl\",\"value\":100},\"type\":\"info.nightscout.androidaps.plugins.general.automation.actions.ActionStartTempTarget\"}", actionStartTempTarget.toJSON());
}

View file

@ -16,27 +16,14 @@ import info.nightscout.androidaps.plugins.configBuilder.ProfileFunctions;
@PrepareForTest({MainApp.class, ProfileFunctions.class})
public class InputBgTest {
@Test
public void textWatcherTest() {
InputBg t = new InputBg().setUnits(Constants.MMOL).setValue(1d);
t.textWatcher.beforeTextChanged(null, 0, 0, 0);
t.textWatcher.onTextChanged(null, 0, 0, 0);
t.textWatcher.afterTextChanged(null);
Assert.assertEquals(4d, t.getValue(), 0.01d);
t = new InputBg().setValue(300d).setUnits(Constants.MGDL);
t.textWatcher.afterTextChanged(null);
Assert.assertEquals(270d, t.getValue(), 0.01d);
}
@Test
public void getSetValueTest() {
InputBg i = new InputBg().setUnits(Constants.MMOL).setValue(5d);
Assert.assertEquals(5d, i.getValue(), 0.01d);
Assert.assertEquals(2, i.minValue, 0.01d);
Assert.assertEquals(InputBg.MMOL_MIN, i.minValue, 0.01d);
i = new InputBg().setValue(100d).setUnits(Constants.MGDL);
Assert.assertEquals(100d, i.getValue(), 0.01d);
Assert.assertEquals(40, i.minValue, 0.01d);
Assert.assertEquals(InputBg.MGDL_MIN, i.minValue, 0.01d);
Assert.assertEquals(Constants.MGDL, i.getUnits());
}

View file

@ -0,0 +1,38 @@
package info.nightscout.androidaps.plugins.general.automation.elements;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
import info.AAPSMocker;
import info.nightscout.androidaps.Constants;
import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.plugins.configBuilder.ProfileFunctions;
@RunWith(PowerMockRunner.class)
@PrepareForTest({MainApp.class, ProfileFunctions.class})
public class InputTempTargetTest {
@Test
public void getSetValueTest() {
InputTempTarget i = new InputTempTarget().setUnits(Constants.MMOL).setValue(5d);
Assert.assertEquals(5d, i.getValue(), 0.01d);
Assert.assertEquals(Constants.MIN_TT_MMOL, i.minValue, 0.01d);
i = new InputTempTarget().setValue(100d).setUnits(Constants.MGDL);
Assert.assertEquals(100d, i.getValue(), 0.01d);
Assert.assertEquals(Constants.MIN_TT_MGDL, i.minValue, 0.01d);
Assert.assertEquals(Constants.MGDL, i.getUnits());
}
@Before
public void prepare() {
AAPSMocker.mockMainApp();
AAPSMocker.mockBus();
AAPSMocker.mockStrings();
AAPSMocker.mockProfileFunctions();
}
}