NSClient: missing initial profile workaround
This commit is contained in:
parent
60c14cda21
commit
3d94f3f840
6 changed files with 120 additions and 77 deletions
|
@ -18,6 +18,7 @@ import info.nightscout.androidaps.plugins.configBuilder.ProfileFunctionImplement
|
|||
import info.nightscout.androidaps.plugins.general.maintenance.ImportExportPrefsImpl
|
||||
import info.nightscout.androidaps.plugins.general.maintenance.PrefFileListProvider
|
||||
import info.nightscout.androidaps.plugins.general.nsclient.DataSyncSelectorImplementation
|
||||
import info.nightscout.androidaps.plugins.general.nsclient.data.DeviceStatusData
|
||||
import info.nightscout.androidaps.plugins.general.smsCommunicator.SmsCommunicatorPlugin
|
||||
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.IobCobCalculatorPlugin
|
||||
import info.nightscout.androidaps.plugins.pump.PumpSyncImplementation
|
||||
|
@ -76,11 +77,11 @@ open class AppModule {
|
|||
aapsLogger: AAPSLogger, sp: SP, rxBus: RxBus, resourceHelper:
|
||||
ResourceHelper, activePlugin:
|
||||
ActivePlugin, repository: AppRepository, dateUtil: DateUtil, config: Config, hardLimits: HardLimits,
|
||||
aapsSchedulers: AapsSchedulers, fabricPrivacy: FabricPrivacy
|
||||
aapsSchedulers: AapsSchedulers, fabricPrivacy: FabricPrivacy, deviceStatusData: DeviceStatusData
|
||||
): ProfileFunction =
|
||||
ProfileFunctionImplementation(
|
||||
aapsLogger, sp, rxBus, resourceHelper, activePlugin, repository, dateUtil,
|
||||
config, hardLimits, aapsSchedulers, fabricPrivacy
|
||||
config, hardLimits, aapsSchedulers, fabricPrivacy, deviceStatusData
|
||||
)
|
||||
|
||||
@Module
|
||||
|
|
|
@ -14,6 +14,7 @@ import info.nightscout.androidaps.interfaces.*
|
|||
import info.nightscout.androidaps.logging.AAPSLogger
|
||||
import info.nightscout.androidaps.logging.LTag
|
||||
import info.nightscout.androidaps.plugins.bus.RxBus
|
||||
import info.nightscout.androidaps.plugins.general.nsclient.data.DeviceStatusData
|
||||
import info.nightscout.androidaps.utils.DateUtil
|
||||
import info.nightscout.androidaps.utils.FabricPrivacy
|
||||
import info.nightscout.androidaps.utils.HardLimits
|
||||
|
@ -39,7 +40,8 @@ class ProfileFunctionImplementation @Inject constructor(
|
|||
private val config: Config,
|
||||
private val hardLimits: HardLimits,
|
||||
aapsSchedulers: AapsSchedulers,
|
||||
private val fabricPrivacy: FabricPrivacy
|
||||
private val fabricPrivacy: FabricPrivacy,
|
||||
private val deviceStatusData: DeviceStatusData
|
||||
) : ProfileFunction {
|
||||
|
||||
val cache = LongSparseArray<Profile>()
|
||||
|
@ -113,6 +115,23 @@ class ProfileFunctionImplementation @Inject constructor(
|
|||
}
|
||||
return sealed
|
||||
}
|
||||
// In NSClient mode effective profile may not be received if older than 2 days
|
||||
// Try to get it from device status
|
||||
// Remove this code after switch to api v3
|
||||
if (config.NSCLIENT && ps is ValueWrapper.Absent) {
|
||||
deviceStatusData.pumpData?.activeProfileName?.let { activeProfile ->
|
||||
activePlugin.activeProfileSource.profile?.getSpecificProfile(activeProfile)?.let { ap ->
|
||||
val sealed = ProfileSealed.Pure(ap)
|
||||
synchronized(cache) {
|
||||
cache.put(rounded, sealed)
|
||||
}
|
||||
return sealed
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return null
|
||||
}
|
||||
|
||||
|
|
|
@ -15,6 +15,7 @@ import info.nightscout.androidaps.logging.LTag
|
|||
import info.nightscout.androidaps.plugins.aps.events.EventOpenAPSUpdateGui
|
||||
import info.nightscout.androidaps.plugins.aps.loop.LoopPlugin
|
||||
import info.nightscout.androidaps.plugins.bus.RxBus
|
||||
import info.nightscout.androidaps.plugins.general.nsclient.data.DeviceStatusData
|
||||
import info.nightscout.androidaps.plugins.general.nsclient.data.NSDeviceStatus
|
||||
import info.nightscout.androidaps.plugins.general.overview.events.EventOverviewBolusProgress
|
||||
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.GlucoseStatusProvider
|
||||
|
@ -43,6 +44,7 @@ class DataBroadcastPlugin @Inject constructor(
|
|||
private val profileFunction: ProfileFunction,
|
||||
private val defaultValueHelper: DefaultValueHelper,
|
||||
private val nsDeviceStatus: NSDeviceStatus,
|
||||
private val deviceStatusData: DeviceStatusData,
|
||||
private val loopPlugin: LoopPlugin,
|
||||
private val activePlugin: ActivePlugin,
|
||||
private var receiverStatusStore: ReceiverStatusStore,
|
||||
|
@ -158,7 +160,7 @@ class DataBroadcastPlugin @Inject constructor(
|
|||
bundle.putString("enacted", loopPlugin.lastRun?.request?.json().toString())
|
||||
}
|
||||
} else { //NSClient or remote
|
||||
val data = nsDeviceStatus.deviceStatusOpenAPSData
|
||||
val data = deviceStatusData.openAPSData
|
||||
if (data.clockSuggested != 0L && data.suggested != null) {
|
||||
bundle.putLong("suggestedTimeStamp", data.clockSuggested)
|
||||
bundle.putString("suggested", data.suggested.toString())
|
||||
|
|
|
@ -0,0 +1,41 @@
|
|||
package info.nightscout.androidaps.plugins.general.nsclient.data
|
||||
|
||||
import android.text.Spanned
|
||||
import org.json.JSONObject
|
||||
import java.util.HashMap
|
||||
import javax.inject.Inject
|
||||
import javax.inject.Singleton
|
||||
|
||||
@Singleton
|
||||
class DeviceStatusData @Inject constructor() {
|
||||
|
||||
class PumpData {
|
||||
var clock = 0L
|
||||
var isPercent = false
|
||||
var percent = 0
|
||||
var voltage = 0.0
|
||||
var status = "N/A"
|
||||
var reservoir = 0.0
|
||||
var extended: Spanned? = null
|
||||
var activeProfileName: String? = null
|
||||
}
|
||||
|
||||
var pumpData: PumpData? = null
|
||||
|
||||
class Uploader {
|
||||
var clock = 0L
|
||||
var battery = 0
|
||||
}
|
||||
|
||||
val uploaderMap = HashMap<String, Uploader>()
|
||||
|
||||
class OpenAPSData {
|
||||
var clockSuggested = 0L
|
||||
var clockEnacted = 0L
|
||||
var suggested: JSONObject? = null
|
||||
var enacted: JSONObject? = null
|
||||
}
|
||||
|
||||
var openAPSData = OpenAPSData()
|
||||
}
|
||||
|
|
@ -10,6 +10,7 @@ import info.nightscout.androidaps.plugins.aps.loop.APSResult
|
|||
import info.nightscout.androidaps.plugins.configBuilder.RunningConfiguration
|
||||
import info.nightscout.androidaps.utils.DateUtil
|
||||
import info.nightscout.androidaps.utils.HtmlHelper.fromHtml
|
||||
import info.nightscout.androidaps.utils.JsonHelper
|
||||
import info.nightscout.androidaps.utils.Round
|
||||
import info.nightscout.androidaps.utils.T
|
||||
import info.nightscout.androidaps.utils.resources.ResourceHelper
|
||||
|
@ -80,12 +81,13 @@ class NSDeviceStatus @Inject constructor(
|
|||
private val nsSettingsStatus: NSSettingsStatus,
|
||||
private val config: Config,
|
||||
private val dateUtil: DateUtil,
|
||||
private val runningConfiguration: RunningConfiguration
|
||||
private val runningConfiguration: RunningConfiguration,
|
||||
private val deviceStatusData: DeviceStatusData
|
||||
) {
|
||||
|
||||
private var data: JSONObject? = null
|
||||
fun handleNewData(deviceStatuses: JSONArray) {
|
||||
aapsLogger.debug(LTag.NSCLIENT, "Got NS deviceStatus: \$deviceStatuses}")
|
||||
aapsLogger.debug(LTag.NSCLIENT, "Got NS deviceStatus: \$deviceStatuses")
|
||||
try {
|
||||
for (i in 0 until deviceStatuses.length()) {
|
||||
val devicestatusJson = deviceStatuses.getJSONObject(i)
|
||||
|
@ -145,16 +147,13 @@ class NSDeviceStatus @Inject constructor(
|
|||
}
|
||||
}
|
||||
|
||||
// ***** PUMP DATA ******
|
||||
private var deviceStatusPumpData: DeviceStatusPumpData? = null
|
||||
|
||||
val extendedPumpStatus: Spanned
|
||||
get() = deviceStatusPumpData?.extended ?: fromHtml("")
|
||||
get() = deviceStatusData.pumpData?.extended ?: fromHtml("")
|
||||
|
||||
val pumpStatus: Spanned
|
||||
// test warning level // color
|
||||
get() {
|
||||
val pumpData = deviceStatusPumpData ?: return fromHtml("")
|
||||
val pumpData = deviceStatusData.pumpData ?: return fromHtml("")
|
||||
|
||||
//String[] ALL_STATUS_FIELDS = {"reservoir", "battery", "clock", "status", "device"};
|
||||
val string = StringBuilder()
|
||||
|
@ -186,27 +185,16 @@ class NSDeviceStatus @Inject constructor(
|
|||
return fromHtml(string.toString())
|
||||
}
|
||||
|
||||
internal class DeviceStatusPumpData {
|
||||
|
||||
var clock = 0L
|
||||
var isPercent = false
|
||||
var percent = 0
|
||||
var voltage = 0.0
|
||||
var status = "N/A"
|
||||
var reservoir = 0.0
|
||||
var extended: Spanned? = null
|
||||
}
|
||||
|
||||
private fun updatePumpData() {
|
||||
try {
|
||||
val data = this.data ?: return
|
||||
val pump = if (data.has("pump")) data.getJSONObject("pump") else JSONObject()
|
||||
val clock = if (pump.has("clock")) dateUtil.fromISODateString(pump.getString("clock")) else 0L
|
||||
// check if this is new data
|
||||
if (clock == 0L || deviceStatusPumpData != null && clock < deviceStatusPumpData!!.clock) return
|
||||
if (clock == 0L || deviceStatusData.pumpData != null && clock < deviceStatusData.pumpData!!.clock) return
|
||||
|
||||
// create new status and process data
|
||||
val deviceStatusPumpData = DeviceStatusPumpData()
|
||||
var deviceStatusPumpData = DeviceStatusData.PumpData()
|
||||
deviceStatusPumpData.clock = clock
|
||||
if (pump.has("status") && pump.getJSONObject("status").has("status")) deviceStatusPumpData.status = pump.getJSONObject("status").getString("status")
|
||||
if (pump.has("reservoir")) deviceStatusPumpData.reservoir = pump.getDouble("reservoir")
|
||||
|
@ -227,21 +215,14 @@ class NSDeviceStatus @Inject constructor(
|
|||
extended.append("<b>").append(key).append(":</b> ").append(value).append("<br>")
|
||||
}
|
||||
deviceStatusPumpData.extended = fromHtml(extended.toString())
|
||||
deviceStatusPumpData.activeProfileName = JsonHelper.safeGetStringAllowNull(extendedJson, "ActiveProfile", null)
|
||||
}
|
||||
this.deviceStatusPumpData = deviceStatusPumpData
|
||||
deviceStatusData.pumpData = deviceStatusPumpData
|
||||
} catch (e: Exception) {
|
||||
aapsLogger.error("Unhandled exception", e)
|
||||
}
|
||||
}
|
||||
|
||||
class DeviceStatusOpenAPSData {
|
||||
|
||||
var clockSuggested = 0L
|
||||
var clockEnacted = 0L
|
||||
var suggested: JSONObject? = null
|
||||
var enacted: JSONObject? = null
|
||||
}
|
||||
|
||||
private fun updateOpenApsData(jsonObject: JSONObject) {
|
||||
try {
|
||||
val openAps = if (jsonObject.has("openaps")) jsonObject.getJSONObject("openaps") else JSONObject()
|
||||
|
@ -249,15 +230,15 @@ class NSDeviceStatus @Inject constructor(
|
|||
val enacted = if (openAps.has("enacted")) openAps.getJSONObject("enacted") else JSONObject()
|
||||
var clock = if (suggested.has("timestamp")) dateUtil.fromISODateString(suggested.getString("timestamp")) else 0L
|
||||
// check if this is new data
|
||||
if (clock != 0L && clock > deviceStatusOpenAPSData.clockSuggested) {
|
||||
deviceStatusOpenAPSData.suggested = suggested
|
||||
deviceStatusOpenAPSData.clockSuggested = clock
|
||||
if (clock != 0L && clock > deviceStatusData.openAPSData.clockSuggested) {
|
||||
deviceStatusData.openAPSData.suggested = suggested
|
||||
deviceStatusData.openAPSData.clockSuggested = clock
|
||||
}
|
||||
clock = if (enacted.has("timestamp")) dateUtil.fromISODateString(enacted.getString("timestamp")) else 0L
|
||||
// check if this is new data
|
||||
if (clock != 0L && clock > deviceStatusOpenAPSData.clockEnacted) {
|
||||
deviceStatusOpenAPSData.enacted = enacted
|
||||
deviceStatusOpenAPSData.clockEnacted = clock
|
||||
if (clock != 0L && clock > deviceStatusData.openAPSData.clockEnacted) {
|
||||
deviceStatusData.openAPSData.enacted = enacted
|
||||
deviceStatusData.openAPSData.clockEnacted = clock
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
aapsLogger.error("Unhandled exception", e)
|
||||
|
@ -273,12 +254,12 @@ class NSDeviceStatus @Inject constructor(
|
|||
|
||||
// test warning level
|
||||
val level = when {
|
||||
deviceStatusOpenAPSData.clockSuggested + T.mins(sp.getLong(R.string.key_nsalarm_urgent_staledatavalue, 31)).msecs() < dateUtil.now() -> Levels.URGENT
|
||||
deviceStatusOpenAPSData.clockSuggested + T.mins(sp.getLong(R.string.key_nsalarm_staledatavalue, 16)).msecs() < dateUtil.now() -> Levels.WARN
|
||||
deviceStatusData.openAPSData.clockSuggested + T.mins(sp.getLong(R.string.key_nsalarm_urgent_staledatavalue, 31)).msecs() < dateUtil.now() -> Levels.URGENT
|
||||
deviceStatusData.openAPSData.clockSuggested + T.mins(sp.getLong(R.string.key_nsalarm_staledatavalue, 16)).msecs() < dateUtil.now() -> Levels.WARN
|
||||
else -> Levels.INFO
|
||||
}
|
||||
string.append("<span style=\"color:${level.toColor()}\">")
|
||||
if (deviceStatusOpenAPSData.clockSuggested != 0L) string.append(dateUtil.minAgo(resourceHelper, deviceStatusOpenAPSData.clockSuggested)).append(" ")
|
||||
if (deviceStatusData.openAPSData.clockSuggested != 0L) string.append(dateUtil.minAgo(resourceHelper, deviceStatusData.openAPSData.clockSuggested)).append(" ")
|
||||
string.append("</span>") // color
|
||||
return fromHtml(string.toString())
|
||||
}
|
||||
|
@ -287,8 +268,8 @@ class NSDeviceStatus @Inject constructor(
|
|||
get() {
|
||||
val string = StringBuilder()
|
||||
try {
|
||||
if (deviceStatusOpenAPSData.enacted != null && deviceStatusOpenAPSData.clockEnacted != deviceStatusOpenAPSData.clockSuggested) string.append("<b>").append(dateUtil.minAgo(resourceHelper, deviceStatusOpenAPSData.clockEnacted)).append("</b> ").append(deviceStatusOpenAPSData.enacted!!.getString("reason")).append("<br>")
|
||||
if (deviceStatusOpenAPSData.suggested != null) string.append("<b>").append(dateUtil.minAgo(resourceHelper, deviceStatusOpenAPSData.clockSuggested)).append("</b> ").append(deviceStatusOpenAPSData.suggested!!.getString("reason")).append("<br>")
|
||||
if (deviceStatusData.openAPSData.enacted != null && deviceStatusData.openAPSData.clockEnacted != deviceStatusData.openAPSData.clockSuggested) string.append("<b>").append(dateUtil.minAgo(resourceHelper, deviceStatusData.openAPSData.clockEnacted)).append("</b> ").append(deviceStatusData.openAPSData.enacted!!.getString("reason")).append("<br>")
|
||||
if (deviceStatusData.openAPSData.suggested != null) string.append("<b>").append(dateUtil.minAgo(resourceHelper, deviceStatusData.openAPSData.clockSuggested)).append("</b> ").append(deviceStatusData.openAPSData.suggested!!.getString("reason")).append("<br>")
|
||||
return fromHtml(string.toString())
|
||||
} catch (e: JSONException) {
|
||||
aapsLogger.error("Unhandled exception", e)
|
||||
|
@ -296,12 +277,6 @@ class NSDeviceStatus @Inject constructor(
|
|||
return fromHtml("")
|
||||
}
|
||||
|
||||
internal class Uploader {
|
||||
|
||||
var clock = 0L
|
||||
var battery = 0
|
||||
}
|
||||
|
||||
private fun updateUploaderData(jsonObject: JSONObject) {
|
||||
try {
|
||||
val clock =
|
||||
|
@ -318,13 +293,13 @@ class NSDeviceStatus @Inject constructor(
|
|||
else -> 0
|
||||
}
|
||||
|
||||
var uploader = uploaderMap[device]
|
||||
var uploader = deviceStatusData.uploaderMap[device]
|
||||
// check if this is new data
|
||||
if (clock != 0L && battery != 0 && (uploader == null || clock > uploader.clock)) {
|
||||
if (uploader == null) uploader = Uploader()
|
||||
if (uploader == null) uploader = DeviceStatusData.Uploader()
|
||||
uploader.battery = battery
|
||||
uploader.clock = clock
|
||||
uploaderMap[device] = uploader
|
||||
deviceStatusData.uploaderMap[device] = uploader
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
aapsLogger.error("Unhandled exception", e)
|
||||
|
@ -333,11 +308,11 @@ class NSDeviceStatus @Inject constructor(
|
|||
|
||||
val uploaderStatus: String
|
||||
get() {
|
||||
val iterator: Iterator<*> = uploaderMap.entries.iterator()
|
||||
val iterator: Iterator<*> = deviceStatusData.uploaderMap.entries.iterator()
|
||||
var minBattery = 100
|
||||
while (iterator.hasNext()) {
|
||||
val pair = iterator.next() as Map.Entry<*, *>
|
||||
val uploader = pair.value as Uploader
|
||||
val uploader = pair.value as DeviceStatusData.Uploader
|
||||
if (minBattery > uploader.battery) minBattery = uploader.battery
|
||||
}
|
||||
return "$minBattery%"
|
||||
|
@ -349,11 +324,11 @@ class NSDeviceStatus @Inject constructor(
|
|||
string.append("<span style=\"color:${resourceHelper.gcs(R.color.defaulttext)}\">")
|
||||
string.append(resourceHelper.gs(R.string.uploader_short))
|
||||
string.append(": </span>")
|
||||
val iterator: Iterator<*> = uploaderMap.entries.iterator()
|
||||
val iterator: Iterator<*> = deviceStatusData.uploaderMap.entries.iterator()
|
||||
var minBattery = 100
|
||||
while (iterator.hasNext()) {
|
||||
val pair = iterator.next() as Map.Entry<*, *>
|
||||
val uploader = pair.value as Uploader
|
||||
val uploader = pair.value as DeviceStatusData.Uploader
|
||||
if (minBattery > uploader.battery) minBattery = uploader.battery
|
||||
}
|
||||
string.append(minBattery)
|
||||
|
@ -364,33 +339,28 @@ class NSDeviceStatus @Inject constructor(
|
|||
val extendedUploaderStatus: Spanned
|
||||
get() {
|
||||
val string = StringBuilder()
|
||||
val iterator: Iterator<*> = uploaderMap.entries.iterator()
|
||||
val iterator: Iterator<*> = deviceStatusData.uploaderMap.entries.iterator()
|
||||
while (iterator.hasNext()) {
|
||||
val pair = iterator.next() as Map.Entry<*, *>
|
||||
val uploader = pair.value as Uploader
|
||||
val uploader = pair.value as DeviceStatusData.Uploader
|
||||
val device = pair.key as String
|
||||
string.append("<b>").append(device).append(":</b> ").append(uploader.battery).append("%<br>")
|
||||
}
|
||||
return fromHtml(string.toString())
|
||||
}
|
||||
|
||||
// ********* OpenAPS data ***********
|
||||
var deviceStatusOpenAPSData = DeviceStatusOpenAPSData()
|
||||
val openApsTimestamp: Long
|
||||
get() =
|
||||
if (deviceStatusOpenAPSData.clockSuggested != 0L) {
|
||||
deviceStatusOpenAPSData.clockSuggested
|
||||
if (deviceStatusData.openAPSData.clockSuggested != 0L) {
|
||||
deviceStatusData.openAPSData.clockSuggested
|
||||
} else {
|
||||
-1
|
||||
}
|
||||
|
||||
// ********* Uploader data ***********
|
||||
private val uploaderMap = HashMap<String, Uploader>()
|
||||
|
||||
fun getAPSResult(injector: HasAndroidInjector): APSResult {
|
||||
val result = APSResult(injector)
|
||||
result.json = deviceStatusOpenAPSData.suggested
|
||||
result.date = deviceStatusOpenAPSData.clockSuggested
|
||||
result.json = deviceStatusData.openAPSData.suggested
|
||||
result.date = deviceStatusData.openAPSData.clockSuggested
|
||||
return result
|
||||
}
|
||||
}
|
|
@ -636,18 +636,28 @@ class OverviewFragment : DaggerFragment(), View.OnClickListener, OnLongClickList
|
|||
OverviewData.Property.PROFILE -> {
|
||||
val profileBackgroundColor =
|
||||
profileFunction.getProfile()?.let {
|
||||
val profile = (it as ProfileSealed.EPS).value
|
||||
if (profile.originalPercentage != 100 || profile.originalTimeshift != 0L || profile.originalDuration != 0L)
|
||||
if (it is ProfileSealed.EPS) {
|
||||
if (it.value.originalPercentage != 100 || it.value.originalTimeshift != 0L || it.value.originalDuration != 0L)
|
||||
resourceHelper.gc(R.color.ribbonWarning)
|
||||
else resourceHelper.gc(R.color.ribbonDefault)
|
||||
} ?: resourceHelper.gc(R.color.ribbonTextDefault)
|
||||
} else if (it is ProfileSealed.PS) {
|
||||
resourceHelper.gc(R.color.ribbonDefault)
|
||||
} else {
|
||||
resourceHelper.gc(R.color.ribbonDefault)
|
||||
}
|
||||
} ?: resourceHelper.gc(R.color.ribbonCritical)
|
||||
|
||||
val profileTextColor =
|
||||
profileFunction.getProfile()?.let {
|
||||
val profile = (it as ProfileSealed.EPS).value
|
||||
if (profile.originalPercentage != 100 || profile.originalTimeshift != 0L || profile.originalDuration != 0L)
|
||||
if (it is ProfileSealed.EPS) {
|
||||
if (it.value.originalPercentage != 100 || it.value.originalTimeshift != 0L || it.value.originalDuration != 0L)
|
||||
resourceHelper.gc(R.color.ribbonTextWarning)
|
||||
else resourceHelper.gc(R.color.ribbonTextDefault)
|
||||
}else if (it is ProfileSealed.PS) {
|
||||
resourceHelper.gc(R.color.ribbonTextDefault)
|
||||
} else {
|
||||
resourceHelper.gc(R.color.ribbonTextDefault)
|
||||
}
|
||||
} ?: resourceHelper.gc(R.color.ribbonTextDefault)
|
||||
|
||||
binding.activeProfile.text = profileFunction.getProfileNameWithRemainingTime()
|
||||
|
|
Loading…
Reference in a new issue