better null checks
This commit is contained in:
parent
6d2e159edb
commit
beb4e004bf
8 changed files with 103 additions and 74 deletions
|
@ -5,6 +5,7 @@ import android.text.Spanned
|
|||
import info.nightscout.androidaps.Constants
|
||||
import info.nightscout.androidaps.MainApp
|
||||
import info.nightscout.androidaps.R
|
||||
import info.nightscout.androidaps.db.BgReading
|
||||
import info.nightscout.androidaps.events.EventNetworkChange
|
||||
import info.nightscout.androidaps.events.EventNewBG
|
||||
import info.nightscout.androidaps.events.EventPreferenceChange
|
||||
|
@ -30,7 +31,6 @@ import io.reactivex.schedulers.Schedulers
|
|||
import org.slf4j.LoggerFactory
|
||||
import java.util.*
|
||||
|
||||
|
||||
object TidepoolPlugin : PluginBase(PluginDescription()
|
||||
.mainType(PluginType.GENERAL)
|
||||
.pluginName(R.string.tidepool)
|
||||
|
@ -39,6 +39,7 @@ object TidepoolPlugin : PluginBase(PluginDescription()
|
|||
.preferencesId(R.xml.pref_tidepool)
|
||||
.description(R.string.description_tidepool)
|
||||
) {
|
||||
|
||||
private val log = LoggerFactory.getLogger(L.TIDEPOOL)
|
||||
private var disposable: CompositeDisposable = CompositeDisposable()
|
||||
|
||||
|
@ -75,15 +76,17 @@ object TidepoolPlugin : PluginBase(PluginDescription()
|
|||
disposable += RxBus
|
||||
.toObservable(EventNewBG::class.java)
|
||||
.observeOn(Schedulers.io())
|
||||
.subscribe({ event ->
|
||||
if (event.bgReading!!.date < TidepoolUploader.getLastEnd())
|
||||
TidepoolUploader.setLastEnd(event.bgReading.date)
|
||||
.filter { it.bgReading != null } // better would be optional in API level >24
|
||||
.map { it.bgReading }
|
||||
.subscribe { bgReading ->
|
||||
if (bgReading!!.date < TidepoolUploader.getLastEnd())
|
||||
TidepoolUploader.setLastEnd(bgReading.date)
|
||||
if (isEnabled(PluginType.GENERAL)
|
||||
&& (!SP.getBoolean(R.string.key_tidepool_only_while_charging, false) || ChargingStateReceiver.isCharging())
|
||||
&& (!SP.getBoolean(R.string.key_tidepool_only_while_unmetered, false) || NetworkChangeReceiver.isWifiConnected())
|
||||
&& RateLimit.rateLimit("tidepool-new-data-upload", T.mins(4).secs().toInt()))
|
||||
doUpload()
|
||||
}, {})
|
||||
}
|
||||
disposable += RxBus
|
||||
.toObservable(EventPreferenceChange::class.java)
|
||||
.observeOn(Schedulers.io())
|
||||
|
|
|
@ -19,14 +19,14 @@ class InfoInterceptor(tag: String) : Interceptor {
|
|||
@Throws(IOException::class)
|
||||
override fun intercept(chain: Interceptor.Chain): Response {
|
||||
val request = chain.request()
|
||||
if (request?.body() != null) {
|
||||
request?.body()?.let {
|
||||
if (L.isEnabled(L.TIDEPOOL)) {
|
||||
log.debug("Interceptor Body size: " + request.body()!!.contentLength())
|
||||
log.debug("Interceptor Body size: " + it.contentLength())
|
||||
val requestBuffer = Buffer()
|
||||
request.body()!!.writeTo(requestBuffer)
|
||||
it.writeTo(requestBuffer)
|
||||
log.debug("Interceptor Body: " + requestBuffer.readUtf8())
|
||||
}
|
||||
}
|
||||
return chain.proceed(request!!)
|
||||
return chain.proceed(request)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,7 +4,7 @@ import info.nightscout.androidaps.plugins.general.tidepool.messages.AuthReplyMes
|
|||
import info.nightscout.androidaps.plugins.general.tidepool.messages.DatasetReplyMessage
|
||||
import okhttp3.Headers
|
||||
|
||||
class Session (var authHeader: String?, private var sessionTokenHeader: String) {
|
||||
class Session(var authHeader: String?, private var sessionTokenHeader: String) {
|
||||
|
||||
val service = TidepoolUploader.getRetrofitInstance()?.create(TidepoolApiService::class.java)
|
||||
|
||||
|
@ -28,9 +28,12 @@ class Session (var authHeader: String?, private var sessionTokenHeader: String)
|
|||
if (obj is AuthReplyMessage) {
|
||||
authReply = obj
|
||||
} else if (obj is List<*>) {
|
||||
val list = obj as List<*>?
|
||||
if (list!!.isNotEmpty() && list[0] is DatasetReplyMessage) {
|
||||
datasetReply = list[0] as DatasetReplyMessage
|
||||
val list = obj as? List<*>?
|
||||
|
||||
list?.getOrNull(0)?.let {
|
||||
if (it is DatasetReplyMessage) {
|
||||
datasetReply = it
|
||||
}
|
||||
}
|
||||
} else if (obj is DatasetReplyMessage) {
|
||||
datasetReply = obj
|
||||
|
|
|
@ -6,8 +6,8 @@ import android.os.SystemClock
|
|||
import info.nightscout.androidaps.BuildConfig
|
||||
import info.nightscout.androidaps.MainApp
|
||||
import info.nightscout.androidaps.R
|
||||
import info.nightscout.androidaps.plugins.bus.RxBus
|
||||
import info.nightscout.androidaps.logging.L
|
||||
import info.nightscout.androidaps.plugins.bus.RxBus
|
||||
import info.nightscout.androidaps.plugins.general.tidepool.events.EventTidepoolStatus
|
||||
import info.nightscout.androidaps.plugins.general.tidepool.messages.*
|
||||
import info.nightscout.androidaps.utils.DateUtil
|
||||
|
@ -28,7 +28,6 @@ object TidepoolUploader {
|
|||
|
||||
private var wl: PowerManager.WakeLock? = null
|
||||
|
||||
|
||||
private const val INTEGRATION_BASE_URL = "https://int-api.tidepool.org"
|
||||
private const val PRODUCTION_BASE_URL = "https://api.tidepool.org"
|
||||
|
||||
|
@ -82,10 +81,11 @@ object TidepoolUploader {
|
|||
// TODO failure backoff
|
||||
extendWakeLock(30000)
|
||||
session = Session(AuthRequestMessage.getAuthRequestHeader(), SESSION_TOKEN_HEADER)
|
||||
if (session?.authHeader != null) {
|
||||
val authHeader = session?.authHeader
|
||||
if (authHeader != null) {
|
||||
connectionStatus = TidepoolUploader.ConnectionStatus.CONNECTING
|
||||
RxBus.send(EventTidepoolStatus(("Connecting")))
|
||||
val call = session!!.service?.getLogin(session?.authHeader!!)
|
||||
val call = session?.service?.getLogin(authHeader)
|
||||
|
||||
call?.enqueue(TidepoolCallback<AuthReplyMessage>(session!!, "Login", {
|
||||
startSession(session!!, doUpload)
|
||||
|
@ -105,22 +105,20 @@ object TidepoolUploader {
|
|||
|
||||
fun testLogin(rootContext: Context) {
|
||||
val session = Session(AuthRequestMessage.getAuthRequestHeader(), SESSION_TOKEN_HEADER)
|
||||
if (session.authHeader != null) {
|
||||
val call = session.service!!.getLogin(session.authHeader!!)
|
||||
session.authHeader?.let {
|
||||
val call = session.service?.getLogin(it)
|
||||
|
||||
call.enqueue(TidepoolCallback<AuthReplyMessage>(session, "Login", {
|
||||
call?.enqueue(TidepoolCallback<AuthReplyMessage>(session, "Login", {
|
||||
OKDialog.show(rootContext, MainApp.gs(R.string.tidepool), "Successfully logged into Tidepool.", null)
|
||||
}, {
|
||||
OKDialog.show(rootContext, MainApp.gs(R.string.tidepool), "Failed to log into Tidepool.\nCheck that your user name and password are correct.", null)
|
||||
}))
|
||||
|
||||
} else {
|
||||
OKDialog.show(rootContext, MainApp.gs(R.string.tidepool), "Cannot do login as user credentials have not been set correctly", null)
|
||||
}
|
||||
?: OKDialog.show(rootContext, MainApp.gs(R.string.tidepool), "Cannot do login as user credentials have not been set correctly", null)
|
||||
|
||||
}
|
||||
|
||||
|
||||
private fun loginFailed() {
|
||||
releaseWakeLock()
|
||||
}
|
||||
|
@ -173,32 +171,35 @@ object TidepoolUploader {
|
|||
|
||||
@Synchronized
|
||||
fun doUpload() {
|
||||
session.let { session ->
|
||||
if (session == null) {
|
||||
log.error("Session is null, cannot proceed")
|
||||
releaseWakeLock()
|
||||
return
|
||||
}
|
||||
extendWakeLock(60000)
|
||||
session!!.iterations++
|
||||
session.iterations++
|
||||
val chunk = UploadChunk.getNext(session)
|
||||
when {
|
||||
chunk == null -> {
|
||||
log.error("Upload chunk is null, cannot proceed")
|
||||
releaseWakeLock()
|
||||
}
|
||||
|
||||
chunk.length == 2 -> {
|
||||
if (L.isEnabled(L.TIDEPOOL)) log.debug("Empty dataset - marking as succeeded")
|
||||
RxBus.send(EventTidepoolStatus(("No data to upload")))
|
||||
releaseWakeLock()
|
||||
unploadNext()
|
||||
}
|
||||
|
||||
else -> {
|
||||
val body = RequestBody.create(MediaType.parse("application/json"), chunk)
|
||||
|
||||
RxBus.send(EventTidepoolStatus(("Uploading")))
|
||||
val call = session!!.service!!.doUpload(session!!.token!!, session!!.datasetReply!!.getUploadId()!!, body)
|
||||
call.enqueue(TidepoolCallback<UploadReplyMessage>(session!!, "Data Upload", {
|
||||
setLastEnd(session!!.end)
|
||||
val call = session.service!!.doUpload(session.token!!, session.datasetReply!!.getUploadId()!!, body)
|
||||
call.enqueue(TidepoolCallback<UploadReplyMessage>(session, "Data Upload", {
|
||||
setLastEnd(session.end)
|
||||
RxBus.send(EventTidepoolStatus(("Upload completed OK")))
|
||||
releaseWakeLock()
|
||||
unploadNext()
|
||||
|
@ -209,6 +210,7 @@ object TidepoolUploader {
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun unploadNext() {
|
||||
if (getLastEnd() < DateUtil.now() - T.mins(1).msecs()) {
|
||||
|
@ -238,10 +240,16 @@ object TidepoolUploader {
|
|||
}
|
||||
|
||||
fun deleteAllData() {
|
||||
if (session!!.authReply!!.userid != null) {
|
||||
val session = this.session
|
||||
val token = session?.token
|
||||
val userid = session?.authReply?.userid
|
||||
try {
|
||||
requireNotNull(session)
|
||||
requireNotNull(token)
|
||||
requireNotNull(userid)
|
||||
extendWakeLock(60000)
|
||||
val call = session!!.service?.deleteAllData(session!!.token!!, session!!.authReply!!.userid!!)
|
||||
call?.enqueue(TidepoolCallback(session!!, "Delete all data", {
|
||||
val call = session.service?.deleteAllData(token, userid)
|
||||
call?.enqueue(TidepoolCallback(session, "Delete all data", {
|
||||
connectionStatus = TidepoolUploader.ConnectionStatus.DISCONNECTED
|
||||
RxBus.send(EventTidepoolStatus(("All data removed OK")))
|
||||
releaseWakeLock()
|
||||
|
@ -250,7 +258,7 @@ object TidepoolUploader {
|
|||
RxBus.send(EventTidepoolStatus(("All data remove FAILED")))
|
||||
releaseWakeLock()
|
||||
}))
|
||||
} else {
|
||||
} catch (e: IllegalArgumentException) {
|
||||
log.error("Got login response but cannot determine userId - cannot proceed")
|
||||
}
|
||||
}
|
||||
|
@ -271,7 +279,6 @@ object TidepoolUploader {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
@Synchronized
|
||||
private fun extendWakeLock(ms: Long) {
|
||||
if (wl == null) {
|
||||
|
@ -286,14 +293,15 @@ object TidepoolUploader {
|
|||
|
||||
@Synchronized
|
||||
private fun releaseWakeLock() {
|
||||
if (wl == null) return
|
||||
if (wl!!.isHeld) {
|
||||
wl?.let {
|
||||
if (it.isHeld) {
|
||||
try {
|
||||
wl!!.release()
|
||||
it.release()
|
||||
} catch (e: Exception) {
|
||||
log.error("Error releasing wakelock: $e")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -120,8 +120,7 @@ object UploadChunk {
|
|||
val pss = MainApp.getDbHelper().getProfileSwitchEventsFromTime(start, end, true)
|
||||
val selection = LinkedList<ProfileElement>()
|
||||
for (ps in pss) {
|
||||
val pe = ProfileElement(ps)
|
||||
selection.add(pe)
|
||||
ProfileElement.newInstanceOrNull(ps)?.let { selection.add(it) }
|
||||
}
|
||||
if (selection.size > 0)
|
||||
RxBus.send(EventTidepoolStatus("${selection.size} ProfileSwitches selected for upload"))
|
||||
|
|
|
@ -9,7 +9,7 @@ import info.nightscout.androidaps.utils.InstanceId
|
|||
import java.util.*
|
||||
import kotlin.collections.ArrayList
|
||||
|
||||
class ProfileElement(ps: ProfileSwitch)
|
||||
class ProfileElement private constructor(ps: ProfileSwitch)
|
||||
: BaseElement(ps.date, UUID.nameUUIDFromBytes(("AAPS-profile" + ps.date).toByteArray()).toString()) {
|
||||
|
||||
@Expose
|
||||
|
@ -25,9 +25,11 @@ class ProfileElement(ps: ProfileSwitch)
|
|||
@Expose
|
||||
internal var insulinSensitivities: IsfProfile = IsfProfile()
|
||||
@Expose
|
||||
internal var deviceId: String = TidepoolUploader.PUMPTYPE + ":" + (ConfigBuilderPlugin.getPlugin().activePump?.serialNumber() ?: InstanceId.instanceId())
|
||||
internal var deviceId: String = TidepoolUploader.PUMPTYPE + ":" + (ConfigBuilderPlugin.getPlugin().activePump?.serialNumber()
|
||||
?: InstanceId.instanceId())
|
||||
@Expose
|
||||
internal var deviceSerialNumber: String = ConfigBuilderPlugin.getPlugin().activePump?.serialNumber() ?: InstanceId.instanceId()
|
||||
internal var deviceSerialNumber: String = ConfigBuilderPlugin.getPlugin().activePump?.serialNumber()
|
||||
?: InstanceId.instanceId()
|
||||
@Expose
|
||||
internal var clockDriftOffset: Long = 0
|
||||
@Expose
|
||||
|
@ -35,7 +37,8 @@ class ProfileElement(ps: ProfileSwitch)
|
|||
|
||||
init {
|
||||
type = "pumpSettings"
|
||||
val profile: Profile = ps.getProfileObject()!!
|
||||
val profile: Profile? = ps.profileObject
|
||||
checkNotNull(profile)
|
||||
for (br in profile.basalValues)
|
||||
basalSchedules.Normal.add(BasalRate(br.timeAsSeconds * 1000, br.value))
|
||||
for (target in profile.singleTargets)
|
||||
|
@ -94,4 +97,15 @@ class ProfileElement(ps: ProfileSwitch)
|
|||
internal var amount: Double
|
||||
)
|
||||
|
||||
companion object {
|
||||
@JvmStatic
|
||||
fun newInstanceOrNull(ps: ProfileSwitch): ProfileElement? = try {
|
||||
ProfileElement(ps)
|
||||
} catch (e: Throwable) {
|
||||
null
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -16,11 +16,13 @@ object RateLimit {
|
|||
@Synchronized
|
||||
fun rateLimit(name: String, seconds: Int): Boolean {
|
||||
// check if over limit
|
||||
if (rateLimits.containsKey(name) && DateUtil.now() - rateLimits[name]!! < T.secs(seconds.toLong()).msecs()) {
|
||||
rateLimits[name]?.let {
|
||||
if (DateUtil.now() - it < T.secs(seconds.toLong()).msecs()) {
|
||||
if (L.isEnabled(L.TIDEPOOL))
|
||||
log.debug("$name rate limited: $seconds seconds")
|
||||
return false
|
||||
}
|
||||
}
|
||||
// not over limit
|
||||
rateLimits[name] = DateUtil.now()
|
||||
return true
|
||||
|
|
|
@ -188,7 +188,7 @@ class BolusWizard @JvmOverloads constructor(val profile: Profile,
|
|||
calculatedTotalInsulin = 0.0
|
||||
}
|
||||
|
||||
val bolusStep = ConfigBuilderPlugin.getPlugin().activePump?.pumpDescription!!.bolusStep
|
||||
val bolusStep = ConfigBuilderPlugin.getPlugin().activePump?.pumpDescription?.bolusStep ?: 0.1
|
||||
calculatedTotalInsulin = Round.roundTo(calculatedTotalInsulin, bolusStep)
|
||||
|
||||
insulinAfterConstraints = MainApp.getConstraintChecker().applyBolusConstraints(Constraint(calculatedTotalInsulin)).value()
|
||||
|
@ -318,7 +318,7 @@ class BolusWizard @JvmOverloads constructor(val profile: Profile,
|
|||
detailedBolusInfo.boluscalc = nsJSON()
|
||||
detailedBolusInfo.source = Source.USER
|
||||
detailedBolusInfo.notes = notes
|
||||
if (detailedBolusInfo.insulin > 0 || ConfigBuilderPlugin.getPlugin().activePump?.pumpDescription!!.storesCarbInfo) {
|
||||
if (detailedBolusInfo.insulin > 0 || ConfigBuilderPlugin.getPlugin().activePump?.pumpDescription?.storesCarbInfo == true) {
|
||||
ConfigBuilderPlugin.getPlugin().commandQueue.bolus(detailedBolusInfo, object : Callback() {
|
||||
override fun run() {
|
||||
if (!result.success) {
|
||||
|
|
Loading…
Reference in a new issue