Bolus, Carbs, BolusCalcResult new way of upload to NS

This commit is contained in:
Milos Kozak 2021-03-28 13:45:27 +02:00
parent c9c02458d6
commit df1e2c53db
54 changed files with 950 additions and 458 deletions

View file

@ -5,10 +5,13 @@ import android.content.Intent
import android.content.IntentFilter
import android.net.ConnectivityManager
import android.net.wifi.WifiManager
import android.os.Build
import com.j256.ormlite.android.apptools.OpenHelperManager
import dagger.android.AndroidInjector
import dagger.android.DaggerApplication
import info.nightscout.androidaps.database.AppRepository
import info.nightscout.androidaps.database.entities.TherapyEvent
import info.nightscout.androidaps.database.transactions.InsertTherapyEventIfNewTransaction
import info.nightscout.androidaps.database.transactions.VersionChangeTransaction
import info.nightscout.androidaps.db.CompatDBHelper
import info.nightscout.androidaps.db.DatabaseHelper
@ -27,9 +30,11 @@ import info.nightscout.androidaps.receivers.KeepAliveReceiver.KeepAliveManager
import info.nightscout.androidaps.receivers.NetworkChangeReceiver
import info.nightscout.androidaps.receivers.TimeDateOrTZChangeReceiver
import info.nightscout.androidaps.utils.ActivityMonitor
import info.nightscout.androidaps.utils.DateUtil
import info.nightscout.androidaps.utils.locale.LocaleHelper.update
import info.nightscout.androidaps.utils.sharedPreferences.SP
import io.reactivex.disposables.CompositeDisposable
import io.reactivex.rxkotlin.plusAssign
import net.danlew.android.joda.JodaTimeAndroid
import javax.inject.Inject
@ -49,6 +54,7 @@ class MainApp : DaggerApplication() {
@Inject lateinit var plugins: List<@JvmSuppressWildcards PluginBase>
@Inject lateinit var compatDBHelper: CompatDBHelper
@Inject lateinit var repository: AppRepository
@Inject lateinit var dateUtil: DateUtil
@Inject lateinit var staticInjector: StaticInjector// TODO avoid , here fake only to initialize
override fun onCreate() {
@ -63,8 +69,9 @@ class MainApp : DaggerApplication() {
gitRemote = null
commitHash = null
}
disposable.add(repository.runTransaction(VersionChangeTransaction(BuildConfig.VERSION_NAME, BuildConfig.VERSION_CODE, gitRemote, commitHash)).subscribe())
disposable.add(compatDBHelper.dbChangeDisposable())
disposable += repository.runTransaction(VersionChangeTransaction(BuildConfig.VERSION_NAME, BuildConfig.VERSION_CODE, gitRemote, commitHash)).subscribe()
disposable += repository.runTransaction(InsertTherapyEventIfNewTransaction(timestamp = dateUtil._now(), type = TherapyEvent.Type.NOTE, note = getString(info.nightscout.androidaps.core.R.string.androidaps_start).toString() + " - " + Build.MANUFACTURER + " " + Build.MODEL, glucoseUnit = TherapyEvent.GlucoseUnit.MGDL)).subscribe()
disposable += compatDBHelper.dbChangeDisposable()
registerActivityLifecycleCallbacks(activityMonitor)
JodaTimeAndroid.init(this)
aapsLogger.debug("Version: " + BuildConfig.VERSION_NAME)
@ -78,8 +85,7 @@ class MainApp : DaggerApplication() {
// Register all tabs in app here
pluginStore.plugins = plugins
configBuilderPlugin.initialize()
nsUpload.uploadAppStart()
Thread { keepAliveManager.setAlarm(this) }.start()
keepAliveManager.setAlarm(this)
doMigrations()
}

View file

@ -23,7 +23,6 @@ import info.nightscout.androidaps.databinding.DialogCareBinding
import info.nightscout.androidaps.interfaces.ProfileFunction
import info.nightscout.androidaps.logging.LTag
import info.nightscout.androidaps.logging.UserEntryLogger
import info.nightscout.androidaps.plugins.general.nsclient.NSUpload
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.GlucoseStatusProvider
import info.nightscout.androidaps.utils.HtmlHelper
import info.nightscout.androidaps.utils.T
@ -43,7 +42,6 @@ class CareDialog : DialogFragmentWithDate() {
@Inject lateinit var ctx: Context
@Inject lateinit var resourceHelper: ResourceHelper
@Inject lateinit var profileFunction: ProfileFunction
@Inject lateinit var nsUpload: NSUpload
@Inject lateinit var translator: Translator
@Inject lateinit var uel: UserEntryLogger
@Inject lateinit var repository: AppRepository
@ -224,11 +222,11 @@ class CareDialog : DialogFragmentWithDate() {
activity?.let { activity ->
OKDialog.showConfirmation(activity, resourceHelper.gs(event), HtmlHelper.fromHtml(Joiner.on("<br/>").join(actions)), {
disposable += repository.runTransactionForResult(InsertTherapyEventIfNewTransaction(therapyEvent)).subscribe({ result ->
result.inserted.forEach { nsUpload.uploadEvent(it) }
}, {
aapsLogger.error(LTag.DATABASE, "Error while saving therapy event", it)
})
disposable += repository.runTransactionForResult(InsertTherapyEventIfNewTransaction(therapyEvent))
.subscribe(
{ result -> result.inserted.forEach { aapsLogger.debug(LTag.DATABASE, "Inserted therapy event $it") } },
{ aapsLogger.error(LTag.DATABASE, "Error while saving therapy event", it) }
)
valuesWithUnit.add(0, ValueWithUnit(eventTime, Units.Timestamp, eventTimeChanged))
valuesWithUnit.add(1, ValueWithUnit(therapyEvent.type.text, Units.TherapyEvent))
uel.log(Action.CAREPORTAL, notes, valuesWithUnit)

View file

@ -22,7 +22,6 @@ import info.nightscout.androidaps.interfaces.Constraint
import info.nightscout.androidaps.logging.LTag
import info.nightscout.androidaps.logging.UserEntryLogger
import info.nightscout.androidaps.plugins.configBuilder.ConstraintChecker
import info.nightscout.androidaps.plugins.general.nsclient.NSUpload
import info.nightscout.androidaps.queue.Callback
import info.nightscout.androidaps.utils.DecimalFormatter
import info.nightscout.androidaps.utils.HtmlHelper
@ -41,7 +40,6 @@ class FillDialog : DialogFragmentWithDate() {
@Inject lateinit var constraintChecker: ConstraintChecker
@Inject lateinit var resourceHelper: ResourceHelper
@Inject lateinit var ctx: Context
@Inject lateinit var nsUpload: NSUpload
@Inject lateinit var commandQueue: CommandQueueProvider
@Inject lateinit var activePlugin: ActivePluginProvider
@Inject lateinit var uel: UserEntryLogger
@ -147,11 +145,10 @@ class FillDialog : DialogFragmentWithDate() {
type = TherapyEvent.Type.CANNULA_CHANGE,
note = notes,
glucoseUnit = TherapyEvent.GlucoseUnit.MGDL
)).subscribe({ result ->
result.inserted.forEach { nsUpload.uploadEvent(it) }
}, {
aapsLogger.error(LTag.DATABASE, "Error while saving therapy event", it)
})
)).subscribe(
{ result -> result.inserted.forEach { aapsLogger.debug(LTag.DATABASE, "Inserted therapy event $it") } },
{ aapsLogger.error(LTag.DATABASE, "Error while saving therapy event", it) }
)
}
if (insulinChange) {
// add a second for case of both checked
@ -161,11 +158,10 @@ class FillDialog : DialogFragmentWithDate() {
type = TherapyEvent.Type.INSULIN_CHANGE,
note = notes,
glucoseUnit = TherapyEvent.GlucoseUnit.MGDL
)).subscribe({ result ->
result.inserted.forEach { nsUpload.uploadEvent(it) }
}, {
aapsLogger.error(LTag.DATABASE, "Error while saving therapy event", it)
})
)).subscribe(
{ result -> result.inserted.forEach { aapsLogger.debug(LTag.DATABASE, "Inserted therapy event $it") } },
{ aapsLogger.error(LTag.DATABASE, "Error while saving therapy event", it) }
)
}
}, null)
}

View file

@ -217,14 +217,10 @@ class InsulinDialog : DialogFragmentWithDate() {
)
if (recordOnlyChecked) {
disposable += repository.runTransactionForResult(detailedBolusInfo.insertBolusTransaction())
.subscribe({ result ->
result.inserted.forEach {
aapsLogger.debug(LTag.DATABASE, "Inserted bolus $it")
nsUpload.uploadBolusRecord(it, detailedBolusInfo.createTherapyEvent(), null)
}
}, {
aapsLogger.error(LTag.DATABASE, "Error while saving bolus", it)
})
.subscribe(
{ result -> result.inserted.forEach { aapsLogger.debug(LTag.DATABASE, "Inserted bolus $it") } },
{ aapsLogger.error(LTag.DATABASE, "Error while saving bolus", it) }
)
} else {
commandQueue.bolus(detailedBolusInfo, object : Callback() {
override fun run() {

View file

@ -152,23 +152,15 @@ class TreatmentDialog : DialogFragmentWithDate() {
)
if (recordOnlyChecked) {
disposable += repository.runTransactionForResult(detailedBolusInfo.insertBolusTransaction())
.subscribe({ result ->
result.inserted.forEach {
aapsLogger.debug(LTag.DATABASE, "Inserted bolus $it")
nsUpload.uploadBolusRecord(it, detailedBolusInfo.createTherapyEvent(), null)
}
}, {
aapsLogger.error(LTag.DATABASE, "Error while saving bolus", it)
})
.subscribe(
{ result -> result.inserted.forEach { aapsLogger.debug(LTag.DATABASE, "Inserted bolus $it") } },
{ aapsLogger.error(LTag.DATABASE, "Error while saving bolus", it) }
)
disposable += repository.runTransactionForResult(detailedBolusInfo.insertCarbsTransaction())
.subscribe({ result ->
result.inserted.forEach {
aapsLogger.debug(LTag.DATABASE, "Inserted carbs $it")
nsUpload.uploadCarbsRecord(it, detailedBolusInfo.createTherapyEvent())
}
}, {
aapsLogger.error(LTag.DATABASE, "Error while saving carbs", it)
})
.subscribe(
{ result -> result.inserted.forEach { aapsLogger.debug(LTag.DATABASE, "Inserted carbs $it") } },
{ aapsLogger.error(LTag.DATABASE, "Error while saving carbs", it) }
)
} else {
commandQueue.bolus(detailedBolusInfo, object : Callback() {
override fun run() {

View file

@ -17,6 +17,7 @@ import info.nightscout.androidaps.data.Profile
import info.nightscout.androidaps.data.PumpEnactResult
import info.nightscout.androidaps.database.AppRepository
import info.nightscout.androidaps.database.entities.TherapyEvent
import info.nightscout.androidaps.database.transactions.InsertTherapyEventAnnouncementTransaction
import info.nightscout.androidaps.database.transactions.InsertTherapyEventIfNewTransaction
import info.nightscout.androidaps.events.EventAcceptOpenLoopChange
import info.nightscout.androidaps.events.EventAutosensCalculationFinished
@ -334,7 +335,7 @@ open class LoopPlugin @Inject constructor(
rxBus.send(EventNewNotification(carbReqLocal))
}
if (sp.getBoolean(R.string.key_ns_create_announcements_from_carbs_req, false)) {
nsUpload.uploadError(resultAfterConstraints.carbsRequiredText)
disposable += repository.runTransaction(InsertTherapyEventAnnouncementTransaction(resultAfterConstraints.carbsRequiredText)).subscribe()
}
if (sp.getBoolean(R.string.key_enable_carbs_required_alert_local, true) && sp.getBoolean(R.string.key_raise_notifications_as_android_notifications, true)) {
val intentAction5m = Intent(context, CarbSuggestionReceiver::class.java)
@ -658,11 +659,10 @@ open class LoopPlugin @Inject constructor(
duration = T.mins(durationInMinutes.toLong()).msecs(),
enteredBy = "openaps://" + "AndroidAPS",
glucoseUnit = TherapyEvent.GlucoseUnit.MGDL
)).subscribe({ result ->
result.inserted.forEach { nsUpload.uploadEvent(it) }
}, {
aapsLogger.error(LTag.DATABASE, "Error while saving therapy event", it)
})
)).subscribe(
{ result -> result.inserted.forEach { aapsLogger.debug(LTag.DATABASE, "Inserted therapy event $it") } },
{ aapsLogger.error(LTag.DATABASE, "Error while saving therapy event", it) }
)
}
companion object {

View file

@ -25,7 +25,6 @@ import info.nightscout.androidaps.logging.AAPSLogger
import info.nightscout.androidaps.logging.LTag
import info.nightscout.androidaps.logging.UserEntryLogger
import info.nightscout.androidaps.plugins.bus.RxBusWrapper
import info.nightscout.androidaps.plugins.general.nsclient.NSUpload
import info.nightscout.androidaps.plugins.general.nsclient.events.EventNSClientRestart
import info.nightscout.androidaps.utils.FabricPrivacy
import info.nightscout.androidaps.utils.alertDialogs.OKDialog
@ -48,7 +47,6 @@ class FoodFragment : DaggerFragment() {
@Inject lateinit var aapsLogger: AAPSLogger
@Inject lateinit var resourceHelper: ResourceHelper
@Inject lateinit var fabricPrivacy: FabricPrivacy
@Inject lateinit var nsUpload: NSUpload
@Inject lateinit var repository: AppRepository
@Inject lateinit var uel: UserEntryLogger
@ -200,8 +198,10 @@ class FoodFragment : DaggerFragment() {
private fun filterData() {
val textFilter = binding.filter.text.toString()
val categoryFilter = binding.category.selectedItem?.toString() ?: resourceHelper.gs(R.string.none)
val subcategoryFilter = binding.subcategory.selectedItem?.toString() ?: resourceHelper.gs(R.string.none)
val categoryFilter = binding.category.selectedItem?.toString()
?: resourceHelper.gs(R.string.none)
val subcategoryFilter = binding.subcategory.selectedItem?.toString()
?: resourceHelper.gs(R.string.none)
val newFiltered = ArrayList<Food>()
for (f in unfiltered) {
if (f.category == null || f.subCategory == null) continue
@ -252,14 +252,10 @@ class FoodFragment : DaggerFragment() {
OKDialog.showConfirmation(activity, resourceHelper.gs(R.string.removerecord) + "\n" + food.name, {
uel.log(Action.FOOD_REMOVED, food.name)
disposable += repository.runTransactionForResult(InvalidateFoodTransaction(food.id))
.subscribe({
val id = food.interfaceIDs.nightscoutId
if (NSUpload.isIdValid(id)) nsUpload.removeFoodFromNS(id)
// no create at the moment
// else uploadQueue.removeID("dbAdd", food.timestamp.toString())
}, {
aapsLogger.error(LTag.DATABASE, "Error while invalidating food", it)
})
.subscribe(
{ aapsLogger.error(LTag.DATABASE, "Invalidated food $it") },
{ aapsLogger.error(LTag.DATABASE, "Error while invalidating food", it) }
)
}, null)
}
}

View file

@ -2,14 +2,12 @@ package info.nightscout.androidaps.plugins.general.nsclient
import info.nightscout.androidaps.R
import info.nightscout.androidaps.database.AppRepository
import info.nightscout.androidaps.database.entities.GlucoseValue
import info.nightscout.androidaps.database.entities.TemporaryTarget
import info.nightscout.androidaps.database.entities.*
import info.nightscout.androidaps.interfaces.ActivePluginProvider
import info.nightscout.androidaps.interfaces.DataSyncSelector
import info.nightscout.androidaps.interfaces.ProfileFunction
import info.nightscout.androidaps.logging.AAPSLogger
import info.nightscout.androidaps.logging.LTag
import info.nightscout.androidaps.utils.DateUtil
import info.nightscout.androidaps.utils.extensions.toJson
import info.nightscout.androidaps.utils.sharedPreferences.SP
import javax.inject.Inject
@ -17,7 +15,6 @@ import javax.inject.Inject
class DataSyncSelectorImplementation @Inject constructor(
private val sp: SP,
private val aapsLogger: AAPSLogger,
private val dateUtil: DateUtil,
private val profileFunction: ProfileFunction,
private val nsClientPlugin: NSClientPlugin,
private val activePlugin: ActivePluginProvider,
@ -25,30 +22,142 @@ class DataSyncSelectorImplementation @Inject constructor(
) : DataSyncSelector {
override fun resetToNextFullSync() {
sp.remove(R.string.key_ns_temporary_target_last_sync)
sp.remove(R.string.key_ns_glucose_value_last_sync)
sp.remove(R.string.key_ns_temporary_target_last_synced_id)
sp.remove(R.string.key_ns_glucose_value_last_synced_id)
sp.remove(R.string.key_ns_food_last_synced_id)
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)
}
override fun confirmTempTargetsTimestamp(lastSynced: Long) {
aapsLogger.debug(LTag.NSCLIENT, "Setting TT data sync from $lastSynced")
sp.putLong(R.string.key_ns_temporary_target_last_sync, lastSynced)
override fun confirmLastBolusIdIfGreater(lastSynced: Long) {
if (lastSynced > sp.getLong(R.string.key_ns_bolus_last_synced_id, 0)) {
aapsLogger.debug(LTag.NSCLIENT, "Setting Bolus data sync from $lastSynced")
sp.putLong(R.string.key_ns_bolus_last_synced_id, lastSynced)
}
}
override fun confirmTempTargetsTimestampIfGreater(lastSynced: Long) {
if (lastSynced > sp.getLong(R.string.key_ns_temporary_target_last_sync, 0))
confirmTempTargetsTimestamp(lastSynced)
// Prepared for v3 (returns all modified after)
override fun changedBoluses(): List<Bolus> {
val startId = sp.getLong(R.string.key_ns_bolus_last_synced_id, 0)
return appRepository.getModifiedBolusesDataFromId(startId).blockingGet().also {
aapsLogger.debug(LTag.NSCLIENT, "Loading Bolus data for sync from $startId. Records ${it.size}")
}
}
override fun processChangedBolusesCompat(): Boolean {
val startId = sp.getLong(R.string.key_ns_bolus_last_synced_id, 0)
appRepository.getNextSyncElementBolus(startId).blockingGet()?.let { bolus ->
aapsLogger.info(LTag.DATABASE, "Loading Bolus data Start: $startId ID: ${bolus.first.id} HistoryID: ${bolus.second} ")
when {
// removed and not uploaded yet = ignore
!bolus.first.isValid && bolus.first.interfaceIDs.nightscoutId == null -> Any()
// removed and already uploaded = send for removal
!bolus.first.isValid && bolus.first.interfaceIDs.nightscoutId != null ->
nsClientPlugin.nsClientService?.dbRemove("treatments", bolus.first.interfaceIDs.nightscoutId, DataSyncSelector.PairBolus(bolus.first, bolus.second))
// existing without nsId = create new
bolus.first.isValid && bolus.first.interfaceIDs.nightscoutId == null ->
nsClientPlugin.nsClientService?.dbAdd("treatments", bolus.first.toJson(), DataSyncSelector.PairBolus(bolus.first, bolus.second))
// existing with nsId = update
bolus.first.isValid && bolus.first.interfaceIDs.nightscoutId != null ->
nsClientPlugin.nsClientService?.dbUpdate("treatments", bolus.first.interfaceIDs.nightscoutId, bolus.first.toJson(), DataSyncSelector.PairBolus(bolus.first, bolus.second))
}
return true
}
return false
}
override fun confirmLastCarbsIdIfGreater(lastSynced: Long) {
if (lastSynced > sp.getLong(R.string.key_ns_carbs_last_synced_id, 0)) {
aapsLogger.debug(LTag.NSCLIENT, "Setting Carbs data sync from $lastSynced")
sp.putLong(R.string.key_ns_carbs_last_synced_id, lastSynced)
}
}
// Prepared for v3 (returns all modified after)
override fun changedCarbs(): List<Carbs> {
val startId = sp.getLong(R.string.key_ns_carbs_last_synced_id, 0)
return appRepository.getModifiedCarbsDataFromId(startId).blockingGet().also {
aapsLogger.debug(LTag.NSCLIENT, "Loading Carbs data for sync from $startId. Records ${it.size}")
}
}
override fun processChangedCarbsCompat(): Boolean {
val startId = sp.getLong(R.string.key_ns_carbs_last_synced_id, 0)
appRepository.getNextSyncElementCarbs(startId).blockingGet()?.let { carb ->
aapsLogger.info(LTag.DATABASE, "Loading Carbs data Start: $startId ID: ${carb.first.id} HistoryID: ${carb.second} ")
when {
// removed and not uploaded yet = ignore
!carb.first.isValid && carb.first.interfaceIDs.nightscoutId == null -> Any()
// removed and already uploaded = send for removal
!carb.first.isValid && carb.first.interfaceIDs.nightscoutId != null ->
nsClientPlugin.nsClientService?.dbRemove("treatments", carb.first.interfaceIDs.nightscoutId, DataSyncSelector.PairCarbs(carb.first, carb.second))
// existing without nsId = create new
carb.first.isValid && carb.first.interfaceIDs.nightscoutId == null ->
nsClientPlugin.nsClientService?.dbAdd("treatments", carb.first.toJson(), DataSyncSelector.PairCarbs(carb.first, carb.second))
// existing with nsId = update
carb.first.isValid && carb.first.interfaceIDs.nightscoutId != null ->
nsClientPlugin.nsClientService?.dbUpdate("treatments", carb.first.interfaceIDs.nightscoutId, carb.first.toJson(), DataSyncSelector.PairCarbs(carb.first, carb.second))
}
return true
}
return false
}
override fun confirmLastBolusCalculatorResultsIdIfGreater(lastSynced: Long) {
if (lastSynced > sp.getLong(R.string.key_ns_bolus_calculator_result_last_synced_id, 0)) {
aapsLogger.debug(LTag.NSCLIENT, "Setting BolusCalculatorResult data sync from $lastSynced")
sp.putLong(R.string.key_ns_bolus_calculator_result_last_synced_id, lastSynced)
}
}
// Prepared for v3 (returns all modified after)
override fun changedBolusCalculatorResults(): List<BolusCalculatorResult> {
val startId = sp.getLong(R.string.key_ns_bolus_calculator_result_last_synced_id, 0)
return appRepository.getModifiedBolusCalculatorResultsDataFromId(startId).blockingGet().also {
aapsLogger.debug(LTag.NSCLIENT, "Loading BolusCalculatorResult data for sync from $startId. Records ${it.size}")
}
}
override fun processChangedBolusCalculatorResultsCompat(): Boolean {
val startId = sp.getLong(R.string.key_ns_bolus_calculator_result_last_synced_id, 0)
appRepository.getNextSyncElementBolusCalculatorResult(startId).blockingGet()?.let { bolusCalculatorResult ->
aapsLogger.info(LTag.DATABASE, "Loading BolusCalculatorResult data Start: $startId ID: ${bolusCalculatorResult.first.id} HistoryID: ${bolusCalculatorResult.second} ")
when {
// removed and not uploaded yet = ignore
!bolusCalculatorResult.first.isValid && bolusCalculatorResult.first.interfaceIDs.nightscoutId == null -> Any()
// removed and already uploaded = send for removal
!bolusCalculatorResult.first.isValid && bolusCalculatorResult.first.interfaceIDs.nightscoutId != null ->
nsClientPlugin.nsClientService?.dbRemove("treatments", bolusCalculatorResult.first.interfaceIDs.nightscoutId, DataSyncSelector.PairBolusCalculatorResult(bolusCalculatorResult.first, bolusCalculatorResult.second))
// existing without nsId = create new
bolusCalculatorResult.first.isValid && bolusCalculatorResult.first.interfaceIDs.nightscoutId == null ->
nsClientPlugin.nsClientService?.dbAdd("treatments", bolusCalculatorResult.first.toJson(), DataSyncSelector.PairBolusCalculatorResult(bolusCalculatorResult.first, bolusCalculatorResult.second))
// existing with nsId = update
bolusCalculatorResult.first.isValid && bolusCalculatorResult.first.interfaceIDs.nightscoutId != null ->
nsClientPlugin.nsClientService?.dbUpdate("treatments", bolusCalculatorResult.first.interfaceIDs.nightscoutId, bolusCalculatorResult.first.toJson(), DataSyncSelector.PairBolusCalculatorResult(bolusCalculatorResult.first, bolusCalculatorResult.second))
}
return true
}
return false
}
override fun confirmLastTempTargetsIdIfGreater(lastSynced: Long) {
if (lastSynced > sp.getLong(R.string.key_ns_temporary_target_last_synced_id, 0)) {
aapsLogger.debug(LTag.NSCLIENT, "Setting TemporaryTarget data sync from $lastSynced")
sp.putLong(R.string.key_ns_temporary_target_last_synced_id, lastSynced)
}
}
// Prepared for v3 (returns all modified after)
override fun changedTempTargets(): List<TemporaryTarget> {
val startId = sp.getLong(R.string.key_ns_temporary_target_last_sync, 0)
val startId = sp.getLong(R.string.key_ns_temporary_target_last_synced_id, 0)
return appRepository.getModifiedTemporaryTargetsDataFromId(startId).blockingGet().also {
aapsLogger.debug(LTag.NSCLIENT, "Loading TT data for sync from $startId. Records ${it.size}")
aapsLogger.debug(LTag.NSCLIENT, "Loading TemporaryTarget data for sync from $startId. Records ${it.size}")
}
}
override fun processChangedTempTargetsCompat(): Boolean {
val startId = sp.getLong(R.string.key_ns_temporary_target_last_sync, 0)
val startId = sp.getLong(R.string.key_ns_temporary_target_last_synced_id, 0)
appRepository.getNextSyncElementTemporaryTarget(startId).blockingGet()?.let { tt ->
aapsLogger.info(LTag.DATABASE, "Loading TemporaryTarget data Start: $startId ID: ${tt.first.id} HistoryID: ${tt.second} ")
when {
@ -69,26 +178,60 @@ class DataSyncSelectorImplementation @Inject constructor(
return false
}
override fun confirmLastGlucoseValueId(lastSynced: Long) {
aapsLogger.debug(LTag.NSCLIENT, "Setting GlucoseValue data sync from $lastSynced")
sp.putLong(R.string.key_ns_glucose_value_last_sync, lastSynced)
override fun confirmLastFoodIdIfGreater(lastSynced: Long) {
if (lastSynced > sp.getLong(R.string.key_ns_food_last_synced_id, 0)) {
aapsLogger.debug(LTag.NSCLIENT, "Setting Food data sync from $lastSynced")
sp.putLong(R.string.key_ns_food_last_synced_id, lastSynced)
}
}
// Prepared for v3 (returns all modified after)
override fun changedFoods(): List<Food> {
val startId = sp.getLong(R.string.key_ns_food_last_synced_id, 0)
return appRepository.getModifiedFoodDataFromId(startId).blockingGet().also {
aapsLogger.debug(LTag.NSCLIENT, "Loading Food data for sync from $startId. Records ${it.size}")
}
}
override fun processChangedFoodsCompat(): Boolean {
val startId = sp.getLong(R.string.key_ns_food_last_synced_id, 0)
appRepository.getNextSyncElementFood(startId).blockingGet()?.let { tt ->
aapsLogger.info(LTag.DATABASE, "Loading Food data Start: $startId ID: ${tt.first.id} HistoryID: ${tt.second} ")
when {
// removed and not uploaded yet = ignore
!tt.first.isValid && tt.first.interfaceIDs.nightscoutId == null -> Any()
// removed and already uploaded = send for removal
!tt.first.isValid && tt.first.interfaceIDs.nightscoutId != null ->
nsClientPlugin.nsClientService?.dbRemove("food", tt.first.interfaceIDs.nightscoutId, DataSyncSelector.PairFood(tt.first, tt.second))
// existing without nsId = create new
tt.first.isValid && tt.first.interfaceIDs.nightscoutId == null ->
nsClientPlugin.nsClientService?.dbAdd("food", tt.first.toJson(profileFunction.getUnits()), DataSyncSelector.PairFood(tt.first, tt.second))
// existing with nsId = update
tt.first.isValid && tt.first.interfaceIDs.nightscoutId != null ->
nsClientPlugin.nsClientService?.dbUpdate("food", tt.first.interfaceIDs.nightscoutId, tt.first.toJson(profileFunction.getUnits()), DataSyncSelector.PairFood(tt.first, tt.second))
}
return true
}
return false
}
override fun confirmLastGlucoseValueIdIfGreater(lastSynced: Long) {
if (lastSynced > sp.getLong(R.string.key_ns_glucose_value_last_sync, 0))
confirmLastGlucoseValueId(lastSynced)
if (lastSynced > sp.getLong(R.string.key_ns_glucose_value_last_synced_id, 0)) {
aapsLogger.debug(LTag.NSCLIENT, "Setting GlucoseValue data sync from $lastSynced")
sp.putLong(R.string.key_ns_glucose_value_last_synced_id, lastSynced)
}
}
// Prepared for v3 (returns all modified after)
override fun changedGlucoseValues(): List<GlucoseValue> {
val startId = sp.getLong(R.string.key_ns_glucose_value_last_sync, 0)
val startId = sp.getLong(R.string.key_ns_glucose_value_last_synced_id, 0)
return appRepository.getModifiedBgReadingsDataFromId(startId).blockingGet().also {
aapsLogger.debug(LTag.NSCLIENT, "Loading GlucoseValue data for sync from $startId . Records ${it.size}")
}
}
override fun processChangedGlucoseValuesCompat(): Boolean {
val startId = sp.getLong(R.string.key_ns_glucose_value_last_sync, 0)
val startId = sp.getLong(R.string.key_ns_glucose_value_last_synced_id, 0)
appRepository.getNextSyncElementGlucoseValue(startId).blockingGet()?.let { gv ->
aapsLogger.info(LTag.DATABASE, "Loading GlucoseValue data Start: $startId ID: ${gv.first.id} HistoryID: ${gv.second} ")
if (activePlugin.activeBgSource.uploadToNs(gv.first)) {
@ -111,4 +254,41 @@ class DataSyncSelectorImplementation @Inject constructor(
return false
}
override fun confirmLastTherapyEventIdIfGreater(lastSynced: Long) {
if (lastSynced > sp.getLong(R.string.key_ns_therapy_event_last_synced_id, 0)) {
aapsLogger.debug(LTag.NSCLIENT, "Setting TherapyEvents data sync from $lastSynced")
sp.putLong(R.string.key_ns_therapy_event_last_synced_id, lastSynced)
}
}
// Prepared for v3 (returns all modified after)
override fun changedTherapyEvents(): List<TherapyEvent> {
val startId = sp.getLong(R.string.key_ns_therapy_event_last_synced_id, 0)
return appRepository.getModifiedTherapyEventDataFromId(startId).blockingGet().also {
aapsLogger.debug(LTag.NSCLIENT, "Loading TherapyEvents data for sync from $startId. Records ${it.size}")
}
}
override fun processChangedTherapyEventsCompat(): Boolean {
val startId = sp.getLong(R.string.key_ns_therapy_event_last_synced_id, 0)
appRepository.getNextSyncElementTherapyEvent(startId).blockingGet()?.let { tt ->
aapsLogger.info(LTag.DATABASE, "Loading TherapyEvents data Start: $startId ID: ${tt.first.id} HistoryID: ${tt.second} ")
when {
// removed and not uploaded yet = ignore
!tt.first.isValid && tt.first.interfaceIDs.nightscoutId == null -> Any()
// removed and already uploaded = send for removal
!tt.first.isValid && tt.first.interfaceIDs.nightscoutId != null ->
nsClientPlugin.nsClientService?.dbRemove("treatments", tt.first.interfaceIDs.nightscoutId, DataSyncSelector.PairTherapyEvent(tt.first, tt.second))
// existing without nsId = create new
tt.first.isValid && tt.first.interfaceIDs.nightscoutId == null ->
nsClientPlugin.nsClientService?.dbAdd("treatments", tt.first.toJson(), DataSyncSelector.PairTherapyEvent(tt.first, tt.second))
// existing with nsId = update
tt.first.isValid && tt.first.interfaceIDs.nightscoutId != null ->
nsClientPlugin.nsClientService?.dbUpdate("treatments", tt.first.interfaceIDs.nightscoutId, tt.first.toJson(), DataSyncSelector.PairTherapyEvent(tt.first, tt.second))
}
return true
}
return false
}
}

View file

@ -32,8 +32,14 @@ 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.transactions.UpdateNsIdBolusCalculatorResultTransaction;
import info.nightscout.androidaps.database.transactions.UpdateNsIdBolusTransaction;
import info.nightscout.androidaps.database.transactions.UpdateNsIdCarbsTransaction;
import info.nightscout.androidaps.database.transactions.UpdateNsIdFoodTransaction;
import info.nightscout.androidaps.database.transactions.UpdateNsIdGlucoseValueTransaction;
import info.nightscout.androidaps.database.transactions.UpdateNsIdTemporaryTargetTransaction;
import info.nightscout.androidaps.database.transactions.UpdateNsIdTherapyEventTransaction;
import info.nightscout.androidaps.db.DbRequest;
import info.nightscout.androidaps.events.EventAppExit;
import info.nightscout.androidaps.events.EventConfigBuilderChange;
@ -231,8 +237,8 @@ public class NSClientService extends DaggerService {
result -> aapsLogger.debug(LTag.DATABASE, "Updated ns id of temporary target " + pair.getValue()),
error -> aapsLogger.error(LTag.DATABASE, "Updated ns id of temporary target failed")
));
dataSyncSelector.confirmTempTargetsTimestampIfGreater(pair.getUpdateRecordId());
rxBus.send(new EventNSClientNewLog("DBADD", "Acked " + pair.getValue().getInterfaceIDs().getNightscoutId()));
dataSyncSelector.confirmLastTempTargetsIdIfGreater(pair.getUpdateRecordId());
rxBus.send(new EventNSClientNewLog("DBADD", "Acked TemporaryTarget " + pair.getValue().getInterfaceIDs().getNightscoutId()));
// Send new if waiting
dataSyncSelector.processChangedTempTargetsCompat();
return;
@ -248,11 +254,91 @@ public class NSClientService extends DaggerService {
error -> aapsLogger.error(LTag.DATABASE, "Updated ns id of glucose value failed", error)
));
dataSyncSelector.confirmLastGlucoseValueIdIfGreater(pair.getUpdateRecordId());
rxBus.send(new EventNSClientNewLog("DBADD", "Acked " + pair.getValue().getInterfaceIDs().getNightscoutId()));
rxBus.send(new EventNSClientNewLog("DBADD", "Acked GlucoseValue " + pair.getValue().getInterfaceIDs().getNightscoutId()));
// Send new if waiting
dataSyncSelector.processChangedGlucoseValuesCompat();
return;
}
if (ack.getOriginalObject() instanceof DataSyncSelector.PairFood) {
DataSyncSelector.PairFood pair = (DataSyncSelector.PairFood) ack.getOriginalObject();
pair.getValue().getInterfaceIDs().setNightscoutId(ack.getId());
disposable.add(repository.runTransactionForResult(new UpdateNsIdFoodTransaction(pair.getValue()))
.observeOn(aapsSchedulers.getIo())
.subscribe(
result -> aapsLogger.debug(LTag.DATABASE, "Updated ns id of food " + pair.getValue()),
error -> aapsLogger.error(LTag.DATABASE, "Updated ns id of food failed", error)
));
dataSyncSelector.confirmLastFoodIdIfGreater(pair.getUpdateRecordId());
rxBus.send(new EventNSClientNewLog("DBADD", "Acked Food " + pair.getValue().getInterfaceIDs().getNightscoutId()));
// Send new if waiting
dataSyncSelector.processChangedFoodsCompat();
return;
}
if (ack.getOriginalObject() instanceof DataSyncSelector.PairTherapyEvent) {
DataSyncSelector.PairTherapyEvent pair = (DataSyncSelector.PairTherapyEvent) ack.getOriginalObject();
pair.getValue().getInterfaceIDs().setNightscoutId(ack.getId());
disposable.add(repository.runTransactionForResult(new UpdateNsIdTherapyEventTransaction(pair.getValue()))
.observeOn(aapsSchedulers.getIo())
.subscribe(
result -> aapsLogger.debug(LTag.DATABASE, "Updated ns id of therapy event " + pair.getValue()),
error -> aapsLogger.error(LTag.DATABASE, "Updated ns id of therapy event failed", error)
));
dataSyncSelector.confirmLastTherapyEventIdIfGreater(pair.getUpdateRecordId());
rxBus.send(new EventNSClientNewLog("DBADD", "Acked TherapyEvent " + pair.getValue().getInterfaceIDs().getNightscoutId()));
// Send new if waiting
dataSyncSelector.processChangedTherapyEventsCompat();
return;
}
if (ack.getOriginalObject() instanceof DataSyncSelector.PairBolus) {
DataSyncSelector.PairBolus pair = (DataSyncSelector.PairBolus) ack.getOriginalObject();
pair.getValue().getInterfaceIDs().setNightscoutId(ack.getId());
disposable.add(repository.runTransactionForResult(new UpdateNsIdBolusTransaction(pair.getValue()))
.observeOn(aapsSchedulers.getIo())
.subscribe(
result -> aapsLogger.debug(LTag.DATABASE, "Updated ns id of bolus " + pair.getValue()),
error -> aapsLogger.error(LTag.DATABASE, "Updated ns id of bolus failed", error)
));
dataSyncSelector.confirmLastBolusIdIfGreater(pair.getUpdateRecordId());
rxBus.send(new EventNSClientNewLog("DBADD", "Acked Bolus " + pair.getValue().getInterfaceIDs().getNightscoutId()));
// Send new if waiting
dataSyncSelector.processChangedBolusesCompat();
return;
}
if (ack.getOriginalObject() instanceof DataSyncSelector.PairCarbs) {
DataSyncSelector.PairCarbs pair = (DataSyncSelector.PairCarbs) ack.getOriginalObject();
pair.getValue().getInterfaceIDs().setNightscoutId(ack.getId());
disposable.add(repository.runTransactionForResult(new UpdateNsIdCarbsTransaction(pair.getValue()))
.observeOn(aapsSchedulers.getIo())
.subscribe(
result -> aapsLogger.debug(LTag.DATABASE, "Updated ns id of carbs " + pair.getValue()),
error -> aapsLogger.error(LTag.DATABASE, "Updated ns id of carbs failed", error)
));
dataSyncSelector.confirmLastCarbsIdIfGreater(pair.getUpdateRecordId());
rxBus.send(new EventNSClientNewLog("DBADD", "Acked Carbs" + pair.getValue().getInterfaceIDs().getNightscoutId()));
// Send new if waiting
dataSyncSelector.processChangedCarbsCompat();
return;
}
if (ack.getOriginalObject() instanceof DataSyncSelector.PairBolusCalculatorResult) {
DataSyncSelector.PairBolusCalculatorResult pair = (DataSyncSelector.PairBolusCalculatorResult) ack.getOriginalObject();
pair.getValue().getInterfaceIDs().setNightscoutId(ack.getId());
disposable.add(repository.runTransactionForResult(new UpdateNsIdBolusCalculatorResultTransaction(pair.getValue()))
.observeOn(aapsSchedulers.getIo())
.subscribe(
result -> aapsLogger.debug(LTag.DATABASE, "Updated ns id of BolusCalculatorResult " + pair.getValue()),
error -> aapsLogger.error(LTag.DATABASE, "Updated ns id of BolusCalculatorResult failed", error)
));
dataSyncSelector.confirmLastBolusCalculatorResultsIdIfGreater(pair.getUpdateRecordId());
rxBus.send(new EventNSClientNewLog("DBADD", "Acked BolusCalculatorResult" + pair.getValue().getInterfaceIDs().getNightscoutId()));
// Send new if waiting
dataSyncSelector.processChangedBolusCalculatorResultsCompat();
return;
}
// old way
if (ack.nsClientID != null) {
uploadQueue.removeByNsClientIdIfExists(ack.json);
@ -267,8 +353,8 @@ public class NSClientService extends DaggerService {
// new room way
if (ack.getOriginalObject() instanceof DataSyncSelector.PairTemporaryTarget) {
DataSyncSelector.PairTemporaryTarget pair = (DataSyncSelector.PairTemporaryTarget) ack.getOriginalObject();
dataSyncSelector.confirmTempTargetsTimestampIfGreater(pair.getUpdateRecordId());
rxBus.send(new EventNSClientNewLog("DBUPDATE/DBREMOVE", "Acked " + ack.get_id()));
dataSyncSelector.confirmLastTempTargetsIdIfGreater(pair.getUpdateRecordId());
rxBus.send(new EventNSClientNewLog("DBUPDATE/DBREMOVE", "Acked TemporaryTarget" + ack.get_id()));
// Send new if waiting
dataSyncSelector.processChangedTempTargetsCompat();
return;
@ -276,11 +362,51 @@ public class NSClientService extends DaggerService {
if (ack.getOriginalObject() instanceof DataSyncSelector.PairGlucoseValue) {
DataSyncSelector.PairGlucoseValue pair = (DataSyncSelector.PairGlucoseValue) ack.getOriginalObject();
dataSyncSelector.confirmLastGlucoseValueIdIfGreater(pair.getUpdateRecordId());
rxBus.send(new EventNSClientNewLog("DBUPDATE/DBREMOVE", "Acked " + ack.get_id()));
rxBus.send(new EventNSClientNewLog("DBUPDATE/DBREMOVE", "Acked GlucoseValue " + ack.get_id()));
// Send new if waiting
dataSyncSelector.processChangedGlucoseValuesCompat();
return;
}
if (ack.getOriginalObject() instanceof DataSyncSelector.PairFood) {
DataSyncSelector.PairFood pair = (DataSyncSelector.PairFood) ack.getOriginalObject();
dataSyncSelector.confirmLastFoodIdIfGreater(pair.getUpdateRecordId());
rxBus.send(new EventNSClientNewLog("DBUPDATE/DBREMOVE", "Acked Food " + ack.get_id()));
// Send new if waiting
dataSyncSelector.processChangedFoodsCompat();
return;
}
if (ack.getOriginalObject() instanceof DataSyncSelector.PairTherapyEvent) {
DataSyncSelector.PairTherapyEvent pair = (DataSyncSelector.PairTherapyEvent) ack.getOriginalObject();
dataSyncSelector.confirmLastTherapyEventIdIfGreater(pair.getUpdateRecordId());
rxBus.send(new EventNSClientNewLog("DBUPDATE/DBREMOVE", "Acked TherapyEvent " + ack.get_id()));
// Send new if waiting
dataSyncSelector.processChangedTherapyEventsCompat();
return;
}
if (ack.getOriginalObject() instanceof DataSyncSelector.PairBolus) {
DataSyncSelector.PairBolus pair = (DataSyncSelector.PairBolus) ack.getOriginalObject();
dataSyncSelector.confirmLastBolusIdIfGreater(pair.getUpdateRecordId());
rxBus.send(new EventNSClientNewLog("DBUPDATE/DBREMOVE", "Acked Bolus " + ack.get_id()));
// Send new if waiting
dataSyncSelector.processChangedBolusesCompat();
return;
}
if (ack.getOriginalObject() instanceof DataSyncSelector.PairCarbs) {
DataSyncSelector.PairCarbs pair = (DataSyncSelector.PairCarbs) ack.getOriginalObject();
dataSyncSelector.confirmLastCarbsIdIfGreater(pair.getUpdateRecordId());
rxBus.send(new EventNSClientNewLog("DBUPDATE/DBREMOVE", "Acked Carbs " + ack.get_id()));
// Send new if waiting
dataSyncSelector.processChangedCarbsCompat();
return;
}
if (ack.getOriginalObject() instanceof DataSyncSelector.PairBolusCalculatorResult) {
DataSyncSelector.PairBolusCalculatorResult pair = (DataSyncSelector.PairBolusCalculatorResult) ack.getOriginalObject();
dataSyncSelector.confirmLastBolusCalculatorResultsIdIfGreater(pair.getUpdateRecordId());
rxBus.send(new EventNSClientNewLog("DBUPDATE/DBREMOVE", "Acked BolusCalculatorResult " + ack.get_id()));
// Send new if waiting
dataSyncSelector.processChangedBolusCalculatorResultsCompat();
return;
}
// old way
if (ack.getResult()) {
uploadQueue.removeByMongoId(ack.getAction(), ack.get_id());
@ -767,7 +893,7 @@ public class NSClientService extends DaggerService {
message.put("_id", _id);
message.put("data", data);
mSocket.emit("dbUpdate", message, new NSUpdateAck("dbUpdate", _id, aapsLogger, rxBus, originalObject));
rxBus.send(new EventNSClientNewLog("DBUPDATE " + collection, "Sent " + _id));
rxBus.send(new EventNSClientNewLog("DBUPDATE " + collection, "Sent " + originalObject.getClass().getSimpleName() + " " + _id));
} catch (JSONException e) {
aapsLogger.error("Unhandled exception", e);
}
@ -793,7 +919,7 @@ public class NSClientService extends DaggerService {
message.put("collection", collection);
message.put("_id", _id);
mSocket.emit("dbRemove", message, new NSUpdateAck("dbRemove", _id, aapsLogger, rxBus, originalObject));
rxBus.send(new EventNSClientNewLog("DBREMOVE " + collection, "Sent " + _id));
rxBus.send(new EventNSClientNewLog("DBREMOVE " + collection, "Sent " + originalObject.getClass().getSimpleName() + " " + _id));
} catch (JSONException e) {
aapsLogger.error("Unhandled exception", e);
}
@ -819,7 +945,7 @@ public class NSClientService extends DaggerService {
message.put("collection", collection);
message.put("data", data);
mSocket.emit("dbAdd", message, new NSAddAck(aapsLogger, rxBus, originalObject));
rxBus.send(new EventNSClientNewLog("DBADD " + collection, "Sent " + data));
rxBus.send(new EventNSClientNewLog("DBADD " + collection, "Sent " + originalObject.getClass().getSimpleName() + " " + data));
} catch (JSONException e) {
aapsLogger.error("Unhandled exception", e);
}
@ -843,8 +969,14 @@ public class NSClientService extends DaggerService {
aapsLogger.debug(LTag.NSCLIENT, "Skipping resend by lastAckTime: " + ((System.currentTimeMillis() - lastAckTime) / 1000L) + " sec");
return;
}
if (dataSyncSelector.processChangedGlucoseValuesCompat()) return;
if (dataSyncSelector.processChangedTempTargetsCompat()) return;
dataSyncSelector.processChangedBolusesCompat();
dataSyncSelector.processChangedCarbsCompat();
dataSyncSelector.processChangedBolusCalculatorResultsCompat();
dataSyncSelector.processChangedGlucoseValuesCompat();
dataSyncSelector.processChangedTempTargetsCompat();
dataSyncSelector.processChangedFoodsCompat();
dataSyncSelector.processChangedTherapyEventsCompat();
if (uploadQueue.size() == 0)
return;

View file

@ -85,7 +85,6 @@ class DexcomPlugin @Inject constructor(
@Inject lateinit var aapsLogger: AAPSLogger
@Inject lateinit var injector: HasAndroidInjector
@Inject lateinit var dexcomPlugin: DexcomPlugin
@Inject lateinit var nsUpload: NSUpload
@Inject lateinit var sp: SP
@Inject lateinit var dataWorker: DataWorker
@Inject lateinit var broadcastToXDrip: XDripBroadcast
@ -157,18 +156,8 @@ class DexcomPlugin @Inject constructor(
broadcastToXDrip(it)
aapsLogger.debug(LTag.DATABASE, "Updated bg $it")
}
result.sensorInsertionsInserted.forEach {
if (sp.getBoolean(R.string.key_dexcomg5_nsupload, false)) {
nsUpload.uploadEvent(it)
}
aapsLogger.debug(LTag.DATABASE, "Inserted sensor insertion $it")
}
result.calibrationsInserted.forEach {
if (sp.getBoolean(R.string.key_dexcomg5_nsupload, false)) {
nsUpload.uploadEvent(it)
}
aapsLogger.debug(LTag.DATABASE, "Inserted calibration $it")
}
result.sensorInsertionsInserted.forEach { aapsLogger.debug(LTag.DATABASE, "Inserted sensor insertion $it") }
result.calibrationsInserted.forEach { aapsLogger.debug(LTag.DATABASE, "Inserted calibration $it") }
}
} catch (e: Exception) {
aapsLogger.error("Error while processing intent from Dexcom App", e)

View file

@ -16,7 +16,6 @@ import info.nightscout.androidaps.interfaces.PluginDescription
import info.nightscout.androidaps.interfaces.PluginType
import info.nightscout.androidaps.logging.AAPSLogger
import info.nightscout.androidaps.logging.LTag
import info.nightscout.androidaps.plugins.general.nsclient.NSUpload
import info.nightscout.androidaps.receivers.DataWorker
import info.nightscout.androidaps.utils.DateUtil
import info.nightscout.androidaps.utils.XDripBroadcast
@ -58,7 +57,6 @@ class EversensePlugin @Inject constructor(
@Inject lateinit var eversensePlugin: EversensePlugin
@Inject lateinit var aapsLogger: AAPSLogger
@Inject lateinit var dateUtil: DateUtil
@Inject lateinit var nsUpload: NSUpload
@Inject lateinit var dataWorker: DataWorker
@Inject lateinit var repository: AppRepository
@Inject lateinit var broadcastToXDrip: XDripBroadcast
@ -147,10 +145,7 @@ class EversensePlugin @Inject constructor(
}
.blockingGet()
.also { result ->
result.inserted.forEach {
nsUpload.uploadEvent(it)
aapsLogger.debug(LTag.DATABASE, "Inserted therapy event $it")
}
result.inserted.forEach { aapsLogger.debug(LTag.DATABASE, "Inserted therapy event $it") }
}
}
}

View file

@ -114,7 +114,7 @@ class NSClientSourcePlugin @Inject constructor(
override fun doWork(): Result {
var ret = Result.success()
if (!nsClientSourcePlugin.isEnabled() && !sp.getBoolean(R.string.key_ns_autobackfill, true) && !dexcomPlugin.isEnabled()) return Result.failure()
if (!nsClientSourcePlugin.isEnabled() && !sp.getBoolean(R.string.key_ns_autobackfill, true) && !dexcomPlugin.isEnabled()) return Result.success()
val sgvs = dataWorker.pickupJSONArray(inputData.getLong(DataWorker.STORE_KEY, -1))
?: return Result.failure()

View file

@ -14,7 +14,6 @@ import info.nightscout.androidaps.data.DetailedBolusInfo
import info.nightscout.androidaps.data.Profile
import info.nightscout.androidaps.data.PumpEnactResult
import info.nightscout.androidaps.database.AppRepository
import info.nightscout.androidaps.database.entities.UserEntry
import info.nightscout.androidaps.dialogs.BolusProgressDialog
import info.nightscout.androidaps.events.EventBolusRequested
import info.nightscout.androidaps.events.EventNewBasalProfile
@ -25,7 +24,6 @@ import info.nightscout.androidaps.interfaces.Constraint
import info.nightscout.androidaps.interfaces.ProfileFunction
import info.nightscout.androidaps.logging.AAPSLogger
import info.nightscout.androidaps.logging.LTag
import info.nightscout.androidaps.logging.UserEntryLogger
import info.nightscout.androidaps.plugins.bus.RxBusWrapper
import info.nightscout.androidaps.plugins.configBuilder.ConstraintChecker
import info.nightscout.androidaps.plugins.general.nsclient.NSUpload
@ -206,14 +204,10 @@ open class CommandQueue @Inject constructor(
|| detailedBolusInfo.carbsTimestamp ?: detailedBolusInfo.timestamp > dateUtil._now()
) {
disposable += repository.runTransactionForResult(detailedBolusInfo.insertCarbsTransaction())
.subscribe({ result ->
result.inserted.forEach {
aapsLogger.debug(LTag.DATABASE, "Inserted carbs $it")
nsUpload.uploadCarbsRecord(it, detailedBolusInfo.createTherapyEvent())
}
}, {
aapsLogger.error(LTag.DATABASE, "Error while saving carbs", it)
})
.subscribe(
{ result -> result.inserted.forEach { aapsLogger.debug(LTag.DATABASE, "Inserted carbs $it") } },
{ aapsLogger.error(LTag.DATABASE, "Error while saving carbs", it) }
)
// Do not process carbs anymore
detailedBolusInfo.carbs = 0.0
// if no insulin just exit

View file

@ -2,11 +2,14 @@ package info.nightscout.androidaps.utils
import android.content.Context
import info.nightscout.androidaps.R
import info.nightscout.androidaps.database.AppRepository
import info.nightscout.androidaps.database.transactions.InsertTherapyEventAnnouncementTransaction
import info.nightscout.androidaps.logging.AAPSLogger
import info.nightscout.androidaps.plugins.bus.RxBusWrapper
import info.nightscout.androidaps.plugins.general.nsclient.NSUpload
import info.nightscout.androidaps.utils.resources.ResourceHelper
import info.nightscout.androidaps.utils.sharedPreferences.SP
import io.reactivex.disposables.CompositeDisposable
import io.reactivex.rxkotlin.plusAssign
import javax.inject.Inject
import javax.inject.Singleton
import kotlin.math.max
@ -19,9 +22,11 @@ class HardLimits @Inject constructor(
private val sp: SP,
private val resourceHelper: ResourceHelper,
private val context: Context,
private val nsUpload: NSUpload
private val repository: AppRepository
) {
private val disposable = CompositeDisposable()
companion object {
private const val CHILD = 0
@ -88,7 +93,7 @@ class HardLimits @Inject constructor(
msg += ".\n"
msg += String.format(resourceHelper.gs(R.string.valuelimitedto), value, newValue)
aapsLogger.error(msg)
nsUpload.uploadError(msg)
disposable += repository.runTransaction(InsertTherapyEventAnnouncementTransaction(msg)).subscribe()
ToastUtils.showToastInUiThread(context, rxBus, msg, R.raw.error)
}
return newValue

View file

@ -3,12 +3,13 @@ package info.nightscout.androidaps.utils
import info.nightscout.androidaps.Config
import info.nightscout.androidaps.Constants
import info.nightscout.androidaps.R
import info.nightscout.androidaps.database.AppRepository
import info.nightscout.androidaps.database.transactions.InsertTherapyEventAnnouncementTransaction
import info.nightscout.androidaps.interfaces.ActivePluginProvider
import info.nightscout.androidaps.interfaces.ProfileFunction
import info.nightscout.androidaps.logging.AAPSLogger
import info.nightscout.androidaps.logging.LTag
import info.nightscout.androidaps.plugins.bus.RxBusWrapper
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
import info.nightscout.androidaps.plugins.general.overview.notifications.Notification
@ -16,6 +17,8 @@ import info.nightscout.androidaps.plugins.general.smsCommunicator.SmsCommunicato
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.IobCobCalculatorPlugin
import info.nightscout.androidaps.utils.resources.ResourceHelper
import info.nightscout.androidaps.utils.sharedPreferences.SP
import io.reactivex.disposables.CompositeDisposable
import io.reactivex.rxkotlin.plusAssign
import javax.inject.Inject
import javax.inject.Singleton
import kotlin.math.min
@ -34,10 +37,12 @@ class LocalAlertUtils @Inject constructor(
private val iobCobCalculatorPlugin: IobCobCalculatorPlugin,
private val smsCommunicatorPlugin: SmsCommunicatorPlugin,
private val config: Config,
private val nsUpload: NSUpload,
private val repository: AppRepository,
private val dateUtil: DateUtil
) {
private val disposable = CompositeDisposable()
private fun missedReadingsThreshold(): Long {
return T.mins(sp.getInt(R.string.key_missed_bg_readings_threshold_minutes, Constants.DEFAULT_MISSED_BG_READINGS_THRESHOLD_MINUTES).toLong()).msecs()
}
@ -55,7 +60,7 @@ class LocalAlertUtils @Inject constructor(
sp.putLong("nextPumpDisconnectedAlarm", System.currentTimeMillis() + pumpUnreachableThreshold())
rxBus.send(EventNewNotification(Notification(Notification.PUMP_UNREACHABLE, resourceHelper.gs(R.string.pump_unreachable), Notification.URGENT).also { it.soundId = R.raw.alarm }))
if (sp.getBoolean(R.string.key_ns_create_announcements_from_errors, true))
nsUpload.uploadError(resourceHelper.gs(R.string.pump_unreachable))
disposable += repository.runTransaction(InsertTherapyEventAnnouncementTransaction(resourceHelper.gs(R.string.pump_unreachable))).subscribe()
}
if (sp.getBoolean(R.string.key_smscommunicator_report_pump_ureachable, true))
smsCommunicatorPlugin.sendNotificationToAllNumbers(resourceHelper.gs(R.string.pump_unreachable))
@ -113,7 +118,7 @@ class LocalAlertUtils @Inject constructor(
sp.putLong("nextMissedReadingsAlarm", System.currentTimeMillis() + missedReadingsThreshold())
rxBus.send(EventNewNotification(n))
if (sp.getBoolean(R.string.key_ns_create_announcements_from_errors, true)) {
nsUpload.uploadError(n.text)
n.text?.let { disposable += repository.runTransaction(InsertTherapyEventAnnouncementTransaction(it)).subscribe() }
}
}
}

View file

@ -425,14 +425,10 @@ class BolusWizard @Inject constructor(
})
}
disposable += repository.runTransactionForResult(InsertOrUpdateBolusCalculatorResultTransaction(bolusCalculatorResult!!))
.subscribe({ result ->
result.inserted.forEach { inserted ->
aapsLogger.debug(LTag.DATABASE, "Inserted bolusCalculatorResult $inserted")
nsUpload.uploadBolusCalc(this)
}
}, {
aapsLogger.error(LTag.DATABASE, "Error while saving meal link", it)
})
.subscribe(
{ result -> result.inserted.forEach { inserted -> aapsLogger.debug(LTag.DATABASE, "Inserted bolusCalculatorResult $inserted") } },
{ aapsLogger.error(LTag.DATABASE, "Error while saving bolusCalculatorResult", it) }
)
}
if (useAlarm && carbs > 0 && carbTime > 0) {

View file

@ -33,8 +33,16 @@
<string name="key_protection_settings" translatable="false">protection</string>
<string name="key_absorption_category_settings" translatable="false">absorption_category_settings</string>
<string name="key_insulin_oref_peak_settings" translatable="false">insulin_oref_peak_settings</string>
<string name="key_ns_temporary_target_last_sync" translatable="false">ns_temporary_target_last_sync</string>
<string name="key_ns_glucose_value_last_sync" translatable="false">ns_glucose_value_last_sync</string>
<string name="key_ns_temporary_target_last_synced_id" translatable="false">ns_temporary_target_last_sync</string>
<string name="key_ns_glucose_value_last_synced_id" translatable="false">ns_glucose_value_last_sync</string>
<string name="key_ns_food_last_synced_id" translatable="false">ns_food_last_sync</string>
<string name="key_ns_therapy_event_last_synced_id" translatable="false">ns_therapy_event_last_sync</string>
<string name="key_smscommunicator_remotebolusmindistance" translatable="false">smscommunicator_remotebolusmindistance</string>
<string name="key_openapsama_bolussnooze_dia_divisor" translatable="false">bolussnooze_dia_divisor</string>
<string name="key_openapsama_autosens_adjusttargets" translatable="false">autosens_adjust_targets</string>
<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="treatmentssafety_title">Treatments safety</string>
<string name="treatmentssafety_maxbolus_title">Max allowed bolus [U]</string>
@ -228,7 +236,6 @@
<string name="smscommunicator_stoppedsms">SMS Remote Service stopped. To reactivate it, use AAPS on master smartphone.</string>
<string name="smscommunicator_calibrationreplywithcode">To send calibration %1$.2f reply with code %2$s</string>
<string name="smscommunicator_bolusfailed">Bolus failed</string>
<string name="key_smscommunicator_remotebolusmindistance" translatable="false">smscommunicator_remotebolusmindistance</string>
<string name="smscommunicator_remotebolusmindistance_summary">Minimum number of minutes that must elapse between one remote bolus and the next</string>
<string name="smscommunicator_remotebolusmindistance">How many minutes must elapse, at least, between one bolus and the next</string>
<string name="smscommunicator_remotebolusmindistance_caveat">For your safety, to edit this preference you need to add at least 2 phone numbers.</string>
@ -341,10 +348,8 @@
<string name="openapsama_current_basal_safety_multiplier_summary">Default value: 4 This is the other half of the key OpenAPS safety caps, and the other half of “3x max daily; 4x current” of the safety caps. This means your basal, regardless of max basal set on your pump, cannot be any higher than this number times the current level of your basal. This is to prevent people from getting into dangerous territory by setting excessively high max basals before understanding how the algorithm works. Again, the default is 4x; most people will never need to adjust this and are instead more likely to need to adjust other settings if they feel like they are “running into” this safety cap.</string>
<string name="openapsama_autosens_max_summary">Default value: 1.2\nThis is a multiplier cap for autosens (and soon autotune) to set a 20%% max limit on how high the autosens ratio can be, which in turn determines how high autosens can adjust basals, how low it can adjust ISF, and how low it can set the BG target.</string>
<string name="openapsama_autosens_min_summary">Default value: 0.7\nThe other side of the autosens safety limits, putting a cap on how low autosens can adjust basals, and how high it can adjust ISF and BG targets.</string>
<string name="key_openapsama_autosens_adjusttargets" translatable="false">autosens_adjust_targets</string>
<string name="openapsama_autosens_adjusttargets">Autosens adjust targets, too</string>
<string name="openapsama_autosens_adjusttargets_summary">Default value: true\nThis is used to allow autosens to adjust BG targets, in addition to ISF and basals.</string>
<string name="key_openapsama_bolussnooze_dia_divisor" translatable="false">bolussnooze_dia_divisor</string>
<string name="openapsama_bolussnooze_dia_divisor_summary">Default value: 2\nBolus snooze is enacted after you do a meal bolus, so the loop wont counteract with low temps when youve just eaten. The example here and default is 2; so a 3 hour DIA means that bolus snooze will be gradually phased out over 1.5 hours (3DIA/2).</string>
<string name="openapsama_min_5m_carbimpact" translatable="false">min_5m_carbimpact</string>
<string name="openapsama_min_5m_carbimpact_summary">Default value: 3.0 (AMA) or 8.0 (SMB). This is a setting for default carb absorption impact per 5 minutes. The default is an expected 3mg/dl/5min. This affects how fast COB are decayed, and how much carb absorption is assumed in calculating future predicted BG, when BG is falling more than expected, or not rising as much as expected.</string>
@ -1130,5 +1135,4 @@
<string name="profile_carbs_ratio_value">Profile carbs ratio value</string>
<string name="full_sync">Full sync</string>
</resources>

View file

@ -5,17 +5,20 @@ import androidx.annotation.DrawableRes
import dagger.android.HasAndroidInjector
import info.nightscout.androidaps.automation.R
import info.nightscout.androidaps.data.PumpEnactResult
import info.nightscout.androidaps.database.AppRepository
import info.nightscout.androidaps.database.transactions.InsertTherapyEventAnnouncementTransaction
import info.nightscout.androidaps.events.EventRefreshOverview
import info.nightscout.androidaps.plugins.bus.RxBusWrapper
import info.nightscout.androidaps.plugins.general.automation.elements.InputString
import info.nightscout.androidaps.plugins.general.automation.elements.LabelWithElement
import info.nightscout.androidaps.plugins.general.automation.elements.LayoutBuilder
import info.nightscout.androidaps.plugins.general.nsclient.NSUpload
import info.nightscout.androidaps.plugins.general.overview.events.EventNewNotification
import info.nightscout.androidaps.plugins.general.overview.notifications.NotificationUserMessage
import info.nightscout.androidaps.queue.Callback
import info.nightscout.androidaps.utils.JsonHelper
import info.nightscout.androidaps.utils.resources.ResourceHelper
import io.reactivex.disposables.CompositeDisposable
import io.reactivex.rxkotlin.plusAssign
import org.json.JSONObject
import javax.inject.Inject
@ -23,7 +26,9 @@ class ActionNotification(injector: HasAndroidInjector) : Action(injector) {
@Inject lateinit var resourceHelper: ResourceHelper
@Inject lateinit var rxBus: RxBusWrapper
@Inject lateinit var nsUpload: NSUpload
@Inject lateinit var repository: AppRepository
private val disposable = CompositeDisposable()
var text = InputString()
@ -34,7 +39,7 @@ class ActionNotification(injector: HasAndroidInjector) : Action(injector) {
override fun doAction(callback: Callback) {
val notification = NotificationUserMessage(text.value)
rxBus.send(EventNewNotification(notification))
nsUpload.uploadError(text.value)
disposable += repository.runTransaction(InsertTherapyEventAnnouncementTransaction(text.value)).subscribe()
rxBus.send(EventRefreshOverview("ActionNotification"))
callback.result(PumpEnactResult(injector).success(true).comment(R.string.ok))?.run()
}

View file

@ -5,6 +5,8 @@ import dagger.android.HasAndroidInjector
import info.nightscout.androidaps.TestBase
import info.nightscout.androidaps.automation.R
import info.nightscout.androidaps.data.PumpEnactResult
import info.nightscout.androidaps.database.AppRepository
import info.nightscout.androidaps.database.transactions.InsertTherapyEventAnnouncementTransaction
import info.nightscout.androidaps.plugins.bus.RxBusWrapper
import info.nightscout.androidaps.plugins.general.automation.elements.InputString
import info.nightscout.androidaps.plugins.general.nsclient.NSUpload
@ -27,7 +29,7 @@ class ActionNotificationTest : TestBase() {
@Mock lateinit var resourceHelper: ResourceHelper
@Mock lateinit var rxBus: RxBusWrapper
@Mock lateinit var nsUpload: NSUpload
@Mock lateinit var repository: AppRepository
private lateinit var sut: ActionNotification
var injector: HasAndroidInjector = HasAndroidInjector {
@ -35,7 +37,6 @@ class ActionNotificationTest : TestBase() {
if (it is ActionNotification) {
it.resourceHelper = resourceHelper
it.rxBus = rxBus
it.nsUpload = nsUpload
}
if (it is PumpEnactResult) {
it.resourceHelper = resourceHelper
@ -72,7 +73,7 @@ class ActionNotificationTest : TestBase() {
}
})
Mockito.verify(rxBus, Mockito.times(2)).send(anyObject())
Mockito.verify(nsUpload, Mockito.times(1)).uploadError(anyObject())
Mockito.verify(repository, Mockito.times(1)).runTransaction(anyObject() as InsertTherapyEventAnnouncementTransaction)
}
@Test fun hasDialogTest() {

View file

@ -5,14 +5,20 @@ import android.content.Intent
import android.os.Bundle
import androidx.annotation.RawRes
import info.nightscout.androidaps.core.R
import info.nightscout.androidaps.database.AppRepository
import info.nightscout.androidaps.database.transactions.InsertTherapyEventAnnouncementTransaction
import info.nightscout.androidaps.dialogs.ErrorDialog
import info.nightscout.androidaps.plugins.general.nsclient.NSUpload
import info.nightscout.androidaps.utils.sharedPreferences.SP
import io.reactivex.disposables.CompositeDisposable
import io.reactivex.rxkotlin.plusAssign
import javax.inject.Inject
class ErrorHelperActivity : DialogAppCompatActivity() {
@Inject lateinit var sp : SP
@Inject lateinit var nsUpload: NSUpload
@Inject lateinit var sp: SP
@Inject lateinit var repository: AppRepository
private val disposable = CompositeDisposable()
@Override
override fun onCreate(savedInstanceState: Bundle?) {
@ -24,17 +30,17 @@ class ErrorHelperActivity : DialogAppCompatActivity() {
errorDialog.title = intent.getStringExtra(TITLE)
errorDialog.show(supportFragmentManager, "Error")
if (sp.getBoolean(R.string.key_ns_create_announcements_from_errors, true)) {
nsUpload.uploadError(intent.getStringExtra(STATUS))
}
if (sp.getBoolean(R.string.key_ns_create_announcements_from_errors, true))
disposable += repository.runTransaction(InsertTherapyEventAnnouncementTransaction(intent.getStringExtra(STATUS))).subscribe()
}
companion object {
const val SOUND_ID = "soundId"
const val STATUS = "status"
const val TITLE = "title"
fun runAlarm(ctx: Context, status: String, title : String, @RawRes soundId: Int = 0) {
fun runAlarm(ctx: Context, status: String, title: String, @RawRes soundId: Int = 0) {
val i = Intent(ctx, ErrorHelperActivity::class.java)
i.putExtra(SOUND_ID, soundId)
i.putExtra(STATUS, status)

View file

@ -1,24 +1,51 @@
package info.nightscout.androidaps.interfaces
import info.nightscout.androidaps.database.entities.GlucoseValue
import info.nightscout.androidaps.database.entities.TemporaryTarget
import info.nightscout.androidaps.database.entities.*
interface DataSyncSelector {
data class PairTemporaryTarget(val value: TemporaryTarget, val updateRecordId: Long)
data class PairGlucoseValue(val value: GlucoseValue, val updateRecordId: Long)
data class PairTherapyEvent(val value: TherapyEvent, val updateRecordId: Long)
data class PairFood(val value: Food, val updateRecordId: Long)
data class PairBolus(val value: Bolus, val updateRecordId: Long)
data class PairCarbs(val value: Carbs, val updateRecordId: Long)
data class PairBolusCalculatorResult(val value: BolusCalculatorResult, val updateRecordId: Long)
fun resetToNextFullSync()
fun confirmTempTargetsTimestamp(lastSynced: Long)
fun confirmTempTargetsTimestampIfGreater(lastSynced: Long)
fun confirmLastBolusIdIfGreater(lastSynced: Long)
fun changedBoluses() : List<Bolus>
// Until NS v3
fun processChangedBolusesCompat(): Boolean
fun confirmLastCarbsIdIfGreater(lastSynced: Long)
fun changedCarbs() : List<Carbs>
// Until NS v3
fun processChangedCarbsCompat(): Boolean
fun confirmLastBolusCalculatorResultsIdIfGreater(lastSynced: Long)
fun changedBolusCalculatorResults() : List<BolusCalculatorResult>
// Until NS v3
fun processChangedBolusCalculatorResultsCompat(): Boolean
fun confirmLastTempTargetsIdIfGreater(lastSynced: Long)
fun changedTempTargets() : List<TemporaryTarget>
// Until NS v3
fun processChangedTempTargetsCompat(): Boolean
fun confirmLastGlucoseValueId(lastSynced: Long)
fun confirmLastGlucoseValueIdIfGreater(lastSynced: Long)
fun changedGlucoseValues() : List<GlucoseValue>
// Until NS v3
fun processChangedGlucoseValuesCompat(): Boolean
fun confirmLastTherapyEventIdIfGreater(lastSynced: Long)
fun changedTherapyEvents() : List<TherapyEvent>
// Until NS v3
fun processChangedTherapyEventsCompat(): Boolean
fun confirmLastFoodIdIfGreater(lastSynced: Long)
fun changedFoods() : List<Food>
// Until NS v3
fun processChangedFoodsCompat(): Boolean
}

View file

@ -23,8 +23,6 @@ import info.nightscout.androidaps.data.Profile;
import info.nightscout.androidaps.database.entities.Bolus;
import info.nightscout.androidaps.database.entities.BolusCalculatorResult;
import info.nightscout.androidaps.database.entities.Carbs;
import info.nightscout.androidaps.database.entities.GlucoseValue;
import info.nightscout.androidaps.database.entities.TemporaryTarget;
import info.nightscout.androidaps.database.entities.TherapyEvent;
import info.nightscout.androidaps.db.DbRequest;
import info.nightscout.androidaps.db.ExtendedBolus;
@ -33,7 +31,6 @@ import info.nightscout.androidaps.db.TemporaryBasal;
import info.nightscout.androidaps.interfaces.IobCobCalculatorInterface;
import info.nightscout.androidaps.interfaces.LoopInterface;
import info.nightscout.androidaps.interfaces.ProfileFunction;
import info.nightscout.androidaps.interfaces.ProfileStore;
import info.nightscout.androidaps.interfaces.PumpInterface;
import info.nightscout.androidaps.interfaces.UploadQueueInterface;
import info.nightscout.androidaps.logging.AAPSLogger;
@ -43,9 +40,6 @@ 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.JsonHelper;
import info.nightscout.androidaps.utils.T;
import info.nightscout.androidaps.utils.resources.ResourceHelper;
import info.nightscout.androidaps.utils.sharedPreferences.SP;
/**
@ -55,29 +49,21 @@ import info.nightscout.androidaps.utils.sharedPreferences.SP;
public class NSUpload {
private final AAPSLogger aapsLogger;
private final ResourceHelper resourceHelper;
private final SP sp;
private final UploadQueueInterface uploadQueue;
private final RunningConfiguration runningConfiguration;
private final ProfileFunction profileFunction;
public static String ISVALID = "isValid";
@Inject
public NSUpload(
AAPSLogger aapsLogger,
ResourceHelper resourceHelper,
SP sp,
UploadQueueInterface uploadQueue,
RunningConfiguration runningConfiguration,
ProfileFunction profileFunction
RunningConfiguration runningConfiguration
) {
this.aapsLogger = aapsLogger;
this.resourceHelper = resourceHelper;
this.sp = sp;
this.uploadQueue = uploadQueue;
this.runningConfiguration = runningConfiguration;
this.profileFunction = profileFunction;
}
public void uploadTempBasalStartAbsolute(TemporaryBasal temporaryBasal, Double originalExtendedAmount) {
@ -281,79 +267,12 @@ public class NSUpload {
*/
}
public void uploadCarbsRecord(@NonNull Carbs carbs, @NonNull TherapyEvent therapyEvent) {
try {
JSONObject data = new JSONObject();
data.put("eventType", therapyEvent.getType().getText());
data.put("carbs", carbs.getAmount());
data.put("created_at", DateUtil.toISOString(carbs.getTimestamp()));
data.put("date", carbs.getTimestamp());
if (carbs.getDuration() != 0)
data.put("duration", carbs.getDuration());
if (carbs.getInterfaceIDs().getPumpId() != null)
data.put("pumpId", carbs.getInterfaceIDs().getPumpId());
if (therapyEvent.getGlucose() != null)
data.put("glucose", therapyEvent.getGlucose());
if (therapyEvent.getGlucoseType() != null)
data.put("glucoseType", therapyEvent.getGlucoseType().getText());
if (therapyEvent.getNote() != null)
data.put("notes", therapyEvent.getNote());
uploadCareportalEntryToNS(data, carbs.getTimestamp());
} catch (JSONException e) {
e.printStackTrace();
}
}
public void uploadBolusRecord(@NonNull Bolus bolus, @NonNull TherapyEvent therapyEvent, @Nullable BolusCalculatorResult bolusCalculatorResult) {
try {
JSONObject data = new JSONObject();
data.put("eventType", therapyEvent.getType().getText());
data.put("insulin", bolus.getAmount());
data.put("created_at", DateUtil.toISOString(bolus.getTimestamp()));
data.put("date", bolus.getTimestamp());
data.put("isSMB", bolus.getType() == Bolus.Type.SMB);
if (bolus.getInterfaceIDs().getPumpId() != null)
data.put("pumpId", bolus.getInterfaceIDs().getPumpId());
if (therapyEvent.getGlucose() != null)
data.put("glucose", therapyEvent.getGlucose());
if (therapyEvent.getGlucoseType() != null)
data.put("glucoseType", therapyEvent.getGlucoseType().getText());
if (bolusCalculatorResult != null)
data.put("bolusCalculatorResult", new Gson().toJson(bolusCalculatorResult));
if (therapyEvent.getNote() != null)
data.put("notes", therapyEvent.getNote());
uploadCareportalEntryToNS(data, bolus.getTimestamp());
} catch (JSONException e) {
e.printStackTrace();
}
}
public void uploadBolusCalc(@NonNull DetailedBolusInfo detailedBolusInfo) {
try {
JSONObject data = new JSONObject();
data.put("eventType", detailedBolusInfo.getEventType().toDBbEventType().getText());
data.put("created_at", DateUtil.toISOString(detailedBolusInfo.timestamp));
data.put("date", detailedBolusInfo.timestamp);
if (detailedBolusInfo.getMgdlGlucose() != null) {
data.put("glucose", detailedBolusInfo.getMgdlGlucose());
data.put("units", Constants.MGDL);
}
if (detailedBolusInfo.getGlucoseType() != null)
data.put("glucoseType", detailedBolusInfo.getGlucoseType().getText());
if (detailedBolusInfo.getBolusCalculatorResult() != null)
data.put("bolusCalculatorResult", new Gson().toJson(detailedBolusInfo.getBolusCalculatorResult()));
if (detailedBolusInfo.getNotes() != null)
data.put("notes", detailedBolusInfo.getNotes());
uploadCareportalEntryToNS(data, detailedBolusInfo.timestamp);
} catch (JSONException e) {
e.printStackTrace();
}
}
public void uploadProfileSwitch(ProfileSwitch profileSwitch, long nsClientId) {
try {
JSONObject data = getJson(profileSwitch);
uploadCareportalEntryToNS(data, nsClientId);
DbRequest dbr = new DbRequest("dbAdd", "treatments", data, nsClientId);
aapsLogger.debug("Prepared: " + dbr.log());
uploadQueue.add(dbr);
} catch (JSONException e) {
aapsLogger.error("Unhandled exception", e);
}
@ -388,133 +307,17 @@ public class NSUpload {
return data;
}
public void uploadCareportalEntryToNS(JSONObject data, long nsClientId) {
try {
if (data.has("preBolus") && data.has("carbs")) {
JSONObject prebolus = new JSONObject();
prebolus.put("carbs", data.get("carbs"));
data.remove("carbs");
prebolus.put("eventType", data.get("eventType"));
if (data.has("enteredBy")) prebolus.put("enteredBy", data.get("enteredBy"));
if (data.has("notes")) prebolus.put("notes", data.get("notes"));
long mills = DateUtil.fromISODateString(data.getString("created_at")).getTime();
Date preBolusDate = new Date(mills + data.getInt("preBolus") * 60000L + 1000L);
prebolus.put("created_at", DateUtil.toISOString(preBolusDate));
uploadCareportalEntryToNS(prebolus, preBolusDate.getTime());
}
DbRequest dbr = new DbRequest("dbAdd", "treatments", data, nsClientId);
aapsLogger.debug("Prepared: " + dbr.log());
uploadQueue.add(dbr);
} catch (Exception e) {
aapsLogger.error("Unhandled exception", e);
}
}
// TODO replace with seting isValid = false
// TODO replace with setting isValid = false
public void removeCareportalEntryFromNS(String _id) {
uploadQueue.add(new DbRequest("dbRemove", "treatments", _id, System.currentTimeMillis()));
}
public void uploadError(String error) {
uploadError(error, new Date());
}
public void uploadError(String error, Date date) {
JSONObject data = new JSONObject();
try {
data.put("eventType", "Announcement");
data.put("created_at", DateUtil.toISOString(date));
data.put("enteredBy", sp.getString("careportal_enteredby", "AndroidAPS"));
data.put("notes", error);
data.put("isAnnouncement", true);
} catch (JSONException e) {
aapsLogger.error("Unhandled exception", e);
}
uploadQueue.add(new DbRequest("dbAdd", "treatments", data, date.getTime()));
}
public void uploadAppStart() {
if (sp.getBoolean(R.string.key_ns_logappstartedevent, true)) {
JSONObject data = new JSONObject();
try {
data.put("eventType", "Note");
data.put("created_at", DateUtil.toISOString(new Date()));
data.put("notes", resourceHelper.gs(R.string.androidaps_start) + " - " + Build.MANUFACTURER + " " + Build.MODEL);
} catch (JSONException e) {
aapsLogger.error("Unhandled exception", e);
}
uploadQueue.add(new DbRequest("dbAdd", "treatments", data, System.currentTimeMillis()));
}
}
public void uploadProfileStore(JSONObject profileStore) {
if (sp.getBoolean(R.string.key_ns_uploadlocalprofile, false)) {
uploadQueue.add(new DbRequest("dbAdd", "profile", profileStore, System.currentTimeMillis()));
}
}
public void uploadEvent(String careportalEvent, long time, @Nullable String notes) {
JSONObject data = new JSONObject();
try {
data.put("eventType", careportalEvent);
data.put("created_at", DateUtil.toISOString(time));
data.put("enteredBy", sp.getString("careportal_enteredby", "AndroidAPS"));
data.put("units", profileFunction.getUnits());
if (notes != null) {
data.put("notes", notes);
}
} catch (JSONException e) {
aapsLogger.error("Unhandled exception", e);
}
uploadQueue.add(new DbRequest("dbAdd", "treatments", data, time));
}
public void uploadEvent(TherapyEvent event) {
JSONObject data = new JSONObject();
try {
data.put("eventType", event.getType().getText());
data.put("created_at", event.getTimestamp());
data.put("enteredBy", event.getEnteredBy());
if (event.getGlucoseUnit() == TherapyEvent.GlucoseUnit.MGDL)
data.put("units", Constants.MGDL);
else data.put("units", Constants.MMOL);
if (event.getDuration() != 0) data.put("duration", T.msecs(event.getDuration()).mins());
if (event.getNote() != null) data.put("notes", event.getNote());
if (event.getGlucose() != null) data.put("glucose", event.getGlucose());
if (event.getGlucoseType() != null)
data.put("glucoseType", event.getGlucoseType().getText());
} catch (JSONException e) {
aapsLogger.error("Unhandled exception", e);
}
uploadQueue.add(new DbRequest("dbAdd", "treatments", data, event.getTimestamp()));
}
public void removeFoodFromNS(String _id) {
try {
uploadQueue.add(new DbRequest("dbRemove", "food", _id, System.currentTimeMillis()));
} catch (Exception e) {
aapsLogger.error("Unhandled exception", e);
}
}
public void createNSTreatment(JSONObject data, ProfileStore profileStore, ProfileFunction profileFunction, long eventTime) {
if (JsonHelper.safeGetString(data, "eventType", "").equals(TherapyEvent.Type.PROFILE_SWITCH.getText())) {
ProfileSwitch profileSwitch = profileFunction.prepareProfileSwitch(
profileStore,
JsonHelper.safeGetString(data, "profile"),
JsonHelper.safeGetInt(data, "duration"),
JsonHelper.safeGetInt(data, "percentage"),
JsonHelper.safeGetInt(data, "timeshift"),
eventTime
);
uploadProfileSwitch(profileSwitch, eventTime);
} else {
uploadCareportalEntryToNS(data, eventTime);
}
}
public static boolean isIdValid(String _id) {
if (_id == null)
return false;

View file

@ -0,0 +1,24 @@
package info.nightscout.androidaps.utils.extensions
import com.google.gson.Gson
import info.nightscout.androidaps.Constants
import info.nightscout.androidaps.data.DetailedBolusInfo
import info.nightscout.androidaps.database.entities.BolusCalculatorResult
import info.nightscout.androidaps.database.entities.TherapyEvent
import info.nightscout.androidaps.utils.DateUtil
import org.json.JSONException
import org.json.JSONObject
fun BolusCalculatorResult.toJson(): JSONObject =
JSONObject()
.put("eventType", TherapyEvent.Type.BOLUS_WIZARD)
.put("created_at", DateUtil.toISOString(timestamp))
.put("bolusCalculatorResult", Gson().toJson(this))
.put("date", timestamp).also {
if (glucoseValue != null) {
it.put("glucose", glucoseValue)
it.put("units", Constants.MGDL)
}
if (note != null) it.put("notes", note)
if (interfaceIDs.nightscoutId != null) it.put("_id", interfaceIDs.nightscoutId)
}

View file

@ -1,12 +1,31 @@
package info.nightscout.androidaps.utils.extensions
import com.google.gson.Gson
import info.nightscout.androidaps.Constants
import info.nightscout.androidaps.data.DetailedBolusInfo
import info.nightscout.androidaps.data.Iob
import info.nightscout.androidaps.database.entities.Bolus
import info.nightscout.androidaps.database.entities.TherapyEvent
import info.nightscout.androidaps.interfaces.ActivePluginProvider
import info.nightscout.androidaps.interfaces.InsulinInterface
import info.nightscout.androidaps.utils.DateUtil
import org.json.JSONException
import org.json.JSONObject
fun Bolus.iobCalc(activePlugin: ActivePluginProvider, time: Long, dia: Double): Iob {
if (!isValid) return Iob()
val insulinInterface: InsulinInterface = activePlugin.activeInsulin
return insulinInterface.iobCalcForTreatment(this, time, dia)
}
fun Bolus.toJson(): JSONObject =
JSONObject()
.put("eventType", if (type == Bolus.Type.SMB) TherapyEvent.Type.CORRECTION_BOLUS else TherapyEvent.Type.MEAL_BOLUS)
.put("insulin", amount)
.put("created_at", DateUtil.toISOString(timestamp))
.put("date", timestamp)
.put("isSMB", type == Bolus.Type.SMB).also {
if (interfaceIDs.pumpId != null) it.put("pumpId", interfaceIDs.pumpId)
if (interfaceIDs.nightscoutId != null) it.put("_id", interfaceIDs.nightscoutId)
}

View file

@ -1,7 +1,10 @@
package info.nightscout.androidaps.utils.extensions
import info.nightscout.androidaps.database.entities.Carbs
import info.nightscout.androidaps.database.entities.TherapyEvent
import info.nightscout.androidaps.utils.DateUtil
import info.nightscout.androidaps.utils.T
import org.json.JSONObject
import kotlin.math.roundToInt
fun Carbs.expandCarbs(): List<Carbs> =
@ -24,3 +27,14 @@ fun Carbs.expandCarbs(): List<Carbs> =
}
}
}
fun Carbs.toJson(): JSONObject =
JSONObject()
.put("eventType", if (amount < 12) TherapyEvent.Type.CARBS_CORRECTION else TherapyEvent.Type.MEAL_BOLUS)
.put("carbs", amount)
.put("created_at", DateUtil.toISOString(timestamp))
.put("date", timestamp).also {
if (duration != 0L) it.put("duration", duration)
if (interfaceIDs.pumpId != null) it.put("pumpId", interfaceIDs.pumpId)
if (interfaceIDs.nightscoutId != null) it.put("_id", interfaceIDs.nightscoutId)
}

View file

@ -1,7 +1,6 @@
package info.nightscout.androidaps.utils.extensions
import info.nightscout.androidaps.database.entities.Food
import info.nightscout.androidaps.plugins.general.nsclient.NSUpload
import info.nightscout.androidaps.utils.JsonHelper
import org.json.JSONObject
@ -18,7 +17,7 @@ fun foodFromJson(jsonObject: JSONObject): Food? {
val protein = JsonHelper.safeGetIntAllowNull(jsonObject, "protein")
val fat = JsonHelper.safeGetIntAllowNull(jsonObject, "fat")
val id = JsonHelper.safeGetStringAllowNull(jsonObject, "_id", null) ?: return null
val isValid = JsonHelper.safeGetBoolean(jsonObject, NSUpload.ISVALID, true)
val isValid = JsonHelper.safeGetBoolean(jsonObject, "isValid", true)
val food = Food(
name = name,
@ -38,3 +37,22 @@ fun foodFromJson(jsonObject: JSONObject): Food? {
}
return null
}
fun Food.toJson(units: String): JSONObject =
JSONObject()
.put("type", "food")
.put("name", name)
.put("category", category)
.put("subcategory", subCategory)
.put("unit", unit)
.put("portion", portion)
.put("carbs", carbs)
.put("gi", gi)
.put("energy", energy)
.put("protein", protein)
.put("fat", fat)
.put("isValid", isValid).also {
if (interfaceIDs.nightscoutId != null) it
.put("_id", interfaceIDs.nightscoutId)
}

View file

@ -4,12 +4,13 @@ import info.nightscout.androidaps.database.entities.GlucoseValue
import info.nightscout.androidaps.utils.DateUtil
import org.json.JSONObject
fun GlucoseValue.toJson() : JSONObject =
fun GlucoseValue.toJson(): JSONObject =
JSONObject()
.put("device", sourceSensor.text)
.put("date", timestamp)
.put("dateString", DateUtil.toISOString(timestamp))
.put("sgv", value)
.put("direction", trendArrow.text)
.put("type", "sgv")
.put("NSCLIENT_ID", System.currentTimeMillis()) // Fake to be accepted by WS
.put("type", "sgv").also {
if (interfaceIDs.nightscoutId != null) it.put("_id", interfaceIDs.nightscoutId)
}

View file

@ -103,4 +103,5 @@ fun TemporaryTarget.toJson(units: String): JSONObject =
.put("targetBottom", Profile.fromMgdlToUnits(lowTarget, units))
.put("targetTop", Profile.fromMgdlToUnits(highTarget, units))
.put("units", units)
if (interfaceIDs.nightscoutId != null) it.put("_id", interfaceIDs.nightscoutId)
}

View file

@ -3,7 +3,6 @@ package info.nightscout.androidaps.utils.extensions
import info.nightscout.androidaps.Constants
import info.nightscout.androidaps.core.R
import info.nightscout.androidaps.database.entities.TherapyEvent
import info.nightscout.androidaps.plugins.general.nsclient.NSUpload
import info.nightscout.androidaps.plugins.general.nsclient.data.NSMbg
import info.nightscout.androidaps.utils.DateUtil
import info.nightscout.androidaps.utils.JsonHelper
@ -57,7 +56,7 @@ fun therapyEventFromNsIdForInvalidating(nsId: String): TherapyEvent =
JSONObject()
.put("mills", 1)
.put("_id", nsId)
.put(NSUpload.ISVALID, false)
.put("isValid", false)
)!!
fun therapyEventFromJson(jsonObject: JSONObject): TherapyEvent? {
@ -70,7 +69,7 @@ fun therapyEventFromJson(jsonObject: JSONObject): TherapyEvent? {
val enteredBy = JsonHelper.safeGetStringAllowNull(jsonObject, "enteredBy", null)
val note = JsonHelper.safeGetStringAllowNull(jsonObject, "notes", null)
val id = JsonHelper.safeGetStringAllowNull(jsonObject, "_id", null) ?: return null
val isValid = JsonHelper.safeGetBoolean(jsonObject, NSUpload.ISVALID, true)
val isValid = JsonHelper.safeGetBoolean(jsonObject, "isValid", true)
val te = TherapyEvent(
timestamp = timestamp,
@ -87,6 +86,21 @@ fun therapyEventFromJson(jsonObject: JSONObject): TherapyEvent? {
return te
}
fun TherapyEvent.toJson(): JSONObject =
JSONObject()
.put("eventType", type.text)
.put("created_at", timestamp)
.put("enteredBy", enteredBy)
.put("units", if (glucoseUnit == TherapyEvent.GlucoseUnit.MGDL) Constants.MGDL else Constants.MMOL)
.also {
if (duration != 0L) it.put("duration", T.msecs(duration).mins())
if (note != null) it.put("notes", note)
if (glucose != null) it.put("glucose", glucose)
if (glucoseType != null) it.put("glucoseType", glucoseType!!.text)
if (interfaceIDs.nightscoutId != null) it.put("_id", interfaceIDs.nightscoutId)
if (type == TherapyEvent.Type.ANNOUNCEMENT) it.put("isAnnouncement", true)
}
fun isEvent5minBack(list: List<TherapyEvent>, time: Long): Boolean {
for (i in list.indices) {
val event = list[i]

View file

@ -38,6 +38,8 @@ import info.nightscout.androidaps.danar.comm.MsgStatusTempBasal;
import info.nightscout.androidaps.danar.services.AbstractDanaRExecutionService;
import info.nightscout.androidaps.data.Profile;
import info.nightscout.androidaps.data.PumpEnactResult;
import info.nightscout.androidaps.database.AppRepository;
import info.nightscout.androidaps.database.transactions.InsertTherapyEventAnnouncementTransaction;
import info.nightscout.androidaps.db.Treatment;
import info.nightscout.androidaps.dialogs.BolusProgressDialog;
import info.nightscout.androidaps.events.EventInitializationChanged;
@ -50,13 +52,13 @@ import info.nightscout.androidaps.logging.AAPSLogger;
import info.nightscout.androidaps.logging.LTag;
import info.nightscout.androidaps.plugins.bus.RxBusWrapper;
import info.nightscout.androidaps.plugins.configBuilder.ConstraintChecker;
import info.nightscout.androidaps.plugins.general.nsclient.NSUpload;
import info.nightscout.androidaps.plugins.general.overview.events.EventNewNotification;
import info.nightscout.androidaps.plugins.general.overview.notifications.Notification;
import info.nightscout.androidaps.queue.commands.Command;
import info.nightscout.androidaps.utils.DateUtil;
import info.nightscout.androidaps.utils.T;
import info.nightscout.androidaps.utils.resources.ResourceHelper;
import io.reactivex.disposables.CompositeDisposable;
public class DanaRKoreanExecutionService extends AbstractDanaRExecutionService {
@Inject AAPSLogger aapsLogger;
@ -70,8 +72,9 @@ public class DanaRKoreanExecutionService extends AbstractDanaRExecutionService {
@Inject MessageHashTableRKorean messageHashTableRKorean;
@Inject ActivePluginProvider activePlugin;
@Inject ProfileFunction profileFunction;
@Inject NSUpload nsUpload;
@Inject DateUtil dateUtil;
@Inject AppRepository repository;
private final CompositeDisposable disposable = new CompositeDisposable();
public DanaRKoreanExecutionService() {
}
@ -199,7 +202,7 @@ public class DanaRKoreanExecutionService extends AbstractDanaRExecutionService {
if (System.currentTimeMillis() > lastApproachingDailyLimit + 30 * 60 * 1000) {
Notification reportFail = new Notification(Notification.APPROACHING_DAILY_LIMIT, resourceHelper.gs(R.string.approachingdailylimit), Notification.URGENT);
rxBus.send(new EventNewNotification(reportFail));
nsUpload.uploadError(resourceHelper.gs(R.string.approachingdailylimit) + ": " + danaPump.getDailyTotalUnits() + "/" + danaPump.getMaxDailyTotalUnits() + "U");
disposable.add(repository.runTransaction(new InsertTherapyEventAnnouncementTransaction(resourceHelper.gs(R.string.approachingdailylimit) + ": " + danaPump.getDailyTotalUnits() + "/" + danaPump.getMaxDailyTotalUnits() + "U")).subscribe());
lastApproachingDailyLimit = System.currentTimeMillis();
}
}

View file

@ -52,6 +52,8 @@ import info.nightscout.androidaps.danar.comm.MsgStatusBasic;
import info.nightscout.androidaps.danar.services.AbstractDanaRExecutionService;
import info.nightscout.androidaps.data.Profile;
import info.nightscout.androidaps.data.PumpEnactResult;
import info.nightscout.androidaps.database.AppRepository;
import info.nightscout.androidaps.database.transactions.InsertTherapyEventAnnouncementTransaction;
import info.nightscout.androidaps.db.Treatment;
import info.nightscout.androidaps.dialogs.BolusProgressDialog;
import info.nightscout.androidaps.events.EventInitializationChanged;
@ -66,7 +68,6 @@ import info.nightscout.androidaps.logging.AAPSLogger;
import info.nightscout.androidaps.logging.LTag;
import info.nightscout.androidaps.plugins.bus.RxBusWrapper;
import info.nightscout.androidaps.plugins.configBuilder.ConstraintChecker;
import info.nightscout.androidaps.plugins.general.nsclient.NSUpload;
import info.nightscout.androidaps.plugins.general.overview.events.EventNewNotification;
import info.nightscout.androidaps.plugins.general.overview.events.EventOverviewBolusProgress;
import info.nightscout.androidaps.plugins.general.overview.notifications.Notification;
@ -77,6 +78,7 @@ import info.nightscout.androidaps.utils.DateUtil;
import info.nightscout.androidaps.utils.T;
import info.nightscout.androidaps.utils.resources.ResourceHelper;
import info.nightscout.androidaps.utils.sharedPreferences.SP;
import io.reactivex.disposables.CompositeDisposable;
public class DanaRv2ExecutionService extends AbstractDanaRExecutionService {
@Inject HasAndroidInjector injector;
@ -96,11 +98,12 @@ public class DanaRv2ExecutionService extends AbstractDanaRExecutionService {
@Inject DetailedBolusInfoStorage detailedBolusInfoStorage;
@Inject ActivePluginProvider activePluginProvider;
@Inject ProfileFunction profileFunction;
@Inject NSUpload nsUpload;
@Inject AppRepository repository;
@Inject SP sp;
@Inject DateUtil dateUtil;
private long lastHistoryFetched = 0;
private final CompositeDisposable disposable = new CompositeDisposable();
public DanaRv2ExecutionService() {
}
@ -248,7 +251,7 @@ public class DanaRv2ExecutionService extends AbstractDanaRExecutionService {
if (System.currentTimeMillis() > lastApproachingDailyLimit + 30 * 60 * 1000) {
Notification reportFail = new Notification(Notification.APPROACHING_DAILY_LIMIT, resourceHelper.gs(R.string.approachingdailylimit), Notification.URGENT);
rxBus.send(new EventNewNotification(reportFail));
nsUpload.uploadError(resourceHelper.gs(R.string.approachingdailylimit) + ": " + danaPump.getDailyTotalUnits() + "/" + danaPump.getMaxDailyTotalUnits() + "U");
disposable.add(repository.runTransaction(new InsertTherapyEventAnnouncementTransaction(resourceHelper.gs(R.string.approachingdailylimit) + ": " + danaPump.getDailyTotalUnits() + "/" + danaPump.getMaxDailyTotalUnits() + "U")).subscribe());
lastApproachingDailyLimit = System.currentTimeMillis();
}
}

View file

@ -17,6 +17,7 @@ import info.nightscout.androidaps.dana.DanaPump;
import info.nightscout.androidaps.danaRKorean.DanaRKoreanPlugin;
import info.nightscout.androidaps.danaRv2.DanaRv2Plugin;
import info.nightscout.androidaps.danar.DanaRPlugin;
import info.nightscout.androidaps.database.AppRepository;
import info.nightscout.androidaps.interfaces.ActivePluginProvider;
import info.nightscout.androidaps.interfaces.CommandQueueProvider;
import info.nightscout.androidaps.interfaces.ConfigBuilderInterface;
@ -30,6 +31,7 @@ import info.nightscout.androidaps.plugins.pump.common.bolusInfo.DetailedBolusInf
import info.nightscout.androidaps.utils.CRC;
import info.nightscout.androidaps.utils.DateUtil;
import info.nightscout.androidaps.utils.resources.ResourceHelper;
import io.reactivex.disposables.CompositeDisposable;
/*
* 00 01 02 03 04 05 06
@ -51,10 +53,12 @@ public class MessageBase {
@Inject public CommandQueueProvider commandQueue;
@Inject public DetailedBolusInfoStorage detailedBolusInfoStorage;
@Inject public ConstraintChecker constraintChecker;
@Inject public NSUpload nsUpload;
@Inject public AppRepository repository;
@Inject public DatabaseHelperInterface databaseHelper;
HasAndroidInjector injector;
final CompositeDisposable disposable = new CompositeDisposable();
public byte[] buffer = new byte[512];
private int position = 6;

View file

@ -2,8 +2,10 @@ package info.nightscout.androidaps.danar.comm
import dagger.android.HasAndroidInjector
import info.nightscout.androidaps.danar.R
import info.nightscout.androidaps.database.transactions.InsertTherapyEventAnnouncementTransaction
import info.nightscout.androidaps.logging.LTag
import info.nightscout.androidaps.plugins.general.overview.events.EventOverviewBolusProgress
import io.reactivex.rxkotlin.plusAssign
class MsgError(
injector: HasAndroidInjector
@ -34,6 +36,6 @@ class MsgError(
failed = false
}
aapsLogger.debug(LTag.PUMPCOMM, "Error detected: $errorString")
nsUpload.uploadError(errorString)
disposable += repository.runTransaction(InsertTherapyEventAnnouncementTransaction(errorString)).subscribe();
}
}

View file

@ -45,6 +45,8 @@ import info.nightscout.androidaps.danar.comm.MsgStatusBolusExtended;
import info.nightscout.androidaps.danar.comm.MsgStatusTempBasal;
import info.nightscout.androidaps.data.Profile;
import info.nightscout.androidaps.data.PumpEnactResult;
import info.nightscout.androidaps.database.AppRepository;
import info.nightscout.androidaps.database.transactions.InsertTherapyEventAnnouncementTransaction;
import info.nightscout.androidaps.db.Treatment;
import info.nightscout.androidaps.dialogs.BolusProgressDialog;
import info.nightscout.androidaps.events.EventInitializationChanged;
@ -57,7 +59,6 @@ import info.nightscout.androidaps.logging.AAPSLogger;
import info.nightscout.androidaps.logging.LTag;
import info.nightscout.androidaps.plugins.bus.RxBusWrapper;
import info.nightscout.androidaps.plugins.configBuilder.ConstraintChecker;
import info.nightscout.androidaps.plugins.general.nsclient.NSUpload;
import info.nightscout.androidaps.plugins.general.overview.events.EventNewNotification;
import info.nightscout.androidaps.plugins.general.overview.events.EventOverviewBolusProgress;
import info.nightscout.androidaps.plugins.general.overview.notifications.Notification;
@ -66,6 +67,7 @@ import info.nightscout.androidaps.queue.commands.Command;
import info.nightscout.androidaps.utils.DateUtil;
import info.nightscout.androidaps.utils.resources.ResourceHelper;
import info.nightscout.androidaps.utils.sharedPreferences.SP;
import io.reactivex.disposables.CompositeDisposable;
public class DanaRExecutionService extends AbstractDanaRExecutionService {
@Inject AAPSLogger aapsLogger;
@ -79,10 +81,12 @@ public class DanaRExecutionService extends AbstractDanaRExecutionService {
@Inject MessageHashTableR messageHashTableR;
@Inject ActivePluginProvider activePlugin;
@Inject ProfileFunction profileFunction;
@Inject NSUpload nsUpload;
@Inject AppRepository repository;
@Inject SP sp;
@Inject HasAndroidInjector injector;
private final CompositeDisposable disposable = new CompositeDisposable();
public DanaRExecutionService() {
}
@ -211,7 +215,7 @@ public class DanaRExecutionService extends AbstractDanaRExecutionService {
if (System.currentTimeMillis() > lastApproachingDailyLimit + 30 * 60 * 1000) {
Notification reportFail = new Notification(Notification.APPROACHING_DAILY_LIMIT, resourceHelper.gs(R.string.approachingdailylimit), Notification.URGENT);
rxBus.send(new EventNewNotification(reportFail));
nsUpload.uploadError(resourceHelper.gs(R.string.approachingdailylimit) + ": " + danaPump.getDailyTotalUnits() + "/" + danaPump.getMaxDailyTotalUnits() + "U");
disposable.add(repository.runTransaction(new InsertTherapyEventAnnouncementTransaction(resourceHelper.gs(R.string.approachingdailylimit) + ": " + danaPump.getDailyTotalUnits() + "/" + danaPump.getMaxDailyTotalUnits() + "U")).subscribe());
lastApproachingDailyLimit = System.currentTimeMillis();
}
}

View file

@ -15,7 +15,6 @@ import info.nightscout.androidaps.events.EventPumpStatusChanged
import info.nightscout.androidaps.interfaces.ActivePluginProvider
import info.nightscout.androidaps.logging.LTag
import info.nightscout.androidaps.plugins.bus.RxBusWrapper
import info.nightscout.androidaps.plugins.general.nsclient.NSUpload
import info.nightscout.androidaps.plugins.pump.common.bolusInfo.DetailedBolusInfoStorage
import info.nightscout.androidaps.plugins.pump.common.defs.PumpType
import info.nightscout.androidaps.utils.DateUtil
@ -38,7 +37,6 @@ open class DanaRS_Packet_APS_History_Events(
@Inject lateinit var danaPump: DanaPump
@Inject lateinit var detailedBolusInfoStorage: DetailedBolusInfoStorage
@Inject lateinit var sp: SP
@Inject lateinit var nsUpload: NSUpload
@Inject lateinit var repository: AppRepository
private val disposable = CompositeDisposable()
@ -188,11 +186,10 @@ open class DanaRS_Packet_APS_History_Events(
type = TherapyEvent.Type.INSULIN_CHANGE,
note = resourceHelper.gs(R.string.danarspump),
glucoseUnit = TherapyEvent.GlucoseUnit.MGDL
)).subscribe({ result ->
result.inserted.forEach { nsUpload.uploadEvent(it) }
}, {
aapsLogger.error(LTag.DATABASE, "Error while saving therapy event", it)
})
)).subscribe(
{ result -> result.inserted.forEach { aapsLogger.debug(LTag.DATABASE, "Inserted therapy event $it") } },
{ aapsLogger.error(LTag.DATABASE, "Error while saving therapy event", it) }
)
status = "REFILL " + dateUtil.timeString(datetime)
}
@ -226,11 +223,10 @@ open class DanaRS_Packet_APS_History_Events(
type = TherapyEvent.Type.CANNULA_CHANGE,
note = resourceHelper.gs(R.string.danarspump),
glucoseUnit = TherapyEvent.GlucoseUnit.MGDL
)).subscribe({ result ->
result.inserted.forEach { nsUpload.uploadEvent(it) }
}, {
aapsLogger.error(LTag.DATABASE, "Error while saving therapy event", it)
})
)).subscribe(
{ result -> result.inserted.forEach { aapsLogger.debug(LTag.DATABASE, "Inserted therapy event $it") } },
{ aapsLogger.error(LTag.DATABASE, "Error while saving therapy event", it) }
)
status = "PRIMECANNULA " + dateUtil.timeString(datetime)
}

View file

@ -2,13 +2,16 @@ package info.nightscout.androidaps.danars.comm
import dagger.android.HasAndroidInjector
import info.nightscout.androidaps.danars.R
import info.nightscout.androidaps.danars.encryption.BleEncryption
import info.nightscout.androidaps.database.AppRepository
import info.nightscout.androidaps.database.transactions.InsertTherapyEventAnnouncementTransaction
import info.nightscout.androidaps.logging.LTag
import info.nightscout.androidaps.plugins.bus.RxBusWrapper
import info.nightscout.androidaps.plugins.general.nsclient.NSUpload
import info.nightscout.androidaps.plugins.general.overview.events.EventNewNotification
import info.nightscout.androidaps.plugins.general.overview.notifications.Notification
import info.nightscout.androidaps.danars.encryption.BleEncryption
import info.nightscout.androidaps.utils.resources.ResourceHelper
import io.reactivex.disposables.CompositeDisposable
import io.reactivex.rxkotlin.plusAssign
import javax.inject.Inject
class DanaRS_Packet_Notify_Alarm(
@ -17,7 +20,9 @@ class DanaRS_Packet_Notify_Alarm(
@Inject lateinit var rxBus: RxBusWrapper
@Inject lateinit var resourceHelper: ResourceHelper
@Inject lateinit var nsUpload: NSUpload
@Inject lateinit var repository: AppRepository
private val disposable = CompositeDisposable()
init {
type = BleEncryption.DANAR_PACKET__TYPE_NOTIFY
@ -64,7 +69,7 @@ class DanaRS_Packet_Notify_Alarm(
}
val notification = Notification(Notification.USER_MESSAGE, errorString, Notification.URGENT)
rxBus.send(EventNewNotification(notification))
nsUpload.uploadError(errorString)
disposable += repository.runTransaction(InsertTherapyEventAnnouncementTransaction(errorString)).subscribe()
}
override fun getFriendlyName(): String {

View file

@ -16,11 +16,12 @@ import info.nightscout.androidaps.danars.comm.DanaRS_Packet
import info.nightscout.androidaps.danars.comm.DanaRS_Packet_Etc_Keep_Connection
import info.nightscout.androidaps.danars.encryption.BleEncryption
import info.nightscout.androidaps.danars.events.EventDanaRSPairingSuccess
import info.nightscout.androidaps.database.AppRepository
import info.nightscout.androidaps.database.transactions.InsertTherapyEventAnnouncementTransaction
import info.nightscout.androidaps.events.EventPumpStatusChanged
import info.nightscout.androidaps.logging.AAPSLogger
import info.nightscout.androidaps.logging.LTag
import info.nightscout.androidaps.plugins.bus.RxBusWrapper
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
import info.nightscout.androidaps.plugins.general.overview.notifications.Notification
@ -31,6 +32,8 @@ import info.nightscout.androidaps.utils.extensions.notify
import info.nightscout.androidaps.utils.extensions.waitMillis
import info.nightscout.androidaps.utils.resources.ResourceHelper
import info.nightscout.androidaps.utils.sharedPreferences.SP
import io.reactivex.disposables.CompositeDisposable
import io.reactivex.rxkotlin.plusAssign
import java.util.*
import java.util.concurrent.ScheduledFuture
import javax.inject.Inject
@ -48,7 +51,7 @@ class BLEComm @Inject internal constructor(
private val danaPump: DanaPump,
private val danaRSPlugin: DanaRSPlugin,
private val bleEncryption: BleEncryption,
private val nsUpload: NSUpload
private val repository: AppRepository
) {
companion object {
@ -61,6 +64,8 @@ class BLEComm @Inject internal constructor(
private const val PACKET_END_BYTE = 0x5A.toByte()
}
private val disposable = CompositeDisposable()
private var scheduledDisconnection: ScheduledFuture<*>? = null
private var processedMessage: DanaRS_Packet? = null
private val mSendQueue = ArrayList<ByteArray>()
@ -488,7 +493,7 @@ class BLEComm @Inject internal constructor(
aapsLogger.debug(LTag.PUMPBTCOMM, "<<<<< " + "ENCRYPTION__PUMP_CHECK (PUMP)" + " " + DanaRS_Packet.toHexString(decryptedBuffer))
mSendQueue.clear()
rxBus.send(EventPumpStatusChanged(EventPumpStatusChanged.Status.DISCONNECTED, resourceHelper.gs(R.string.pumperror)))
nsUpload.uploadError(resourceHelper.gs(R.string.pumperror))
disposable += repository.runTransaction(InsertTherapyEventAnnouncementTransaction(resourceHelper.gs(R.string.pumperror))).subscribe()
val n = Notification(Notification.PUMP_ERROR, resourceHelper.gs(R.string.pumperror), Notification.URGENT)
rxBus.send(EventNewNotification(n))
// response BUSY: error status

View file

@ -18,6 +18,8 @@ import info.nightscout.androidaps.danars.R
import info.nightscout.androidaps.danars.comm.*
import info.nightscout.androidaps.data.Profile
import info.nightscout.androidaps.data.PumpEnactResult
import info.nightscout.androidaps.database.AppRepository
import info.nightscout.androidaps.database.transactions.InsertTherapyEventAnnouncementTransaction
import info.nightscout.androidaps.db.Treatment
import info.nightscout.androidaps.dialogs.BolusProgressDialog
import info.nightscout.androidaps.events.EventAppExit
@ -31,7 +33,6 @@ import info.nightscout.androidaps.logging.AAPSLogger
import info.nightscout.androidaps.logging.LTag
import info.nightscout.androidaps.plugins.bus.RxBusWrapper
import info.nightscout.androidaps.plugins.configBuilder.ConstraintChecker
import info.nightscout.androidaps.plugins.general.nsclient.NSUpload
import info.nightscout.androidaps.plugins.general.overview.events.EventNewNotification
import info.nightscout.androidaps.plugins.general.overview.events.EventOverviewBolusProgress
import info.nightscout.androidaps.plugins.general.overview.notifications.Notification
@ -45,6 +46,7 @@ import info.nightscout.androidaps.utils.resources.ResourceHelper
import info.nightscout.androidaps.utils.rx.AapsSchedulers
import info.nightscout.androidaps.utils.sharedPreferences.SP
import io.reactivex.disposables.CompositeDisposable
import io.reactivex.rxkotlin.plusAssign
import org.joda.time.DateTime
import org.joda.time.DateTimeZone
import java.util.concurrent.TimeUnit
@ -71,7 +73,7 @@ class DanaRSService : DaggerService() {
@Inject lateinit var detailedBolusInfoStorage: DetailedBolusInfoStorage
@Inject lateinit var bleComm: BLEComm
@Inject lateinit var fabricPrivacy: FabricPrivacy
@Inject lateinit var nsUpload: NSUpload
@Inject lateinit var repository: AppRepository
@Inject lateinit var dateUtil: DateUtil
private val disposable = CompositeDisposable()
@ -180,9 +182,11 @@ class DanaRSService : DaggerService() {
danaPump.usingUTC -> {
sendMessage(DanaRS_Packet_Option_Set_Pump_UTC_And_TimeZone(injector, DateUtil.now(), offset))
}
danaPump.protocol >= 6 -> { // can set seconds
sendMessage(DanaRS_Packet_Option_Set_Pump_Time(injector, DateUtil.now()))
}
else -> {
waitForWholeMinute() // Dana can set only whole minute
// add 10sec to be sure we are over minute (will be cut off anyway)
@ -204,7 +208,7 @@ class DanaRSService : DaggerService() {
if (System.currentTimeMillis() > lastApproachingDailyLimit + 30 * 60 * 1000) {
val reportFail = Notification(Notification.APPROACHING_DAILY_LIMIT, resourceHelper.gs(R.string.approachingdailylimit), Notification.URGENT)
rxBus.send(EventNewNotification(reportFail))
nsUpload.uploadError(resourceHelper.gs(R.string.approachingdailylimit) + ": " + danaPump.dailyTotalUnits + "/" + danaPump.maxDailyTotalUnits + "U")
disposable += repository.runTransaction(InsertTherapyEventAnnouncementTransaction(resourceHelper.gs(R.string.approachingdailylimit) + ": " + danaPump.dailyTotalUnits + "/" + danaPump.maxDailyTotalUnits + "U")).subscribe()
lastApproachingDailyLimit = System.currentTimeMillis()
}
}

View file

@ -90,7 +90,7 @@ open class AppRepository @Inject internal constructor(
Maybe.just(nextIdElement to nextIdElement.id)
} else {
database.glucoseValueDao.getCurrentFromHistoric(nextIdElemReferenceId)
.map { it to nextIdElement.id}
.map { it to nextIdElement.id }
}
}
@ -118,7 +118,7 @@ open class AppRepository @Inject internal constructor(
Maybe.just(nextIdElement to nextIdElement.id)
} else {
database.temporaryTargetDao.getCurrentFromHistoric(nextIdElemReferenceId)
.map { it to nextIdElement.id}
.map { it to nextIdElement.id }
}
}
@ -161,6 +161,29 @@ open class AppRepository @Inject internal constructor(
}
// THERAPY EVENT
/*
* 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 getNextSyncElementTherapyEvent(id: Long): Maybe<Pair<TherapyEvent, Long>> =
database.therapyEventDao.getNextModifiedOrNewAfter(id)
.flatMap { nextIdElement ->
val nextIdElemReferenceId = nextIdElement.referenceId
if (nextIdElemReferenceId == null) {
Maybe.just(nextIdElement to nextIdElement.id)
} else {
database.therapyEventDao.getCurrentFromHistoric(nextIdElemReferenceId)
.map { it to nextIdElement.id }
}
}
fun getModifiedTherapyEventDataFromId(lastId: Long): Single<List<TherapyEvent>> =
database.therapyEventDao.getModifiedFrom(lastId)
.subscribeOn(Schedulers.io())
fun getTherapyEventDataFromTime(timestamp: Long, ascending: Boolean): Single<List<TherapyEvent>> =
database.therapyEventDao.getTherapyEventDataFromTime(timestamp)
.map { if (!ascending) it.reversed() else it }
@ -200,6 +223,29 @@ open class AppRepository @Inject internal constructor(
.subscribeOn(Schedulers.io())
// FOOD
/*
* 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 getNextSyncElementFood(id: Long): Maybe<Pair<Food, Long>> =
database.foodDao.getNextModifiedOrNewAfter(id)
.flatMap { nextIdElement ->
val nextIdElemReferenceId = nextIdElement.referenceId
if (nextIdElemReferenceId == null) {
Maybe.just(nextIdElement to nextIdElement.id)
} else {
database.foodDao.getCurrentFromHistoric(nextIdElemReferenceId)
.map { it to nextIdElement.id }
}
}
fun getModifiedFoodDataFromId(lastId: Long): Single<List<Food>> =
database.foodDao.getModifiedFrom(lastId)
.subscribeOn(Schedulers.io())
fun getFoodData(): Single<List<Food>> =
database.foodDao.getFoodData()
.subscribeOn(Schedulers.io())
@ -208,6 +254,29 @@ open class AppRepository @Inject internal constructor(
database.foodDao.deleteAllEntries()
// BOLUS
/*
* 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 getNextSyncElementBolus(id: Long): Maybe<Pair<Bolus, Long>> =
database.bolusDao.getNextModifiedOrNewAfter(id)
.flatMap { nextIdElement ->
val nextIdElemReferenceId = nextIdElement.referenceId
if (nextIdElemReferenceId == null) {
Maybe.just(nextIdElement to nextIdElement.id)
} else {
database.bolusDao.getCurrentFromHistoric(nextIdElemReferenceId)
.map { it to nextIdElement.id }
}
}
fun getModifiedBolusesDataFromId(lastId: Long): Single<List<Bolus>> =
database.bolusDao.getModifiedFrom(lastId)
.subscribeOn(Schedulers.io())
fun getBolusesDataFromTime(timestamp: Long, ascending: Boolean): Single<List<Bolus>> =
database.bolusDao.getBolusesFromTime(timestamp)
.map { if (!ascending) it.reversed() else it }
@ -222,6 +291,29 @@ open class AppRepository @Inject internal constructor(
database.bolusDao.deleteAllEntries()
// CARBS
/*
* 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 getNextSyncElementCarbs(id: Long): Maybe<Pair<Carbs, Long>> =
database.carbsDao.getNextModifiedOrNewAfter(id)
.flatMap { nextIdElement ->
val nextIdElemReferenceId = nextIdElement.referenceId
if (nextIdElemReferenceId == null) {
Maybe.just(nextIdElement to nextIdElement.id)
} else {
database.carbsDao.getCurrentFromHistoric(nextIdElemReferenceId)
.map { it to nextIdElement.id }
}
}
fun getModifiedCarbsDataFromId(lastId: Long): Single<List<Carbs>> =
database.carbsDao.getModifiedFrom(lastId)
.subscribeOn(Schedulers.io())
fun getCarbsDataFromTime(timestamp: Long, ascending: Boolean): Single<List<Carbs>> =
database.carbsDao.getCarbsFromTime(timestamp)
.map { if (!ascending) it.reversed() else it }
@ -235,7 +327,30 @@ open class AppRepository @Inject internal constructor(
fun deleteAllCarbs() =
database.carbsDao.deleteAllEntries()
// CARBS
// BOLUS CALCULATOR RESULT
/*
* 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 getNextSyncElementBolusCalculatorResult(id: Long): Maybe<Pair<BolusCalculatorResult, Long>> =
database.bolusCalculatorResultDao.getNextModifiedOrNewAfter(id)
.flatMap { nextIdElement ->
val nextIdElemReferenceId = nextIdElement.referenceId
if (nextIdElemReferenceId == null) {
Maybe.just(nextIdElement to nextIdElement.id)
} else {
database.bolusCalculatorResultDao.getCurrentFromHistoric(nextIdElemReferenceId)
.map { it to nextIdElement.id }
}
}
fun getModifiedBolusCalculatorResultsDataFromId(lastId: Long): Single<List<BolusCalculatorResult>> =
database.bolusCalculatorResultDao.getModifiedFrom(lastId)
.subscribeOn(Schedulers.io())
fun getBolusCalculatorResultsDataFromTime(timestamp: Long, ascending: Boolean): Single<List<BolusCalculatorResult>> =
database.bolusCalculatorResultDao.getBolusCalculatorResultsFromTime(timestamp)
.map { if (!ascending) it.reversed() else it }

View file

@ -4,6 +4,7 @@ import androidx.room.Dao
import androidx.room.Query
import info.nightscout.androidaps.database.TABLE_BOLUS_CALCULATOR_RESULTS
import info.nightscout.androidaps.database.entities.BolusCalculatorResult
import io.reactivex.Maybe
import io.reactivex.Single
@Suppress("FunctionName")
@ -22,4 +23,15 @@ internal interface BolusCalculatorResultDao : TraceableDao<BolusCalculatorResult
@Query("SELECT * FROM $TABLE_BOLUS_CALCULATOR_RESULTS WHERE timestamp >= :timestamp AND referenceId IS NULL ORDER BY id DESC")
fun getBolusCalculatorResultsIncludingInvalidFromTime(timestamp: Long): Single<List<BolusCalculatorResult>>
// This query will be used with v3 to get all changed records
@Query("SELECT * FROM $TABLE_BOLUS_CALCULATOR_RESULTS WHERE id > :id AND referenceId IS NULL OR id IN (SELECT DISTINCT referenceId FROM $TABLE_BOLUS_CALCULATOR_RESULTS WHERE id > :id) ORDER BY id ASC")
fun getModifiedFrom(id: Long): Single<List<BolusCalculatorResult>>
// for WS we need 1 record only
@Query("SELECT * FROM $TABLE_BOLUS_CALCULATOR_RESULTS WHERE id > :id ORDER BY id ASC limit 1")
fun getNextModifiedOrNewAfter(id: Long): Maybe<BolusCalculatorResult>
@Query("SELECT * FROM $TABLE_BOLUS_CALCULATOR_RESULTS WHERE id = :referenceId")
fun getCurrentFromHistoric(referenceId: Long): Maybe<BolusCalculatorResult>
}

View file

@ -4,6 +4,7 @@ import androidx.room.Dao
import androidx.room.Query
import info.nightscout.androidaps.database.TABLE_BOLUSES
import info.nightscout.androidaps.database.entities.Bolus
import io.reactivex.Maybe
import io.reactivex.Single
@Suppress("FunctionName")
@ -21,4 +22,15 @@ internal interface BolusDao : TraceableDao<Bolus> {
@Query("SELECT * FROM $TABLE_BOLUSES WHERE timestamp >= :timestamp AND referenceId IS NULL ORDER BY id DESC")
fun getBolusesIncludingInvalidFromTime(timestamp: Long): Single<List<Bolus>>
// This query will be used with v3 to get all changed records
@Query("SELECT * FROM $TABLE_BOLUSES WHERE id > :id AND referenceId IS NULL OR id IN (SELECT DISTINCT referenceId FROM $TABLE_BOLUSES WHERE id > :id) ORDER BY id ASC")
fun getModifiedFrom(id: Long): Single<List<Bolus>>
// for WS we need 1 record only
@Query("SELECT * FROM $TABLE_BOLUSES WHERE id > :id ORDER BY id ASC limit 1")
fun getNextModifiedOrNewAfter(id: Long): Maybe<Bolus>
@Query("SELECT * FROM $TABLE_BOLUSES WHERE id = :referenceId")
fun getCurrentFromHistoric(referenceId: Long): Maybe<Bolus>
}

View file

@ -4,6 +4,7 @@ import androidx.room.Dao
import androidx.room.Query
import info.nightscout.androidaps.database.TABLE_CARBS
import info.nightscout.androidaps.database.entities.Carbs
import io.reactivex.Maybe
import io.reactivex.Single
@Suppress("FunctionName")
@ -21,4 +22,15 @@ internal interface CarbsDao : TraceableDao<Carbs> {
@Query("SELECT * FROM $TABLE_CARBS WHERE timestamp >= :timestamp AND referenceId IS NULL ORDER BY id DESC")
fun getCarbsIncludingInvalidFromTime(timestamp: Long): Single<List<Carbs>>
// This query will be used with v3 to get all changed records
@Query("SELECT * FROM $TABLE_CARBS WHERE id > :id AND referenceId IS NULL OR id IN (SELECT DISTINCT referenceId FROM $TABLE_CARBS WHERE id > :id) ORDER BY id ASC")
fun getModifiedFrom(id: Long): Single<List<Carbs>>
// for WS we need 1 record only
@Query("SELECT * FROM $TABLE_CARBS WHERE id > :id ORDER BY id ASC limit 1")
fun getNextModifiedOrNewAfter(id: Long): Maybe<Carbs>
@Query("SELECT * FROM $TABLE_CARBS WHERE id = :referenceId")
fun getCurrentFromHistoric(referenceId: Long): Maybe<Carbs>
}

View file

@ -4,6 +4,7 @@ import androidx.room.Dao
import androidx.room.Query
import info.nightscout.androidaps.database.TABLE_FOODS
import info.nightscout.androidaps.database.entities.Food
import io.reactivex.Maybe
import io.reactivex.Single
@Suppress("FunctionName")
@ -22,4 +23,14 @@ internal interface FoodDao : TraceableDao<Food> {
@Query("SELECT * FROM $TABLE_FOODS WHERE isValid = 1 AND referenceId IS NULL ORDER BY id DESC")
fun getFoodData(): Single<List<Food>>
// This query will be used with v3 to get all changed records
@Query("SELECT * FROM $TABLE_FOODS WHERE id > :id AND referenceId IS NULL OR id IN (SELECT DISTINCT referenceId FROM $TABLE_FOODS WHERE id > :id) ORDER BY id ASC")
fun getModifiedFrom(id: Long): Single<List<Food>>
// for WS we need 1 record only
@Query("SELECT * FROM $TABLE_FOODS WHERE id > :id ORDER BY id ASC limit 1")
fun getNextModifiedOrNewAfter(id: Long): Maybe<Food>
@Query("SELECT * FROM $TABLE_FOODS WHERE id = :referenceId")
fun getCurrentFromHistoric(referenceId: Long): Maybe<Food>
}

View file

@ -42,4 +42,15 @@ internal interface TherapyEventDao : TraceableDao<TherapyEvent> {
@Query("SELECT * FROM $TABLE_THERAPY_EVENTS WHERE timestamp >= :from AND timestamp <= :to AND isValid = 1 AND referenceId IS NULL ORDER BY timestamp ASC")
fun compatGetTherapyEventDataFromToTime(from: Long, to: Long): Single<List<TherapyEvent>>
// This query will be used with v3 to get all changed records
@Query("SELECT * FROM $TABLE_THERAPY_EVENTS WHERE id > :id AND referenceId IS NULL OR id IN (SELECT DISTINCT referenceId FROM $TABLE_THERAPY_EVENTS WHERE id > :id) ORDER BY id ASC")
fun getModifiedFrom(id: Long): Single<List<TherapyEvent>>
// for WS we need 1 record only
@Query("SELECT * FROM $TABLE_THERAPY_EVENTS WHERE id > :id ORDER BY id ASC limit 1")
fun getNextModifiedOrNewAfter(id: Long): Maybe<TherapyEvent>
@Query("SELECT * FROM $TABLE_THERAPY_EVENTS WHERE id = :referenceId")
fun getCurrentFromHistoric(referenceId: Long): Maybe<TherapyEvent>
}

View file

@ -0,0 +1,23 @@
package info.nightscout.androidaps.database.transactions
import info.nightscout.androidaps.database.entities.TherapyEvent
class InsertTherapyEventAnnouncementTransaction(
val therapyEvent: TherapyEvent
) : Transaction<InsertTherapyEventAnnouncementTransaction.TransactionResult>() {
constructor(error: String) :
this(TherapyEvent(timestamp = System.currentTimeMillis(), type = TherapyEvent.Type.ANNOUNCEMENT, duration = 0, note = error, enteredBy = "AndroidAPS", glucose = null, glucoseType = null, glucoseUnit = TherapyEvent.GlucoseUnit.MGDL))
override fun run(): TransactionResult {
val result = TransactionResult()
database.therapyEventDao.insertNewEntry(therapyEvent)
result.inserted.add(therapyEvent)
return result
}
class TransactionResult {
val inserted = mutableListOf<TherapyEvent>()
}
}

View file

@ -0,0 +1,12 @@
package info.nightscout.androidaps.database.transactions
import info.nightscout.androidaps.database.entities.BolusCalculatorResult
class UpdateNsIdBolusCalculatorResultTransaction(val bolusCalculatorResult: BolusCalculatorResult) : Transaction<Unit>() {
override fun run() {
val current = database.bolusCalculatorResultDao.findById(bolusCalculatorResult.id)
if (current != null && current.interfaceIDs.nightscoutId != bolusCalculatorResult.interfaceIDs.nightscoutId)
database.bolusCalculatorResultDao.updateExistingEntry(bolusCalculatorResult)
}
}

View file

@ -0,0 +1,12 @@
package info.nightscout.androidaps.database.transactions
import info.nightscout.androidaps.database.entities.Bolus
class UpdateNsIdBolusTransaction(val bolus: Bolus) : Transaction<Unit>() {
override fun run() {
val current = database.bolusDao.findById(bolus.id)
if (current != null && current.interfaceIDs.nightscoutId != bolus.interfaceIDs.nightscoutId)
database.bolusDao.updateExistingEntry(bolus)
}
}

View file

@ -0,0 +1,12 @@
package info.nightscout.androidaps.database.transactions
import info.nightscout.androidaps.database.entities.Carbs
class UpdateNsIdCarbsTransaction(val carbs: Carbs) : Transaction<Unit>() {
override fun run() {
val current = database.carbsDao.findById(carbs.id)
if (current != null && current.interfaceIDs.nightscoutId != carbs.interfaceIDs.nightscoutId)
database.carbsDao.updateExistingEntry(carbs)
}
}

View file

@ -0,0 +1,12 @@
package info.nightscout.androidaps.database.transactions
import info.nightscout.androidaps.database.entities.Food
class UpdateNsIdFoodTransaction(val food: Food) : Transaction<Unit>() {
override fun run() {
val current = database.foodDao.findById(food.id)
if (current != null && current.interfaceIDs.nightscoutId != food.interfaceIDs.nightscoutId)
database.foodDao.updateExistingEntry(food)
}
}

View file

@ -0,0 +1,12 @@
package info.nightscout.androidaps.database.transactions
import info.nightscout.androidaps.database.entities.TherapyEvent
class UpdateNsIdTherapyEventTransaction(val therapyEvent: TherapyEvent) : Transaction<Unit>() {
override fun run() {
val current = database.therapyEventDao.findById(therapyEvent.id)
if (current != null && current.interfaceIDs.nightscoutId != therapyEvent.interfaceIDs.nightscoutId)
database.therapyEventDao.updateExistingEntry(therapyEvent)
}
}

View file

@ -1558,7 +1558,7 @@ public class LocalInsightPlugin extends PumpPluginBase implements PumpInterface,
if (repository.getTherapyEventByTimestamp(TherapyEvent.Type.NOTE, date) != null) return;
disposable.add(repository.runTransactionForResult(new InsertTherapyEventIfNewTransaction(date, TherapyEvent.Type.NOTE, 0, note, sp.getString("careportal_enteredby", "AndroidAPS"), null, null, TherapyEvent.GlucoseUnit.MGDL))
.subscribe(
result -> result.getInserted().forEach(nsUpload::uploadEvent),
result -> result.getInserted().forEach(event -> aapsLogger.debug(LTag.DATABASE, "Inserted therapy event " + event)),
error -> aapsLogger.error(LTag.DATABASE, "Error while saving therapy event", error)
));
}
@ -1580,7 +1580,7 @@ public class LocalInsightPlugin extends PumpPluginBase implements PumpInterface,
if (repository.getTherapyEventByTimestamp(event, date) != null) return;
disposable.add(repository.runTransactionForResult(new InsertTherapyEventIfNewTransaction(date, event, 0, null, sp.getString("careportal_enteredby", "AndroidAPS"), null, null, TherapyEvent.GlucoseUnit.MGDL))
.subscribe(
result -> result.getInserted().forEach(nsUpload::uploadEvent),
result -> result.getInserted().forEach(record -> aapsLogger.debug(LTag.DATABASE, "Inserted therapy event " + record)),
error -> aapsLogger.error(LTag.DATABASE, "Error while saving therapy event", error)
));
}

View file

@ -34,7 +34,6 @@ import info.nightscout.androidaps.interfaces.ActivePluginProvider;
import info.nightscout.androidaps.interfaces.DatabaseHelperInterface;
import info.nightscout.androidaps.logging.AAPSLogger;
import info.nightscout.androidaps.logging.LTag;
import info.nightscout.androidaps.plugins.general.nsclient.NSUpload;
import info.nightscout.androidaps.plugins.pump.common.defs.PumpType;
import info.nightscout.androidaps.plugins.pump.common.utils.DateTimeUtil;
import info.nightscout.androidaps.plugins.pump.common.utils.StringUtil;
@ -77,7 +76,6 @@ public class MedtronicHistoryData {
private final AAPSLogger aapsLogger;
private final SP sp;
private final ActivePluginProvider activePlugin;
private final NSUpload nsUpload;
private final MedtronicUtil medtronicUtil;
private final MedtronicPumpHistoryDecoder medtronicPumpHistoryDecoder;
private final MedtronicPumpStatus medtronicPumpStatus;
@ -112,7 +110,6 @@ public class MedtronicHistoryData {
AAPSLogger aapsLogger,
SP sp,
ActivePluginProvider activePlugin,
NSUpload nsUpload,
MedtronicUtil medtronicUtil,
MedtronicPumpHistoryDecoder medtronicPumpHistoryDecoder,
MedtronicPumpStatus medtronicPumpStatus,
@ -125,7 +122,6 @@ public class MedtronicHistoryData {
this.aapsLogger = aapsLogger;
this.sp = sp;
this.activePlugin = activePlugin;
this.nsUpload = nsUpload;
this.medtronicUtil = medtronicUtil;
this.medtronicPumpHistoryDecoder = medtronicPumpHistoryDecoder;
this.medtronicPumpStatus = medtronicPumpStatus;
@ -593,7 +589,7 @@ public class MedtronicHistoryData {
event, 0, null, sp.getString("careportal_enteredby", "AndroidAPS"),
null, null, TherapyEvent.GlucoseUnit.MGDL))
.subscribe(
result -> result.getInserted().forEach(nsUpload::uploadEvent),
result -> result.getInserted().forEach(record -> aapsLogger.debug(LTag.DATABASE, "Inserted therapy event " + record)),
error -> aapsLogger.error(LTag.DATABASE, "Error while saving therapy event", error)
));
}

View file

@ -1,5 +1,7 @@
package info.nightscout.androidaps.plugins.pump.omnipod.eros;
import static info.nightscout.androidaps.plugins.pump.omnipod.eros.driver.definition.OmnipodConstants.BASAL_STEP_DURATION;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
@ -31,7 +33,8 @@ import info.nightscout.androidaps.activities.ErrorHelperActivity;
import info.nightscout.androidaps.data.DetailedBolusInfo;
import info.nightscout.androidaps.data.Profile;
import info.nightscout.androidaps.data.PumpEnactResult;
import info.nightscout.androidaps.database.entities.Bolus;
import info.nightscout.androidaps.database.AppRepository;
import info.nightscout.androidaps.database.transactions.InsertTherapyEventAnnouncementTransaction;
import info.nightscout.androidaps.db.ExtendedBolus;
import info.nightscout.androidaps.db.Source;
import info.nightscout.androidaps.db.TemporaryBasal;
@ -52,7 +55,6 @@ import info.nightscout.androidaps.logging.LTag;
import info.nightscout.androidaps.plugins.bus.RxBusWrapper;
import info.nightscout.androidaps.plugins.common.ManufacturerType;
import info.nightscout.androidaps.plugins.general.actions.defs.CustomActionType;
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;
import info.nightscout.androidaps.plugins.general.overview.notifications.Notification;
@ -108,8 +110,6 @@ import info.nightscout.androidaps.utils.rx.AapsSchedulers;
import info.nightscout.androidaps.utils.sharedPreferences.SP;
import io.reactivex.disposables.CompositeDisposable;
import static info.nightscout.androidaps.plugins.pump.omnipod.eros.driver.definition.OmnipodConstants.BASAL_STEP_DURATION;
/**
* Created by andy on 23.04.18.
*
@ -141,8 +141,9 @@ public class OmnipodErosPumpPlugin extends PumpPluginBase implements PumpInterfa
private final PumpDescription pumpDescription;
private final ServiceConnection serviceConnection;
private final PumpType pumpType = PumpType.OMNIPOD_EROS;
private final CompositeDisposable disposables = new CompositeDisposable();
private final NSUpload nsUpload;
private final AppRepository repository;
private final CompositeDisposable disposable = new CompositeDisposable();
// variables for handling statuses and history
private boolean firstRun = true;
@ -177,7 +178,7 @@ public class OmnipodErosPumpPlugin extends PumpPluginBase implements PumpInterfa
RileyLinkUtil rileyLinkUtil,
OmnipodAlertUtil omnipodAlertUtil,
ProfileFunction profileFunction,
NSUpload nsUpload
AppRepository repository
) {
super(new PluginDescription() //
.mainType(PluginType.PUMP) //
@ -204,7 +205,7 @@ public class OmnipodErosPumpPlugin extends PumpPluginBase implements PumpInterfa
this.rileyLinkUtil = rileyLinkUtil;
this.omnipodAlertUtil = omnipodAlertUtil;
this.profileFunction = profileFunction;
this.nsUpload = nsUpload;
this.repository = repository;
pumpDescription = new PumpDescription(pumpType);
@ -283,32 +284,32 @@ public class OmnipodErosPumpPlugin extends PumpPluginBase implements PumpInterfa
Intent intent = new Intent(context, RileyLinkOmnipodService.class);
context.bindService(intent, serviceConnection, Context.BIND_AUTO_CREATE);
disposables.add(rxBus
disposable.add(rxBus
.toObservable(EventAppExit.class)
.observeOn(aapsSchedulers.getIo())
.subscribe(event -> context.unbindService(serviceConnection), fabricPrivacy::logException)
);
disposables.add(rxBus
disposable.add(rxBus
.toObservable(EventOmnipodErosTbrChanged.class)
.observeOn(aapsSchedulers.getIo())
.subscribe(event -> handleCancelledTbr(), fabricPrivacy::logException)
);
disposables.add(rxBus
disposable.add(rxBus
.toObservable(EventOmnipodErosUncertainTbrRecovered.class)
.observeOn(aapsSchedulers.getIo())
.subscribe(event -> handleUncertainTbrRecovery(), fabricPrivacy::logException)
);
disposables.add(rxBus
disposable.add(rxBus
.toObservable(EventOmnipodErosActiveAlertsChanged.class)
.observeOn(aapsSchedulers.getIo())
.subscribe(event -> handleActivePodAlerts(), fabricPrivacy::logException)
);
disposables.add(rxBus
disposable.add(rxBus
.toObservable(EventOmnipodErosFaultEventChanged.class)
.observeOn(aapsSchedulers.getIo())
.subscribe(event -> handlePodFaultEvent(), fabricPrivacy::logException)
);
disposables.add(rxBus
disposable.add(rxBus
.toObservable(EventPreferenceChange.class)
.observeOn(aapsSchedulers.getIo())
.subscribe(event -> {
@ -337,7 +338,7 @@ public class OmnipodErosPumpPlugin extends PumpPluginBase implements PumpInterfa
}
}, fabricPrivacy::logException)
);
disposables.add(rxBus
disposable.add(rxBus
.toObservable(EventAppInitialized.class)
.observeOn(aapsSchedulers.getIo())
.subscribe(event -> {
@ -407,7 +408,7 @@ public class OmnipodErosPumpPlugin extends PumpPluginBase implements PumpInterfa
String notificationText = resourceHelper.gq(R.plurals.omnipod_common_pod_alerts, activeAlerts.size(), alerts);
Notification notification = new Notification(Notification.OMNIPOD_POD_ALERTS, notificationText, Notification.URGENT);
rxBus.send(new EventNewNotification(notification));
nsUpload.uploadError(notificationText);
disposable.add(repository.runTransaction(new InsertTherapyEventAnnouncementTransaction(notificationText)).subscribe());
if (aapsOmnipodErosManager.isAutomaticallyAcknowledgeAlertsEnabled() && !getCommandQueue().isCustomCommandInQueue(CommandAcknowledgeAlerts.class)) {
queueAcknowledgeAlertsCommand();
@ -419,7 +420,7 @@ public class OmnipodErosPumpPlugin extends PumpPluginBase implements PumpInterfa
private void handlePodFaultEvent() {
if (podStateManager.isPodFaulted()) {
String notificationText = resourceHelper.gs(R.string.omnipod_common_pod_status_pod_fault_description, podStateManager.getFaultEventCode().getValue(), podStateManager.getFaultEventCode().name());
nsUpload.uploadError(notificationText);
disposable.add(repository.runTransaction(new InsertTherapyEventAnnouncementTransaction(notificationText)).subscribe());
}
}
@ -432,7 +433,7 @@ public class OmnipodErosPumpPlugin extends PumpPluginBase implements PumpInterfa
context.unbindService(serviceConnection);
disposables.clear();
disposable.clear();
}
private void queueAcknowledgeAlertsCommand() {

View file

@ -31,7 +31,6 @@ import info.nightscout.androidaps.interfaces.DatabaseHelperInterface;
import info.nightscout.androidaps.logging.AAPSLogger;
import info.nightscout.androidaps.logging.LTag;
import info.nightscout.androidaps.plugins.bus.RxBusWrapper;
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;
import info.nightscout.androidaps.plugins.general.overview.events.EventOverviewBolusProgress;
@ -103,7 +102,6 @@ public class AapsOmnipodErosManager {
private final OmnipodManager delegate;
private final DatabaseHelperInterface databaseHelper;
private final OmnipodAlertUtil omnipodAlertUtil;
private final NSUpload nsUpload;
private final Context context;
private final AppRepository repository;
@ -137,7 +135,6 @@ public class AapsOmnipodErosManager {
ActivePluginProvider activePlugin,
DatabaseHelperInterface databaseHelper,
OmnipodAlertUtil omnipodAlertUtil,
NSUpload nsUpload,
Context context,
AppRepository repository) {
@ -151,7 +148,6 @@ public class AapsOmnipodErosManager {
this.activePlugin = activePlugin;
this.databaseHelper = databaseHelper;
this.omnipodAlertUtil = omnipodAlertUtil;
this.nsUpload = nsUpload;
this.context = context;
this.repository = repository;
@ -1007,7 +1003,7 @@ public class AapsOmnipodErosManager {
if (repository.getTherapyEventByTimestamp(event, date) != null) return;
disposable.add(repository.runTransactionForResult(new InsertTherapyEventIfNewTransaction(date, event, 0, null, sp.getString("careportal_enteredby", "AndroidAPS"), null, null, TherapyEvent.GlucoseUnit.MGDL))
.subscribe(
result -> result.getInserted().forEach(nsUpload::uploadEvent),
result -> result.getInserted().forEach(record -> aapsLogger.debug(LTag.DATABASE, "Inserted therapy event " + record)),
error -> aapsLogger.error(LTag.DATABASE, "Error while saving therapy event", error)
));
}