Tidepool cleanup

This commit is contained in:
Milos Kozak 2020-01-03 00:26:59 +01:00
parent c45b434647
commit 89b1dda10b
9 changed files with 61 additions and 55 deletions

View file

@ -1,14 +1,14 @@
package info.nightscout.androidaps.plugins.general.tidepool.comm package info.nightscout.androidaps.plugins.general.tidepool.comm
import info.nightscout.androidaps.plugins.bus.RxBus
import info.nightscout.androidaps.logging.L import info.nightscout.androidaps.logging.L
import info.nightscout.androidaps.plugins.bus.RxBusWrapper
import info.nightscout.androidaps.plugins.general.tidepool.events.EventTidepoolStatus import info.nightscout.androidaps.plugins.general.tidepool.events.EventTidepoolStatus
import org.slf4j.LoggerFactory import org.slf4j.LoggerFactory
import retrofit2.Call import retrofit2.Call
import retrofit2.Callback import retrofit2.Callback
import retrofit2.Response import retrofit2.Response
internal class TidepoolCallback<T>(private val session: Session, val name: String, val onSuccess: () -> Unit, val onFail: () -> Unit) : Callback<T> { internal class TidepoolCallback<T>(private val rxBus: RxBusWrapper, private val session: Session, val name: String, val onSuccess: () -> Unit, val onFail: () -> Unit) : Callback<T> {
private val log = LoggerFactory.getLogger(L.TIDEPOOL) private val log = LoggerFactory.getLogger(L.TIDEPOOL)
override fun onResponse(call: Call<T>, response: Response<T>) { override fun onResponse(call: Call<T>, response: Response<T>) {
@ -20,7 +20,7 @@ internal class TidepoolCallback<T>(private val session: Session, val name: Strin
} else { } else {
val msg = name + " was not successful: " + response.code() + " " + response.message() val msg = name + " was not successful: " + response.code() + " " + response.message()
if (L.isEnabled(L.TIDEPOOL)) log.debug(msg) if (L.isEnabled(L.TIDEPOOL)) log.debug(msg)
RxBus.INSTANCE.send(EventTidepoolStatus(msg)) rxBus.send(EventTidepoolStatus(msg))
onFail() onFail()
} }
} }
@ -28,7 +28,7 @@ internal class TidepoolCallback<T>(private val session: Session, val name: Strin
override fun onFailure(call: Call<T>, t: Throwable) { override fun onFailure(call: Call<T>, t: Throwable) {
val msg = "$name Failed: $t" val msg = "$name Failed: $t"
if (L.isEnabled(L.TIDEPOOL)) log.debug(msg) if (L.isEnabled(L.TIDEPOOL)) log.debug(msg)
RxBus.INSTANCE.send(EventTidepoolStatus(msg)) rxBus.send(EventTidepoolStatus(msg))
onFail() onFail()
} }

View file

@ -9,6 +9,7 @@ import info.nightscout.androidaps.R
import info.nightscout.androidaps.logging.AAPSLogger import info.nightscout.androidaps.logging.AAPSLogger
import info.nightscout.androidaps.logging.LTag import info.nightscout.androidaps.logging.LTag
import info.nightscout.androidaps.plugins.bus.RxBusWrapper import info.nightscout.androidaps.plugins.bus.RxBusWrapper
import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin
import info.nightscout.androidaps.plugins.general.tidepool.events.EventTidepoolStatus import info.nightscout.androidaps.plugins.general.tidepool.events.EventTidepoolStatus
import info.nightscout.androidaps.plugins.general.tidepool.messages.AuthReplyMessage import info.nightscout.androidaps.plugins.general.tidepool.messages.AuthReplyMessage
import info.nightscout.androidaps.plugins.general.tidepool.messages.AuthRequestMessage import info.nightscout.androidaps.plugins.general.tidepool.messages.AuthRequestMessage
@ -16,6 +17,7 @@ import info.nightscout.androidaps.plugins.general.tidepool.messages.DatasetReply
import info.nightscout.androidaps.plugins.general.tidepool.messages.OpenDatasetRequestMessage import info.nightscout.androidaps.plugins.general.tidepool.messages.OpenDatasetRequestMessage
import info.nightscout.androidaps.plugins.general.tidepool.messages.UploadReplyMessage import info.nightscout.androidaps.plugins.general.tidepool.messages.UploadReplyMessage
import info.nightscout.androidaps.utils.DateUtil import info.nightscout.androidaps.utils.DateUtil
import info.nightscout.androidaps.utils.InstanceId
import info.nightscout.androidaps.utils.OKDialog import info.nightscout.androidaps.utils.OKDialog
import info.nightscout.androidaps.utils.T import info.nightscout.androidaps.utils.T
import info.nightscout.androidaps.utils.resources.ResourceHelper import info.nightscout.androidaps.utils.resources.ResourceHelper
@ -36,7 +38,8 @@ class TidepoolUploader @Inject constructor(
private val mainApp: MainApp, private val mainApp: MainApp,
private val resourceHelper: ResourceHelper, private val resourceHelper: ResourceHelper,
private val sp: SP, private val sp: SP,
private val uploadChunk: UploadChunk private val uploadChunk: UploadChunk,
private val configBuilderPlugin: ConfigBuilderPlugin
) { ) {
private var wl: PowerManager.WakeLock? = null private var wl: PowerManager.WakeLock? = null
@ -80,7 +83,7 @@ class TidepoolUploader @Inject constructor(
private fun createSession(): Session { private fun createSession(): Session {
val service = getRetrofitInstance()?.create(TidepoolApiService::class.java) val service = getRetrofitInstance()?.create(TidepoolApiService::class.java)
return Session(AuthRequestMessage.getAuthRequestHeader(), SESSION_TOKEN_HEADER, service) return Session(AuthRequestMessage.getAuthRequestHeader(sp), SESSION_TOKEN_HEADER, service)
} }
// TODO: call on preference change // TODO: call on preference change
@ -105,7 +108,7 @@ class TidepoolUploader @Inject constructor(
rxBus.send(EventTidepoolStatus(("Connecting"))) rxBus.send(EventTidepoolStatus(("Connecting")))
val call = session?.service?.getLogin(authHeader) val call = session?.service?.getLogin(authHeader)
call?.enqueue(TidepoolCallback<AuthReplyMessage>(session!!, "Login", { call?.enqueue(TidepoolCallback<AuthReplyMessage>(rxBus, session!!, "Login", {
startSession(session!!, doUpload) startSession(session!!, doUpload)
}, { }, {
connectionStatus = ConnectionStatus.FAILED connectionStatus = ConnectionStatus.FAILED
@ -126,7 +129,7 @@ class TidepoolUploader @Inject constructor(
session.authHeader?.let { session.authHeader?.let {
val call = session.service?.getLogin(it) val call = session.service?.getLogin(it)
call?.enqueue(TidepoolCallback<AuthReplyMessage>(session, "Login", { call?.enqueue(TidepoolCallback<AuthReplyMessage>(rxBus, session, "Login", {
OKDialog.show(rootContext, resourceHelper.gs(R.string.tidepool), "Successfully logged into Tidepool.") OKDialog.show(rootContext, resourceHelper.gs(R.string.tidepool), "Successfully logged into Tidepool.")
}, { }, {
OKDialog.show(rootContext, resourceHelper.gs(R.string.tidepool), "Failed to log into Tidepool.\nCheck that your user name and password are correct.") OKDialog.show(rootContext, resourceHelper.gs(R.string.tidepool), "Failed to log into Tidepool.\nCheck that your user name and password are correct.")
@ -144,11 +147,13 @@ class TidepoolUploader @Inject constructor(
val datasetCall = session.service!!.getOpenDataSets(session.token!!, val datasetCall = session.service!!.getOpenDataSets(session.token!!,
session.authReply!!.userid!!, BuildConfig.APPLICATION_ID, 1) session.authReply!!.userid!!, BuildConfig.APPLICATION_ID, 1)
datasetCall.enqueue(TidepoolCallback<List<DatasetReplyMessage>>(session, "Get Open Datasets", { datasetCall.enqueue(TidepoolCallback<List<DatasetReplyMessage>>(rxBus, session, "Get Open Datasets", {
if (session.datasetReply == null) { if (session.datasetReply == null) {
rxBus.send(EventTidepoolStatus(("Creating new dataset"))) rxBus.send(EventTidepoolStatus(("Creating new dataset")))
val call = session.service.openDataSet(session.token!!, session.authReply!!.userid!!, OpenDatasetRequestMessage().getBody()) val call = session.service.openDataSet(session.token!!, session.authReply!!.userid!!,
call.enqueue(TidepoolCallback<DatasetReplyMessage>(session, "Open New Dataset", { OpenDatasetRequestMessage((configBuilderPlugin.activePump?.serialNumber()
?: InstanceId.instanceId())).getBody())
call.enqueue(TidepoolCallback<DatasetReplyMessage>(rxBus, session, "Open New Dataset", {
connectionStatus = ConnectionStatus.CONNECTED connectionStatus = ConnectionStatus.CONNECTED
rxBus.send(EventTidepoolStatus(("New dataset OK"))) rxBus.send(EventTidepoolStatus(("New dataset OK")))
if (doUpload) doUpload() if (doUpload) doUpload()
@ -212,7 +217,7 @@ class TidepoolUploader @Inject constructor(
rxBus.send(EventTidepoolStatus(("Uploading"))) rxBus.send(EventTidepoolStatus(("Uploading")))
if (session.service != null && session.token != null && session.datasetReply != null) { if (session.service != null && session.token != null && session.datasetReply != null) {
val call = session.service.doUpload(session.token!!, session.datasetReply!!.getUploadId()!!, body) val call = session.service.doUpload(session.token!!, session.datasetReply!!.getUploadId()!!, body)
call.enqueue(TidepoolCallback<UploadReplyMessage>(session, "Data Upload", { call.enqueue(TidepoolCallback<UploadReplyMessage>(rxBus, session, "Data Upload", {
uploadChunk.setLastEnd(session.end) uploadChunk.setLastEnd(session.end)
rxBus.send(EventTidepoolStatus(("Upload completed OK"))) rxBus.send(EventTidepoolStatus(("Upload completed OK")))
releaseWakeLock() releaseWakeLock()
@ -239,7 +244,7 @@ class TidepoolUploader @Inject constructor(
if (session?.datasetReply?.id != null) { if (session?.datasetReply?.id != null) {
extendWakeLock(60000) extendWakeLock(60000)
val call = session!!.service?.deleteDataSet(session!!.token!!, session!!.datasetReply!!.id!!) val call = session!!.service?.deleteDataSet(session!!.token!!, session!!.datasetReply!!.id!!)
call?.enqueue(TidepoolCallback(session!!, "Delete Dataset", { call?.enqueue(TidepoolCallback(rxBus, session!!, "Delete Dataset", {
connectionStatus = ConnectionStatus.DISCONNECTED connectionStatus = ConnectionStatus.DISCONNECTED
rxBus.send(EventTidepoolStatus(("Dataset removed OK"))) rxBus.send(EventTidepoolStatus(("Dataset removed OK")))
releaseWakeLock() releaseWakeLock()
@ -264,7 +269,7 @@ class TidepoolUploader @Inject constructor(
requireNotNull(userId) requireNotNull(userId)
extendWakeLock(60000) extendWakeLock(60000)
val call = session.service?.deleteAllData(token, userId) val call = session.service?.deleteAllData(token, userId)
call?.enqueue(TidepoolCallback(session, "Delete all data", { call?.enqueue(TidepoolCallback(rxBus, session, "Delete all data", {
connectionStatus = ConnectionStatus.DISCONNECTED connectionStatus = ConnectionStatus.DISCONNECTED
rxBus.send(EventTidepoolStatus(("All data removed OK"))) rxBus.send(EventTidepoolStatus(("All data removed OK")))
releaseWakeLock() releaseWakeLock()

View file

@ -2,15 +2,21 @@ package info.nightscout.androidaps.plugins.general.tidepool.comm
import info.nightscout.androidaps.MainApp import info.nightscout.androidaps.MainApp
import info.nightscout.androidaps.R import info.nightscout.androidaps.R
import info.nightscout.androidaps.data.Intervals
import info.nightscout.androidaps.db.ProfileSwitch
import info.nightscout.androidaps.db.TemporaryBasal
import info.nightscout.androidaps.logging.AAPSLogger import info.nightscout.androidaps.logging.AAPSLogger
import info.nightscout.androidaps.logging.L import info.nightscout.androidaps.logging.L
import info.nightscout.androidaps.logging.LTag import info.nightscout.androidaps.logging.LTag
import info.nightscout.androidaps.plugins.bus.RxBusWrapper import info.nightscout.androidaps.plugins.bus.RxBusWrapper
import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin
import info.nightscout.androidaps.plugins.configBuilder.ProfileFunction
import info.nightscout.androidaps.plugins.general.tidepool.elements.* import info.nightscout.androidaps.plugins.general.tidepool.elements.*
import info.nightscout.androidaps.plugins.general.tidepool.events.EventTidepoolStatus import info.nightscout.androidaps.plugins.general.tidepool.events.EventTidepoolStatus
import info.nightscout.androidaps.plugins.general.tidepool.utils.GsonInstance import info.nightscout.androidaps.plugins.general.tidepool.utils.GsonInstance
import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin
import info.nightscout.androidaps.utils.DateUtil import info.nightscout.androidaps.utils.DateUtil
import info.nightscout.androidaps.utils.InstanceId
import info.nightscout.androidaps.utils.T import info.nightscout.androidaps.utils.T
import info.nightscout.androidaps.utils.sharedPreferences.SP import info.nightscout.androidaps.utils.sharedPreferences.SP
import org.slf4j.LoggerFactory import org.slf4j.LoggerFactory
@ -24,7 +30,9 @@ class UploadChunk @Inject constructor(
private val sp: SP, private val sp: SP,
private val rxBus: RxBusWrapper, private val rxBus: RxBusWrapper,
private val aapsLogger: AAPSLogger, private val aapsLogger: AAPSLogger,
private val treatmentsPlugin: TreatmentsPlugin private val profileFunction: ProfileFunction,
private val treatmentsPlugin: TreatmentsPlugin,
private val configBuilderPlugin: ConfigBuilderPlugin
) { ) {
private val MAX_UPLOAD_SIZE = T.days(7).msecs() // don't change this private val MAX_UPLOAD_SIZE = T.days(7).msecs() // don't change this
@ -134,20 +142,34 @@ class UploadChunk @Inject constructor(
return selection return selection
} }
private fun fromTemporaryBasals(tbrList: Intervals<TemporaryBasal>, start: Long, end: Long): List<BasalElement> {
val results = LinkedList<BasalElement>()
for (tbr in tbrList.list) {
if (tbr.date >= start && tbr.date <= end && tbr.durationInMinutes != 0)
results.add(BasalElement(tbr, profileFunction))
}
return results
}
private fun getBasals(start: Long, end: Long): List<BasalElement> { private fun getBasals(start: Long, end: Long): List<BasalElement> {
val tbrs = treatmentsPlugin.temporaryBasalsFromHistory val tbrs = treatmentsPlugin.temporaryBasalsFromHistory
tbrs.merge() tbrs.merge()
val selection = BasalElement.fromTemporaryBasals(tbrs, start, end) // TODO do not upload running TBR val selection = fromTemporaryBasals(tbrs, start, end) // TODO do not upload running TBR
if (selection.isNotEmpty()) if (selection.isNotEmpty())
rxBus.send(EventTidepoolStatus("${selection.size} TBRs selected for upload")) rxBus.send(EventTidepoolStatus("${selection.size} TBRs selected for upload"))
return selection return selection
} }
fun newInstanceOrNull(ps: ProfileSwitch): ProfileElement? = try {
ProfileElement(ps, configBuilderPlugin.activePump?.serialNumber() ?: InstanceId.instanceId())
} catch (e: Throwable) {
null
}
private fun getProfiles(start: Long, end: Long): List<ProfileElement> { private fun getProfiles(start: Long, end: Long): List<ProfileElement> {
val pss = MainApp.getDbHelper().getProfileSwitchEventsFromTime(start, end, true) val pss = MainApp.getDbHelper().getProfileSwitchEventsFromTime(start, end, true)
val selection = LinkedList<ProfileElement>() val selection = LinkedList<ProfileElement>()
for (ps in pss) { for (ps in pss) {
ProfileElement.newInstanceOrNull(ps)?.let { selection.add(it) } newInstanceOrNull(ps)?.let { selection.add(it) }
} }
if (selection.size > 0) if (selection.size > 0)
rxBus.send(EventTidepoolStatus("${selection.size} ProfileSwitches selected for upload")) rxBus.send(EventTidepoolStatus("${selection.size} ProfileSwitches selected for upload"))

View file

@ -1,12 +1,11 @@
package info.nightscout.androidaps.plugins.general.tidepool.elements package info.nightscout.androidaps.plugins.general.tidepool.elements
import com.google.gson.annotations.Expose import com.google.gson.annotations.Expose
import info.nightscout.androidaps.data.Intervals
import info.nightscout.androidaps.db.TemporaryBasal import info.nightscout.androidaps.db.TemporaryBasal
import info.nightscout.androidaps.plugins.configBuilder.ProfileFunctions import info.nightscout.androidaps.plugins.configBuilder.ProfileFunction
import java.util.* import java.util.*
class BasalElement(tbr: TemporaryBasal) class BasalElement(tbr: TemporaryBasal, private val profileFunction: ProfileFunction)
: BaseElement(tbr.date, UUID.nameUUIDFromBytes(("AAPS-basal" + tbr.date).toByteArray()).toString()) { : BaseElement(tbr.date, UUID.nameUUIDFromBytes(("AAPS-basal" + tbr.date).toByteArray()).toString()) {
internal var timestamp: Long = 0 // not exposed internal var timestamp: Long = 0 // not exposed
@ -27,18 +26,7 @@ class BasalElement(tbr: TemporaryBasal)
init { init {
type = "basal" type = "basal"
timestamp = tbr.date timestamp = tbr.date
rate = tbr.tempBasalConvertedToAbsolute(tbr.date, ProfileFunctions.getInstance().getProfile(tbr.date)) rate = tbr.tempBasalConvertedToAbsolute(tbr.date, profileFunction.getProfile(tbr.date))
duration = tbr.end() - tbr.start() duration = tbr.end() - tbr.start()
} }
companion object {
internal fun fromTemporaryBasals(tbrList: Intervals<TemporaryBasal>, start: Long, end: Long): List<BasalElement> {
val results = LinkedList<BasalElement>()
for (tbr in tbrList.list) {
if (tbr.date >= start && tbr.date <= end && tbr.durationInMinutes != 0)
results.add(BasalElement(tbr))
}
return results
}
}
} }

View file

@ -9,7 +9,7 @@ import info.nightscout.androidaps.utils.InstanceId
import java.util.* import java.util.*
import kotlin.collections.ArrayList import kotlin.collections.ArrayList
class ProfileElement private constructor(ps: ProfileSwitch) class ProfileElement(ps: ProfileSwitch, serialNumber: String)
: BaseElement(ps.date, UUID.nameUUIDFromBytes(("AAPS-profile" + ps.date).toByteArray()).toString()) { : BaseElement(ps.date, UUID.nameUUIDFromBytes(("AAPS-profile" + ps.date).toByteArray()).toString()) {
@Expose @Expose
@ -25,11 +25,9 @@ class ProfileElement private constructor(ps: ProfileSwitch)
@Expose @Expose
internal var insulinSensitivities: IsfProfile = IsfProfile() internal var insulinSensitivities: IsfProfile = IsfProfile()
@Expose @Expose
internal var deviceId: String = TidepoolUploader.PUMP_TYPE + ":" + (ConfigBuilderPlugin.getPlugin().activePump?.serialNumber() internal var deviceId: String = TidepoolUploader.PUMP_TYPE + ":" + serialNumber
?: InstanceId.instanceId())
@Expose @Expose
internal var deviceSerialNumber: String = ConfigBuilderPlugin.getPlugin().activePump?.serialNumber() internal var deviceSerialNumber: String = serialNumber
?: InstanceId.instanceId()
@Expose @Expose
internal var clockDriftOffset: Long = 0 internal var clockDriftOffset: Long = 0
@Expose @Expose
@ -96,16 +94,6 @@ class ProfileElement private constructor(ps: ProfileSwitch)
@field:Expose @field:Expose
internal var amount: Double internal var amount: Double
) )
companion object {
@JvmStatic
fun newInstanceOrNull(ps: ProfileSwitch): ProfileElement? = try {
ProfileElement(ps)
} catch (e: Throwable) {
null
}
}
} }

View file

@ -1,17 +1,17 @@
package info.nightscout.androidaps.plugins.general.tidepool.messages package info.nightscout.androidaps.plugins.general.tidepool.messages
import info.nightscout.androidaps.R import info.nightscout.androidaps.R
import info.nightscout.androidaps.utils.SP
import info.nightscout.androidaps.utils.StringUtils import info.nightscout.androidaps.utils.StringUtils
import info.nightscout.androidaps.utils.sharedPreferences.SP
import okhttp3.Credentials import okhttp3.Credentials
class AuthRequestMessage : BaseMessage() { class AuthRequestMessage : BaseMessage() {
companion object { companion object {
fun getAuthRequestHeader(): String? { fun getAuthRequestHeader(sp: SP): String? {
val username = SP.getString(R.string.key_tidepool_username, null) val username = sp.getStringOrNull(R.string.key_tidepool_username, null)
val password = SP.getString(R.string.key_tidepool_password, null) val password = sp.getStringOrNull(R.string.key_tidepool_password, null)
return if (StringUtils.emptyString(username) || StringUtils.emptyString(password)) null else Credentials.basic(username.trim { it <= ' ' }, password) return if (StringUtils.emptyString(username) || StringUtils.emptyString(password)) null else Credentials.basic(username!!.trim { it <= ' ' }, password!!)
} }
} }
} }

View file

@ -9,11 +9,10 @@ import info.nightscout.androidaps.utils.InstanceId
import info.nightscout.androidaps.utils.T import info.nightscout.androidaps.utils.T
import java.util.* import java.util.*
class OpenDatasetRequestMessage : BaseMessage() { class OpenDatasetRequestMessage (val serialNumber : String): BaseMessage() {
@Expose @Expose
var deviceId: String = TidepoolUploader.PUMP_TYPE + ":" + (ConfigBuilderPlugin.getPlugin().activePump?.serialNumber() var deviceId: String = TidepoolUploader.PUMP_TYPE + ":" + serialNumber
?: InstanceId.instanceId())
@Expose @Expose
var time = DateUtil.toISOAsUTC(DateUtil.now()) var time = DateUtil.toISOAsUTC(DateUtil.now())
@Expose @Expose

View file

@ -15,6 +15,7 @@ interface SP {
fun remove(@StringRes resourceID: Int) fun remove(@StringRes resourceID: Int)
fun remove(key: String) fun remove(key: String)
fun getString(@StringRes resourceID: Int, defaultValue: String): String fun getString(@StringRes resourceID: Int, defaultValue: String): String
fun getStringOrNull(@StringRes resourceID: Int, defaultValue: String?): String?
fun getString(key: String, defaultValue: String): String fun getString(key: String, defaultValue: String): String
fun getBoolean(@StringRes resourceID: Int, defaultValue: Boolean): Boolean fun getBoolean(@StringRes resourceID: Int, defaultValue: Boolean): Boolean
fun getBoolean(key: String, defaultValue: Boolean): Boolean fun getBoolean(key: String, defaultValue: Boolean): Boolean

View file

@ -31,6 +31,9 @@ class SPImplementation @Inject constructor(
override fun getString(resourceID: Int, defaultValue: String): String = override fun getString(resourceID: Int, defaultValue: String): String =
sharedPreferences.getString(resourceHelper.gs(resourceID), defaultValue) ?: defaultValue sharedPreferences.getString(resourceHelper.gs(resourceID), defaultValue) ?: defaultValue
override fun getStringOrNull(resourceID: Int, defaultValue: String?): String? =
sharedPreferences.getString(resourceHelper.gs(resourceID), defaultValue) ?: defaultValue
override fun getString(key: String, defaultValue: String): String = override fun getString(key: String, defaultValue: String): String =
sharedPreferences.getString(key, defaultValue) ?: defaultValue sharedPreferences.getString(key, defaultValue) ?: defaultValue