clean time related triggers
This commit is contained in:
parent
fa4d4c9fa9
commit
ec84c3fa70
|
@ -90,6 +90,8 @@ interface AppComponent : AndroidInjector<MainApp> {
|
|||
fun injectElement(inputString: InputString)
|
||||
fun injectElement(inputTempTarget: InputTempTarget)
|
||||
fun injectElement(inputTimeRange: InputTimeRange)
|
||||
fun injectElement(inputTime: InputTime)
|
||||
fun injectElement(inputWeekDay: InputWeekDay)
|
||||
fun injectElement(labelWithElement: LabelWithElement)
|
||||
fun injectElement(staticLabel: StaticLabel)
|
||||
|
||||
|
|
|
@ -112,7 +112,7 @@ open class AppModule {
|
|||
@ContributesAndroidInjector fun inputButtonInjector(): InputButton
|
||||
@ContributesAndroidInjector fun comparatorInjector(): Comparator
|
||||
@ContributesAndroidInjector fun comparatorExistsInjector(): ComparatorExists
|
||||
@ContributesAndroidInjector fun inputTimeInjector(): InputDateTime
|
||||
@ContributesAndroidInjector fun inputDateTimeInjector(): InputDateTime
|
||||
@ContributesAndroidInjector fun inputDeltaInjector(): InputDelta
|
||||
@ContributesAndroidInjector fun inputDoubleInjector(): InputDouble
|
||||
@ContributesAndroidInjector fun inputDurationInjector(): InputDuration
|
||||
|
@ -123,6 +123,8 @@ open class AppModule {
|
|||
@ContributesAndroidInjector fun inputStringInjector(): InputString
|
||||
@ContributesAndroidInjector fun inputTempTargetInjector(): InputTempTarget
|
||||
@ContributesAndroidInjector fun inputTimeRangeInjector(): InputTimeRange
|
||||
@ContributesAndroidInjector fun inputTimeInjector(): InputTime
|
||||
@ContributesAndroidInjector fun inputWeekDayInjector(): InputWeekDay
|
||||
@ContributesAndroidInjector fun labelWithElementInjector(): LabelWithElement
|
||||
@ContributesAndroidInjector fun staticLabelInjector(): StaticLabel
|
||||
|
||||
|
|
|
@ -21,10 +21,10 @@ class InputTempTarget(mainApp: MainApp) : Element(mainApp) {
|
|||
}
|
||||
|
||||
override fun addToLayout(root: LinearLayout) {
|
||||
var minValue = 0.0
|
||||
var maxValue = 0.0
|
||||
var step = 0.0
|
||||
var decimalFormat: DecimalFormat? = null
|
||||
var minValue: Double
|
||||
var maxValue: Double
|
||||
var step: Double
|
||||
var decimalFormat: DecimalFormat?
|
||||
if (units == Constants.MMOL) { // mmol
|
||||
minValue = Constants.MIN_TT_MMOL
|
||||
maxValue = Constants.MAX_TT_MMOL
|
||||
|
|
|
@ -0,0 +1,57 @@
|
|||
package info.nightscout.androidaps.plugins.general.automation.elements
|
||||
|
||||
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 info.nightscout.androidaps.MainApp
|
||||
import info.nightscout.androidaps.R
|
||||
import info.nightscout.androidaps.data.Profile
|
||||
import info.nightscout.androidaps.utils.DateUtil
|
||||
import info.nightscout.androidaps.utils.MidnightTime
|
||||
import info.nightscout.androidaps.utils.T
|
||||
import java.util.*
|
||||
|
||||
class InputTime(mainApp: MainApp) : Element(mainApp) {
|
||||
var value: Int = getMinSinceMidnight(DateUtil.now())
|
||||
|
||||
override fun addToLayout(root: LinearLayout) {
|
||||
val label = TextView(root.context)
|
||||
val startButton = TextView(root.context)
|
||||
startButton.text = DateUtil.timeString(toMills(value))
|
||||
|
||||
val startTimeSetListener = TimePickerDialog.OnTimeSetListener { _, hour, minute ->
|
||||
value = 60 * hour + minute
|
||||
startButton.text = DateUtil.timeString(toMills(value))
|
||||
}
|
||||
|
||||
startButton.setOnClickListener {
|
||||
root.context?.let {
|
||||
val cal = Calendar.getInstance()
|
||||
cal.timeInMillis = toMills(value)
|
||||
TimePickerDialog(it, startTimeSetListener,
|
||||
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)
|
||||
startButton.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)
|
||||
root.addView(l)
|
||||
}
|
||||
|
||||
private fun toMills(minutesSinceMidnight: Int): Long = MidnightTime.calc() + T.mins(minutesSinceMidnight.toLong()).msecs()
|
||||
|
||||
private fun getMinSinceMidnight(time: Long): Int = Profile.secondsFromMidnight(time) / 60
|
||||
}
|
|
@ -0,0 +1,86 @@
|
|||
package info.nightscout.androidaps.plugins.general.automation.elements
|
||||
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.LinearLayout
|
||||
import androidx.annotation.StringRes
|
||||
import com.dpro.widgets.WeekdaysPicker
|
||||
import info.nightscout.androidaps.MainApp
|
||||
import info.nightscout.androidaps.R
|
||||
import java.util.*
|
||||
|
||||
class InputWeekDay(mainApp: MainApp) : Element(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")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val weekdays = BooleanArray(DayOfWeek.values().size)
|
||||
|
||||
init {
|
||||
for (day in DayOfWeek.values()) set(day, false)
|
||||
}
|
||||
|
||||
operator fun set(day: DayOfWeek, value: Boolean): InputWeekDay {
|
||||
weekdays[day.ordinal] = value
|
||||
return this
|
||||
}
|
||||
|
||||
fun isSet(day: DayOfWeek): Boolean = weekdays[day.ordinal]
|
||||
|
||||
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 addToLayout(root: LinearLayout) {
|
||||
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)
|
||||
}
|
||||
}
|
|
@ -1,99 +1,38 @@
|
|||
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.data.Profile
|
||||
import info.nightscout.androidaps.logging.LTag
|
||||
import info.nightscout.androidaps.plugins.general.automation.elements.InputTime
|
||||
import info.nightscout.androidaps.plugins.general.automation.elements.InputWeekDay
|
||||
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.MidnightTime
|
||||
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
|
||||
private val days = InputWeekDay(mainApp)
|
||||
private val time = InputTime(mainApp)
|
||||
|
||||
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)
|
||||
this.time.value = triggerRecurringTime.time.value
|
||||
if (days.weekdays.size >= 0)
|
||||
System.arraycopy(triggerRecurringTime.days.weekdays, 0, days.weekdays, 0, triggerRecurringTime.days.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()) {
|
||||
val currentMinSinceMidnight = getMinSinceMidnight(DateUtil.now())
|
||||
val scheduledDayOfWeek = Calendar.getInstance()[Calendar.DAY_OF_WEEK]
|
||||
val scheduled = getMinSinceMidnight(time.value.toLong())
|
||||
if (days.isSet(Objects.requireNonNull(InputWeekDay.DayOfWeek.fromCalendarInt(scheduledDayOfWeek)))) {
|
||||
if (currentMinSinceMidnight >= scheduled && currentMinSinceMidnight - scheduled < 5) {
|
||||
aapsLogger.debug(LTag.AUTOMATION, "Ready for execution: " + friendlyDescription())
|
||||
return true
|
||||
}
|
||||
|
@ -104,11 +43,9 @@ class TriggerRecurringTime(mainApp: MainApp) : Trigger(mainApp) {
|
|||
|
||||
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])
|
||||
.put("time", time.value)
|
||||
for (i in days.weekdays.indices) {
|
||||
data.put(InputWeekDay.DayOfWeek.values()[i].name, days.weekdays[i])
|
||||
}
|
||||
return JSONObject()
|
||||
.put("type", TriggerRecurringTime::class.java.name)
|
||||
|
@ -118,11 +55,16 @@ class TriggerRecurringTime(mainApp: MainApp) : Trigger(mainApp) {
|
|||
|
||||
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")
|
||||
for (i in days.weekdays.indices)
|
||||
days.weekdays[i] = JsonHelper.safeGetBoolean(o, InputWeekDay.DayOfWeek.values()[i].name)
|
||||
if (o.has("hour")) {
|
||||
// do conversion from 2.5.1 format
|
||||
val hour = JsonHelper.safeGetInt(o, "hour")
|
||||
val minute = JsonHelper.safeGetInt(o, "minute")
|
||||
time.value = 60 * hour + minute
|
||||
} else {
|
||||
time.value = JsonHelper.safeGetInt(o, "time")
|
||||
}
|
||||
return this
|
||||
}
|
||||
|
||||
|
@ -133,17 +75,12 @@ class TriggerRecurringTime(mainApp: MainApp) : Trigger(mainApp) {
|
|||
sb.append(resourceHelper.gs(R.string.every))
|
||||
sb.append(" ")
|
||||
var counter = 0
|
||||
for (i in getSelectedDays()) {
|
||||
for (i in days.getSelectedDays()) {
|
||||
if (counter++ > 0) sb.append(",")
|
||||
sb.append(resourceHelper.gs(Objects.requireNonNull(DayOfWeek.fromCalendarInt(i)).shortName))
|
||||
sb.append(resourceHelper.gs(Objects.requireNonNull(InputWeekDay.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))
|
||||
sb.append(DateUtil.timeString(toMills(time.value)))
|
||||
return if (counter == 0) resourceHelper.gs(R.string.never) else sb.toString()
|
||||
}
|
||||
|
||||
|
@ -151,61 +88,15 @@ class TriggerRecurringTime(mainApp: MainApp) : Trigger(mainApp) {
|
|||
|
||||
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
|
||||
}
|
||||
private fun toMills(minutesSinceMidnight: Int): Long = MidnightTime.calc() + T.mins(minutesSinceMidnight.toLong()).msecs()
|
||||
|
||||
private fun getMinSinceMidnight(time: Long): Int = Profile.secondsFromMidnight(time) / 60
|
||||
|
||||
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)
|
||||
LayoutBuilder()
|
||||
.add(StaticLabel(mainApp, R.string.recurringTime))
|
||||
.add(days)
|
||||
.add(time)
|
||||
.build(root)
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue