DeviceStatus
This commit is contained in:
parent
93b1b37021
commit
a5ea0d9027
|
@ -17,6 +17,7 @@ abstract class ReceiversModule {
|
|||
@ContributesAndroidInjector abstract fun contributesChargingStateReceiver(): ChargingStateReceiver
|
||||
@ContributesAndroidInjector abstract fun contributesDataReceiver(): DataReceiver
|
||||
@ContributesAndroidInjector abstract fun contributesKeepAliveReceiver(): KeepAliveReceiver
|
||||
@ContributesAndroidInjector abstract fun contributesKeepAliveWorker(): KeepAliveReceiver.KeepAliveWorker
|
||||
@ContributesAndroidInjector abstract fun contributesRileyLinkBluetoothStateReceiver(): RileyLinkBluetoothStateReceiver
|
||||
@ContributesAndroidInjector abstract fun contributesSmsReceiver(): SmsReceiver
|
||||
@ContributesAndroidInjector abstract fun contributesTimeDateOrTZChangeReceiver(): TimeDateOrTZChangeReceiver
|
||||
|
|
|
@ -32,6 +32,7 @@ import info.nightscout.androidaps.plugins.aps.loop.events.EventLoopUpdateGui
|
|||
import info.nightscout.androidaps.plugins.aps.loop.events.EventNewOpenLoopNotification
|
||||
import info.nightscout.androidaps.plugins.bus.RxBusWrapper
|
||||
import info.nightscout.androidaps.plugins.configBuilder.ConstraintChecker
|
||||
import info.nightscout.androidaps.plugins.configBuilder.RunningConfiguration
|
||||
import info.nightscout.androidaps.plugins.general.nsclient.NSUpload
|
||||
import info.nightscout.androidaps.plugins.general.overview.events.EventDismissNotification
|
||||
import info.nightscout.androidaps.plugins.general.overview.events.EventNewNotification
|
||||
|
@ -48,6 +49,7 @@ import info.nightscout.androidaps.utils.DateUtil
|
|||
import info.nightscout.androidaps.utils.FabricPrivacy
|
||||
import info.nightscout.androidaps.utils.HardLimits
|
||||
import info.nightscout.androidaps.utils.T
|
||||
import info.nightscout.androidaps.utils.extensions.buildDeviceStatus
|
||||
import info.nightscout.androidaps.utils.resources.ResourceHelper
|
||||
import info.nightscout.androidaps.utils.rx.AapsSchedulers
|
||||
import info.nightscout.androidaps.utils.sharedPreferences.SP
|
||||
|
@ -78,7 +80,8 @@ open class LoopPlugin @Inject constructor(
|
|||
private val fabricPrivacy: FabricPrivacy,
|
||||
private val nsUpload: NSUpload,
|
||||
private val dateUtil: DateUtil,
|
||||
private val repository: AppRepository
|
||||
private val repository: AppRepository,
|
||||
private val runningConfiguration: RunningConfiguration
|
||||
) : PluginBase(PluginDescription()
|
||||
.mainType(PluginType.LOOP)
|
||||
.fragmentClass(LoopFragment::class.java.name)
|
||||
|
@ -316,7 +319,12 @@ open class LoopPlugin @Inject constructor(
|
|||
lastRun!!.lastTBRRequest = 0
|
||||
lastRun!!.lastSMBEnact = 0
|
||||
lastRun!!.lastSMBRequest = 0
|
||||
nsUpload.uploadDeviceStatus(this, iobCobCalculatorPlugin, profileFunction, activePlugin.activePump, receiverStatusStore, BuildConfig.VERSION_NAME + "-" + BuildConfig.BUILDVERSION)
|
||||
buildDeviceStatus(dateUtil, this, iobCobCalculatorPlugin, profileFunction,
|
||||
activePlugin.activePump, receiverStatusStore, runningConfiguration,
|
||||
BuildConfig.VERSION_NAME + "-" + BuildConfig.BUILDVERSION)?.also {
|
||||
repository.insert(it)
|
||||
}
|
||||
|
||||
if (isSuspended) {
|
||||
aapsLogger.debug(LTag.APS, resourceHelper.gs(R.string.loopsuspended))
|
||||
rxBus.send(EventLoopSetLastRunGui(resourceHelper.gs(R.string.loopsuspended)))
|
||||
|
@ -489,7 +497,6 @@ open class LoopPlugin @Inject constructor(
|
|||
|
||||
fun acceptChangeRequest() {
|
||||
val profile = profileFunction.getProfile()
|
||||
val lp = this
|
||||
applyTBRRequest(lastRun!!.constraintsProcessed, profile, object : Callback() {
|
||||
override fun run() {
|
||||
if (result.enacted) {
|
||||
|
@ -497,7 +504,11 @@ open class LoopPlugin @Inject constructor(
|
|||
lastRun!!.lastTBRRequest = lastRun!!.lastAPSRun
|
||||
lastRun!!.lastTBREnact = DateUtil.now()
|
||||
lastRun!!.lastOpenModeAccept = DateUtil.now()
|
||||
nsUpload.uploadDeviceStatus(lp, iobCobCalculatorPlugin, profileFunction, activePlugin.activePump, receiverStatusStore, BuildConfig.VERSION_NAME + "-" + BuildConfig.BUILDVERSION)
|
||||
buildDeviceStatus(dateUtil, this@LoopPlugin, iobCobCalculatorPlugin, profileFunction,
|
||||
activePlugin.activePump, receiverStatusStore, runningConfiguration,
|
||||
BuildConfig.VERSION_NAME + "-" + BuildConfig.BUILDVERSION)?.also {
|
||||
repository.insert(it)
|
||||
}
|
||||
sp.incInt(R.string.key_ObjectivesmanualEnacts)
|
||||
}
|
||||
rxBus.send(EventAcceptOpenLoopChange())
|
||||
|
|
|
@ -2,6 +2,7 @@ package info.nightscout.androidaps.plugins.general.nsclient
|
|||
|
||||
import info.nightscout.androidaps.R
|
||||
import info.nightscout.androidaps.database.AppRepository
|
||||
import info.nightscout.androidaps.database.entities.DeviceStatus
|
||||
import info.nightscout.androidaps.database.entities.*
|
||||
import info.nightscout.androidaps.interfaces.ActivePluginProvider
|
||||
import info.nightscout.androidaps.interfaces.DataSyncSelector
|
||||
|
@ -28,6 +29,7 @@ class DataSyncSelectorImplementation @Inject constructor(
|
|||
sp.remove(R.string.key_ns_bolus_last_synced_id)
|
||||
sp.remove(R.string.key_ns_carbs_last_synced_id)
|
||||
sp.remove(R.string.key_ns_bolus_calculator_result_last_synced_id)
|
||||
sp.remove(R.string.key_ns_device_status_last_synced_id)
|
||||
}
|
||||
|
||||
override fun confirmLastBolusIdIfGreater(lastSynced: Long) {
|
||||
|
@ -294,4 +296,34 @@ class DataSyncSelectorImplementation @Inject constructor(
|
|||
return false
|
||||
}
|
||||
|
||||
override fun confirmLastDeviceStatusIdIfGreater(lastSynced: Long) {
|
||||
if (lastSynced > sp.getLong(R.string.key_ns_device_status_last_synced_id, 0)) {
|
||||
aapsLogger.debug(LTag.NSCLIENT, "Setting DeviceStatus data sync from $lastSynced")
|
||||
sp.putLong(R.string.key_ns_device_status_last_synced_id, lastSynced)
|
||||
}
|
||||
}
|
||||
|
||||
override fun changedDeviceStatuses(): List<DeviceStatus> {
|
||||
val startId = sp.getLong(R.string.key_ns_device_status_last_synced_id, 0)
|
||||
return appRepository.getModifiedDeviceStatusDataFromId(startId).blockingGet().also {
|
||||
aapsLogger.debug(LTag.NSCLIENT, "Loading DeviceStatus data for sync from $startId. Records ${it.size}")
|
||||
}
|
||||
}
|
||||
|
||||
override fun processChangedDeviceStatusesCompat(): Boolean {
|
||||
val startId = sp.getLong(R.string.key_ns_device_status_last_synced_id, 0)
|
||||
appRepository.getNextSyncElementDeviceStatus(startId).blockingGet()?.let { deviceStatus ->
|
||||
aapsLogger.info(LTag.DATABASE, "Loading DeviceStatus data Start: $startId ID: ${deviceStatus.id}")
|
||||
when {
|
||||
// without nsId = create new
|
||||
deviceStatus.interfaceIDs.nightscoutId == null ->
|
||||
nsClientPlugin.nsClientService?.dbAdd("devicestatus", deviceStatus.toJson(), deviceStatus)
|
||||
// with nsId = ignore
|
||||
deviceStatus.interfaceIDs.nightscoutId != null -> Any()
|
||||
}
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -32,10 +32,11 @@ import dagger.android.HasAndroidInjector;
|
|||
import info.nightscout.androidaps.Config;
|
||||
import info.nightscout.androidaps.R;
|
||||
import info.nightscout.androidaps.database.AppRepository;
|
||||
import info.nightscout.androidaps.database.entities.Carbs;
|
||||
import info.nightscout.androidaps.database.entities.DeviceStatus;
|
||||
import info.nightscout.androidaps.database.transactions.UpdateNsIdBolusCalculatorResultTransaction;
|
||||
import info.nightscout.androidaps.database.transactions.UpdateNsIdBolusTransaction;
|
||||
import info.nightscout.androidaps.database.transactions.UpdateNsIdCarbsTransaction;
|
||||
import info.nightscout.androidaps.database.transactions.UpdateNsIdDeviceStatusTransaction;
|
||||
import info.nightscout.androidaps.database.transactions.UpdateNsIdFoodTransaction;
|
||||
import info.nightscout.androidaps.database.transactions.UpdateNsIdGlucoseValueTransaction;
|
||||
import info.nightscout.androidaps.database.transactions.UpdateNsIdTemporaryTargetTransaction;
|
||||
|
@ -339,6 +340,22 @@ public class NSClientService extends DaggerService {
|
|||
dataSyncSelector.processChangedBolusCalculatorResultsCompat();
|
||||
return;
|
||||
}
|
||||
if (ack.getOriginalObject() instanceof DeviceStatus) {
|
||||
DeviceStatus deviceStatus = (DeviceStatus) ack.getOriginalObject();
|
||||
deviceStatus.getInterfaceIDs().setNightscoutId(ack.getId());
|
||||
|
||||
disposable.add(repository.runTransactionForResult(new UpdateNsIdDeviceStatusTransaction(deviceStatus))
|
||||
.observeOn(aapsSchedulers.getIo())
|
||||
.subscribe(
|
||||
result -> aapsLogger.debug(LTag.DATABASE, "Updated ns id of DeviceStatus " + deviceStatus),
|
||||
error -> aapsLogger.error(LTag.DATABASE, "Updated ns id of DeviceStatus failed", error)
|
||||
));
|
||||
dataSyncSelector.confirmLastDeviceStatusIdIfGreater(deviceStatus.getId());
|
||||
rxBus.send(new EventNSClientNewLog("DBADD", "Acked DeviceStatus" + deviceStatus.getInterfaceIDs().getNightscoutId()));
|
||||
// Send new if waiting
|
||||
dataSyncSelector.processChangedBolusCalculatorResultsCompat();
|
||||
return;
|
||||
}
|
||||
// old way
|
||||
if (ack.nsClientID != null) {
|
||||
uploadQueue.removeByNsClientIdIfExists(ack.json);
|
||||
|
@ -977,6 +994,7 @@ public class NSClientService extends DaggerService {
|
|||
dataSyncSelector.processChangedTempTargetsCompat();
|
||||
dataSyncSelector.processChangedFoodsCompat();
|
||||
dataSyncSelector.processChangedTherapyEventsCompat();
|
||||
dataSyncSelector.processChangedDeviceStatusesCompat();
|
||||
|
||||
if (uploadQueue.size() == 0)
|
||||
return;
|
||||
|
|
|
@ -3,13 +3,19 @@ package info.nightscout.androidaps.receivers
|
|||
import android.app.AlarmManager
|
||||
import android.app.PendingIntent
|
||||
import android.app.PendingIntent.CanceledException
|
||||
import android.app.PendingIntent.FLAG_IMMUTABLE
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.os.PowerManager
|
||||
import android.os.SystemClock
|
||||
import androidx.work.OneTimeWorkRequest
|
||||
import androidx.work.WorkManager
|
||||
import androidx.work.Worker
|
||||
import androidx.work.WorkerParameters
|
||||
import dagger.android.DaggerBroadcastReceiver
|
||||
import dagger.android.HasAndroidInjector
|
||||
import info.nightscout.androidaps.BuildConfig
|
||||
import info.nightscout.androidaps.Config
|
||||
import info.nightscout.androidaps.database.AppRepository
|
||||
import info.nightscout.androidaps.events.EventProfileNeedsUpdate
|
||||
import info.nightscout.androidaps.interfaces.ActivePluginProvider
|
||||
import info.nightscout.androidaps.interfaces.CommandQueueProvider
|
||||
|
@ -18,37 +24,62 @@ import info.nightscout.androidaps.logging.AAPSLogger
|
|||
import info.nightscout.androidaps.logging.LTag
|
||||
import info.nightscout.androidaps.plugins.aps.loop.LoopPlugin
|
||||
import info.nightscout.androidaps.plugins.bus.RxBusWrapper
|
||||
import info.nightscout.androidaps.plugins.general.nsclient.NSUpload
|
||||
import info.nightscout.androidaps.plugins.configBuilder.RunningConfiguration
|
||||
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.IobCobCalculatorPlugin
|
||||
import info.nightscout.androidaps.queue.commands.Command
|
||||
import info.nightscout.androidaps.utils.DateUtil
|
||||
import info.nightscout.androidaps.utils.FabricPrivacy
|
||||
import info.nightscout.androidaps.utils.LocalAlertUtils
|
||||
import info.nightscout.androidaps.utils.T
|
||||
import info.nightscout.androidaps.utils.extensions.buildDeviceStatus
|
||||
import javax.inject.Inject
|
||||
import kotlin.math.abs
|
||||
|
||||
class KeepAliveReceiver : DaggerBroadcastReceiver() {
|
||||
|
||||
@Inject lateinit var aapsLogger: AAPSLogger
|
||||
@Inject lateinit var rxBus: RxBusWrapper
|
||||
@Inject lateinit var activePlugin: ActivePluginProvider
|
||||
@Inject lateinit var commandQueue: CommandQueueProvider
|
||||
@Inject lateinit var profileFunction: ProfileFunction
|
||||
@Inject lateinit var loopPlugin: LoopPlugin
|
||||
@Inject lateinit var iobCobCalculatorPlugin: IobCobCalculatorPlugin
|
||||
@Inject lateinit var localAlertUtils: LocalAlertUtils
|
||||
@Inject lateinit var fabricPrivacy: FabricPrivacy
|
||||
@Inject lateinit var receiverStatusStore: ReceiverStatusStore
|
||||
@Inject lateinit var config: Config
|
||||
@Inject lateinit var nsUpload: NSUpload
|
||||
@Inject lateinit var dateUtil: DateUtil
|
||||
|
||||
companion object {
|
||||
|
||||
private val KEEP_ALIVE_MILLISECONDS = T.mins(5).msecs()
|
||||
}
|
||||
|
||||
override fun onReceive(context: Context, intent: Intent) {
|
||||
super.onReceive(context, intent)
|
||||
aapsLogger.debug(LTag.CORE, "KeepAlive received")
|
||||
|
||||
WorkManager.getInstance(context)
|
||||
.enqueue(OneTimeWorkRequest.Builder(KeepAliveWorker::class.java).build())
|
||||
}
|
||||
|
||||
class KeepAliveWorker(
|
||||
context: Context,
|
||||
params: WorkerParameters
|
||||
) : Worker(context, params) {
|
||||
|
||||
@Inject lateinit var aapsLogger: AAPSLogger
|
||||
@Inject lateinit var localAlertUtils: LocalAlertUtils
|
||||
@Inject lateinit var repository: AppRepository
|
||||
@Inject lateinit var config: Config
|
||||
@Inject lateinit var iobCobCalculatorPlugin: IobCobCalculatorPlugin
|
||||
@Inject lateinit var loopPlugin: LoopPlugin
|
||||
@Inject lateinit var dateUtil: DateUtil
|
||||
@Inject lateinit var activePlugin: ActivePluginProvider
|
||||
@Inject lateinit var profileFunction: ProfileFunction
|
||||
@Inject lateinit var runningConfiguration: RunningConfiguration
|
||||
@Inject lateinit var receiverStatusStore: ReceiverStatusStore
|
||||
@Inject lateinit var rxBus: RxBusWrapper
|
||||
@Inject lateinit var commandQueue: CommandQueueProvider
|
||||
@Inject lateinit var fabricPrivacy: FabricPrivacy
|
||||
|
||||
init {
|
||||
(context.applicationContext as HasAndroidInjector).androidInjector().inject(this)
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
||||
private val STATUS_UPDATE_FREQUENCY = T.mins(15).msecs()
|
||||
private val IOB_UPDATE_FREQUENCY_IN_MINS = 5L
|
||||
private const val IOB_UPDATE_FREQUENCY_IN_MINUTES = 5L
|
||||
|
||||
private var lastReadStatus: Long = 0
|
||||
private var lastRun: Long = 0
|
||||
|
@ -56,48 +87,12 @@ class KeepAliveReceiver : DaggerBroadcastReceiver() {
|
|||
|
||||
}
|
||||
|
||||
override fun onReceive(context: Context, intent: Intent) {
|
||||
super.onReceive(context, intent)
|
||||
aapsLogger.debug(LTag.CORE, "KeepAlive received")
|
||||
val pm = context.getSystemService(Context.POWER_SERVICE) as PowerManager
|
||||
val wl = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "AndroidAPS:KeepAliveReceiver")
|
||||
wl.acquire(T.mins(2).msecs())
|
||||
override fun doWork(): Result {
|
||||
localAlertUtils.shortenSnoozeInterval()
|
||||
localAlertUtils.checkStaleBGAlert()
|
||||
checkPump()
|
||||
checkAPS()
|
||||
wl.release()
|
||||
}
|
||||
|
||||
class KeepAliveManager @Inject constructor(
|
||||
private val aapsLogger: AAPSLogger,
|
||||
private val localAlertUtils: LocalAlertUtils
|
||||
) {
|
||||
|
||||
//called by MainApp at first app start
|
||||
fun setAlarm(context: Context) {
|
||||
aapsLogger.debug(LTag.CORE, "KeepAlive scheduled")
|
||||
SystemClock.sleep(5000) // wait for app initialization
|
||||
localAlertUtils.shortenSnoozeInterval()
|
||||
localAlertUtils.preSnoozeAlarms()
|
||||
val am = context.getSystemService(Context.ALARM_SERVICE) as AlarmManager
|
||||
val i = Intent(context, KeepAliveReceiver::class.java)
|
||||
val pi = PendingIntent.getBroadcast(context, 0, i, 0)
|
||||
try {
|
||||
pi.send()
|
||||
} catch (e: CanceledException) {
|
||||
}
|
||||
am.cancel(pi)
|
||||
am.setInexactRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis(), KEEP_ALIVE_MILLISECONDS, pi)
|
||||
}
|
||||
|
||||
fun cancelAlarm(context: Context) {
|
||||
aapsLogger.debug(LTag.CORE, "KeepAlive canceled")
|
||||
val intent = Intent(context, KeepAliveReceiver::class.java)
|
||||
val sender = PendingIntent.getBroadcast(context, 0, intent, 0)
|
||||
val alarmManager = context.getSystemService(Context.ALARM_SERVICE) as AlarmManager
|
||||
alarmManager.cancel(sender)
|
||||
}
|
||||
return Result.success()
|
||||
}
|
||||
|
||||
// Usually deviceStatus is uploaded through LoopPlugin after every loop cycle.
|
||||
|
@ -110,9 +105,13 @@ class KeepAliveReceiver : DaggerBroadcastReceiver() {
|
|||
else if (!loopPlugin.isEnabled() || iobCobCalculatorPlugin.actualBg() == null)
|
||||
shouldUploadStatus = true
|
||||
else if (DateUtil.isOlderThan(activePlugin.activeAPS.lastAPSRun, 5)) shouldUploadStatus = true
|
||||
if (DateUtil.isOlderThan(lastIobUpload, IOB_UPDATE_FREQUENCY_IN_MINS) && shouldUploadStatus) {
|
||||
lastIobUpload = DateUtil.now()
|
||||
nsUpload.uploadDeviceStatus(loopPlugin, iobCobCalculatorPlugin, profileFunction, activePlugin.activePump, receiverStatusStore, BuildConfig.VERSION_NAME + "-" + BuildConfig.BUILDVERSION)
|
||||
if (DateUtil.isOlderThan(lastIobUpload, IOB_UPDATE_FREQUENCY_IN_MINUTES) && shouldUploadStatus) {
|
||||
lastIobUpload = dateUtil._now()
|
||||
buildDeviceStatus(dateUtil, loopPlugin, iobCobCalculatorPlugin, profileFunction,
|
||||
activePlugin.activePump, receiverStatusStore, runningConfiguration,
|
||||
BuildConfig.VERSION_NAME + "-" + BuildConfig.BUILDVERSION)?.also {
|
||||
repository.insert(it)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -143,4 +142,36 @@ class KeepAliveReceiver : DaggerBroadcastReceiver() {
|
|||
}
|
||||
lastRun = System.currentTimeMillis()
|
||||
}
|
||||
}
|
||||
|
||||
class KeepAliveManager @Inject constructor(
|
||||
private val aapsLogger: AAPSLogger,
|
||||
private val localAlertUtils: LocalAlertUtils
|
||||
) {
|
||||
|
||||
//called by MainApp at first app start
|
||||
fun setAlarm(context: Context) {
|
||||
aapsLogger.debug(LTag.CORE, "KeepAlive scheduled")
|
||||
SystemClock.sleep(5000) // wait for app initialization
|
||||
localAlertUtils.shortenSnoozeInterval()
|
||||
localAlertUtils.preSnoozeAlarms()
|
||||
val am = context.getSystemService(Context.ALARM_SERVICE) as AlarmManager
|
||||
val i = Intent(context, KeepAliveReceiver::class.java)
|
||||
val pi = PendingIntent.getBroadcast(context, 0, i, FLAG_IMMUTABLE)
|
||||
try {
|
||||
pi.send()
|
||||
} catch (e: CanceledException) {
|
||||
}
|
||||
am.cancel(pi)
|
||||
am.setInexactRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis(), KEEP_ALIVE_MILLISECONDS, pi)
|
||||
}
|
||||
|
||||
fun cancelAlarm(context: Context) {
|
||||
aapsLogger.debug(LTag.CORE, "KeepAlive canceled")
|
||||
val intent = Intent(context, KeepAliveReceiver::class.java)
|
||||
val sender = PendingIntent.getBroadcast(context, 0, intent, FLAG_IMMUTABLE)
|
||||
val alarmManager = context.getSystemService(Context.ALARM_SERVICE) as AlarmManager
|
||||
alarmManager.cancel(sender)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -43,6 +43,7 @@
|
|||
<string name="key_ns_bolus_calculator_result_last_synced_id" translatable="false">ns_bolus_calculator_result_last_synced_id</string>
|
||||
<string name="key_ns_carbs_last_synced_id" translatable="false">ns_carbs_last_synced_id</string>
|
||||
<string name="key_ns_bolus_last_synced_id" translatable="false">ns_bolus_last_synced_id</string>
|
||||
<string name="key_ns_device_status_last_synced_id" translatable="false">ns_device_status_last_synced_id</string>
|
||||
|
||||
<string name="treatmentssafety_title">Treatments safety</string>
|
||||
<string name="treatmentssafety_maxbolus_title">Max allowed bolus [U]</string>
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package info.nightscout.androidaps.interfaces
|
||||
|
||||
import info.nightscout.androidaps.database.entities.DeviceStatus
|
||||
import info.nightscout.androidaps.database.entities.*
|
||||
|
||||
interface DataSyncSelector {
|
||||
|
@ -48,4 +49,9 @@ interface DataSyncSelector {
|
|||
fun changedFoods() : List<Food>
|
||||
// Until NS v3
|
||||
fun processChangedFoodsCompat(): Boolean
|
||||
|
||||
fun confirmLastDeviceStatusIdIfGreater(lastSynced: Long)
|
||||
fun changedDeviceStatuses() : List<DeviceStatus>
|
||||
// Until NS v3
|
||||
fun processChangedDeviceStatusesCompat(): Boolean
|
||||
}
|
|
@ -1,35 +1,22 @@
|
|||
package info.nightscout.androidaps.plugins.general.nsclient;
|
||||
|
||||
import android.os.Build;
|
||||
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Singleton;
|
||||
|
||||
import info.nightscout.androidaps.core.R;
|
||||
import info.nightscout.androidaps.data.DetailedBolusInfo;
|
||||
import info.nightscout.androidaps.data.IobTotal;
|
||||
import info.nightscout.androidaps.data.Profile;
|
||||
import info.nightscout.androidaps.database.entities.TherapyEvent;
|
||||
import info.nightscout.androidaps.db.DbRequest;
|
||||
import info.nightscout.androidaps.db.ExtendedBolus;
|
||||
import info.nightscout.androidaps.db.ProfileSwitch;
|
||||
import info.nightscout.androidaps.db.TemporaryBasal;
|
||||
import info.nightscout.androidaps.interfaces.IobCobCalculator;
|
||||
import info.nightscout.androidaps.interfaces.LoopInterface;
|
||||
import info.nightscout.androidaps.interfaces.ProfileFunction;
|
||||
import info.nightscout.androidaps.interfaces.PumpInterface;
|
||||
import info.nightscout.androidaps.interfaces.UploadQueueInterface;
|
||||
import info.nightscout.androidaps.logging.AAPSLogger;
|
||||
import info.nightscout.androidaps.logging.LTag;
|
||||
import info.nightscout.androidaps.plugins.aps.loop.APSResult;
|
||||
import info.nightscout.androidaps.plugins.aps.loop.DeviceStatus;
|
||||
import info.nightscout.androidaps.plugins.configBuilder.RunningConfiguration;
|
||||
import info.nightscout.androidaps.receivers.ReceiverStatusStore;
|
||||
import info.nightscout.androidaps.utils.DateUtil;
|
||||
import info.nightscout.androidaps.utils.sharedPreferences.SP;
|
||||
|
||||
|
@ -165,70 +152,6 @@ public class NSUpload {
|
|||
}
|
||||
}
|
||||
|
||||
public void uploadDeviceStatus(LoopInterface loopPlugin, IobCobCalculator iobCobCalculatorPlugin, ProfileFunction profileFunction, PumpInterface pumpInterface, ReceiverStatusStore receiverStatusStore, String version) {
|
||||
Profile profile = profileFunction.getProfile();
|
||||
String profileName = profileFunction.getProfileName();
|
||||
|
||||
if (profile == null) {
|
||||
aapsLogger.error("Profile is null. Skipping upload");
|
||||
return;
|
||||
}
|
||||
|
||||
DeviceStatus deviceStatus = new DeviceStatus(aapsLogger);
|
||||
try {
|
||||
LoopInterface.LastRun lastRun = loopPlugin.getLastRun();
|
||||
if (lastRun != null && lastRun.getLastAPSRun() > System.currentTimeMillis() - 300 * 1000L) {
|
||||
// do not send if result is older than 1 min
|
||||
APSResult apsResult = lastRun.getRequest();
|
||||
apsResult.json().put("timestamp", DateUtil.toISOString(lastRun.getLastAPSRun()));
|
||||
deviceStatus.suggested = apsResult.json();
|
||||
|
||||
deviceStatus.iob = lastRun.getRequest().getIob().json();
|
||||
deviceStatus.iob.put("time", DateUtil.toISOString(lastRun.getLastAPSRun()));
|
||||
|
||||
JSONObject requested = new JSONObject();
|
||||
|
||||
if (lastRun.getTbrSetByPump() != null && lastRun.getTbrSetByPump().getEnacted()) { // enacted
|
||||
deviceStatus.enacted = lastRun.getRequest().json();
|
||||
deviceStatus.enacted.put("rate", lastRun.getTbrSetByPump().json(profile).get("rate"));
|
||||
deviceStatus.enacted.put("duration", lastRun.getTbrSetByPump().json(profile).get("duration"));
|
||||
deviceStatus.enacted.put("recieved", true);
|
||||
requested.put("duration", lastRun.getRequest().getDuration());
|
||||
requested.put("rate", lastRun.getRequest().getRate());
|
||||
requested.put("temp", "absolute");
|
||||
deviceStatus.enacted.put("requested", requested);
|
||||
}
|
||||
if (lastRun.getTbrSetByPump() != null && lastRun.getTbrSetByPump().getEnacted()) { // enacted
|
||||
if (deviceStatus.enacted == null) {
|
||||
deviceStatus.enacted = lastRun.getRequest().json();
|
||||
}
|
||||
deviceStatus.enacted.put("smb", lastRun.getTbrSetByPump().getBolusDelivered());
|
||||
requested.put("smb", lastRun.getRequest().getSmb());
|
||||
deviceStatus.enacted.put("requested", requested);
|
||||
}
|
||||
} else {
|
||||
aapsLogger.debug(LTag.NSCLIENT, "OpenAPS data too old to upload, sending iob only");
|
||||
IobTotal[] iob = iobCobCalculatorPlugin.calculateIobArrayInDia(profile);
|
||||
if (iob.length > 0) {
|
||||
deviceStatus.iob = iob[0].json();
|
||||
deviceStatus.iob.put("time", DateUtil.toISOString(dateUtil._now()));
|
||||
}
|
||||
}
|
||||
deviceStatus.device = "openaps://" + Build.MANUFACTURER + " " + Build.MODEL;
|
||||
JSONObject pumpstatus = pumpInterface.getJSONStatus(profile, profileName, version);
|
||||
deviceStatus.pump = pumpstatus;
|
||||
|
||||
deviceStatus.uploaderBattery = receiverStatusStore.getBatteryLevel();
|
||||
|
||||
deviceStatus.created_at = DateUtil.toISOString(new Date());
|
||||
|
||||
deviceStatus.configuration = runningConfiguration.configuration();
|
||||
|
||||
uploadQueue.add(new DbRequest("dbAdd", "devicestatus", deviceStatus.mongoRecord(), System.currentTimeMillis()));
|
||||
} catch (JSONException e) {
|
||||
aapsLogger.error("Unhandled exception", e);
|
||||
}
|
||||
}
|
||||
|
||||
public void uploadTreatmentRecord(DetailedBolusInfo detailedBolusInfo) {
|
||||
throw new IllegalStateException("DO NOT USE");
|
||||
|
|
|
@ -1,12 +1,88 @@
|
|||
package info.nightscout.androidaps.plugins.aps.loop;
|
||||
package info.nightscout.androidaps.utils.extensions
|
||||
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
import org.slf4j.Logger;
|
||||
import android.os.Build
|
||||
import info.nightscout.androidaps.database.entities.DeviceStatus
|
||||
import info.nightscout.androidaps.interfaces.IobCobCalculator
|
||||
import info.nightscout.androidaps.interfaces.LoopInterface
|
||||
import info.nightscout.androidaps.interfaces.ProfileFunction
|
||||
import info.nightscout.androidaps.interfaces.PumpInterface
|
||||
import info.nightscout.androidaps.plugins.configBuilder.RunningConfiguration
|
||||
import info.nightscout.androidaps.receivers.ReceiverStatusStore
|
||||
import info.nightscout.androidaps.utils.DateUtil
|
||||
import org.json.JSONObject
|
||||
|
||||
import info.nightscout.androidaps.logging.AAPSLogger;
|
||||
import info.nightscout.androidaps.logging.LTag;
|
||||
import info.nightscout.androidaps.logging.StacktraceLoggerWrapper;
|
||||
fun DeviceStatus.toJson(): JSONObject =
|
||||
JSONObject()
|
||||
.put("created_at", DateUtil.toISOString(timestamp))
|
||||
.also {
|
||||
if (device != null) it.put("device", device)
|
||||
if (pump != null) it.put("pump", JSONObject(pump))
|
||||
it.put("openaps", JSONObject().also { openaps ->
|
||||
if (enacted != null) openaps.put("enacted", JSONObject(enacted))
|
||||
if (suggested != null) openaps.put("suggested", JSONObject(suggested))
|
||||
if (iob != null) openaps.put("iob", iob)
|
||||
})
|
||||
if (uploaderBattery != 0) it.put("uploaderBattery", uploaderBattery)
|
||||
if (configuration != null) it.put("configuration", JSONObject(configuration))
|
||||
}
|
||||
|
||||
fun buildDeviceStatus(
|
||||
dateUtil: DateUtil,
|
||||
loopPlugin: LoopInterface,
|
||||
iobCobCalculatorPlugin: IobCobCalculator,
|
||||
profileFunction: ProfileFunction,
|
||||
pumpInterface: PumpInterface,
|
||||
receiverStatusStore: ReceiverStatusStore,
|
||||
runningConfiguration: RunningConfiguration,
|
||||
version: String
|
||||
): DeviceStatus? {
|
||||
val profile = profileFunction.getProfile() ?: return null
|
||||
val profileName = profileFunction.getProfileName() ?: return null
|
||||
|
||||
val lastRun = loopPlugin.lastRun
|
||||
var apsResult: JSONObject? = null
|
||||
var iob: JSONObject? = null
|
||||
var enacted: JSONObject? = null
|
||||
if (lastRun != null && lastRun.lastAPSRun > dateUtil._now() - 300 * 1000L) {
|
||||
// do not send if result is older than 1 min
|
||||
apsResult = lastRun.request?.json()?.also {
|
||||
it.put("timestamp", DateUtil.toISOString(lastRun.lastAPSRun))
|
||||
}
|
||||
iob = lastRun.request?.iob?.json()?.also {
|
||||
it.put("time", DateUtil.toISOString(lastRun.lastAPSRun))
|
||||
}
|
||||
val requested = JSONObject()
|
||||
if (lastRun.tbrSetByPump?.enacted == true) { // enacted
|
||||
enacted = lastRun.request?.json()?.also {
|
||||
it.put("rate", lastRun.tbrSetByPump!!.json(profile)["rate"])
|
||||
it.put("duration", lastRun.tbrSetByPump!!.json(profile)["duration"])
|
||||
it.put("received", true)
|
||||
}
|
||||
requested.put("duration", lastRun.request?.duration)
|
||||
requested.put("rate", lastRun.request?.rate)
|
||||
requested.put("temp", "absolute")
|
||||
requested.put("smb", lastRun.request?.smb)
|
||||
enacted?.put("requested", requested)
|
||||
enacted?.put("smb", lastRun.tbrSetByPump?.bolusDelivered)
|
||||
}
|
||||
} else {
|
||||
val calcIob = iobCobCalculatorPlugin.calculateIobArrayInDia(profile)
|
||||
if (calcIob.isNotEmpty()) {
|
||||
iob = calcIob[0].json()
|
||||
iob.put("time", DateUtil.toISOString(dateUtil._now()))
|
||||
}
|
||||
}
|
||||
return DeviceStatus(
|
||||
timestamp = dateUtil._now(),
|
||||
suggested = apsResult?.toString(),
|
||||
iob = iob?.toString(),
|
||||
enacted = enacted?.toString(),
|
||||
device = "openaps://" + Build.MANUFACTURER + " " + Build.MODEL,
|
||||
pump = pumpInterface.getJSONStatus(profile, profileName, version).toString(),
|
||||
uploaderBattery = receiverStatusStore.batteryLevel,
|
||||
configuration = runningConfiguration.configuration().toString()
|
||||
)
|
||||
}
|
||||
|
||||
/*
|
||||
{
|
||||
|
@ -364,41 +440,3 @@ import info.nightscout.androidaps.logging.StacktraceLoggerWrapper;
|
|||
"created_at": "2016-06-24T09:27:49.230Z"
|
||||
}
|
||||
*/
|
||||
|
||||
public class DeviceStatus {
|
||||
private final AAPSLogger aapsLogger;
|
||||
|
||||
public String device = null;
|
||||
public JSONObject pump = null;
|
||||
public JSONObject enacted = null;
|
||||
public JSONObject suggested = null;
|
||||
public JSONObject iob = null;
|
||||
public int uploaderBattery = 0;
|
||||
public String created_at = null;
|
||||
public JSONObject configuration = null;
|
||||
|
||||
public DeviceStatus(AAPSLogger aapsLogger) {
|
||||
this.aapsLogger = aapsLogger;
|
||||
}
|
||||
|
||||
public JSONObject mongoRecord() {
|
||||
JSONObject record = new JSONObject();
|
||||
|
||||
try {
|
||||
if (device != null) record.put("device", device);
|
||||
if (pump != null) record.put("pump", pump);
|
||||
JSONObject openaps = new JSONObject();
|
||||
if (enacted != null) openaps.put("enacted", enacted);
|
||||
if (suggested != null) openaps.put("suggested", suggested);
|
||||
if (iob != null) openaps.put("iob", iob);
|
||||
record.put("openaps", openaps);
|
||||
if (uploaderBattery != 0) record.put("uploaderBattery", uploaderBattery);
|
||||
if (created_at != null) record.put("created_at", created_at);
|
||||
if (configuration != null) record.put("configuration", configuration);
|
||||
} catch (JSONException e) {
|
||||
aapsLogger.error("Unhandled exception", e);
|
||||
}
|
||||
return record;
|
||||
}
|
||||
|
||||
}
|
File diff suppressed because it is too large
Load diff
|
@ -6,14 +6,14 @@ import androidx.room.TypeConverters
|
|||
import info.nightscout.androidaps.database.daos.*
|
||||
import info.nightscout.androidaps.database.entities.*
|
||||
|
||||
const val DATABASE_VERSION = 9
|
||||
const val DATABASE_VERSION = 10
|
||||
|
||||
@Database(version = DATABASE_VERSION,
|
||||
entities = [APSResult::class, Bolus::class, BolusCalculatorResult::class, Carbs::class,
|
||||
EffectiveProfileSwitch::class, ExtendedBolus::class, GlucoseValue::class, ProfileSwitch::class,
|
||||
TemporaryBasal::class, TemporaryTarget::class, TherapyEvent::class, TotalDailyDose::class, APSResultLink::class,
|
||||
MultiwaveBolusLink::class, PreferenceChange::class, VersionChange::class, UserEntry::class,
|
||||
Food::class],
|
||||
Food::class, DeviceStatus::class],
|
||||
exportSchema = true)
|
||||
@TypeConverters(Converters::class)
|
||||
internal abstract class AppDatabase : RoomDatabase() {
|
||||
|
@ -54,4 +54,6 @@ internal abstract class AppDatabase : RoomDatabase() {
|
|||
|
||||
abstract val foodDao: FoodDao
|
||||
|
||||
abstract val deviceStatusDao: DeviceStatusDao
|
||||
|
||||
}
|
|
@ -455,6 +455,26 @@ open class AppRepository @Inject internal constructor(
|
|||
fun deleteAllBolusCalculatorResults() =
|
||||
database.bolusCalculatorResultDao.deleteAllEntries()
|
||||
|
||||
// DEVICE STATUS
|
||||
fun insert(deviceStatus: DeviceStatus) : Long =
|
||||
database.deviceStatusDao.insert(deviceStatus)
|
||||
|
||||
/*
|
||||
* returns a Pair of the next entity to sync and the ID of the "update".
|
||||
* The update id might either be the entry id itself if it is a new entry - or the id
|
||||
* of the update ("historic") entry. The sync counter should be incremented to that id if it was synced successfully.
|
||||
*
|
||||
* It is a Maybe as there might be no next element.
|
||||
* */
|
||||
|
||||
fun getNextSyncElementDeviceStatus(id: Long): Maybe<DeviceStatus> =
|
||||
database.deviceStatusDao.getNextModifiedOrNewAfter(id)
|
||||
.subscribeOn(Schedulers.io())
|
||||
|
||||
fun getModifiedDeviceStatusDataFromId(lastId: Long): Single<List<DeviceStatus>> =
|
||||
database.deviceStatusDao.getModifiedFrom(lastId)
|
||||
.subscribeOn(Schedulers.io())
|
||||
|
||||
}
|
||||
|
||||
@Suppress("USELESS_CAST")
|
||||
|
|
|
@ -24,5 +24,6 @@ internal class DelegatedAppDatabase(val changes: MutableList<DBEntry>, val datab
|
|||
val userEntryDao: UserEntryDao = DelegatedUserEntryDao(changes, database.userEntryDao)
|
||||
val preferenceChangeDao: PreferenceChangeDao = DelegatedPreferenceChangeDao(changes, database.preferenceChangeDao)
|
||||
val foodDao: FoodDao = DelegatedFoodDao(changes, database.foodDao)
|
||||
val deviceStatusDao: DeviceStatusDao = DelegatedDeviceStatusDao(changes, database.deviceStatusDao)
|
||||
fun clearAllTables() = database.clearAllTables()
|
||||
}
|
|
@ -5,11 +5,11 @@ const val TABLE_APS_RESULT_LINKS = "apsResultLinks"
|
|||
const val TABLE_BOLUSES = "boluses"
|
||||
const val TABLE_BOLUS_CALCULATOR_RESULTS = "bolusCalculatorResults"
|
||||
const val TABLE_CARBS = "carbs"
|
||||
const val TABLE_DEVICE_STATUS = "deviceStatus"
|
||||
const val TABLE_EFFECTIVE_PROFILE_SWITCHES = "effectiveProfileSwitches"
|
||||
const val TABLE_EXTENDED_BOLUSES = "extendedBoluses"
|
||||
const val TABLE_GLUCOSE_VALUES = "glucoseValues"
|
||||
const val TABLE_FOODS = "foods"
|
||||
const val TABLE_MEAL_LINKS = "mealLinks"
|
||||
const val TABLE_MULTIWAVE_BOLUS_LINKS = "multiwaveBolusLinks"
|
||||
const val TABLE_PROFILE_SWITCHES = "profileSwitches"
|
||||
const val TABLE_TEMPORARY_BASALS = "temporaryBasals"
|
||||
|
|
|
@ -0,0 +1,41 @@
|
|||
package info.nightscout.androidaps.database.daos
|
||||
|
||||
import androidx.room.Dao
|
||||
import androidx.room.Insert
|
||||
import androidx.room.Query
|
||||
import androidx.room.Update
|
||||
import info.nightscout.androidaps.database.entities.DeviceStatus
|
||||
import info.nightscout.androidaps.database.TABLE_DEVICE_STATUS
|
||||
import io.reactivex.Maybe
|
||||
import io.reactivex.Single
|
||||
|
||||
@Suppress("FunctionName")
|
||||
@Dao
|
||||
internal interface DeviceStatusDao {
|
||||
|
||||
@Insert
|
||||
fun insert(entry: DeviceStatus): Long
|
||||
|
||||
@Update
|
||||
fun update(entry: DeviceStatus)
|
||||
|
||||
@Query("SELECT * FROM $TABLE_DEVICE_STATUS WHERE id = :id")
|
||||
fun findById(id: Long): DeviceStatus?
|
||||
|
||||
@Query("DELETE FROM $TABLE_DEVICE_STATUS")
|
||||
fun deleteAllEntries()
|
||||
|
||||
@Query("DELETE FROM $TABLE_DEVICE_STATUS WHERE id NOT IN (SELECT MAX(id) FROM $TABLE_DEVICE_STATUS)")
|
||||
fun deleteAllEntriesExceptLast()
|
||||
|
||||
@Query("SELECT * FROM $TABLE_DEVICE_STATUS WHERE nightscoutId = :nsId")
|
||||
fun findByNSId(nsId: String): DeviceStatus?
|
||||
|
||||
// This query will be used with v3 to get all changed records
|
||||
@Query("SELECT * FROM $TABLE_DEVICE_STATUS WHERE id > :id ORDER BY id ASC")
|
||||
fun getModifiedFrom(id: Long): Single<List<DeviceStatus>>
|
||||
|
||||
// for WS we need 1 record only
|
||||
@Query("SELECT * FROM $TABLE_DEVICE_STATUS WHERE id > :id ORDER BY id ASC limit 1")
|
||||
fun getNextModifiedOrNewAfter(id: Long): Maybe<DeviceStatus>
|
||||
}
|
|
@ -0,0 +1,6 @@
|
|||
package info.nightscout.androidaps.database.daos.delegated
|
||||
|
||||
import info.nightscout.androidaps.database.daos.DeviceStatusDao
|
||||
import info.nightscout.androidaps.database.interfaces.DBEntry
|
||||
|
||||
internal class DelegatedDeviceStatusDao(changes: MutableList<DBEntry>, private val dao: DeviceStatusDao) : DelegatedDao(changes), DeviceStatusDao by dao
|
|
@ -0,0 +1,44 @@
|
|||
package info.nightscout.androidaps.database.entities
|
||||
|
||||
import androidx.room.Embedded
|
||||
import androidx.room.Entity
|
||||
import androidx.room.Index
|
||||
import androidx.room.PrimaryKey
|
||||
import info.nightscout.androidaps.database.TABLE_DEVICE_STATUS
|
||||
import info.nightscout.androidaps.database.embedments.InterfaceIDs
|
||||
import info.nightscout.androidaps.database.interfaces.DBEntryWithTime
|
||||
import java.util.*
|
||||
|
||||
@Entity(tableName = TABLE_DEVICE_STATUS,
|
||||
foreignKeys = [],
|
||||
indices = [Index("timestamp")])
|
||||
data class DeviceStatus(
|
||||
@PrimaryKey(autoGenerate = true)
|
||||
var id: Long = 0,
|
||||
@Embedded
|
||||
var interfaceIDs_backing: InterfaceIDs? = null,
|
||||
override var timestamp: Long,
|
||||
override var utcOffset: Long = TimeZone.getDefault().getOffset(timestamp).toLong(),
|
||||
var device: String? = null,
|
||||
var pump: String? = null,
|
||||
var enacted: String? = null,
|
||||
var suggested: String? = null,
|
||||
var iob: String? = null,
|
||||
var uploaderBattery: Int = 0,
|
||||
var configuration: String? = null
|
||||
|
||||
) : DBEntryWithTime {
|
||||
|
||||
var interfaceIDs: InterfaceIDs
|
||||
get() {
|
||||
var value = this.interfaceIDs_backing
|
||||
if (value == null) {
|
||||
value = InterfaceIDs()
|
||||
interfaceIDs_backing = value
|
||||
}
|
||||
return value
|
||||
}
|
||||
set(value) {
|
||||
interfaceIDs_backing = value
|
||||
}
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
package info.nightscout.androidaps.database.transactions
|
||||
|
||||
import info.nightscout.androidaps.database.entities.DeviceStatus
|
||||
|
||||
class UpdateNsIdDeviceStatusTransaction(val deviceStatus: DeviceStatus) : Transaction<Unit>() {
|
||||
|
||||
override fun run() {
|
||||
val current = database.deviceStatusDao.findById(deviceStatus.id)
|
||||
if (current != null && current.interfaceIDs.nightscoutId != deviceStatus.interfaceIDs.nightscoutId)
|
||||
database.deviceStatusDao.update(deviceStatus)
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue