Triggers injection
This commit is contained in:
parent
bd1b1d8d76
commit
925de127a7
90 changed files with 2778 additions and 4284 deletions
|
@ -4,11 +4,15 @@ import dagger.BindsInstance
|
||||||
import dagger.Component
|
import dagger.Component
|
||||||
import dagger.android.AndroidInjectionModule
|
import dagger.android.AndroidInjectionModule
|
||||||
import dagger.android.AndroidInjector
|
import dagger.android.AndroidInjector
|
||||||
|
import dagger.android.ContributesAndroidInjector
|
||||||
import info.nightscout.androidaps.MainApp
|
import info.nightscout.androidaps.MainApp
|
||||||
import info.nightscout.androidaps.db.BgReading
|
import info.nightscout.androidaps.db.BgReading
|
||||||
import info.nightscout.androidaps.plugins.aps.openAPSMA.LoggerCallback
|
import info.nightscout.androidaps.plugins.aps.openAPSMA.LoggerCallback
|
||||||
import info.nightscout.androidaps.plugins.constraints.objectives.objectives.*
|
import info.nightscout.androidaps.plugins.constraints.objectives.objectives.*
|
||||||
|
import info.nightscout.androidaps.plugins.general.automation.AutomationEvent
|
||||||
import info.nightscout.androidaps.plugins.general.automation.actions.*
|
import info.nightscout.androidaps.plugins.general.automation.actions.*
|
||||||
|
import info.nightscout.androidaps.plugins.general.automation.elements.*
|
||||||
|
import info.nightscout.androidaps.plugins.general.automation.triggers.*
|
||||||
import info.nightscout.androidaps.plugins.general.overview.notifications.NotificationWithAction
|
import info.nightscout.androidaps.plugins.general.overview.notifications.NotificationWithAction
|
||||||
import info.nightscout.androidaps.plugins.treatments.Treatment
|
import info.nightscout.androidaps.plugins.treatments.Treatment
|
||||||
import info.nightscout.androidaps.queue.commands.CommandSetProfile
|
import info.nightscout.androidaps.queue.commands.CommandSetProfile
|
||||||
|
@ -38,6 +42,26 @@ interface AppComponent : AndroidInjector<MainApp> {
|
||||||
fun injectObjective5(objective5: Objective5)
|
fun injectObjective5(objective5: Objective5)
|
||||||
fun injectObjective6(objective6: Objective6)
|
fun injectObjective6(objective6: Objective6)
|
||||||
|
|
||||||
|
fun injectAutomationEvent(automationEvent: AutomationEvent)
|
||||||
|
|
||||||
|
fun injectTrigger(trigger: Trigger)
|
||||||
|
fun injectTrigger(triggerAutosensValue: TriggerAutosensValue)
|
||||||
|
fun injectTrigger(triggerBg: TriggerBg)
|
||||||
|
fun injectTrigger(triggerBolusAgo: TriggerBolusAgo)
|
||||||
|
fun injectTrigger(triggerCOB: TriggerCOB)
|
||||||
|
fun injectTrigger(triggerConnector: TriggerConnector)
|
||||||
|
fun injectTrigger(triggerDelta: TriggerDelta)
|
||||||
|
fun injectTrigger(triggerDummy: TriggerDummy)
|
||||||
|
fun injectTrigger(triggerIob: TriggerIob)
|
||||||
|
fun injectTrigger(triggerLocation: TriggerLocation)
|
||||||
|
fun injectTrigger(triggerProfilePercent: TriggerProfilePercent)
|
||||||
|
fun injectTrigger(triggerPumpLastConnection: TriggerPumpLastConnection)
|
||||||
|
fun injectTrigger(triggerRecurringTime: TriggerRecurringTime)
|
||||||
|
fun injectTrigger(triggerTempTarget: TriggerTempTarget)
|
||||||
|
fun injectTrigger(triggerTime: TriggerTime)
|
||||||
|
fun injectTrigger(triggerTimeRange : TriggerTimeRange)
|
||||||
|
fun injectTrigger(triggerWifiSsid: TriggerWifiSsid)
|
||||||
|
|
||||||
fun injectAction(action: Action)
|
fun injectAction(action: Action)
|
||||||
fun injectActionDummy(action: ActionDummy)
|
fun injectActionDummy(action: ActionDummy)
|
||||||
fun injectActionLoopDisable(action: ActionLoopDisable)
|
fun injectActionLoopDisable(action: ActionLoopDisable)
|
||||||
|
@ -51,6 +75,23 @@ interface AppComponent : AndroidInjector<MainApp> {
|
||||||
fun injectActionStartTempTarget(action: ActionStartTempTarget)
|
fun injectActionStartTempTarget(action: ActionStartTempTarget)
|
||||||
fun injectActionStopTempTarget(action: ActionStopTempTarget)
|
fun injectActionStopTempTarget(action: ActionStopTempTarget)
|
||||||
|
|
||||||
|
fun injectElement(element: Element)
|
||||||
|
fun injectElement(comparator: Comparator)
|
||||||
|
fun injectElement(comparatorExists: ComparatorExists)
|
||||||
|
fun injectElement(inputBg: InputBg)
|
||||||
|
fun injectElement(inputButton: InputButton)
|
||||||
|
fun injectElement(inputDelta: InputDelta)
|
||||||
|
fun injectElement(inputDouble: InputDouble)
|
||||||
|
fun injectElement(inputDuration: InputDuration)
|
||||||
|
fun injectElement(inputInsulin: InputInsulin)
|
||||||
|
fun injectElement(inputLocationMode: InputLocationMode)
|
||||||
|
fun injectElement(inputPercent: InputPercent)
|
||||||
|
fun injectElement(inputProfileName: InputProfileName)
|
||||||
|
fun injectElement(inputString: InputString)
|
||||||
|
fun injectElement(inputTempTarget: InputTempTarget)
|
||||||
|
fun injectElement(labelWithElement: LabelWithElement)
|
||||||
|
fun injectElement(staticLabel: StaticLabel)
|
||||||
|
|
||||||
fun injectTreatment(treatment: Treatment)
|
fun injectTreatment(treatment: Treatment)
|
||||||
fun injectBgReading(bgReading: BgReading)
|
fun injectBgReading(bgReading: BgReading)
|
||||||
|
|
||||||
|
|
|
@ -17,7 +17,10 @@ import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin
|
||||||
import info.nightscout.androidaps.plugins.configBuilder.ProfileFunction
|
import info.nightscout.androidaps.plugins.configBuilder.ProfileFunction
|
||||||
import info.nightscout.androidaps.plugins.configBuilder.ProfileFunctionImplementation
|
import info.nightscout.androidaps.plugins.configBuilder.ProfileFunctionImplementation
|
||||||
import info.nightscout.androidaps.plugins.constraints.objectives.objectives.*
|
import info.nightscout.androidaps.plugins.constraints.objectives.objectives.*
|
||||||
|
import info.nightscout.androidaps.plugins.general.automation.AutomationEvent
|
||||||
import info.nightscout.androidaps.plugins.general.automation.actions.*
|
import info.nightscout.androidaps.plugins.general.automation.actions.*
|
||||||
|
import info.nightscout.androidaps.plugins.general.automation.elements.*
|
||||||
|
import info.nightscout.androidaps.plugins.general.automation.triggers.*
|
||||||
import info.nightscout.androidaps.plugins.general.overview.notifications.NotificationWithAction
|
import info.nightscout.androidaps.plugins.general.overview.notifications.NotificationWithAction
|
||||||
import info.nightscout.androidaps.plugins.treatments.Treatment
|
import info.nightscout.androidaps.plugins.treatments.Treatment
|
||||||
import info.nightscout.androidaps.queue.commands.CommandSetProfile
|
import info.nightscout.androidaps.queue.commands.CommandSetProfile
|
||||||
|
@ -71,10 +74,30 @@ open class AppModule {
|
||||||
@ContributesAndroidInjector fun objective5Injector(): Objective5
|
@ContributesAndroidInjector fun objective5Injector(): Objective5
|
||||||
@ContributesAndroidInjector fun objective6Injector(): Objective6
|
@ContributesAndroidInjector fun objective6Injector(): Objective6
|
||||||
|
|
||||||
|
@ContributesAndroidInjector fun automationEventInjector(): AutomationEvent
|
||||||
|
|
||||||
|
@ContributesAndroidInjector fun triggerInjector(): Trigger
|
||||||
|
@ContributesAndroidInjector fun triggerAutosensValueInjector(): TriggerAutosensValue
|
||||||
|
@ContributesAndroidInjector fun triggerBgInjector(): TriggerBg
|
||||||
|
@ContributesAndroidInjector fun triggerBolusAgoInjector(): TriggerBolusAgo
|
||||||
|
@ContributesAndroidInjector fun triggerCOBInjector(): TriggerCOB
|
||||||
|
@ContributesAndroidInjector fun triggerConnectorInjector(): TriggerConnector
|
||||||
|
@ContributesAndroidInjector fun triggerDeltaInjector(): TriggerDelta
|
||||||
|
@ContributesAndroidInjector fun triggerDummyInjector(): TriggerDummy
|
||||||
|
@ContributesAndroidInjector fun triggerIobInjector(): TriggerIob
|
||||||
|
@ContributesAndroidInjector fun triggerLocationInjector(): TriggerLocation
|
||||||
|
@ContributesAndroidInjector fun triggerProfilePercentInjector(): TriggerProfilePercent
|
||||||
|
@ContributesAndroidInjector fun triggerPumpLastConnectonInjector(): TriggerPumpLastConnection
|
||||||
|
@ContributesAndroidInjector fun triggerRecurringTimeInjector(): TriggerRecurringTime
|
||||||
|
@ContributesAndroidInjector fun triggerTempTargetInjector(): TriggerTempTarget
|
||||||
|
@ContributesAndroidInjector fun triggerTime(): TriggerTime
|
||||||
|
@ContributesAndroidInjector fun triggerTimeRangeInjector(): TriggerTimeRange
|
||||||
|
@ContributesAndroidInjector fun triggerWifiSsidInjector(): TriggerWifiSsid
|
||||||
|
|
||||||
@ContributesAndroidInjector fun actionInjector(): Action
|
@ContributesAndroidInjector fun actionInjector(): Action
|
||||||
@ContributesAndroidInjector fun actionLoopDisableInjector(): ActionLoopDisable
|
@ContributesAndroidInjector fun actionLoopDisableInjector(): ActionLoopDisable
|
||||||
@ContributesAndroidInjector fun actionLoopEnableInjector(): ActionLoopEnable
|
@ContributesAndroidInjector fun actionLoopEnableInjector(): ActionLoopEnable
|
||||||
@ContributesAndroidInjector fun ActionLoopResumeInjector(): ActionLoopResume
|
@ContributesAndroidInjector fun actionLoopResumeInjector(): ActionLoopResume
|
||||||
@ContributesAndroidInjector fun actionLoopSuspendInjector(): ActionLoopSuspend
|
@ContributesAndroidInjector fun actionLoopSuspendInjector(): ActionLoopSuspend
|
||||||
@ContributesAndroidInjector fun actionNotificationInjector(): ActionNotification
|
@ContributesAndroidInjector fun actionNotificationInjector(): ActionNotification
|
||||||
@ContributesAndroidInjector fun actionProfileSwitchInjector(): ActionProfileSwitch
|
@ContributesAndroidInjector fun actionProfileSwitchInjector(): ActionProfileSwitch
|
||||||
|
@ -84,6 +107,23 @@ open class AppModule {
|
||||||
@ContributesAndroidInjector fun actionStopTempTargetInjector(): ActionStopTempTarget
|
@ContributesAndroidInjector fun actionStopTempTargetInjector(): ActionStopTempTarget
|
||||||
@ContributesAndroidInjector fun actionDummyInjector(): ActionDummy
|
@ContributesAndroidInjector fun actionDummyInjector(): ActionDummy
|
||||||
|
|
||||||
|
@ContributesAndroidInjector fun elementInjector(): Element
|
||||||
|
@ContributesAndroidInjector fun comparatorInjector(): Comparator
|
||||||
|
@ContributesAndroidInjector fun comparatorExistsInjector(): ComparatorExists
|
||||||
|
@ContributesAndroidInjector fun inputBgInjector(): InputBg
|
||||||
|
@ContributesAndroidInjector fun inputButtonInjector(): InputButton
|
||||||
|
@ContributesAndroidInjector fun inputDeltaInjector(): InputDelta
|
||||||
|
@ContributesAndroidInjector fun inputDoubleInjector(): InputDouble
|
||||||
|
@ContributesAndroidInjector fun inputDurationInjector(): InputDuration
|
||||||
|
@ContributesAndroidInjector fun inputInsulinInjector(): InputInsulin
|
||||||
|
@ContributesAndroidInjector fun inputLocationModeInjector(): InputLocationMode
|
||||||
|
@ContributesAndroidInjector fun inputPercentInjector(): InputPercent
|
||||||
|
@ContributesAndroidInjector fun inputProfileNameInjector(): InputProfileName
|
||||||
|
@ContributesAndroidInjector fun inputStringInjector(): InputString
|
||||||
|
@ContributesAndroidInjector fun inputTempTargetInjector(): InputTempTarget
|
||||||
|
@ContributesAndroidInjector fun labelWithElementInjector(): LabelWithElement
|
||||||
|
@ContributesAndroidInjector fun staticLabelInjector(): StaticLabel
|
||||||
|
|
||||||
@ContributesAndroidInjector fun bgReadingInjector(): BgReading
|
@ContributesAndroidInjector fun bgReadingInjector(): BgReading
|
||||||
@ContributesAndroidInjector fun treatmentInjector(): Treatment
|
@ContributesAndroidInjector fun treatmentInjector(): Treatment
|
||||||
|
|
||||||
|
|
|
@ -1,103 +0,0 @@
|
||||||
package info.nightscout.androidaps.plugins.general.automation;
|
|
||||||
|
|
||||||
import org.json.JSONArray;
|
|
||||||
import org.json.JSONException;
|
|
||||||
import org.json.JSONObject;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import info.nightscout.androidaps.MainApp;
|
|
||||||
import info.nightscout.androidaps.plugins.general.automation.actions.Action;
|
|
||||||
import info.nightscout.androidaps.plugins.general.automation.actions.ActionDummy;
|
|
||||||
import info.nightscout.androidaps.plugins.general.automation.triggers.Trigger;
|
|
||||||
import info.nightscout.androidaps.plugins.general.automation.triggers.TriggerConnector;
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
public class AutomationEvent {
|
|
||||||
private static final Logger log = LoggerFactory.getLogger(AutomationEvent.class);
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setTrigger(Trigger trigger) {
|
|
||||||
this.trigger = trigger;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Trigger getTrigger() {
|
|
||||||
return trigger;
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<Action> getActions() {
|
|
||||||
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) {
|
|
||||||
if (action.getPrecondition() != null)
|
|
||||||
trigger.add(action.getPrecondition());
|
|
||||||
}
|
|
||||||
return trigger;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void addAction(Action action) {
|
|
||||||
actions.add(action);
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getTitle() {
|
|
||||||
return title;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String toJSON() {
|
|
||||||
JSONObject o = new JSONObject();
|
|
||||||
try {
|
|
||||||
// title
|
|
||||||
o.put("title", title);
|
|
||||||
o.put("enabled", enabled);
|
|
||||||
// trigger
|
|
||||||
o.put("trigger", trigger.toJSON());
|
|
||||||
// actions
|
|
||||||
JSONArray array = new JSONArray();
|
|
||||||
for (Action a : actions) {
|
|
||||||
array.put(a.toJSON());
|
|
||||||
}
|
|
||||||
o.put("actions", array);
|
|
||||||
} catch (JSONException e) {
|
|
||||||
log.error("Unhandled exception", e);
|
|
||||||
}
|
|
||||||
return o.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
public AutomationEvent fromJSON(String data) {
|
|
||||||
try {
|
|
||||||
JSONObject d = new JSONObject(data);
|
|
||||||
title = d.optString("title", "");
|
|
||||||
enabled = d.optBoolean("enabled", true);
|
|
||||||
trigger = Trigger.instantiate(d.getString("trigger"));
|
|
||||||
JSONArray array = d.getJSONArray("actions");
|
|
||||||
actions.clear();
|
|
||||||
for (int i = 0; i < array.length(); i++) {
|
|
||||||
actions.add(new ActionDummy(MainApp.instance()).instantiate(new JSONObject(array.getString(i))));
|
|
||||||
}
|
|
||||||
} catch (JSONException e) {
|
|
||||||
log.error("Unhandled exception", e);
|
|
||||||
}
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -0,0 +1,70 @@
|
||||||
|
package info.nightscout.androidaps.plugins.general.automation
|
||||||
|
|
||||||
|
import info.nightscout.androidaps.MainApp
|
||||||
|
import info.nightscout.androidaps.logging.AAPSLogger
|
||||||
|
import info.nightscout.androidaps.plugins.general.automation.actions.Action
|
||||||
|
import info.nightscout.androidaps.plugins.general.automation.actions.ActionDummy
|
||||||
|
import info.nightscout.androidaps.plugins.general.automation.triggers.Trigger
|
||||||
|
import info.nightscout.androidaps.plugins.general.automation.triggers.TriggerConnector
|
||||||
|
import info.nightscout.androidaps.plugins.general.automation.triggers.TriggerDummy
|
||||||
|
import info.nightscout.androidaps.utils.DateUtil
|
||||||
|
import info.nightscout.androidaps.utils.T
|
||||||
|
import org.json.JSONArray
|
||||||
|
import org.json.JSONObject
|
||||||
|
import java.util.*
|
||||||
|
import javax.inject.Inject
|
||||||
|
|
||||||
|
class AutomationEvent(private val mainApp: MainApp) {
|
||||||
|
@Inject lateinit var aapsLogger: AAPSLogger
|
||||||
|
|
||||||
|
var trigger: Trigger = TriggerConnector(mainApp)
|
||||||
|
val actions: MutableList<Action> = ArrayList()
|
||||||
|
var title: String? = null
|
||||||
|
var isEnabled = true
|
||||||
|
var lastRun: Long = 0
|
||||||
|
|
||||||
|
init {
|
||||||
|
mainApp.androidInjector().inject(this)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getPreconditions(): TriggerConnector {
|
||||||
|
val trigger = TriggerConnector(mainApp, TriggerConnector.Type.AND)
|
||||||
|
for (action in actions) {
|
||||||
|
action.precondition?.let { trigger.add(it) }
|
||||||
|
}
|
||||||
|
return trigger
|
||||||
|
}
|
||||||
|
|
||||||
|
fun addAction(action: Action) = actions.add(action)
|
||||||
|
|
||||||
|
fun toJSON(): String {
|
||||||
|
val array = JSONArray()
|
||||||
|
for (a in actions) array.put(a.toJSON())
|
||||||
|
return JSONObject()
|
||||||
|
.put("title", title)
|
||||||
|
.put("enabled", isEnabled)
|
||||||
|
.put("trigger", trigger.toJSON())
|
||||||
|
.put("actions", array)
|
||||||
|
.toString()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun fromJSON(data: String?): AutomationEvent {
|
||||||
|
val d = JSONObject(data)
|
||||||
|
title = d.optString("title", "")
|
||||||
|
isEnabled = d.optBoolean("enabled", true)
|
||||||
|
trigger = TriggerDummy(mainApp).instantiate(JSONObject(d.getString("trigger")))
|
||||||
|
?: TriggerConnector(mainApp)
|
||||||
|
val array = d.getJSONArray("actions")
|
||||||
|
actions.clear()
|
||||||
|
for (i in 0 until array.length()) {
|
||||||
|
ActionDummy(mainApp).instantiate(JSONObject(array.getString(i)))?.let {
|
||||||
|
actions.add(it)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
|
||||||
|
fun shouldRun() : Boolean{
|
||||||
|
return lastRun <= DateUtil.now() - T.mins(5).msecs()
|
||||||
|
}
|
||||||
|
}
|
|
@ -19,6 +19,7 @@ import androidx.recyclerview.widget.ItemTouchHelper
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager
|
import androidx.recyclerview.widget.LinearLayoutManager
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
import dagger.android.support.DaggerFragment
|
import dagger.android.support.DaggerFragment
|
||||||
|
import info.nightscout.androidaps.MainApp
|
||||||
import info.nightscout.androidaps.R
|
import info.nightscout.androidaps.R
|
||||||
import info.nightscout.androidaps.plugins.bus.RxBusWrapper
|
import info.nightscout.androidaps.plugins.bus.RxBusWrapper
|
||||||
import info.nightscout.androidaps.plugins.general.automation.dialogs.EditEventDialog
|
import info.nightscout.androidaps.plugins.general.automation.dialogs.EditEventDialog
|
||||||
|
@ -45,6 +46,7 @@ class AutomationFragment : DaggerFragment(), OnStartDragListener {
|
||||||
@Inject lateinit var rxBus: RxBusWrapper
|
@Inject lateinit var rxBus: RxBusWrapper
|
||||||
@Inject lateinit var fabricPrivacy: FabricPrivacy
|
@Inject lateinit var fabricPrivacy: FabricPrivacy
|
||||||
@Inject lateinit var automationPlugin: AutomationPlugin
|
@Inject lateinit var automationPlugin: AutomationPlugin
|
||||||
|
@Inject lateinit var mainApp : MainApp
|
||||||
|
|
||||||
private var disposable: CompositeDisposable = CompositeDisposable()
|
private var disposable: CompositeDisposable = CompositeDisposable()
|
||||||
private lateinit var eventListAdapter: EventListAdapter
|
private lateinit var eventListAdapter: EventListAdapter
|
||||||
|
@ -67,7 +69,7 @@ class AutomationFragment : DaggerFragment(), OnStartDragListener {
|
||||||
automation_fabAddEvent.setOnClickListener {
|
automation_fabAddEvent.setOnClickListener {
|
||||||
val dialog = EditEventDialog()
|
val dialog = EditEventDialog()
|
||||||
val args = Bundle()
|
val args = Bundle()
|
||||||
args.putString("event", AutomationEvent().toJSON())
|
args.putString("event", AutomationEvent(mainApp).toJSON())
|
||||||
args.putInt("position", -1) // New event
|
args.putInt("position", -1) // New event
|
||||||
dialog.arguments = args
|
dialog.arguments = args
|
||||||
fragmentManager?.let { dialog.show(it, "EditEventDialog") }
|
fragmentManager?.let { dialog.show(it, "EditEventDialog") }
|
||||||
|
@ -116,6 +118,19 @@ class AutomationFragment : DaggerFragment(), OnStartDragListener {
|
||||||
itemTouchHelper?.startDrag(viewHolder)
|
itemTouchHelper?.startDrag(viewHolder)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun fillIconSet(connector: TriggerConnector, set: HashSet<Int>) {
|
||||||
|
for (t in connector.list) {
|
||||||
|
if (t is TriggerConnector) {
|
||||||
|
fillIconSet(t, set)
|
||||||
|
} else {
|
||||||
|
val icon = t.icon()
|
||||||
|
if (icon.isPresent) {
|
||||||
|
set.add(icon.get()!!)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
inner class EventListAdapter : RecyclerView.Adapter<EventListAdapter.ViewHolder>(), ItemTouchHelperAdapter {
|
inner class EventListAdapter : RecyclerView.Adapter<EventListAdapter.ViewHolder>(), ItemTouchHelperAdapter {
|
||||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
|
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
|
||||||
val v = LayoutInflater.from(parent.context).inflate(R.layout.automation_event_item, parent, false)
|
val v = LayoutInflater.from(parent.context).inflate(R.layout.automation_event_item, parent, false)
|
||||||
|
@ -137,7 +152,7 @@ class AutomationFragment : DaggerFragment(), OnStartDragListener {
|
||||||
holder.iconLayout.removeAllViews()
|
holder.iconLayout.removeAllViews()
|
||||||
// trigger icons
|
// trigger icons
|
||||||
val triggerIcons = HashSet<Int>()
|
val triggerIcons = HashSet<Int>()
|
||||||
TriggerConnector.fillIconSet(event.trigger as TriggerConnector, triggerIcons)
|
fillIconSet(event.trigger as TriggerConnector, triggerIcons)
|
||||||
for (res in triggerIcons) {
|
for (res in triggerIcons) {
|
||||||
addImage(res, holder.context, holder.iconLayout)
|
addImage(res, holder.context, holder.iconLayout)
|
||||||
}
|
}
|
||||||
|
|
|
@ -149,7 +149,7 @@ class AutomationPlugin @Inject constructor(
|
||||||
val array = JSONArray(data)
|
val array = JSONArray(data)
|
||||||
for (i in 0 until array.length()) {
|
for (i in 0 until array.length()) {
|
||||||
val o = array.getJSONObject(i)
|
val o = array.getJSONObject(i)
|
||||||
val event = AutomationEvent().fromJSON(o.toString())
|
val event = AutomationEvent(mainApp).fromJSON(o.toString())
|
||||||
automationEvents.add(event)
|
automationEvents.add(event)
|
||||||
}
|
}
|
||||||
} catch (e: JSONException) {
|
} catch (e: JSONException) {
|
||||||
|
@ -169,7 +169,7 @@ class AutomationPlugin @Inject constructor(
|
||||||
|
|
||||||
aapsLogger.debug(LTag.AUTOMATION, "processActions")
|
aapsLogger.debug(LTag.AUTOMATION, "processActions")
|
||||||
for (event in automationEvents) {
|
for (event in automationEvents) {
|
||||||
if (event.isEnabled && event.trigger.shouldRun() && event.preconditions.shouldRun()) {
|
if (event.isEnabled && event.shouldRun() && event.trigger.shouldRun() && event.getPreconditions().shouldRun()) {
|
||||||
val actions = event.actions
|
val actions = event.actions
|
||||||
for (action in actions) {
|
for (action in actions) {
|
||||||
action.doAction(object : Callback() {
|
action.doAction(object : Callback() {
|
||||||
|
@ -190,7 +190,7 @@ class AutomationPlugin @Inject constructor(
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
event.trigger.executed(DateUtil.now())
|
event.lastRun = DateUtil.now()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
storeToSP() // save last run time
|
storeToSP() // save last run time
|
||||||
|
@ -213,20 +213,20 @@ class AutomationPlugin @Inject constructor(
|
||||||
|
|
||||||
fun getTriggerDummyObjects(): List<Trigger> {
|
fun getTriggerDummyObjects(): List<Trigger> {
|
||||||
return listOf(
|
return listOf(
|
||||||
TriggerTime(),
|
TriggerTime(mainApp),
|
||||||
TriggerRecurringTime(),
|
TriggerRecurringTime(mainApp),
|
||||||
TriggerTimeRange(),
|
TriggerTimeRange(mainApp),
|
||||||
TriggerBg(),
|
TriggerBg(mainApp),
|
||||||
TriggerDelta(),
|
TriggerDelta(mainApp),
|
||||||
TriggerIob(),
|
TriggerIob(mainApp),
|
||||||
TriggerCOB(),
|
TriggerCOB(mainApp),
|
||||||
TriggerProfilePercent(),
|
TriggerProfilePercent(mainApp),
|
||||||
TriggerTempTarget(),
|
TriggerTempTarget(mainApp),
|
||||||
TriggerWifiSsid(),
|
TriggerWifiSsid(mainApp),
|
||||||
TriggerLocation(),
|
TriggerLocation(mainApp),
|
||||||
TriggerAutosensValue(),
|
TriggerAutosensValue(mainApp),
|
||||||
TriggerBolusAgo(),
|
TriggerBolusAgo(mainApp),
|
||||||
TriggerPumpLastConnection()
|
TriggerPumpLastConnection(mainApp)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -17,6 +17,7 @@ import info.nightscout.androidaps.utils.sharedPreferences.SP
|
||||||
import org.json.JSONException
|
import org.json.JSONException
|
||||||
import org.json.JSONObject
|
import org.json.JSONObject
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
import kotlin.reflect.full.primaryConstructor
|
||||||
|
|
||||||
abstract class Action(val mainApp: MainApp) {
|
abstract class Action(val mainApp: MainApp) {
|
||||||
@Inject lateinit var aapsLogger: AAPSLogger
|
@Inject lateinit var aapsLogger: AAPSLogger
|
||||||
|
@ -61,7 +62,7 @@ abstract class Action(val mainApp: MainApp) {
|
||||||
val type = obj.getString("type")
|
val type = obj.getString("type")
|
||||||
val data = obj.optJSONObject("data")
|
val data = obj.optJSONObject("data")
|
||||||
val clazz = Class.forName(type).kotlin
|
val clazz = Class.forName(type).kotlin
|
||||||
return (clazz.constructors.first().call(mainApp) as Action).fromJSON(data?.toString()
|
return (clazz.primaryConstructor?.call(mainApp) as Action).fromJSON(data?.toString()
|
||||||
?: "")
|
?: "")
|
||||||
//return (clazz.newInstance() as Action).fromJSON(data?.toString() ?: "")
|
//return (clazz.newInstance() as Action).fromJSON(data?.toString() ?: "")
|
||||||
} catch (e: ClassNotFoundException) {
|
} catch (e: ClassNotFoundException) {
|
||||||
|
|
|
@ -14,15 +14,15 @@ import info.nightscout.androidaps.utils.JsonHelper
|
||||||
import org.json.JSONObject
|
import org.json.JSONObject
|
||||||
|
|
||||||
class ActionLoopSuspend(mainApp: MainApp) : Action(mainApp) {
|
class ActionLoopSuspend(mainApp: MainApp) : Action(mainApp) {
|
||||||
var minutes = InputDuration(0, InputDuration.TimeUnit.MINUTES)
|
var minutes = InputDuration(mainApp, 0, InputDuration.TimeUnit.MINUTES)
|
||||||
|
|
||||||
override fun friendlyName(): Int = R.string.suspendloop
|
override fun friendlyName(): Int = R.string.suspendloop
|
||||||
override fun shortDescription(): String = resourceHelper.gs(R.string.suspendloopforXmin, minutes.minutes)
|
override fun shortDescription(): String = resourceHelper.gs(R.string.suspendloopforXmin, minutes.getMinutes())
|
||||||
@DrawableRes override fun icon(): Int = R.drawable.ic_pause_circle_outline_24dp
|
@DrawableRes override fun icon(): Int = R.drawable.ic_pause_circle_outline_24dp
|
||||||
|
|
||||||
override fun doAction(callback: Callback) {
|
override fun doAction(callback: Callback) {
|
||||||
if (!loopPlugin.isSuspended) {
|
if (!loopPlugin.isSuspended) {
|
||||||
loopPlugin.suspendLoop(minutes.minutes)
|
loopPlugin.suspendLoop(minutes.getMinutes())
|
||||||
rxBus.send(EventRefreshOverview("ActionLoopSuspend"))
|
rxBus.send(EventRefreshOverview("ActionLoopSuspend"))
|
||||||
callback.result(PumpEnactResult().success(true).comment(R.string.ok))?.run()
|
callback.result(PumpEnactResult().success(true).comment(R.string.ok))?.run()
|
||||||
} else {
|
} else {
|
||||||
|
@ -31,7 +31,7 @@ class ActionLoopSuspend(mainApp: MainApp) : Action(mainApp) {
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun toJSON(): String {
|
override fun toJSON(): String {
|
||||||
val data = JSONObject().put("minutes", minutes.minutes)
|
val data = JSONObject().put("minutes", minutes.getMinutes())
|
||||||
return JSONObject()
|
return JSONObject()
|
||||||
.put("type", this.javaClass.name)
|
.put("type", this.javaClass.name)
|
||||||
.put("data", data)
|
.put("data", data)
|
||||||
|
@ -40,7 +40,7 @@ class ActionLoopSuspend(mainApp: MainApp) : Action(mainApp) {
|
||||||
|
|
||||||
override fun fromJSON(data: String): Action {
|
override fun fromJSON(data: String): Action {
|
||||||
val o = JSONObject(data)
|
val o = JSONObject(data)
|
||||||
minutes.minutes = JsonHelper.safeGetInt(o, "minutes")
|
minutes.setMinutes(JsonHelper.safeGetInt(o, "minutes"))
|
||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -48,7 +48,7 @@ class ActionLoopSuspend(mainApp: MainApp) : Action(mainApp) {
|
||||||
|
|
||||||
override fun generateDialog(root: LinearLayout) {
|
override fun generateDialog(root: LinearLayout) {
|
||||||
LayoutBuilder()
|
LayoutBuilder()
|
||||||
.add(LabelWithElement(resourceHelper.gs(R.string.careportal_newnstreatment_duration_min_label), "", minutes))
|
.add(LabelWithElement(mainApp, resourceHelper.gs(R.string.careportal_newnstreatment_duration_min_label), "", minutes))
|
||||||
.build(root)
|
.build(root)
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -17,7 +17,7 @@ import info.nightscout.androidaps.utils.JsonHelper
|
||||||
import org.json.JSONObject
|
import org.json.JSONObject
|
||||||
|
|
||||||
class ActionNotification(mainApp: MainApp) : Action(mainApp) {
|
class ActionNotification(mainApp: MainApp) : Action(mainApp) {
|
||||||
var text = InputString()
|
var text = InputString(mainApp)
|
||||||
|
|
||||||
override fun friendlyName(): Int = R.string.notification
|
override fun friendlyName(): Int = R.string.notification
|
||||||
override fun shortDescription(): String = resourceHelper.gs(R.string.notification_message, text.value)
|
override fun shortDescription(): String = resourceHelper.gs(R.string.notification_message, text.value)
|
||||||
|
@ -41,7 +41,7 @@ class ActionNotification(mainApp: MainApp) : Action(mainApp) {
|
||||||
|
|
||||||
override fun fromJSON(data: String): Action {
|
override fun fromJSON(data: String): Action {
|
||||||
val o = JSONObject(data)
|
val o = JSONObject(data)
|
||||||
text.value = JsonHelper.safeGetString(o, "text")
|
text.value = JsonHelper.safeGetString(o, "text", "")
|
||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -49,7 +49,7 @@ class ActionNotification(mainApp: MainApp) : Action(mainApp) {
|
||||||
|
|
||||||
override fun generateDialog(root: LinearLayout) {
|
override fun generateDialog(root: LinearLayout) {
|
||||||
LayoutBuilder()
|
LayoutBuilder()
|
||||||
.add(LabelWithElement(resourceHelper.gs(R.string.message_short), "", text))
|
.add(LabelWithElement(mainApp,resourceHelper.gs(R.string.message_short), "", text))
|
||||||
.build(root)
|
.build(root)
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -15,7 +15,7 @@ import info.nightscout.androidaps.utils.JsonHelper
|
||||||
import org.json.JSONObject
|
import org.json.JSONObject
|
||||||
|
|
||||||
class ActionProfileSwitch(mainApp: MainApp) : Action(mainApp) {
|
class ActionProfileSwitch(mainApp: MainApp) : Action(mainApp) {
|
||||||
var inputProfileName: InputProfileName = InputProfileName("")
|
var inputProfileName: InputProfileName = InputProfileName(mainApp, "")
|
||||||
|
|
||||||
override fun friendlyName(): Int = R.string.profilename
|
override fun friendlyName(): Int = R.string.profilename
|
||||||
override fun shortDescription(): String = resourceHelper.gs(R.string.changengetoprofilename, inputProfileName.value)
|
override fun shortDescription(): String = resourceHelper.gs(R.string.changengetoprofilename, inputProfileName.value)
|
||||||
|
@ -51,7 +51,7 @@ class ActionProfileSwitch(mainApp: MainApp) : Action(mainApp) {
|
||||||
|
|
||||||
override fun generateDialog(root: LinearLayout) {
|
override fun generateDialog(root: LinearLayout) {
|
||||||
LayoutBuilder()
|
LayoutBuilder()
|
||||||
.add(LabelWithElement(resourceHelper.gs(R.string.profilename), "", inputProfileName))
|
.add(LabelWithElement(mainApp, resourceHelper.gs(R.string.profilename), "", inputProfileName))
|
||||||
.build(root)
|
.build(root)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -67,7 +67,7 @@ class ActionProfileSwitch(mainApp: MainApp) : Action(mainApp) {
|
||||||
|
|
||||||
override fun fromJSON(data: String): Action {
|
override fun fromJSON(data: String): Action {
|
||||||
val o = JSONObject(data)
|
val o = JSONObject(data)
|
||||||
inputProfileName.value = JsonHelper.safeGetString(o, "profileToSwitchTo")
|
inputProfileName.value = JsonHelper.safeGetString(o, "profileToSwitchTo", "")
|
||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -16,29 +16,29 @@ import info.nightscout.androidaps.utils.JsonHelper
|
||||||
import org.json.JSONObject
|
import org.json.JSONObject
|
||||||
|
|
||||||
class ActionProfileSwitchPercent(mainApp: MainApp) : Action(mainApp) {
|
class ActionProfileSwitchPercent(mainApp: MainApp) : Action(mainApp) {
|
||||||
var pct = InputPercent()
|
var pct = InputPercent(mainApp)
|
||||||
var duration = InputDuration(0, InputDuration.TimeUnit.MINUTES)
|
var duration = InputDuration(mainApp, 0, InputDuration.TimeUnit.MINUTES)
|
||||||
|
|
||||||
override fun friendlyName(): Int = R.string.profilepercentage
|
override fun friendlyName(): Int = R.string.profilepercentage
|
||||||
override fun shortDescription(): String =
|
override fun shortDescription(): String =
|
||||||
if (duration.minutes == 0) resourceHelper.gs(R.string.startprofileforever, pct.value.toInt())
|
if (duration.value == 0) resourceHelper.gs(R.string.startprofileforever, pct.value.toInt())
|
||||||
else resourceHelper.gs(R.string.startprofile, pct.value.toInt(), duration.minutes)
|
else resourceHelper.gs(R.string.startprofile, pct.value.toInt(), duration.value)
|
||||||
|
|
||||||
@DrawableRes override fun icon(): Int = R.drawable.icon_actions_profileswitch
|
@DrawableRes override fun icon(): Int = R.drawable.icon_actions_profileswitch
|
||||||
|
|
||||||
init {
|
init {
|
||||||
precondition = TriggerProfilePercent().comparator(Comparator.Compare.IS_EQUAL).setValue(100.0)
|
precondition = TriggerProfilePercent(mainApp, 100.0, Comparator.Compare.IS_EQUAL)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun doAction(callback: Callback) {
|
override fun doAction(callback: Callback) {
|
||||||
treatmentsPlugin.doProfileSwitch(duration.value.toInt(), pct.value.toInt(), 0)
|
treatmentsPlugin.doProfileSwitch(duration.value, pct.value.toInt(), 0)
|
||||||
callback.result(PumpEnactResult().success(true).comment(R.string.ok))?.run()
|
callback.result(PumpEnactResult().success(true).comment(R.string.ok))?.run()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun generateDialog(root: LinearLayout) {
|
override fun generateDialog(root: LinearLayout) {
|
||||||
LayoutBuilder()
|
LayoutBuilder()
|
||||||
.add(LabelWithElement(resourceHelper.gs(R.string.percent_u), "", pct))
|
.add(LabelWithElement(mainApp, resourceHelper.gs(R.string.percent_u), "", pct))
|
||||||
.add(LabelWithElement(resourceHelper.gs(R.string.careportal_newnstreatment_duration_min_label), "", duration))
|
.add(LabelWithElement(mainApp, resourceHelper.gs(R.string.careportal_newnstreatment_duration_min_label), "", duration))
|
||||||
.build(root)
|
.build(root)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -47,7 +47,7 @@ class ActionProfileSwitchPercent(mainApp: MainApp) : Action(mainApp) {
|
||||||
override fun toJSON(): String {
|
override fun toJSON(): String {
|
||||||
val data = JSONObject()
|
val data = JSONObject()
|
||||||
.put("percentage", pct.value)
|
.put("percentage", pct.value)
|
||||||
.put("durationInMinutes", duration.minutes)
|
.put("durationInMinutes", duration.value)
|
||||||
return JSONObject()
|
return JSONObject()
|
||||||
.put("type", this.javaClass.name)
|
.put("type", this.javaClass.name)
|
||||||
.put("data", data)
|
.put("data", data)
|
||||||
|
@ -57,7 +57,7 @@ class ActionProfileSwitchPercent(mainApp: MainApp) : Action(mainApp) {
|
||||||
override fun fromJSON(data: String): Action {
|
override fun fromJSON(data: String): Action {
|
||||||
val o = JSONObject(data)
|
val o = JSONObject(data)
|
||||||
pct.value = JsonHelper.safeGetDouble(o, "percentage")
|
pct.value = JsonHelper.safeGetDouble(o, "percentage")
|
||||||
duration.minutes = JsonHelper.safeGetInt(o, "durationInMinutes")
|
duration.value = JsonHelper.safeGetInt(o, "durationInMinutes")
|
||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -8,11 +8,11 @@ import info.nightscout.androidaps.plugins.general.automation.elements.InputStrin
|
||||||
import info.nightscout.androidaps.plugins.general.automation.elements.LabelWithElement
|
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.elements.LayoutBuilder
|
||||||
import info.nightscout.androidaps.queue.Callback
|
import info.nightscout.androidaps.queue.Callback
|
||||||
import info.nightscout.androidaps.utils.JsonHelper.safeGetString
|
import info.nightscout.androidaps.utils.JsonHelper
|
||||||
import org.json.JSONObject
|
import org.json.JSONObject
|
||||||
|
|
||||||
class ActionSendSMS(mainApp: MainApp) : Action(mainApp) {
|
class ActionSendSMS(mainApp: MainApp) : Action(mainApp) {
|
||||||
var text = InputString()
|
var text = InputString(mainApp)
|
||||||
|
|
||||||
override fun friendlyName(): Int = R.string.sendsmsactiondescription
|
override fun friendlyName(): Int = R.string.sendsmsactiondescription
|
||||||
override fun shortDescription(): String = resourceHelper.gs(R.string.sendsmsactionlabel, text.value)
|
override fun shortDescription(): String = resourceHelper.gs(R.string.sendsmsactionlabel, text.value)
|
||||||
|
@ -33,7 +33,7 @@ class ActionSendSMS(mainApp: MainApp) : Action(mainApp) {
|
||||||
|
|
||||||
override fun fromJSON(data: String): Action {
|
override fun fromJSON(data: String): Action {
|
||||||
val o = JSONObject(data)
|
val o = JSONObject(data)
|
||||||
text.value = safeGetString(o, "text")
|
text.value = JsonHelper.safeGetString(o, "text", "")
|
||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -41,7 +41,7 @@ class ActionSendSMS(mainApp: MainApp) : Action(mainApp) {
|
||||||
|
|
||||||
override fun generateDialog(root: LinearLayout) {
|
override fun generateDialog(root: LinearLayout) {
|
||||||
LayoutBuilder()
|
LayoutBuilder()
|
||||||
.add(LabelWithElement(resourceHelper.gs(R.string.sendsmsactiontext), "", text))
|
.add(LabelWithElement(mainApp, resourceHelper.gs(R.string.sendsmsactiontext), "", text))
|
||||||
.build(root)
|
.build(root)
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -17,17 +17,16 @@ import info.nightscout.androidaps.plugins.general.automation.elements.LayoutBuil
|
||||||
import info.nightscout.androidaps.plugins.general.automation.triggers.TriggerTempTarget
|
import info.nightscout.androidaps.plugins.general.automation.triggers.TriggerTempTarget
|
||||||
import info.nightscout.androidaps.queue.Callback
|
import info.nightscout.androidaps.queue.Callback
|
||||||
import info.nightscout.androidaps.utils.DateUtil
|
import info.nightscout.androidaps.utils.DateUtil
|
||||||
|
import info.nightscout.androidaps.utils.JsonHelper
|
||||||
import info.nightscout.androidaps.utils.JsonHelper.safeGetDouble
|
import info.nightscout.androidaps.utils.JsonHelper.safeGetDouble
|
||||||
import info.nightscout.androidaps.utils.JsonHelper.safeGetInt
|
|
||||||
import info.nightscout.androidaps.utils.JsonHelper.safeGetString
|
|
||||||
import org.json.JSONObject
|
import org.json.JSONObject
|
||||||
|
|
||||||
class ActionStartTempTarget(mainApp: MainApp) : Action(mainApp) {
|
class ActionStartTempTarget(mainApp: MainApp) : Action(mainApp) {
|
||||||
var value = InputTempTarget()
|
var value = InputTempTarget(mainApp)
|
||||||
var duration = InputDuration(0, InputDuration.TimeUnit.MINUTES)
|
var duration = InputDuration(mainApp, 0, InputDuration.TimeUnit.MINUTES)
|
||||||
|
|
||||||
init {
|
init {
|
||||||
precondition = TriggerTempTarget().comparator(ComparatorExists.Compare.NOT_EXISTS)
|
precondition = TriggerTempTarget(mainApp, ComparatorExists.Compare.NOT_EXISTS)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun friendlyName(): Int = R.string.starttemptarget
|
override fun friendlyName(): Int = R.string.starttemptarget
|
||||||
|
@ -42,8 +41,8 @@ class ActionStartTempTarget(mainApp: MainApp) : Action(mainApp) {
|
||||||
override fun generateDialog(root: LinearLayout) {
|
override fun generateDialog(root: LinearLayout) {
|
||||||
val unitResId = if (value.units == Constants.MGDL) R.string.mgdl else R.string.mmol
|
val unitResId = if (value.units == Constants.MGDL) R.string.mgdl else R.string.mmol
|
||||||
LayoutBuilder()
|
LayoutBuilder()
|
||||||
.add(LabelWithElement(resourceHelper.gs(R.string.careportal_temporarytarget) + "\n[" + resourceHelper.gs(unitResId) + "]", "", value))
|
.add(LabelWithElement(mainApp, resourceHelper.gs(R.string.careportal_temporarytarget) + "\n[" + resourceHelper.gs(unitResId) + "]", "", value))
|
||||||
.add(LabelWithElement(resourceHelper.gs(R.string.careportal_newnstreatment_duration_min_label), "", duration))
|
.add(LabelWithElement(mainApp, resourceHelper.gs(R.string.careportal_newnstreatment_duration_min_label), "", duration))
|
||||||
.build(root)
|
.build(root)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -55,7 +54,7 @@ class ActionStartTempTarget(mainApp: MainApp) : Action(mainApp) {
|
||||||
val data = JSONObject()
|
val data = JSONObject()
|
||||||
.put("value", value.value)
|
.put("value", value.value)
|
||||||
.put("units", value.units)
|
.put("units", value.units)
|
||||||
.put("durationInMinutes", duration.minutes)
|
.put("durationInMinutes", duration.getMinutes())
|
||||||
return JSONObject()
|
return JSONObject()
|
||||||
.put("type", this.javaClass.name)
|
.put("type", this.javaClass.name)
|
||||||
.put("data", data)
|
.put("data", data)
|
||||||
|
@ -64,16 +63,16 @@ class ActionStartTempTarget(mainApp: MainApp) : Action(mainApp) {
|
||||||
|
|
||||||
override fun fromJSON(data: String): Action {
|
override fun fromJSON(data: String): Action {
|
||||||
val o = JSONObject(data)
|
val o = JSONObject(data)
|
||||||
value.units = safeGetString(o, "units")
|
value.units = JsonHelper.safeGetString(o, "units", Constants.MGDL)
|
||||||
value.value = safeGetDouble(o, "value")
|
value.value = safeGetDouble(o, "value")
|
||||||
duration.minutes = safeGetInt(o, "durationInMinutes")
|
duration.setMinutes(JsonHelper.safeGetInt(o, "durationInMinutes"))
|
||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
fun tt(): TempTarget =
|
fun tt(): TempTarget =
|
||||||
TempTarget()
|
TempTarget()
|
||||||
.date(DateUtil.now())
|
.date(DateUtil.now())
|
||||||
.duration(duration.minutes)
|
.duration(duration.getMinutes())
|
||||||
.reason("Automation")
|
.reason("Automation")
|
||||||
.source(Source.USER)
|
.source(Source.USER)
|
||||||
.low(Profile.toMgdl(value.value, value.units))
|
.low(Profile.toMgdl(value.value, value.units))
|
||||||
|
|
|
@ -15,6 +15,7 @@ import info.nightscout.androidaps.plugins.general.automation.events.EventAutomat
|
||||||
import info.nightscout.androidaps.plugins.general.automation.events.EventAutomationUpdateGui
|
import info.nightscout.androidaps.plugins.general.automation.events.EventAutomationUpdateGui
|
||||||
import kotlinx.android.synthetic.main.automation_dialog_choose_action.*
|
import kotlinx.android.synthetic.main.automation_dialog_choose_action.*
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
import kotlin.reflect.full.primaryConstructor
|
||||||
|
|
||||||
class ChooseActionDialog : DialogFragmentWithDate() {
|
class ChooseActionDialog : DialogFragmentWithDate() {
|
||||||
@Inject lateinit var automationPlugin: AutomationPlugin
|
@Inject lateinit var automationPlugin: AutomationPlugin
|
||||||
|
@ -64,7 +65,7 @@ class ChooseActionDialog : DialogFragmentWithDate() {
|
||||||
private fun instantiateAction(): Action? {
|
private fun instantiateAction(): Action? {
|
||||||
return getActionClass()?.let {
|
return getActionClass()?.let {
|
||||||
val clazz = Class.forName(it).kotlin
|
val clazz = Class.forName(it).kotlin
|
||||||
clazz.constructors.first().call(mainApp) as Action
|
clazz.primaryConstructor?.call(mainApp) as Action
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -5,15 +5,18 @@ import android.view.LayoutInflater
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import android.widget.RadioButton
|
import android.widget.RadioButton
|
||||||
|
import info.nightscout.androidaps.MainApp
|
||||||
import info.nightscout.androidaps.R
|
import info.nightscout.androidaps.R
|
||||||
import info.nightscout.androidaps.dialogs.DialogFragmentWithDate
|
import info.nightscout.androidaps.dialogs.DialogFragmentWithDate
|
||||||
import info.nightscout.androidaps.plugins.general.automation.AutomationPlugin
|
import info.nightscout.androidaps.plugins.general.automation.AutomationPlugin
|
||||||
import info.nightscout.androidaps.plugins.general.automation.triggers.Trigger
|
import info.nightscout.androidaps.plugins.general.automation.triggers.Trigger
|
||||||
import kotlinx.android.synthetic.main.automation_dialog_choose_trigger.*
|
import kotlinx.android.synthetic.main.automation_dialog_choose_trigger.*
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
import kotlin.reflect.full.primaryConstructor
|
||||||
|
|
||||||
class ChooseTriggerDialog : DialogFragmentWithDate() {
|
class ChooseTriggerDialog : DialogFragmentWithDate() {
|
||||||
@Inject lateinit var automationPlugin: AutomationPlugin
|
@Inject lateinit var automationPlugin: AutomationPlugin
|
||||||
|
@Inject lateinit var mainApp : MainApp
|
||||||
|
|
||||||
private var checkedIndex = -1
|
private var checkedIndex = -1
|
||||||
private var clickListener: OnClickListener? = null
|
private var clickListener: OnClickListener? = null
|
||||||
|
@ -39,7 +42,7 @@ class ChooseTriggerDialog : DialogFragmentWithDate() {
|
||||||
for (t in automationPlugin.getTriggerDummyObjects()) {
|
for (t in automationPlugin.getTriggerDummyObjects()) {
|
||||||
val radioButton = RadioButton(context)
|
val radioButton = RadioButton(context)
|
||||||
radioButton.setText(t.friendlyName())
|
radioButton.setText(t.friendlyName())
|
||||||
radioButton.tag = t.javaClass
|
radioButton.tag = t.javaClass.name
|
||||||
automation_chooseTriggerRadioGroup.addView(radioButton)
|
automation_chooseTriggerRadioGroup.addView(radioButton)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -65,15 +68,16 @@ class ChooseTriggerDialog : DialogFragmentWithDate() {
|
||||||
|
|
||||||
private fun instantiateTrigger(): Trigger? {
|
private fun instantiateTrigger(): Trigger? {
|
||||||
return getTriggerClass()?.let {
|
return getTriggerClass()?.let {
|
||||||
it.newInstance() as Trigger
|
val clazz = Class.forName(it).kotlin
|
||||||
|
clazz.primaryConstructor?.call(mainApp) as Trigger
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getTriggerClass(): Class<*>? {
|
private fun getTriggerClass(): String? {
|
||||||
val radioButtonID = automation_chooseTriggerRadioGroup.checkedRadioButtonId
|
val radioButtonID = automation_chooseTriggerRadioGroup.checkedRadioButtonId
|
||||||
val radioButton = automation_chooseTriggerRadioGroup.findViewById<RadioButton>(radioButtonID)
|
val radioButton = automation_chooseTriggerRadioGroup.findViewById<RadioButton>(radioButtonID)
|
||||||
return radioButton?.let {
|
return radioButton?.let {
|
||||||
it.tag as Class<*>
|
it.tag as String
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -9,6 +9,7 @@ import android.widget.LinearLayout
|
||||||
import android.widget.TextView
|
import android.widget.TextView
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager
|
import androidx.recyclerview.widget.LinearLayoutManager
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
|
import info.nightscout.androidaps.MainApp
|
||||||
import info.nightscout.androidaps.R
|
import info.nightscout.androidaps.R
|
||||||
import info.nightscout.androidaps.dialogs.DialogFragmentWithDate
|
import info.nightscout.androidaps.dialogs.DialogFragmentWithDate
|
||||||
import info.nightscout.androidaps.plugins.bus.RxBusWrapper
|
import info.nightscout.androidaps.plugins.bus.RxBusWrapper
|
||||||
|
@ -31,21 +32,23 @@ import javax.inject.Inject
|
||||||
|
|
||||||
class EditEventDialog : DialogFragmentWithDate() {
|
class EditEventDialog : DialogFragmentWithDate() {
|
||||||
@Inject lateinit var rxBus: RxBusWrapper
|
@Inject lateinit var rxBus: RxBusWrapper
|
||||||
|
@Inject lateinit var mainApp: MainApp
|
||||||
@Inject lateinit var fabricPrivacy: FabricPrivacy
|
@Inject lateinit var fabricPrivacy: FabricPrivacy
|
||||||
@Inject lateinit var automationPlugin: AutomationPlugin
|
@Inject lateinit var automationPlugin: AutomationPlugin
|
||||||
|
|
||||||
private var actionListAdapter: ActionListAdapter? = null
|
private var actionListAdapter: ActionListAdapter? = null
|
||||||
private var event: AutomationEvent = AutomationEvent()
|
private lateinit var event: AutomationEvent
|
||||||
private var position: Int = -1
|
private var position: Int = -1
|
||||||
|
|
||||||
private var disposable: CompositeDisposable = CompositeDisposable()
|
private var disposable: CompositeDisposable = CompositeDisposable()
|
||||||
|
|
||||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
|
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
|
||||||
savedInstanceState: Bundle?): View? {
|
savedInstanceState: Bundle?): View? {
|
||||||
|
event = AutomationEvent(mainApp)
|
||||||
// load data from bundle
|
// load data from bundle
|
||||||
(savedInstanceState ?: arguments)?.let { bundle ->
|
(savedInstanceState ?: arguments)?.let { bundle ->
|
||||||
position = bundle.getInt("position", -1)
|
position = bundle.getInt("position", -1)
|
||||||
bundle.getString("event")?.let { event = AutomationEvent().fromJSON(it) }
|
bundle.getString("event")?.let { event = AutomationEvent(mainApp).fromJSON(it) }
|
||||||
}
|
}
|
||||||
|
|
||||||
onCreateViewGeneral()
|
onCreateViewGeneral()
|
||||||
|
@ -149,7 +152,7 @@ class EditEventDialog : DialogFragmentWithDate() {
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun showPreconditions() {
|
private fun showPreconditions() {
|
||||||
val forcedTriggers = event.preconditions
|
val forcedTriggers = event.getPreconditions()
|
||||||
if (forcedTriggers.size() > 0) {
|
if (forcedTriggers.size() > 0) {
|
||||||
automation_forcedTriggerDescription.visibility = View.VISIBLE
|
automation_forcedTriggerDescription.visibility = View.VISIBLE
|
||||||
automation_forcedTriggerDescriptionLabel.visibility = View.VISIBLE
|
automation_forcedTriggerDescriptionLabel.visibility = View.VISIBLE
|
||||||
|
|
|
@ -4,16 +4,20 @@ import android.os.Bundle
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
|
import info.nightscout.androidaps.MainApp
|
||||||
import info.nightscout.androidaps.R
|
import info.nightscout.androidaps.R
|
||||||
import info.nightscout.androidaps.dialogs.DialogFragmentWithDate
|
import info.nightscout.androidaps.dialogs.DialogFragmentWithDate
|
||||||
import info.nightscout.androidaps.plugins.bus.RxBusWrapper
|
import info.nightscout.androidaps.plugins.bus.RxBusWrapper
|
||||||
import info.nightscout.androidaps.plugins.general.automation.events.EventAutomationUpdateTrigger
|
import info.nightscout.androidaps.plugins.general.automation.events.EventAutomationUpdateTrigger
|
||||||
import info.nightscout.androidaps.plugins.general.automation.triggers.Trigger
|
import info.nightscout.androidaps.plugins.general.automation.triggers.Trigger
|
||||||
|
import info.nightscout.androidaps.plugins.general.automation.triggers.TriggerDummy
|
||||||
import kotlinx.android.synthetic.main.automation_dialog_edit_trigger.*
|
import kotlinx.android.synthetic.main.automation_dialog_edit_trigger.*
|
||||||
|
import org.json.JSONObject
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
class EditTriggerDialog : DialogFragmentWithDate() {
|
class EditTriggerDialog : DialogFragmentWithDate() {
|
||||||
@Inject lateinit var rxBus: RxBusWrapper
|
@Inject lateinit var rxBus: RxBusWrapper
|
||||||
|
@Inject lateinit var mainApp: MainApp
|
||||||
|
|
||||||
private var trigger: Trigger? = null
|
private var trigger: Trigger? = null
|
||||||
|
|
||||||
|
@ -21,7 +25,7 @@ class EditTriggerDialog : DialogFragmentWithDate() {
|
||||||
savedInstanceState: Bundle?): View? {
|
savedInstanceState: Bundle?): View? {
|
||||||
// load data from bundle
|
// load data from bundle
|
||||||
(savedInstanceState ?: arguments)?.let { bundle ->
|
(savedInstanceState ?: arguments)?.let { bundle ->
|
||||||
bundle.getString("trigger")?.let { trigger = Trigger.instantiate(it) }
|
bundle.getString("trigger")?.let { trigger = TriggerDummy(mainApp).instantiate(JSONObject(it)) }
|
||||||
}
|
}
|
||||||
|
|
||||||
onCreateViewGeneral()
|
onCreateViewGeneral()
|
||||||
|
@ -32,7 +36,7 @@ class EditTriggerDialog : DialogFragmentWithDate() {
|
||||||
super.onViewCreated(view, savedInstanceState)
|
super.onViewCreated(view, savedInstanceState)
|
||||||
|
|
||||||
// display root trigger
|
// display root trigger
|
||||||
trigger?.generateDialog(automation_layoutTrigger, fragmentManager)
|
trigger?.generateDialog(automation_layoutTrigger)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun submit(): Boolean {
|
override fun submit(): Boolean {
|
||||||
|
|
|
@ -15,29 +15,28 @@ import info.nightscout.androidaps.MainApp;
|
||||||
import info.nightscout.androidaps.R;
|
import info.nightscout.androidaps.R;
|
||||||
import info.nightscout.androidaps.plugins.general.automation.triggers.Trigger;
|
import info.nightscout.androidaps.plugins.general.automation.triggers.Trigger;
|
||||||
import info.nightscout.androidaps.plugins.general.automation.triggers.TriggerConnector;
|
import info.nightscout.androidaps.plugins.general.automation.triggers.TriggerConnector;
|
||||||
|
import info.nightscout.androidaps.utils.resources.ResourceHelper;
|
||||||
|
|
||||||
public class TriggerListAdapter {
|
public class TriggerListAdapter {
|
||||||
private final LinearLayout mRootLayout;
|
private final LinearLayout mRootLayout;
|
||||||
private final FragmentManager mFragmentManager;
|
|
||||||
private final Context mContext;
|
private final Context mContext;
|
||||||
private final TriggerConnector mRootConnector;
|
private final TriggerConnector mRootConnector;
|
||||||
|
private final MainApp mainApp;
|
||||||
|
private final ResourceHelper resourceHelper;
|
||||||
|
|
||||||
public TriggerListAdapter(FragmentManager fragmentManager, Context context, LinearLayout rootLayout, TriggerConnector rootTrigger) {
|
public TriggerListAdapter(MainApp mainApp, ResourceHelper resourceHelper, Context context, LinearLayout rootLayout, TriggerConnector rootTrigger) {
|
||||||
mRootLayout = rootLayout;
|
mRootLayout = rootLayout;
|
||||||
mFragmentManager = fragmentManager;
|
this.mainApp = mainApp;
|
||||||
|
this.resourceHelper = resourceHelper;
|
||||||
mContext = context;
|
mContext = context;
|
||||||
mRootConnector = rootTrigger;
|
mRootConnector = rootTrigger;
|
||||||
build(fragmentManager);
|
build(rootTrigger.scanForActivity(context).getSupportFragmentManager());
|
||||||
}
|
}
|
||||||
|
|
||||||
public Context getContext() {
|
public Context getContext() {
|
||||||
return mContext;
|
return mContext;
|
||||||
}
|
}
|
||||||
|
|
||||||
private FragmentManager getFM() {
|
|
||||||
return mFragmentManager;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void destroy() {
|
private void destroy() {
|
||||||
mRootLayout.removeAllViews();
|
mRootLayout.removeAllViews();
|
||||||
}
|
}
|
||||||
|
@ -48,11 +47,11 @@ public class TriggerListAdapter {
|
||||||
|
|
||||||
// spinner
|
// spinner
|
||||||
if (i > 0) {
|
if (i > 0) {
|
||||||
createSpinner(trigger);
|
createSpinner(trigger, fragmentManager);
|
||||||
}
|
}
|
||||||
|
|
||||||
// trigger layout
|
// trigger layout
|
||||||
trigger.generateDialog(mRootLayout, fragmentManager);
|
trigger.generateDialog(mRootLayout);
|
||||||
|
|
||||||
// buttons
|
// buttons
|
||||||
createButtons(fragmentManager, trigger);
|
createButtons(fragmentManager, trigger);
|
||||||
|
@ -60,7 +59,7 @@ public class TriggerListAdapter {
|
||||||
|
|
||||||
if (mRootConnector.size() == 0) {
|
if (mRootConnector.size() == 0) {
|
||||||
Button buttonAdd = new Button(mContext);
|
Button buttonAdd = new Button(mContext);
|
||||||
buttonAdd.setText(MainApp.gs(R.string.addnew));
|
buttonAdd.setText(resourceHelper.gs(R.string.addnew));
|
||||||
buttonAdd.setOnClickListener(v -> {
|
buttonAdd.setOnClickListener(v -> {
|
||||||
ChooseTriggerDialog dialog = new ChooseTriggerDialog();
|
ChooseTriggerDialog dialog = new ChooseTriggerDialog();
|
||||||
dialog.setOnClickListener(newTriggerObject -> {
|
dialog.setOnClickListener(newTriggerObject -> {
|
||||||
|
@ -75,30 +74,30 @@ public class TriggerListAdapter {
|
||||||
|
|
||||||
private Spinner createSpinner() {
|
private Spinner createSpinner() {
|
||||||
Spinner spinner = new Spinner(mContext);
|
Spinner spinner = new Spinner(mContext);
|
||||||
ArrayAdapter<String> spinnerArrayAdapter = new ArrayAdapter<>(mContext, R.layout.spinner_centered, TriggerConnector.Type.labels());
|
ArrayAdapter<String> spinnerArrayAdapter = new ArrayAdapter<>(mContext, R.layout.spinner_centered, TriggerConnector.Type.AND.labels(resourceHelper));
|
||||||
spinnerArrayAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
|
spinnerArrayAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
|
||||||
spinner.setAdapter(spinnerArrayAdapter);
|
spinner.setAdapter(spinnerArrayAdapter);
|
||||||
return spinner;
|
return spinner;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void createSpinner(Trigger trigger) {
|
private void createSpinner(Trigger trigger, FragmentManager fragmentManager) {
|
||||||
final TriggerConnector connector = trigger.getConnector();
|
final TriggerConnector connector = trigger.getConnector();
|
||||||
final int initialPosition = connector.getConnectorType().ordinal();
|
final int initialPosition = connector.getConnectorType().ordinal();
|
||||||
Spinner spinner = createSpinner();
|
Spinner spinner = createSpinner();
|
||||||
spinner.setSelection(initialPosition);
|
spinner.setSelection(initialPosition);
|
||||||
spinner.setBackgroundColor(MainApp.gc(R.color.black_overlay));
|
spinner.setBackgroundColor(resourceHelper.gc(R.color.black_overlay));
|
||||||
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(
|
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(
|
||||||
LinearLayout.LayoutParams.MATCH_PARENT,
|
LinearLayout.LayoutParams.MATCH_PARENT,
|
||||||
LinearLayout.LayoutParams.WRAP_CONTENT
|
LinearLayout.LayoutParams.WRAP_CONTENT
|
||||||
);
|
);
|
||||||
params.setMargins(0, MainApp.dpToPx(8), 0, MainApp.dpToPx(8));
|
params.setMargins(0, resourceHelper.dpToPx(8), 0, resourceHelper.dpToPx(8));
|
||||||
spinner.setLayoutParams(params);
|
spinner.setLayoutParams(params);
|
||||||
spinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
|
spinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
|
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
|
||||||
if (position != initialPosition) {
|
if (position != initialPosition) {
|
||||||
// connector type changed
|
// connector type changed
|
||||||
changeConnector(getFM(), trigger, connector, TriggerConnector.Type.values()[position]);
|
changeConnector(fragmentManager, trigger, connector, TriggerConnector.Type.values()[position]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -123,35 +122,35 @@ public class TriggerListAdapter {
|
||||||
|
|
||||||
// Button [-]
|
// Button [-]
|
||||||
Button buttonRemove = new Button(mContext);
|
Button buttonRemove = new Button(mContext);
|
||||||
buttonRemove.setText(MainApp.gs(R.string.delete_short));
|
buttonRemove.setText(resourceHelper.gs(R.string.delete_short));
|
||||||
buttonRemove.setOnClickListener(v -> {
|
buttonRemove.setOnClickListener(v -> {
|
||||||
final TriggerConnector connector = trigger.getConnector();
|
final TriggerConnector connector = trigger.getConnector();
|
||||||
connector.remove(trigger);
|
connector.remove(trigger);
|
||||||
connector.simplify().rebuildView(getFM());
|
connector.simplify().rebuildView(fragmentManager);
|
||||||
});
|
});
|
||||||
buttonLayout.addView(buttonRemove);
|
buttonLayout.addView(buttonRemove);
|
||||||
|
|
||||||
// Button [+]
|
// Button [+]
|
||||||
Button buttonAdd = new Button(mContext);
|
Button buttonAdd = new Button(mContext);
|
||||||
buttonAdd.setText(MainApp.gs(R.string.add_short));
|
buttonAdd.setText(resourceHelper.gs(R.string.add_short));
|
||||||
buttonAdd.setOnClickListener(v -> {
|
buttonAdd.setOnClickListener(v -> {
|
||||||
ChooseTriggerDialog dialog = new ChooseTriggerDialog();
|
ChooseTriggerDialog dialog = new ChooseTriggerDialog();
|
||||||
dialog.show(fragmentManager, "ChooseTriggerDialog");
|
dialog.show(fragmentManager, "ChooseTriggerDialog");
|
||||||
dialog.setOnClickListener(newTriggerObject -> {
|
dialog.setOnClickListener(newTriggerObject -> {
|
||||||
TriggerConnector connector = trigger.getConnector();
|
TriggerConnector connector = trigger.getConnector();
|
||||||
connector.add(connector.pos(trigger) + 1, newTriggerObject);
|
connector.add(connector.pos(trigger) + 1, newTriggerObject);
|
||||||
connector.simplify().rebuildView(getFM());
|
connector.simplify().rebuildView(fragmentManager);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
buttonLayout.addView(buttonAdd);
|
buttonLayout.addView(buttonAdd);
|
||||||
|
|
||||||
// Button [*]
|
// Button [*]
|
||||||
Button buttonCopy = new Button(mContext);
|
Button buttonCopy = new Button(mContext);
|
||||||
buttonCopy.setText(MainApp.gs(R.string.copy_short));
|
buttonCopy.setText(resourceHelper.gs(R.string.copy_short));
|
||||||
buttonCopy.setOnClickListener(v -> {
|
buttonCopy.setOnClickListener(v -> {
|
||||||
TriggerConnector connector = trigger.getConnector();
|
TriggerConnector connector = trigger.getConnector();
|
||||||
connector.add(connector.pos(trigger) + 1, trigger.duplicate());
|
connector.add(connector.pos(trigger) + 1, trigger.duplicate());
|
||||||
connector.simplify().rebuildView(getFM());
|
connector.simplify().rebuildView(fragmentManager);
|
||||||
});
|
});
|
||||||
buttonLayout.addView(buttonCopy);
|
buttonLayout.addView(buttonCopy);
|
||||||
}
|
}
|
||||||
|
@ -161,12 +160,12 @@ public class TriggerListAdapter {
|
||||||
build(fragmentManager);
|
build(fragmentManager);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void changeConnector(final FragmentManager fragmentManager, final Trigger trigger, final TriggerConnector connector, final TriggerConnector.Type newConnectorType) {
|
public void changeConnector(final FragmentManager fragmentManager, final Trigger trigger, final TriggerConnector connector, final TriggerConnector.Type newConnectorType) {
|
||||||
if (connector.size() > 2) {
|
if (connector.size() > 2) {
|
||||||
// split connector
|
// split connector
|
||||||
int pos = connector.pos(trigger) - 1;
|
int pos = connector.pos(trigger) - 1;
|
||||||
|
|
||||||
TriggerConnector newConnector = new TriggerConnector(newConnectorType);
|
TriggerConnector newConnector = new TriggerConnector(mainApp, newConnectorType);
|
||||||
|
|
||||||
// move trigger from pos and pos+1 into new connector
|
// move trigger from pos and pos+1 into new connector
|
||||||
for (int i = 0; i < 2; ++i) {
|
for (int i = 0; i < 2; ++i) {
|
||||||
|
@ -177,10 +176,8 @@ public class TriggerListAdapter {
|
||||||
|
|
||||||
connector.add(pos, newConnector);
|
connector.add(pos, newConnector);
|
||||||
} else {
|
} else {
|
||||||
connector.changeConnectorType(newConnectorType);
|
connector.setType(newConnectorType);
|
||||||
}
|
}
|
||||||
|
|
||||||
connector.simplify().rebuildView(fragmentManager);
|
connector.simplify().rebuildView(fragmentManager);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,123 +0,0 @@
|
||||||
package info.nightscout.androidaps.plugins.general.automation.elements;
|
|
||||||
|
|
||||||
import android.view.View;
|
|
||||||
import android.widget.AdapterView;
|
|
||||||
import android.widget.ArrayAdapter;
|
|
||||||
import android.widget.LinearLayout;
|
|
||||||
import android.widget.Spinner;
|
|
||||||
|
|
||||||
import androidx.annotation.StringRes;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import info.nightscout.androidaps.MainApp;
|
|
||||||
import info.nightscout.androidaps.R;
|
|
||||||
|
|
||||||
public class Comparator extends Element {
|
|
||||||
public enum Compare {
|
|
||||||
IS_LESSER,
|
|
||||||
IS_EQUAL_OR_LESSER,
|
|
||||||
IS_EQUAL,
|
|
||||||
IS_EQUAL_OR_GREATER,
|
|
||||||
IS_GREATER,
|
|
||||||
IS_NOT_AVAILABLE;
|
|
||||||
|
|
||||||
public @StringRes
|
|
||||||
int getStringRes() {
|
|
||||||
switch (this) {
|
|
||||||
case IS_LESSER:
|
|
||||||
return R.string.islesser;
|
|
||||||
case IS_EQUAL_OR_LESSER:
|
|
||||||
return R.string.isequalorlesser;
|
|
||||||
case IS_EQUAL:
|
|
||||||
return R.string.isequal;
|
|
||||||
case IS_EQUAL_OR_GREATER:
|
|
||||||
return R.string.isequalorgreater;
|
|
||||||
case IS_GREATER:
|
|
||||||
return R.string.isgreater;
|
|
||||||
case IS_NOT_AVAILABLE:
|
|
||||||
return R.string.isnotavailable;
|
|
||||||
default:
|
|
||||||
return R.string.unknown;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public <T extends Comparable> boolean check(T obj1, T obj2) {
|
|
||||||
if (obj1 == null || obj2 == null)
|
|
||||||
return this.equals(IS_NOT_AVAILABLE);
|
|
||||||
|
|
||||||
int comparison = obj1.compareTo(obj2);
|
|
||||||
switch (this) {
|
|
||||||
case IS_LESSER:
|
|
||||||
return comparison < 0;
|
|
||||||
case IS_EQUAL_OR_LESSER:
|
|
||||||
return comparison <= 0;
|
|
||||||
case IS_EQUAL:
|
|
||||||
return comparison == 0;
|
|
||||||
case IS_EQUAL_OR_GREATER:
|
|
||||||
return comparison >= 0;
|
|
||||||
case IS_GREATER:
|
|
||||||
return comparison > 0;
|
|
||||||
default:
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static List<String> labels() {
|
|
||||||
List<String> list = new ArrayList<>();
|
|
||||||
for (Compare c : Compare.values()) {
|
|
||||||
list.add(MainApp.gs(c.getStringRes()));
|
|
||||||
}
|
|
||||||
return list;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private Compare compare = Compare.IS_EQUAL;
|
|
||||||
|
|
||||||
public Comparator() {
|
|
||||||
super();
|
|
||||||
}
|
|
||||||
|
|
||||||
public Comparator(Comparator another) {
|
|
||||||
super();
|
|
||||||
compare = another.getValue();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void addToLayout(LinearLayout root) {
|
|
||||||
Spinner spinner = new Spinner(root.getContext());
|
|
||||||
ArrayAdapter<String> spinnerArrayAdapter = new ArrayAdapter<>(root.getContext(), R.layout.spinner_centered, Compare.labels());
|
|
||||||
spinnerArrayAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
|
|
||||||
spinner.setAdapter(spinnerArrayAdapter);
|
|
||||||
LinearLayout.LayoutParams spinnerParams = new LinearLayout.LayoutParams(
|
|
||||||
LinearLayout.LayoutParams.MATCH_PARENT,
|
|
||||||
LinearLayout.LayoutParams.WRAP_CONTENT
|
|
||||||
);
|
|
||||||
spinnerParams.setMargins(0, MainApp.dpToPx(4), 0, MainApp.dpToPx(4));
|
|
||||||
spinner.setLayoutParams(spinnerParams);
|
|
||||||
spinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
|
|
||||||
@Override
|
|
||||||
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
|
|
||||||
compare = Compare.values()[position];
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onNothingSelected(AdapterView<?> parent) {
|
|
||||||
}
|
|
||||||
});
|
|
||||||
spinner.setSelection(compare.ordinal());
|
|
||||||
root.addView(spinner);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public Compare getValue() {
|
|
||||||
return compare;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Comparator setValue(Compare compare) {
|
|
||||||
this.compare = compare;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -0,0 +1,88 @@
|
||||||
|
package info.nightscout.androidaps.plugins.general.automation.elements
|
||||||
|
|
||||||
|
import android.view.View
|
||||||
|
import android.widget.AdapterView
|
||||||
|
import android.widget.ArrayAdapter
|
||||||
|
import android.widget.LinearLayout
|
||||||
|
import android.widget.Spinner
|
||||||
|
import androidx.annotation.StringRes
|
||||||
|
import info.nightscout.androidaps.MainApp
|
||||||
|
import info.nightscout.androidaps.R
|
||||||
|
import info.nightscout.androidaps.utils.resources.ResourceHelper
|
||||||
|
import java.util.*
|
||||||
|
|
||||||
|
class Comparator(mainApp: MainApp) : Element(mainApp) {
|
||||||
|
enum class Compare {
|
||||||
|
IS_LESSER,
|
||||||
|
IS_EQUAL_OR_LESSER,
|
||||||
|
IS_EQUAL,
|
||||||
|
IS_EQUAL_OR_GREATER,
|
||||||
|
IS_GREATER,
|
||||||
|
IS_NOT_AVAILABLE;
|
||||||
|
|
||||||
|
@get:StringRes val stringRes: Int
|
||||||
|
get() = when (this) {
|
||||||
|
IS_LESSER -> R.string.islesser
|
||||||
|
IS_EQUAL_OR_LESSER -> R.string.isequalorlesser
|
||||||
|
IS_EQUAL -> R.string.isequal
|
||||||
|
IS_EQUAL_OR_GREATER -> R.string.isequalorgreater
|
||||||
|
IS_GREATER -> R.string.isgreater
|
||||||
|
IS_NOT_AVAILABLE -> R.string.isnotavailable
|
||||||
|
}
|
||||||
|
|
||||||
|
fun <T : Comparable<T>> check(obj1: T, obj2: T): Boolean {
|
||||||
|
val comparison = obj1.compareTo(obj2)
|
||||||
|
return when (this) {
|
||||||
|
IS_LESSER -> comparison < 0
|
||||||
|
IS_EQUAL_OR_LESSER -> comparison <= 0
|
||||||
|
IS_EQUAL -> comparison == 0
|
||||||
|
IS_EQUAL_OR_GREATER -> comparison >= 0
|
||||||
|
IS_GREATER -> comparison > 0
|
||||||
|
else -> false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
fun labels(resourceHelper: ResourceHelper): List<String> {
|
||||||
|
val list: MutableList<String> = ArrayList()
|
||||||
|
for (c in values()) {
|
||||||
|
list.add(resourceHelper.gs(c.stringRes))
|
||||||
|
}
|
||||||
|
return list
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
constructor(mainApp: MainApp, value : Compare) : this(mainApp) {
|
||||||
|
this.value = value
|
||||||
|
}
|
||||||
|
|
||||||
|
var value = Compare.IS_EQUAL
|
||||||
|
|
||||||
|
override fun addToLayout(root: LinearLayout) {
|
||||||
|
val spinner = Spinner(root.context)
|
||||||
|
val spinnerArrayAdapter = ArrayAdapter(root.context, R.layout.spinner_centered, Compare.labels(resourceHelper))
|
||||||
|
spinnerArrayAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item)
|
||||||
|
spinner.adapter = spinnerArrayAdapter
|
||||||
|
val spinnerParams = LinearLayout.LayoutParams(
|
||||||
|
LinearLayout.LayoutParams.MATCH_PARENT,
|
||||||
|
LinearLayout.LayoutParams.WRAP_CONTENT
|
||||||
|
)
|
||||||
|
spinnerParams.setMargins(0, resourceHelper.dpToPx(4), 0, resourceHelper.dpToPx(4))
|
||||||
|
spinner.layoutParams = spinnerParams
|
||||||
|
spinner.onItemSelectedListener = object : AdapterView.OnItemSelectedListener {
|
||||||
|
override fun onItemSelected(parent: AdapterView<*>?, view: View, position: Int, id: Long) {
|
||||||
|
value = Compare.values()[position]
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onNothingSelected(parent: AdapterView<*>?) {}
|
||||||
|
}
|
||||||
|
spinner.setSelection(value.ordinal)
|
||||||
|
root.addView(spinner)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun setValue(compare: Compare): Comparator {
|
||||||
|
value = compare
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,90 +0,0 @@
|
||||||
package info.nightscout.androidaps.plugins.general.automation.elements;
|
|
||||||
|
|
||||||
import android.view.View;
|
|
||||||
import android.widget.AdapterView;
|
|
||||||
import android.widget.ArrayAdapter;
|
|
||||||
import android.widget.LinearLayout;
|
|
||||||
import android.widget.Spinner;
|
|
||||||
|
|
||||||
import androidx.annotation.StringRes;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import info.nightscout.androidaps.MainApp;
|
|
||||||
import info.nightscout.androidaps.R;
|
|
||||||
|
|
||||||
public class ComparatorExists extends Element {
|
|
||||||
public enum Compare {
|
|
||||||
EXISTS,
|
|
||||||
NOT_EXISTS;
|
|
||||||
|
|
||||||
public @StringRes
|
|
||||||
int getStringRes() {
|
|
||||||
switch (this) {
|
|
||||||
case EXISTS:
|
|
||||||
return R.string.exists;
|
|
||||||
case NOT_EXISTS:
|
|
||||||
return R.string.notexists;
|
|
||||||
default:
|
|
||||||
return R.string.unknown;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static List<String> labels() {
|
|
||||||
List<String> list = new ArrayList<>();
|
|
||||||
for (Compare c : Compare.values()) {
|
|
||||||
list.add(MainApp.gs(c.getStringRes()));
|
|
||||||
}
|
|
||||||
return list;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private Compare compare = Compare.EXISTS;
|
|
||||||
|
|
||||||
public ComparatorExists() {
|
|
||||||
super();
|
|
||||||
}
|
|
||||||
|
|
||||||
public ComparatorExists(ComparatorExists another) {
|
|
||||||
super();
|
|
||||||
compare = another.getValue();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void addToLayout(LinearLayout root) {
|
|
||||||
Spinner spinner = new Spinner(root.getContext());
|
|
||||||
ArrayAdapter<String> spinnerArrayAdapter = new ArrayAdapter<>(root.getContext(), R.layout.spinner_centered, Compare.labels());
|
|
||||||
spinnerArrayAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
|
|
||||||
spinner.setAdapter(spinnerArrayAdapter);
|
|
||||||
LinearLayout.LayoutParams spinnerParams = new LinearLayout.LayoutParams(
|
|
||||||
LinearLayout.LayoutParams.MATCH_PARENT,
|
|
||||||
LinearLayout.LayoutParams.WRAP_CONTENT
|
|
||||||
);
|
|
||||||
spinnerParams.setMargins(0, MainApp.dpToPx(4), 0, MainApp.dpToPx(4));
|
|
||||||
spinner.setLayoutParams(spinnerParams);
|
|
||||||
spinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
|
|
||||||
@Override
|
|
||||||
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
|
|
||||||
compare = Compare.values()[position];
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onNothingSelected(AdapterView<?> parent) {
|
|
||||||
}
|
|
||||||
});
|
|
||||||
spinner.setSelection(compare.ordinal());
|
|
||||||
root.addView(spinner);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public Compare getValue() {
|
|
||||||
return compare;
|
|
||||||
}
|
|
||||||
|
|
||||||
public ComparatorExists setValue(Compare compare) {
|
|
||||||
this.compare = compare;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -0,0 +1,57 @@
|
||||||
|
package info.nightscout.androidaps.plugins.general.automation.elements
|
||||||
|
|
||||||
|
import android.view.View
|
||||||
|
import android.widget.AdapterView
|
||||||
|
import android.widget.ArrayAdapter
|
||||||
|
import android.widget.LinearLayout
|
||||||
|
import android.widget.Spinner
|
||||||
|
import androidx.annotation.StringRes
|
||||||
|
import info.nightscout.androidaps.MainApp
|
||||||
|
import info.nightscout.androidaps.R
|
||||||
|
import info.nightscout.androidaps.utils.resources.ResourceHelper
|
||||||
|
import java.util.*
|
||||||
|
|
||||||
|
class ComparatorExists(mainApp: MainApp) : Element(mainApp) {
|
||||||
|
enum class Compare {
|
||||||
|
EXISTS, NOT_EXISTS;
|
||||||
|
|
||||||
|
@get:StringRes val stringRes: Int
|
||||||
|
get() = when (this) {
|
||||||
|
EXISTS -> R.string.exists
|
||||||
|
NOT_EXISTS -> R.string.notexists
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
fun labels(resourceHelper: ResourceHelper): List<String> {
|
||||||
|
val list: MutableList<String> = ArrayList()
|
||||||
|
for (c in values()) list.add(resourceHelper.gs(c.stringRes))
|
||||||
|
return list
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
constructor(mainApp: MainApp, value: Compare) : this(mainApp) {
|
||||||
|
this.value = value
|
||||||
|
}
|
||||||
|
|
||||||
|
var value = Compare.EXISTS
|
||||||
|
|
||||||
|
override fun addToLayout(root: LinearLayout) {
|
||||||
|
val spinner = Spinner(root.context)
|
||||||
|
val spinnerArrayAdapter = ArrayAdapter(root.context, R.layout.spinner_centered, Compare.labels(resourceHelper))
|
||||||
|
spinnerArrayAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item)
|
||||||
|
spinner.adapter = spinnerArrayAdapter
|
||||||
|
val spinnerParams = LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT)
|
||||||
|
spinnerParams.setMargins(0, resourceHelper.dpToPx(4), 0, resourceHelper.dpToPx(4))
|
||||||
|
spinner.layoutParams = spinnerParams
|
||||||
|
spinner.onItemSelectedListener = object : AdapterView.OnItemSelectedListener {
|
||||||
|
override fun onItemSelected(parent: AdapterView<*>?, view: View, position: Int, id: Long) {
|
||||||
|
value = Compare.values()[position]
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onNothingSelected(parent: AdapterView<*>?) {}
|
||||||
|
}
|
||||||
|
spinner.setSelection(value.ordinal)
|
||||||
|
root.addView(spinner)
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,7 +0,0 @@
|
||||||
package info.nightscout.androidaps.plugins.general.automation.elements;
|
|
||||||
|
|
||||||
import android.widget.LinearLayout;
|
|
||||||
|
|
||||||
public abstract class Element {
|
|
||||||
public abstract void addToLayout(LinearLayout root);
|
|
||||||
}
|
|
|
@ -0,0 +1,20 @@
|
||||||
|
package info.nightscout.androidaps.plugins.general.automation.elements
|
||||||
|
|
||||||
|
import android.widget.LinearLayout
|
||||||
|
import info.nightscout.androidaps.MainApp
|
||||||
|
import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin
|
||||||
|
import info.nightscout.androidaps.plugins.configBuilder.ProfileFunction
|
||||||
|
import info.nightscout.androidaps.utils.resources.ResourceHelper
|
||||||
|
import javax.inject.Inject
|
||||||
|
|
||||||
|
abstract class Element(val mainApp: MainApp) {
|
||||||
|
@Inject lateinit var resourceHelper: ResourceHelper
|
||||||
|
@Inject lateinit var profileFunction: ProfileFunction
|
||||||
|
@Inject lateinit var configBuilderPlugin: ConfigBuilderPlugin
|
||||||
|
|
||||||
|
abstract fun addToLayout(root: LinearLayout)
|
||||||
|
|
||||||
|
init {
|
||||||
|
mainApp.androidInjector().inject(this)
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,83 +0,0 @@
|
||||||
package info.nightscout.androidaps.plugins.general.automation.elements;
|
|
||||||
|
|
||||||
import android.text.Editable;
|
|
||||||
import android.text.TextWatcher;
|
|
||||||
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 InputBg extends Element {
|
|
||||||
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;
|
|
||||||
double minValue;
|
|
||||||
private double maxValue;
|
|
||||||
private double step;
|
|
||||||
private DecimalFormat decimalFormat;
|
|
||||||
|
|
||||||
public InputBg() {
|
|
||||||
super();
|
|
||||||
setUnits(ProfileFunctions.getSystemUnits());
|
|
||||||
if (getUnits().equals(Constants.MMOL))
|
|
||||||
value = MMOL_MIN;
|
|
||||||
else
|
|
||||||
value = MGDL_MIN;
|
|
||||||
}
|
|
||||||
|
|
||||||
public InputBg(InputBg 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 InputBg setUnits(String units) {
|
|
||||||
// set default initial value
|
|
||||||
if (units.equals(Constants.MMOL)) {
|
|
||||||
// mmol
|
|
||||||
minValue = MMOL_MIN;
|
|
||||||
maxValue = MMOL_MAX;
|
|
||||||
step = 0.1;
|
|
||||||
decimalFormat = new DecimalFormat("0.0");
|
|
||||||
} else {
|
|
||||||
// mg/dL
|
|
||||||
minValue = MGDL_MIN;
|
|
||||||
maxValue = MGDL_MAX;
|
|
||||||
step = 1;
|
|
||||||
decimalFormat = new DecimalFormat("0");
|
|
||||||
}
|
|
||||||
|
|
||||||
this.units = units;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public InputBg setValue(double value) {
|
|
||||||
this.value = value;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public double getValue() {
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -0,0 +1,58 @@
|
||||||
|
package info.nightscout.androidaps.plugins.general.automation.elements
|
||||||
|
|
||||||
|
import android.widget.LinearLayout
|
||||||
|
import info.nightscout.androidaps.Constants
|
||||||
|
import info.nightscout.androidaps.MainApp
|
||||||
|
import info.nightscout.androidaps.R
|
||||||
|
import info.nightscout.androidaps.utils.NumberPicker
|
||||||
|
import java.text.DecimalFormat
|
||||||
|
|
||||||
|
class InputBg(mainApp: MainApp) : Element(mainApp) {
|
||||||
|
var units = Constants.MGDL
|
||||||
|
var value = 0.0
|
||||||
|
private var minValue = 0.0
|
||||||
|
private var maxValue = 0.0
|
||||||
|
private var step = 0.0
|
||||||
|
private var decimalFormat: DecimalFormat? = null
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
constructor(mainApp: MainApp, value : Double, units: String) : this(mainApp) {
|
||||||
|
setUnits(units)
|
||||||
|
this.value = value
|
||||||
|
}
|
||||||
|
|
||||||
|
init {
|
||||||
|
setUnits(profileFunction.getUnits())
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun addToLayout(root: LinearLayout) {
|
||||||
|
val numberPicker = NumberPicker(root.context, null)
|
||||||
|
numberPicker.setParams(value, minValue, maxValue, step, decimalFormat, false, root.findViewById(R.id.ok))
|
||||||
|
numberPicker.setOnValueChangedListener { value: Double -> this.value = value }
|
||||||
|
root.addView(numberPicker)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun setUnits(units: String): InputBg {
|
||||||
|
if (units == Constants.MMOL) {
|
||||||
|
minValue = MMOL_MIN
|
||||||
|
maxValue = MMOL_MAX
|
||||||
|
step = 0.1
|
||||||
|
decimalFormat = DecimalFormat("0.0")
|
||||||
|
} else {
|
||||||
|
minValue = MGDL_MIN
|
||||||
|
maxValue = MGDL_MAX
|
||||||
|
step = 1.0
|
||||||
|
decimalFormat = DecimalFormat("0")
|
||||||
|
}
|
||||||
|
this.units = units
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
const val MMOL_MIN = 3.0
|
||||||
|
const val MMOL_MAX = 20.0
|
||||||
|
const val MGDL_MIN = 54.0
|
||||||
|
const val MGDL_MAX = 360.0
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,28 +0,0 @@
|
||||||
package info.nightscout.androidaps.plugins.general.automation.elements;
|
|
||||||
|
|
||||||
import android.widget.Button;
|
|
||||||
import android.widget.LinearLayout;
|
|
||||||
|
|
||||||
public class InputButton extends Element {
|
|
||||||
|
|
||||||
String text;
|
|
||||||
Runnable runnable;
|
|
||||||
|
|
||||||
public InputButton(String text, Runnable runnable) {
|
|
||||||
this.text = text;
|
|
||||||
this.runnable = runnable;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void addToLayout(LinearLayout root) {
|
|
||||||
Button button = new Button(root.getContext());
|
|
||||||
|
|
||||||
button.setText(text);
|
|
||||||
button.setOnClickListener(view -> {
|
|
||||||
if (runnable != null)
|
|
||||||
runnable.run();
|
|
||||||
});
|
|
||||||
|
|
||||||
root.addView(button);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -0,0 +1,22 @@
|
||||||
|
package info.nightscout.androidaps.plugins.general.automation.elements
|
||||||
|
|
||||||
|
import android.widget.Button
|
||||||
|
import android.widget.LinearLayout
|
||||||
|
import info.nightscout.androidaps.MainApp
|
||||||
|
|
||||||
|
class InputButton(mainApp: MainApp) : Element(mainApp) {
|
||||||
|
var text: String? = null
|
||||||
|
var runnable: Runnable? = null
|
||||||
|
|
||||||
|
constructor(mainApp: MainApp, text: String, runnable: Runnable) : this(mainApp) {
|
||||||
|
this.text = text
|
||||||
|
this.runnable = runnable
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun addToLayout(root: LinearLayout) {
|
||||||
|
val button = Button(root.context)
|
||||||
|
button.text = text
|
||||||
|
button.setOnClickListener { runnable?.run() }
|
||||||
|
root.addView(button)
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,138 +0,0 @@
|
||||||
package info.nightscout.androidaps.plugins.general.automation.elements;
|
|
||||||
|
|
||||||
import android.text.Editable;
|
|
||||||
import android.text.TextWatcher;
|
|
||||||
import android.view.View;
|
|
||||||
import android.view.ViewGroup;
|
|
||||||
import android.widget.AdapterView;
|
|
||||||
import android.widget.ArrayAdapter;
|
|
||||||
import android.widget.LinearLayout;
|
|
||||||
import android.widget.Spinner;
|
|
||||||
|
|
||||||
import androidx.annotation.StringRes;
|
|
||||||
|
|
||||||
import java.text.DecimalFormat;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import info.nightscout.androidaps.MainApp;
|
|
||||||
import info.nightscout.androidaps.R;
|
|
||||||
import info.nightscout.androidaps.utils.NumberPicker;
|
|
||||||
|
|
||||||
public class InputDelta extends Element {
|
|
||||||
private Comparator.Compare compare = Comparator.Compare.IS_EQUAL;
|
|
||||||
|
|
||||||
public enum DeltaType {
|
|
||||||
DELTA,
|
|
||||||
SHORT_AVERAGE,
|
|
||||||
LONG_AVERAGE;
|
|
||||||
|
|
||||||
public @StringRes
|
|
||||||
int getStringRes() {
|
|
||||||
switch (this) {
|
|
||||||
case DELTA:
|
|
||||||
return R.string.delta;
|
|
||||||
case SHORT_AVERAGE:
|
|
||||||
return R.string.short_avgdelta;
|
|
||||||
case LONG_AVERAGE:
|
|
||||||
return R.string.long_avgdelta;
|
|
||||||
default:
|
|
||||||
return R.string.unknown;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static List<String> labels() {
|
|
||||||
List<String> list = new ArrayList<>();
|
|
||||||
for (DeltaType d : DeltaType.values()) {
|
|
||||||
list.add(MainApp.gs(d.getStringRes()));
|
|
||||||
}
|
|
||||||
return list;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private double value;
|
|
||||||
double minValue;
|
|
||||||
double maxValue;
|
|
||||||
private double step;
|
|
||||||
private DecimalFormat decimalFormat;
|
|
||||||
private DeltaType deltaType;
|
|
||||||
|
|
||||||
NumberPicker numberPicker;
|
|
||||||
|
|
||||||
public InputDelta() {
|
|
||||||
super();
|
|
||||||
}
|
|
||||||
|
|
||||||
public InputDelta(double value, double minValue, double maxValue, double step, DecimalFormat decimalFormat, DeltaType deltaType) {
|
|
||||||
super();
|
|
||||||
this.value = value;
|
|
||||||
this.minValue = minValue;
|
|
||||||
this.maxValue = maxValue;
|
|
||||||
this.step = step;
|
|
||||||
this.decimalFormat = decimalFormat;
|
|
||||||
this.deltaType = deltaType;
|
|
||||||
}
|
|
||||||
|
|
||||||
public InputDelta(InputDelta another) {
|
|
||||||
super();
|
|
||||||
value = another.getValue();
|
|
||||||
minValue = another.minValue;
|
|
||||||
maxValue = another.maxValue;
|
|
||||||
step = another.step;
|
|
||||||
decimalFormat = another.decimalFormat;
|
|
||||||
deltaType = another.deltaType;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void addToLayout(LinearLayout root) {
|
|
||||||
Spinner spinner = new Spinner(root.getContext());
|
|
||||||
ArrayAdapter<String> spinnerArrayAdapter = new ArrayAdapter<>(root.getContext(), R.layout.spinner_centered, DeltaType.labels());
|
|
||||||
spinnerArrayAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
|
|
||||||
spinner.setAdapter(spinnerArrayAdapter);
|
|
||||||
LinearLayout.LayoutParams spinnerParams = new LinearLayout.LayoutParams(
|
|
||||||
LinearLayout.LayoutParams.WRAP_CONTENT,
|
|
||||||
LinearLayout.LayoutParams.WRAP_CONTENT
|
|
||||||
);
|
|
||||||
spinnerParams.setMargins(0, MainApp.dpToPx(4), 0, MainApp.dpToPx(4));
|
|
||||||
spinner.setLayoutParams(spinnerParams);
|
|
||||||
spinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
|
|
||||||
@Override
|
|
||||||
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
|
|
||||||
deltaType = DeltaType.values()[position];
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onNothingSelected(AdapterView<?> parent) {
|
|
||||||
}
|
|
||||||
});
|
|
||||||
spinner.setSelection(this.deltaType.ordinal());
|
|
||||||
// root.addView(spinner);
|
|
||||||
numberPicker = new NumberPicker(root.getContext(), null);
|
|
||||||
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);
|
|
||||||
l.setLayoutParams(new LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT));
|
|
||||||
l.addView(spinner);
|
|
||||||
l.addView(numberPicker);
|
|
||||||
root.addView(l);
|
|
||||||
}
|
|
||||||
|
|
||||||
public InputDelta setValue(double value, DeltaType type) {
|
|
||||||
this.value = value;
|
|
||||||
this.deltaType = type;
|
|
||||||
if (numberPicker != null)
|
|
||||||
numberPicker.setValue(value);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public double getValue() {
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
|
|
||||||
public DeltaType getDeltaType() {
|
|
||||||
return deltaType;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -0,0 +1,93 @@
|
||||||
|
package info.nightscout.androidaps.plugins.general.automation.elements
|
||||||
|
|
||||||
|
import android.view.View
|
||||||
|
import android.view.ViewGroup
|
||||||
|
import android.widget.AdapterView
|
||||||
|
import android.widget.ArrayAdapter
|
||||||
|
import android.widget.LinearLayout
|
||||||
|
import android.widget.Spinner
|
||||||
|
import androidx.annotation.StringRes
|
||||||
|
import info.nightscout.androidaps.MainApp
|
||||||
|
import info.nightscout.androidaps.R
|
||||||
|
import info.nightscout.androidaps.utils.NumberPicker
|
||||||
|
import info.nightscout.androidaps.utils.resources.ResourceHelper
|
||||||
|
import java.text.DecimalFormat
|
||||||
|
import java.util.*
|
||||||
|
|
||||||
|
class InputDelta(mainApp: MainApp) : Element(mainApp) {
|
||||||
|
enum class DeltaType {
|
||||||
|
DELTA, SHORT_AVERAGE, LONG_AVERAGE;
|
||||||
|
|
||||||
|
@get:StringRes val stringRes: Int
|
||||||
|
get() = when (this) {
|
||||||
|
DELTA -> R.string.delta
|
||||||
|
SHORT_AVERAGE -> R.string.short_avgdelta
|
||||||
|
LONG_AVERAGE -> R.string.long_avgdelta
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
fun labels(resourceHelper: ResourceHelper): List<String> {
|
||||||
|
val list: MutableList<String> = ArrayList()
|
||||||
|
for (d in values()) {
|
||||||
|
list.add(resourceHelper.gs(d.stringRes))
|
||||||
|
}
|
||||||
|
return list
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var value = 0.0
|
||||||
|
private var minValue = 0.0
|
||||||
|
private var maxValue = 0.0
|
||||||
|
private var step = 0.0
|
||||||
|
private var decimalFormat: DecimalFormat? = null
|
||||||
|
var deltaType: DeltaType = DeltaType.DELTA
|
||||||
|
|
||||||
|
constructor(mainApp: MainApp, value: Double, minValue: Double, maxValue: Double, step: Double, decimalFormat: DecimalFormat, deltaType: DeltaType) : this(mainApp) {
|
||||||
|
this.value = value
|
||||||
|
this.minValue = minValue
|
||||||
|
this.maxValue = maxValue
|
||||||
|
this.step = step
|
||||||
|
this.decimalFormat = decimalFormat
|
||||||
|
this.deltaType = deltaType
|
||||||
|
}
|
||||||
|
|
||||||
|
constructor(mainApp: MainApp, inputDelta: InputDelta) : this(mainApp) {
|
||||||
|
value = inputDelta.value
|
||||||
|
minValue = inputDelta.minValue
|
||||||
|
maxValue = inputDelta.maxValue
|
||||||
|
step = inputDelta.step
|
||||||
|
decimalFormat = inputDelta.decimalFormat
|
||||||
|
deltaType = inputDelta.deltaType
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun addToLayout(root: LinearLayout) {
|
||||||
|
val spinner = Spinner(root.context)
|
||||||
|
val spinnerArrayAdapter = ArrayAdapter(root.context, R.layout.spinner_centered, DeltaType.labels(resourceHelper))
|
||||||
|
spinnerArrayAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item)
|
||||||
|
spinner.adapter = spinnerArrayAdapter
|
||||||
|
val spinnerParams = LinearLayout.LayoutParams(
|
||||||
|
LinearLayout.LayoutParams.WRAP_CONTENT,
|
||||||
|
LinearLayout.LayoutParams.WRAP_CONTENT
|
||||||
|
)
|
||||||
|
spinnerParams.setMargins(0, resourceHelper.dpToPx(4), 0, resourceHelper.dpToPx(4))
|
||||||
|
spinner.layoutParams = spinnerParams
|
||||||
|
spinner.onItemSelectedListener = object : AdapterView.OnItemSelectedListener {
|
||||||
|
override fun onItemSelected(parent: AdapterView<*>?, view: View, position: Int, id: Long) {
|
||||||
|
deltaType = DeltaType.values()[position]
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onNothingSelected(parent: AdapterView<*>?) {}
|
||||||
|
}
|
||||||
|
spinner.setSelection(deltaType.ordinal)
|
||||||
|
val numberPicker = NumberPicker(root.context, null)
|
||||||
|
numberPicker.setParams(value, minValue, maxValue, step, decimalFormat, true, null, null)
|
||||||
|
numberPicker.setOnValueChangedListener { value: Double -> this.value = value }
|
||||||
|
val l = LinearLayout(root.context)
|
||||||
|
l.orientation = LinearLayout.VERTICAL
|
||||||
|
l.layoutParams = LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT)
|
||||||
|
l.addView(spinner)
|
||||||
|
l.addView(numberPicker)
|
||||||
|
root.addView(l)
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,77 +0,0 @@
|
||||||
package info.nightscout.androidaps.plugins.general.automation.elements;
|
|
||||||
|
|
||||||
import android.text.Editable;
|
|
||||||
import android.text.TextWatcher;
|
|
||||||
import android.widget.LinearLayout;
|
|
||||||
|
|
||||||
import java.text.DecimalFormat;
|
|
||||||
|
|
||||||
import info.nightscout.androidaps.utils.NumberPicker;
|
|
||||||
|
|
||||||
public class InputDouble extends Element {
|
|
||||||
|
|
||||||
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) {
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
private double value;
|
|
||||||
private double minValue;
|
|
||||||
private double maxValue;
|
|
||||||
private double step;
|
|
||||||
private DecimalFormat decimalFormat;
|
|
||||||
|
|
||||||
NumberPicker numberPicker;
|
|
||||||
|
|
||||||
public InputDouble() {
|
|
||||||
super();
|
|
||||||
}
|
|
||||||
|
|
||||||
public InputDouble(double value, double minValue, double maxValue, double step, DecimalFormat decimalFormat) {
|
|
||||||
super();
|
|
||||||
this.value = value;
|
|
||||||
this.minValue = minValue;
|
|
||||||
this.maxValue = maxValue;
|
|
||||||
this.step = step;
|
|
||||||
this.decimalFormat = decimalFormat;
|
|
||||||
}
|
|
||||||
|
|
||||||
public InputDouble(InputDouble another) {
|
|
||||||
super();
|
|
||||||
value = another.getValue();
|
|
||||||
minValue = another.minValue;
|
|
||||||
maxValue = another.maxValue;
|
|
||||||
step = another.step;
|
|
||||||
decimalFormat = another.decimalFormat;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void addToLayout(LinearLayout root) {
|
|
||||||
numberPicker = new NumberPicker(root.getContext(), null);
|
|
||||||
numberPicker.setParams(value, minValue, maxValue, step, decimalFormat, true, null, textWatcher);
|
|
||||||
numberPicker.setOnValueChangedListener(value -> this.value = value);
|
|
||||||
root.addView(numberPicker);
|
|
||||||
}
|
|
||||||
|
|
||||||
public InputDouble setValue(double value) {
|
|
||||||
this.value = value;
|
|
||||||
if (numberPicker != null)
|
|
||||||
numberPicker.setValue(value);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public double getValue() {
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -0,0 +1,45 @@
|
||||||
|
package info.nightscout.androidaps.plugins.general.automation.elements
|
||||||
|
|
||||||
|
import android.widget.LinearLayout
|
||||||
|
import info.nightscout.androidaps.MainApp
|
||||||
|
import info.nightscout.androidaps.R
|
||||||
|
import info.nightscout.androidaps.utils.NumberPicker
|
||||||
|
import java.text.DecimalFormat
|
||||||
|
|
||||||
|
class InputDouble(mainApp: MainApp) : Element(mainApp) {
|
||||||
|
var value = 0.0
|
||||||
|
private var minValue = 0.0
|
||||||
|
private var maxValue = 0.0
|
||||||
|
private var step = 0.0
|
||||||
|
private var decimalFormat: DecimalFormat? = null
|
||||||
|
private var numberPicker: NumberPicker? = null
|
||||||
|
|
||||||
|
constructor(mainApp: MainApp, value: Double, minValue: Double, maxValue: Double, step: Double, decimalFormat: DecimalFormat) : this(mainApp) {
|
||||||
|
this.value = value
|
||||||
|
this.minValue = minValue
|
||||||
|
this.maxValue = maxValue
|
||||||
|
this.step = step
|
||||||
|
this.decimalFormat = decimalFormat
|
||||||
|
}
|
||||||
|
|
||||||
|
constructor(mainApp: MainApp, inputDouble: InputDouble) : this(mainApp) {
|
||||||
|
this.value = inputDouble.value
|
||||||
|
this.minValue = inputDouble.minValue
|
||||||
|
this.maxValue = inputDouble.maxValue
|
||||||
|
this.step = inputDouble.step
|
||||||
|
this.decimalFormat = inputDouble.decimalFormat
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun addToLayout(root: LinearLayout) {
|
||||||
|
numberPicker = NumberPicker(root.context, null)
|
||||||
|
numberPicker?.setParams(value, minValue, maxValue, step, decimalFormat, true, root.findViewById(R.id.ok))
|
||||||
|
numberPicker?.setOnValueChangedListener { value: Double -> this.value = value }
|
||||||
|
root.addView(numberPicker)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun setValue(value: Double): InputDouble {
|
||||||
|
this.value = value
|
||||||
|
numberPicker?.value = value
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,66 +0,0 @@
|
||||||
package info.nightscout.androidaps.plugins.general.automation.elements;
|
|
||||||
|
|
||||||
import android.widget.LinearLayout;
|
|
||||||
|
|
||||||
import java.text.DecimalFormat;
|
|
||||||
|
|
||||||
import info.nightscout.androidaps.utils.NumberPicker;
|
|
||||||
|
|
||||||
public class InputDuration extends Element {
|
|
||||||
public enum TimeUnit {
|
|
||||||
MINUTES,
|
|
||||||
HOURS
|
|
||||||
}
|
|
||||||
|
|
||||||
private TimeUnit unit;
|
|
||||||
private int value;
|
|
||||||
|
|
||||||
public InputDuration(int value, TimeUnit unit) {
|
|
||||||
this.unit = unit;
|
|
||||||
this.value = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
public InputDuration(InputDuration another) {
|
|
||||||
unit = another.unit;
|
|
||||||
value = another.value;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void addToLayout(LinearLayout root) {
|
|
||||||
NumberPicker numberPicker = new NumberPicker(root.getContext(), null);
|
|
||||||
if (unit.equals(TimeUnit.MINUTES)) {
|
|
||||||
// Minutes
|
|
||||||
numberPicker.setParams(0d, 0d, 24 * 60d, 10d, new DecimalFormat("0"), false, null);
|
|
||||||
} else {
|
|
||||||
// Hours
|
|
||||||
numberPicker.setParams(0d, 0d, 24d, 1d, new DecimalFormat("0"), false, null);
|
|
||||||
}
|
|
||||||
numberPicker.setValue((double) value);
|
|
||||||
numberPicker.setOnValueChangedListener(value -> this.value = (int) value);
|
|
||||||
root.addView(numberPicker);
|
|
||||||
}
|
|
||||||
|
|
||||||
TimeUnit getUnit() {
|
|
||||||
return unit;
|
|
||||||
}
|
|
||||||
|
|
||||||
public double getValue() {
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setMinutes(int value) {
|
|
||||||
if (unit.equals(TimeUnit.MINUTES)) {
|
|
||||||
this.value = value;
|
|
||||||
} else {
|
|
||||||
this.value = value / 60;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getMinutes() {
|
|
||||||
if (unit.equals(TimeUnit.MINUTES)) {
|
|
||||||
return value;
|
|
||||||
} else {
|
|
||||||
return value * 60;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -0,0 +1,49 @@
|
||||||
|
package info.nightscout.androidaps.plugins.general.automation.elements
|
||||||
|
|
||||||
|
import android.widget.LinearLayout
|
||||||
|
import info.nightscout.androidaps.MainApp
|
||||||
|
import info.nightscout.androidaps.R
|
||||||
|
import info.nightscout.androidaps.utils.NumberPicker
|
||||||
|
import java.text.DecimalFormat
|
||||||
|
|
||||||
|
class InputDuration(mainApp: MainApp) : Element(mainApp) {
|
||||||
|
enum class TimeUnit {
|
||||||
|
MINUTES, HOURS
|
||||||
|
}
|
||||||
|
|
||||||
|
constructor(mainApp: MainApp, value: Int, unit: TimeUnit) : this(mainApp) {
|
||||||
|
this.unit = unit
|
||||||
|
this.value = value
|
||||||
|
}
|
||||||
|
|
||||||
|
var unit: TimeUnit = TimeUnit.MINUTES
|
||||||
|
var value: Int = 0
|
||||||
|
|
||||||
|
override fun addToLayout(root: LinearLayout) {
|
||||||
|
val numberPicker = NumberPicker(root.context, null)
|
||||||
|
if (unit == TimeUnit.MINUTES)
|
||||||
|
numberPicker.setParams(0.0, 0.0, 24 * 60.0, 10.0, DecimalFormat("0"), false, root.findViewById(R.id.ok))
|
||||||
|
else
|
||||||
|
numberPicker.setParams(0.0, 0.0, 24.0, 1.0, DecimalFormat("0"), false, root.findViewById(R.id.ok))
|
||||||
|
numberPicker.value = value.toDouble()
|
||||||
|
numberPicker.setOnValueChangedListener { value: Double -> this.value = value.toInt() }
|
||||||
|
root.addView(numberPicker)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun duplicate(): InputDuration {
|
||||||
|
val i = InputDuration(mainApp)
|
||||||
|
i.unit = unit
|
||||||
|
i.value = value
|
||||||
|
return i
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getMinutes(): Int = if (unit == TimeUnit.MINUTES) value else value * 60
|
||||||
|
|
||||||
|
fun setMinutes(value: Int): InputDuration {
|
||||||
|
if (unit == TimeUnit.MINUTES)
|
||||||
|
this.value = value
|
||||||
|
else
|
||||||
|
this.value = value / 60
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,57 +0,0 @@
|
||||||
package info.nightscout.androidaps.plugins.general.automation.elements;
|
|
||||||
|
|
||||||
import android.text.Editable;
|
|
||||||
import android.text.TextWatcher;
|
|
||||||
import android.widget.LinearLayout;
|
|
||||||
|
|
||||||
import java.text.DecimalFormat;
|
|
||||||
|
|
||||||
import info.nightscout.androidaps.utils.NumberPicker;
|
|
||||||
|
|
||||||
public class InputInsulin extends Element {
|
|
||||||
|
|
||||||
final TextWatcher textWatcher = new TextWatcher() {
|
|
||||||
@Override
|
|
||||||
public void afterTextChanged(Editable s) {
|
|
||||||
value = Math.max(value, -20d);
|
|
||||||
value = Math.min(value, 20d);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onTextChanged(CharSequence s, int start, int before, int count) {
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
private double value;
|
|
||||||
|
|
||||||
public InputInsulin() {
|
|
||||||
super();
|
|
||||||
}
|
|
||||||
|
|
||||||
public InputInsulin(InputInsulin another) {
|
|
||||||
super();
|
|
||||||
value = another.getValue();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void addToLayout(LinearLayout root) {
|
|
||||||
NumberPicker numberPicker = new NumberPicker(root.getContext(), null);
|
|
||||||
numberPicker.setParams(0d, -20d, 20d, 0.1, new DecimalFormat("0.0"), true, null, textWatcher);
|
|
||||||
numberPicker.setValue(value);
|
|
||||||
numberPicker.setOnValueChangedListener(value -> this.value = value);
|
|
||||||
root.addView(numberPicker);
|
|
||||||
}
|
|
||||||
|
|
||||||
public double getValue() {
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
|
|
||||||
public InputInsulin setValue(double value) {
|
|
||||||
this.value = value;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -0,0 +1,23 @@
|
||||||
|
package info.nightscout.androidaps.plugins.general.automation.elements
|
||||||
|
|
||||||
|
import android.widget.LinearLayout
|
||||||
|
import info.nightscout.androidaps.MainApp
|
||||||
|
import info.nightscout.androidaps.R
|
||||||
|
import info.nightscout.androidaps.utils.NumberPicker
|
||||||
|
import java.text.DecimalFormat
|
||||||
|
|
||||||
|
class InputInsulin(mainApp: MainApp) : Element(mainApp) {
|
||||||
|
var value = 0.0
|
||||||
|
|
||||||
|
constructor(mainApp: MainApp, another: InputInsulin) : this(mainApp) {
|
||||||
|
value = another.value
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun addToLayout(root: LinearLayout) {
|
||||||
|
val numberPicker = NumberPicker(root.context, null)
|
||||||
|
numberPicker.setParams(0.0, -20.0, 20.0, 0.1, DecimalFormat("0.0"), true, root.findViewById(R.id.ok))
|
||||||
|
numberPicker.value = value
|
||||||
|
numberPicker.setOnValueChangedListener { value: Double -> this.value = value }
|
||||||
|
root.addView(numberPicker)
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,107 +0,0 @@
|
||||||
package info.nightscout.androidaps.plugins.general.automation.elements;
|
|
||||||
import android.view.View;
|
|
||||||
import android.widget.AdapterView;
|
|
||||||
import android.widget.ArrayAdapter;
|
|
||||||
import android.widget.LinearLayout;
|
|
||||||
import android.widget.Spinner;
|
|
||||||
|
|
||||||
import androidx.annotation.StringRes;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import info.nightscout.androidaps.MainApp;
|
|
||||||
import info.nightscout.androidaps.R;
|
|
||||||
|
|
||||||
public class InputLocationMode extends Element {
|
|
||||||
|
|
||||||
public enum Mode {
|
|
||||||
INSIDE,
|
|
||||||
OUTSIDE,
|
|
||||||
GOING_IN,
|
|
||||||
GOING_OUT;
|
|
||||||
|
|
||||||
public @StringRes
|
|
||||||
int getStringRes() {
|
|
||||||
switch (this) {
|
|
||||||
case INSIDE:
|
|
||||||
return R.string.location_inside;
|
|
||||||
case OUTSIDE:
|
|
||||||
return R.string.location_outside;
|
|
||||||
case GOING_IN:
|
|
||||||
return R.string.location_going_in;
|
|
||||||
case GOING_OUT:
|
|
||||||
return R.string.location_going_out;
|
|
||||||
default:
|
|
||||||
return R.string.unknown;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static List<String> labels() {
|
|
||||||
List<String> list = new ArrayList<>();
|
|
||||||
for (Mode c : Mode.values()) {
|
|
||||||
list.add(MainApp.gs(c.getStringRes()));
|
|
||||||
}
|
|
||||||
return list;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Mode fromString(String wanted){
|
|
||||||
for (Mode c : Mode.values()) {
|
|
||||||
if(c.toString() == wanted)
|
|
||||||
return c;
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private Mode mode;
|
|
||||||
|
|
||||||
public InputLocationMode() {
|
|
||||||
super();
|
|
||||||
mode = Mode.INSIDE;
|
|
||||||
}
|
|
||||||
|
|
||||||
public InputLocationMode(InputLocationMode another) {
|
|
||||||
super();
|
|
||||||
this.mode = another.mode;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void addToLayout(LinearLayout root) {
|
|
||||||
ArrayAdapter<String> adapter = new ArrayAdapter<>(root.getContext(),
|
|
||||||
R.layout.spinner_centered, Mode.labels());
|
|
||||||
Spinner spinner = new Spinner(root.getContext());
|
|
||||||
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
|
|
||||||
spinner.setAdapter(adapter);
|
|
||||||
LinearLayout.LayoutParams spinnerParams = new LinearLayout.LayoutParams(
|
|
||||||
LinearLayout.LayoutParams.WRAP_CONTENT,
|
|
||||||
LinearLayout.LayoutParams.WRAP_CONTENT
|
|
||||||
);
|
|
||||||
spinnerParams.setMargins(0, MainApp.dpToPx(4), 0, MainApp.dpToPx(4));
|
|
||||||
spinner.setLayoutParams(spinnerParams);
|
|
||||||
spinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
|
|
||||||
@Override
|
|
||||||
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
|
|
||||||
setValue(Mode.values()[position]);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onNothingSelected(AdapterView<?> parent) {
|
|
||||||
}
|
|
||||||
});
|
|
||||||
spinner.setSelection(this.getValue().ordinal());
|
|
||||||
root.addView(spinner);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public Mode getValue() {
|
|
||||||
return mode;
|
|
||||||
}
|
|
||||||
|
|
||||||
public InputLocationMode setValue(Mode mode) {
|
|
||||||
this.mode = mode;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
|
@ -0,0 +1,71 @@
|
||||||
|
package info.nightscout.androidaps.plugins.general.automation.elements
|
||||||
|
|
||||||
|
import android.view.View
|
||||||
|
import android.widget.AdapterView
|
||||||
|
import android.widget.ArrayAdapter
|
||||||
|
import android.widget.LinearLayout
|
||||||
|
import android.widget.Spinner
|
||||||
|
import androidx.annotation.StringRes
|
||||||
|
import info.nightscout.androidaps.MainApp
|
||||||
|
import info.nightscout.androidaps.R
|
||||||
|
import info.nightscout.androidaps.utils.resources.ResourceHelper
|
||||||
|
import java.util.*
|
||||||
|
|
||||||
|
class InputLocationMode(mainApp: MainApp) : Element(mainApp) {
|
||||||
|
enum class Mode {
|
||||||
|
INSIDE, OUTSIDE, GOING_IN, GOING_OUT;
|
||||||
|
|
||||||
|
@get:StringRes val stringRes: Int
|
||||||
|
get() = when (this) {
|
||||||
|
INSIDE -> R.string.location_inside
|
||||||
|
OUTSIDE -> R.string.location_outside
|
||||||
|
GOING_IN -> R.string.location_going_in
|
||||||
|
GOING_OUT -> R.string.location_going_out
|
||||||
|
}
|
||||||
|
|
||||||
|
fun fromString(wanted: String): Mode {
|
||||||
|
for (c in values()) {
|
||||||
|
if (c.toString() === wanted) return c
|
||||||
|
}
|
||||||
|
throw IllegalStateException("Invalid parameter")
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
fun labels(resourceHelper: ResourceHelper): List<String> {
|
||||||
|
val list: MutableList<String> = ArrayList()
|
||||||
|
for (c in values()) {
|
||||||
|
list.add(resourceHelper.gs(c.stringRes))
|
||||||
|
}
|
||||||
|
return list
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var value: Mode = Mode.INSIDE
|
||||||
|
|
||||||
|
constructor(mainApp: MainApp, value: InputLocationMode.Mode) : this(mainApp) {
|
||||||
|
this.value = value
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun addToLayout(root: LinearLayout) {
|
||||||
|
val adapter = ArrayAdapter(root.context, R.layout.spinner_centered, Mode.labels(resourceHelper))
|
||||||
|
val spinner = Spinner(root.context)
|
||||||
|
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item)
|
||||||
|
spinner.adapter = adapter
|
||||||
|
val spinnerParams = LinearLayout.LayoutParams(
|
||||||
|
LinearLayout.LayoutParams.WRAP_CONTENT,
|
||||||
|
LinearLayout.LayoutParams.WRAP_CONTENT
|
||||||
|
)
|
||||||
|
spinnerParams.setMargins(0, resourceHelper.dpToPx(4), 0, resourceHelper.dpToPx(4))
|
||||||
|
spinner.layoutParams = spinnerParams
|
||||||
|
spinner.onItemSelectedListener = object : AdapterView.OnItemSelectedListener {
|
||||||
|
override fun onItemSelected(parent: AdapterView<*>?, view: View, position: Int, id: Long) {
|
||||||
|
value = Mode.values()[position]
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onNothingSelected(parent: AdapterView<*>?) {}
|
||||||
|
}
|
||||||
|
spinner.setSelection(value.ordinal)
|
||||||
|
root.addView(spinner)
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,58 +0,0 @@
|
||||||
package info.nightscout.androidaps.plugins.general.automation.elements;
|
|
||||||
|
|
||||||
import android.text.Editable;
|
|
||||||
import android.text.TextWatcher;
|
|
||||||
import android.widget.LinearLayout;
|
|
||||||
|
|
||||||
import java.text.DecimalFormat;
|
|
||||||
|
|
||||||
import info.nightscout.androidaps.utils.NumberPicker;
|
|
||||||
|
|
||||||
public class InputPercent extends Element {
|
|
||||||
|
|
||||||
final TextWatcher textWatcher = new TextWatcher() {
|
|
||||||
@Override
|
|
||||||
public void afterTextChanged(Editable s) {
|
|
||||||
value = Math.max(value, 70d);
|
|
||||||
value = Math.min(value, 130d);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onTextChanged(CharSequence s, int start, int before, int count) {
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
private double value;
|
|
||||||
|
|
||||||
public InputPercent() {
|
|
||||||
super();
|
|
||||||
value = 100d;
|
|
||||||
}
|
|
||||||
|
|
||||||
public InputPercent(InputPercent another) {
|
|
||||||
super();
|
|
||||||
value = another.getValue();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void addToLayout(LinearLayout root) {
|
|
||||||
NumberPicker numberPicker = new NumberPicker(root.getContext(), null);
|
|
||||||
numberPicker.setParams(100d, 70d, 130d, 5d, new DecimalFormat("0"), true, null, textWatcher);
|
|
||||||
numberPicker.setValue(value);
|
|
||||||
numberPicker.setOnValueChangedListener(value -> this.value = value);
|
|
||||||
root.addView(numberPicker);
|
|
||||||
}
|
|
||||||
|
|
||||||
public double getValue() {
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
|
|
||||||
public InputPercent setValue(double value) {
|
|
||||||
this.value = value;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -0,0 +1,28 @@
|
||||||
|
package info.nightscout.androidaps.plugins.general.automation.elements
|
||||||
|
|
||||||
|
import android.widget.LinearLayout
|
||||||
|
import info.nightscout.androidaps.MainApp
|
||||||
|
import info.nightscout.androidaps.R
|
||||||
|
import info.nightscout.androidaps.utils.NumberPicker
|
||||||
|
import java.text.DecimalFormat
|
||||||
|
|
||||||
|
class InputPercent(mainApp: MainApp) : Element(mainApp) {
|
||||||
|
var value: Double = 100.0
|
||||||
|
|
||||||
|
constructor(mainApp: MainApp, value: Double) : this(mainApp) {
|
||||||
|
this.value = value
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun addToLayout(root: LinearLayout) {
|
||||||
|
val numberPicker = NumberPicker(root.context, null)
|
||||||
|
numberPicker.setParams(100.0, MIN, MAX, 5.0, DecimalFormat("0"), true, root.findViewById(R.id.ok))
|
||||||
|
numberPicker.value = value
|
||||||
|
numberPicker.setOnValueChangedListener { value: Double -> this.value = value }
|
||||||
|
root.addView(numberPicker)
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
const val MIN = 70.0
|
||||||
|
const val MAX = 130.0
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,99 +0,0 @@
|
||||||
package info.nightscout.androidaps.plugins.general.automation.elements;
|
|
||||||
|
|
||||||
import android.view.View;
|
|
||||||
import android.view.ViewGroup;
|
|
||||||
import android.widget.AdapterView;
|
|
||||||
import android.widget.ArrayAdapter;
|
|
||||||
import android.widget.LinearLayout;
|
|
||||||
import android.widget.Spinner;
|
|
||||||
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
|
|
||||||
import info.nightscout.androidaps.MainApp;
|
|
||||||
import info.nightscout.androidaps.R;
|
|
||||||
import info.nightscout.androidaps.data.Profile;
|
|
||||||
import info.nightscout.androidaps.data.ProfileStore;
|
|
||||||
import info.nightscout.androidaps.logging.L;
|
|
||||||
import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin;
|
|
||||||
|
|
||||||
public class InputProfileName extends Element {
|
|
||||||
private static Logger log = LoggerFactory.getLogger(L.AUTOMATION);
|
|
||||||
ProfileStore profileStore;
|
|
||||||
|
|
||||||
String profileName;
|
|
||||||
|
|
||||||
public InputProfileName(String name) {
|
|
||||||
super();
|
|
||||||
this.profileName = name;
|
|
||||||
}
|
|
||||||
|
|
||||||
public InputProfileName(InputProfileName another) {
|
|
||||||
super();
|
|
||||||
profileName = another.getValue();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void addToLayout(LinearLayout root) {
|
|
||||||
ArrayList<CharSequence> profileList = new ArrayList<>();
|
|
||||||
profileStore = ConfigBuilderPlugin.getPlugin().getActiveProfileInterface().getProfile();
|
|
||||||
if (profileStore == null) {
|
|
||||||
log.error("ProfileStore is empty");
|
|
||||||
} else {
|
|
||||||
profileList = profileStore.getProfileList();
|
|
||||||
}
|
|
||||||
ArrayAdapter<CharSequence> adapter = new ArrayAdapter<>(root.getContext(),
|
|
||||||
R.layout.spinner_centered, profileList);
|
|
||||||
Spinner spinner = new Spinner(root.getContext());
|
|
||||||
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
|
|
||||||
spinner.setAdapter(adapter);
|
|
||||||
LinearLayout.LayoutParams spinnerParams = new LinearLayout.LayoutParams(
|
|
||||||
LinearLayout.LayoutParams.WRAP_CONTENT,
|
|
||||||
LinearLayout.LayoutParams.WRAP_CONTENT
|
|
||||||
);
|
|
||||||
spinnerParams.setMargins(0, MainApp.dpToPx(4), 0, MainApp.dpToPx(4));
|
|
||||||
spinner.setLayoutParams(spinnerParams);
|
|
||||||
spinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
|
|
||||||
@Override
|
|
||||||
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
|
|
||||||
setValue(listNames().get(position).toString());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onNothingSelected(AdapterView<?> parent) {
|
|
||||||
}
|
|
||||||
});
|
|
||||||
spinner.setSelection(0);
|
|
||||||
LinearLayout l = new LinearLayout(root.getContext());
|
|
||||||
l.setOrientation(LinearLayout.VERTICAL);
|
|
||||||
l.setLayoutParams(new LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT));
|
|
||||||
l.addView(spinner);
|
|
||||||
root.addView(l);
|
|
||||||
}
|
|
||||||
|
|
||||||
public InputProfileName setValue(String name) {
|
|
||||||
this.profileName = name;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getValue() {
|
|
||||||
return profileName;
|
|
||||||
}
|
|
||||||
|
|
||||||
public ArrayList<CharSequence> listNames(){
|
|
||||||
ArrayList<CharSequence> profileList = new ArrayList<>();
|
|
||||||
// profile
|
|
||||||
profileStore = ConfigBuilderPlugin.getPlugin().getActiveProfileInterface().getProfile();
|
|
||||||
if (profileStore == null) {
|
|
||||||
log.error("ProfileStore is empty");
|
|
||||||
} else {
|
|
||||||
profileList = profileStore.getProfileList();
|
|
||||||
}
|
|
||||||
return profileList;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
|
@ -0,0 +1,47 @@
|
||||||
|
package info.nightscout.androidaps.plugins.general.automation.elements
|
||||||
|
|
||||||
|
import android.view.View
|
||||||
|
import android.view.ViewGroup
|
||||||
|
import android.widget.AdapterView
|
||||||
|
import android.widget.ArrayAdapter
|
||||||
|
import android.widget.LinearLayout
|
||||||
|
import android.widget.Spinner
|
||||||
|
import info.nightscout.androidaps.MainApp
|
||||||
|
import info.nightscout.androidaps.R
|
||||||
|
import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin
|
||||||
|
|
||||||
|
class InputProfileName(mainApp: MainApp) : Element(mainApp) {
|
||||||
|
var value: String = ""
|
||||||
|
|
||||||
|
constructor(mainApp: MainApp, name: String) : this(mainApp) {
|
||||||
|
value = name
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun addToLayout(root: LinearLayout) {
|
||||||
|
val profileStore = ConfigBuilderPlugin.getPlugin().activeProfileInterface.profile ?: return
|
||||||
|
val profileList = profileStore.getProfileList()
|
||||||
|
val adapter = ArrayAdapter(root.context, R.layout.spinner_centered, profileList)
|
||||||
|
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item)
|
||||||
|
val spinner = Spinner(root.context)
|
||||||
|
spinner.adapter = adapter
|
||||||
|
val spinnerParams = LinearLayout.LayoutParams(
|
||||||
|
LinearLayout.LayoutParams.WRAP_CONTENT,
|
||||||
|
LinearLayout.LayoutParams.WRAP_CONTENT
|
||||||
|
)
|
||||||
|
spinnerParams.setMargins(0, resourceHelper.dpToPx(4), 0, resourceHelper.dpToPx(4))
|
||||||
|
spinner.layoutParams = spinnerParams
|
||||||
|
spinner.onItemSelectedListener = object : AdapterView.OnItemSelectedListener {
|
||||||
|
override fun onItemSelected(parent: AdapterView<*>?, view: View, position: Int, id: Long) {
|
||||||
|
value = profileList[position].toString()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onNothingSelected(parent: AdapterView<*>?) {}
|
||||||
|
}
|
||||||
|
spinner.setSelection(0)
|
||||||
|
val l = LinearLayout(root.context)
|
||||||
|
l.orientation = LinearLayout.VERTICAL
|
||||||
|
l.layoutParams = LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT)
|
||||||
|
l.addView(spinner)
|
||||||
|
root.addView(l)
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,56 +0,0 @@
|
||||||
package info.nightscout.androidaps.plugins.general.automation.elements;
|
|
||||||
|
|
||||||
import android.text.Editable;
|
|
||||||
import android.text.TextWatcher;
|
|
||||||
import android.view.ViewGroup;
|
|
||||||
import android.widget.EditText;
|
|
||||||
import android.widget.LinearLayout;
|
|
||||||
|
|
||||||
public class InputString extends Element {
|
|
||||||
|
|
||||||
TextWatcher textWatcher = new TextWatcher() {
|
|
||||||
@Override
|
|
||||||
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onTextChanged(CharSequence s, int start, int before, int count) {
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void afterTextChanged(Editable s) {
|
|
||||||
value = s.toString();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
private String value = "";
|
|
||||||
|
|
||||||
public InputString() {
|
|
||||||
super();
|
|
||||||
}
|
|
||||||
|
|
||||||
public InputString(InputString another) {
|
|
||||||
super();
|
|
||||||
value = another.getValue();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void addToLayout(LinearLayout root) {
|
|
||||||
EditText editText = new EditText(root.getContext());
|
|
||||||
editText.setText(value);
|
|
||||||
editText.setLayoutParams(new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT));
|
|
||||||
editText.addTextChangedListener(textWatcher);
|
|
||||||
root.addView(editText);
|
|
||||||
}
|
|
||||||
|
|
||||||
public InputString setValue(String value) {
|
|
||||||
this.value = value;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getValue() {
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -0,0 +1,31 @@
|
||||||
|
package info.nightscout.androidaps.plugins.general.automation.elements
|
||||||
|
|
||||||
|
import android.text.Editable
|
||||||
|
import android.text.TextWatcher
|
||||||
|
import android.view.ViewGroup
|
||||||
|
import android.widget.EditText
|
||||||
|
import android.widget.LinearLayout
|
||||||
|
import info.nightscout.androidaps.MainApp
|
||||||
|
|
||||||
|
class InputString(mainApp: MainApp) : Element(mainApp) {
|
||||||
|
var textWatcher: TextWatcher = object : TextWatcher {
|
||||||
|
override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int) {}
|
||||||
|
override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) {}
|
||||||
|
override fun afterTextChanged(s: Editable) {
|
||||||
|
value = s.toString()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var value = ""
|
||||||
|
|
||||||
|
constructor(mainApp: MainApp, value: String) : this(mainApp) {
|
||||||
|
this.value = value
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun addToLayout(root: LinearLayout) {
|
||||||
|
val editText = EditText(root.context)
|
||||||
|
editText.setText(value)
|
||||||
|
editText.layoutParams = LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)
|
||||||
|
editText.addTextChangedListener(textWatcher)
|
||||||
|
root.addView(editText)
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,95 +0,0 @@
|
||||||
package info.nightscout.androidaps.plugins.general.automation.elements;
|
|
||||||
|
|
||||||
import android.text.Editable;
|
|
||||||
import android.text.TextWatcher;
|
|
||||||
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;
|
|
||||||
|
|
||||||
private final TextWatcher textWatcher = new TextWatcher() {
|
|
||||||
@Override
|
|
||||||
public void afterTextChanged(Editable s) {
|
|
||||||
value = Math.max(minValue, value);
|
|
||||||
value = Math.min(maxValue, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
@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 InputTempTarget() {
|
|
||||||
super();
|
|
||||||
setUnits(ProfileFunctions.getSystemUnits());
|
|
||||||
if (getUnits().equals(Constants.MMOL))
|
|
||||||
value = 6;
|
|
||||||
else
|
|
||||||
value = 110;
|
|
||||||
}
|
|
||||||
|
|
||||||
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, textWatcher);
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -0,0 +1,44 @@
|
||||||
|
package info.nightscout.androidaps.plugins.general.automation.elements
|
||||||
|
|
||||||
|
import android.widget.LinearLayout
|
||||||
|
import info.nightscout.androidaps.Constants
|
||||||
|
import info.nightscout.androidaps.MainApp
|
||||||
|
import info.nightscout.androidaps.R
|
||||||
|
import info.nightscout.androidaps.utils.NumberPicker
|
||||||
|
import java.text.DecimalFormat
|
||||||
|
|
||||||
|
class InputTempTarget(mainApp: MainApp) : Element(mainApp) {
|
||||||
|
var units = Constants.MGDL
|
||||||
|
var value = 0.0
|
||||||
|
|
||||||
|
init {
|
||||||
|
value = if (units == Constants.MMOL) 6.0 else 110.0
|
||||||
|
}
|
||||||
|
|
||||||
|
constructor(mainApp: MainApp, inputTempTarget: InputTempTarget) : this(mainApp) {
|
||||||
|
value = inputTempTarget.value
|
||||||
|
units = inputTempTarget.units
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun addToLayout(root: LinearLayout) {
|
||||||
|
var minValue = 0.0
|
||||||
|
var maxValue = 0.0
|
||||||
|
var step = 0.0
|
||||||
|
var decimalFormat: DecimalFormat? = null
|
||||||
|
if (units == Constants.MMOL) { // mmol
|
||||||
|
minValue = Constants.MIN_TT_MMOL
|
||||||
|
maxValue = Constants.MAX_TT_MMOL
|
||||||
|
step = 0.1
|
||||||
|
decimalFormat = DecimalFormat("0.0")
|
||||||
|
} else { // mg/dL
|
||||||
|
minValue = Constants.MIN_TT_MGDL
|
||||||
|
maxValue = Constants.MAX_TT_MGDL
|
||||||
|
step = 1.0
|
||||||
|
decimalFormat = DecimalFormat("0")
|
||||||
|
}
|
||||||
|
val numberPicker = NumberPicker(root.context, null)
|
||||||
|
numberPicker.setParams(value, minValue, maxValue, step, decimalFormat, true, root.findViewById(R.id.ok))
|
||||||
|
numberPicker.setOnValueChangedListener { value: Double -> this.value = value }
|
||||||
|
root.addView(numberPicker)
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,64 +0,0 @@
|
||||||
package info.nightscout.androidaps.plugins.general.automation.elements;
|
|
||||||
|
|
||||||
import android.graphics.Typeface;
|
|
||||||
import android.view.ViewGroup;
|
|
||||||
import android.widget.LinearLayout;
|
|
||||||
import android.widget.TableLayout;
|
|
||||||
import android.widget.TextView;
|
|
||||||
|
|
||||||
import info.nightscout.androidaps.MainApp;
|
|
||||||
|
|
||||||
public class LabelWithElement extends Element {
|
|
||||||
final Element element;
|
|
||||||
final String textPre;
|
|
||||||
final String textPost;
|
|
||||||
|
|
||||||
public LabelWithElement(String textPre, String textPost, Element element) {
|
|
||||||
this.element = element;
|
|
||||||
this.textPre = textPre;
|
|
||||||
this.textPost = textPost;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void addToLayout(LinearLayout root) {
|
|
||||||
// container layout
|
|
||||||
LinearLayout layout = new LinearLayout(root.getContext());
|
|
||||||
layout.setOrientation(LinearLayout.HORIZONTAL);
|
|
||||||
layout.setLayoutParams(new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
|
|
||||||
ViewGroup.LayoutParams.WRAP_CONTENT));
|
|
||||||
|
|
||||||
// text view pre element
|
|
||||||
int px = MainApp.dpToPx(10);
|
|
||||||
TextView textViewPre = new TextView(root.getContext());
|
|
||||||
textViewPre.setText(textPre);
|
|
||||||
textViewPre.setLayoutParams(new LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,
|
|
||||||
ViewGroup.LayoutParams.WRAP_CONTENT));
|
|
||||||
//textViewPre.setWidth(MainApp.dpToPx(120));
|
|
||||||
textViewPre.setPadding(px, px, px, px);
|
|
||||||
textViewPre.setTypeface(textViewPre.getTypeface(), Typeface.BOLD);
|
|
||||||
layout.addView(textViewPre);
|
|
||||||
|
|
||||||
TextView spacer = new TextView(root.getContext());
|
|
||||||
spacer.setLayoutParams(new TableLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT, 1f));
|
|
||||||
layout.addView(spacer);
|
|
||||||
|
|
||||||
// add element to layout
|
|
||||||
element.addToLayout(layout);
|
|
||||||
|
|
||||||
// text view post element
|
|
||||||
if (textPost != null) {
|
|
||||||
px = MainApp.dpToPx(5);
|
|
||||||
TextView textViewPost = new TextView(root.getContext());
|
|
||||||
textViewPost.setText(textPost);
|
|
||||||
textViewPost.setLayoutParams(new LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,
|
|
||||||
ViewGroup.LayoutParams.WRAP_CONTENT));
|
|
||||||
//textViewPost.setWidth(MainApp.dpToPx(45));
|
|
||||||
textViewPost.setPadding(px, px, px, px);
|
|
||||||
textViewPost.setTypeface(textViewPost.getTypeface(), Typeface.BOLD);
|
|
||||||
layout.addView(textViewPost);
|
|
||||||
}
|
|
||||||
|
|
||||||
// add layout to root layout
|
|
||||||
root.addView(layout);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -0,0 +1,55 @@
|
||||||
|
package info.nightscout.androidaps.plugins.general.automation.elements
|
||||||
|
|
||||||
|
import android.graphics.Typeface
|
||||||
|
import android.view.ViewGroup
|
||||||
|
import android.widget.LinearLayout
|
||||||
|
import android.widget.TableLayout
|
||||||
|
import android.widget.TextView
|
||||||
|
import info.nightscout.androidaps.MainApp
|
||||||
|
|
||||||
|
class LabelWithElement(mainApp: MainApp) : Element(mainApp) {
|
||||||
|
var element: Element? = null
|
||||||
|
var textPre: String = ""
|
||||||
|
var textPost: String = ""
|
||||||
|
|
||||||
|
constructor(mainApp: MainApp, textPre: String, textPost: String, element: Element) : this(mainApp) {
|
||||||
|
this.textPre = textPre
|
||||||
|
this.textPost = textPost
|
||||||
|
this.element = element
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun addToLayout(root: LinearLayout) { // container layout
|
||||||
|
val layout = LinearLayout(root.context)
|
||||||
|
layout.orientation = LinearLayout.HORIZONTAL
|
||||||
|
layout.layoutParams = LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
|
||||||
|
ViewGroup.LayoutParams.WRAP_CONTENT)
|
||||||
|
// text view pre element
|
||||||
|
var px = resourceHelper.dpToPx(10)
|
||||||
|
val textViewPre = TextView(root.context)
|
||||||
|
textViewPre.text = textPre
|
||||||
|
textViewPre.layoutParams = LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,
|
||||||
|
ViewGroup.LayoutParams.WRAP_CONTENT)
|
||||||
|
//textViewPre.setWidth(MainApp.dpToPx(120));
|
||||||
|
textViewPre.setPadding(px, px, px, px)
|
||||||
|
textViewPre.setTypeface(textViewPre.typeface, Typeface.BOLD)
|
||||||
|
layout.addView(textViewPre)
|
||||||
|
val spacer = TextView(root.context)
|
||||||
|
spacer.layoutParams = TableLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT, 1f)
|
||||||
|
layout.addView(spacer)
|
||||||
|
// add element to layout
|
||||||
|
element?.addToLayout(layout)
|
||||||
|
// text view post element
|
||||||
|
px = resourceHelper.dpToPx(5)
|
||||||
|
val textViewPost = TextView(root.context)
|
||||||
|
textViewPost.text = textPost
|
||||||
|
textViewPost.layoutParams = LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,
|
||||||
|
ViewGroup.LayoutParams.WRAP_CONTENT)
|
||||||
|
//textViewPost.setWidth(MainApp.dpToPx(45));
|
||||||
|
textViewPost.setPadding(px, px, px, px)
|
||||||
|
textViewPost.setTypeface(textViewPost.typeface, Typeface.BOLD)
|
||||||
|
layout.addView(textViewPost)
|
||||||
|
// add layout to root layout
|
||||||
|
root.addView(layout)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -1,26 +0,0 @@
|
||||||
package info.nightscout.androidaps.plugins.general.automation.elements;
|
|
||||||
|
|
||||||
import android.widget.LinearLayout;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
|
|
||||||
public class LayoutBuilder {
|
|
||||||
ArrayList<Element> mElements = new ArrayList<>();
|
|
||||||
|
|
||||||
public LayoutBuilder add(Element element) {
|
|
||||||
mElements.add(element);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public LayoutBuilder add(Element element, boolean condition) {
|
|
||||||
if (condition) mElements.add(element);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void build(LinearLayout layout) {
|
|
||||||
for (Element e : mElements) {
|
|
||||||
e.addToLayout(layout);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -0,0 +1,23 @@
|
||||||
|
package info.nightscout.androidaps.plugins.general.automation.elements
|
||||||
|
|
||||||
|
import android.widget.LinearLayout
|
||||||
|
import java.util.*
|
||||||
|
|
||||||
|
class LayoutBuilder {
|
||||||
|
var mElements = ArrayList<Element>()
|
||||||
|
fun add(element: Element): LayoutBuilder {
|
||||||
|
mElements.add(element)
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
|
||||||
|
fun add(element: Element, condition: Boolean): LayoutBuilder {
|
||||||
|
if (condition) mElements.add(element)
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
|
||||||
|
fun build(layout: LinearLayout) {
|
||||||
|
for (e in mElements) {
|
||||||
|
e.addToLayout(layout)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,36 +0,0 @@
|
||||||
package info.nightscout.androidaps.plugins.general.automation.elements;
|
|
||||||
|
|
||||||
import android.graphics.Typeface;
|
|
||||||
import android.widget.LinearLayout;
|
|
||||||
import android.widget.TextView;
|
|
||||||
|
|
||||||
import info.nightscout.androidaps.MainApp;
|
|
||||||
import info.nightscout.androidaps.R;
|
|
||||||
|
|
||||||
public class StaticLabel extends Element {
|
|
||||||
String label;
|
|
||||||
|
|
||||||
public StaticLabel(String label) {
|
|
||||||
super();
|
|
||||||
this.label = label;
|
|
||||||
}
|
|
||||||
|
|
||||||
public StaticLabel(int resourceId) {
|
|
||||||
super();
|
|
||||||
this.label = MainApp.gs(resourceId);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void addToLayout(LinearLayout root) {
|
|
||||||
// text view pre element
|
|
||||||
int px = MainApp.dpToPx(10);
|
|
||||||
TextView textView = new TextView(root.getContext());
|
|
||||||
textView.setText(label);
|
|
||||||
// textViewPre.setLayoutParams(new LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT));
|
|
||||||
textView.setPadding(px, px, px, px);
|
|
||||||
textView.setTypeface(textView.getTypeface(), Typeface.BOLD);
|
|
||||||
textView.setBackgroundColor(MainApp.gc(R.color.mdtp_line_dark));
|
|
||||||
// add element to layout
|
|
||||||
root.addView(textView);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -0,0 +1,30 @@
|
||||||
|
package info.nightscout.androidaps.plugins.general.automation.elements
|
||||||
|
|
||||||
|
import android.graphics.Typeface
|
||||||
|
import android.widget.LinearLayout
|
||||||
|
import android.widget.TextView
|
||||||
|
import info.nightscout.androidaps.MainApp
|
||||||
|
import info.nightscout.androidaps.R
|
||||||
|
|
||||||
|
class StaticLabel(mainApp: MainApp) : Element(mainApp) {
|
||||||
|
var label = ""
|
||||||
|
|
||||||
|
constructor(mainApp: MainApp, label: String) : this(mainApp) {
|
||||||
|
this.label = label
|
||||||
|
}
|
||||||
|
|
||||||
|
constructor(mainApp: MainApp, resourceId: Int) : this(mainApp) {
|
||||||
|
label = resourceHelper.gs(resourceId)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun addToLayout(root: LinearLayout) { // text view pre element
|
||||||
|
val px = resourceHelper.dpToPx(10)
|
||||||
|
val textView = TextView(root.context)
|
||||||
|
textView.text = label
|
||||||
|
// textViewPre.setLayoutParams(new LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT));
|
||||||
|
textView.setPadding(px, px, px, px)
|
||||||
|
textView.setTypeface(textView.typeface, Typeface.BOLD)
|
||||||
|
textView.setBackgroundColor(resourceHelper.gc(R.color.mdtp_line_dark))
|
||||||
|
root.addView(textView)
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,97 +0,0 @@
|
||||||
package info.nightscout.androidaps.plugins.general.automation.triggers;
|
|
||||||
|
|
||||||
|
|
||||||
import android.content.Context;
|
|
||||||
import android.content.ContextWrapper;
|
|
||||||
import android.widget.LinearLayout;
|
|
||||||
import android.widget.TextView;
|
|
||||||
|
|
||||||
import androidx.appcompat.app.AppCompatActivity;
|
|
||||||
import androidx.fragment.app.FragmentManager;
|
|
||||||
|
|
||||||
import com.google.common.base.Optional;
|
|
||||||
|
|
||||||
import org.json.JSONException;
|
|
||||||
import org.json.JSONObject;
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
import javax.annotation.Nullable;
|
|
||||||
|
|
||||||
public abstract class Trigger {
|
|
||||||
private static final Logger log = LoggerFactory.getLogger(Trigger.class);
|
|
||||||
|
|
||||||
TriggerConnector connector = null;
|
|
||||||
long lastRun;
|
|
||||||
|
|
||||||
Trigger() {
|
|
||||||
}
|
|
||||||
|
|
||||||
public TriggerConnector getConnector() {
|
|
||||||
return connector;
|
|
||||||
}
|
|
||||||
|
|
||||||
public abstract boolean shouldRun();
|
|
||||||
|
|
||||||
|
|
||||||
public abstract String toJSON();
|
|
||||||
|
|
||||||
/*package*/
|
|
||||||
abstract Trigger fromJSON(String data);
|
|
||||||
|
|
||||||
public abstract int friendlyName();
|
|
||||||
|
|
||||||
public abstract String friendlyDescription();
|
|
||||||
|
|
||||||
public abstract Optional<Integer> icon();
|
|
||||||
|
|
||||||
public void executed(long time) {
|
|
||||||
lastRun = time;
|
|
||||||
}
|
|
||||||
|
|
||||||
public long getLastRun() {
|
|
||||||
return lastRun;
|
|
||||||
}
|
|
||||||
|
|
||||||
public abstract Trigger duplicate();
|
|
||||||
|
|
||||||
public static Trigger instantiate(String json) {
|
|
||||||
try {
|
|
||||||
return instantiate(new JSONObject(json));
|
|
||||||
} catch (JSONException e) {
|
|
||||||
log.error("Unhandled exception", e);
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Nullable
|
|
||||||
public static Trigger instantiate(JSONObject object) {
|
|
||||||
try {
|
|
||||||
String type = object.getString("type");
|
|
||||||
JSONObject data = object.getJSONObject("data");
|
|
||||||
Class clazz = Class.forName(type);
|
|
||||||
return ((Trigger) clazz.newInstance()).fromJSON(data.toString());
|
|
||||||
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | JSONException e) {
|
|
||||||
log.error("Unhandled exception", e);
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void generateDialog(LinearLayout root, FragmentManager fragmentManager) {
|
|
||||||
TextView title = new TextView(root.getContext());
|
|
||||||
title.setText(friendlyName());
|
|
||||||
root.addView(title);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Nullable
|
|
||||||
AppCompatActivity scanForActivity(Context cont) {
|
|
||||||
if (cont == null)
|
|
||||||
return null;
|
|
||||||
else if (cont instanceof AppCompatActivity)
|
|
||||||
return (AppCompatActivity) cont;
|
|
||||||
else if (cont instanceof ContextWrapper)
|
|
||||||
return scanForActivity(((ContextWrapper) cont).getBaseContext());
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -0,0 +1,79 @@
|
||||||
|
package info.nightscout.androidaps.plugins.general.automation.triggers
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import android.content.ContextWrapper
|
||||||
|
import android.widget.LinearLayout
|
||||||
|
import android.widget.TextView
|
||||||
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
|
import com.google.common.base.Optional
|
||||||
|
import info.nightscout.androidaps.MainApp
|
||||||
|
import info.nightscout.androidaps.logging.AAPSLogger
|
||||||
|
import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin
|
||||||
|
import info.nightscout.androidaps.plugins.configBuilder.ProfileFunction
|
||||||
|
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.IobCobCalculatorPlugin
|
||||||
|
import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin
|
||||||
|
import info.nightscout.androidaps.services.LocationService
|
||||||
|
import info.nightscout.androidaps.utils.resources.ResourceHelper
|
||||||
|
import info.nightscout.androidaps.utils.sharedPreferences.SP
|
||||||
|
import org.json.JSONException
|
||||||
|
import org.json.JSONObject
|
||||||
|
import javax.inject.Inject
|
||||||
|
import kotlin.reflect.full.primaryConstructor
|
||||||
|
|
||||||
|
abstract class Trigger(val mainApp: MainApp) {
|
||||||
|
@Inject lateinit var aapsLogger: AAPSLogger
|
||||||
|
@Inject lateinit var resourceHelper: ResourceHelper
|
||||||
|
@Inject lateinit var profileFunction: ProfileFunction
|
||||||
|
@Inject lateinit var sp : SP
|
||||||
|
@Inject lateinit var locationService: LocationService
|
||||||
|
@Inject lateinit var treatmentsPlugin: TreatmentsPlugin
|
||||||
|
@Inject lateinit var configBuilderPlugin: ConfigBuilderPlugin
|
||||||
|
@Inject lateinit var iobCobCalculatorPlugin: IobCobCalculatorPlugin
|
||||||
|
|
||||||
|
var connector: TriggerConnector? = null
|
||||||
|
|
||||||
|
init {
|
||||||
|
mainApp.androidInjector().inject(this)
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract fun shouldRun(): Boolean
|
||||||
|
abstract fun toJSON(): String
|
||||||
|
abstract fun fromJSON(data: String): Trigger
|
||||||
|
|
||||||
|
abstract fun friendlyName(): Int
|
||||||
|
abstract fun friendlyDescription(): String
|
||||||
|
abstract fun icon(): Optional<Int?>
|
||||||
|
abstract fun duplicate(): Trigger
|
||||||
|
|
||||||
|
open fun generateDialog(root: LinearLayout) {
|
||||||
|
val title = TextView(root.context)
|
||||||
|
title.setText(friendlyName())
|
||||||
|
root.addView(title)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun scanForActivity(cont: Context?): AppCompatActivity? {
|
||||||
|
if (cont == null) return null
|
||||||
|
else if (cont is AppCompatActivity) return cont
|
||||||
|
else if (cont is ContextWrapper) return scanForActivity(cont.baseContext)
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
fun instantiate(obj: JSONObject): Trigger? {
|
||||||
|
try {
|
||||||
|
val type = obj.getString("type")
|
||||||
|
val data = obj.getJSONObject("data")
|
||||||
|
val clazz = Class.forName(type).kotlin
|
||||||
|
return (clazz.primaryConstructor?.call(mainApp) as Trigger).fromJSON(data?.toString()
|
||||||
|
?: "")
|
||||||
|
} catch (e: ClassNotFoundException) {
|
||||||
|
aapsLogger.error("Unhandled exception", e)
|
||||||
|
} catch (e: InstantiationException) {
|
||||||
|
aapsLogger.error("Unhandled exception", e)
|
||||||
|
} catch (e: IllegalAccessException) {
|
||||||
|
aapsLogger.error("Unhandled exception", e)
|
||||||
|
} catch (e: JSONException) {
|
||||||
|
aapsLogger.error("Unhandled exception", e)
|
||||||
|
}
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,153 +0,0 @@
|
||||||
package info.nightscout.androidaps.plugins.general.automation.triggers;
|
|
||||||
|
|
||||||
|
|
||||||
import android.widget.LinearLayout;
|
|
||||||
|
|
||||||
import androidx.fragment.app.FragmentManager;
|
|
||||||
|
|
||||||
import com.google.common.base.Optional;
|
|
||||||
|
|
||||||
import org.json.JSONException;
|
|
||||||
import org.json.JSONObject;
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
import java.text.DecimalFormat;
|
|
||||||
|
|
||||||
import info.nightscout.androidaps.MainApp;
|
|
||||||
import info.nightscout.androidaps.R;
|
|
||||||
import info.nightscout.androidaps.logging.L;
|
|
||||||
import info.nightscout.androidaps.plugins.general.automation.elements.Comparator;
|
|
||||||
import info.nightscout.androidaps.plugins.general.automation.elements.InputDouble;
|
|
||||||
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.elements.StaticLabel;
|
|
||||||
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.AutosensData;
|
|
||||||
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.IobCobCalculatorPlugin;
|
|
||||||
import info.nightscout.androidaps.utils.DateUtil;
|
|
||||||
import info.nightscout.androidaps.utils.JsonHelper;
|
|
||||||
import info.nightscout.androidaps.utils.SP;
|
|
||||||
import info.nightscout.androidaps.utils.T;
|
|
||||||
|
|
||||||
public class TriggerAutosensValue extends Trigger {
|
|
||||||
private static Logger log = LoggerFactory.getLogger(L.AUTOMATION);
|
|
||||||
private final int minValue = (int) (SP.getDouble("openapsama_autosens_min", 0.7d) * 100);
|
|
||||||
private final int maxValue = (int) (SP.getDouble("openapsama_autosens_max", 1.2d) * 100);
|
|
||||||
private final double step = 1;
|
|
||||||
private DecimalFormat decimalFormat = new DecimalFormat("1");
|
|
||||||
private InputDouble value = new InputDouble(100, (double) minValue, (double) maxValue, step, decimalFormat);
|
|
||||||
private Comparator comparator = new Comparator();
|
|
||||||
|
|
||||||
public TriggerAutosensValue() {
|
|
||||||
super();
|
|
||||||
}
|
|
||||||
|
|
||||||
private TriggerAutosensValue(TriggerAutosensValue triggerAutosensValue) {
|
|
||||||
super();
|
|
||||||
value = new InputDouble(triggerAutosensValue.value);
|
|
||||||
lastRun = triggerAutosensValue.lastRun;
|
|
||||||
comparator = new Comparator(triggerAutosensValue.comparator);
|
|
||||||
}
|
|
||||||
|
|
||||||
public double getValue() {
|
|
||||||
return value.getValue();
|
|
||||||
}
|
|
||||||
|
|
||||||
public Comparator getComparator() {
|
|
||||||
return comparator;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public synchronized boolean shouldRun() {
|
|
||||||
AutosensData autosensData = IobCobCalculatorPlugin.getPlugin().getLastAutosensData("Automation trigger");
|
|
||||||
if (autosensData == null)
|
|
||||||
if (comparator.getValue() == Comparator.Compare.IS_NOT_AVAILABLE)
|
|
||||||
return true;
|
|
||||||
else
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if (lastRun > DateUtil.now() - T.mins(5).msecs())
|
|
||||||
return false;
|
|
||||||
|
|
||||||
boolean doRun = comparator.getValue().check((autosensData.autosensResult.ratio), getValue() / 100d);
|
|
||||||
if (doRun) {
|
|
||||||
if (L.isEnabled(L.AUTOMATION))
|
|
||||||
log.debug("Ready for execution: " + friendlyDescription());
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public synchronized String toJSON() {
|
|
||||||
JSONObject o = new JSONObject();
|
|
||||||
try {
|
|
||||||
o.put("type", TriggerAutosensValue.class.getName());
|
|
||||||
JSONObject data = new JSONObject();
|
|
||||||
data.put("value", getValue());
|
|
||||||
data.put("lastRun", lastRun);
|
|
||||||
data.put("comparator", comparator.getValue().toString());
|
|
||||||
o.put("data", data);
|
|
||||||
} catch (JSONException e) {
|
|
||||||
log.error("Unhandled exception", e);
|
|
||||||
}
|
|
||||||
return o.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
Trigger fromJSON(String data) {
|
|
||||||
try {
|
|
||||||
JSONObject d = new JSONObject(data);
|
|
||||||
value.setValue(JsonHelper.safeGetDouble(d, "value"));
|
|
||||||
lastRun = JsonHelper.safeGetLong(d, "lastRun");
|
|
||||||
comparator.setValue(Comparator.Compare.valueOf(JsonHelper.safeGetString(d, "comparator")));
|
|
||||||
} catch (Exception e) {
|
|
||||||
log.error("Unhandled exception", e);
|
|
||||||
}
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int friendlyName() {
|
|
||||||
return R.string.autosenslabel;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String friendlyDescription() {
|
|
||||||
return MainApp.gs(R.string.autosenscompared, MainApp.gs(comparator.getValue().getStringRes()), getValue());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Optional<Integer> icon() {
|
|
||||||
return Optional.of(R.drawable.as);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Trigger duplicate() {
|
|
||||||
return new TriggerAutosensValue(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
TriggerAutosensValue setValue(int requestedValue) {
|
|
||||||
this.value.setValue(requestedValue);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
TriggerAutosensValue lastRun(long lastRun) {
|
|
||||||
this.lastRun = lastRun;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
TriggerAutosensValue comparator(Comparator.Compare compare) {
|
|
||||||
this.comparator = new Comparator().setValue(compare);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void generateDialog(LinearLayout root, FragmentManager fragmentManager) {
|
|
||||||
new LayoutBuilder()
|
|
||||||
.add(new StaticLabel(R.string.autosenslabel))
|
|
||||||
.add(comparator)
|
|
||||||
.add(new LabelWithElement(MainApp.gs(R.string.autosenslabel) + ": ", "", value))
|
|
||||||
.build(root);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -0,0 +1,82 @@
|
||||||
|
package info.nightscout.androidaps.plugins.general.automation.triggers
|
||||||
|
|
||||||
|
import android.widget.LinearLayout
|
||||||
|
import com.google.common.base.Optional
|
||||||
|
import info.nightscout.androidaps.MainApp
|
||||||
|
import info.nightscout.androidaps.R
|
||||||
|
import info.nightscout.androidaps.logging.LTag
|
||||||
|
import info.nightscout.androidaps.plugins.general.automation.elements.Comparator
|
||||||
|
import info.nightscout.androidaps.plugins.general.automation.elements.InputDouble
|
||||||
|
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.elements.StaticLabel
|
||||||
|
import info.nightscout.androidaps.utils.JsonHelper.safeGetDouble
|
||||||
|
import info.nightscout.androidaps.utils.JsonHelper.safeGetString
|
||||||
|
import org.json.JSONObject
|
||||||
|
import java.text.DecimalFormat
|
||||||
|
|
||||||
|
class TriggerAutosensValue(mainApp: MainApp) : Trigger(mainApp) {
|
||||||
|
private val minValue = (sp.getDouble(R.string.key_openapsama_autosens_min, 0.7) * 100).toInt()
|
||||||
|
private val maxValue = (sp.getDouble(R.string.key_openapsama_autosens_max, 1.2) * 100).toInt()
|
||||||
|
private val step = 1.0
|
||||||
|
private val decimalFormat = DecimalFormat("1")
|
||||||
|
private var autosens: InputDouble = InputDouble(mainApp, 100.0, minValue.toDouble(), maxValue.toDouble(), step, decimalFormat)
|
||||||
|
|
||||||
|
var comparator: Comparator = Comparator(mainApp)
|
||||||
|
|
||||||
|
private constructor(mainApp: MainApp, triggerAutosensValue: TriggerAutosensValue) : this(mainApp) {
|
||||||
|
autosens = InputDouble(mainApp, triggerAutosensValue.autosens)
|
||||||
|
comparator = Comparator(mainApp, triggerAutosensValue.comparator.value)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun shouldRun(): Boolean {
|
||||||
|
val autosensData = iobCobCalculatorPlugin.getLastAutosensData("Automation trigger")
|
||||||
|
?: return if (comparator.value == Comparator.Compare.IS_NOT_AVAILABLE) {
|
||||||
|
aapsLogger.debug(LTag.AUTOMATION, "Ready for execution: " + friendlyDescription())
|
||||||
|
true
|
||||||
|
} else {
|
||||||
|
aapsLogger.debug(LTag.AUTOMATION, "NOT ready for execution: " + friendlyDescription())
|
||||||
|
false
|
||||||
|
}
|
||||||
|
if (comparator.value.check(autosensData.autosensResult.ratio, autosens.value / 100.0)) {
|
||||||
|
aapsLogger.debug(LTag.AUTOMATION, "Ready for execution: " + friendlyDescription())
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
aapsLogger.debug(LTag.AUTOMATION, "NOT ready for execution: " + friendlyDescription())
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun toJSON(): String {
|
||||||
|
val data = JSONObject()
|
||||||
|
.put("value", autosens.value)
|
||||||
|
.put("comparator", comparator.value.toString())
|
||||||
|
return JSONObject()
|
||||||
|
.put("type", this::class.java.name)
|
||||||
|
.put("data", data)
|
||||||
|
.toString()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun fromJSON(data: String): Trigger {
|
||||||
|
val d = JSONObject(data)
|
||||||
|
autosens.setValue(safeGetDouble(d, "value"))
|
||||||
|
comparator.setValue(Comparator.Compare.valueOf(safeGetString(d, "comparator")!!))
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun friendlyName(): Int = R.string.autosenslabel
|
||||||
|
|
||||||
|
override fun friendlyDescription(): String =
|
||||||
|
resourceHelper.gs(R.string.autosenscompared, resourceHelper.gs(comparator.value.stringRes), autosens.value)
|
||||||
|
|
||||||
|
override fun icon(): Optional<Int?> = Optional.of(R.drawable.`as`)
|
||||||
|
|
||||||
|
override fun duplicate(): Trigger = TriggerAutosensValue(mainApp, this)
|
||||||
|
|
||||||
|
override fun generateDialog(root: LinearLayout) {
|
||||||
|
LayoutBuilder()
|
||||||
|
.add(StaticLabel(mainApp, R.string.autosenslabel))
|
||||||
|
.add(comparator)
|
||||||
|
.add(LabelWithElement(mainApp, resourceHelper.gs(R.string.autosenslabel) + ": ", "", autosens))
|
||||||
|
.build(root)
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,178 +0,0 @@
|
||||||
package info.nightscout.androidaps.plugins.general.automation.triggers;
|
|
||||||
|
|
||||||
import android.widget.LinearLayout;
|
|
||||||
|
|
||||||
import androidx.fragment.app.FragmentManager;
|
|
||||||
|
|
||||||
import com.google.common.base.Optional;
|
|
||||||
|
|
||||||
import org.json.JSONException;
|
|
||||||
import org.json.JSONObject;
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
import info.nightscout.androidaps.Constants;
|
|
||||||
import info.nightscout.androidaps.MainApp;
|
|
||||||
import info.nightscout.androidaps.R;
|
|
||||||
import info.nightscout.androidaps.data.Profile;
|
|
||||||
import info.nightscout.androidaps.logging.L;
|
|
||||||
import info.nightscout.androidaps.plugins.general.automation.elements.Comparator;
|
|
||||||
import info.nightscout.androidaps.plugins.general.automation.elements.InputBg;
|
|
||||||
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.elements.StaticLabel;
|
|
||||||
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.GlucoseStatus;
|
|
||||||
import info.nightscout.androidaps.utils.DateUtil;
|
|
||||||
import info.nightscout.androidaps.utils.JsonHelper;
|
|
||||||
import info.nightscout.androidaps.utils.T;
|
|
||||||
|
|
||||||
public class TriggerBg extends Trigger {
|
|
||||||
private static Logger log = LoggerFactory.getLogger(L.AUTOMATION);
|
|
||||||
|
|
||||||
private InputBg bg = new InputBg();
|
|
||||||
private Comparator comparator = new Comparator();
|
|
||||||
|
|
||||||
public TriggerBg() {
|
|
||||||
super();
|
|
||||||
}
|
|
||||||
|
|
||||||
private TriggerBg(TriggerBg triggerBg) {
|
|
||||||
super();
|
|
||||||
bg = new InputBg(triggerBg.bg);
|
|
||||||
comparator = new Comparator(triggerBg.comparator);
|
|
||||||
lastRun = triggerBg.lastRun;
|
|
||||||
}
|
|
||||||
|
|
||||||
public double getValue() {
|
|
||||||
return bg.getValue();
|
|
||||||
}
|
|
||||||
|
|
||||||
public Comparator getComparator() {
|
|
||||||
return comparator;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getUnits() {
|
|
||||||
return bg.getUnits();
|
|
||||||
}
|
|
||||||
|
|
||||||
public long getLastRun() {
|
|
||||||
return lastRun;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public synchronized boolean shouldRun() {
|
|
||||||
GlucoseStatus glucoseStatus = GlucoseStatus.getGlucoseStatusData();
|
|
||||||
|
|
||||||
if (lastRun > DateUtil.now() - T.mins(5).msecs()) {
|
|
||||||
if (L.isEnabled(L.AUTOMATION))
|
|
||||||
log.debug("NOT ready for execution: " + friendlyDescription());
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (glucoseStatus == null && comparator.getValue().equals(Comparator.Compare.IS_NOT_AVAILABLE)) {
|
|
||||||
if (L.isEnabled(L.AUTOMATION))
|
|
||||||
log.debug("Ready for execution: " + friendlyDescription());
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (glucoseStatus == null) {
|
|
||||||
if (L.isEnabled(L.AUTOMATION))
|
|
||||||
log.debug("NOT ready for execution: " + friendlyDescription());
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
boolean doRun = comparator.getValue().check(glucoseStatus.glucose, Profile.toMgdl(bg.getValue(), bg.getUnits()));
|
|
||||||
if (doRun) {
|
|
||||||
if (L.isEnabled(L.AUTOMATION))
|
|
||||||
log.debug("Ready for execution: " + friendlyDescription());
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (L.isEnabled(L.AUTOMATION))
|
|
||||||
log.debug("NOT ready for execution: " + friendlyDescription());
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public synchronized String toJSON() {
|
|
||||||
JSONObject o = new JSONObject();
|
|
||||||
try {
|
|
||||||
o.put("type", TriggerBg.class.getName());
|
|
||||||
JSONObject data = new JSONObject();
|
|
||||||
data.put("bg", bg.getValue());
|
|
||||||
data.put("lastRun", lastRun);
|
|
||||||
data.put("comparator", comparator.getValue().toString());
|
|
||||||
data.put("units", bg.getUnits());
|
|
||||||
o.put("data", data);
|
|
||||||
} catch (JSONException e) {
|
|
||||||
log.error("Unhandled exception", e);
|
|
||||||
}
|
|
||||||
return o.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
Trigger fromJSON(String data) {
|
|
||||||
try {
|
|
||||||
JSONObject d = new JSONObject(data);
|
|
||||||
bg.setUnits(JsonHelper.safeGetString(d, "units"));
|
|
||||||
bg.setValue(JsonHelper.safeGetDouble(d, "bg"));
|
|
||||||
lastRun = JsonHelper.safeGetLong(d, "lastRun");
|
|
||||||
comparator.setValue(Comparator.Compare.valueOf(JsonHelper.safeGetString(d, "comparator")));
|
|
||||||
} catch (Exception e) {
|
|
||||||
log.error("Unhandled exception", e);
|
|
||||||
}
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int friendlyName() {
|
|
||||||
return R.string.glucose;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String friendlyDescription() {
|
|
||||||
if (comparator.getValue().equals(Comparator.Compare.IS_NOT_AVAILABLE))
|
|
||||||
return MainApp.gs(R.string.glucoseisnotavailable);
|
|
||||||
else {
|
|
||||||
return MainApp.gs(bg.getUnits().equals(Constants.MGDL) ? R.string.glucosecomparedmgdl : R.string.glucosecomparedmmol, MainApp.gs(comparator.getValue().getStringRes()), bg.getValue(), bg.getUnits());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Optional<Integer> icon() {
|
|
||||||
return Optional.of(R.drawable.icon_cp_bgcheck);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Trigger duplicate() {
|
|
||||||
return new TriggerBg(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
TriggerBg setValue(double value) {
|
|
||||||
bg.setValue(value);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
TriggerBg lastRun(long lastRun) {
|
|
||||||
this.lastRun = lastRun;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
TriggerBg comparator(Comparator.Compare compare) {
|
|
||||||
this.comparator = new Comparator().setValue(compare);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
TriggerBg setUnits(String units) {
|
|
||||||
bg.setUnits(units);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void generateDialog(LinearLayout root, FragmentManager fragmentManager) {
|
|
||||||
new LayoutBuilder()
|
|
||||||
.add(new StaticLabel(R.string.glucose))
|
|
||||||
.add(comparator)
|
|
||||||
.add(new LabelWithElement(MainApp.gs(R.string.glucose_u, bg.getUnits()), "", bg))
|
|
||||||
.build(root);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -0,0 +1,90 @@
|
||||||
|
package info.nightscout.androidaps.plugins.general.automation.triggers
|
||||||
|
|
||||||
|
import android.widget.LinearLayout
|
||||||
|
import com.google.common.base.Optional
|
||||||
|
import info.nightscout.androidaps.Constants
|
||||||
|
import info.nightscout.androidaps.MainApp
|
||||||
|
import info.nightscout.androidaps.R
|
||||||
|
import info.nightscout.androidaps.data.Profile
|
||||||
|
import info.nightscout.androidaps.logging.LTag
|
||||||
|
import info.nightscout.androidaps.plugins.general.automation.elements.Comparator
|
||||||
|
import info.nightscout.androidaps.plugins.general.automation.elements.InputBg
|
||||||
|
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.elements.StaticLabel
|
||||||
|
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.GlucoseStatus
|
||||||
|
import info.nightscout.androidaps.utils.JsonHelper
|
||||||
|
import org.json.JSONObject
|
||||||
|
|
||||||
|
class TriggerBg(mainApp: MainApp) : Trigger(mainApp) {
|
||||||
|
private var bg = InputBg(mainApp)
|
||||||
|
var comparator = Comparator(mainApp)
|
||||||
|
|
||||||
|
constructor(mainApp: MainApp, value : Double, units : String, compare: Comparator.Compare) : this(mainApp){
|
||||||
|
bg = InputBg(mainApp, value, units)
|
||||||
|
comparator = Comparator(mainApp, compare)
|
||||||
|
}
|
||||||
|
|
||||||
|
constructor(mainApp: MainApp, triggerBg: TriggerBg) : this(mainApp){
|
||||||
|
bg = InputBg(mainApp, triggerBg.bg.value, triggerBg.bg.units)
|
||||||
|
comparator = Comparator(mainApp, triggerBg.comparator.value)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun shouldRun(): Boolean {
|
||||||
|
val glucoseStatus = GlucoseStatus.getGlucoseStatusData()
|
||||||
|
if (glucoseStatus == null && comparator.value == Comparator.Compare.IS_NOT_AVAILABLE) {
|
||||||
|
aapsLogger.debug(LTag.AUTOMATION, "Ready for execution: " + friendlyDescription())
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
if (glucoseStatus == null) {
|
||||||
|
aapsLogger.debug(LTag.AUTOMATION, "NOT ready for execution: " + friendlyDescription())
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if (comparator.value.check(glucoseStatus.glucose, Profile.toMgdl(bg.value, bg.units))) {
|
||||||
|
aapsLogger.debug(LTag.AUTOMATION, "Ready for execution: " + friendlyDescription())
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
aapsLogger.debug(LTag.AUTOMATION, "NOT ready for execution: " + friendlyDescription())
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun toJSON(): String {
|
||||||
|
val data = JSONObject()
|
||||||
|
.put("bg", bg.value)
|
||||||
|
.put("comparator", comparator.value.toString())
|
||||||
|
.put("units", bg.units)
|
||||||
|
return JSONObject()
|
||||||
|
.put("type", this::class.java.name)
|
||||||
|
.put("data", data)
|
||||||
|
.toString()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun fromJSON(data: String): Trigger {
|
||||||
|
val d = JSONObject(data)
|
||||||
|
bg.setUnits(JsonHelper.safeGetString(d, "units")!!)
|
||||||
|
bg.value = JsonHelper.safeGetDouble(d, "bg")
|
||||||
|
comparator.setValue(Comparator.Compare.valueOf(JsonHelper.safeGetString(d, "comparator")!!))
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun friendlyName(): Int = R.string.glucose
|
||||||
|
|
||||||
|
override fun friendlyDescription(): String {
|
||||||
|
return if (comparator.value == Comparator.Compare.IS_NOT_AVAILABLE)
|
||||||
|
resourceHelper.gs(R.string.glucoseisnotavailable)
|
||||||
|
else
|
||||||
|
resourceHelper.gs(if (bg.units == Constants.MGDL) R.string.glucosecomparedmgdl else R.string.glucosecomparedmmol, resourceHelper.gs(comparator.value.stringRes), bg.value, bg.units)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun icon(): Optional<Int?> = Optional.of(R.drawable.icon_cp_bgcheck)
|
||||||
|
|
||||||
|
override fun duplicate(): Trigger = TriggerBg(mainApp, this)
|
||||||
|
|
||||||
|
override fun generateDialog(root: LinearLayout) {
|
||||||
|
LayoutBuilder()
|
||||||
|
.add(StaticLabel(mainApp, R.string.glucose))
|
||||||
|
.add(comparator)
|
||||||
|
.add(LabelWithElement(mainApp, resourceHelper.gs(R.string.glucose_u, bg.units), "", bg))
|
||||||
|
.build(root)
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,150 +0,0 @@
|
||||||
package info.nightscout.androidaps.plugins.general.automation.triggers;
|
|
||||||
|
|
||||||
import android.widget.LinearLayout;
|
|
||||||
|
|
||||||
import androidx.fragment.app.FragmentManager;
|
|
||||||
|
|
||||||
import com.google.common.base.Optional;
|
|
||||||
|
|
||||||
import org.json.JSONException;
|
|
||||||
import org.json.JSONObject;
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
import info.nightscout.androidaps.MainApp;
|
|
||||||
import info.nightscout.androidaps.R;
|
|
||||||
import info.nightscout.androidaps.logging.L;
|
|
||||||
import info.nightscout.androidaps.plugins.general.automation.elements.Comparator;
|
|
||||||
import info.nightscout.androidaps.plugins.general.automation.elements.InputDuration;
|
|
||||||
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.elements.StaticLabel;
|
|
||||||
import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin;
|
|
||||||
import info.nightscout.androidaps.utils.DateUtil;
|
|
||||||
import info.nightscout.androidaps.utils.JsonHelper;
|
|
||||||
import info.nightscout.androidaps.utils.T;
|
|
||||||
|
|
||||||
public class TriggerBolusAgo extends Trigger {
|
|
||||||
private static Logger log = LoggerFactory.getLogger(L.AUTOMATION);
|
|
||||||
private InputDuration minutesAgo = new InputDuration(0, InputDuration.TimeUnit.MINUTES);
|
|
||||||
private Comparator comparator = new Comparator();
|
|
||||||
|
|
||||||
public TriggerBolusAgo() {
|
|
||||||
super();
|
|
||||||
}
|
|
||||||
|
|
||||||
private TriggerBolusAgo(TriggerBolusAgo triggerBolusAgo) {
|
|
||||||
super();
|
|
||||||
minutesAgo = new InputDuration(triggerBolusAgo.minutesAgo);
|
|
||||||
lastRun = triggerBolusAgo.lastRun;
|
|
||||||
comparator = new Comparator(triggerBolusAgo.comparator);
|
|
||||||
}
|
|
||||||
|
|
||||||
public double getValue() {
|
|
||||||
return minutesAgo.getValue();
|
|
||||||
}
|
|
||||||
|
|
||||||
public Comparator getComparator() {
|
|
||||||
return comparator;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public synchronized boolean shouldRun() {
|
|
||||||
|
|
||||||
if (lastRun > DateUtil.now() - T.mins(5).msecs())
|
|
||||||
return false;
|
|
||||||
|
|
||||||
long lastBolusTime = TreatmentsPlugin.getPlugin().getLastBolusTime(false);
|
|
||||||
|
|
||||||
if (lastBolusTime == 0)
|
|
||||||
if (comparator.getValue() == Comparator.Compare.IS_NOT_AVAILABLE)
|
|
||||||
return true;
|
|
||||||
else
|
|
||||||
return false;
|
|
||||||
|
|
||||||
double minutesAgo = (double) (DateUtil.now() - lastBolusTime) / (60 * 1000);
|
|
||||||
if (L.isEnabled(L.AUTOMATION))
|
|
||||||
log.debug("LastBolus min ago: " + minutesAgo);
|
|
||||||
|
|
||||||
boolean doRun = comparator.getValue().check((minutesAgo), getValue());
|
|
||||||
if (doRun) {
|
|
||||||
if (L.isEnabled(L.AUTOMATION))
|
|
||||||
log.debug("Ready for execution: " + friendlyDescription());
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public synchronized String toJSON() {
|
|
||||||
JSONObject o = new JSONObject();
|
|
||||||
try {
|
|
||||||
o.put("type", TriggerBolusAgo.class.getName());
|
|
||||||
JSONObject data = new JSONObject();
|
|
||||||
data.put("minutesAgo", getValue());
|
|
||||||
data.put("lastRun", lastRun);
|
|
||||||
data.put("comparator", comparator.getValue().toString());
|
|
||||||
o.put("data", data);
|
|
||||||
} catch (JSONException e) {
|
|
||||||
log.error("Unhandled exception", e);
|
|
||||||
}
|
|
||||||
return o.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
Trigger fromJSON(String data) {
|
|
||||||
try {
|
|
||||||
JSONObject d = new JSONObject(data);
|
|
||||||
minutesAgo.setMinutes(JsonHelper.safeGetInt(d, "minutesAgo"));
|
|
||||||
lastRun = JsonHelper.safeGetLong(d, "lastRun");
|
|
||||||
comparator.setValue(Comparator.Compare.valueOf(JsonHelper.safeGetString(d, "comparator")));
|
|
||||||
} catch (Exception e) {
|
|
||||||
log.error("Unhandled exception", e);
|
|
||||||
}
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int friendlyName() {
|
|
||||||
return R.string.lastboluslabel;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String friendlyDescription() {
|
|
||||||
return MainApp.gs(R.string.lastboluscompared, MainApp.gs(comparator.getValue().getStringRes()), (int) getValue());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Optional<Integer> icon() {
|
|
||||||
return Optional.of(R.drawable.icon_bolus);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Trigger duplicate() {
|
|
||||||
return new TriggerBolusAgo(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
TriggerBolusAgo setValue(int requestedValue) {
|
|
||||||
this.minutesAgo.setMinutes(requestedValue);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
TriggerBolusAgo lastRun(long lastRun) {
|
|
||||||
this.lastRun = lastRun;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
TriggerBolusAgo comparator(Comparator.Compare compare) {
|
|
||||||
this.comparator = new Comparator().setValue(compare);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void generateDialog(LinearLayout root, FragmentManager fragmentManager) {
|
|
||||||
new LayoutBuilder()
|
|
||||||
.add(new StaticLabel(R.string.lastboluslabel))
|
|
||||||
.add(comparator)
|
|
||||||
.add(new LabelWithElement(MainApp.gs(R.string.lastboluslabel) + ": ", "", minutesAgo))
|
|
||||||
.build(root);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -0,0 +1,81 @@
|
||||||
|
package info.nightscout.androidaps.plugins.general.automation.triggers
|
||||||
|
|
||||||
|
import android.widget.LinearLayout
|
||||||
|
import com.google.common.base.Optional
|
||||||
|
import info.nightscout.androidaps.MainApp
|
||||||
|
import info.nightscout.androidaps.R
|
||||||
|
import info.nightscout.androidaps.logging.LTag
|
||||||
|
import info.nightscout.androidaps.plugins.general.automation.elements.Comparator
|
||||||
|
import info.nightscout.androidaps.plugins.general.automation.elements.InputDuration
|
||||||
|
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.elements.StaticLabel
|
||||||
|
import info.nightscout.androidaps.utils.DateUtil
|
||||||
|
import info.nightscout.androidaps.utils.JsonHelper
|
||||||
|
import info.nightscout.androidaps.utils.JsonHelper.safeGetString
|
||||||
|
import org.json.JSONObject
|
||||||
|
|
||||||
|
class TriggerBolusAgo(mainApp: MainApp) : Trigger(mainApp) {
|
||||||
|
private var minutesAgo: InputDuration = InputDuration(mainApp, 0, InputDuration.TimeUnit.MINUTES)
|
||||||
|
var comparator: Comparator = Comparator(mainApp)
|
||||||
|
|
||||||
|
private constructor(mainApp: MainApp, triggerBolusAgo: TriggerBolusAgo) : this(mainApp) {
|
||||||
|
minutesAgo = InputDuration(mainApp, triggerBolusAgo.minutesAgo.value, InputDuration.TimeUnit.MINUTES)
|
||||||
|
comparator = Comparator(mainApp, triggerBolusAgo.comparator.value)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun shouldRun(): Boolean {
|
||||||
|
val lastBolusTime = treatmentsPlugin.getLastBolusTime(false)
|
||||||
|
if (lastBolusTime == 0L)
|
||||||
|
return if (comparator.value == Comparator.Compare.IS_NOT_AVAILABLE) {
|
||||||
|
aapsLogger.debug(LTag.AUTOMATION, "Ready for execution: " + friendlyDescription())
|
||||||
|
true
|
||||||
|
} else {
|
||||||
|
aapsLogger.debug(LTag.AUTOMATION, "NOT ready for execution: " + friendlyDescription())
|
||||||
|
false
|
||||||
|
}
|
||||||
|
val last = (DateUtil.now() - lastBolusTime).toDouble() / (60 * 1000)
|
||||||
|
aapsLogger.debug(LTag.AUTOMATION, "LastBolus min ago: $minutesAgo")
|
||||||
|
val doRun = comparator.value.check(last.toInt(), minutesAgo.getMinutes())
|
||||||
|
if (doRun) {
|
||||||
|
aapsLogger.debug(LTag.AUTOMATION, "Ready for execution: " + friendlyDescription())
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
aapsLogger.debug(LTag.AUTOMATION, "NOT ready for execution: " + friendlyDescription())
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun toJSON(): String {
|
||||||
|
val data = JSONObject()
|
||||||
|
.put("minutesAgo", minutesAgo.value)
|
||||||
|
.put("comparator", comparator.value.toString())
|
||||||
|
return JSONObject()
|
||||||
|
.put("type", this::class.java.name)
|
||||||
|
.put("data", data)
|
||||||
|
.toString()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun fromJSON(data: String): Trigger {
|
||||||
|
val d = JSONObject(data)
|
||||||
|
minutesAgo.setMinutes(JsonHelper.safeGetInt(d, "minutesAgo"))
|
||||||
|
comparator.setValue(Comparator.Compare.valueOf(safeGetString(d, "comparator")!!))
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun friendlyName(): Int = R.string.lastboluslabel
|
||||||
|
|
||||||
|
override fun friendlyDescription(): String =
|
||||||
|
resourceHelper.gs(R.string.lastboluscompared, resourceHelper.gs(comparator.value.stringRes), minutesAgo.getMinutes())
|
||||||
|
|
||||||
|
override fun icon(): Optional<Int?> = Optional.of(R.drawable.icon_bolus)
|
||||||
|
|
||||||
|
override fun duplicate(): Trigger = TriggerBolusAgo(mainApp, this)
|
||||||
|
|
||||||
|
override fun generateDialog(root: LinearLayout) {
|
||||||
|
LayoutBuilder()
|
||||||
|
.add(StaticLabel(mainApp, R.string.lastboluslabel))
|
||||||
|
.add(comparator)
|
||||||
|
.add(LabelWithElement(mainApp, resourceHelper.gs(R.string.lastboluslabel) + ": ", "", minutesAgo))
|
||||||
|
.build(root)
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,151 +0,0 @@
|
||||||
package info.nightscout.androidaps.plugins.general.automation.triggers;
|
|
||||||
|
|
||||||
|
|
||||||
import android.widget.LinearLayout;
|
|
||||||
|
|
||||||
import androidx.fragment.app.FragmentManager;
|
|
||||||
|
|
||||||
import com.google.common.base.Optional;
|
|
||||||
|
|
||||||
import org.json.JSONException;
|
|
||||||
import org.json.JSONObject;
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
import java.text.DecimalFormat;
|
|
||||||
|
|
||||||
import info.nightscout.androidaps.MainApp;
|
|
||||||
import info.nightscout.androidaps.R;
|
|
||||||
import info.nightscout.androidaps.logging.L;
|
|
||||||
import info.nightscout.androidaps.plugins.general.automation.elements.Comparator;
|
|
||||||
import info.nightscout.androidaps.plugins.general.automation.elements.InputDouble;
|
|
||||||
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.elements.StaticLabel;
|
|
||||||
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.CobInfo;
|
|
||||||
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.IobCobCalculatorPlugin;
|
|
||||||
import info.nightscout.androidaps.utils.DateUtil;
|
|
||||||
import info.nightscout.androidaps.utils.JsonHelper;
|
|
||||||
import info.nightscout.androidaps.utils.SP;
|
|
||||||
import info.nightscout.androidaps.utils.T;
|
|
||||||
|
|
||||||
public class TriggerCOB extends Trigger {
|
|
||||||
private static Logger log = LoggerFactory.getLogger(L.AUTOMATION);
|
|
||||||
private final int minValue = 0;
|
|
||||||
private final int maxValue = SP.getInt(R.string.key_treatmentssafety_maxcarbs, 48);
|
|
||||||
private InputDouble value = new InputDouble(0, (double) minValue, (double) maxValue, 1, new DecimalFormat("1"));
|
|
||||||
private Comparator comparator = new Comparator();
|
|
||||||
|
|
||||||
public TriggerCOB() {
|
|
||||||
super();
|
|
||||||
}
|
|
||||||
|
|
||||||
private TriggerCOB(TriggerCOB triggerCOB) {
|
|
||||||
super();
|
|
||||||
value = new InputDouble(triggerCOB.value);
|
|
||||||
lastRun = triggerCOB.lastRun;
|
|
||||||
comparator = new Comparator(triggerCOB.comparator);
|
|
||||||
}
|
|
||||||
|
|
||||||
public double getValue() {
|
|
||||||
return value.getValue();
|
|
||||||
}
|
|
||||||
|
|
||||||
public Comparator getComparator() {
|
|
||||||
return comparator;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public synchronized boolean shouldRun() {
|
|
||||||
CobInfo cobInfo = IobCobCalculatorPlugin.getPlugin().getCobInfo(false, "AutomationTriggerCOB");
|
|
||||||
if (cobInfo == null)
|
|
||||||
if (comparator.getValue() == Comparator.Compare.IS_NOT_AVAILABLE)
|
|
||||||
return true;
|
|
||||||
else
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if (lastRun > DateUtil.now() - T.mins(5).msecs())
|
|
||||||
return false;
|
|
||||||
|
|
||||||
boolean doRun = comparator.getValue().check((cobInfo.displayCob), getValue());
|
|
||||||
if (doRun) {
|
|
||||||
if (L.isEnabled(L.AUTOMATION))
|
|
||||||
log.debug("Ready for execution: " + friendlyDescription());
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public synchronized String toJSON() {
|
|
||||||
JSONObject o = new JSONObject();
|
|
||||||
try {
|
|
||||||
o.put("type", TriggerCOB.class.getName());
|
|
||||||
JSONObject data = new JSONObject();
|
|
||||||
data.put("carbs", getValue());
|
|
||||||
data.put("lastRun", lastRun);
|
|
||||||
data.put("comparator", comparator.getValue().toString());
|
|
||||||
o.put("data", data);
|
|
||||||
} catch (JSONException e) {
|
|
||||||
log.error("Unhandled exception", e);
|
|
||||||
}
|
|
||||||
return o.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
Trigger fromJSON(String data) {
|
|
||||||
try {
|
|
||||||
JSONObject d = new JSONObject(data);
|
|
||||||
value.setValue(JsonHelper.safeGetDouble(d, "carbs"));
|
|
||||||
lastRun = JsonHelper.safeGetLong(d, "lastRun");
|
|
||||||
comparator.setValue(Comparator.Compare.valueOf(JsonHelper.safeGetString(d, "comparator")));
|
|
||||||
} catch (Exception e) {
|
|
||||||
log.error("Unhandled exception", e);
|
|
||||||
}
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int friendlyName() {
|
|
||||||
return R.string.triggercoblabel;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String friendlyDescription() {
|
|
||||||
return MainApp.gs(R.string.cobcompared, MainApp.gs(comparator.getValue().getStringRes()), getValue());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Optional<Integer> icon() {
|
|
||||||
return Optional.of(R.drawable.icon_cp_bolus_carbs);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Trigger duplicate() {
|
|
||||||
return new TriggerCOB(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
TriggerCOB setValue(int requestedValue) {
|
|
||||||
this.value.setValue(requestedValue);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
TriggerCOB lastRun(long lastRun) {
|
|
||||||
this.lastRun = lastRun;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
TriggerCOB comparator(Comparator.Compare compare) {
|
|
||||||
this.comparator = new Comparator().setValue(compare);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void generateDialog(LinearLayout root, FragmentManager fragmentManager) {
|
|
||||||
new LayoutBuilder()
|
|
||||||
.add(new StaticLabel(R.string.triggercoblabel))
|
|
||||||
.add(comparator)
|
|
||||||
.add(new LabelWithElement(MainApp.gs(R.string.triggercoblabel) + ": ", "", value))
|
|
||||||
.build(root);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -0,0 +1,81 @@
|
||||||
|
package info.nightscout.androidaps.plugins.general.automation.triggers
|
||||||
|
|
||||||
|
import android.widget.LinearLayout
|
||||||
|
import com.google.common.base.Optional
|
||||||
|
import info.nightscout.androidaps.MainApp
|
||||||
|
import info.nightscout.androidaps.R
|
||||||
|
import info.nightscout.androidaps.logging.LTag
|
||||||
|
import info.nightscout.androidaps.plugins.general.automation.elements.Comparator
|
||||||
|
import info.nightscout.androidaps.plugins.general.automation.elements.InputDouble
|
||||||
|
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.elements.StaticLabel
|
||||||
|
import info.nightscout.androidaps.utils.JsonHelper
|
||||||
|
import info.nightscout.androidaps.utils.JsonHelper.safeGetDouble
|
||||||
|
import org.json.JSONObject
|
||||||
|
import java.text.DecimalFormat
|
||||||
|
|
||||||
|
class TriggerCOB(mainApp: MainApp) : Trigger(mainApp) {
|
||||||
|
private val minValue = 0
|
||||||
|
private val maxValue = sp.getInt(R.string.key_treatmentssafety_maxcarbs, 48)
|
||||||
|
private var cob: InputDouble = InputDouble(mainApp, 0.0, minValue.toDouble(), maxValue.toDouble(), 1.0, DecimalFormat("1"))
|
||||||
|
var comparator: Comparator = Comparator(mainApp)
|
||||||
|
|
||||||
|
private constructor(mainApp: MainApp, triggerCOB: TriggerCOB) : this(mainApp) {
|
||||||
|
cob = InputDouble(mainApp, triggerCOB.cob)
|
||||||
|
comparator = Comparator(mainApp, triggerCOB.comparator.value)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun shouldRun(): Boolean {
|
||||||
|
val cobInfo = iobCobCalculatorPlugin.getCobInfo(false, "AutomationTriggerCOB")
|
||||||
|
if (cobInfo.displayCob == null) {
|
||||||
|
return if (comparator.value === Comparator.Compare.IS_NOT_AVAILABLE) {
|
||||||
|
aapsLogger.debug(LTag.AUTOMATION, "Ready for execution: " + friendlyDescription())
|
||||||
|
true
|
||||||
|
} else {
|
||||||
|
aapsLogger.debug(LTag.AUTOMATION, "NOT ready for execution: " + friendlyDescription())
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (comparator.value.check(cobInfo.displayCob, cob.value)) {
|
||||||
|
aapsLogger.debug(LTag.AUTOMATION, "Ready for execution: " + friendlyDescription())
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
aapsLogger.debug(LTag.AUTOMATION, "NOT ready for execution: " + friendlyDescription())
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
@Synchronized override fun toJSON(): String {
|
||||||
|
val data = JSONObject()
|
||||||
|
.put("carbs", cob.value)
|
||||||
|
.put("comparator", comparator.value.toString())
|
||||||
|
return JSONObject()
|
||||||
|
.put("type", this::class.java.name)
|
||||||
|
.put("data", data)
|
||||||
|
.toString()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun fromJSON(data: String): Trigger {
|
||||||
|
val d = JSONObject(data)
|
||||||
|
cob.setValue(safeGetDouble(d, "carbs"))
|
||||||
|
comparator.setValue(Comparator.Compare.valueOf(JsonHelper.safeGetString(d, "comparator")!!))
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun friendlyName(): Int = R.string.triggercoblabel
|
||||||
|
|
||||||
|
override fun friendlyDescription(): String =
|
||||||
|
resourceHelper.gs(R.string.cobcompared, resourceHelper.gs(comparator.value.stringRes), cob.value)
|
||||||
|
|
||||||
|
override fun icon(): Optional<Int?> = Optional.of(R.drawable.icon_cp_bolus_carbs)
|
||||||
|
|
||||||
|
override fun duplicate(): Trigger = TriggerCOB(mainApp, this)
|
||||||
|
|
||||||
|
override fun generateDialog(root: LinearLayout) {
|
||||||
|
LayoutBuilder()
|
||||||
|
.add(StaticLabel(mainApp, R.string.triggercoblabel))
|
||||||
|
.add(comparator)
|
||||||
|
.add(LabelWithElement(mainApp, resourceHelper.gs(R.string.triggercoblabel) + ": ", "", cob))
|
||||||
|
.build(root)
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,277 +0,0 @@
|
||||||
package info.nightscout.androidaps.plugins.general.automation.triggers;
|
|
||||||
|
|
||||||
|
|
||||||
import android.view.ViewGroup;
|
|
||||||
import android.widget.LinearLayout;
|
|
||||||
|
|
||||||
import androidx.annotation.StringRes;
|
|
||||||
import androidx.fragment.app.FragmentManager;
|
|
||||||
|
|
||||||
import com.google.common.base.Optional;
|
|
||||||
|
|
||||||
import org.json.JSONArray;
|
|
||||||
import org.json.JSONException;
|
|
||||||
import org.json.JSONObject;
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import info.nightscout.androidaps.MainApp;
|
|
||||||
import info.nightscout.androidaps.R;
|
|
||||||
import info.nightscout.androidaps.logging.L;
|
|
||||||
import info.nightscout.androidaps.plugins.general.automation.dialogs.TriggerListAdapter;
|
|
||||||
import info.nightscout.androidaps.utils.JsonHelper;
|
|
||||||
|
|
||||||
public class TriggerConnector extends Trigger {
|
|
||||||
private static Logger log = LoggerFactory.getLogger(L.AUTOMATION);
|
|
||||||
|
|
||||||
public enum Type {
|
|
||||||
AND,
|
|
||||||
OR,
|
|
||||||
XOR;
|
|
||||||
|
|
||||||
public boolean apply(boolean a, boolean b) {
|
|
||||||
switch (this) {
|
|
||||||
case AND:
|
|
||||||
return a && b;
|
|
||||||
case OR:
|
|
||||||
return a || b;
|
|
||||||
case XOR:
|
|
||||||
return a ^ b;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public @StringRes
|
|
||||||
int getStringRes() {
|
|
||||||
switch (this) {
|
|
||||||
case OR:
|
|
||||||
return R.string.or;
|
|
||||||
case XOR:
|
|
||||||
return R.string.xor;
|
|
||||||
|
|
||||||
default:
|
|
||||||
case AND:
|
|
||||||
return R.string.and;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static List<String> labels() {
|
|
||||||
List<String> list = new ArrayList<>();
|
|
||||||
for (Type t : values()) {
|
|
||||||
list.add(MainApp.gs(t.getStringRes()));
|
|
||||||
}
|
|
||||||
return list;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void fillIconSet(TriggerConnector connector, HashSet<Integer> set) {
|
|
||||||
for (Trigger t : connector.list) {
|
|
||||||
if (t instanceof TriggerConnector) {
|
|
||||||
fillIconSet((TriggerConnector) t, set);
|
|
||||||
} else {
|
|
||||||
Optional<Integer> icon = t.icon();
|
|
||||||
if (icon.isPresent()) {
|
|
||||||
set.add(icon.get());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected List<Trigger> list = new ArrayList<>();
|
|
||||||
private Type connectorType;
|
|
||||||
|
|
||||||
public TriggerConnector() {
|
|
||||||
connectorType = Type.AND;
|
|
||||||
}
|
|
||||||
|
|
||||||
public TriggerConnector(Type connectorType) {
|
|
||||||
this.connectorType = connectorType;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void changeConnectorType(Type type) {
|
|
||||||
this.connectorType = type;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Type getConnectorType() {
|
|
||||||
return connectorType;
|
|
||||||
}
|
|
||||||
|
|
||||||
public synchronized void add(Trigger t) {
|
|
||||||
list.add(t);
|
|
||||||
t.connector = this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public synchronized void add(int pos, Trigger t) {
|
|
||||||
list.add(pos, t);
|
|
||||||
t.connector = this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public synchronized boolean remove(Trigger t) {
|
|
||||||
return list.remove(t);
|
|
||||||
}
|
|
||||||
|
|
||||||
public int size() {
|
|
||||||
return list.size();
|
|
||||||
}
|
|
||||||
|
|
||||||
public Trigger get(int i) {
|
|
||||||
return list.get(i);
|
|
||||||
}
|
|
||||||
|
|
||||||
public int pos(Trigger trigger) {
|
|
||||||
for (int i = 0; i < list.size(); ++i) {
|
|
||||||
if (list.get(i) == trigger) return i;
|
|
||||||
}
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public synchronized boolean shouldRun() {
|
|
||||||
boolean result = true;
|
|
||||||
|
|
||||||
// check first trigger
|
|
||||||
if (list.size() > 0)
|
|
||||||
result = list.get(0).shouldRun();
|
|
||||||
|
|
||||||
// check all others
|
|
||||||
for (int i = 1; i < list.size(); ++i) {
|
|
||||||
result = connectorType.apply(result, list.get(i).shouldRun());
|
|
||||||
}
|
|
||||||
if (result)
|
|
||||||
if (L.isEnabled(L.AUTOMATION))
|
|
||||||
log.debug("Ready for execution: " + friendlyDescription().replace("\n", " "));
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public synchronized String toJSON() {
|
|
||||||
JSONObject o = new JSONObject();
|
|
||||||
try {
|
|
||||||
o.put("type", TriggerConnector.class.getName());
|
|
||||||
JSONObject data = new JSONObject();
|
|
||||||
data.put("connectorType", connectorType.toString());
|
|
||||||
JSONArray array = new JSONArray();
|
|
||||||
for (Trigger t : list) {
|
|
||||||
array.put(t.toJSON());
|
|
||||||
}
|
|
||||||
data.put("triggerList", array);
|
|
||||||
o.put("data", data);
|
|
||||||
} catch (JSONException e) {
|
|
||||||
log.error("Unhandled exception", e);
|
|
||||||
}
|
|
||||||
return o.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
Trigger fromJSON(String data) {
|
|
||||||
try {
|
|
||||||
JSONObject d = new JSONObject(data);
|
|
||||||
connectorType = Type.valueOf(JsonHelper.safeGetString(d, "connectorType"));
|
|
||||||
JSONArray array = d.getJSONArray("triggerList");
|
|
||||||
list.clear();
|
|
||||||
for (int i = 0; i < array.length(); i++) {
|
|
||||||
Trigger newItem = instantiate(new JSONObject(array.getString(i)));
|
|
||||||
add(newItem);
|
|
||||||
}
|
|
||||||
} catch (JSONException e) {
|
|
||||||
log.error("Unhandled exception", e);
|
|
||||||
}
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int friendlyName() {
|
|
||||||
return connectorType.getStringRes();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String friendlyDescription() {
|
|
||||||
int counter = 0;
|
|
||||||
StringBuilder result = new StringBuilder();
|
|
||||||
for (Trigger t : list) {
|
|
||||||
if (counter++ > 0) result.append("\n").append(MainApp.gs(friendlyName())).append("\n");
|
|
||||||
result.append(t.friendlyDescription());
|
|
||||||
}
|
|
||||||
return result.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Optional<Integer> icon() {
|
|
||||||
return Optional.absent();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void executed(long time) {
|
|
||||||
for (int i = 0; i < list.size(); ++i) {
|
|
||||||
list.get(i).executed(time);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Trigger duplicate() {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
private TriggerListAdapter adapter;
|
|
||||||
|
|
||||||
public void rebuildView(FragmentManager fragmentManager) {
|
|
||||||
if (adapter != null)
|
|
||||||
adapter.rebuild(fragmentManager);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void generateDialog(LinearLayout root, FragmentManager fragmentManager) {
|
|
||||||
final int padding = MainApp.dpToPx(5);
|
|
||||||
|
|
||||||
root.setPadding(padding, padding, padding, padding);
|
|
||||||
root.setBackgroundResource(R.drawable.border_automation_unit);
|
|
||||||
|
|
||||||
LinearLayout triggerListLayout = new LinearLayout(root.getContext());
|
|
||||||
triggerListLayout.setOrientation(LinearLayout.VERTICAL);
|
|
||||||
triggerListLayout.setLayoutParams(new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT));
|
|
||||||
root.addView(triggerListLayout);
|
|
||||||
|
|
||||||
adapter = new TriggerListAdapter(fragmentManager, root.getContext(), triggerListLayout, this);
|
|
||||||
}
|
|
||||||
|
|
||||||
public TriggerConnector simplify() {
|
|
||||||
// simplify children
|
|
||||||
for (int i = 0; i < size(); ++i) {
|
|
||||||
if (get(i) instanceof TriggerConnector) {
|
|
||||||
TriggerConnector t = (TriggerConnector) get(i);
|
|
||||||
t.simplify();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// drop connector with only 1 element
|
|
||||||
if (size() == 1 && get(0) instanceof TriggerConnector) {
|
|
||||||
TriggerConnector c = (TriggerConnector) get(0);
|
|
||||||
remove(c);
|
|
||||||
changeConnectorType(c.getConnectorType());
|
|
||||||
for (Trigger t : c.list) {
|
|
||||||
add(t);
|
|
||||||
}
|
|
||||||
c.list.clear();
|
|
||||||
return simplify();
|
|
||||||
}
|
|
||||||
|
|
||||||
// merge connectors
|
|
||||||
if (connector != null && (connector.getConnectorType().equals(connectorType) || size() == 1)) {
|
|
||||||
final int pos = connector.pos(this);
|
|
||||||
connector.remove(this);
|
|
||||||
// move triggers of child connector into parent connector
|
|
||||||
for (int i = size() - 1; i >= 0; --i) {
|
|
||||||
connector.add(pos, get(i));
|
|
||||||
}
|
|
||||||
list.clear();
|
|
||||||
return connector.simplify();
|
|
||||||
}
|
|
||||||
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -0,0 +1,181 @@
|
||||||
|
package info.nightscout.androidaps.plugins.general.automation.triggers
|
||||||
|
|
||||||
|
import android.view.ViewGroup
|
||||||
|
import android.widget.LinearLayout
|
||||||
|
import androidx.annotation.StringRes
|
||||||
|
import androidx.fragment.app.FragmentManager
|
||||||
|
import com.google.common.base.Optional
|
||||||
|
import info.nightscout.androidaps.MainApp
|
||||||
|
import info.nightscout.androidaps.R
|
||||||
|
import info.nightscout.androidaps.logging.LTag
|
||||||
|
import info.nightscout.androidaps.plugins.general.automation.dialogs.TriggerListAdapter
|
||||||
|
import info.nightscout.androidaps.utils.JsonHelper.safeGetString
|
||||||
|
import info.nightscout.androidaps.utils.resources.ResourceHelper
|
||||||
|
import org.json.JSONArray
|
||||||
|
import org.json.JSONObject
|
||||||
|
import java.util.*
|
||||||
|
|
||||||
|
class TriggerConnector(mainApp: MainApp) : Trigger(mainApp) {
|
||||||
|
var list: MutableList<Trigger> = ArrayList()
|
||||||
|
var connectorType: Type = Type.AND
|
||||||
|
|
||||||
|
enum class Type {
|
||||||
|
AND, OR, XOR;
|
||||||
|
|
||||||
|
fun apply(a: Boolean, b: Boolean): Boolean =
|
||||||
|
when (this) {
|
||||||
|
AND -> a && b
|
||||||
|
OR -> a || b
|
||||||
|
XOR -> a xor b
|
||||||
|
}
|
||||||
|
|
||||||
|
@get:StringRes val stringRes: Int
|
||||||
|
get() = when (this) {
|
||||||
|
OR -> R.string.or
|
||||||
|
XOR -> R.string.xor
|
||||||
|
AND -> R.string.and
|
||||||
|
}
|
||||||
|
|
||||||
|
fun labels(resourceHelper: ResourceHelper): List<String> {
|
||||||
|
val list: MutableList<String> = ArrayList()
|
||||||
|
for (t in values()) {
|
||||||
|
list.add(resourceHelper.gs(t.stringRes))
|
||||||
|
}
|
||||||
|
return list
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
constructor(mainApp: MainApp, connectorType: Type) : this(mainApp) {
|
||||||
|
this.connectorType = connectorType
|
||||||
|
}
|
||||||
|
|
||||||
|
fun setType(type: Type) {
|
||||||
|
connectorType = type
|
||||||
|
}
|
||||||
|
|
||||||
|
@Synchronized
|
||||||
|
fun add(t: Trigger) {
|
||||||
|
list.add(t)
|
||||||
|
t.connector = this
|
||||||
|
}
|
||||||
|
|
||||||
|
@Synchronized
|
||||||
|
fun add(pos: Int, t: Trigger) {
|
||||||
|
list.add(pos, t)
|
||||||
|
t.connector = this
|
||||||
|
}
|
||||||
|
|
||||||
|
@Synchronized
|
||||||
|
fun remove(t: Trigger): Boolean = list.remove(t)
|
||||||
|
|
||||||
|
fun size(): Int = list.size
|
||||||
|
|
||||||
|
operator fun get(i: Int): Trigger = list[i]
|
||||||
|
|
||||||
|
fun pos(trigger: Trigger): Int {
|
||||||
|
for (i in list.indices) {
|
||||||
|
if (list[i] === trigger) return i
|
||||||
|
}
|
||||||
|
return -1
|
||||||
|
}
|
||||||
|
|
||||||
|
@Synchronized override fun shouldRun(): Boolean {
|
||||||
|
var result = true
|
||||||
|
// check first trigger
|
||||||
|
if (list.size > 0) result = list[0].shouldRun()
|
||||||
|
// check all others
|
||||||
|
for (i in 1 until list.size) {
|
||||||
|
result = connectorType.apply(result, list[i].shouldRun())
|
||||||
|
}
|
||||||
|
if (result) aapsLogger.debug(LTag.AUTOMATION, "Ready for execution: " + friendlyDescription().replace("\n", " "))
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
@Synchronized override fun toJSON(): String {
|
||||||
|
val array = JSONArray()
|
||||||
|
for (t in list) array.put(t.toJSON())
|
||||||
|
val data = JSONObject()
|
||||||
|
.put("connectorType", connectorType.toString())
|
||||||
|
.put("triggerList", array)
|
||||||
|
return JSONObject()
|
||||||
|
.put("type", TriggerConnector::class.java.name)
|
||||||
|
.put("data", data)
|
||||||
|
.toString()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun fromJSON(data: String): Trigger {
|
||||||
|
val d = JSONObject(data)
|
||||||
|
connectorType = Type.valueOf(safeGetString(d, "connectorType")!!)
|
||||||
|
val array = d.getJSONArray("triggerList")
|
||||||
|
list.clear()
|
||||||
|
for (i in 0 until array.length()) {
|
||||||
|
instantiate(JSONObject(array.getString(i)))?.let {
|
||||||
|
add(it)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun friendlyName(): Int = connectorType.stringRes
|
||||||
|
|
||||||
|
override fun friendlyDescription(): String {
|
||||||
|
val result = StringBuilder()
|
||||||
|
for ((counter, t) in list.withIndex()) {
|
||||||
|
if (counter > 0)
|
||||||
|
result.append("\n").append(resourceHelper.gs(friendlyName())).append("\n")
|
||||||
|
result.append(t.friendlyDescription())
|
||||||
|
}
|
||||||
|
return result.toString()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun icon(): Optional<Int?> = Optional.absent()
|
||||||
|
|
||||||
|
override fun duplicate(): Trigger = TriggerConnector(mainApp, connectorType)
|
||||||
|
|
||||||
|
private var adapter: TriggerListAdapter? = null
|
||||||
|
|
||||||
|
fun rebuildView(fragmentManager: FragmentManager) = adapter?.rebuild(fragmentManager)
|
||||||
|
|
||||||
|
override fun generateDialog(root: LinearLayout) {
|
||||||
|
val padding = resourceHelper.dpToPx(5)
|
||||||
|
root.setPadding(padding, padding, padding, padding)
|
||||||
|
root.setBackgroundResource(R.drawable.border_automation_unit)
|
||||||
|
val triggerListLayout = LinearLayout(root.context)
|
||||||
|
triggerListLayout.orientation = LinearLayout.VERTICAL
|
||||||
|
triggerListLayout.layoutParams = LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)
|
||||||
|
root.addView(triggerListLayout)
|
||||||
|
adapter = TriggerListAdapter(mainApp, resourceHelper, root.context, triggerListLayout, this)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun simplify(): TriggerConnector { // simplify children
|
||||||
|
for (i in 0 until size()) {
|
||||||
|
if (get(i) is TriggerConnector) {
|
||||||
|
val t = get(i) as TriggerConnector
|
||||||
|
t.simplify()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// drop connector with only 1 element
|
||||||
|
if (size() == 1 && get(0) is TriggerConnector) {
|
||||||
|
val c = get(0) as TriggerConnector
|
||||||
|
remove(c)
|
||||||
|
connectorType = c.connectorType
|
||||||
|
for (t in c.list) add(t)
|
||||||
|
c.list.clear()
|
||||||
|
return simplify()
|
||||||
|
}
|
||||||
|
// merge connectors
|
||||||
|
connector?.let { connector ->
|
||||||
|
if (connector.connectorType == connectorType || size() == 1) {
|
||||||
|
val pos = connector.pos(this)
|
||||||
|
connector.remove(this)
|
||||||
|
// move triggers of child connector into parent connector
|
||||||
|
for (i in size() - 1 downTo 0) {
|
||||||
|
connector.add(pos, get(i))
|
||||||
|
}
|
||||||
|
list.clear()
|
||||||
|
return connector.simplify()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,202 +0,0 @@
|
||||||
package info.nightscout.androidaps.plugins.general.automation.triggers;
|
|
||||||
|
|
||||||
|
|
||||||
import android.widget.LinearLayout;
|
|
||||||
|
|
||||||
import androidx.fragment.app.FragmentManager;
|
|
||||||
|
|
||||||
import com.google.common.base.Optional;
|
|
||||||
|
|
||||||
import org.json.JSONException;
|
|
||||||
import org.json.JSONObject;
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
import java.text.DecimalFormat;
|
|
||||||
|
|
||||||
import info.nightscout.androidaps.Constants;
|
|
||||||
import info.nightscout.androidaps.MainApp;
|
|
||||||
import info.nightscout.androidaps.R;
|
|
||||||
import info.nightscout.androidaps.data.Profile;
|
|
||||||
import info.nightscout.androidaps.logging.L;
|
|
||||||
import info.nightscout.androidaps.plugins.configBuilder.ProfileFunctions;
|
|
||||||
import info.nightscout.androidaps.plugins.general.automation.elements.Comparator;
|
|
||||||
import info.nightscout.androidaps.plugins.general.automation.elements.InputDelta;
|
|
||||||
import info.nightscout.androidaps.plugins.general.automation.elements.InputDelta.DeltaType;
|
|
||||||
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.elements.StaticLabel;
|
|
||||||
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.GlucoseStatus;
|
|
||||||
import info.nightscout.androidaps.utils.DateUtil;
|
|
||||||
import info.nightscout.androidaps.utils.JsonHelper;
|
|
||||||
import info.nightscout.androidaps.utils.T;
|
|
||||||
|
|
||||||
public class TriggerDelta extends Trigger {
|
|
||||||
private static Logger log = LoggerFactory.getLogger(L.AUTOMATION);
|
|
||||||
|
|
||||||
private final int MMOL_MAX = 4;
|
|
||||||
private final int MGDL_MAX = 72;
|
|
||||||
|
|
||||||
private String units;
|
|
||||||
private DeltaType deltaType;
|
|
||||||
|
|
||||||
private InputDelta value;
|
|
||||||
private Comparator comparator;
|
|
||||||
|
|
||||||
public TriggerDelta() {
|
|
||||||
super();
|
|
||||||
this.units = ProfileFunctions.getSystemUnits();
|
|
||||||
initializer();
|
|
||||||
}
|
|
||||||
|
|
||||||
private TriggerDelta(TriggerDelta triggerDelta) {
|
|
||||||
super();
|
|
||||||
lastRun = triggerDelta.lastRun;
|
|
||||||
this.units = triggerDelta.units;
|
|
||||||
deltaType = triggerDelta.deltaType;
|
|
||||||
value = new InputDelta(triggerDelta.value);
|
|
||||||
comparator = new Comparator(triggerDelta.comparator);
|
|
||||||
}
|
|
||||||
|
|
||||||
public double getValue() {
|
|
||||||
deltaType = value.getDeltaType();
|
|
||||||
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, 1d, new DecimalFormat("1"), DeltaType.DELTA);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public DeltaType getType() {
|
|
||||||
return deltaType;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getUnits() {
|
|
||||||
return this.units;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Comparator getComparator() {
|
|
||||||
return comparator;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public synchronized boolean shouldRun() {
|
|
||||||
GlucoseStatus glucoseStatus = GlucoseStatus.getGlucoseStatusData();
|
|
||||||
if (glucoseStatus == null)
|
|
||||||
if (comparator.getValue() == Comparator.Compare.IS_NOT_AVAILABLE)
|
|
||||||
return true;
|
|
||||||
else
|
|
||||||
return false;
|
|
||||||
|
|
||||||
// Setting type of delta
|
|
||||||
double delta;
|
|
||||||
|
|
||||||
if (deltaType == DeltaType.SHORT_AVERAGE)
|
|
||||||
delta = glucoseStatus.short_avgdelta;
|
|
||||||
else if (deltaType == DeltaType.LONG_AVERAGE)
|
|
||||||
delta = glucoseStatus.long_avgdelta;
|
|
||||||
else
|
|
||||||
delta = glucoseStatus.delta;
|
|
||||||
|
|
||||||
if (lastRun > DateUtil.now() - T.mins(5).msecs())
|
|
||||||
return false;
|
|
||||||
|
|
||||||
boolean doRun = comparator.getValue().check(delta, Profile.toMgdl(value.getValue(), this.units));
|
|
||||||
if (doRun) {
|
|
||||||
if (L.isEnabled(L.AUTOMATION))
|
|
||||||
log.debug("Ready for execution: delta is " + delta + " " + friendlyDescription());
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public synchronized String toJSON() {
|
|
||||||
JSONObject o = new JSONObject();
|
|
||||||
try {
|
|
||||||
o.put("type", TriggerDelta.class.getName());
|
|
||||||
JSONObject data = new JSONObject();
|
|
||||||
data.put("value", getValue());
|
|
||||||
data.put("units", units);
|
|
||||||
data.put("lastRun", lastRun);
|
|
||||||
data.put("deltaType", getType());
|
|
||||||
data.put("comparator", comparator.getValue().toString());
|
|
||||||
o.put("data", data);
|
|
||||||
} catch (JSONException e) {
|
|
||||||
log.error("Unhandled exception", e);
|
|
||||||
}
|
|
||||||
return o.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
Trigger fromJSON(String data) {
|
|
||||||
try {
|
|
||||||
JSONObject d = new JSONObject(data);
|
|
||||||
units = JsonHelper.safeGetString(d, "units");
|
|
||||||
deltaType = DeltaType.valueOf(JsonHelper.safeGetString(d, "deltaType", ""));
|
|
||||||
value.setValue(JsonHelper.safeGetDouble(d, "value"), deltaType);
|
|
||||||
lastRun = JsonHelper.safeGetLong(d, "lastRun");
|
|
||||||
comparator.setValue(Comparator.Compare.valueOf(JsonHelper.safeGetString(d, "comparator")));
|
|
||||||
} catch (Exception e) {
|
|
||||||
log.error("Unhandled exception", e);
|
|
||||||
}
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int friendlyName() {
|
|
||||||
return R.string.deltalabel;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String friendlyDescription() {
|
|
||||||
return MainApp.gs(R.string.deltacompared, MainApp.gs(comparator.getValue().getStringRes()), getValue(), MainApp.gs(deltaType.getStringRes()));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Optional<Integer> icon() {
|
|
||||||
return Optional.of(R.drawable.icon_auto_delta);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Trigger duplicate() {
|
|
||||||
return new TriggerDelta(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
TriggerDelta setValue(double requestedValue, DeltaType requestedType) {
|
|
||||||
this.value.setValue(requestedValue, requestedType);
|
|
||||||
this.deltaType = requestedType;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
TriggerDelta setUnits(String units) {
|
|
||||||
this.units = units;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
TriggerDelta lastRun(long lastRun) {
|
|
||||||
this.lastRun = lastRun;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
TriggerDelta comparator(Comparator.Compare compare) {
|
|
||||||
this.comparator = new Comparator().setValue(compare);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void generateDialog(LinearLayout root, FragmentManager fragmentManager) {
|
|
||||||
new LayoutBuilder()
|
|
||||||
.add(new StaticLabel(R.string.deltalabel))
|
|
||||||
.add(comparator)
|
|
||||||
.add(new LabelWithElement(MainApp.gs(R.string.deltalabel_u, getUnits()) + ": ", "", value))
|
|
||||||
.build(root);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -0,0 +1,106 @@
|
||||||
|
package info.nightscout.androidaps.plugins.general.automation.triggers
|
||||||
|
|
||||||
|
import android.widget.LinearLayout
|
||||||
|
import com.google.common.base.Optional
|
||||||
|
import info.nightscout.androidaps.Constants
|
||||||
|
import info.nightscout.androidaps.MainApp
|
||||||
|
import info.nightscout.androidaps.R
|
||||||
|
import info.nightscout.androidaps.data.Profile
|
||||||
|
import info.nightscout.androidaps.logging.LTag
|
||||||
|
import info.nightscout.androidaps.plugins.general.automation.elements.Comparator
|
||||||
|
import info.nightscout.androidaps.plugins.general.automation.elements.InputDelta
|
||||||
|
import info.nightscout.androidaps.plugins.general.automation.elements.InputDelta.DeltaType
|
||||||
|
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.elements.StaticLabel
|
||||||
|
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.GlucoseStatus
|
||||||
|
import info.nightscout.androidaps.utils.JsonHelper
|
||||||
|
import org.json.JSONObject
|
||||||
|
import java.text.DecimalFormat
|
||||||
|
|
||||||
|
class TriggerDelta(mainApp: MainApp) : Trigger(mainApp) {
|
||||||
|
|
||||||
|
var units: String = Constants.MGDL
|
||||||
|
private var delta: InputDelta = InputDelta(mainApp)
|
||||||
|
var comparator: Comparator = Comparator(mainApp)
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
private const val MMOL_MAX = 4.0
|
||||||
|
private const val MGDL_MAX = 72.0
|
||||||
|
}
|
||||||
|
|
||||||
|
init {
|
||||||
|
units = profileFunction.getUnits()
|
||||||
|
delta = if (units == Constants.MMOL) InputDelta(mainApp, 0.0, (-MMOL_MAX), MMOL_MAX, 0.1, DecimalFormat("0.1"), DeltaType.DELTA)
|
||||||
|
else InputDelta(mainApp, 0.0, (-MGDL_MAX), MGDL_MAX, 1.0, DecimalFormat("1"), DeltaType.DELTA)
|
||||||
|
}
|
||||||
|
|
||||||
|
private constructor(mainApp: MainApp, triggerDelta: TriggerDelta) : this(mainApp) {
|
||||||
|
units = triggerDelta.units
|
||||||
|
delta = InputDelta(mainApp, triggerDelta.delta)
|
||||||
|
comparator = Comparator(mainApp, triggerDelta.comparator.value)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun shouldRun(): Boolean {
|
||||||
|
val glucoseStatus = GlucoseStatus.getGlucoseStatusData()
|
||||||
|
?: return if (comparator.value == Comparator.Compare.IS_NOT_AVAILABLE) {
|
||||||
|
aapsLogger.debug(LTag.AUTOMATION, "Ready for execution: " + friendlyDescription())
|
||||||
|
true
|
||||||
|
} else {
|
||||||
|
aapsLogger.debug(LTag.AUTOMATION, "NOT ready for execution: " + friendlyDescription())
|
||||||
|
false
|
||||||
|
}
|
||||||
|
val calculatedDelta = when (delta.deltaType) {
|
||||||
|
DeltaType.SHORT_AVERAGE -> glucoseStatus.short_avgdelta
|
||||||
|
DeltaType.LONG_AVERAGE -> glucoseStatus.long_avgdelta
|
||||||
|
else -> glucoseStatus.delta
|
||||||
|
}
|
||||||
|
if (comparator.value.check(calculatedDelta, Profile.toMgdl(delta.value, units))) {
|
||||||
|
aapsLogger.debug(LTag.AUTOMATION, "Ready for execution: delta is " + calculatedDelta + " " + friendlyDescription())
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
aapsLogger.debug(LTag.AUTOMATION, "NOT ready for execution: " + friendlyDescription())
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun toJSON(): String {
|
||||||
|
val data = JSONObject()
|
||||||
|
.put("value", delta.value)
|
||||||
|
.put("units", units)
|
||||||
|
.put("deltaType", delta.deltaType)
|
||||||
|
.put("comparator", comparator.value.toString())
|
||||||
|
return JSONObject()
|
||||||
|
.put("type", this::class.java.name)
|
||||||
|
.put("data", data)
|
||||||
|
.toString()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun fromJSON(data: String): Trigger {
|
||||||
|
val d = JSONObject(data)
|
||||||
|
units = JsonHelper.safeGetString(d, "units")!!
|
||||||
|
val type = DeltaType.valueOf(JsonHelper.safeGetString(d, "deltaType", ""))
|
||||||
|
val value = JsonHelper.safeGetDouble(d, "value")
|
||||||
|
delta =
|
||||||
|
if (units == Constants.MMOL) InputDelta(mainApp, value, (-MMOL_MAX), MMOL_MAX, 0.1, DecimalFormat("0.1"), type)
|
||||||
|
else InputDelta(mainApp, value, (-MGDL_MAX), MGDL_MAX, 1.0, DecimalFormat("1"), type)
|
||||||
|
comparator.setValue(Comparator.Compare.valueOf(JsonHelper.safeGetString(d, "comparator")!!))
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun friendlyName(): Int = R.string.deltalabel
|
||||||
|
|
||||||
|
override fun friendlyDescription(): String =
|
||||||
|
resourceHelper.gs(R.string.deltacompared, resourceHelper.gs(comparator.value.stringRes), delta.value, resourceHelper.gs(delta.deltaType.stringRes))
|
||||||
|
|
||||||
|
override fun icon(): Optional<Int?> = Optional.of(R.drawable.icon_auto_delta)
|
||||||
|
|
||||||
|
override fun duplicate(): Trigger = TriggerDelta(mainApp, this)
|
||||||
|
|
||||||
|
override fun generateDialog(root: LinearLayout) {
|
||||||
|
LayoutBuilder()
|
||||||
|
.add(StaticLabel(mainApp, R.string.deltalabel))
|
||||||
|
.add(comparator)
|
||||||
|
.add(LabelWithElement(mainApp, resourceHelper.gs(R.string.deltalabel_u, units) + ": ", "", delta))
|
||||||
|
.build(root)
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,36 @@
|
||||||
|
package info.nightscout.androidaps.plugins.general.automation.triggers
|
||||||
|
|
||||||
|
import com.google.common.base.Optional
|
||||||
|
import info.nightscout.androidaps.MainApp
|
||||||
|
|
||||||
|
// Used for instantiation of other triggers only
|
||||||
|
class TriggerDummy(mainApp: MainApp) : Trigger(mainApp) {
|
||||||
|
|
||||||
|
override fun shouldRun(): Boolean {
|
||||||
|
throw NotImplementedError("An operation is not implemented")
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun toJSON(): String {
|
||||||
|
throw NotImplementedError("An operation is not implemented")
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun fromJSON(data: String): Trigger {
|
||||||
|
throw NotImplementedError("An operation is not implemented")
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun friendlyName(): Int {
|
||||||
|
throw NotImplementedError("An operation is not implemented")
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun friendlyDescription(): String {
|
||||||
|
throw NotImplementedError("An operation is not implemented")
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun icon(): Optional<Int?> {
|
||||||
|
throw NotImplementedError("An operation is not implemented")
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun duplicate(): Trigger {
|
||||||
|
throw NotImplementedError("An operation is not implemented")
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,146 +0,0 @@
|
||||||
package info.nightscout.androidaps.plugins.general.automation.triggers;
|
|
||||||
|
|
||||||
import android.widget.LinearLayout;
|
|
||||||
|
|
||||||
import androidx.fragment.app.FragmentManager;
|
|
||||||
|
|
||||||
import com.google.common.base.Optional;
|
|
||||||
|
|
||||||
import org.json.JSONException;
|
|
||||||
import org.json.JSONObject;
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
import info.nightscout.androidaps.MainApp;
|
|
||||||
import info.nightscout.androidaps.R;
|
|
||||||
import info.nightscout.androidaps.data.IobTotal;
|
|
||||||
import info.nightscout.androidaps.data.Profile;
|
|
||||||
import info.nightscout.androidaps.logging.L;
|
|
||||||
import info.nightscout.androidaps.plugins.configBuilder.ProfileFunctions;
|
|
||||||
import info.nightscout.androidaps.plugins.general.automation.elements.Comparator;
|
|
||||||
import info.nightscout.androidaps.plugins.general.automation.elements.InputInsulin;
|
|
||||||
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.elements.StaticLabel;
|
|
||||||
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.IobCobCalculatorPlugin;
|
|
||||||
import info.nightscout.androidaps.utils.DateUtil;
|
|
||||||
import info.nightscout.androidaps.utils.JsonHelper;
|
|
||||||
import info.nightscout.androidaps.utils.T;
|
|
||||||
|
|
||||||
public class TriggerIob extends Trigger {
|
|
||||||
private static Logger log = LoggerFactory.getLogger(L.AUTOMATION);
|
|
||||||
|
|
||||||
private InputInsulin insulin = new InputInsulin();
|
|
||||||
private Comparator comparator = new Comparator();
|
|
||||||
|
|
||||||
public TriggerIob() {
|
|
||||||
super();
|
|
||||||
}
|
|
||||||
|
|
||||||
private TriggerIob(TriggerIob triggerIob) {
|
|
||||||
super();
|
|
||||||
insulin = new InputInsulin(triggerIob.insulin);
|
|
||||||
comparator = new Comparator(triggerIob.comparator);
|
|
||||||
lastRun = triggerIob.lastRun;
|
|
||||||
}
|
|
||||||
|
|
||||||
public double getValue() {
|
|
||||||
return insulin.getValue();
|
|
||||||
}
|
|
||||||
|
|
||||||
public Comparator getComparator() {
|
|
||||||
return comparator;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public synchronized boolean shouldRun() {
|
|
||||||
Profile profile = ProfileFunctions.getInstance().getProfile();
|
|
||||||
if (profile == null)
|
|
||||||
return false;
|
|
||||||
IobTotal iob = IobCobCalculatorPlugin.getPlugin().calculateFromTreatmentsAndTempsSynchronized(DateUtil.now(), profile);
|
|
||||||
|
|
||||||
if (lastRun > DateUtil.now() - T.mins(5).msecs())
|
|
||||||
return false;
|
|
||||||
|
|
||||||
boolean doRun = comparator.getValue().check(iob.iob, getValue());
|
|
||||||
if (doRun) {
|
|
||||||
if (L.isEnabled(L.AUTOMATION))
|
|
||||||
log.debug("Ready for execution: " + friendlyDescription());
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public synchronized String toJSON() {
|
|
||||||
JSONObject o = new JSONObject();
|
|
||||||
try {
|
|
||||||
o.put("type", TriggerIob.class.getName());
|
|
||||||
JSONObject data = new JSONObject();
|
|
||||||
data.put("insulin", getValue());
|
|
||||||
data.put("lastRun", lastRun);
|
|
||||||
data.put("comparator", comparator.getValue().toString());
|
|
||||||
o.put("data", data);
|
|
||||||
} catch (JSONException e) {
|
|
||||||
log.error("Unhandled exception", e);
|
|
||||||
}
|
|
||||||
return o.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
Trigger fromJSON(String data) {
|
|
||||||
try {
|
|
||||||
JSONObject d = new JSONObject(data);
|
|
||||||
insulin.setValue(JsonHelper.safeGetDouble(d, "insulin"));
|
|
||||||
lastRun = JsonHelper.safeGetLong(d, "lastRun");
|
|
||||||
comparator.setValue(Comparator.Compare.valueOf(JsonHelper.safeGetString(d, "comparator")));
|
|
||||||
} catch (Exception e) {
|
|
||||||
log.error("Unhandled exception", e);
|
|
||||||
}
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int friendlyName() {
|
|
||||||
return R.string.iob;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String friendlyDescription() {
|
|
||||||
return MainApp.gs(R.string.iobcompared, MainApp.gs(comparator.getValue().getStringRes()), getValue());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Optional<Integer> icon() {
|
|
||||||
return Optional.of(R.drawable.ic_keyboard_capslock);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Trigger duplicate() {
|
|
||||||
return new TriggerIob(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
TriggerIob setValue(double threshold) {
|
|
||||||
insulin.setValue(threshold);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
TriggerIob lastRun(long lastRun) {
|
|
||||||
this.lastRun = lastRun;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
TriggerIob comparator(Comparator.Compare compare) {
|
|
||||||
this.comparator = new Comparator().setValue(compare);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void generateDialog(LinearLayout root, FragmentManager fragmentManager) {
|
|
||||||
new LayoutBuilder()
|
|
||||||
.add(new StaticLabel(R.string.iob))
|
|
||||||
.add(comparator)
|
|
||||||
.add(new LabelWithElement(MainApp.gs(R.string.iob_u), "", insulin))
|
|
||||||
.build(root);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -0,0 +1,72 @@
|
||||||
|
package info.nightscout.androidaps.plugins.general.automation.triggers
|
||||||
|
|
||||||
|
import android.widget.LinearLayout
|
||||||
|
import com.google.common.base.Optional
|
||||||
|
import info.nightscout.androidaps.MainApp
|
||||||
|
import info.nightscout.androidaps.R
|
||||||
|
import info.nightscout.androidaps.logging.LTag
|
||||||
|
import info.nightscout.androidaps.plugins.general.automation.elements.Comparator
|
||||||
|
import info.nightscout.androidaps.plugins.general.automation.elements.InputInsulin
|
||||||
|
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.elements.StaticLabel
|
||||||
|
import info.nightscout.androidaps.utils.DateUtil
|
||||||
|
import info.nightscout.androidaps.utils.JsonHelper
|
||||||
|
import org.json.JSONObject
|
||||||
|
|
||||||
|
class TriggerIob(mainApp: MainApp) : Trigger(mainApp) {
|
||||||
|
private var insulin = InputInsulin(mainApp)
|
||||||
|
var comparator: Comparator = Comparator(mainApp)
|
||||||
|
|
||||||
|
constructor(mainApp: MainApp, triggerIob: TriggerIob) : this(mainApp) {
|
||||||
|
insulin = InputInsulin(mainApp, triggerIob.insulin)
|
||||||
|
comparator = Comparator(mainApp, triggerIob.comparator.value)
|
||||||
|
}
|
||||||
|
|
||||||
|
val value: Double = 0.0
|
||||||
|
|
||||||
|
override fun shouldRun(): Boolean {
|
||||||
|
val profile = profileFunction.getProfile() ?: return false
|
||||||
|
val iob = iobCobCalculatorPlugin.calculateFromTreatmentsAndTempsSynchronized(DateUtil.now(), profile)
|
||||||
|
if (comparator.value.check(iob.iob, value)) {
|
||||||
|
aapsLogger.debug(LTag.AUTOMATION, "Ready for execution: " + friendlyDescription())
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
aapsLogger.debug(LTag.AUTOMATION, "NOT ready for execution: " + friendlyDescription())
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
@Synchronized override fun toJSON(): String {
|
||||||
|
val data = JSONObject()
|
||||||
|
.put("insulin", value)
|
||||||
|
.put("comparator", comparator.value.toString())
|
||||||
|
return JSONObject()
|
||||||
|
.put("type", this::class.java.name)
|
||||||
|
.put("data", data)
|
||||||
|
.toString()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun fromJSON(data: String): Trigger {
|
||||||
|
val d = JSONObject(data)
|
||||||
|
insulin.value = JsonHelper.safeGetDouble(d, "insulin")
|
||||||
|
comparator.setValue(Comparator.Compare.valueOf(JsonHelper.safeGetString(d, "comparator")!!))
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun friendlyName(): Int = R.string.iob
|
||||||
|
|
||||||
|
override fun friendlyDescription(): String =
|
||||||
|
resourceHelper.gs(R.string.iobcompared, resourceHelper.gs(comparator.value.stringRes), value)
|
||||||
|
|
||||||
|
override fun icon(): Optional<Int?> = Optional.of(R.drawable.ic_keyboard_capslock)
|
||||||
|
|
||||||
|
override fun duplicate(): Trigger = TriggerIob(mainApp, this)
|
||||||
|
|
||||||
|
override fun generateDialog(root: LinearLayout) {
|
||||||
|
LayoutBuilder()
|
||||||
|
.add(StaticLabel(mainApp, R.string.iob))
|
||||||
|
.add(comparator)
|
||||||
|
.add(LabelWithElement(mainApp, resourceHelper.gs(R.string.iob_u), "", insulin))
|
||||||
|
.build(root)
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,190 +0,0 @@
|
||||||
package info.nightscout.androidaps.plugins.general.automation.triggers;
|
|
||||||
|
|
||||||
import android.location.Location;
|
|
||||||
import android.widget.LinearLayout;
|
|
||||||
|
|
||||||
import androidx.fragment.app.FragmentManager;
|
|
||||||
|
|
||||||
import com.google.common.base.Optional;
|
|
||||||
|
|
||||||
import org.json.JSONException;
|
|
||||||
import org.json.JSONObject;
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
import java.text.DecimalFormat;
|
|
||||||
|
|
||||||
import info.nightscout.androidaps.MainApp;
|
|
||||||
import info.nightscout.androidaps.R;
|
|
||||||
import info.nightscout.androidaps.logging.L;
|
|
||||||
import info.nightscout.androidaps.plugins.general.automation.elements.InputButton;
|
|
||||||
import info.nightscout.androidaps.plugins.general.automation.elements.InputDouble;
|
|
||||||
import info.nightscout.androidaps.plugins.general.automation.elements.InputLocationMode;
|
|
||||||
import info.nightscout.androidaps.plugins.general.automation.elements.InputString;
|
|
||||||
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.elements.StaticLabel;
|
|
||||||
import info.nightscout.androidaps.services.LocationService;
|
|
||||||
import info.nightscout.androidaps.utils.DateUtil;
|
|
||||||
import info.nightscout.androidaps.utils.JsonHelper;
|
|
||||||
import info.nightscout.androidaps.utils.T;
|
|
||||||
|
|
||||||
import static info.nightscout.androidaps.plugins.general.automation.elements.InputLocationMode.Mode.*;
|
|
||||||
|
|
||||||
public class TriggerLocation extends Trigger {
|
|
||||||
private static Logger log = LoggerFactory.getLogger(L.AUTOMATION);
|
|
||||||
|
|
||||||
InputDouble latitude = new InputDouble(0d, -90d, +90d, 0.000001d, new DecimalFormat("0.000000"));
|
|
||||||
InputDouble longitude = new InputDouble(0d, -180d, +180d, 0.000001d, new DecimalFormat("0.000000"));
|
|
||||||
InputDouble distance = new InputDouble(200d, 0, 100000, 10d, new DecimalFormat("0"));
|
|
||||||
InputLocationMode modeSelected = new InputLocationMode();
|
|
||||||
InputLocationMode.Mode lastMode = INSIDE;
|
|
||||||
|
|
||||||
InputString name = new InputString();
|
|
||||||
|
|
||||||
private Runnable buttonAction = () -> {
|
|
||||||
Location location = LocationService.getLastLocation();
|
|
||||||
if (location != null) {
|
|
||||||
latitude.setValue(location.getLatitude());
|
|
||||||
longitude.setValue(location.getLongitude());
|
|
||||||
log.debug(String.format("Grabbed location: %f %f", latitude.getValue(), longitude.getValue()));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
public TriggerLocation() {
|
|
||||||
super();
|
|
||||||
}
|
|
||||||
|
|
||||||
private TriggerLocation(TriggerLocation triggerLocation) {
|
|
||||||
super();
|
|
||||||
latitude = new InputDouble(triggerLocation.latitude);
|
|
||||||
longitude = new InputDouble(triggerLocation.longitude);
|
|
||||||
distance = new InputDouble(triggerLocation.distance);
|
|
||||||
modeSelected = new InputLocationMode(triggerLocation.modeSelected);
|
|
||||||
if (modeSelected.getValue() == GOING_OUT)
|
|
||||||
lastMode = OUTSIDE;
|
|
||||||
lastRun = triggerLocation.lastRun;
|
|
||||||
name = triggerLocation.name;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public synchronized boolean shouldRun() {
|
|
||||||
Location location = this.getCurrentLocation();
|
|
||||||
if (location == null)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if (lastRun > DateUtil.now() - T.mins(5).msecs())
|
|
||||||
return false;
|
|
||||||
|
|
||||||
Location a = new Location("Trigger");
|
|
||||||
a.setLatitude(latitude.getValue());
|
|
||||||
a.setLongitude(longitude.getValue());
|
|
||||||
double calculatedDistance = location.distanceTo(a);
|
|
||||||
|
|
||||||
// log.debug("Moded(current/last/wanted): "+(currentMode(calculatedDistance))+"/"+lastMode+"/"+modeSelected.getValue());
|
|
||||||
// log.debug("Distance: "+calculatedDistance + "("+distance.getValue()+")");
|
|
||||||
|
|
||||||
if ((modeSelected.getValue() == INSIDE) && (calculatedDistance <= distance.getValue()) ||
|
|
||||||
((modeSelected.getValue() == OUTSIDE) && (calculatedDistance > distance.getValue())) ||
|
|
||||||
((modeSelected.getValue() == GOING_IN) && (calculatedDistance <= distance.getValue()) && (lastMode == OUTSIDE)) ||
|
|
||||||
((modeSelected.getValue() == GOING_OUT) && (calculatedDistance > distance.getValue()) && (lastMode == INSIDE))
|
|
||||||
) {
|
|
||||||
if (L.isEnabled(L.AUTOMATION))
|
|
||||||
log.debug("Ready for execution: " + friendlyDescription());
|
|
||||||
lastMode = currentMode(calculatedDistance);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
lastMode = currentMode(calculatedDistance); // current mode will be last mode for the next check
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public synchronized String toJSON() {
|
|
||||||
JSONObject o = new JSONObject();
|
|
||||||
try {
|
|
||||||
o.put("type", TriggerLocation.class.getName());
|
|
||||||
JSONObject data = new JSONObject();
|
|
||||||
data.put("latitude", latitude.getValue());
|
|
||||||
data.put("longitude", longitude.getValue());
|
|
||||||
data.put("distance", distance.getValue());
|
|
||||||
data.put("name", name.getValue());
|
|
||||||
data.put("mode", modeSelected.getValue());
|
|
||||||
data.put("lastRun", lastRun);
|
|
||||||
o.put("data", data);
|
|
||||||
} catch (JSONException e) {
|
|
||||||
log.error("Unhandled exception", e);
|
|
||||||
}
|
|
||||||
return o.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
Trigger fromJSON(String data) {
|
|
||||||
try {
|
|
||||||
JSONObject d = new JSONObject(data);
|
|
||||||
latitude.setValue(JsonHelper.safeGetDouble(d, "latitude"));
|
|
||||||
longitude.setValue(JsonHelper.safeGetDouble(d, "longitude"));
|
|
||||||
distance.setValue(JsonHelper.safeGetDouble(d, "distance"));
|
|
||||||
name.setValue(JsonHelper.safeGetString(d, "name"));
|
|
||||||
modeSelected.setValue(InputLocationMode.Mode.valueOf(JsonHelper.safeGetString(d, "mode")));
|
|
||||||
if (modeSelected.getValue() == GOING_OUT)
|
|
||||||
lastMode = OUTSIDE;
|
|
||||||
lastRun = DateUtil.now(); // set lastRun to now to give the service 5 mins to get the location properly
|
|
||||||
} catch (Exception e) {
|
|
||||||
log.error("Unhandled exception", e);
|
|
||||||
}
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int friendlyName() {
|
|
||||||
return R.string.location;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String friendlyDescription() {
|
|
||||||
return MainApp.gs(R.string.locationis, MainApp.gs(modeSelected.getValue().getStringRes()), " " + name.getValue());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Optional<Integer> icon() {
|
|
||||||
return Optional.of(R.drawable.ic_location_on);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Trigger duplicate() {
|
|
||||||
return new TriggerLocation(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
TriggerLocation lastRun(long lastRun) {
|
|
||||||
this.lastRun = lastRun;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void generateDialog(LinearLayout root, FragmentManager fragmentManager) {
|
|
||||||
new LayoutBuilder()
|
|
||||||
.add(new StaticLabel(R.string.location))
|
|
||||||
.add(new LabelWithElement(MainApp.gs(R.string.name_short), "", name))
|
|
||||||
.add(new LabelWithElement(MainApp.gs(R.string.latitude_short), "", latitude))
|
|
||||||
.add(new LabelWithElement(MainApp.gs(R.string.longitude_short), "", longitude))
|
|
||||||
.add(new LabelWithElement(MainApp.gs(R.string.distance_short), "", distance))
|
|
||||||
.add(new LabelWithElement(MainApp.gs(R.string.location_mode), "", modeSelected))
|
|
||||||
.add(new InputButton(MainApp.gs(R.string.currentlocation), buttonAction), LocationService.getLastLocation() != null)
|
|
||||||
.build(root);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Method to return the actual mode based on the current distance
|
|
||||||
InputLocationMode.Mode currentMode(double currentDistance){
|
|
||||||
if ( currentDistance <= this.distance.getValue() )
|
|
||||||
return INSIDE;
|
|
||||||
else
|
|
||||||
return OUTSIDE;
|
|
||||||
}
|
|
||||||
|
|
||||||
// for mocking only TODO remove
|
|
||||||
static Location getCurrentLocation(){
|
|
||||||
return LocationService.getLastLocation();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -0,0 +1,109 @@
|
||||||
|
package info.nightscout.androidaps.plugins.general.automation.triggers
|
||||||
|
|
||||||
|
import android.location.Location
|
||||||
|
import android.widget.LinearLayout
|
||||||
|
import com.google.common.base.Optional
|
||||||
|
import info.nightscout.androidaps.MainApp
|
||||||
|
import info.nightscout.androidaps.R
|
||||||
|
import info.nightscout.androidaps.logging.LTag
|
||||||
|
import info.nightscout.androidaps.plugins.general.automation.elements.*
|
||||||
|
import info.nightscout.androidaps.utils.JsonHelper
|
||||||
|
import org.json.JSONObject
|
||||||
|
import java.text.DecimalFormat
|
||||||
|
|
||||||
|
class TriggerLocation(mainApp: MainApp) : Trigger(mainApp) {
|
||||||
|
var latitude = InputDouble(mainApp, 0.0, -90.0, +90.0, 0.000001, DecimalFormat("0.000000"))
|
||||||
|
var longitude = InputDouble(mainApp, 0.0, -180.0, +180.0, 0.000001, DecimalFormat("0.000000"))
|
||||||
|
var distance = InputDouble(mainApp, 200.0, 0.0, 100000.0, 10.0, DecimalFormat("0"))
|
||||||
|
var modeSelected = InputLocationMode(mainApp)
|
||||||
|
var name: InputString = InputString(mainApp)
|
||||||
|
|
||||||
|
var lastMode = InputLocationMode.Mode.INSIDE
|
||||||
|
private val buttonAction = Runnable {
|
||||||
|
val location = locationService.lastLocation
|
||||||
|
if (location != null) {
|
||||||
|
latitude.value = location.latitude
|
||||||
|
longitude.value = location.longitude
|
||||||
|
aapsLogger.debug(LTag.AUTOMATION, String.format("Grabbed location: %f %f", latitude.value, longitude.value))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private constructor(mainApp: MainApp, triggerLocation: TriggerLocation) : this(mainApp) {
|
||||||
|
latitude = InputDouble(mainApp, triggerLocation.latitude)
|
||||||
|
longitude = InputDouble(mainApp, triggerLocation.longitude)
|
||||||
|
distance = InputDouble(mainApp, triggerLocation.distance)
|
||||||
|
modeSelected = InputLocationMode(mainApp, triggerLocation.modeSelected.value)
|
||||||
|
if (modeSelected.value == InputLocationMode.Mode.GOING_OUT)
|
||||||
|
lastMode = InputLocationMode.Mode.OUTSIDE
|
||||||
|
name = triggerLocation.name
|
||||||
|
}
|
||||||
|
|
||||||
|
@Synchronized override fun shouldRun(): Boolean {
|
||||||
|
val location: Location = locationService.lastLocation ?: return false
|
||||||
|
val a = Location("Trigger")
|
||||||
|
a.latitude = latitude.value
|
||||||
|
a.longitude = longitude.value
|
||||||
|
val calculatedDistance = location.distanceTo(a).toDouble()
|
||||||
|
if (modeSelected.value == InputLocationMode.Mode.INSIDE && calculatedDistance <= distance.value ||
|
||||||
|
modeSelected.value == InputLocationMode.Mode.OUTSIDE && calculatedDistance > distance.value ||
|
||||||
|
modeSelected.value == InputLocationMode.Mode.GOING_IN && calculatedDistance <= distance.value && lastMode == InputLocationMode.Mode.OUTSIDE ||
|
||||||
|
modeSelected.value == InputLocationMode.Mode.GOING_OUT && calculatedDistance > distance.value && lastMode == InputLocationMode.Mode.INSIDE) {
|
||||||
|
aapsLogger.debug(LTag.AUTOMATION, "Ready for execution: " + friendlyDescription())
|
||||||
|
lastMode = currentMode(calculatedDistance)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
lastMode = currentMode(calculatedDistance) // current mode will be last mode for the next check
|
||||||
|
aapsLogger.debug(LTag.AUTOMATION, "NOT ready for execution: " + friendlyDescription())
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun toJSON(): String {
|
||||||
|
val data = JSONObject()
|
||||||
|
.put("latitude", latitude.value)
|
||||||
|
.put("longitude", longitude.value)
|
||||||
|
.put("distance", distance.value)
|
||||||
|
.put("name", name.value)
|
||||||
|
.put("mode", modeSelected.value)
|
||||||
|
return JSONObject()
|
||||||
|
.put("type", this::class.java.name)
|
||||||
|
.put("data", data)
|
||||||
|
.toString()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun fromJSON(data: String): Trigger {
|
||||||
|
val d = JSONObject(data)
|
||||||
|
latitude.value = JsonHelper.safeGetDouble(d, "latitude")
|
||||||
|
longitude.value = JsonHelper.safeGetDouble(d, "longitude")
|
||||||
|
distance.value = JsonHelper.safeGetDouble(d, "distance")
|
||||||
|
name.value = JsonHelper.safeGetString(d, "name")!!
|
||||||
|
modeSelected.value = InputLocationMode.Mode.valueOf(JsonHelper.safeGetString(d, "mode")!!)
|
||||||
|
if (modeSelected.value == InputLocationMode.Mode.GOING_OUT) lastMode = InputLocationMode.Mode.OUTSIDE
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun friendlyName(): Int = R.string.location
|
||||||
|
|
||||||
|
override fun friendlyDescription(): String =
|
||||||
|
resourceHelper.gs(R.string.locationis, resourceHelper.gs(modeSelected.value.stringRes), " " + name.value)
|
||||||
|
|
||||||
|
override fun icon(): Optional<Int?> = Optional.of(R.drawable.ic_location_on)
|
||||||
|
|
||||||
|
override fun duplicate(): Trigger = TriggerLocation(mainApp, this)
|
||||||
|
|
||||||
|
override fun generateDialog(root: LinearLayout) {
|
||||||
|
LayoutBuilder()
|
||||||
|
.add(StaticLabel(mainApp, R.string.location))
|
||||||
|
.add(LabelWithElement(mainApp, resourceHelper.gs(R.string.name_short), "", name))
|
||||||
|
.add(LabelWithElement(mainApp, resourceHelper.gs(R.string.latitude_short), "", latitude))
|
||||||
|
.add(LabelWithElement(mainApp, resourceHelper.gs(R.string.longitude_short), "", longitude))
|
||||||
|
.add(LabelWithElement(mainApp, resourceHelper.gs(R.string.distance_short), "", distance))
|
||||||
|
.add(LabelWithElement(mainApp, resourceHelper.gs(R.string.location_mode), "", modeSelected))
|
||||||
|
.add(InputButton(mainApp, resourceHelper.gs(R.string.currentlocation), buttonAction), locationService.lastLocation != null)
|
||||||
|
.build(root)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Method to return the actual mode based on the current distance
|
||||||
|
fun currentMode(currentDistance: Double): InputLocationMode.Mode {
|
||||||
|
return if (currentDistance <= distance.value) InputLocationMode.Mode.INSIDE else InputLocationMode.Mode.OUTSIDE
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,152 +0,0 @@
|
||||||
package info.nightscout.androidaps.plugins.general.automation.triggers;
|
|
||||||
|
|
||||||
import android.widget.LinearLayout;
|
|
||||||
|
|
||||||
import androidx.fragment.app.FragmentManager;
|
|
||||||
|
|
||||||
import com.google.common.base.Optional;
|
|
||||||
|
|
||||||
import org.json.JSONException;
|
|
||||||
import org.json.JSONObject;
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
import info.nightscout.androidaps.MainApp;
|
|
||||||
import info.nightscout.androidaps.R;
|
|
||||||
import info.nightscout.androidaps.data.Profile;
|
|
||||||
import info.nightscout.androidaps.logging.L;
|
|
||||||
import info.nightscout.androidaps.plugins.configBuilder.ProfileFunctions;
|
|
||||||
import info.nightscout.androidaps.plugins.general.automation.elements.Comparator;
|
|
||||||
import info.nightscout.androidaps.plugins.general.automation.elements.InputPercent;
|
|
||||||
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.elements.StaticLabel;
|
|
||||||
import info.nightscout.androidaps.utils.DateUtil;
|
|
||||||
import info.nightscout.androidaps.utils.JsonHelper;
|
|
||||||
import info.nightscout.androidaps.utils.T;
|
|
||||||
|
|
||||||
public class TriggerProfilePercent extends Trigger {
|
|
||||||
private static Logger log = LoggerFactory.getLogger(L.AUTOMATION);
|
|
||||||
|
|
||||||
private InputPercent pct = new InputPercent();
|
|
||||||
private Comparator comparator = new Comparator();
|
|
||||||
|
|
||||||
public TriggerProfilePercent() {
|
|
||||||
super();
|
|
||||||
}
|
|
||||||
|
|
||||||
private TriggerProfilePercent(TriggerProfilePercent triggerProfilePercent) {
|
|
||||||
super();
|
|
||||||
pct = new InputPercent(triggerProfilePercent.pct);
|
|
||||||
comparator = new Comparator(triggerProfilePercent.comparator);
|
|
||||||
lastRun = triggerProfilePercent.lastRun;
|
|
||||||
}
|
|
||||||
|
|
||||||
public double getValue() {
|
|
||||||
return pct.getValue();
|
|
||||||
}
|
|
||||||
|
|
||||||
public Comparator getComparator() {
|
|
||||||
return comparator;
|
|
||||||
}
|
|
||||||
|
|
||||||
public long getLastRun() {
|
|
||||||
return lastRun;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public synchronized boolean shouldRun() {
|
|
||||||
if (lastRun > DateUtil.now() - T.mins(5).msecs())
|
|
||||||
return false;
|
|
||||||
|
|
||||||
Profile profile = ProfileFunctions.getInstance().getProfile();
|
|
||||||
if (profile == null && comparator.getValue().equals(Comparator.Compare.IS_NOT_AVAILABLE)) {
|
|
||||||
if (L.isEnabled(L.AUTOMATION))
|
|
||||||
log.debug("Ready for execution: " + friendlyDescription());
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (profile == null)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
boolean doRun = comparator.getValue().check((double) profile.getPercentage(), pct.getValue());
|
|
||||||
if (doRun) {
|
|
||||||
if (L.isEnabled(L.AUTOMATION))
|
|
||||||
log.debug("Ready for execution: " + friendlyDescription());
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public synchronized String toJSON() {
|
|
||||||
JSONObject o = new JSONObject();
|
|
||||||
try {
|
|
||||||
o.put("type", TriggerProfilePercent.class.getName());
|
|
||||||
JSONObject data = new JSONObject();
|
|
||||||
data.put("percentage", pct.getValue());
|
|
||||||
data.put("lastRun", lastRun);
|
|
||||||
data.put("comparator", comparator.getValue().toString());
|
|
||||||
o.put("data", data);
|
|
||||||
} catch (JSONException e) {
|
|
||||||
log.error("Unhandled exception", e);
|
|
||||||
}
|
|
||||||
return o.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
Trigger fromJSON(String data) {
|
|
||||||
try {
|
|
||||||
JSONObject d = new JSONObject(data);
|
|
||||||
pct.setValue(JsonHelper.safeGetDouble(d, "percentage"));
|
|
||||||
lastRun = JsonHelper.safeGetLong(d, "lastRun");
|
|
||||||
comparator.setValue(Comparator.Compare.valueOf(JsonHelper.safeGetString(d, "comparator")));
|
|
||||||
} catch (Exception e) {
|
|
||||||
log.error("Unhandled exception", e);
|
|
||||||
}
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int friendlyName() {
|
|
||||||
return R.string.profilepercentage;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String friendlyDescription() {
|
|
||||||
return MainApp.gs(R.string.percentagecompared, MainApp.gs(comparator.getValue().getStringRes()), (int) pct.getValue());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Optional<Integer> icon() {
|
|
||||||
return Optional.of(R.drawable.icon_actions_profileswitch);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Trigger duplicate() {
|
|
||||||
return new TriggerProfilePercent(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
public TriggerProfilePercent setValue(double value) {
|
|
||||||
pct.setValue(value);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
TriggerProfilePercent lastRun(long lastRun) {
|
|
||||||
this.lastRun = lastRun;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public TriggerProfilePercent comparator(Comparator.Compare compare) {
|
|
||||||
this.comparator = new Comparator().setValue(compare);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void generateDialog(LinearLayout root, FragmentManager fragmentManager) {
|
|
||||||
new LayoutBuilder()
|
|
||||||
.add(new StaticLabel(R.string.profilepercentage))
|
|
||||||
.add(comparator)
|
|
||||||
.add(new LabelWithElement(MainApp.gs(R.string.percent_u), "", pct))
|
|
||||||
.build(root);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -0,0 +1,81 @@
|
||||||
|
package info.nightscout.androidaps.plugins.general.automation.triggers
|
||||||
|
|
||||||
|
import android.widget.LinearLayout
|
||||||
|
import com.google.common.base.Optional
|
||||||
|
import info.nightscout.androidaps.MainApp
|
||||||
|
import info.nightscout.androidaps.R
|
||||||
|
import info.nightscout.androidaps.logging.LTag
|
||||||
|
import info.nightscout.androidaps.plugins.general.automation.elements.Comparator
|
||||||
|
import info.nightscout.androidaps.plugins.general.automation.elements.InputPercent
|
||||||
|
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.elements.StaticLabel
|
||||||
|
import info.nightscout.androidaps.utils.JsonHelper
|
||||||
|
import org.json.JSONObject
|
||||||
|
|
||||||
|
class TriggerProfilePercent(mainApp: MainApp) : Trigger(mainApp) {
|
||||||
|
private var pct = InputPercent(mainApp)
|
||||||
|
var comparator = Comparator(mainApp)
|
||||||
|
|
||||||
|
constructor(mainApp: MainApp, value: Double, compare: Comparator.Compare) : this(mainApp) {
|
||||||
|
pct = InputPercent(mainApp, value)
|
||||||
|
comparator = Comparator(mainApp, compare)
|
||||||
|
}
|
||||||
|
|
||||||
|
constructor(mainApp: MainApp, triggerProfilePercent: TriggerProfilePercent) : this(mainApp) {
|
||||||
|
pct = InputPercent(mainApp, triggerProfilePercent.pct.value)
|
||||||
|
comparator = Comparator(mainApp, triggerProfilePercent.comparator.value)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun shouldRun(): Boolean {
|
||||||
|
val profile = profileFunction.getProfile()
|
||||||
|
if (profile == null && comparator.value == Comparator.Compare.IS_NOT_AVAILABLE) {
|
||||||
|
aapsLogger.debug(LTag.AUTOMATION, "Ready for execution: " + friendlyDescription())
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
if (profile == null) {
|
||||||
|
aapsLogger.debug(LTag.AUTOMATION, "NOT ready for execution: " + friendlyDescription())
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if (comparator.value.check(profile.percentage.toDouble(), pct.value)) {
|
||||||
|
aapsLogger.debug(LTag.AUTOMATION, "Ready for execution: " + friendlyDescription())
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
aapsLogger.debug(LTag.AUTOMATION, "NOT ready for execution: " + friendlyDescription())
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
@Synchronized override fun toJSON(): String {
|
||||||
|
val data = JSONObject()
|
||||||
|
.put("percentage", pct.value)
|
||||||
|
.put("comparator", comparator.value.toString())
|
||||||
|
return JSONObject()
|
||||||
|
.put("type", this::class.java.name)
|
||||||
|
.put("data", data)
|
||||||
|
.toString()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun fromJSON(data: String): Trigger {
|
||||||
|
val d = JSONObject(data)
|
||||||
|
pct.value = JsonHelper.safeGetDouble(d, "percentage")
|
||||||
|
comparator.setValue(Comparator.Compare.valueOf(JsonHelper.safeGetString(d, "comparator")!!))
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun friendlyName(): Int = R.string.profilepercentage
|
||||||
|
|
||||||
|
override fun friendlyDescription(): String =
|
||||||
|
resourceHelper.gs(R.string.percentagecompared, resourceHelper.gs(comparator.value.stringRes), pct.value.toInt())
|
||||||
|
|
||||||
|
override fun icon(): Optional<Int?> = Optional.of(R.drawable.icon_actions_profileswitch)
|
||||||
|
|
||||||
|
override fun duplicate(): Trigger = TriggerProfilePercent(mainApp, this)
|
||||||
|
|
||||||
|
override fun generateDialog(root: LinearLayout) {
|
||||||
|
LayoutBuilder()
|
||||||
|
.add(StaticLabel(mainApp, R.string.profilepercentage))
|
||||||
|
.add(comparator)
|
||||||
|
.add(LabelWithElement(mainApp, resourceHelper.gs(R.string.percent_u), "", pct))
|
||||||
|
.build(root)
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,146 +0,0 @@
|
||||||
package info.nightscout.androidaps.plugins.general.automation.triggers;
|
|
||||||
|
|
||||||
import android.widget.LinearLayout;
|
|
||||||
|
|
||||||
import androidx.fragment.app.FragmentManager;
|
|
||||||
|
|
||||||
import com.google.common.base.Optional;
|
|
||||||
|
|
||||||
import org.json.JSONException;
|
|
||||||
import org.json.JSONObject;
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
import info.nightscout.androidaps.MainApp;
|
|
||||||
import info.nightscout.androidaps.R;
|
|
||||||
import info.nightscout.androidaps.logging.L;
|
|
||||||
import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin;
|
|
||||||
import info.nightscout.androidaps.plugins.general.automation.elements.Comparator;
|
|
||||||
import info.nightscout.androidaps.plugins.general.automation.elements.InputDuration;
|
|
||||||
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.elements.StaticLabel;
|
|
||||||
import info.nightscout.androidaps.utils.DateUtil;
|
|
||||||
import info.nightscout.androidaps.utils.JsonHelper;
|
|
||||||
import info.nightscout.androidaps.utils.T;
|
|
||||||
|
|
||||||
public class TriggerPumpLastConnection extends Trigger {
|
|
||||||
private static Logger log = LoggerFactory.getLogger(L.AUTOMATION);
|
|
||||||
private InputDuration minutesAgo = new InputDuration(0, InputDuration.TimeUnit.MINUTES);
|
|
||||||
private Comparator comparator = new Comparator();
|
|
||||||
|
|
||||||
public TriggerPumpLastConnection() {
|
|
||||||
super();
|
|
||||||
}
|
|
||||||
|
|
||||||
private TriggerPumpLastConnection(TriggerPumpLastConnection triggerPumpLastConnection) {
|
|
||||||
super();
|
|
||||||
minutesAgo = new InputDuration(triggerPumpLastConnection.minutesAgo);
|
|
||||||
lastRun = triggerPumpLastConnection.lastRun;
|
|
||||||
comparator = new Comparator(triggerPumpLastConnection.comparator);
|
|
||||||
}
|
|
||||||
|
|
||||||
public double getValue() {
|
|
||||||
return minutesAgo.getValue();
|
|
||||||
}
|
|
||||||
|
|
||||||
public Comparator getComparator() {
|
|
||||||
return comparator;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public synchronized boolean shouldRun() {
|
|
||||||
|
|
||||||
if (lastRun > DateUtil.now() - T.mins(5).msecs())
|
|
||||||
return false;
|
|
||||||
long lastConnection = ConfigBuilderPlugin.getPlugin().getActivePump().lastDataTime();
|
|
||||||
|
|
||||||
if (lastConnection == 0 && comparator.getValue() == Comparator.Compare.IS_NOT_AVAILABLE)
|
|
||||||
return true;
|
|
||||||
|
|
||||||
double minutesAgo = (double) (DateUtil.now() - lastConnection) / (60 * 1000);
|
|
||||||
if (L.isEnabled(L.AUTOMATION))
|
|
||||||
log.debug("Last connection min ago: " + minutesAgo);
|
|
||||||
|
|
||||||
boolean doRun = comparator.getValue().check((minutesAgo), getValue());
|
|
||||||
if (doRun) {
|
|
||||||
if (L.isEnabled(L.AUTOMATION))
|
|
||||||
log.debug("Ready for execution: " + friendlyDescription());
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public synchronized String toJSON() {
|
|
||||||
JSONObject o = new JSONObject();
|
|
||||||
try {
|
|
||||||
o.put("type", TriggerPumpLastConnection.class.getName());
|
|
||||||
JSONObject data = new JSONObject();
|
|
||||||
data.put("minutesAgo", getValue());
|
|
||||||
data.put("lastRun", lastRun);
|
|
||||||
data.put("comparator", comparator.getValue().toString());
|
|
||||||
o.put("data", data);
|
|
||||||
} catch (JSONException e) {
|
|
||||||
log.error("Unhandled exception", e);
|
|
||||||
}
|
|
||||||
return o.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
Trigger fromJSON(String data) {
|
|
||||||
try {
|
|
||||||
JSONObject d = new JSONObject(data);
|
|
||||||
minutesAgo.setMinutes(JsonHelper.safeGetInt(d, "minutesAgo"));
|
|
||||||
lastRun = JsonHelper.safeGetLong(d, "lastRun");
|
|
||||||
comparator.setValue(Comparator.Compare.valueOf(JsonHelper.safeGetString(d, "comparator")));
|
|
||||||
} catch (Exception e) {
|
|
||||||
log.error("Unhandled exception", e);
|
|
||||||
}
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int friendlyName() {
|
|
||||||
return R.string.automation_trigger_pump_last_connection_label;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String friendlyDescription() {
|
|
||||||
return MainApp.gs(R.string.automation_trigger_pump_last_connection_compared, MainApp.gs(comparator.getValue().getStringRes()), (int) getValue());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Optional<Integer> icon() {
|
|
||||||
return Optional.of(R.drawable.remove);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Trigger duplicate() {
|
|
||||||
return new TriggerPumpLastConnection(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
TriggerPumpLastConnection setValue(int requestedValue) {
|
|
||||||
this.minutesAgo.setMinutes(requestedValue);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
TriggerPumpLastConnection lastRun(long lastRun) {
|
|
||||||
this.lastRun = lastRun;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
TriggerPumpLastConnection comparator(Comparator.Compare compare) {
|
|
||||||
this.comparator = new Comparator().setValue(compare);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void generateDialog(LinearLayout root, FragmentManager fragmentManager) {
|
|
||||||
new LayoutBuilder()
|
|
||||||
.add(new StaticLabel(R.string.automation_trigger_pump_last_connection_label))
|
|
||||||
.add(comparator)
|
|
||||||
.add(new LabelWithElement(MainApp.gs(R.string.automation_trigger_pump_last_connection_description) + ": ", "", minutesAgo))
|
|
||||||
.build(root);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -0,0 +1,81 @@
|
||||||
|
package info.nightscout.androidaps.plugins.general.automation.triggers
|
||||||
|
|
||||||
|
import android.widget.LinearLayout
|
||||||
|
import com.google.common.base.Optional
|
||||||
|
import info.nightscout.androidaps.MainApp
|
||||||
|
import info.nightscout.androidaps.R
|
||||||
|
import info.nightscout.androidaps.logging.LTag
|
||||||
|
import info.nightscout.androidaps.plugins.general.automation.elements.Comparator
|
||||||
|
import info.nightscout.androidaps.plugins.general.automation.elements.InputDuration
|
||||||
|
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.elements.StaticLabel
|
||||||
|
import info.nightscout.androidaps.utils.DateUtil
|
||||||
|
import info.nightscout.androidaps.utils.JsonHelper.safeGetInt
|
||||||
|
import info.nightscout.androidaps.utils.JsonHelper.safeGetString
|
||||||
|
import org.json.JSONObject
|
||||||
|
|
||||||
|
class TriggerPumpLastConnection(mainApp: MainApp) : Trigger(mainApp) {
|
||||||
|
private var minutesAgo = InputDuration(mainApp)
|
||||||
|
private var comparator = Comparator(mainApp)
|
||||||
|
|
||||||
|
constructor(mainApp: MainApp, value: Int, unit: InputDuration.TimeUnit, compare: Comparator.Compare) : this(mainApp) {
|
||||||
|
minutesAgo = InputDuration(mainApp, value, unit)
|
||||||
|
comparator = Comparator(mainApp, compare)
|
||||||
|
}
|
||||||
|
|
||||||
|
constructor(mainApp: MainApp, triggerPumpLastConnection: TriggerPumpLastConnection) : this(mainApp) {
|
||||||
|
minutesAgo = InputDuration(mainApp, triggerPumpLastConnection.minutesAgo.value, triggerPumpLastConnection.minutesAgo.unit)
|
||||||
|
comparator = Comparator(mainApp, triggerPumpLastConnection.comparator.value)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun shouldRun(): Boolean {
|
||||||
|
val lastConnection = configBuilderPlugin.activePump?.lastDataTime() ?: return false
|
||||||
|
if (lastConnection == 0L && comparator.value === Comparator.Compare.IS_NOT_AVAILABLE) {
|
||||||
|
aapsLogger.debug(LTag.AUTOMATION, "Ready for execution: " + friendlyDescription())
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
val connectionAgo = (DateUtil.now() - lastConnection) / (60 * 1000)
|
||||||
|
aapsLogger.debug(LTag.AUTOMATION, "Last connection min ago: $connectionAgo")
|
||||||
|
if (comparator.value.check(connectionAgo.toInt(), minutesAgo.value)) {
|
||||||
|
aapsLogger.debug(LTag.AUTOMATION, "Ready for execution: " + friendlyDescription())
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
aapsLogger.debug(LTag.AUTOMATION, "NOT ready for execution: " + friendlyDescription())
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun toJSON(): String {
|
||||||
|
val data = JSONObject()
|
||||||
|
.put("minutesAgo", minutesAgo.value)
|
||||||
|
.put("comparator", comparator.value.toString())
|
||||||
|
return JSONObject()
|
||||||
|
.put("type", this::class.java.name)
|
||||||
|
.put("data", data)
|
||||||
|
.toString()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun fromJSON(data: String): Trigger {
|
||||||
|
val d = JSONObject(data)
|
||||||
|
minutesAgo.setMinutes(safeGetInt(d, "minutesAgo"))
|
||||||
|
comparator.setValue(Comparator.Compare.valueOf(safeGetString(d, "comparator")!!))
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun friendlyName(): Int = R.string.automation_trigger_pump_last_connection_label
|
||||||
|
|
||||||
|
override fun friendlyDescription(): String =
|
||||||
|
resourceHelper.gs(R.string.automation_trigger_pump_last_connection_compared, resourceHelper.gs(comparator.value.stringRes), minutesAgo.value)
|
||||||
|
|
||||||
|
override fun icon(): Optional<Int?> = Optional.of(R.drawable.remove)
|
||||||
|
|
||||||
|
override fun duplicate(): Trigger = TriggerPumpLastConnection(mainApp, this)
|
||||||
|
|
||||||
|
override fun generateDialog(root: LinearLayout) {
|
||||||
|
LayoutBuilder()
|
||||||
|
.add(StaticLabel(mainApp, R.string.automation_trigger_pump_last_connection_label))
|
||||||
|
.add(comparator)
|
||||||
|
.add(LabelWithElement(mainApp, resourceHelper.gs(R.string.automation_trigger_pump_last_connection_description) + ": ", "", minutesAgo))
|
||||||
|
.build(root)
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,319 +0,0 @@
|
||||||
package info.nightscout.androidaps.plugins.general.automation.triggers;
|
|
||||||
|
|
||||||
import android.graphics.Typeface;
|
|
||||||
import android.text.format.DateFormat;
|
|
||||||
import android.view.ViewGroup;
|
|
||||||
import android.widget.LinearLayout;
|
|
||||||
import android.widget.TextView;
|
|
||||||
|
|
||||||
import androidx.annotation.Nullable;
|
|
||||||
import androidx.annotation.StringRes;
|
|
||||||
import androidx.appcompat.app.AppCompatActivity;
|
|
||||||
import androidx.fragment.app.FragmentManager;
|
|
||||||
|
|
||||||
import com.dpro.widgets.WeekdaysPicker;
|
|
||||||
import com.google.common.base.Optional;
|
|
||||||
import com.wdullaer.materialdatetimepicker.time.TimePickerDialog;
|
|
||||||
|
|
||||||
import org.json.JSONException;
|
|
||||||
import org.json.JSONObject;
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Calendar;
|
|
||||||
import java.util.GregorianCalendar;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Objects;
|
|
||||||
|
|
||||||
import info.nightscout.androidaps.MainApp;
|
|
||||||
import info.nightscout.androidaps.R;
|
|
||||||
import info.nightscout.androidaps.logging.L;
|
|
||||||
import info.nightscout.androidaps.utils.DateUtil;
|
|
||||||
import info.nightscout.androidaps.utils.JsonHelper;
|
|
||||||
import info.nightscout.androidaps.utils.T;
|
|
||||||
|
|
||||||
public class TriggerRecurringTime extends Trigger {
|
|
||||||
private static Logger log = LoggerFactory.getLogger(L.AUTOMATION);
|
|
||||||
|
|
||||||
public enum DayOfWeek {
|
|
||||||
MONDAY,
|
|
||||||
TUESDAY,
|
|
||||||
WEDNESDAY,
|
|
||||||
THURSDAY,
|
|
||||||
FRIDAY,
|
|
||||||
SATURDAY,
|
|
||||||
SUNDAY;
|
|
||||||
|
|
||||||
private static final int[] calendarInts = new int[]{
|
|
||||||
Calendar.MONDAY,
|
|
||||||
Calendar.TUESDAY,
|
|
||||||
Calendar.WEDNESDAY,
|
|
||||||
Calendar.THURSDAY,
|
|
||||||
Calendar.FRIDAY,
|
|
||||||
Calendar.SATURDAY,
|
|
||||||
Calendar.SUNDAY
|
|
||||||
};
|
|
||||||
|
|
||||||
private static final int[] shortNames = new int[]{
|
|
||||||
R.string.weekday_monday_short,
|
|
||||||
R.string.weekday_tuesday_short,
|
|
||||||
R.string.weekday_wednesday_short,
|
|
||||||
R.string.weekday_thursday_short,
|
|
||||||
R.string.weekday_friday_short,
|
|
||||||
R.string.weekday_saturday_short,
|
|
||||||
R.string.weekday_sunday_short
|
|
||||||
};
|
|
||||||
|
|
||||||
public int toCalendarInt() {
|
|
||||||
return calendarInts[ordinal()];
|
|
||||||
}
|
|
||||||
|
|
||||||
@Nullable
|
|
||||||
public static DayOfWeek fromCalendarInt(int day) {
|
|
||||||
for (int i = 0; i < calendarInts.length; ++i) {
|
|
||||||
if (calendarInts[i] == day)
|
|
||||||
return values()[i];
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public @StringRes
|
|
||||||
int getShortName() {
|
|
||||||
return shortNames[ordinal()];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private final boolean[] weekdays = new boolean[DayOfWeek.values().length];
|
|
||||||
|
|
||||||
// Recurring
|
|
||||||
private int hour;
|
|
||||||
private int minute;
|
|
||||||
|
|
||||||
private long validTo;
|
|
||||||
|
|
||||||
public TriggerRecurringTime() {
|
|
||||||
super();
|
|
||||||
setAll(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
private TriggerRecurringTime(TriggerRecurringTime triggerTime) {
|
|
||||||
super();
|
|
||||||
lastRun = triggerTime.lastRun;
|
|
||||||
hour = triggerTime.hour;
|
|
||||||
minute = triggerTime.minute;
|
|
||||||
validTo = triggerTime.validTo;
|
|
||||||
|
|
||||||
if (weekdays.length >= 0)
|
|
||||||
System.arraycopy(triggerTime.weekdays, 0, weekdays, 0, weekdays.length);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setAll(boolean value) {
|
|
||||||
for (DayOfWeek day : DayOfWeek.values()) {
|
|
||||||
set(day, value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public TriggerRecurringTime set(DayOfWeek day, boolean value) {
|
|
||||||
weekdays[day.ordinal()] = value;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean isSet(DayOfWeek day) {
|
|
||||||
return weekdays[day.ordinal()];
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean shouldRun() {
|
|
||||||
if (validTo != 0 && DateUtil.now() > validTo)
|
|
||||||
return false;
|
|
||||||
Calendar c = Calendar.getInstance();
|
|
||||||
int scheduledDayOfWeek = c.get(Calendar.DAY_OF_WEEK);
|
|
||||||
|
|
||||||
Calendar scheduledCal = DateUtil.gregorianCalendar();
|
|
||||||
scheduledCal.set(Calendar.HOUR_OF_DAY, hour);
|
|
||||||
scheduledCal.set(Calendar.MINUTE, minute);
|
|
||||||
scheduledCal.set(Calendar.SECOND, 0);
|
|
||||||
long scheduled = scheduledCal.getTimeInMillis();
|
|
||||||
|
|
||||||
if (isSet(Objects.requireNonNull(DayOfWeek.fromCalendarInt(scheduledDayOfWeek)))) {
|
|
||||||
if (DateUtil.now() >= scheduled && DateUtil.now() - scheduled < T.mins(5).msecs()) {
|
|
||||||
if (lastRun < scheduled) {
|
|
||||||
if (L.isEnabled(L.AUTOMATION))
|
|
||||||
log.debug("Ready for execution: " + friendlyDescription());
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toJSON() {
|
|
||||||
JSONObject object = new JSONObject();
|
|
||||||
JSONObject data = new JSONObject();
|
|
||||||
try {
|
|
||||||
data.put("lastRun", lastRun);
|
|
||||||
for (int i = 0; i < weekdays.length; ++i) {
|
|
||||||
data.put(DayOfWeek.values()[i].name(), weekdays[i]);
|
|
||||||
}
|
|
||||||
data.put("hour", hour);
|
|
||||||
data.put("minute", minute);
|
|
||||||
data.put("validTo", validTo);
|
|
||||||
object.put("type", TriggerRecurringTime.class.getName());
|
|
||||||
object.put("data", data);
|
|
||||||
} catch (JSONException e) {
|
|
||||||
log.error("Unhandled exception", e);
|
|
||||||
}
|
|
||||||
return object.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
Trigger fromJSON(String data) {
|
|
||||||
JSONObject o;
|
|
||||||
try {
|
|
||||||
o = new JSONObject(data);
|
|
||||||
lastRun = JsonHelper.safeGetLong(o, "lastRun");
|
|
||||||
for (int i = 0; i < weekdays.length; ++i) {
|
|
||||||
weekdays[i] = JsonHelper.safeGetBoolean(o, DayOfWeek.values()[i].name());
|
|
||||||
}
|
|
||||||
hour = JsonHelper.safeGetInt(o, "hour");
|
|
||||||
minute = JsonHelper.safeGetInt(o, "minute");
|
|
||||||
validTo = JsonHelper.safeGetLong(o, "validTo");
|
|
||||||
} catch (JSONException e) {
|
|
||||||
log.error("Unhandled exception", e);
|
|
||||||
}
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int friendlyName() {
|
|
||||||
return R.string.recurringTime;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String friendlyDescription() {
|
|
||||||
int counter = 0;
|
|
||||||
StringBuilder sb = new StringBuilder();
|
|
||||||
sb.append(MainApp.gs(R.string.every));
|
|
||||||
sb.append(" ");
|
|
||||||
for (Integer i : getSelectedDays()) {
|
|
||||||
if (counter > 0)
|
|
||||||
sb.append(",");
|
|
||||||
sb.append(MainApp.gs(Objects.requireNonNull(DayOfWeek.fromCalendarInt(i)).getShortName()));
|
|
||||||
counter++;
|
|
||||||
}
|
|
||||||
sb.append(" ");
|
|
||||||
|
|
||||||
Calendar scheduledCal = DateUtil.gregorianCalendar();
|
|
||||||
scheduledCal.set(Calendar.HOUR_OF_DAY, hour);
|
|
||||||
scheduledCal.set(Calendar.MINUTE, minute);
|
|
||||||
scheduledCal.set(Calendar.SECOND, 0);
|
|
||||||
long scheduled = scheduledCal.getTimeInMillis();
|
|
||||||
|
|
||||||
sb.append(DateUtil.timeString(scheduled));
|
|
||||||
|
|
||||||
if (counter == 0)
|
|
||||||
return MainApp.gs(R.string.never);
|
|
||||||
return sb.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Optional<Integer> icon() {
|
|
||||||
return Optional.of(R.drawable.ic_access_alarm_24dp);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Trigger duplicate() {
|
|
||||||
return new TriggerRecurringTime(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
TriggerRecurringTime lastRun(long lastRun) {
|
|
||||||
this.lastRun = lastRun;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressWarnings("SameParameterValue")
|
|
||||||
TriggerRecurringTime validTo(long validTo) {
|
|
||||||
this.validTo = validTo;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
TriggerRecurringTime hour(int hour) {
|
|
||||||
this.hour = hour;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
TriggerRecurringTime minute(int minute) {
|
|
||||||
this.minute = minute;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
private List<Integer> getSelectedDays() {
|
|
||||||
List<Integer> selectedDays = new ArrayList<>();
|
|
||||||
for (int i = 0; i < weekdays.length; ++i) {
|
|
||||||
DayOfWeek day = DayOfWeek.values()[i];
|
|
||||||
boolean selected = weekdays[i];
|
|
||||||
if (selected) selectedDays.add(day.toCalendarInt());
|
|
||||||
}
|
|
||||||
return selectedDays;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void generateDialog(LinearLayout root, FragmentManager fragmentManager) {
|
|
||||||
TextView label = new TextView(root.getContext());
|
|
||||||
|
|
||||||
// TODO: Replace external tool WeekdaysPicker with a self-made GUI element
|
|
||||||
WeekdaysPicker weekdaysPicker = new WeekdaysPicker(root.getContext());
|
|
||||||
weekdaysPicker.setEditable(true);
|
|
||||||
weekdaysPicker.setSelectedDays(getSelectedDays());
|
|
||||||
weekdaysPicker.setOnWeekdaysChangeListener((view, i, list) -> set(DayOfWeek.fromCalendarInt(i), list.contains(i)));
|
|
||||||
weekdaysPicker.setLayoutParams(new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT));
|
|
||||||
weekdaysPicker.setSundayFirstDay(Calendar.getInstance().getFirstDayOfWeek() == Calendar.SUNDAY);
|
|
||||||
weekdaysPicker.redrawDays();
|
|
||||||
|
|
||||||
root.addView(weekdaysPicker);
|
|
||||||
|
|
||||||
TextView timeButton = new TextView(root.getContext());
|
|
||||||
|
|
||||||
GregorianCalendar runAt = new GregorianCalendar();
|
|
||||||
//Date runAt = new Date();
|
|
||||||
runAt.set(Calendar.HOUR_OF_DAY, hour);
|
|
||||||
runAt.set(Calendar.MINUTE, minute);
|
|
||||||
timeButton.setText(DateUtil.timeString(runAt.getTimeInMillis()));
|
|
||||||
timeButton.setOnClickListener(view -> {
|
|
||||||
TimePickerDialog tpd = TimePickerDialog.newInstance(
|
|
||||||
(view12, hourOfDay, minute, second) -> {
|
|
||||||
hour(hourOfDay);
|
|
||||||
minute(minute);
|
|
||||||
runAt.set(Calendar.HOUR_OF_DAY, hour);
|
|
||||||
runAt.set(Calendar.MINUTE, minute);
|
|
||||||
timeButton.setText(DateUtil.timeString(runAt.getTimeInMillis()));
|
|
||||||
},
|
|
||||||
runAt.get(Calendar.HOUR_OF_DAY),
|
|
||||||
runAt.get(Calendar.MINUTE),
|
|
||||||
DateFormat.is24HourFormat(root.getContext())
|
|
||||||
);
|
|
||||||
tpd.setThemeDark(true);
|
|
||||||
tpd.dismissOnPause(true);
|
|
||||||
AppCompatActivity a = scanForActivity(root.getContext());
|
|
||||||
if (a != null)
|
|
||||||
tpd.show(a.getSupportFragmentManager(), "TimePickerDialog");
|
|
||||||
});
|
|
||||||
|
|
||||||
int px = MainApp.dpToPx(10);
|
|
||||||
label.setText(MainApp.gs(R.string.atspecifiedtime, ""));
|
|
||||||
label.setTypeface(label.getTypeface(), Typeface.BOLD);
|
|
||||||
label.setPadding(px, px, px, px);
|
|
||||||
timeButton.setPadding(px, px, px, px);
|
|
||||||
|
|
||||||
LinearLayout l = new LinearLayout(root.getContext());
|
|
||||||
l.setOrientation(LinearLayout.HORIZONTAL);
|
|
||||||
l.setLayoutParams(new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT));
|
|
||||||
|
|
||||||
l.addView(label);
|
|
||||||
l.addView(timeButton);
|
|
||||||
root.addView(l);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -0,0 +1,211 @@
|
||||||
|
package info.nightscout.androidaps.plugins.general.automation.triggers
|
||||||
|
|
||||||
|
import android.app.TimePickerDialog
|
||||||
|
import android.graphics.Typeface
|
||||||
|
import android.text.format.DateFormat
|
||||||
|
import android.view.View
|
||||||
|
import android.view.ViewGroup
|
||||||
|
import android.widget.LinearLayout
|
||||||
|
import android.widget.TextView
|
||||||
|
import androidx.annotation.StringRes
|
||||||
|
import com.dpro.widgets.WeekdaysPicker
|
||||||
|
import com.google.common.base.Optional
|
||||||
|
import info.nightscout.androidaps.MainApp
|
||||||
|
import info.nightscout.androidaps.R
|
||||||
|
import info.nightscout.androidaps.logging.LTag
|
||||||
|
import info.nightscout.androidaps.utils.DateUtil
|
||||||
|
import info.nightscout.androidaps.utils.JsonHelper
|
||||||
|
import info.nightscout.androidaps.utils.T
|
||||||
|
import org.json.JSONObject
|
||||||
|
import java.util.*
|
||||||
|
|
||||||
|
class TriggerRecurringTime(mainApp: MainApp) : Trigger(mainApp) {
|
||||||
|
enum class DayOfWeek {
|
||||||
|
MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY;
|
||||||
|
|
||||||
|
fun toCalendarInt(): Int {
|
||||||
|
return calendarInts[ordinal]
|
||||||
|
}
|
||||||
|
|
||||||
|
@get:StringRes val shortName: Int
|
||||||
|
get() = shortNames[ordinal]
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
private val calendarInts = intArrayOf(
|
||||||
|
Calendar.MONDAY,
|
||||||
|
Calendar.TUESDAY,
|
||||||
|
Calendar.WEDNESDAY,
|
||||||
|
Calendar.THURSDAY,
|
||||||
|
Calendar.FRIDAY,
|
||||||
|
Calendar.SATURDAY,
|
||||||
|
Calendar.SUNDAY
|
||||||
|
)
|
||||||
|
private val shortNames = intArrayOf(
|
||||||
|
R.string.weekday_monday_short,
|
||||||
|
R.string.weekday_tuesday_short,
|
||||||
|
R.string.weekday_wednesday_short,
|
||||||
|
R.string.weekday_thursday_short,
|
||||||
|
R.string.weekday_friday_short,
|
||||||
|
R.string.weekday_saturday_short,
|
||||||
|
R.string.weekday_sunday_short
|
||||||
|
)
|
||||||
|
|
||||||
|
fun fromCalendarInt(day: Int): DayOfWeek {
|
||||||
|
for (i in calendarInts.indices) {
|
||||||
|
if (calendarInts[i] == day) return values()[i]
|
||||||
|
}
|
||||||
|
throw IllegalStateException("Invalid day")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private val weekdays = BooleanArray(DayOfWeek.values().size)
|
||||||
|
private var hour = 0
|
||||||
|
private var minute = 0
|
||||||
|
private var validTo: Long = 0
|
||||||
|
|
||||||
|
constructor(mainApp: MainApp, triggerRecurringTime: TriggerRecurringTime) : this(mainApp) {
|
||||||
|
this.hour = triggerRecurringTime.hour
|
||||||
|
this.minute = triggerRecurringTime.minute
|
||||||
|
this.validTo = triggerRecurringTime.validTo
|
||||||
|
if (weekdays.size >= 0)
|
||||||
|
System.arraycopy(triggerRecurringTime.weekdays, 0, weekdays, 0, triggerRecurringTime.weekdays.size)
|
||||||
|
}
|
||||||
|
|
||||||
|
init {
|
||||||
|
for (day in DayOfWeek.values()) set(day, false)
|
||||||
|
}
|
||||||
|
|
||||||
|
operator fun set(day: DayOfWeek, value: Boolean): TriggerRecurringTime {
|
||||||
|
weekdays[day.ordinal] = value
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun isSet(day: DayOfWeek): Boolean = weekdays[day.ordinal]
|
||||||
|
|
||||||
|
override fun shouldRun(): Boolean {
|
||||||
|
if (validTo != 0L && DateUtil.now() > validTo) return false
|
||||||
|
val c = Calendar.getInstance()
|
||||||
|
val scheduledDayOfWeek = c[Calendar.DAY_OF_WEEK]
|
||||||
|
val scheduledCal: Calendar = DateUtil.gregorianCalendar()
|
||||||
|
scheduledCal[Calendar.HOUR_OF_DAY] = hour
|
||||||
|
scheduledCal[Calendar.MINUTE] = minute
|
||||||
|
scheduledCal[Calendar.SECOND] = 0
|
||||||
|
val scheduled = scheduledCal.timeInMillis
|
||||||
|
if (isSet(Objects.requireNonNull(DayOfWeek.fromCalendarInt(scheduledDayOfWeek)))) {
|
||||||
|
if (DateUtil.now() >= scheduled && DateUtil.now() - scheduled < T.mins(5).msecs()) {
|
||||||
|
aapsLogger.debug(LTag.AUTOMATION, "Ready for execution: " + friendlyDescription())
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
aapsLogger.debug(LTag.AUTOMATION, "NOT ready for execution: " + friendlyDescription())
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun toJSON(): String {
|
||||||
|
val data = JSONObject()
|
||||||
|
.put("hour", hour)
|
||||||
|
.put("minute", minute)
|
||||||
|
.put("validTo", validTo)
|
||||||
|
for (i in weekdays.indices) {
|
||||||
|
data.put(DayOfWeek.values()[i].name, weekdays[i])
|
||||||
|
}
|
||||||
|
return JSONObject()
|
||||||
|
.put("type", TriggerRecurringTime::class.java.name)
|
||||||
|
.put("data", data)
|
||||||
|
.toString()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun fromJSON(data: String): Trigger {
|
||||||
|
val o = JSONObject(data)
|
||||||
|
for (i in weekdays.indices)
|
||||||
|
weekdays[i] = JsonHelper.safeGetBoolean(o, DayOfWeek.values()[i].name)
|
||||||
|
hour = JsonHelper.safeGetInt(o, "hour")
|
||||||
|
minute = JsonHelper.safeGetInt(o, "minute")
|
||||||
|
validTo = JsonHelper.safeGetLong(o, "validTo")
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun friendlyName(): Int = R.string.recurringTime
|
||||||
|
|
||||||
|
override fun friendlyDescription(): String {
|
||||||
|
val sb = StringBuilder()
|
||||||
|
sb.append(resourceHelper.gs(R.string.every))
|
||||||
|
sb.append(" ")
|
||||||
|
var counter = 0
|
||||||
|
for (i in getSelectedDays()) {
|
||||||
|
if (counter++ > 0) sb.append(",")
|
||||||
|
sb.append(resourceHelper.gs(Objects.requireNonNull(DayOfWeek.fromCalendarInt(i)).shortName))
|
||||||
|
}
|
||||||
|
sb.append(" ")
|
||||||
|
val scheduledCal: Calendar = DateUtil.gregorianCalendar()
|
||||||
|
scheduledCal[Calendar.HOUR_OF_DAY] = hour
|
||||||
|
scheduledCal[Calendar.MINUTE] = minute
|
||||||
|
scheduledCal[Calendar.SECOND] = 0
|
||||||
|
val scheduled = scheduledCal.timeInMillis
|
||||||
|
sb.append(DateUtil.timeString(scheduled))
|
||||||
|
return if (counter == 0) resourceHelper.gs(R.string.never) else sb.toString()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun icon(): Optional<Int?> = Optional.of(R.drawable.ic_access_alarm_24dp)
|
||||||
|
|
||||||
|
override fun duplicate(): Trigger = TriggerRecurringTime(mainApp, this)
|
||||||
|
|
||||||
|
private fun getSelectedDays(): List<Int> {
|
||||||
|
val selectedDays: MutableList<Int> = ArrayList()
|
||||||
|
for (i in weekdays.indices) {
|
||||||
|
val day = DayOfWeek.values()[i]
|
||||||
|
val selected = weekdays[i]
|
||||||
|
if (selected) selectedDays.add(day.toCalendarInt())
|
||||||
|
}
|
||||||
|
return selectedDays
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun generateDialog(root: LinearLayout) {
|
||||||
|
val label = TextView(root.context)
|
||||||
|
// TODO: Replace external tool WeekdaysPicker with a self-made GUI element
|
||||||
|
val weekdaysPicker = WeekdaysPicker(root.context)
|
||||||
|
weekdaysPicker.setEditable(true)
|
||||||
|
weekdaysPicker.selectedDays = getSelectedDays()
|
||||||
|
weekdaysPicker.setOnWeekdaysChangeListener { _: View?, i: Int, list: List<Int?> -> set(DayOfWeek.fromCalendarInt(i), list.contains(i)) }
|
||||||
|
weekdaysPicker.layoutParams = LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)
|
||||||
|
weekdaysPicker.sundayFirstDay = Calendar.getInstance().firstDayOfWeek == Calendar.SUNDAY
|
||||||
|
weekdaysPicker.redrawDays()
|
||||||
|
root.addView(weekdaysPicker)
|
||||||
|
|
||||||
|
val timeButton = TextView(root.context)
|
||||||
|
val runAt = GregorianCalendar()
|
||||||
|
runAt[Calendar.HOUR_OF_DAY] = hour
|
||||||
|
runAt[Calendar.MINUTE] = minute
|
||||||
|
timeButton.text = DateUtil.timeString(runAt.timeInMillis)
|
||||||
|
|
||||||
|
val timeSetListener = TimePickerDialog.OnTimeSetListener { _, h, m ->
|
||||||
|
val cal = Calendar.getInstance()
|
||||||
|
hour = h
|
||||||
|
minute = m
|
||||||
|
cal.set(Calendar.HOUR_OF_DAY, hour)
|
||||||
|
cal.set(Calendar.MINUTE, minute)
|
||||||
|
cal.set(Calendar.SECOND, 0)
|
||||||
|
timeButton.text = DateUtil.timeString(cal.timeInMillis)
|
||||||
|
}
|
||||||
|
|
||||||
|
timeButton.setOnClickListener {
|
||||||
|
root.context?.let {
|
||||||
|
TimePickerDialog(it, timeSetListener, hour, minute, DateFormat.is24HourFormat(mainApp))
|
||||||
|
.show()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val px = resourceHelper.dpToPx(10)
|
||||||
|
label.text = resourceHelper.gs(R.string.atspecifiedtime, "")
|
||||||
|
label.setTypeface(label.typeface, Typeface.BOLD)
|
||||||
|
label.setPadding(px, px, px, px)
|
||||||
|
timeButton.setPadding(px, px, px, px)
|
||||||
|
val l = LinearLayout(root.context)
|
||||||
|
l.orientation = LinearLayout.HORIZONTAL
|
||||||
|
l.layoutParams = LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)
|
||||||
|
l.addView(label)
|
||||||
|
l.addView(timeButton)
|
||||||
|
root.addView(l)
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,131 +0,0 @@
|
||||||
package info.nightscout.androidaps.plugins.general.automation.triggers;
|
|
||||||
|
|
||||||
import android.widget.LinearLayout;
|
|
||||||
|
|
||||||
import androidx.fragment.app.FragmentManager;
|
|
||||||
|
|
||||||
import com.google.common.base.Optional;
|
|
||||||
|
|
||||||
import org.json.JSONException;
|
|
||||||
import org.json.JSONObject;
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
import info.nightscout.androidaps.MainApp;
|
|
||||||
import info.nightscout.androidaps.R;
|
|
||||||
import info.nightscout.androidaps.db.TempTarget;
|
|
||||||
import info.nightscout.androidaps.logging.L;
|
|
||||||
import info.nightscout.androidaps.plugins.general.automation.elements.ComparatorExists;
|
|
||||||
import info.nightscout.androidaps.plugins.general.automation.elements.LayoutBuilder;
|
|
||||||
import info.nightscout.androidaps.plugins.general.automation.elements.StaticLabel;
|
|
||||||
import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin;
|
|
||||||
import info.nightscout.androidaps.utils.DateUtil;
|
|
||||||
import info.nightscout.androidaps.utils.JsonHelper;
|
|
||||||
import info.nightscout.androidaps.utils.T;
|
|
||||||
|
|
||||||
public class TriggerTempTarget extends Trigger {
|
|
||||||
private static Logger log = LoggerFactory.getLogger(L.AUTOMATION);
|
|
||||||
|
|
||||||
private ComparatorExists comparator = new ComparatorExists();
|
|
||||||
|
|
||||||
public TriggerTempTarget() {
|
|
||||||
super();
|
|
||||||
}
|
|
||||||
|
|
||||||
private TriggerTempTarget(TriggerTempTarget triggerTempTarget) {
|
|
||||||
super();
|
|
||||||
comparator = new ComparatorExists(triggerTempTarget.comparator);
|
|
||||||
lastRun = triggerTempTarget.lastRun;
|
|
||||||
}
|
|
||||||
|
|
||||||
public ComparatorExists getComparator() {
|
|
||||||
return comparator;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public synchronized boolean shouldRun() {
|
|
||||||
TempTarget tt = TreatmentsPlugin.getPlugin().getTempTargetFromHistory();
|
|
||||||
|
|
||||||
if (lastRun > DateUtil.now() - T.mins(5).msecs())
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if (tt == null && comparator.getValue() == ComparatorExists.Compare.NOT_EXISTS) {
|
|
||||||
if (L.isEnabled(L.AUTOMATION))
|
|
||||||
log.debug("Ready for execution: " + friendlyDescription());
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (tt != null && comparator.getValue() == ComparatorExists.Compare.EXISTS) {
|
|
||||||
if (L.isEnabled(L.AUTOMATION))
|
|
||||||
log.debug("Ready for execution: " + friendlyDescription());
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public synchronized String toJSON() {
|
|
||||||
JSONObject o = new JSONObject();
|
|
||||||
try {
|
|
||||||
o.put("type", TriggerTempTarget.class.getName());
|
|
||||||
JSONObject data = new JSONObject();
|
|
||||||
data.put("lastRun", lastRun);
|
|
||||||
data.put("comparator", comparator.getValue().toString());
|
|
||||||
o.put("data", data);
|
|
||||||
} catch (JSONException e) {
|
|
||||||
log.error("Unhandled exception", e);
|
|
||||||
}
|
|
||||||
return o.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
Trigger fromJSON(String data) {
|
|
||||||
try {
|
|
||||||
JSONObject d = new JSONObject(data);
|
|
||||||
lastRun = JsonHelper.safeGetLong(d, "lastRun");
|
|
||||||
comparator.setValue(ComparatorExists.Compare.valueOf(JsonHelper.safeGetString(d, "comparator")));
|
|
||||||
} catch (Exception e) {
|
|
||||||
log.error("Unhandled exception", e);
|
|
||||||
}
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int friendlyName() {
|
|
||||||
return R.string.careportal_temporarytarget;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String friendlyDescription() {
|
|
||||||
return MainApp.gs(R.string.temptargetcompared, MainApp.gs(comparator.getValue().getStringRes()));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Optional<Integer> icon() {
|
|
||||||
return Optional.of(R.drawable.ic_keyboard_tab);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Trigger duplicate() {
|
|
||||||
return new TriggerTempTarget(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
TriggerTempTarget lastRun(long lastRun) {
|
|
||||||
this.lastRun = lastRun;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public TriggerTempTarget comparator(ComparatorExists.Compare compare) {
|
|
||||||
this.comparator = new ComparatorExists().setValue(compare);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void generateDialog(LinearLayout root, FragmentManager fragmentManager) {
|
|
||||||
new LayoutBuilder()
|
|
||||||
.add(new StaticLabel(R.string.careportal_temporarytarget))
|
|
||||||
.add(comparator)
|
|
||||||
.build(root);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -0,0 +1,69 @@
|
||||||
|
package info.nightscout.androidaps.plugins.general.automation.triggers
|
||||||
|
|
||||||
|
import android.widget.LinearLayout
|
||||||
|
import com.google.common.base.Optional
|
||||||
|
import info.nightscout.androidaps.MainApp
|
||||||
|
import info.nightscout.androidaps.R
|
||||||
|
import info.nightscout.androidaps.logging.LTag
|
||||||
|
import info.nightscout.androidaps.plugins.general.automation.elements.ComparatorExists
|
||||||
|
import info.nightscout.androidaps.plugins.general.automation.elements.LayoutBuilder
|
||||||
|
import info.nightscout.androidaps.plugins.general.automation.elements.StaticLabel
|
||||||
|
import info.nightscout.androidaps.utils.JsonHelper
|
||||||
|
import org.json.JSONObject
|
||||||
|
|
||||||
|
class TriggerTempTarget(mainApp: MainApp) : Trigger(mainApp) {
|
||||||
|
var comparator = ComparatorExists(mainApp)
|
||||||
|
|
||||||
|
constructor(mainApp: MainApp, compare: ComparatorExists.Compare) : this(mainApp) {
|
||||||
|
comparator = ComparatorExists(mainApp, compare)
|
||||||
|
}
|
||||||
|
|
||||||
|
constructor(mainApp: MainApp, triggerTempTarget: TriggerTempTarget) : this(mainApp) {
|
||||||
|
comparator = ComparatorExists(mainApp, triggerTempTarget.comparator.value)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun shouldRun(): Boolean {
|
||||||
|
val tt = treatmentsPlugin.tempTargetFromHistory
|
||||||
|
if (tt == null && comparator.value == ComparatorExists.Compare.NOT_EXISTS) {
|
||||||
|
aapsLogger.debug(LTag.AUTOMATION, "Ready for execution: " + friendlyDescription())
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
if (tt != null && comparator.value == ComparatorExists.Compare.EXISTS) {
|
||||||
|
aapsLogger.debug(LTag.AUTOMATION, "Ready for execution: " + friendlyDescription())
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
aapsLogger.debug(LTag.AUTOMATION, "NOT ready for execution: " + friendlyDescription())
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun toJSON(): String {
|
||||||
|
val data = JSONObject()
|
||||||
|
.put("comparator", comparator.value.toString())
|
||||||
|
return JSONObject()
|
||||||
|
.put("type", TriggerTempTarget::class.java.name)
|
||||||
|
.put("data", data)
|
||||||
|
.toString()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun fromJSON(data: String): Trigger {
|
||||||
|
val d = JSONObject(data)
|
||||||
|
comparator.value = ComparatorExists.Compare.valueOf(JsonHelper.safeGetString(d, "comparator")!!)
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun friendlyName(): Int = R.string.careportal_temporarytarget
|
||||||
|
|
||||||
|
override fun friendlyDescription(): String =
|
||||||
|
resourceHelper.gs(R.string.temptargetcompared, resourceHelper.gs(comparator.value.stringRes))
|
||||||
|
|
||||||
|
override fun icon(): Optional<Int?> = Optional.of(R.drawable.ic_keyboard_tab)
|
||||||
|
|
||||||
|
override fun duplicate(): Trigger = TriggerTempTarget(mainApp, this)
|
||||||
|
|
||||||
|
override fun generateDialog(root: LinearLayout) {
|
||||||
|
LayoutBuilder()
|
||||||
|
.add(StaticLabel(mainApp, R.string.careportal_temporarytarget))
|
||||||
|
.add(comparator)
|
||||||
|
.build(root)
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,186 +0,0 @@
|
||||||
package info.nightscout.androidaps.plugins.general.automation.triggers;
|
|
||||||
|
|
||||||
import android.graphics.Typeface;
|
|
||||||
import android.text.format.DateFormat;
|
|
||||||
import android.view.ViewGroup;
|
|
||||||
import android.widget.LinearLayout;
|
|
||||||
import android.widget.TextView;
|
|
||||||
|
|
||||||
import androidx.appcompat.app.AppCompatActivity;
|
|
||||||
import androidx.fragment.app.FragmentManager;
|
|
||||||
|
|
||||||
import com.google.common.base.Optional;
|
|
||||||
import com.wdullaer.materialdatetimepicker.date.DatePickerDialog;
|
|
||||||
import com.wdullaer.materialdatetimepicker.time.TimePickerDialog;
|
|
||||||
|
|
||||||
import org.json.JSONException;
|
|
||||||
import org.json.JSONObject;
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
import java.util.Calendar;
|
|
||||||
import java.util.GregorianCalendar;
|
|
||||||
|
|
||||||
import info.nightscout.androidaps.MainApp;
|
|
||||||
import info.nightscout.androidaps.R;
|
|
||||||
import info.nightscout.androidaps.logging.L;
|
|
||||||
import info.nightscout.androidaps.utils.DateUtil;
|
|
||||||
import info.nightscout.androidaps.utils.JsonHelper;
|
|
||||||
import info.nightscout.androidaps.utils.T;
|
|
||||||
|
|
||||||
public class TriggerTime extends Trigger {
|
|
||||||
private static Logger log = LoggerFactory.getLogger(L.AUTOMATION);
|
|
||||||
|
|
||||||
private long runAt;
|
|
||||||
|
|
||||||
public TriggerTime() {
|
|
||||||
runAt = DateUtil.now();
|
|
||||||
}
|
|
||||||
|
|
||||||
private TriggerTime(TriggerTime triggerTime) {
|
|
||||||
super();
|
|
||||||
lastRun = triggerTime.lastRun;
|
|
||||||
runAt = triggerTime.runAt;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean shouldRun() {
|
|
||||||
long now = DateUtil.now();
|
|
||||||
if (now >= runAt && now - runAt < T.mins(5).msecs())
|
|
||||||
if (lastRun < runAt) {
|
|
||||||
if (L.isEnabled(L.AUTOMATION))
|
|
||||||
log.debug("Ready for execution: " + friendlyDescription());
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toJSON() {
|
|
||||||
JSONObject object = new JSONObject();
|
|
||||||
JSONObject data = new JSONObject();
|
|
||||||
try {
|
|
||||||
data.put("runAt", runAt);
|
|
||||||
data.put("lastRun", lastRun);
|
|
||||||
object.put("type", TriggerTime.class.getName());
|
|
||||||
object.put("data", data);
|
|
||||||
} catch (JSONException e) {
|
|
||||||
log.error("Unhandled exception", e);
|
|
||||||
}
|
|
||||||
return object.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
Trigger fromJSON(String data) {
|
|
||||||
JSONObject o;
|
|
||||||
try {
|
|
||||||
o = new JSONObject(data);
|
|
||||||
lastRun = JsonHelper.safeGetLong(o, "lastRun");
|
|
||||||
runAt = JsonHelper.safeGetLong(o, "runAt");
|
|
||||||
} catch (JSONException e) {
|
|
||||||
log.error("Unhandled exception", e);
|
|
||||||
}
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int friendlyName() {
|
|
||||||
return R.string.time;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String friendlyDescription() {
|
|
||||||
return MainApp.gs(R.string.atspecifiedtime, DateUtil.dateAndTimeString(runAt));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Optional<Integer> icon() {
|
|
||||||
return Optional.of(R.drawable.ic_access_alarm_24dp);
|
|
||||||
}
|
|
||||||
|
|
||||||
TriggerTime runAt(long runAt) {
|
|
||||||
this.runAt = runAt;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
TriggerTime lastRun(long lastRun) {
|
|
||||||
this.lastRun = lastRun;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Trigger duplicate() {
|
|
||||||
return new TriggerTime(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
long getRunAt() {
|
|
||||||
return runAt;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void generateDialog(LinearLayout root, FragmentManager fragmentManager) {
|
|
||||||
TextView label = new TextView(root.getContext());
|
|
||||||
TextView dateButton = new TextView(root.getContext());
|
|
||||||
TextView timeButton = new TextView(root.getContext());
|
|
||||||
|
|
||||||
dateButton.setText(DateUtil.dateString(runAt));
|
|
||||||
timeButton.setText(DateUtil.timeString(runAt));
|
|
||||||
dateButton.setOnClickListener(view -> {
|
|
||||||
GregorianCalendar calendar = new GregorianCalendar();
|
|
||||||
calendar.setTimeInMillis(runAt);
|
|
||||||
DatePickerDialog dpd = DatePickerDialog.newInstance(
|
|
||||||
(view1, year, monthOfYear, dayOfMonth) -> {
|
|
||||||
calendar.set(Calendar.YEAR, year);
|
|
||||||
calendar.set(Calendar.MONTH, monthOfYear);
|
|
||||||
calendar.set(Calendar.DAY_OF_MONTH, dayOfMonth);
|
|
||||||
runAt = calendar.getTimeInMillis();
|
|
||||||
dateButton.setText(DateUtil.dateString(runAt));
|
|
||||||
},
|
|
||||||
calendar.get(Calendar.YEAR),
|
|
||||||
calendar.get(Calendar.MONTH),
|
|
||||||
calendar.get(Calendar.DAY_OF_MONTH)
|
|
||||||
);
|
|
||||||
dpd.setThemeDark(true);
|
|
||||||
dpd.dismissOnPause(true);
|
|
||||||
AppCompatActivity a = scanForActivity(root.getContext());
|
|
||||||
if (a != null)
|
|
||||||
dpd.show(a.getSupportFragmentManager(), "DatePickerDialog");
|
|
||||||
});
|
|
||||||
timeButton.setOnClickListener(view -> {
|
|
||||||
GregorianCalendar calendar = new GregorianCalendar();
|
|
||||||
calendar.setTimeInMillis(runAt);
|
|
||||||
TimePickerDialog tpd = TimePickerDialog.newInstance(
|
|
||||||
(view12, hourOfDay, minute, second) -> {
|
|
||||||
calendar.set(Calendar.HOUR_OF_DAY, hourOfDay);
|
|
||||||
calendar.set(Calendar.MINUTE, minute);
|
|
||||||
runAt = calendar.getTimeInMillis();
|
|
||||||
timeButton.setText(DateUtil.timeString(runAt));
|
|
||||||
},
|
|
||||||
calendar.get(Calendar.HOUR_OF_DAY),
|
|
||||||
calendar.get(Calendar.MINUTE),
|
|
||||||
DateFormat.is24HourFormat(root.getContext())
|
|
||||||
);
|
|
||||||
tpd.setThemeDark(true);
|
|
||||||
tpd.dismissOnPause(true);
|
|
||||||
AppCompatActivity a = scanForActivity(root.getContext());
|
|
||||||
if (a != null)
|
|
||||||
tpd.show(a.getSupportFragmentManager(), "TimePickerDialog");
|
|
||||||
});
|
|
||||||
|
|
||||||
int px = MainApp.dpToPx(10);
|
|
||||||
label.setText(MainApp.gs(R.string.atspecifiedtime, ""));
|
|
||||||
label.setTypeface(label.getTypeface(), Typeface.BOLD);
|
|
||||||
label.setPadding(px, px, px, px);
|
|
||||||
dateButton.setPadding(px, px, px, px);
|
|
||||||
timeButton.setPadding(px, px, px, px);
|
|
||||||
|
|
||||||
LinearLayout l = new LinearLayout(root.getContext());
|
|
||||||
l.setOrientation(LinearLayout.HORIZONTAL);
|
|
||||||
l.setLayoutParams(new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT));
|
|
||||||
|
|
||||||
l.addView(label);
|
|
||||||
l.addView(dateButton);
|
|
||||||
l.addView(timeButton);
|
|
||||||
root.addView(l);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -0,0 +1,132 @@
|
||||||
|
package info.nightscout.androidaps.plugins.general.automation.triggers
|
||||||
|
|
||||||
|
import android.app.DatePickerDialog
|
||||||
|
import android.app.TimePickerDialog
|
||||||
|
import android.graphics.Typeface
|
||||||
|
import android.text.format.DateFormat
|
||||||
|
import android.view.ViewGroup
|
||||||
|
import android.widget.LinearLayout
|
||||||
|
import android.widget.TextView
|
||||||
|
import com.google.common.base.Optional
|
||||||
|
import info.nightscout.androidaps.MainApp
|
||||||
|
import info.nightscout.androidaps.R
|
||||||
|
import info.nightscout.androidaps.logging.LTag
|
||||||
|
import info.nightscout.androidaps.utils.DateUtil
|
||||||
|
import info.nightscout.androidaps.utils.JsonHelper.safeGetLong
|
||||||
|
import info.nightscout.androidaps.utils.T
|
||||||
|
import org.json.JSONObject
|
||||||
|
import java.util.*
|
||||||
|
|
||||||
|
class TriggerTime(mainApp: MainApp) : Trigger(mainApp) {
|
||||||
|
var runAt = DateUtil.now()
|
||||||
|
|
||||||
|
constructor(mainApp: MainApp, runAt: Long) : this(mainApp) {
|
||||||
|
this.runAt = runAt
|
||||||
|
}
|
||||||
|
|
||||||
|
constructor(mainApp: MainApp, triggerTime : TriggerTime) : this(mainApp) {
|
||||||
|
this.runAt = triggerTime.runAt
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun shouldRun(): Boolean {
|
||||||
|
val now = DateUtil.now()
|
||||||
|
if (now >= runAt && now - runAt < T.mins(5).msecs()) {
|
||||||
|
aapsLogger.debug(LTag.AUTOMATION, "Ready for execution: " + friendlyDescription())
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
aapsLogger.debug(LTag.AUTOMATION, "NOT ready for execution: " + friendlyDescription())
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun toJSON(): String {
|
||||||
|
val data = JSONObject()
|
||||||
|
.put("runAt", runAt)
|
||||||
|
return JSONObject()
|
||||||
|
.put("type", this::class.java.name)
|
||||||
|
.put("data", data)
|
||||||
|
.toString()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun fromJSON(data: String): Trigger {
|
||||||
|
val o = JSONObject(data)
|
||||||
|
runAt = safeGetLong(o, "runAt")
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun friendlyName(): Int = R.string.time
|
||||||
|
|
||||||
|
override fun friendlyDescription(): String =
|
||||||
|
resourceHelper.gs(R.string.atspecifiedtime, DateUtil.dateAndTimeString(runAt))
|
||||||
|
|
||||||
|
override fun icon(): Optional<Int?> = Optional.of(R.drawable.ic_access_alarm_24dp)
|
||||||
|
|
||||||
|
override fun duplicate(): Trigger = TriggerTime(mainApp, runAt)
|
||||||
|
|
||||||
|
override fun generateDialog(root: LinearLayout) {
|
||||||
|
val label = TextView(root.context)
|
||||||
|
val dateButton = TextView(root.context)
|
||||||
|
val timeButton = TextView(root.context)
|
||||||
|
dateButton.text = DateUtil.dateString(runAt)
|
||||||
|
timeButton.text = DateUtil.timeString(runAt)
|
||||||
|
|
||||||
|
// create an OnDateSetListener
|
||||||
|
val dateSetListener = DatePickerDialog.OnDateSetListener { _, year, monthOfYear, dayOfMonth ->
|
||||||
|
val cal = Calendar.getInstance()
|
||||||
|
cal.timeInMillis = runAt
|
||||||
|
cal.set(Calendar.YEAR, year)
|
||||||
|
cal.set(Calendar.MONTH, monthOfYear)
|
||||||
|
cal.set(Calendar.DAY_OF_MONTH, dayOfMonth)
|
||||||
|
runAt = cal.timeInMillis
|
||||||
|
dateButton.text = DateUtil.dateString(runAt)
|
||||||
|
}
|
||||||
|
|
||||||
|
dateButton.setOnClickListener {
|
||||||
|
root.context?.let {
|
||||||
|
val cal = Calendar.getInstance()
|
||||||
|
cal.timeInMillis = runAt
|
||||||
|
DatePickerDialog(it, dateSetListener,
|
||||||
|
cal.get(Calendar.YEAR),
|
||||||
|
cal.get(Calendar.MONTH),
|
||||||
|
cal.get(Calendar.DAY_OF_MONTH)
|
||||||
|
).show()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// create an OnTimeSetListener
|
||||||
|
val timeSetListener = TimePickerDialog.OnTimeSetListener { _, hour, minute ->
|
||||||
|
val cal = Calendar.getInstance()
|
||||||
|
cal.timeInMillis = runAt
|
||||||
|
cal.set(Calendar.HOUR_OF_DAY, hour)
|
||||||
|
cal.set(Calendar.MINUTE, minute)
|
||||||
|
cal.set(Calendar.SECOND, 0) // randomize seconds to prevent creating record of the same time, if user choose time manually
|
||||||
|
runAt = cal.timeInMillis
|
||||||
|
timeButton.text = DateUtil.timeString(runAt)
|
||||||
|
}
|
||||||
|
|
||||||
|
timeButton.setOnClickListener {
|
||||||
|
root.context?.let {
|
||||||
|
val cal = Calendar.getInstance()
|
||||||
|
cal.timeInMillis = runAt
|
||||||
|
TimePickerDialog(it, timeSetListener,
|
||||||
|
cal.get(Calendar.HOUR_OF_DAY),
|
||||||
|
cal.get(Calendar.MINUTE),
|
||||||
|
DateFormat.is24HourFormat(mainApp)
|
||||||
|
).show()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val px = resourceHelper.dpToPx(10)
|
||||||
|
label.text = resourceHelper.gs(R.string.atspecifiedtime, "")
|
||||||
|
label.setTypeface(label.typeface, Typeface.BOLD)
|
||||||
|
label.setPadding(px, px, px, px)
|
||||||
|
dateButton.setPadding(px, px, px, px)
|
||||||
|
timeButton.setPadding(px, px, px, px)
|
||||||
|
val l = LinearLayout(root.context)
|
||||||
|
l.orientation = LinearLayout.HORIZONTAL
|
||||||
|
l.layoutParams = LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)
|
||||||
|
l.addView(label)
|
||||||
|
l.addView(dateButton)
|
||||||
|
l.addView(timeButton)
|
||||||
|
root.addView(l)
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,235 +0,0 @@
|
||||||
package info.nightscout.androidaps.plugins.general.automation.triggers;
|
|
||||||
|
|
||||||
import android.graphics.Typeface;
|
|
||||||
import android.text.format.DateFormat;
|
|
||||||
import android.view.ViewGroup;
|
|
||||||
import android.widget.LinearLayout;
|
|
||||||
import android.widget.TextView;
|
|
||||||
|
|
||||||
import androidx.appcompat.app.AppCompatActivity;
|
|
||||||
import androidx.fragment.app.FragmentManager;
|
|
||||||
|
|
||||||
import com.google.common.base.Optional;
|
|
||||||
import com.wdullaer.materialdatetimepicker.time.TimePickerDialog;
|
|
||||||
|
|
||||||
import org.json.JSONException;
|
|
||||||
import org.json.JSONObject;
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
import java.util.Calendar;
|
|
||||||
import java.util.GregorianCalendar;
|
|
||||||
|
|
||||||
import info.nightscout.androidaps.MainApp;
|
|
||||||
import info.nightscout.androidaps.R;
|
|
||||||
import info.nightscout.androidaps.logging.L;
|
|
||||||
import info.nightscout.androidaps.utils.DateUtil;
|
|
||||||
import info.nightscout.androidaps.utils.JsonHelper;
|
|
||||||
import info.nightscout.androidaps.utils.T;
|
|
||||||
|
|
||||||
|
|
||||||
// Trigger for time range ( from 10:00AM till 13:00PM )
|
|
||||||
|
|
||||||
public class TriggerTimeRange extends Trigger {
|
|
||||||
private static Logger log = LoggerFactory.getLogger(L.AUTOMATION);
|
|
||||||
|
|
||||||
// in minutes since midnight 60 means 1AM
|
|
||||||
private int start;
|
|
||||||
private int end;
|
|
||||||
long timeZoneOffset = DateUtil.getTimeZoneOffsetMs();
|
|
||||||
|
|
||||||
public TriggerTimeRange() {
|
|
||||||
|
|
||||||
start = getMinSinceMidnight(DateUtil.now());
|
|
||||||
end = getMinSinceMidnight(DateUtil.now());
|
|
||||||
}
|
|
||||||
|
|
||||||
private TriggerTimeRange(TriggerTimeRange triggerTimeRange) {
|
|
||||||
super();
|
|
||||||
lastRun = triggerTimeRange.lastRun;
|
|
||||||
start = triggerTimeRange.start;
|
|
||||||
end = triggerTimeRange.end;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean shouldRun() {
|
|
||||||
int currentMinSinceMidnight = getMinSinceMidnight(DateUtil.now());
|
|
||||||
|
|
||||||
if (lastRun > DateUtil.now() - T.mins(5).msecs())
|
|
||||||
return false;
|
|
||||||
|
|
||||||
boolean doRun = false;
|
|
||||||
if (start < end && start < currentMinSinceMidnight && currentMinSinceMidnight < end)
|
|
||||||
doRun = true;
|
|
||||||
|
|
||||||
// handle cases like 10PM to 6AM
|
|
||||||
else if (start > end && (start < currentMinSinceMidnight || currentMinSinceMidnight < end))
|
|
||||||
doRun = true;
|
|
||||||
|
|
||||||
if (doRun) {
|
|
||||||
if (L.isEnabled(L.AUTOMATION))
|
|
||||||
log.debug("Ready for execution: " + friendlyDescription());
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toJSON() {
|
|
||||||
JSONObject object = new JSONObject();
|
|
||||||
JSONObject data = new JSONObject();
|
|
||||||
|
|
||||||
// check for too big values
|
|
||||||
if (start > 1440)
|
|
||||||
start = getMinSinceMidnight(start);
|
|
||||||
if (end > 1440)
|
|
||||||
end = getMinSinceMidnight(end);
|
|
||||||
|
|
||||||
try {
|
|
||||||
data.put("start", getMinSinceMidnight(start));
|
|
||||||
data.put("end", getMinSinceMidnight(end));
|
|
||||||
data.put("lastRun", lastRun);
|
|
||||||
object.put("type", TriggerTimeRange.class.getName());
|
|
||||||
object.put("data", data);
|
|
||||||
} catch (JSONException e) {
|
|
||||||
log.error("Unhandled exception", e);
|
|
||||||
}
|
|
||||||
log.debug(object.toString());
|
|
||||||
return object.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
TriggerTimeRange fromJSON(String data) {
|
|
||||||
JSONObject o;
|
|
||||||
try {
|
|
||||||
o = new JSONObject(data);
|
|
||||||
lastRun = JsonHelper.safeGetLong(o, "lastRun");
|
|
||||||
start = JsonHelper.safeGetInt(o, "start");
|
|
||||||
end = JsonHelper.safeGetInt(o, "end");
|
|
||||||
} catch (JSONException e) {
|
|
||||||
log.error("Unhandled exception", e);
|
|
||||||
}
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int friendlyName() {
|
|
||||||
return R.string.time_range;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String friendlyDescription() {
|
|
||||||
return MainApp.gs(R.string.timerange_value, DateUtil.timeString(toMilis(start) - timeZoneOffset), DateUtil.timeString(toMilis(end) - timeZoneOffset));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Optional<Integer> icon() {
|
|
||||||
return Optional.of(R.drawable.ic_access_alarm_24dp);
|
|
||||||
}
|
|
||||||
|
|
||||||
TriggerTimeRange period(int start, int end) {
|
|
||||||
this.start = getMinSinceMidnight(start * 60000);
|
|
||||||
this.end = getMinSinceMidnight(end * 60000);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
TriggerTimeRange lastRun(long lastRun) {
|
|
||||||
this.lastRun = lastRun;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Trigger duplicate() {
|
|
||||||
return new TriggerTimeRange(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
long toMilis(long minutesSinceMidnight) {
|
|
||||||
return minutesSinceMidnight * 60 * 1000;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getMinSinceMidnight(long time) {
|
|
||||||
// if passed argument is smaller than 1440 ( 24 h * 60 min ) that value is already converted
|
|
||||||
if (0 < time && time < 1441)
|
|
||||||
return (int) time;
|
|
||||||
Calendar calendar = DateUtil.gregorianCalendar();
|
|
||||||
calendar.setTimeInMillis(time);
|
|
||||||
return (calendar.get(Calendar.HOUR_OF_DAY) * 60) + calendar.get(Calendar.MINUTE);
|
|
||||||
}
|
|
||||||
|
|
||||||
int getStart() {
|
|
||||||
return start;
|
|
||||||
}
|
|
||||||
|
|
||||||
int getEnd() {
|
|
||||||
return end;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void generateDialog(LinearLayout root, FragmentManager fragmentManager) {
|
|
||||||
TextView label = new TextView(root.getContext());
|
|
||||||
TextView startButton = new TextView(root.getContext());
|
|
||||||
TextView endButton = new TextView(root.getContext());
|
|
||||||
log.debug("Start is: " + start);
|
|
||||||
log.debug("End is: " + end);
|
|
||||||
startButton.setText(DateUtil.timeString(toMilis(start) - timeZoneOffset));
|
|
||||||
endButton.setText(MainApp.gs(R.string.and) + " " + DateUtil.timeString(toMilis(end) - timeZoneOffset));
|
|
||||||
|
|
||||||
startButton.setOnClickListener(view -> {
|
|
||||||
GregorianCalendar calendar = new GregorianCalendar();
|
|
||||||
//setTimeInMillis sets time in milliseconds after
|
|
||||||
// * January 1, 1970, 0:00:00 GMT., but our time contains timezone offsset
|
|
||||||
calendar.setTimeInMillis(toMilis(start) - timeZoneOffset);
|
|
||||||
TimePickerDialog tpd = TimePickerDialog.newInstance(
|
|
||||||
(view12, hourOfDay, minute, second) -> {
|
|
||||||
calendar.set(Calendar.HOUR_OF_DAY, hourOfDay);
|
|
||||||
calendar.set(Calendar.MINUTE, minute);
|
|
||||||
start = getMinSinceMidnight(calendar.getTimeInMillis());
|
|
||||||
startButton.setText(DateUtil.timeString(toMilis(start) - timeZoneOffset));
|
|
||||||
},
|
|
||||||
calendar.get(Calendar.HOUR_OF_DAY),
|
|
||||||
calendar.get(Calendar.MINUTE),
|
|
||||||
DateFormat.is24HourFormat(root.getContext())
|
|
||||||
);
|
|
||||||
tpd.setThemeDark(true);
|
|
||||||
tpd.dismissOnPause(true);
|
|
||||||
AppCompatActivity a = scanForActivity(root.getContext());
|
|
||||||
if (a != null)
|
|
||||||
tpd.show(a.getSupportFragmentManager(), "TimePickerDialog");
|
|
||||||
});
|
|
||||||
endButton.setOnClickListener(view -> {
|
|
||||||
GregorianCalendar calendar = new GregorianCalendar();
|
|
||||||
calendar.setTimeInMillis(toMilis(end) - timeZoneOffset);
|
|
||||||
TimePickerDialog tpd = TimePickerDialog.newInstance(
|
|
||||||
(view12, hourOfDay, minute, second) -> {
|
|
||||||
calendar.set(Calendar.HOUR_OF_DAY, hourOfDay);
|
|
||||||
calendar.set(Calendar.MINUTE, minute);
|
|
||||||
end = getMinSinceMidnight(calendar.getTimeInMillis());
|
|
||||||
endButton.setText(MainApp.gs(R.string.and) + " " + DateUtil.timeString(toMilis(end) - timeZoneOffset));
|
|
||||||
},
|
|
||||||
calendar.get(Calendar.HOUR_OF_DAY),
|
|
||||||
calendar.get(Calendar.MINUTE),
|
|
||||||
DateFormat.is24HourFormat(root.getContext())
|
|
||||||
);
|
|
||||||
tpd.setThemeDark(true);
|
|
||||||
tpd.dismissOnPause(true);
|
|
||||||
AppCompatActivity a = scanForActivity(root.getContext());
|
|
||||||
if (a != null)
|
|
||||||
tpd.show(a.getSupportFragmentManager(), "TimePickerDialog");
|
|
||||||
});
|
|
||||||
|
|
||||||
int px = MainApp.dpToPx(10);
|
|
||||||
label.setText(MainApp.gs(R.string.between));
|
|
||||||
label.setTypeface(label.getTypeface(), Typeface.BOLD);
|
|
||||||
startButton.setPadding(px, px, px, px);
|
|
||||||
endButton.setPadding(px, px, px, px);
|
|
||||||
|
|
||||||
LinearLayout l = new LinearLayout(root.getContext());
|
|
||||||
l.setOrientation(LinearLayout.HORIZONTAL);
|
|
||||||
l.setLayoutParams(new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT));
|
|
||||||
|
|
||||||
l.addView(label);
|
|
||||||
l.addView(startButton);
|
|
||||||
l.addView(endButton);
|
|
||||||
root.addView(l);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -0,0 +1,145 @@
|
||||||
|
package info.nightscout.androidaps.plugins.general.automation.triggers
|
||||||
|
|
||||||
|
import android.app.TimePickerDialog
|
||||||
|
import android.graphics.Typeface
|
||||||
|
import android.text.format.DateFormat
|
||||||
|
import android.view.ViewGroup
|
||||||
|
import android.widget.LinearLayout
|
||||||
|
import android.widget.TextView
|
||||||
|
import com.google.common.base.Optional
|
||||||
|
import info.nightscout.androidaps.MainApp
|
||||||
|
import info.nightscout.androidaps.R
|
||||||
|
import info.nightscout.androidaps.data.Profile
|
||||||
|
import info.nightscout.androidaps.logging.LTag
|
||||||
|
import info.nightscout.androidaps.utils.DateUtil
|
||||||
|
import info.nightscout.androidaps.utils.JsonHelper.safeGetInt
|
||||||
|
import info.nightscout.androidaps.utils.T
|
||||||
|
import org.json.JSONObject
|
||||||
|
import java.util.*
|
||||||
|
|
||||||
|
// Trigger for time range ( from 10:00AM till 13:00PM )
|
||||||
|
class TriggerTimeRange(mainApp: MainApp) : Trigger(mainApp) {
|
||||||
|
|
||||||
|
// in minutes since midnight 60 means 1AM
|
||||||
|
var start: Int = getMinSinceMidnight(DateUtil.now())
|
||||||
|
var end: Int = getMinSinceMidnight(DateUtil.now())
|
||||||
|
|
||||||
|
constructor(mainApp: MainApp, start : Int, end :Int) : this(mainApp) {
|
||||||
|
this.start = start
|
||||||
|
this.end = end
|
||||||
|
}
|
||||||
|
|
||||||
|
constructor(mainApp: MainApp, triggerTimeRange: TriggerTimeRange) : this(mainApp) {
|
||||||
|
this.start = triggerTimeRange.start
|
||||||
|
this.end = triggerTimeRange.end
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun shouldRun(): Boolean {
|
||||||
|
val currentMinSinceMidnight = getMinSinceMidnight(DateUtil.now())
|
||||||
|
var doRun = false
|
||||||
|
if (start < end && start < currentMinSinceMidnight && currentMinSinceMidnight < end) doRun = true
|
||||||
|
else if (start > end && (start < currentMinSinceMidnight || currentMinSinceMidnight < end)) doRun = true
|
||||||
|
if (doRun) {
|
||||||
|
aapsLogger.debug(LTag.AUTOMATION, "Ready for execution: " + friendlyDescription())
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
aapsLogger.debug(LTag.AUTOMATION, "NOT ready for execution: " + friendlyDescription())
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun toJSON(): String {
|
||||||
|
val data = JSONObject()
|
||||||
|
.put("start", getMinSinceMidnight(start.toLong()))
|
||||||
|
.put("end", getMinSinceMidnight(end.toLong()))
|
||||||
|
return JSONObject()
|
||||||
|
.put("type", this::class.java.name)
|
||||||
|
.put("data", data)
|
||||||
|
.toString()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun fromJSON(data: String): TriggerTimeRange {
|
||||||
|
val o = JSONObject(data)
|
||||||
|
start = safeGetInt(o, "start")
|
||||||
|
end = safeGetInt(o, "end")
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun friendlyName(): Int = R.string.time_range
|
||||||
|
|
||||||
|
override fun friendlyDescription(): String =
|
||||||
|
resourceHelper.gs(R.string.timerange_value, DateUtil.timeString(toMills(start)), DateUtil.timeString(toMills(end)))
|
||||||
|
|
||||||
|
override fun icon(): Optional<Int?> = Optional.of(R.drawable.ic_access_alarm_24dp)
|
||||||
|
|
||||||
|
override fun duplicate(): Trigger = TriggerTimeRange(mainApp, start, end)
|
||||||
|
|
||||||
|
private fun toMills(minutesSinceMidnight: Int): Long = T.secs(minutesSinceMidnight.toLong()).msecs()
|
||||||
|
|
||||||
|
private fun getMinSinceMidnight(time: Long): Int = Profile.secondsFromMidnight(time) / 60
|
||||||
|
|
||||||
|
override fun generateDialog(root: LinearLayout) {
|
||||||
|
val label = TextView(root.context)
|
||||||
|
val startButton = TextView(root.context)
|
||||||
|
val endButton = TextView(root.context)
|
||||||
|
startButton.text = DateUtil.timeString(toMills(start))
|
||||||
|
@Suppress("SetTextI18n")
|
||||||
|
endButton.text = resourceHelper.gs(R.string.and) + " " + DateUtil.timeString(toMills(end))
|
||||||
|
|
||||||
|
val startTimeSetListener = TimePickerDialog.OnTimeSetListener { _, hour, minute ->
|
||||||
|
val cal = Calendar.getInstance()
|
||||||
|
cal.timeInMillis = toMills(start)
|
||||||
|
cal.set(Calendar.HOUR_OF_DAY, hour)
|
||||||
|
cal.set(Calendar.MINUTE, minute)
|
||||||
|
cal.set(Calendar.SECOND, 0)
|
||||||
|
start = getMinSinceMidnight(cal.timeInMillis)
|
||||||
|
startButton.text = DateUtil.timeString(toMills(start))
|
||||||
|
}
|
||||||
|
|
||||||
|
startButton.setOnClickListener {
|
||||||
|
root.context?.let {
|
||||||
|
val cal = Calendar.getInstance()
|
||||||
|
cal.timeInMillis = toMills(start)
|
||||||
|
TimePickerDialog(it, startTimeSetListener,
|
||||||
|
cal.get(Calendar.HOUR_OF_DAY),
|
||||||
|
cal.get(Calendar.MINUTE),
|
||||||
|
DateFormat.is24HourFormat(mainApp)
|
||||||
|
).show()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val endTimeSetListener = TimePickerDialog.OnTimeSetListener { _, hour, minute ->
|
||||||
|
val cal = Calendar.getInstance()
|
||||||
|
cal.timeInMillis = toMills(end)
|
||||||
|
cal.set(Calendar.HOUR_OF_DAY, hour)
|
||||||
|
cal.set(Calendar.MINUTE, minute)
|
||||||
|
cal.set(Calendar.SECOND, 0) // randomize seconds to prevent creating record of the same time, if user choose time manually
|
||||||
|
end = getMinSinceMidnight(cal.timeInMillis)
|
||||||
|
endButton.text = DateUtil.timeString(toMills(end))
|
||||||
|
}
|
||||||
|
|
||||||
|
endButton.setOnClickListener {
|
||||||
|
root.context?.let {
|
||||||
|
val cal = Calendar.getInstance()
|
||||||
|
cal.timeInMillis = toMills(end)
|
||||||
|
TimePickerDialog(it, endTimeSetListener,
|
||||||
|
cal.get(Calendar.HOUR_OF_DAY),
|
||||||
|
cal.get(Calendar.MINUTE),
|
||||||
|
DateFormat.is24HourFormat(mainApp)
|
||||||
|
).show()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val px = resourceHelper.dpToPx(10)
|
||||||
|
label.text = resourceHelper.gs(R.string.between)
|
||||||
|
label.setTypeface(label.typeface, Typeface.BOLD)
|
||||||
|
startButton.setPadding(px, px, px, px)
|
||||||
|
endButton.setPadding(px, px, px, px)
|
||||||
|
val l = LinearLayout(root.context)
|
||||||
|
l.orientation = LinearLayout.HORIZONTAL
|
||||||
|
l.layoutParams = LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)
|
||||||
|
l.addView(label)
|
||||||
|
l.addView(startButton)
|
||||||
|
l.addView(endButton)
|
||||||
|
root.addView(l)
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,149 +0,0 @@
|
||||||
package info.nightscout.androidaps.plugins.general.automation.triggers;
|
|
||||||
|
|
||||||
import android.widget.LinearLayout;
|
|
||||||
|
|
||||||
import androidx.fragment.app.FragmentManager;
|
|
||||||
|
|
||||||
import com.google.common.base.Optional;
|
|
||||||
|
|
||||||
import org.json.JSONException;
|
|
||||||
import org.json.JSONObject;
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
import info.nightscout.androidaps.MainApp;
|
|
||||||
import info.nightscout.androidaps.R;
|
|
||||||
import info.nightscout.androidaps.events.EventNetworkChange;
|
|
||||||
import info.nightscout.androidaps.logging.L;
|
|
||||||
import info.nightscout.androidaps.plugins.general.automation.elements.Comparator;
|
|
||||||
import info.nightscout.androidaps.plugins.general.automation.elements.InputString;
|
|
||||||
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.elements.StaticLabel;
|
|
||||||
import info.nightscout.androidaps.receivers.NetworkChangeReceiver;
|
|
||||||
import info.nightscout.androidaps.utils.DateUtil;
|
|
||||||
import info.nightscout.androidaps.utils.JsonHelper;
|
|
||||||
import info.nightscout.androidaps.utils.T;
|
|
||||||
|
|
||||||
public class TriggerWifiSsid extends Trigger {
|
|
||||||
private static Logger log = LoggerFactory.getLogger(L.AUTOMATION);
|
|
||||||
|
|
||||||
private InputString ssid = new InputString();
|
|
||||||
private Comparator comparator = new Comparator();
|
|
||||||
|
|
||||||
public TriggerWifiSsid() {
|
|
||||||
super();
|
|
||||||
}
|
|
||||||
|
|
||||||
private TriggerWifiSsid(TriggerWifiSsid triggerWifiSsid) {
|
|
||||||
super();
|
|
||||||
ssid = new InputString(triggerWifiSsid.ssid);
|
|
||||||
comparator = new Comparator(triggerWifiSsid.comparator);
|
|
||||||
lastRun = triggerWifiSsid.lastRun;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getValue() {
|
|
||||||
return ssid.getValue();
|
|
||||||
}
|
|
||||||
|
|
||||||
public Comparator getComparator() {
|
|
||||||
return comparator;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public synchronized boolean shouldRun() {
|
|
||||||
EventNetworkChange eventNetworkChange = NetworkChangeReceiver.getLastEvent();
|
|
||||||
if (eventNetworkChange == null)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if (lastRun > DateUtil.now() - T.mins(5).msecs())
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if (!eventNetworkChange.getWifiConnected() && comparator.getValue() == Comparator.Compare.IS_NOT_AVAILABLE) {
|
|
||||||
if (L.isEnabled(L.AUTOMATION))
|
|
||||||
log.debug("Ready for execution: " + friendlyDescription());
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
boolean doRun = eventNetworkChange.getWifiConnected() && comparator.getValue().check(eventNetworkChange.connectedSsid(), getValue());
|
|
||||||
if (doRun) {
|
|
||||||
if (L.isEnabled(L.AUTOMATION))
|
|
||||||
log.debug("Ready for execution: " + friendlyDescription());
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public synchronized String toJSON() {
|
|
||||||
JSONObject o = new JSONObject();
|
|
||||||
try {
|
|
||||||
o.put("type", TriggerWifiSsid.class.getName());
|
|
||||||
JSONObject data = new JSONObject();
|
|
||||||
data.put("ssid", getValue());
|
|
||||||
data.put("lastRun", lastRun);
|
|
||||||
data.put("comparator", comparator.getValue().toString());
|
|
||||||
o.put("data", data);
|
|
||||||
} catch (JSONException e) {
|
|
||||||
log.error("Unhandled exception", e);
|
|
||||||
}
|
|
||||||
return o.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
Trigger fromJSON(String data) {
|
|
||||||
try {
|
|
||||||
JSONObject d = new JSONObject(data);
|
|
||||||
ssid.setValue(JsonHelper.safeGetString(d, "ssid"));
|
|
||||||
lastRun = JsonHelper.safeGetLong(d, "lastRun");
|
|
||||||
comparator.setValue(Comparator.Compare.valueOf(JsonHelper.safeGetString(d, "comparator")));
|
|
||||||
} catch (Exception e) {
|
|
||||||
log.error("Unhandled exception", e);
|
|
||||||
}
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int friendlyName() {
|
|
||||||
return R.string.ns_wifi_ssids;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String friendlyDescription() {
|
|
||||||
return MainApp.gs(R.string.wifissidcompared, MainApp.gs(comparator.getValue().getStringRes()), getValue());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Optional<Integer> icon() {
|
|
||||||
return Optional.of(R.drawable.ic_network_wifi);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Trigger duplicate() {
|
|
||||||
return new TriggerWifiSsid(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
TriggerWifiSsid setValue(String value) {
|
|
||||||
ssid.setValue(value);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
TriggerWifiSsid lastRun(long lastRun) {
|
|
||||||
this.lastRun = lastRun;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
TriggerWifiSsid comparator(Comparator.Compare compare) {
|
|
||||||
this.comparator = new Comparator().setValue(compare);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void generateDialog(LinearLayout root, FragmentManager fragmentManager) {
|
|
||||||
new LayoutBuilder()
|
|
||||||
.add(new StaticLabel(R.string.ns_wifi_ssids))
|
|
||||||
.add(comparator)
|
|
||||||
.add(new LabelWithElement(MainApp.gs(R.string.ns_wifi_ssids) + ": ", "", ssid))
|
|
||||||
.build(root);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -0,0 +1,78 @@
|
||||||
|
package info.nightscout.androidaps.plugins.general.automation.triggers
|
||||||
|
|
||||||
|
import android.widget.LinearLayout
|
||||||
|
import com.google.common.base.Optional
|
||||||
|
import info.nightscout.androidaps.MainApp
|
||||||
|
import info.nightscout.androidaps.R
|
||||||
|
import info.nightscout.androidaps.logging.LTag
|
||||||
|
import info.nightscout.androidaps.plugins.general.automation.elements.Comparator
|
||||||
|
import info.nightscout.androidaps.plugins.general.automation.elements.InputString
|
||||||
|
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.elements.StaticLabel
|
||||||
|
import info.nightscout.androidaps.receivers.NetworkChangeReceiver
|
||||||
|
import info.nightscout.androidaps.utils.JsonHelper
|
||||||
|
import org.json.JSONObject
|
||||||
|
|
||||||
|
class TriggerWifiSsid(mainApp: MainApp) : Trigger(mainApp) {
|
||||||
|
private var ssid = InputString(mainApp)
|
||||||
|
var comparator = Comparator(mainApp)
|
||||||
|
|
||||||
|
constructor(mainApp: MainApp, ssid: String, compare: Comparator.Compare) : this(mainApp) {
|
||||||
|
this.ssid = InputString(mainApp, ssid)
|
||||||
|
comparator = Comparator(mainApp, compare)
|
||||||
|
}
|
||||||
|
|
||||||
|
constructor(mainApp: MainApp, triggerWifiSsid: TriggerWifiSsid) : this(mainApp) {
|
||||||
|
this.ssid = InputString(mainApp, triggerWifiSsid.ssid.value)
|
||||||
|
comparator = Comparator(mainApp, triggerWifiSsid.comparator.value)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun shouldRun(): Boolean {
|
||||||
|
val eventNetworkChange = NetworkChangeReceiver.getLastEvent() ?: return false
|
||||||
|
if (!eventNetworkChange.wifiConnected && comparator.value == Comparator.Compare.IS_NOT_AVAILABLE) {
|
||||||
|
aapsLogger.debug(LTag.AUTOMATION, "Ready for execution: " + friendlyDescription())
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
if (eventNetworkChange.wifiConnected && comparator.value.check(eventNetworkChange.connectedSsid(), ssid.value)) {
|
||||||
|
aapsLogger.debug(LTag.AUTOMATION, "Ready for execution: " + friendlyDescription())
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
aapsLogger.debug(LTag.AUTOMATION, "NOT ready for execution: " + friendlyDescription())
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun toJSON(): String {
|
||||||
|
val data = JSONObject()
|
||||||
|
.put("ssid", ssid)
|
||||||
|
.put("comparator", comparator.value.toString())
|
||||||
|
return JSONObject()
|
||||||
|
.put("type", this::class.java.name)
|
||||||
|
.put("data", data)
|
||||||
|
.toString()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun fromJSON(data: String): Trigger {
|
||||||
|
val d = JSONObject(data)
|
||||||
|
ssid.value = JsonHelper.safeGetString(d, "ssid")!!
|
||||||
|
comparator.value = Comparator.Compare.valueOf(JsonHelper.safeGetString(d, "comparator")!!)
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun friendlyName(): Int = R.string.ns_wifi_ssids
|
||||||
|
|
||||||
|
override fun friendlyDescription(): String =
|
||||||
|
resourceHelper.gs(R.string.wifissidcompared, resourceHelper.gs(comparator.value.stringRes), ssid.value)
|
||||||
|
|
||||||
|
override fun icon(): Optional<Int?> = Optional.of(R.drawable.ic_network_wifi)
|
||||||
|
|
||||||
|
override fun duplicate(): Trigger = TriggerWifiSsid(mainApp, this)
|
||||||
|
|
||||||
|
override fun generateDialog(root: LinearLayout) {
|
||||||
|
LayoutBuilder()
|
||||||
|
.add(StaticLabel(mainApp, R.string.ns_wifi_ssids))
|
||||||
|
.add(comparator)
|
||||||
|
.add(LabelWithElement(mainApp, resourceHelper.gs(R.string.ns_wifi_ssids) + ": ", "", ssid))
|
||||||
|
.build(root)
|
||||||
|
}
|
||||||
|
}
|
|
@ -8,10 +8,12 @@ import info.nightscout.androidaps.plugins.configBuilder.ProfileFunction
|
||||||
import info.nightscout.androidaps.utils.resources.ResourceHelper
|
import info.nightscout.androidaps.utils.resources.ResourceHelper
|
||||||
import info.nightscout.androidaps.utils.sharedPreferences.SP
|
import info.nightscout.androidaps.utils.sharedPreferences.SP
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
import javax.inject.Singleton
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by adrian on 14/08/17.
|
* Created by adrian on 14/08/17.
|
||||||
*/
|
*/
|
||||||
|
@Singleton
|
||||||
class InsulinOrefRapidActingPlugin @Inject constructor(
|
class InsulinOrefRapidActingPlugin @Inject constructor(
|
||||||
resourceHelper: ResourceHelper,
|
resourceHelper: ResourceHelper,
|
||||||
rxBus: RxBusWrapper,
|
rxBus: RxBusWrapper,
|
||||||
|
|
|
@ -8,10 +8,12 @@ import info.nightscout.androidaps.plugins.configBuilder.ProfileFunction
|
||||||
import info.nightscout.androidaps.utils.resources.ResourceHelper
|
import info.nightscout.androidaps.utils.resources.ResourceHelper
|
||||||
import info.nightscout.androidaps.utils.sharedPreferences.SP
|
import info.nightscout.androidaps.utils.sharedPreferences.SP
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
import javax.inject.Singleton
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by adrian on 14/08/17.
|
* Created by adrian on 14/08/17.
|
||||||
*/
|
*/
|
||||||
|
@Singleton
|
||||||
class InsulinOrefUltraRapidActingPlugin @Inject constructor(
|
class InsulinOrefUltraRapidActingPlugin @Inject constructor(
|
||||||
private val sp: SP,
|
private val sp: SP,
|
||||||
resourceHelper: ResourceHelper,
|
resourceHelper: ResourceHelper,
|
||||||
|
|
|
@ -26,7 +26,7 @@ import io.reactivex.disposables.CompositeDisposable
|
||||||
import io.reactivex.schedulers.Schedulers
|
import io.reactivex.schedulers.Schedulers
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
class LocationService : DaggerService() {
|
class LocationService @Inject constructor(): DaggerService() {
|
||||||
@Inject lateinit var aapsLogger: AAPSLogger
|
@Inject lateinit var aapsLogger: AAPSLogger
|
||||||
@Inject lateinit var rxBus: RxBusWrapper
|
@Inject lateinit var rxBus: RxBusWrapper
|
||||||
@Inject lateinit var sp: SP
|
@Inject lateinit var sp: SP
|
||||||
|
@ -40,13 +40,10 @@ class LocationService : DaggerService() {
|
||||||
private val LOCATION_INTERVAL_ACTIVE = T.mins(5).msecs()
|
private val LOCATION_INTERVAL_ACTIVE = T.mins(5).msecs()
|
||||||
private val LOCATION_INTERVAL_PASSIVE = T.mins(1).msecs() // this doesn't cost more power
|
private val LOCATION_INTERVAL_PASSIVE = T.mins(1).msecs() // this doesn't cost more power
|
||||||
|
|
||||||
|
var lastLocation: Location? = null
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
private const val LOCATION_DISTANCE = 10f
|
private const val LOCATION_DISTANCE = 10f
|
||||||
private var lastLocation: Location? = null
|
|
||||||
|
|
||||||
@JvmStatic
|
|
||||||
@Deprecated("replace by injection")
|
|
||||||
fun getLastLocation(): Location? = lastLocation
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inner class LocationListener internal constructor(val provider: String) : android.location.LocationListener {
|
inner class LocationListener internal constructor(val provider: String) : android.location.LocationListener {
|
||||||
|
|
|
@ -81,13 +81,6 @@ public class TriggerAutosensValueTest {
|
||||||
Assert.assertEquals(Comparator.Compare.IS_EQUAL_OR_LESSER, t.getComparator().getValue());
|
Assert.assertEquals(Comparator.Compare.IS_EQUAL_OR_LESSER, t.getComparator().getValue());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
|
||||||
public void executeTest() {
|
|
||||||
TriggerAutosensValue t = new TriggerAutosensValue().setValue(213).comparator(Comparator.Compare.IS_EQUAL_OR_LESSER);
|
|
||||||
t.executed(1);
|
|
||||||
Assert.assertEquals(1l, t.getLastRun());
|
|
||||||
}
|
|
||||||
|
|
||||||
String ASJson = "{\"data\":{\"comparator\":\"IS_EQUAL\",\"lastRun\":0,\"value\":410},\"type\":\"info.nightscout.androidaps.plugins.general.automation.triggers.TriggerAutosensValue\"}";
|
String ASJson = "{\"data\":{\"comparator\":\"IS_EQUAL\",\"lastRun\":0,\"value\":410},\"type\":\"info.nightscout.androidaps.plugins.general.automation.triggers.TriggerAutosensValue\"}";
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|
|
@ -2,6 +2,7 @@ package info.nightscout.androidaps.plugins.insulin
|
||||||
|
|
||||||
import info.nightscout.androidaps.R
|
import info.nightscout.androidaps.R
|
||||||
import info.nightscout.androidaps.plugins.bus.RxBusWrapper
|
import info.nightscout.androidaps.plugins.bus.RxBusWrapper
|
||||||
|
import info.nightscout.androidaps.plugins.configBuilder.ProfileFunction
|
||||||
import info.nightscout.androidaps.utils.resources.ResourceHelper
|
import info.nightscout.androidaps.utils.resources.ResourceHelper
|
||||||
import info.nightscout.androidaps.utils.sharedPreferences.SP
|
import info.nightscout.androidaps.utils.sharedPreferences.SP
|
||||||
import junit.framework.Assert.assertEquals
|
import junit.framework.Assert.assertEquals
|
||||||
|
@ -34,10 +35,11 @@ class InsulinOrefFreePeakPluginTest {
|
||||||
@Mock lateinit var sp: SP
|
@Mock lateinit var sp: SP
|
||||||
@Mock lateinit var resourceHelper: ResourceHelper
|
@Mock lateinit var resourceHelper: ResourceHelper
|
||||||
@Mock lateinit var rxBus: RxBusWrapper
|
@Mock lateinit var rxBus: RxBusWrapper
|
||||||
|
@Mock lateinit var profileFunction: ProfileFunction
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
fun setup() {
|
fun setup() {
|
||||||
sut = InsulinOrefFreePeakPlugin(sp, resourceHelper, rxBus)
|
sut = InsulinOrefFreePeakPlugin(sp, resourceHelper, rxBus, profileFunction)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|
Loading…
Reference in a new issue