Merge branch 'dev' into bug423_historyProblem

This commit is contained in:
Andy Rozman 2021-03-28 20:45:19 +01:00
commit e3a75a55eb
250 changed files with 9053 additions and 3017 deletions

View file

@ -111,7 +111,7 @@ android {
defaultConfig {
multiDexEnabled true
versionCode 1500
version "2.8.2.1-dev-d"
version "2.8.2.1-dev-e"
buildConfigField "String", "VERSION", '"' + version + '"'
buildConfigField "String", "BUILDVERSION", '"' + generateGitBuild() + '-' + generateDate() + '"'
buildConfigField "String", "REMOTE", '"' + generateGitRemote() + '"'

View file

@ -295,7 +295,7 @@ class MainActivity : NoSplashAppCompatActivity() {
R.id.nav_about -> {
var message = "Build: ${BuildConfig.BUILDVERSION}\n"
message += "Flavor: ${BuildConfig.FLAVOR}${BuildConfig.BUILD_TYPE}\n"
message += "${resourceHelper.gs(R.string.configbuilder_nightscoutversion_label)} ${nsSettingsStatus.nightscoutVersionName}"
message += "${resourceHelper.gs(R.string.configbuilder_nightscoutversion_label)} ${nsSettingsStatus.getVersion()}"
if (buildHelper.isEngineeringMode()) message += "\n${resourceHelper.gs(R.string.engineering_mode_enabled)}"
if (!fabricPrivacy.fabricEnabled()) message += "\n${resourceHelper.gs(R.string.fabric_upload_disabled)}"
message += resourceHelper.gs(R.string.about_link_urls)

View file

@ -5,7 +5,6 @@ import android.content.Intent
import android.content.IntentFilter
import android.net.ConnectivityManager
import android.net.wifi.WifiManager
import androidx.localbroadcastmanager.content.LocalBroadcastManager
import com.j256.ormlite.android.apptools.OpenHelperManager
import dagger.android.AndroidInjector
import dagger.android.DaggerApplication
@ -24,11 +23,9 @@ import info.nightscout.androidaps.plugins.constraints.versionChecker.VersionChec
import info.nightscout.androidaps.plugins.general.nsclient.NSUpload
import info.nightscout.androidaps.receivers.BTReceiver
import info.nightscout.androidaps.receivers.ChargingStateReceiver
import info.nightscout.androidaps.receivers.DataReceiver
import info.nightscout.androidaps.receivers.KeepAliveReceiver.KeepAliveManager
import info.nightscout.androidaps.receivers.NetworkChangeReceiver
import info.nightscout.androidaps.receivers.TimeDateOrTZChangeReceiver
import info.nightscout.androidaps.services.Intents
import info.nightscout.androidaps.utils.ActivityMonitor
import info.nightscout.androidaps.utils.locale.LocaleHelper.update
import info.nightscout.androidaps.utils.sharedPreferences.SP
@ -102,15 +99,6 @@ class MainApp : DaggerApplication() {
private fun registerLocalBroadcastReceiver() {
var filter = IntentFilter()
filter.addAction(Intents.ACTION_NEW_TREATMENT)
filter.addAction(Intents.ACTION_CHANGED_TREATMENT)
filter.addAction(Intents.ACTION_REMOVED_TREATMENT)
filter.addAction(Intents.ACTION_NEW_SGV)
filter.addAction(Intents.ACTION_NEW_PROFILE)
filter.addAction(Intents.ACTION_NEW_MBG)
filter.addAction(Intents.ACTION_NEW_CAL)
LocalBroadcastManager.getInstance(this).registerReceiver(DataReceiver(), filter)
filter = IntentFilter()
filter.addAction(Intent.ACTION_TIME_CHANGED)
filter.addAction(Intent.ACTION_TIMEZONE_CHANGED)
registerReceiver(TimeDateOrTZChangeReceiver(), filter)

View file

@ -2,6 +2,7 @@ package info.nightscout.androidaps.activities
import android.os.Bundle
import info.nightscout.androidaps.R
import info.nightscout.androidaps.database.entities.UserEntry.*
import info.nightscout.androidaps.databinding.ActivityStatsBinding
import info.nightscout.androidaps.logging.UserEntryLogger
import info.nightscout.androidaps.utils.ActivityMonitor
@ -31,7 +32,7 @@ class StatsActivity : NoSplashAppCompatActivity() {
binding.ok.setOnClickListener { finish() }
binding.reset.setOnClickListener {
OKDialog.showConfirmation(this, resourceHelper.gs(R.string.doyouwantresetstats)) {
uel.log("STATS RESET")
uel.log(Action.STAT_RESET)
activityMonitor.reset()
recreate()
}

View file

@ -1,9 +1,11 @@
package info.nightscout.androidaps.db
import info.nightscout.androidaps.database.AppRepository
import info.nightscout.androidaps.database.entities.Food
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.events.EventFoodDatabaseChanged
import info.nightscout.androidaps.events.EventNewBG
import info.nightscout.androidaps.events.EventTempTargetChange
import info.nightscout.androidaps.events.EventTherapyEventChange
@ -44,5 +46,9 @@ class CompatDBHelper @Inject constructor(
aapsLogger.debug(LTag.DATABASE, "Firing EventTherapyEventChange")
rxBus.send(EventTherapyEventChange())
}
it.filterIsInstance<Food>().firstOrNull()?.let {
aapsLogger.debug(LTag.DATABASE, "Firing EventFoodDatabaseChanged")
rxBus.send(EventFoodDatabaseChanged())
}
}
}

View file

@ -67,6 +67,8 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
@Inject RxBusWrapper rxBus;
@Inject VirtualPumpPlugin virtualPumpPlugin;
@Inject OpenHumansUploader openHumansUploader;
@Inject ActivePluginProvider activePlugin;
@Inject NSUpload nsUpload;
public static final String DATABASE_NAME = "AndroidAPSDb";
public static final String DATABASE_EXTENDEDBOLUSES = "ExtendedBoluses";
@ -1216,7 +1218,7 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
}
*/
public void createProfileSwitchFromJsonIfNotExists(ActivePluginProvider activePluginProvider, NSUpload nsUpload, JSONObject trJson) {
public void createProfileSwitchFromJsonIfNotExists(JSONObject trJson) {
try {
ProfileSwitch profileSwitch = new ProfileSwitch(StaticInjector.Companion.getInstance());
profileSwitch.date = trJson.getLong("mills");
@ -1233,7 +1235,7 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
if (trJson.has("profileJson"))
profileSwitch.profileJson = trJson.getString("profileJson");
else {
ProfileInterface profileInterface = activePluginProvider.getActiveProfileInterface();
ProfileInterface profileInterface = activePlugin.getActiveProfileInterface();
ProfileStore store = profileInterface.getProfile();
if (store != null) {
Profile profile = store.getSpecificProfile(profileSwitch.profileName);

View file

@ -14,9 +14,7 @@ import javax.inject.Inject;
import javax.inject.Singleton;
import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.interfaces.ActivePluginProvider;
import info.nightscout.androidaps.interfaces.DatabaseHelperInterface;
import info.nightscout.androidaps.plugins.general.nsclient.NSUpload;
@Singleton
public class DatabaseHelperProvider implements DatabaseHelperInterface {
@ -172,8 +170,8 @@ public class DatabaseHelperProvider implements DatabaseHelperInterface {
MainApp.Companion.getDbHelper().createExtendedBolusFromJsonIfNotExists(json);
}
@Override public void createProfileSwitchFromJsonIfNotExists(@NonNull ActivePluginProvider activePluginProvider, @NonNull NSUpload nsUpload, @NonNull JSONObject trJson) {
MainApp.Companion.getDbHelper().createProfileSwitchFromJsonIfNotExists(activePluginProvider, nsUpload, trJson);
@Override public void createProfileSwitchFromJsonIfNotExists(@NonNull JSONObject trJson) {
MainApp.Companion.getDbHelper().createProfileSwitchFromJsonIfNotExists(trJson);
}
@Override public void resetDatabases() {

View file

@ -10,7 +10,9 @@ import info.nightscout.androidaps.Config
import info.nightscout.androidaps.MainApp
import info.nightscout.androidaps.db.DatabaseHelperProvider
import info.nightscout.androidaps.interfaces.*
import info.nightscout.androidaps.logging.AAPSLogger
import info.nightscout.androidaps.plugins.aps.loop.LoopPlugin
import info.nightscout.androidaps.plugins.bus.RxBusWrapper
import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin
import info.nightscout.androidaps.plugins.configBuilder.PluginStore
import info.nightscout.androidaps.plugins.general.maintenance.ImportExportPrefs
@ -23,10 +25,10 @@ import info.nightscout.androidaps.utils.androidNotification.NotificationHolder
import info.nightscout.androidaps.utils.resources.IconsProvider
import info.nightscout.androidaps.utils.rx.AapsSchedulers
import info.nightscout.androidaps.utils.rx.DefaultAapsSchedulers
import info.nightscout.androidaps.utils.sharedPreferences.SP
import info.nightscout.androidaps.utils.storage.FileStorage
import info.nightscout.androidaps.utils.storage.Storage
import javax.inject.Singleton
@Module(includes = [
AppModule.AppBindings::class
])
@ -56,9 +58,18 @@ open class AppModule {
@Singleton
internal fun provideSchedulers(): AapsSchedulers = DefaultAapsSchedulers()
@Provides
@Singleton
fun providesUploadQueue(
aapsLogger: AAPSLogger,
databaseHelper: DatabaseHelperInterface,
context: Context,
sp: SP,
rxBus: RxBusWrapper
): UploadQueueAdminInterface = UploadQueue(aapsLogger, databaseHelper, context, sp, rxBus)
@Module
interface AppBindings {
@Binds fun bindContext(mainApp: MainApp): Context
@Binds fun bindInjector(mainApp: MainApp): HasAndroidInjector
@Binds fun bindActivePluginProvider(pluginStore: PluginStore): ActivePluginProvider
@ -67,12 +78,13 @@ open class AppModule {
@Binds fun bindConfigBuilderInterface(configBuilderPlugin: ConfigBuilderPlugin): ConfigBuilderInterface
@Binds fun bindTreatmentInterface(treatmentsPlugin: TreatmentsPlugin): TreatmentsInterface
@Binds fun bindDatabaseHelperInterface(databaseHelperProvider: DatabaseHelperProvider): DatabaseHelperInterface
@Binds fun bindUploadQueueInterface(uploadQueue: UploadQueue): UploadQueueInterface
@Binds fun bindNotificationHolderInterface(notificationHolder: NotificationHolder): NotificationHolderInterface
@Binds fun bindImportExportPrefsInterface(importExportPrefs: ImportExportPrefs): ImportExportPrefsInterface
@Binds fun bindIconsProviderInterface(iconsProvider: IconsProvider): IconsProviderInterface
@Binds fun bindLoopInterface(loopPlugin: LoopPlugin): LoopInterface
@Binds fun bindIobCobCalculatorInterface(iobCobCalculatorPlugin: IobCobCalculatorPlugin): IobCobCalculatorInterface
@Binds fun bindSmsCommunicatorInterface(smsCommunicatorPlugin: SmsCommunicatorPlugin): SmsCommunicatorInterface
@Binds fun bindUploadQueueAdminInterfaceToUploadQueue(uploadQueueAdminInterface: UploadQueueAdminInterface) : UploadQueueInterface
}
}

View file

@ -3,7 +3,6 @@ package info.nightscout.androidaps.dependencyInjection
import dagger.Module
import dagger.android.ContributesAndroidInjector
import info.nightscout.androidaps.db.DatabaseHelper
import info.nightscout.androidaps.plugins.general.food.FoodService
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.GlucoseStatus
import info.nightscout.androidaps.plugins.treatments.TreatmentService
import info.nightscout.androidaps.utils.wizard.BolusWizard
@ -17,7 +16,6 @@ abstract class DataClassesModule {
@ContributesAndroidInjector abstract fun DatabaseHelperInjector(): DatabaseHelper
@ContributesAndroidInjector abstract fun treatmentServiceInjector(): TreatmentService
@ContributesAndroidInjector abstract fun foodServiceInjector(): FoodService
@ContributesAndroidInjector abstract fun bolusWizardInjector(): BolusWizard
@ContributesAndroidInjector abstract fun quickWizardEntryInjector(): QuickWizardEntry

View file

@ -2,7 +2,10 @@ package info.nightscout.androidaps.dependencyInjection
import dagger.Module
import dagger.android.ContributesAndroidInjector
import info.nightscout.androidaps.plugins.general.nsclient.NSClientWorker
import info.nightscout.androidaps.plugins.general.food.FoodPlugin
import info.nightscout.androidaps.plugins.general.nsclient.NSClientAddUpdateWorker
import info.nightscout.androidaps.plugins.general.nsclient.NSClientMbgWorker
import info.nightscout.androidaps.plugins.general.nsclient.NSClientRemoveWorker
import info.nightscout.androidaps.plugins.general.smsCommunicator.SmsCommunicatorPlugin
import info.nightscout.androidaps.plugins.profile.ns.NSProfilePlugin
import info.nightscout.androidaps.plugins.source.*
@ -21,5 +24,8 @@ abstract class WorkersModule {
@ContributesAndroidInjector abstract fun contributesNSClientSourceWorker(): NSClientSourcePlugin.NSClientSourceWorker
@ContributesAndroidInjector abstract fun contributesNSProfileWorker(): NSProfilePlugin.NSProfileWorker
@ContributesAndroidInjector abstract fun contributesSmsCommunicatorWorker(): SmsCommunicatorPlugin.SmsCommunicatorWorker
@ContributesAndroidInjector abstract fun contributesNSClientWorker(): NSClientWorker
@ContributesAndroidInjector abstract fun contributesNSClientWorker(): NSClientAddUpdateWorker
@ContributesAndroidInjector abstract fun contributesNSClientRemoveWorker(): NSClientRemoveWorker
@ContributesAndroidInjector abstract fun contributesNSClientMbgWorker(): NSClientMbgWorker
@ContributesAndroidInjector abstract fun contributesFoodWorker(): FoodPlugin.FoodWorker
}

View file

@ -9,10 +9,10 @@ import dagger.android.HasAndroidInjector
import info.nightscout.androidaps.Constants
import info.nightscout.androidaps.R
import info.nightscout.androidaps.data.Profile
import info.nightscout.androidaps.database.entities.UserEntry.*
import info.nightscout.androidaps.databinding.DialogCalibrationBinding
import info.nightscout.androidaps.interfaces.ProfileFunction
import info.nightscout.androidaps.logging.UserEntryLogger
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.GlucoseStatus
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.GlucoseStatusProvider
import info.nightscout.androidaps.utils.HtmlHelper
import info.nightscout.androidaps.utils.XdripCalibrations
@ -79,7 +79,7 @@ class CalibrationDialog : DialogFragmentWithDate() {
if (bg > 0) {
activity?.let { activity ->
OKDialog.showConfirmation(activity, resourceHelper.gs(R.string.overview_calibration), HtmlHelper.fromHtml(Joiner.on("<br/>").join(actions)), {
uel.log("CALIBRATION", d1 = bg)
uel.log(Action.CALIBRATION, ValueWithUnit(bg, units))
xdripCalibrations.sendIntent(bg)
})
}

View file

@ -14,6 +14,7 @@ import info.nightscout.androidaps.data.Profile
import info.nightscout.androidaps.database.AppRepository
import info.nightscout.androidaps.database.entities.TemporaryTarget
import info.nightscout.androidaps.database.entities.TherapyEvent
import info.nightscout.androidaps.database.entities.UserEntry.*
import info.nightscout.androidaps.database.transactions.InsertTemporaryTargetAndCancelCurrentTransaction
import info.nightscout.androidaps.databinding.DialogCarbsBinding
import info.nightscout.androidaps.interfaces.Constraint
@ -221,7 +222,7 @@ class CarbsDialog : DialogFragmentWithDate() {
OKDialog.showConfirmation(activity, resourceHelper.gs(R.string.carbs), HtmlHelper.fromHtml(Joiner.on("<br/>").join(actions)), {
when {
activitySelected -> {
uel.log("TT ACTIVITY", d1 = activityTT, i1 = activityTTDuration)
uel.log(Action.TT, ValueWithUnit(TemporaryTarget.Reason.ACTIVITY.text, Units.TherapyEvent), ValueWithUnit(activityTT, units) , ValueWithUnit(activityTTDuration, Units.M))
disposable += repository.runTransactionForResult(InsertTemporaryTargetAndCancelCurrentTransaction(
timestamp = System.currentTimeMillis(),
duration = TimeUnit.MINUTES.toMillis(activityTTDuration.toLong()),
@ -237,7 +238,7 @@ class CarbsDialog : DialogFragmentWithDate() {
}
eatingSoonSelected -> {
uel.log("TT EATING SOON", d1 = eatingSoonTT, i1 = eatingSoonTTDuration)
uel.log(Action.TT, ValueWithUnit(TemporaryTarget.Reason.EATING_SOON.text, Units.TherapyEvent), ValueWithUnit(eatingSoonTT, units) , ValueWithUnit(eatingSoonTTDuration, Units.M))
disposable += repository.runTransactionForResult(InsertTemporaryTargetAndCancelCurrentTransaction(
timestamp = System.currentTimeMillis(),
duration = TimeUnit.MINUTES.toMillis(eatingSoonTTDuration.toLong()),
@ -253,7 +254,7 @@ class CarbsDialog : DialogFragmentWithDate() {
}
hypoSelected -> {
uel.log("TT HYPO", d1 = hypoTT, i1 = hypoTTDuration)
uel.log(Action.TT, ValueWithUnit(TemporaryTarget.Reason.HYPOGLYCEMIA.text, Units.TherapyEvent), ValueWithUnit(hypoTT, units) , ValueWithUnit(hypoTTDuration, Units.M))
disposable += repository.runTransactionForResult(InsertTemporaryTargetAndCancelCurrentTransaction(
timestamp = System.currentTimeMillis(),
duration = TimeUnit.MINUTES.toMillis(hypoTTDuration.toLong()),
@ -270,13 +271,12 @@ class CarbsDialog : DialogFragmentWithDate() {
}
if (carbsAfterConstraints > 0) {
if (duration == 0) {
uel.log("CARBS", d1 = carbsAfterConstraints.toDouble(), i1 = timeOffset)
carbsGenerator.createCarb(carbsAfterConstraints, time, TherapyEvent.Type.CARBS_CORRECTION.text, notes)
} else {
uel.log("CARBS", d1 = carbsAfterConstraints.toDouble(), i1 = timeOffset, i2 = duration)
carbsGenerator.generateCarbs(carbsAfterConstraints, time, duration, notes)
nsUpload.uploadEvent(TherapyEvent.Type.NOTE.text, DateUtil.now() - 2000, resourceHelper.gs(R.string.generated_ecarbs_note, carbsAfterConstraints, duration, timeOffset))
}
uel.log(Action.CARBS, notes, ValueWithUnit(eventTime, Units.Timestamp, eventTimeChanged), ValueWithUnit(carbsAfterConstraints, Units.G), ValueWithUnit(timeOffset, Units.M, timeOffset != 0), ValueWithUnit(duration, Units.H, duration != 0))
}
if (useAlarm && carbs > 0 && timeOffset > 0) {
carbTimer.scheduleReminder(dateUtil._now() + T.mins(timeOffset.toLong()).msecs())

View file

@ -16,6 +16,7 @@ import info.nightscout.androidaps.data.Profile
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.entities.UserEntry.*
import info.nightscout.androidaps.databinding.DialogCareBinding
import info.nightscout.androidaps.interfaces.ProfileFunction
import info.nightscout.androidaps.logging.LTag
@ -59,6 +60,7 @@ class CareDialog : DialogFragmentWithDate() {
}
private var options: EventType = EventType.BGCHECK
private var valuesWithUnit = mutableListOf<ValueWithUnit>()
@StringRes
private var event: Int = R.string.none
@ -200,10 +202,13 @@ class CareDialog : DialogFragmentWithDate() {
actions.add(resourceHelper.gs(R.string.treatments_wizard_bg_label) + ": " + Profile.toCurrentUnitsString(profileFunction, binding.bg.value) + " " + resourceHelper.gs(unitResId))
therapyEvent.glucoseType = meterType
therapyEvent.glucose = binding.bg.value
valuesWithUnit.add(ValueWithUnit(binding.bg.value.toDouble(), profileFunction.getUnits()))
valuesWithUnit.add(ValueWithUnit(meterType.text, Units.TherapyEvent))
}
if (options == EventType.NOTE || options == EventType.EXERCISE) {
actions.add(resourceHelper.gs(R.string.careportal_newnstreatment_duration_label) + ": " + resourceHelper.gs(R.string.format_mins, binding.duration.value.toInt()))
therapyEvent.duration = T.mins(binding.duration.value.toLong()).msecs()
valuesWithUnit.add(ValueWithUnit(binding.duration.value.toInt(), Units.M, !binding.duration.value.equals(0.0)))
}
val notes = binding.notesLayout.notes.text.toString()
if (notes.isNotEmpty()) {
@ -211,8 +216,7 @@ class CareDialog : DialogFragmentWithDate() {
therapyEvent.note = notes
}
if (eventTimeChanged)
actions.add(resourceHelper.gs(R.string.time) + ": " + dateUtil.dateAndTimeString(eventTime))
if (eventTimeChanged) actions.add(resourceHelper.gs(R.string.time) + ": " + dateUtil.dateAndTimeString(eventTime))
therapyEvent.enteredBy = enteredBy
@ -223,8 +227,9 @@ class CareDialog : DialogFragmentWithDate() {
}, {
aapsLogger.error(LTag.BGSOURCE, "Error while saving therapy event", it)
})
uel.log("CAREPORTAL", therapyEvent.type.text)
valuesWithUnit.add(0, ValueWithUnit(eventTime, Units.Timestamp, eventTimeChanged))
valuesWithUnit.add(1, ValueWithUnit(therapyEvent.type.text, Units.TherapyEvent))
uel.log(Action.CAREPORTAL, notes, valuesWithUnit)
}, null)
}
return true

View file

@ -8,6 +8,7 @@ import android.view.ViewGroup
import com.google.common.base.Joiner
import info.nightscout.androidaps.R
import info.nightscout.androidaps.activities.ErrorHelperActivity
import info.nightscout.androidaps.database.entities.UserEntry.*
import info.nightscout.androidaps.databinding.DialogExtendedbolusBinding
import info.nightscout.androidaps.interfaces.ActivePluginProvider
import info.nightscout.androidaps.interfaces.CommandQueueProvider
@ -87,7 +88,7 @@ class ExtendedBolusDialog : DialogFragmentWithDate() {
activity?.let { activity ->
OKDialog.showConfirmation(activity, resourceHelper.gs(R.string.extended_bolus), HtmlHelper.fromHtml(Joiner.on("<br/>").join(actions)), {
uel.log("EXTENDED BOLUS", d1 = insulinAfterConstraint, i1 = durationInMinutes)
uel.log(Action.EXTENDED_BOLUS, ValueWithUnit(insulinAfterConstraint, Units.U), ValueWithUnit(durationInMinutes, Units.M))
commandQueue.extendedBolus(insulinAfterConstraint, durationInMinutes, object : Callback() {
override fun run() {
if (!result.success) {

View file

@ -12,6 +12,7 @@ import info.nightscout.androidaps.data.DetailedBolusInfo
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.entities.UserEntry.*
import info.nightscout.androidaps.databinding.DialogFillBinding
import info.nightscout.androidaps.db.Source
import info.nightscout.androidaps.interfaces.ActivePluginProvider
@ -135,11 +136,11 @@ class FillDialog : DialogFragmentWithDate() {
activity?.let { activity ->
OKDialog.showConfirmation(activity, resourceHelper.gs(R.string.primefill), HtmlHelper.fromHtml(Joiner.on("<br/>").join(actions)), {
if (insulinAfterConstraints > 0) {
uel.log("PRIME BOLUS", d1 = insulinAfterConstraints)
uel.log(Action.PRIME_BOLUS, notes, ValueWithUnit(insulinAfterConstraints, Units.U, insulinAfterConstraints != 0.0))
requestPrimeBolus(insulinAfterConstraints, notes)
}
if (siteChange) {
uel.log("SITE CHANGE")
uel.log(Action.CAREPORTAL, notes, ValueWithUnit(TherapyEvent.Type.CANNULA_CHANGE.text, Units.TherapyEvent))
disposable += repository.runTransactionForResult(InsertTherapyEventIfNewTransaction(
timestamp = eventTime,
type = TherapyEvent.Type.CANNULA_CHANGE,
@ -153,7 +154,7 @@ class FillDialog : DialogFragmentWithDate() {
}
if (insulinChange) {
// add a second for case of both checked
uel.log("INSULIN CHANGE")
uel.log(Action.CAREPORTAL, notes, ValueWithUnit(TherapyEvent.Type.INSULIN_CHANGE.text, Units.TherapyEvent))
disposable += repository.runTransactionForResult(InsertTherapyEventIfNewTransaction(
timestamp = eventTime + 1000,
type = TherapyEvent.Type.INSULIN_CHANGE,

View file

@ -17,6 +17,7 @@ import info.nightscout.androidaps.data.Profile
import info.nightscout.androidaps.database.AppRepository
import info.nightscout.androidaps.database.entities.TemporaryTarget
import info.nightscout.androidaps.database.entities.TherapyEvent
import info.nightscout.androidaps.database.entities.UserEntry.*
import info.nightscout.androidaps.database.transactions.InsertTemporaryTargetAndCancelCurrentTransaction
import info.nightscout.androidaps.databinding.DialogInsulinBinding
import info.nightscout.androidaps.db.Source
@ -188,7 +189,7 @@ class InsulinDialog : DialogFragmentWithDate() {
activity?.let { activity ->
OKDialog.showConfirmation(activity, resourceHelper.gs(R.string.bolus), HtmlHelper.fromHtml(Joiner.on("<br/>").join(actions)), {
if (eatingSoonChecked) {
uel.log("TT EATING SOON", d1 = eatingSoonTT, i1 = eatingSoonTTDuration)
uel.log(Action.TT, notes, ValueWithUnit(TemporaryTarget.Reason.EATING_SOON.text, Units.TherapyEvent), ValueWithUnit(eatingSoonTT, units), ValueWithUnit(eatingSoonTTDuration, Units.M))
disposable += repository.runTransactionForResult(InsertTemporaryTargetAndCancelCurrentTransaction(
timestamp = System.currentTimeMillis(),
duration = TimeUnit.MINUTES.toMillis(eatingSoonTTDuration.toLong()),
@ -210,11 +211,11 @@ class InsulinDialog : DialogFragmentWithDate() {
detailedBolusInfo.source = Source.USER
detailedBolusInfo.notes = notes
if (recordOnlyChecked) {
uel.log("BOLUS RECORD", d1 = insulinAfterConstraints, i1 = timeOffset)
uel.log(Action.BOLUS_RECORD, notes, ValueWithUnit(insulinAfterConstraints, Units.U), ValueWithUnit(timeOffset, Units.M, timeOffset!= 0))
detailedBolusInfo.date = time
activePlugin.activeTreatments.addToHistoryTreatment(detailedBolusInfo, false)
} else {
uel.log("BOLUS", d1 = insulinAfterConstraints)
uel.log(Action.BOLUS, notes, ValueWithUnit(insulinAfterConstraints, Units.U))
detailedBolusInfo.date = DateUtil.now()
commandQueue.bolus(detailedBolusInfo, object : Callback() {
override fun run() {

View file

@ -12,6 +12,7 @@ import androidx.fragment.app.FragmentManager
import dagger.android.support.DaggerDialogFragment
import info.nightscout.androidaps.R
import info.nightscout.androidaps.activities.ErrorHelperActivity
import info.nightscout.androidaps.database.entities.UserEntry.*
import info.nightscout.androidaps.databinding.DialogLoopBinding
import info.nightscout.androidaps.events.EventPreferenceChange
import info.nightscout.androidaps.events.EventRefreshOverview
@ -238,28 +239,28 @@ class LoopDialog : DaggerDialogFragment() {
val profile = profileFunction.getProfile() ?: return true
when (v.id) {
R.id.overview_closeloop -> {
uel.log("CLOSED LOOP MODE")
uel.log(Action.CLOSED_LOOP_MODE)
sp.putString(R.string.key_aps_mode, "closed")
rxBus.send(EventPreferenceChange(resourceHelper.gs(R.string.closedloop)))
return true
}
R.id.overview_lgsloop -> {
uel.log("LGS LOOP MODE")
uel.log(Action.LGS_LOOP_MODE)
sp.putString(R.string.key_aps_mode, "lgs")
rxBus.send(EventPreferenceChange(resourceHelper.gs(R.string.lowglucosesuspend)))
return true
}
R.id.overview_openloop -> {
uel.log("OPEN LOOP MODE")
uel.log(Action.OPEN_LOOP_MODE)
sp.putString(R.string.key_aps_mode, "open")
rxBus.send(EventPreferenceChange(resourceHelper.gs(R.string.lowglucosesuspend)))
return true
}
R.id.overview_disable -> {
uel.log("LOOP DISABLED")
uel.log(Action.LOOP_DISABLED)
loopPlugin.setPluginEnabled(PluginType.LOOP, false)
loopPlugin.setFragmentVisible(PluginType.LOOP, false)
configBuilderPlugin.storeSettings("DisablingLoop")
@ -276,7 +277,7 @@ class LoopDialog : DaggerDialogFragment() {
}
R.id.overview_enable -> {
uel.log("LOOP ENABLED")
uel.log(Action.LOOP_ENABLED)
loopPlugin.setPluginEnabled(PluginType.LOOP, true)
loopPlugin.setFragmentVisible(PluginType.LOOP, true)
configBuilderPlugin.storeSettings("EnablingLoop")
@ -286,7 +287,7 @@ class LoopDialog : DaggerDialogFragment() {
}
R.id.overview_resume, R.id.overview_reconnect -> {
uel.log("RESUME")
uel.log(if (v.id==R.id.overview_resume) Action.RESUME else Action.RECONNECT )
loopPlugin.suspendTo(0L)
rxBus.send(EventRefreshOverview("suspendmenu"))
commandQueue.cancelTempBasal(true, object : Callback() {
@ -302,49 +303,49 @@ class LoopDialog : DaggerDialogFragment() {
}
R.id.overview_suspend_1h -> {
uel.log("SUSPEND 1h")
uel.log(Action.SUSPEND, ValueWithUnit(1, Units.H))
loopPlugin.suspendLoop(60)
rxBus.send(EventRefreshOverview("suspendmenu"))
return true
}
R.id.overview_suspend_2h -> {
uel.log("SUSPEND 2h")
uel.log(Action.SUSPEND, ValueWithUnit(2, Units.H))
loopPlugin.suspendLoop(120)
rxBus.send(EventRefreshOverview("suspendmenu"))
return true
}
R.id.overview_suspend_3h -> {
uel.log("SUSPEND 3h")
uel.log(Action.SUSPEND, ValueWithUnit(3, Units.H))
loopPlugin.suspendLoop(180)
rxBus.send(EventRefreshOverview("suspendmenu"))
return true
}
R.id.overview_suspend_10h -> {
uel.log("SUSPEND 10h")
uel.log(Action.SUSPEND, ValueWithUnit(10, Units.H))
loopPlugin.suspendLoop(600)
rxBus.send(EventRefreshOverview("suspendmenu"))
return true
}
R.id.overview_disconnect_15m -> {
uel.log("DISCONNECT 15m")
uel.log(Action.DISCONNECT, ValueWithUnit(15, Units.M))
loopPlugin.disconnectPump(15, profile)
rxBus.send(EventRefreshOverview("suspendmenu"))
return true
}
R.id.overview_disconnect_30m -> {
uel.log("DISCONNECT 30m")
uel.log(Action.DISCONNECT, ValueWithUnit(30, Units.M))
loopPlugin.disconnectPump(30, profile)
rxBus.send(EventRefreshOverview("suspendmenu"))
return true
}
R.id.overview_disconnect_1h -> {
uel.log("DISCONNECT 1h")
uel.log(Action.DISCONNECT, ValueWithUnit(1, Units.H))
loopPlugin.disconnectPump(60, profile)
sp.putBoolean(R.string.key_objectiveusedisconnect, true)
rxBus.send(EventRefreshOverview("suspendmenu"))
@ -352,14 +353,14 @@ class LoopDialog : DaggerDialogFragment() {
}
R.id.overview_disconnect_2h -> {
uel.log("DISCONNECT 2h")
uel.log(Action.DISCONNECT, ValueWithUnit(2, Units.H))
loopPlugin.disconnectPump(120, profile)
rxBus.send(EventRefreshOverview("suspendmenu"))
return true
}
R.id.overview_disconnect_3h -> {
uel.log("DISCONNECT 3h")
uel.log(Action.DISCONNECT, ValueWithUnit(3, Units.H))
loopPlugin.disconnectPump(180, profile)
rxBus.send(EventRefreshOverview("suspendmenu"))
return true

View file

@ -8,6 +8,7 @@ import android.widget.ArrayAdapter
import com.google.common.base.Joiner
import info.nightscout.androidaps.Constants
import info.nightscout.androidaps.R
import info.nightscout.androidaps.database.entities.UserEntry.*
import info.nightscout.androidaps.databinding.DialogProfileswitchBinding
import info.nightscout.androidaps.interfaces.ActivePluginProvider
import info.nightscout.androidaps.interfaces.ProfileFunction
@ -124,7 +125,7 @@ class ProfileSwitchDialog : DialogFragmentWithDate() {
activity?.let { activity ->
OKDialog.showConfirmation(activity, resourceHelper.gs(R.string.careportal_profileswitch), HtmlHelper.fromHtml(Joiner.on("<br/>").join(actions)), {
uel.log("PROFILE SWITCH", d1 = percent.toDouble(), i1 = timeShift, i2 = duration)
uel.log(Action.PROFILE_SWITCH, notes, ValueWithUnit(eventTime, Units.Timestamp, eventTimeChanged), ValueWithUnit(profile, Units.None), ValueWithUnit(percent, Units.Percent), ValueWithUnit(timeShift, Units.H, timeShift != 0), ValueWithUnit(duration, Units.M, duration != 0))
treatmentsPlugin.doProfileSwitch(profileStore, profile, duration, percent, timeShift, eventTime)
})
}

View file

@ -8,6 +8,7 @@ import android.view.ViewGroup
import com.google.common.base.Joiner
import info.nightscout.androidaps.R
import info.nightscout.androidaps.activities.ErrorHelperActivity
import info.nightscout.androidaps.database.entities.UserEntry.*
import info.nightscout.androidaps.databinding.DialogTempbasalBinding
import info.nightscout.androidaps.interfaces.ActivePluginProvider
import info.nightscout.androidaps.interfaces.CommandQueueProvider
@ -125,10 +126,10 @@ class TempBasalDialog : DialogFragmentWithDate() {
}
}
if (isPercentPump) {
uel.log("TEMP BASAL", d1 = percent.toDouble(), i1 = durationInMinutes)
uel.log(Action.TEMP_BASAL, ValueWithUnit(percent, Units.Percent), ValueWithUnit(durationInMinutes, Units.M))
commandQueue.tempBasalPercent(percent, durationInMinutes, true, profile, callback)
} else {
uel.log("TEMP BASAL", d1 = absolute, i1 = durationInMinutes)
uel.log(Action.TEMP_BASAL, ValueWithUnit(absolute, Units.U), ValueWithUnit(durationInMinutes, Units.M))
commandQueue.tempBasalAbsolute(absolute, durationInMinutes, true, profile, callback)
}
})

View file

@ -13,6 +13,7 @@ import info.nightscout.androidaps.data.Profile
import info.nightscout.androidaps.database.AppRepository
import info.nightscout.androidaps.database.ValueWrapper
import info.nightscout.androidaps.database.entities.TemporaryTarget
import info.nightscout.androidaps.database.entities.UserEntry.*
import info.nightscout.androidaps.database.transactions.CancelCurrentTemporaryTargetIfAnyTransaction
import info.nightscout.androidaps.database.transactions.InsertTemporaryTargetAndCancelCurrentTransaction
import info.nightscout.androidaps.databinding.DialogTemptargetBinding
@ -145,6 +146,10 @@ class TempTargetDialog : DialogFragmentWithDate() {
binding.duration.value = defaultValueHelper.determineHypoTTDuration().toDouble()
binding.reason.setSelection(reasonList.indexOf(resourceHelper.gs(R.string.hypo)))
}
R.id.cancel -> {
binding.duration.value = 0.0
}
}
}
@ -157,7 +162,7 @@ class TempTargetDialog : DialogFragmentWithDate() {
override fun submit(): Boolean {
if (_binding == null) return false
val actions: LinkedList<String> = LinkedList()
val reason = binding.reason.selectedItem?.toString() ?: return false
var reason = binding.reason.selectedItem?.toString() ?: return false
val unitResId = if (profileFunction.getUnits() == Constants.MGDL) R.string.mgdl else R.string.mmol
val target = binding.temptarget.value
val duration = binding.duration.value.toInt()
@ -167,13 +172,21 @@ class TempTargetDialog : DialogFragmentWithDate() {
actions.add(resourceHelper.gs(R.string.duration) + ": " + resourceHelper.gs(R.string.format_mins, duration))
} else {
actions.add(resourceHelper.gs(R.string.stoptemptarget))
reason = resourceHelper.gs(R.string.stoptemptarget)
}
if (eventTimeChanged)
actions.add(resourceHelper.gs(R.string.time) + ": " + dateUtil.dateAndTimeString(eventTime))
activity?.let { activity ->
OKDialog.showConfirmation(activity, resourceHelper.gs(R.string.careportal_temporarytarget), HtmlHelper.fromHtml(Joiner.on("<br/>").join(actions)), {
uel.log("TT", d1 = target, i1 = duration)
val units = profileFunction.getUnits()
when(reason) {
resourceHelper.gs(R.string.eatingsoon) -> uel.log(Action.TT, ValueWithUnit(eventTime, Units.Timestamp, eventTimeChanged), ValueWithUnit(TemporaryTarget.Reason.EATING_SOON.text, Units.TherapyEvent), ValueWithUnit(target, units), ValueWithUnit(duration, Units.M))
resourceHelper.gs(R.string.activity) -> uel.log(Action.TT, ValueWithUnit(eventTime, Units.Timestamp, eventTimeChanged), ValueWithUnit(TemporaryTarget.Reason.ACTIVITY.text, Units.TherapyEvent), ValueWithUnit(target, units), ValueWithUnit(duration, Units.M))
resourceHelper.gs(R.string.hypo) -> uel.log(Action.TT, ValueWithUnit(eventTime, Units.Timestamp, eventTimeChanged), ValueWithUnit(TemporaryTarget.Reason.HYPOGLYCEMIA.text, Units.TherapyEvent), ValueWithUnit(target, units), ValueWithUnit(duration, Units.M))
resourceHelper.gs(R.string.manual) -> uel.log(Action.TT, ValueWithUnit(eventTime, Units.Timestamp, eventTimeChanged), ValueWithUnit(TemporaryTarget.Reason.CUSTOM.text, Units.TherapyEvent), ValueWithUnit(target, units), ValueWithUnit(duration, Units.M))
resourceHelper.gs(R.string.stoptemptarget) -> uel.log(Action.CANCEL_TT, ValueWithUnit(eventTime, Units.Timestamp, eventTimeChanged))
}
if (target == 0.0 || duration == 0) {
disposable += repository.runTransactionForResult(CancelCurrentTemporaryTargetIfAnyTransaction(eventTime))
.subscribe({ result ->
@ -200,6 +213,7 @@ class TempTargetDialog : DialogFragmentWithDate() {
aapsLogger.error(LTag.BGSOURCE, "Error while saving temporary target", it)
})
}
if (duration == 10) sp.putBoolean(R.string.key_objectiveusetemptarget, true)
})
}

View file

@ -13,6 +13,7 @@ import info.nightscout.androidaps.R
import info.nightscout.androidaps.activities.ErrorHelperActivity
import info.nightscout.androidaps.data.DetailedBolusInfo
import info.nightscout.androidaps.database.entities.TherapyEvent
import info.nightscout.androidaps.database.entities.UserEntry.*
import info.nightscout.androidaps.databinding.DialogTreatmentBinding
import info.nightscout.androidaps.db.Source
import info.nightscout.androidaps.interfaces.ActivePluginProvider
@ -129,7 +130,7 @@ class TreatmentDialog : DialogFragmentWithDate() {
if (insulinAfterConstraints > 0 || carbsAfterConstraints > 0) {
activity?.let { activity ->
OKDialog.showConfirmation(activity, resourceHelper.gs(R.string.overview_treatment_label), HtmlHelper.fromHtml(Joiner.on("<br/>").join(actions)), {
uel.log("TREATMENT", d1 = insulin, i1 = carbs)
uel.log(Action.TREATMENT, ValueWithUnit(insulin, Units.U, insulin != 0.0), ValueWithUnit(carbs, Units.G, carbs != 0))
val detailedBolusInfo = DetailedBolusInfo()
if (insulinAfterConstraints == 0.0) detailedBolusInfo.eventType = TherapyEvent.Type.CARBS_CORRECTION.text
if (carbsAfterConstraints == 0) detailedBolusInfo.eventType = TherapyEvent.Type.CORRECTION_BOLUS.text

View file

@ -1,20 +0,0 @@
package info.nightscout.androidaps.events
import org.json.JSONArray
/**
* Event which is published with data fetched from NightScout specific for the
* Food-class.
*
* Payload is the from NS retrieved JSON-String which should be handled by all
* subscriber.
*/
class EventNsFood(val mode: Int, val foods: JSONArray) : Event() {
companion object {
val ADD = 0
val UPDATE = 1
val REMOVE = 2
}
}

View file

@ -6,10 +6,10 @@ import info.nightscout.androidaps.database.AppRepository
import info.nightscout.androidaps.interfaces.ActivePluginProvider
import info.nightscout.androidaps.interfaces.DatabaseHelperInterface
import info.nightscout.androidaps.interfaces.ProfileFunction
import info.nightscout.androidaps.interfaces.UploadQueueInterface
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.plugins.general.nsclient.UploadQueue
import info.nightscout.androidaps.plugins.treatments.TreatmentService
import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin
import info.nightscout.androidaps.utils.DateUtil
@ -34,7 +34,7 @@ class TreatmentsPluginHistory @Inject constructor(
nsUpload: NSUpload,
fabricPrivacy: FabricPrivacy,
dateUtil: DateUtil,
uploadQueue: UploadQueue,
uploadQueue: UploadQueueInterface,
databaseHelper: DatabaseHelperInterface,
repository: AppRepository
) : TreatmentsPlugin(injector, aapsLogger, rxBus, aapsSchedulers, resourceHelper, context, sp, profileFunction, activePlugin, nsUpload, fabricPrivacy, dateUtil, uploadQueue, databaseHelper, repository) {

View file

@ -3,6 +3,7 @@ package info.nightscout.androidaps.plugins.configBuilder
import androidx.fragment.app.FragmentActivity
import dagger.android.HasAndroidInjector
import info.nightscout.androidaps.R
import info.nightscout.androidaps.database.entities.UserEntry.*
import info.nightscout.androidaps.events.EventAppInitialized
import info.nightscout.androidaps.events.EventConfigBuilderChange
import info.nightscout.androidaps.events.EventRebuildTabs
@ -142,7 +143,7 @@ class ConfigBuilderPlugin @Inject constructor(
OKDialog.showConfirmation(activity, resourceHelper.gs(R.string.allow_hardware_pump_text), Runnable {
performPluginSwitch(changedPlugin, newState, type)
sp.putBoolean("allow_hardware_pump", true)
uel.log("HW PUMP ALLOWED")
uel.log(Action.HW_PUMP_ALLOWED)
aapsLogger.debug(LTag.PUMP, "First time HW pump allowed!")
}, Runnable {
rxBus.send(EventConfigBuilderUpdateGui())

View file

@ -17,6 +17,7 @@ import androidx.recyclerview.widget.LinearSmoothScroller
import androidx.recyclerview.widget.RecyclerView
import dagger.android.support.DaggerFragment
import info.nightscout.androidaps.R
import info.nightscout.androidaps.database.entities.UserEntry.*
import info.nightscout.androidaps.databinding.ObjectivesFragmentBinding
import info.nightscout.androidaps.databinding.ObjectivesItemBinding
import info.nightscout.androidaps.dialogs.NtpProgressDialog
@ -307,7 +308,7 @@ class ObjectivesFragment : DaggerFragment() {
holder.binding.unstart.setOnClickListener {
activity?.let { activity ->
OKDialog.showConfirmation(activity, resourceHelper.gs(R.string.objectives), resourceHelper.gs(R.string.doyouwantresetstart), Runnable {
uel.log("OBJECTIVE UNSTARTED", i1 = position + 1)
uel.log(Action.OBJECTIVE_UNSTARTED, ValueWithUnit(position + 1, Units.None))
objective.startedOn = 0
scrollToCurrentObjective()
rxBus.send(EventObjectivesUpdateGui())

View file

@ -7,6 +7,7 @@ import dagger.android.HasAndroidInjector
import info.nightscout.androidaps.BuildConfig
import info.nightscout.androidaps.Config
import info.nightscout.androidaps.R
import info.nightscout.androidaps.database.entities.UserEntry.*
import info.nightscout.androidaps.interfaces.*
import info.nightscout.androidaps.logging.AAPSLogger
import info.nightscout.androidaps.logging.UserEntryLogger
@ -142,7 +143,7 @@ class ObjectivesPlugin @Inject constructor(
sp.putLong("Objectives_" + "auto" + "_accomplished", DateUtil.now())
setupObjectives()
OKDialog.show(activity, resourceHelper.gs(R.string.objectives), resourceHelper.gs(R.string.codeaccepted))
uel.log("OBJECTIVES SKIPPED")
uel.log(Action.OBJECTIVES_SKIPPED)
} else {
OKDialog.show(activity, resourceHelper.gs(R.string.objectives), resourceHelper.gs(R.string.codeinvalid))
}

View file

@ -16,6 +16,7 @@ import info.nightscout.androidaps.Constants
import info.nightscout.androidaps.R
import info.nightscout.androidaps.activities.ErrorHelperActivity
import info.nightscout.androidaps.activities.TDDStatsActivity
import info.nightscout.androidaps.database.entities.UserEntry.*
import info.nightscout.androidaps.dialogs.*
import info.nightscout.androidaps.events.*
import info.nightscout.androidaps.historyBrowser.HistoryBrowseActivity
@ -154,7 +155,7 @@ class ActionsFragment : DaggerFragment() {
}
extendedBolusCancel?.setOnClickListener {
if (activePlugin.activeTreatments.isInHistoryExtendedBolusInProgress) {
uel.log("CANCEL EXTENDED BOLUS")
uel.log(Action.CANCEL_EXTENDED_BOLUS)
commandQueue.cancelExtended(object : Callback() {
override fun run() {
if (!result.success) {
@ -169,7 +170,7 @@ class ActionsFragment : DaggerFragment() {
}
cancelTempBasal?.setOnClickListener {
if (activePlugin.activeTreatments.isTempBasalInProgress) {
uel.log("CANCEL TEMP BASAL")
uel.log(Action.CANCEL_TEMP_BASAL)
commandQueue.cancelTempBasal(true, object : Callback() {
override fun run() {
if (!result.success) {

View file

@ -163,7 +163,7 @@ class DataBroadcastPlugin @Inject constructor(
bundle.putString("enacted", loopPlugin.lastRun?.request?.json().toString())
}
} else { //NSClient or remote
val data = NSDeviceStatus.deviceStatusOpenAPSData
val data = nsDeviceStatus.deviceStatusOpenAPSData
if (data.clockSuggested != 0L && data.suggested != null) {
bundle.putLong("suggestedTimeStamp", data.clockSuggested)
bundle.putString("suggested", data.suggested.toString())

View file

@ -1,145 +0,0 @@
package info.nightscout.androidaps.plugins.general.food;
import androidx.annotation.NonNull;
import com.j256.ormlite.field.DatabaseField;
import com.j256.ormlite.table.DatabaseTable;
import org.json.JSONException;
import org.json.JSONObject;
import java.util.Objects;
import info.nightscout.androidaps.utils.JsonHelper;
/**
* Created by mike on 20.09.2017.
*/
@DatabaseTable(tableName = Food.TABLE_FOODS)
public class Food {
static final String TABLE_FOODS = "Foods";
@DatabaseField(id = true)
public long key;
@DatabaseField
public boolean isValid = true;
@DatabaseField
public String _id; // NS _id
@DatabaseField
public String name;
@DatabaseField
public String category;
@DatabaseField
public String subcategory;
// Example:
// name="juice" portion=250 units="ml" carbs=12
// means 250ml of juice has 12g of carbs
@DatabaseField
public double portion; // common portion in "units"
@DatabaseField
public int carbs; // in grams
@DatabaseField
public int fat = 0; // in grams
@DatabaseField
public int protein = 0; // in grams
@DatabaseField
public int energy = 0; // in kJ
@DatabaseField
public String units = "g";
@DatabaseField
public int gi; // not used yet
private Food() {
key = System.currentTimeMillis();
}
public static Food createFromJson(JSONObject json) throws JSONException {
Food food = new Food();
if ("food".equals(JsonHelper.safeGetString(json, "type"))) {
food._id = JsonHelper.safeGetString(json, "_id");
food.category = JsonHelper.safeGetString(json, "category");
food.subcategory = JsonHelper.safeGetString(json, "subcategory");
food.name = JsonHelper.safeGetString(json, "name");
food.units = JsonHelper.safeGetString(json, "unit");
food.portion = JsonHelper.safeGetDouble(json, "portion");
food.carbs = JsonHelper.safeGetInt(json, "carbs");
food.gi = JsonHelper.safeGetInt(json, "gi");
food.energy = JsonHelper.safeGetInt(json, "energy");
food.protein = JsonHelper.safeGetInt(json, "protein");
food.fat = JsonHelper.safeGetInt(json, "fat");
}
return food;
}
public boolean isEqual(Food other) {
if (portion != other.portion)
return false;
if (carbs != other.carbs)
return false;
if (fat != other.fat)
return false;
if (protein != other.protein)
return false;
if (energy != other.energy)
return false;
if (gi != other.gi)
return false;
if (!Objects.equals(_id, other._id))
return false;
if (!Objects.equals(name, other.name))
return false;
if (!Objects.equals(category, other.category))
return false;
if (!Objects.equals(subcategory, other.subcategory))
return false;
return Objects.equals(units, other.units);
}
public void copyFrom(Food other) {
isValid = other.isValid;
_id = other._id;
name = other.name;
category = other.category;
subcategory = other.subcategory;
portion = other.portion;
carbs = other.carbs;
fat = other.fat;
protein = other.protein;
energy = other.energy;
units = other.units;
gi = other.gi;
}
@Override @NonNull
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append("_id=" + _id + ";");
sb.append("isValid=" + isValid + ";");
sb.append("name=" + name + ";");
sb.append("category=" + category + ";");
sb.append("subcategory=" + subcategory + ";");
sb.append("portion=" + portion + ";");
sb.append("carbs=" + carbs + ";");
sb.append("protein=" + protein + ";");
sb.append("energy=" + energy + ";");
sb.append("units=" + units + ";");
sb.append("gi=" + gi + ";");
return sb.toString();
}
}

View file

@ -1,7 +1,6 @@
package info.nightscout.androidaps.plugins.general.food
import android.annotation.SuppressLint
import android.content.DialogInterface
import android.graphics.Paint
import android.os.Bundle
import android.text.Editable
@ -15,19 +14,30 @@ import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import dagger.android.support.DaggerFragment
import info.nightscout.androidaps.R
import info.nightscout.androidaps.database.AppRepository
import info.nightscout.androidaps.database.entities.Food
import info.nightscout.androidaps.database.entities.UserEntry.Action
import info.nightscout.androidaps.database.transactions.InvalidateFoodTransaction
import info.nightscout.androidaps.databinding.FoodFragmentBinding
import info.nightscout.androidaps.databinding.FoodItemBinding
import info.nightscout.androidaps.events.EventFoodDatabaseChanged
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.food.FoodFragment.RecyclerViewAdapter.FoodsViewHolder
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
import info.nightscout.androidaps.utils.extensions.toVisibility
import info.nightscout.androidaps.utils.resources.ResourceHelper
import info.nightscout.androidaps.utils.rx.AapsSchedulers
import io.reactivex.Completable
import io.reactivex.disposables.CompositeDisposable
import io.reactivex.rxkotlin.plusAssign
import io.reactivex.rxkotlin.subscribeBy
import java.util.*
import java.util.concurrent.TimeUnit
import javax.inject.Inject
import kotlin.collections.ArrayList
@ -35,10 +45,11 @@ class FoodFragment : DaggerFragment() {
@Inject lateinit var aapsSchedulers: AapsSchedulers
@Inject lateinit var rxBus: RxBusWrapper
@Inject lateinit var aapsLogger: AAPSLogger
@Inject lateinit var resourceHelper: ResourceHelper
@Inject lateinit var fabricPrivacy: FabricPrivacy
@Inject lateinit var foodPlugin: FoodPlugin
@Inject lateinit var nsUpload: NSUpload
@Inject lateinit var repository: AppRepository
@Inject lateinit var uel: UserEntryLogger
private val disposable = CompositeDisposable()
@ -61,8 +72,23 @@ class FoodFragment : DaggerFragment() {
binding.recyclerview.setHasFixedSize(true)
binding.recyclerview.layoutManager = LinearLayoutManager(view.context)
binding.recyclerview.adapter = RecyclerViewAdapter(foodPlugin.service?.foodData
?: ArrayList())
binding.refreshFromNightscout.setOnClickListener {
context?.let { context ->
OKDialog.showConfirmation(context, resourceHelper.gs(R.string.refresheventsfromnightscout) + " ?", {
uel.log(Action.FOOD_FROM_NS)
disposable += Completable.fromAction { repository.deleteAllFoods() }
.subscribeOn(aapsSchedulers.io)
.observeOn(aapsSchedulers.main)
.subscribeBy(
onError = { aapsLogger.error("Error removing foods", it) },
onComplete = { rxBus.send(EventFoodDatabaseChanged()) }
)
rxBus.send(EventNSClientRestart())
})
}
}
binding.clearfilter.setOnClickListener {
binding.filter.setText("")
@ -98,10 +124,6 @@ class FoodFragment : DaggerFragment() {
override fun afterTextChanged(s: Editable) {}
})
loadData()
fillCategories()
fillSubcategories()
filterData()
}
@Synchronized
@ -110,9 +132,23 @@ class FoodFragment : DaggerFragment() {
disposable.add(rxBus
.toObservable(EventFoodDatabaseChanged::class.java)
.observeOn(aapsSchedulers.main)
.subscribe({ updateGui() }, fabricPrivacy::logException)
.debounce(1L, TimeUnit.SECONDS)
.subscribe({ swapAdapter() }, fabricPrivacy::logException)
)
updateGui()
swapAdapter()
}
private fun swapAdapter() {
disposable += repository
.getFoodData()
.observeOn(aapsSchedulers.main)
.subscribe { list ->
unfiltered = list
fillCategories()
fillSubcategories()
filterData()
binding.recyclerview.swapAdapter(RecyclerViewAdapter(filtered), true)
}
}
@Synchronized
@ -127,14 +163,11 @@ class FoodFragment : DaggerFragment() {
_binding = null
}
private fun loadData() {
unfiltered = foodPlugin.service?.foodData ?: ArrayList()
}
private fun fillCategories() {
val catSet: MutableSet<CharSequence> = HashSet()
for (f in unfiltered) {
if (f.category != null && f.category != "") catSet.add(f.category)
val category = f.category
if (!category.isNullOrBlank()) catSet.add(category)
}
// make it unique
val categories = ArrayList(catSet)
@ -150,7 +183,10 @@ class FoodFragment : DaggerFragment() {
val subCatSet: MutableSet<CharSequence> = HashSet()
if (categoryFilter != resourceHelper.gs(R.string.none)) {
for (f in unfiltered) {
if (f.category != null && f.category == categoryFilter) if (f.subcategory != null && f.subcategory != "") subCatSet.add(f.subcategory)
if (f.category != null && f.category == categoryFilter) {
val subCategory = f.subCategory
if (!subCategory.isNullOrEmpty()) subCatSet.add(subCategory)
}
}
}
// make it unique
@ -164,25 +200,23 @@ class FoodFragment : DaggerFragment() {
private fun filterData() {
val textFilter = binding.filter.text.toString()
val categoryFilter = binding.category.selectedItem.toString()
val subcategoryFilter = binding.subcategory.selectedItem.toString()
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.name == null || f.category == null || f.subcategory == null) continue
if (subcategoryFilter != resourceHelper.gs(R.string.none) && f.subcategory != subcategoryFilter) continue
if (f.category == null || f.subCategory == null) continue
if (subcategoryFilter != resourceHelper.gs(R.string.none) && f.subCategory != subcategoryFilter) continue
if (categoryFilter != resourceHelper.gs(R.string.none) && f.category != categoryFilter) continue
if (textFilter != "" && !f.name.toLowerCase(Locale.getDefault()).contains(textFilter.toLowerCase(Locale.getDefault()))) continue
newFiltered.add(f)
}
filtered = newFiltered
updateGui()
}
private fun updateGui() {
binding.recyclerview.swapAdapter(RecyclerViewAdapter(filtered), true)
}
inner class RecyclerViewAdapter internal constructor(var foodList: List<Food>) : RecyclerView.Adapter<FoodsViewHolder>() {
fun Int?.isNotZero(): Boolean = this != null && this != 0
inner class RecyclerViewAdapter internal constructor(private var foodList: List<Food>) : RecyclerView.Adapter<RecyclerViewAdapter.FoodsViewHolder>() {
override fun onCreateViewHolder(viewGroup: ViewGroup, viewType: Int): FoodsViewHolder {
val v = LayoutInflater.from(viewGroup.context).inflate(R.layout.food_item, viewGroup, false)
@ -192,16 +226,16 @@ class FoodFragment : DaggerFragment() {
@SuppressLint("SetTextI18n")
override fun onBindViewHolder(holder: FoodsViewHolder, position: Int) {
val food = foodList[position]
holder.binding.nsSign.visibility = if (food._id != null) View.VISIBLE else View.GONE
holder.binding.nsSign.visibility = (food.interfaceIDs.nightscoutId != null).toVisibility()
holder.binding.name.text = food.name
holder.binding.portion.text = food.portion.toString() + food.units
holder.binding.portion.text = food.portion.toString() + food.unit
holder.binding.carbs.text = food.carbs.toString() + resourceHelper.gs(R.string.shortgramm)
holder.binding.fat.text = resourceHelper.gs(R.string.shortfat) + ": " + food.fat + resourceHelper.gs(R.string.shortgramm)
if (food.fat == 0) holder.binding.fat.visibility = View.INVISIBLE
holder.binding.fat.visibility = food.fat.isNotZero().toVisibility()
holder.binding.protein.text = resourceHelper.gs(R.string.shortprotein) + ": " + food.protein + resourceHelper.gs(R.string.shortgramm)
if (food.protein == 0) holder.binding.protein.visibility = View.INVISIBLE
holder.binding.protein.visibility = food.protein.isNotZero().toVisibility()
holder.binding.energy.text = resourceHelper.gs(R.string.shortenergy) + ": " + food.energy + resourceHelper.gs(R.string.shortkilojoul)
if (food.energy == 0) holder.binding.energy.visibility = View.INVISIBLE
holder.binding.energy.visibility = food.energy.isNotZero().toVisibility()
holder.binding.remove.tag = food
}
@ -215,12 +249,17 @@ class FoodFragment : DaggerFragment() {
binding.remove.setOnClickListener { v: View ->
val food = v.tag as Food
activity?.let { activity ->
OKDialog.showConfirmation(activity, resourceHelper.gs(R.string.confirmation), resourceHelper.gs(R.string.removerecord) + "\n" + food.name, DialogInterface.OnClickListener { _: DialogInterface?, _: Int ->
uel.log("FOOD REMOVED", food.name)
if (food._id != null && food._id != "") {
nsUpload.removeFoodFromNS(food._id)
}
foodPlugin.service?.delete(food)
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.BGSOURCE, "Error while invalidating food", it)
})
}, null)
}
}

View file

@ -1,12 +1,25 @@
package info.nightscout.androidaps.plugins.general.food
import android.content.Context
import androidx.work.Worker
import androidx.work.WorkerParameters
import dagger.android.HasAndroidInjector
import info.nightscout.androidaps.R
import info.nightscout.androidaps.database.AppRepository
import info.nightscout.androidaps.database.entities.Food
import info.nightscout.androidaps.database.transactions.SyncFoodTransaction
import info.nightscout.androidaps.interfaces.PluginBase
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.receivers.DataWorker
import info.nightscout.androidaps.utils.JsonHelper
import info.nightscout.androidaps.utils.extensions.foodFromJson
import info.nightscout.androidaps.utils.resources.ResourceHelper
import info.nightscout.androidaps.utils.sharedPreferences.SP
import org.json.JSONArray
import org.json.JSONObject
import javax.inject.Inject
import javax.inject.Singleton
@ -25,10 +38,76 @@ class FoodPlugin @Inject constructor(
aapsLogger, resourceHelper, injector
) {
var service: FoodService? = null
// cannot be inner class because of needed injection
class FoodWorker(
context: Context,
params: WorkerParameters
) : Worker(context, params) {
override fun onStart() {
super.onStart()
service = FoodService(injector)
@Inject lateinit var injector: HasAndroidInjector
@Inject lateinit var aapsLogger: AAPSLogger
@Inject lateinit var repository: AppRepository
@Inject lateinit var sp: SP
@Inject lateinit var dataWorker: DataWorker
init {
(context.applicationContext as HasAndroidInjector).androidInjector().inject(this)
}
override fun doWork(): Result {
val foods = dataWorker.pickupJSONArray(inputData.getLong(DataWorker.STORE_KEY, -1))
?: return Result.failure()
aapsLogger.debug(LTag.DATAFOOD, "Received Food Data: $foods")
var ret = Result.success()
for (index in 0 until foods.length()) {
val jsonFood: JSONObject = foods.getJSONObject(index)
if (JsonHelper.safeGetString(jsonFood, "type") != "food") continue
when (JsonHelper.safeGetString(jsonFood, "action")) {
"remove" -> {
val delFood = Food(
name = "",
portion = 0.0,
carbs = 0,
isValid = false
).also { it.interfaceIDs.nightscoutId = JsonHelper.safeGetString(jsonFood, "_id") }
repository.runTransactionForResult(SyncFoodTransaction(delFood))
.doOnError {
aapsLogger.error(LTag.DATAFOOD, "Error while removing food", it)
ret = Result.failure()
}
.blockingGet()
.also {
it.invalidated.forEach { f -> aapsLogger.debug(LTag.DATAFOOD, "Invalidated food ${f.interfaceIDs.nightscoutId}") }
}
}
else -> {
val food = foodFromJson(jsonFood)
if (food != null) {
repository.runTransactionForResult(SyncFoodTransaction(food))
.doOnError {
aapsLogger.error(LTag.DATAFOOD, "Error while adding/updating food", it)
ret = Result.failure()
}
.blockingGet()
.also { result ->
result.inserted.forEach { aapsLogger.debug(LTag.DATAFOOD, "Inserted food $it") }
result.updated.forEach { aapsLogger.debug(LTag.DATAFOOD, "Updated food $it") }
result.invalidated.forEach { aapsLogger.debug(LTag.DATAFOOD, "Invalidated food $it") }
}
} else {
aapsLogger.error(LTag.DATAFOOD, "Error parsing food", jsonFood.toString())
ret = Result.failure()
}
}
}
}
return ret
}
}
}

View file

@ -1,359 +0,0 @@
package info.nightscout.androidaps.plugins.general.food;
import android.content.Intent;
import android.os.IBinder;
import androidx.annotation.Nullable;
import com.j256.ormlite.android.apptools.OpenHelperManager;
import com.j256.ormlite.android.apptools.OrmLiteBaseService;
import com.j256.ormlite.dao.Dao;
import com.j256.ormlite.dao.DaoManager;
import com.j256.ormlite.support.ConnectionSource;
import com.j256.ormlite.table.TableUtils;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
import javax.inject.Inject;
import dagger.android.HasAndroidInjector;
import info.nightscout.androidaps.db.DatabaseHelper;
import info.nightscout.androidaps.db.ICallback;
import info.nightscout.androidaps.events.Event;
import info.nightscout.androidaps.events.EventFoodDatabaseChanged;
import info.nightscout.androidaps.events.EventNsFood;
import info.nightscout.androidaps.logging.AAPSLogger;
import info.nightscout.androidaps.logging.LTag;
import info.nightscout.androidaps.plugins.bus.RxBusWrapper;
import info.nightscout.androidaps.utils.FabricPrivacy;
import info.nightscout.androidaps.utils.rx.AapsSchedulers;
import io.reactivex.disposables.CompositeDisposable;
/**
* Created by mike on 24.09.2017.
*/
public class FoodService extends OrmLiteBaseService<DatabaseHelper> {
@Inject AAPSLogger aapsLogger;
@Inject RxBusWrapper rxBus;
@Inject FabricPrivacy fabricPrivacy;
@Inject AapsSchedulers aapsSchedulers;
private final CompositeDisposable disposable = new CompositeDisposable();
private static final ScheduledExecutorService foodEventWorker = Executors.newSingleThreadScheduledExecutor();
private static ScheduledFuture<?> scheduledFoodEventPost = null;
public FoodService(HasAndroidInjector injector) {
injector.androidInjector().inject(this);
onCreate();
dbInitialize();
disposable.add(rxBus
.toObservable(EventNsFood.class)
.observeOn(aapsSchedulers.getIo())
.subscribe(event -> {
int mode = event.getMode();
JSONArray array = event.getFoods();
if (mode == EventNsFood.Companion.getADD() || mode == EventNsFood.Companion.getUPDATE())
this.createFoodFromJsonIfNotExists(array);
else
this.deleteNS(array);
}, fabricPrivacy::logException)
);
}
/**
* This method is a simple re-implementation of the database create and up/downgrade functionality
* in SQLiteOpenHelper#getDatabaseLocked method.
* <p>
* It is implemented to be able to late initialize separate plugins of the application.
*/
protected void dbInitialize() {
DatabaseHelper helper = OpenHelperManager.getHelper(this, DatabaseHelper.class);
int newVersion = helper.getNewVersion();
int oldVersion = helper.getOldVersion();
if (oldVersion > newVersion) {
onDowngrade(this.getConnectionSource(), oldVersion, newVersion);
} else {
onUpgrade(this.getConnectionSource(), oldVersion, newVersion);
}
}
public Dao<Food, Long> getDao() {
try {
return DaoManager.createDao(this.getConnectionSource(), Food.class);
} catch (SQLException e) {
aapsLogger.error("Cannot create Dao for Food.class");
}
return null;
}
@Override
public void onCreate() {
super.onCreate();
try {
aapsLogger.info(LTag.DATAFOOD, "onCreate");
TableUtils.createTableIfNotExists(this.getConnectionSource(), Food.class);
} catch (SQLException e) {
aapsLogger.error("Can't create database", e);
throw new RuntimeException(e);
}
}
public void onUpgrade(ConnectionSource connectionSource, int oldVersion, int newVersion) {
aapsLogger.info(LTag.DATAFOOD, "onUpgrade");
// this.resetFood();
}
public void onDowngrade(ConnectionSource connectionSource, int oldVersion, int newVersion) {
// this method is not supported right now
}
public void resetFood() {
try {
TableUtils.dropTable(this.getConnectionSource(), Food.class, true);
TableUtils.createTableIfNotExists(this.getConnectionSource(), Food.class);
} catch (SQLException e) {
aapsLogger.error("Unhandled exception", e);
}
scheduleFoodChange();
}
/**
* A place to centrally register events to be posted, if any data changed.
* This should be implemented in an abstract service-class.
* <p>
* We do need to make sure, that ICallback is extended to be able to handle multiple
* events, or handle a list of events.
* <p>
* on some methods the earliestDataChange event is handled separatly, in that it is checked if it is
* set to null by another event already (eg. scheduleExtendedBolusChange).
*
* @param event
* @param eventWorker
* @param callback
*/
private void scheduleEvent(final Event event, ScheduledExecutorService eventWorker,
final ICallback callback) {
class PostRunnable implements Runnable {
public void run() {
aapsLogger.debug(LTag.DATAFOOD, "Firing EventFoodChange");
rxBus.send(event);
callback.setPost(null);
}
}
// prepare task for execution in 1 sec
// cancel waiting task to prevent sending multiple posts
if (callback.getPost() != null)
callback.getPost().cancel(false);
Runnable task = new PostRunnable();
final int sec = 1;
callback.setPost(eventWorker.schedule(task, sec, TimeUnit.SECONDS));
}
/**
* Schedule a foodChange Event.
*/
public void scheduleFoodChange() {
this.scheduleEvent(new EventFoodDatabaseChanged(), foodEventWorker, new ICallback() {
@Override
public void setPost(ScheduledFuture<?> post) {
scheduledFoodEventPost = post;
}
@Override
public ScheduledFuture<?> getPost() {
return scheduledFoodEventPost;
}
});
}
public List<Food> getFoodData() {
try {
return this.getDao().queryForAll();
} catch (SQLException e) {
aapsLogger.error("Unhandled exception", e);
}
return new ArrayList<>();
}
/*
{
"_id": "551ee3ad368e06e80856e6a9",
"type": "food",
"category": "Zakladni",
"subcategory": "Napoje",
"name": "Mleko",
"portion": 250,
"carbs": 12,
"gi": 1,
"created_at": "2015-04-14T06:59:16.500Z",
"unit": "ml"
}
*/
public void createFoodFromJsonIfNotExists(JSONObject json) {
try {
Food food = Food.createFromJson(json);
this.createFoodFromJsonIfNotExists(food);
} catch (JSONException e) {
aapsLogger.error("Unhandled exception", e);
}
}
public void createFoodFromJsonIfNotExists(JSONArray array) {
try {
for (int n = 0; n < array.length(); n++) {
JSONObject json = array.getJSONObject(n);
Food food = Food.createFromJson(json);
this.createFoodFromJsonIfNotExists(food);
}
} catch (JSONException e) {
aapsLogger.error("Unhandled exception", e);
}
}
public void createFoodFromJsonIfNotExists(Food food) {
this.createOrUpdateByNS(food);
}
public void deleteNS(JSONObject json) {
try {
String _id = json.getString("_id");
this.deleteByNSId(_id);
} catch (JSONException | SQLException e) {
aapsLogger.error("Unhandled exception", e);
}
}
public void deleteNS(JSONArray array) {
try {
for (int n = 0; n < array.length(); n++) {
JSONObject json = array.getJSONObject(n);
this.deleteNS(json);
}
} catch (JSONException e) {
aapsLogger.error("Unhandled exception", e);
}
}
/**
* deletes an entry by its NS Id.
* <p>
* Basically a convenience method for findByNSId and delete.
*
* @param _id
*/
public void deleteByNSId(String _id) throws SQLException {
Food stored = this.findByNSId(_id);
if (stored != null) {
aapsLogger.debug(LTag.DATAFOOD, "Removing Food record from database: " + stored.toString());
this.delete(stored);
}
}
/**
* deletes the food and sends the foodChange Event
* <p>
* should be moved ot a Service
*
* @param food
*/
public void delete(Food food) {
try {
this.getDao().delete(food);
this.scheduleFoodChange();
} catch (SQLException e) {
aapsLogger.error("Unhandled exception", e);
}
}
/**
* Create of update a food record by the NS (Nightscout) Id.
*
* @param food
* @return
*/
public boolean createOrUpdateByNS(Food food) {
// find by NS _id
if (food._id != null && !food._id.equals("")) {
Food old = this.findByNSId(food._id);
if (old != null) {
if (!old.isEqual(food)) {
this.delete(old); // need to delete/create because date may change too
old.copyFrom(food);
this.create(old);
return true;
} else {
return false;
}
} else {
this.createOrUpdate(food);
return true;
}
}
return false;
}
public void createOrUpdate(Food food) {
try {
this.getDao().createOrUpdate(food);
aapsLogger.debug(LTag.DATAFOOD, "Created or Updated: " + food.toString());
} catch (SQLException e) {
aapsLogger.error("Unable to createOrUpdate Food", e);
}
this.scheduleFoodChange();
}
public void create(Food food) {
try {
this.getDao().create(food);
aapsLogger.debug(LTag.DATAFOOD, "New record: " + food.toString());
} catch (SQLException e) {
aapsLogger.error("Unable to create Food", e);
}
this.scheduleFoodChange();
}
/**
* finds food by its NS Id.
*
* @param _id
* @return
*/
@Nullable
public Food findByNSId(String _id) {
try {
List<Food> list = this.getDao().queryForEq("_id", _id);
if (list.size() == 1) { // really? if there are more then one result, then we do not return anything...
return list.get(0);
}
} catch (SQLException e) {
aapsLogger.error("Unhandled exception", e);
}
return null;
}
@Nullable
@Override
public IBinder onBind(Intent intent) {
return null;
}
}

View file

@ -15,6 +15,8 @@ import info.nightscout.androidaps.BuildConfig
import info.nightscout.androidaps.R
import info.nightscout.androidaps.activities.DaggerAppCompatActivityWithResult
import info.nightscout.androidaps.activities.PreferencesActivity
import info.nightscout.androidaps.database.entities.UserEntry
import info.nightscout.androidaps.database.entities.UserEntry.*
import info.nightscout.androidaps.events.EventAppExit
import info.nightscout.androidaps.interfaces.ConfigInterface
import info.nightscout.androidaps.interfaces.ImportExportPrefsInterface
@ -34,6 +36,7 @@ import info.nightscout.androidaps.utils.buildHelper.BuildHelper
import info.nightscout.androidaps.utils.protection.PasswordCheck
import info.nightscout.androidaps.utils.resources.ResourceHelper
import info.nightscout.androidaps.utils.sharedPreferences.SP
import io.reactivex.Single
import java.io.File
import java.io.FileNotFoundException
import java.io.IOException
@ -105,6 +108,7 @@ class ImportExportPrefs @Inject constructor(
return metadata
}
@Suppress("SpellCheckingInspection")
private fun detectUserName(context: Context): String {
// based on https://medium.com/@pribble88/how-to-get-an-android-device-nickname-4b4700b3068c
val n1 = Settings.System.getString(context.contentResolver, "bluetooth_name")
@ -343,8 +347,8 @@ class ImportExportPrefs @Inject constructor(
private fun restartAppAfterImport(context: Context) {
sp.putBoolean(R.string.key_setupwizard_processed, true)
OKDialog.show(context, resourceHelper.gs(R.string.setting_imported), resourceHelper.gs(R.string.restartingapp), Runnable {
uel.log("IMPORT")
OKDialog.show(context, resourceHelper.gs(R.string.setting_imported), resourceHelper.gs(R.string.restartingapp)) {
uel.log(Action.IMPORT_SETTINGS)
log.debug(LTag.CORE, "Exiting")
rxBus.send(EventAppExit())
if (context is AppCompatActivity) {
@ -352,6 +356,23 @@ class ImportExportPrefs @Inject constructor(
}
System.runFinalization()
exitProcess(0)
})
}
}
override fun exportUserEntriesCsv(activity: FragmentActivity, singleEntries: Single<List<UserEntry>>) {
val entries = singleEntries.blockingGet()
prefFileList.ensureExportDirExists()
val newFile = prefFileList.newExportXmlFile()
try {
classicPrefsFormat.saveCsv(newFile, entries)
ToastUtils.okToast(activity, resourceHelper.gs(R.string.ue_exported))
} catch (e: FileNotFoundException) {
ToastUtils.errorToast(activity, resourceHelper.gs(R.string.filenotfound) + " " + newFile)
log.error(LTag.CORE, "Unhandled exception", e)
} catch (e: IOException) {
ToastUtils.errorToast(activity, e.message)
log.error(LTag.CORE, "Unhandled exception", e)
}
}
}

View file

@ -8,6 +8,7 @@ import android.view.ViewGroup
import dagger.android.support.DaggerFragment
import info.nightscout.androidaps.R
import info.nightscout.androidaps.database.AppRepository
import info.nightscout.androidaps.database.entities.UserEntry.*
import info.nightscout.androidaps.databinding.MaintenanceFragmentBinding
import info.nightscout.androidaps.events.EventNewBG
import info.nightscout.androidaps.interfaces.DatabaseHelperInterface
@ -15,7 +16,6 @@ import info.nightscout.androidaps.interfaces.ImportExportPrefsInterface
import info.nightscout.androidaps.logging.AAPSLogger
import info.nightscout.androidaps.logging.UserEntryLogger
import info.nightscout.androidaps.plugins.bus.RxBusWrapper
import info.nightscout.androidaps.plugins.general.food.FoodPlugin
import info.nightscout.androidaps.plugins.general.maintenance.activities.LogSettingActivity
import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin
import info.nightscout.androidaps.utils.alertDialogs.OKDialog
@ -33,7 +33,6 @@ class MaintenanceFragment : DaggerFragment() {
@Inject lateinit var rxBus: RxBusWrapper
@Inject lateinit var resourceHelper: ResourceHelper
@Inject lateinit var treatmentsPlugin: TreatmentsPlugin
@Inject lateinit var foodPlugin: FoodPlugin
@Inject lateinit var importExportPrefs: ImportExportPrefsInterface
@Inject lateinit var aapsSchedulers: AapsSchedulers
@Inject lateinit var repository: AppRepository
@ -57,19 +56,18 @@ class MaintenanceFragment : DaggerFragment() {
super.onViewCreated(view, savedInstanceState)
binding.logSend.setOnClickListener { maintenancePlugin.sendLogs() }
binding.logDelete.setOnClickListener {
uel.log("DELETE LOGS")
uel.log(Action.DELETE_LOGS)
maintenancePlugin.deleteLogs()
}
binding.navResetdb.setOnClickListener {
activity?.let { activity ->
OKDialog.showConfirmation(activity, resourceHelper.gs(R.string.maintenance), resourceHelper.gs(R.string.reset_db_confirm), Runnable {
uel.log("RESET DATABASES")
uel.log(Action.RESET_DATABASES)
compositeDisposable.add(
fromAction {
databaseHelper.resetDatabases()
// should be handled by Plugin-Interface and
// additional service interface and plugin registry
foodPlugin.service?.resetFood()
treatmentsPlugin.service.resetTreatments()
repository.clearDatabases()
}
@ -84,20 +82,28 @@ class MaintenanceFragment : DaggerFragment() {
}
}
binding.navExport.setOnClickListener {
uel.log("EXPORT SETTINGS")
uel.log(Action.EXPORT_SETTINGS)
// start activity for checking permissions...
importExportPrefs.verifyStoragePermissions(this) {
importExportPrefs.exportSharedPreferences(this)
}
}
binding.navImport.setOnClickListener {
uel.log("IMPORT SETTINGS")
uel.log(Action.IMPORT_SETTINGS)
// start activity for checking permissions...
importExportPrefs.verifyStoragePermissions(this) {
importExportPrefs.importSharedPreferences(this)
}
}
binding.navLogsettings.setOnClickListener { startActivity(Intent(activity, LogSettingActivity::class.java)) }
binding.exportCsv.setOnClickListener {
activity?.let { activity ->
OKDialog.showConfirmation(activity, resourceHelper.gs(R.string.ue_export_to_csv) + "?") {
uel.log(Action.EXPORT_CSV)
importExportPrefs.exportUserEntriesCsv(activity, repository.getAllUserEntries())
}
}
}
}
@Synchronized

View file

@ -173,7 +173,7 @@ class MaintenancePlugin @Inject constructor(
builder.append("Build: " + BuildConfig.BUILDVERSION + System.lineSeparator())
builder.append("Remote: " + BuildConfig.REMOTE + System.lineSeparator())
builder.append("Flavor: " + BuildConfig.FLAVOR + BuildConfig.BUILD_TYPE + System.lineSeparator())
builder.append(resourceHelper.gs(R.string.configbuilder_nightscoutversion_label) + " " + nsSettingsStatus.nightscoutVersionName + System.lineSeparator())
builder.append(resourceHelper.gs(R.string.configbuilder_nightscoutversion_label) + " " + nsSettingsStatus.getVersion() + System.lineSeparator())
if (buildHelper.isEngineeringMode()) builder.append(resourceHelper.gs(R.string.engineering_mode_enabled))
return sendMail(attachmentUri, recipient, subject, builder.toString())
}

View file

@ -0,0 +1,178 @@
package info.nightscout.androidaps.plugins.general.nsclient
import android.content.Context
import androidx.work.Worker
import androidx.work.WorkerParameters
import dagger.android.HasAndroidInjector
import info.nightscout.androidaps.R
import info.nightscout.androidaps.database.AppRepository
import info.nightscout.androidaps.database.entities.TherapyEvent
import info.nightscout.androidaps.database.entities.UserEntry
import info.nightscout.androidaps.database.entities.UserEntry.ValueWithUnit
import info.nightscout.androidaps.database.transactions.SyncTemporaryTargetTransaction
import info.nightscout.androidaps.database.transactions.SyncTherapyEventTransaction
import info.nightscout.androidaps.events.EventNsTreatment
import info.nightscout.androidaps.interfaces.ConfigInterface
import info.nightscout.androidaps.interfaces.DatabaseHelperInterface
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.overview.events.EventNewNotification
import info.nightscout.androidaps.plugins.general.overview.notifications.Notification
import info.nightscout.androidaps.receivers.DataWorker
import info.nightscout.androidaps.utils.DateUtil
import info.nightscout.androidaps.utils.JsonHelper
import info.nightscout.androidaps.utils.JsonHelper.safeGetLong
import info.nightscout.androidaps.utils.buildHelper.BuildHelper
import info.nightscout.androidaps.utils.extensions.temporaryTargetFromJson
import info.nightscout.androidaps.utils.extensions.therapyEventFromJson
import info.nightscout.androidaps.utils.sharedPreferences.SP
import javax.inject.Inject
class NSClientAddUpdateWorker(
context: Context,
params: WorkerParameters
) : Worker(context, params) {
@Inject lateinit var nsClientPlugin: NSClientPlugin
@Inject lateinit var dataWorker: DataWorker
@Inject lateinit var aapsLogger: AAPSLogger
@Inject lateinit var buildHelper: BuildHelper
@Inject lateinit var sp: SP
@Inject lateinit var dateutil: DateUtil
@Inject lateinit var config: ConfigInterface
@Inject lateinit var repository: AppRepository
@Inject lateinit var databaseHelper: DatabaseHelperInterface
@Inject lateinit var rxBus: RxBusWrapper
@Inject lateinit var uel: UserEntryLogger
override fun doWork(): Result {
val acceptNSData = !sp.getBoolean(R.string.key_ns_upload_only, true) && buildHelper.isEngineeringMode() || config.NSCLIENT
if (!acceptNSData) return Result.failure()
val treatments = dataWorker.pickupJSONArray(inputData.getLong(DataWorker.STORE_KEY, -1))
?: return Result.failure()
var ret = Result.success()
var latestDateInReceivedData = 0L
for (i in 0 until treatments.length()) {
val json = treatments.getJSONObject(i)
// new DB model
val insulin = JsonHelper.safeGetDouble(json, "insulin")
val carbs = JsonHelper.safeGetDouble(json, "carbs")
val eventType = JsonHelper.safeGetString(json, "eventType")
if (eventType == null) {
aapsLogger.debug(LTag.DATASERVICE, "Wrong treatment. Ignoring : $json")
continue
}
//Find latest date in treatment
val mills = safeGetLong(json, "mills")
if (mills != 0L && mills < dateutil._now())
if (mills > latestDateInReceivedData) latestDateInReceivedData = mills
when {
insulin > 0 || carbs > 0 ->
rxBus.send(EventNsTreatment(EventNsTreatment.ADD, json))
eventType == TherapyEvent.Type.TEMPORARY_TARGET.text ->
temporaryTargetFromJson(json)?.let { temporaryTarget ->
repository.runTransactionForResult(SyncTemporaryTargetTransaction(temporaryTarget))
.doOnError {
aapsLogger.error(LTag.DATABASE, "Error while saving temporary target", it)
ret = Result.failure()
}
.blockingGet()
.also { result ->
result.inserted.forEach {
uel.log(UserEntry.Action.TT_FROM_NS,
ValueWithUnit(it.reason.text, UserEntry.Units.TherapyEvent),
ValueWithUnit(it.lowTarget, UserEntry.Units.Mg_Dl, true),
ValueWithUnit(it.highTarget, UserEntry.Units.Mg_Dl, it.lowTarget != it.highTarget),
ValueWithUnit(it.duration.toInt() / 60000, UserEntry.Units.M, true)
)
}
result.invalidated.forEach {
uel.log(UserEntry.Action.TT_DELETED_FROM_NS,
ValueWithUnit(it.reason.text, UserEntry.Units.TherapyEvent),
ValueWithUnit(it.lowTarget, UserEntry.Units.Mg_Dl, true),
ValueWithUnit(it.highTarget, UserEntry.Units.Mg_Dl, it.lowTarget != it.highTarget),
ValueWithUnit(it.duration.toInt() / 60000, UserEntry.Units.M, true)
)
}
result.ended.forEach {
uel.log(UserEntry.Action.TT_CANCELED_FROM_NS,
ValueWithUnit(it.reason.text, UserEntry.Units.TherapyEvent),
ValueWithUnit(it.lowTarget, UserEntry.Units.Mg_Dl, true),
ValueWithUnit(it.highTarget, UserEntry.Units.Mg_Dl, it.lowTarget != it.highTarget),
ValueWithUnit(it.duration.toInt() / 60000, UserEntry.Units.M, true)
)
}
}
} ?: aapsLogger.error("Error parsing TT json $json")
eventType == TherapyEvent.Type.CANNULA_CHANGE.text ||
eventType == TherapyEvent.Type.INSULIN_CHANGE.text ||
eventType == TherapyEvent.Type.SENSOR_CHANGE.text ||
eventType == TherapyEvent.Type.FINGER_STICK_BG_VALUE.text ||
eventType == TherapyEvent.Type.NOTE.text ||
eventType == TherapyEvent.Type.NONE.text ||
eventType == TherapyEvent.Type.ANNOUNCEMENT.text ||
eventType == TherapyEvent.Type.QUESTION.text ||
eventType == TherapyEvent.Type.EXERCISE.text ||
eventType == TherapyEvent.Type.APS_OFFLINE.text ||
eventType == TherapyEvent.Type.PUMP_BATTERY_CHANGE.text ->
therapyEventFromJson(json)?.let { therapyEvent ->
repository.runTransactionForResult(SyncTherapyEventTransaction(therapyEvent))
.doOnError {
aapsLogger.error(LTag.DATABASE, "Error while saving therapy event", it)
ret = Result.failure()
}
.blockingGet()
.also { result ->
result.inserted.forEach {
uel.log(UserEntry.Action.CAREPORTAL_FROM_NS,
it.note ?: "",
ValueWithUnit(it.timestamp, UserEntry.Units.Timestamp, true),
ValueWithUnit(it.type.text, UserEntry.Units.TherapyEvent)
)
}
result.invalidated.forEach {
uel.log(UserEntry.Action.CAREPORTAL_DELETED_FROM_NS,
it.note ?: "",
ValueWithUnit(it.timestamp, UserEntry.Units.Timestamp, true),
ValueWithUnit(it.type.text, UserEntry.Units.TherapyEvent)
)
}
}
} ?: aapsLogger.error("Error parsing TherapyEvent json $json")
eventType == TherapyEvent.Type.TEMPORARY_BASAL.text ->
databaseHelper.createTempBasalFromJsonIfNotExists(json)
eventType == TherapyEvent.Type.COMBO_BOLUS.text ->
databaseHelper.createExtendedBolusFromJsonIfNotExists(json)
eventType == TherapyEvent.Type.PROFILE_SWITCH.text ->
databaseHelper.createProfileSwitchFromJsonIfNotExists(json)
}
if (eventType == TherapyEvent.Type.ANNOUNCEMENT.text) {
val date = safeGetLong(json, "mills")
val now = System.currentTimeMillis()
val enteredBy = JsonHelper.safeGetString(json, "enteredBy", "")
val notes = JsonHelper.safeGetString(json, "notes", "")
if (date > now - 15 * 60 * 1000L && notes.isNotEmpty()
&& enteredBy != sp.getString("careportal_enteredby", "AndroidAPS")) {
val defaultVal = config.NSCLIENT
if (sp.getBoolean(R.string.key_ns_announcements, defaultVal)) {
val announcement = Notification(Notification.NS_ANNOUNCEMENT, notes, Notification.ANNOUNCEMENT, 60)
rxBus.send(EventNewNotification(announcement))
}
}
}
}
nsClientPlugin.updateLatestDateReceivedIfNewer(latestDateInReceivedData)
return ret
}
init {
(context.applicationContext as HasAndroidInjector).androidInjector().inject(this)
}
}

View file

@ -16,6 +16,9 @@ import javax.inject.Inject;
import dagger.android.support.DaggerFragment;
import info.nightscout.androidaps.R;
import info.nightscout.androidaps.interfaces.UploadQueueAdminInterface;
import info.nightscout.androidaps.database.entities.UserEntry;
import info.nightscout.androidaps.database.entities.UserEntry.*;
import info.nightscout.androidaps.logging.UserEntryLogger;
import info.nightscout.androidaps.plugins.bus.RxBusWrapper;
import info.nightscout.androidaps.plugins.general.nsclient.events.EventNSClientNewLog;
@ -34,7 +37,7 @@ public class NSClientFragment extends DaggerFragment implements View.OnClickList
@Inject SP sp;
@Inject ResourceHelper resourceHelper;
@Inject RxBusWrapper rxBus;
@Inject UploadQueue uploadQueue;
@Inject UploadQueueAdminInterface uploadQueue;
@Inject FabricPrivacy fabricPrivacy;
@Inject AapsSchedulers aapsSchedulers;
@Inject UserEntryLogger uel;
@ -123,7 +126,7 @@ public class NSClientFragment extends DaggerFragment implements View.OnClickList
break;
case R.id.nsclientinternal_clearqueue:
OKDialog.showConfirmation(getContext(), resourceHelper.gs(R.string.nsclientinternal), resourceHelper.gs(R.string.clearqueueconfirm), () -> {
uel.log("NS QUEUE CLEARED", "", 0.0, 0.0, 0, 0);
uel.log(Action.NS_QUEUE_CLEARED);
uploadQueue.clearQueue();
updateGui();
fabricPrivacy.logCustom("NSClientClearQueue");
@ -139,7 +142,7 @@ public class NSClientFragment extends DaggerFragment implements View.OnClickList
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
switch (buttonView.getId()) {
case R.id.nsclientinternal_paused:
uel.log("NS PAUSED", "", 0.0, 0.0, isChecked ? 1 : 0, 0);
uel.log(isChecked ? Action.NS_PAUSED : Action.NS_RESUME);
nsClientPlugin.pause(isChecked);
updateGui();
fabricPrivacy.logCustom("NSClientPause");

View file

@ -0,0 +1,59 @@
package info.nightscout.androidaps.plugins.general.nsclient
import android.content.Context
import androidx.work.Worker
import androidx.work.WorkerParameters
import dagger.android.HasAndroidInjector
import info.nightscout.androidaps.R
import info.nightscout.androidaps.database.AppRepository
import info.nightscout.androidaps.database.transactions.SyncTherapyEventTransaction
import info.nightscout.androidaps.interfaces.ConfigInterface
import info.nightscout.androidaps.logging.AAPSLogger
import info.nightscout.androidaps.logging.LTag
import info.nightscout.androidaps.plugins.general.nsclient.data.NSMbg
import info.nightscout.androidaps.receivers.DataWorker
import info.nightscout.androidaps.utils.buildHelper.BuildHelper
import info.nightscout.androidaps.utils.extensions.therapyEventFromNsMbg
import info.nightscout.androidaps.utils.sharedPreferences.SP
import javax.inject.Inject
class NSClientMbgWorker(
context: Context,
params: WorkerParameters
) : Worker(context, params) {
@Inject lateinit var repository: AppRepository
@Inject lateinit var dataWorker: DataWorker
@Inject lateinit var aapsLogger: AAPSLogger
@Inject lateinit var sp: SP
@Inject lateinit var buildHelper: BuildHelper
@Inject lateinit var config: ConfigInterface
override fun doWork(): Result {
var ret = Result.success()
val acceptNSData = !sp.getBoolean(R.string.key_ns_upload_only, true) && buildHelper.isEngineeringMode() || config.NSCLIENT
if (!acceptNSData) return ret
val mbgArray = dataWorker.pickupJSONArray(inputData.getLong(DataWorker.STORE_KEY, -1))
?: return Result.failure()
for (i in 0 until mbgArray.length()) {
val nsMbg = NSMbg(mbgArray.getJSONObject(i))
if (!nsMbg.isValid()) continue
repository.runTransactionForResult(SyncTherapyEventTransaction(therapyEventFromNsMbg(nsMbg)))
.doOnError {
aapsLogger.error("Error while saving therapy event", it)
ret = Result.failure()
}
.blockingGet()
.also {
aapsLogger.debug(LTag.DATABASE, "Saved therapy event $it")
}
}
return ret
}
init {
(context.applicationContext as HasAndroidInjector).androidInjector().inject(this)
}
}

View file

@ -31,6 +31,9 @@ import info.nightscout.androidaps.R;
import info.nightscout.androidaps.database.AppRepository;
import info.nightscout.androidaps.database.entities.TemporaryTarget;
import info.nightscout.androidaps.database.entities.TherapyEvent;
import info.nightscout.androidaps.database.entities.UserEntry.Action;
import info.nightscout.androidaps.database.entities.UserEntry.Units;
import info.nightscout.androidaps.database.entities.UserEntry.ValueWithUnit;
import info.nightscout.androidaps.database.transactions.SyncTemporaryTargetTransaction;
import info.nightscout.androidaps.database.transactions.SyncTherapyEventTransaction;
import info.nightscout.androidaps.events.EventAppExit;
@ -49,7 +52,6 @@ import info.nightscout.androidaps.logging.UserEntryLogger;
import info.nightscout.androidaps.plugins.bus.RxBusWrapper;
import info.nightscout.androidaps.plugins.general.nsclient.data.AlarmAck;
import info.nightscout.androidaps.plugins.general.nsclient.data.NSAlarm;
import info.nightscout.androidaps.plugins.general.nsclient.data.NSMbg;
import info.nightscout.androidaps.plugins.general.nsclient.events.EventNSClientNewLog;
import info.nightscout.androidaps.plugins.general.nsclient.events.EventNSClientResend;
import info.nightscout.androidaps.plugins.general.nsclient.events.EventNSClientStatus;
@ -72,7 +74,6 @@ import static info.nightscout.androidaps.utils.extensions.TemporaryTargetExtensi
import static info.nightscout.androidaps.utils.extensions.TemporaryTargetExtensionKt.temporaryTargetFromNsIdForInvalidating;
import static info.nightscout.androidaps.utils.extensions.TherapyEventExtensionKt.therapyEventFromJson;
import static info.nightscout.androidaps.utils.extensions.TherapyEventExtensionKt.therapyEventFromNsIdForInvalidating;
import static info.nightscout.androidaps.utils.extensions.TherapyEventExtensionKt.therapyEventFromNsMbg;
@Singleton
public class NSClientPlugin extends PluginBase {
@ -256,7 +257,7 @@ public class NSClientPlugin extends PluginBase {
SwitchPreference key_ns_sync_use_absolute = preferenceFragment.findPreference(resourceHelper.gs(R.string.key_ns_sync_use_absolute));
if (key_ns_sync_use_absolute != null) key_ns_sync_use_absolute.setVisible(false);
} else {
// APS or pumpcontrol mode
// APS or pumpControl mode
SwitchPreference key_ns_upload_only = preferenceFragment.findPreference(resourceHelper.gs(R.string.key_ns_upload_only));
if (key_ns_upload_only != null)
key_ns_upload_only.setVisible(buildHelper.isEngineeringMode());
@ -352,178 +353,8 @@ public class NSClientPlugin extends PluginBase {
nsClientService.sendAlarmAck(ack);
}
// Parsing input data
public void handleNewDataFromNSClient(String action, Bundle bundle) {
boolean acceptNSData = !sp.getBoolean(R.string.key_ns_upload_only, true) && buildHelper.isEngineeringMode() || config.getNSCLIENT();
if (!acceptNSData) return;
aapsLogger.debug(LTag.DATASERVICE, "Got intent: " + action);
if (action.equals(Intents.ACTION_NEW_TREATMENT) || action.equals(Intents.ACTION_CHANGED_TREATMENT)) {
try {
if (bundle.containsKey("treatment")) {
JSONObject json = new JSONObject(bundle.getString("treatment"));
handleTreatmentFromNS(json, action);
}
if (bundle.containsKey("treatments")) {
String trstring = bundle.getString("treatments");
JSONArray jsonArray = new JSONArray(trstring);
for (int i = 0; i < jsonArray.length(); i++) {
JSONObject json = jsonArray.getJSONObject(i);
handleTreatmentFromNS(json, action);
}
}
} catch (JSONException e) {
aapsLogger.error(LTag.DATASERVICE, "Unhandled exception", e);
}
}
if (action.equals(Intents.ACTION_REMOVED_TREATMENT)) {
try {
if (bundle.containsKey("treatment")) {
String trstring = bundle.getString("treatment");
JSONObject json = new JSONObject(trstring);
handleRemovedTreatmentFromNS(json);
}
if (bundle.containsKey("treatments")) {
String trstring = bundle.getString("treatments");
JSONArray jsonArray = new JSONArray(trstring);
for (int i = 0; i < jsonArray.length(); i++) {
JSONObject json = jsonArray.getJSONObject(i);
handleRemovedTreatmentFromNS(json);
}
}
} catch (JSONException e) {
aapsLogger.error(LTag.DATASERVICE, "Unhandled exception", e);
}
}
if (action.equals(Intents.ACTION_NEW_MBG)) {
try {
if (bundle.containsKey("mbg")) {
String mbgstring = bundle.getString("mbg");
JSONObject mbgJson = new JSONObject(mbgstring);
storeMbg(mbgJson);
}
if (bundle.containsKey("mbgs")) {
String sgvstring = bundle.getString("mbgs");
JSONArray jsonArray = new JSONArray(sgvstring);
for (int i = 0; i < jsonArray.length(); i++) {
JSONObject mbgJson = jsonArray.getJSONObject(i);
storeMbg(mbgJson);
}
}
} catch (Exception e) {
aapsLogger.error(LTag.DATASERVICE, "Unhandled exception", e);
}
}
}
private void handleRemovedTreatmentFromNS(JSONObject json) {
String _id = JsonHelper.safeGetString(json, "_id");
if (_id == null) return;
// room Temporary target
TemporaryTarget temporaryTarget = temporaryTargetFromNsIdForInvalidating(_id);
disposable.add(repository.runTransactionForResult(new SyncTemporaryTargetTransaction(temporaryTarget)).subscribe(
result -> result.getInvalidated().forEach(record -> uel.log("TT DELETED FROM NS", record.getReason().getText(), record.getLowTarget(), record.getHighTarget(), (int) record.getDuration(), 0)),
error -> aapsLogger.error(LTag.DATABASE, "Error while removing temporary target", error)));
// room Therapy Event
TherapyEvent therapyEvent = therapyEventFromNsIdForInvalidating(_id);
disposable.add(repository.runTransactionForResult(new SyncTherapyEventTransaction(therapyEvent)).subscribe(
result -> result.getInvalidated().forEach(record -> uel.log("CAREPORTAL EVENT DELETED FROM NS", record.getType().getText(), 0.0, 0.0, 0, 0)),
error -> aapsLogger.error(LTag.DATABASE, "Error while removing therapy event", error)));
// new DB model
EventNsTreatment evtTreatment = new EventNsTreatment(EventNsTreatment.Companion.getREMOVE(), json);
rxBus.send(evtTreatment);
// old DB model
databaseHelper.deleteTempBasalById(_id);
databaseHelper.deleteExtendedBolusById(_id);
databaseHelper.deleteProfileSwitchById(_id);
}
private void handleTreatmentFromNS(JSONObject json, String action) {
// new DB model
int mode = Intents.ACTION_NEW_TREATMENT.equals(action) ? EventNsTreatment.Companion.getADD() : EventNsTreatment.Companion.getUPDATE();
double insulin = JsonHelper.safeGetDouble(json, "insulin");
double carbs = JsonHelper.safeGetDouble(json, "carbs");
String eventType = JsonHelper.safeGetString(json, "eventType");
if (eventType == null) {
aapsLogger.debug(LTag.DATASERVICE, "Wrong treatment. Ignoring : " + json.toString());
return;
}
if (insulin > 0 || carbs > 0) {
EventNsTreatment evtTreatment = new EventNsTreatment(mode, json);
rxBus.send(evtTreatment);
} else if (eventType.equals(TherapyEvent.Type.TEMPORARY_TARGET.getText())) {
TemporaryTarget temporaryTarget = temporaryTargetFromJson(json);
if (temporaryTarget != null) {
disposable.add(repository.runTransactionForResult(new SyncTemporaryTargetTransaction(temporaryTarget))
.subscribe(
result -> {
result.getInserted().forEach(record -> uel.log("TT FROM NS", record.getReason().getText(), record.getLowTarget(), record.getHighTarget(), (int) record.getDuration(), 0));
result.getInvalidated().forEach(record -> uel.log("TT DELETED FROM NS", record.getReason().getText(), record.getLowTarget(), record.getHighTarget(), (int) record.getDuration(), 0));
result.getEnded().forEach(record -> uel.log("TT CANCELED FROM NS", record.getReason().getText(), record.getLowTarget(), record.getHighTarget(), (int) record.getDuration(), 0));
},
error -> aapsLogger.error(LTag.DATABASE, "Error while saving temporary target", error)));
} else {
aapsLogger.error("Error parsing TT json " + json.toString());
}
} else if (eventType.equals(TherapyEvent.Type.TEMPORARY_BASAL.getText())) {
databaseHelper.createTempBasalFromJsonIfNotExists(json);
} else if (eventType.equals(TherapyEvent.Type.COMBO_BOLUS.getText())) {
databaseHelper.createExtendedBolusFromJsonIfNotExists(json);
} else if (eventType.equals(TherapyEvent.Type.PROFILE_SWITCH.getText())) {
databaseHelper.createProfileSwitchFromJsonIfNotExists(activePlugin, nsUpload, json);
} else if (eventType.equals(TherapyEvent.Type.CANNULA_CHANGE.getText()) ||
eventType.equals(TherapyEvent.Type.INSULIN_CHANGE.getText()) ||
eventType.equals(TherapyEvent.Type.SENSOR_CHANGE.getText()) ||
eventType.equals(TherapyEvent.Type.FINGER_STICK_BG_VALUE.getText()) ||
eventType.equals(TherapyEvent.Type.NOTE.getText()) ||
eventType.equals(TherapyEvent.Type.NONE.getText()) ||
eventType.equals(TherapyEvent.Type.ANNOUNCEMENT.getText()) ||
eventType.equals(TherapyEvent.Type.QUESTION.getText()) ||
eventType.equals(TherapyEvent.Type.EXERCISE.getText()) ||
eventType.equals(TherapyEvent.Type.APS_OFFLINE.getText()) ||
eventType.equals(TherapyEvent.Type.PUMP_BATTERY_CHANGE.getText())) {
TherapyEvent therapyEvent = therapyEventFromJson(json);
if (therapyEvent != null) {
disposable.add(repository.runTransactionForResult(new SyncTherapyEventTransaction(therapyEvent))
.subscribe(
result -> {
result.getInserted().forEach(record -> uel.log("CAREPORTAL EVENT NS", record.getType().getText(), 0.0, 0.0, 0, 0));
result.getInvalidated().forEach(record -> uel.log("CAREPORTAL EVENT DELETED FROM NS", "", 0.0, 0.0, (int) record.getTimestamp(), 0));
},
error -> aapsLogger.error(LTag.DATABASE, "Error while saving therapy event", error)));
} else {
aapsLogger.error("Error parsing TherapyEvent json " + json.toString());
}
}
if (eventType.equals(TherapyEvent.Type.ANNOUNCEMENT.getText())) {
long date = JsonHelper.safeGetLong(json, "mills");
long now = System.currentTimeMillis();
String enteredBy = JsonHelper.safeGetString(json, "enteredBy", "");
String notes = JsonHelper.safeGetString(json, "notes", "");
if (date > now - 15 * 60 * 1000L && !notes.isEmpty()
&& !enteredBy.equals(sp.getString("careportal_enteredby", "AndroidAPS"))) {
boolean defaultVal = config.getNSCLIENT();
if (sp.getBoolean(R.string.key_ns_announcements, defaultVal)) {
Notification announcement = new Notification(Notification.NS_ANNOUNCEMENT, notes, Notification.ANNOUNCEMENT, 60);
rxBus.send(new EventNewNotification(announcement));
}
}
}
}
private void storeMbg(JSONObject mbgJson) {
NSMbg nsMbg = new NSMbg(getInjector(), mbgJson);
if (nsMbg.mbg != 0.0 && nsMbg.date != 0)
disposable.add(repository.runTransactionForResult(new SyncTherapyEventTransaction(therapyEventFromNsMbg(nsMbg)))
.subscribe(
result -> aapsLogger.debug(LTag.DATABASE, "Saved therapy event" + result),
error -> aapsLogger.error("Error while saving therapy event", error))
);
public void updateLatestDateReceivedIfNewer(long latestReceived) {
if (latestReceived > nsClientService.latestDateInReceivedData)
nsClientService.latestDateInReceivedData = latestReceived;
}
}

View file

@ -0,0 +1,111 @@
package info.nightscout.androidaps.plugins.general.nsclient
import android.content.Context
import androidx.work.Worker
import androidx.work.WorkerParameters
import dagger.android.HasAndroidInjector
import info.nightscout.androidaps.R
import info.nightscout.androidaps.database.AppRepository
import info.nightscout.androidaps.database.entities.UserEntry
import info.nightscout.androidaps.database.entities.UserEntry.ValueWithUnit
import info.nightscout.androidaps.database.transactions.SyncTemporaryTargetTransaction
import info.nightscout.androidaps.database.transactions.SyncTherapyEventTransaction
import info.nightscout.androidaps.events.EventNsTreatment
import info.nightscout.androidaps.events.EventNsTreatment.Companion.REMOVE
import info.nightscout.androidaps.interfaces.ConfigInterface
import info.nightscout.androidaps.interfaces.DatabaseHelperInterface
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.receivers.DataWorker
import info.nightscout.androidaps.utils.JsonHelper
import info.nightscout.androidaps.utils.buildHelper.BuildHelper
import info.nightscout.androidaps.utils.extensions.temporaryTargetFromNsIdForInvalidating
import info.nightscout.androidaps.utils.extensions.therapyEventFromNsIdForInvalidating
import info.nightscout.androidaps.utils.sharedPreferences.SP
import javax.inject.Inject
// This will not be needed fpr NS v3
// Now NS provides on _id of removed records
class NSClientRemoveWorker(
context: Context,
params: WorkerParameters) : Worker(context, params) {
@Inject lateinit var nsClientPlugin: NSClientPlugin
@Inject lateinit var dataWorker: DataWorker
@Inject lateinit var aapsLogger: AAPSLogger
@Inject lateinit var buildHelper: BuildHelper
@Inject lateinit var sp: SP
@Inject lateinit var config: ConfigInterface
@Inject lateinit var repository: AppRepository
@Inject lateinit var databaseHelper: DatabaseHelperInterface
@Inject lateinit var rxBus: RxBusWrapper
@Inject lateinit var uel: UserEntryLogger
override fun doWork(): Result {
val acceptNSData = !sp.getBoolean(R.string.key_ns_upload_only, true) && buildHelper.isEngineeringMode() || config.NSCLIENT
if (!acceptNSData) return Result.failure()
var ret = Result.success()
val treatments = dataWorker.pickupJSONArray(inputData.getLong(DataWorker.STORE_KEY, -1))
?: return Result.failure()
for (i in 0 until treatments.length()) {
val json = treatments.getJSONObject(i)
val nsId = JsonHelper.safeGetString(json, "_id") ?: continue
// room Temporary target
val temporaryTarget = temporaryTargetFromNsIdForInvalidating(nsId)
repository.runTransactionForResult(SyncTemporaryTargetTransaction(temporaryTarget))
.doOnError {
aapsLogger.error(LTag.DATABASE, "Error while removing temporary target", it)
ret = Result.failure()
}
.blockingGet()
.also { result ->
result.invalidated.forEach {
uel.log(
UserEntry.Action.TT_DELETED_FROM_NS,
ValueWithUnit(it.reason.text, UserEntry.Units.TherapyEvent),
ValueWithUnit(it.lowTarget, UserEntry.Units.Mg_Dl, true),
ValueWithUnit(it.highTarget, UserEntry.Units.Mg_Dl, it.lowTarget != it.highTarget),
ValueWithUnit(it.duration.toInt() / 60000, UserEntry.Units.M, it.duration != 0L)
)
}
}
// room Therapy Event
val therapyEvent = therapyEventFromNsIdForInvalidating(nsId)
repository.runTransactionForResult(SyncTherapyEventTransaction(therapyEvent))
.doOnError {
aapsLogger.error(LTag.DATABASE, "Error while removing therapy event", it)
ret = Result.failure()
}
.blockingGet()
.also { result ->
result.invalidated.forEach {
uel.log(
UserEntry.Action.CAREPORTAL_DELETED_FROM_NS, (it.note ?: ""),
ValueWithUnit(it.timestamp, UserEntry.Units.Timestamp, true),
ValueWithUnit(it.type.text, UserEntry.Units.TherapyEvent))
}
}
// Insulin, carbs
rxBus.send(EventNsTreatment(REMOVE, json))
// old DB model
databaseHelper.deleteTempBasalById(nsId)
databaseHelper.deleteExtendedBolusById(nsId)
databaseHelper.deleteProfileSwitchById(nsId)
}
return ret
}
init {
(context.applicationContext as HasAndroidInjector).androidInjector().inject(this)
}
}

View file

@ -1,41 +0,0 @@
package info.nightscout.androidaps.plugins.general.nsclient;
import android.content.Context;
import android.os.Bundle;
import androidx.annotation.NonNull;
import androidx.work.Worker;
import androidx.work.WorkerParameters;
import androidx.annotation.NonNull;
import javax.inject.Inject;
import dagger.android.HasAndroidInjector;
import info.nightscout.androidaps.receivers.BundleStore;
import info.nightscout.androidaps.receivers.DataReceiver;
// cannot be inner class because of needed injection
public class NSClientWorker extends Worker {
public NSClientWorker(
@NonNull Context context,
@NonNull WorkerParameters params) {
super(context, params);
((HasAndroidInjector) context.getApplicationContext()).androidInjector().inject(this);
}
@Inject NSClientPlugin nsClientPlugin;
@Inject BundleStore bundleStore;
@NonNull
@Override
public Result doWork() {
Bundle bundle = bundleStore.pickup(getInputData().getLong(DataReceiver.STORE_KEY, -1));
if (bundle == null) return Result.failure();
String action = getInputData().getString(DataReceiver.ACTION_KEY);
nsClientPlugin.handleNewDataFromNSClient(action, bundle);
return Result.success();
}
}

View file

@ -11,12 +11,11 @@ import org.json.JSONObject;
import java.sql.SQLException;
import javax.inject.Inject;
import info.nightscout.androidaps.R;
import info.nightscout.androidaps.db.DatabaseHelper;
import info.nightscout.androidaps.db.DbRequest;
import info.nightscout.androidaps.interfaces.DatabaseHelperInterface;
import info.nightscout.androidaps.interfaces.UploadQueueAdminInterface;
import info.nightscout.androidaps.interfaces.UploadQueueInterface;
import info.nightscout.androidaps.logging.AAPSLogger;
import info.nightscout.androidaps.logging.LTag;
@ -28,14 +27,13 @@ import info.nightscout.androidaps.utils.sharedPreferences.SP;
/**
* Created by mike on 21.02.2016.
*/
public class UploadQueue implements UploadQueueInterface {
public class UploadQueue implements UploadQueueAdminInterface {
private final AAPSLogger aapsLogger;
private final DatabaseHelperInterface databaseHelper;
private final Context context;
private final SP sp;
private final RxBusWrapper rxBus;
@Inject
public UploadQueue(
AAPSLogger aapsLogger,
DatabaseHelperInterface databaseHelper,
@ -54,6 +52,7 @@ public class UploadQueue implements UploadQueueInterface {
return "QUEUE: " + databaseHelper.size(DatabaseHelper.DATABASE_DBREQUESTS);
}
@Override
public long size() {
return databaseHelper.size(DatabaseHelper.DATABASE_DBREQUESTS);
}
@ -76,7 +75,7 @@ public class UploadQueue implements UploadQueueInterface {
rxBus.send(new EventNSClientResend("newdata"));
}
void clearQueue() {
@Override public void clearQueue() {
startService();
if (NSClientService.handler != null) {
NSClientService.handler.post(() -> {
@ -87,7 +86,8 @@ public class UploadQueue implements UploadQueueInterface {
}
}
public void removeID(final JSONObject record) {
@Override
public void removeByNsClientIdIfExists(final JSONObject record) {
startService();
if (NSClientService.handler != null) {
NSClientService.handler.post(() -> {
@ -108,7 +108,8 @@ public class UploadQueue implements UploadQueueInterface {
}
}
public void removeID(final String action, final String _id) {
@Override
public void removeByMongoId(final String action, final String _id) {
if (_id == null || _id.equals(""))
return;
startService();
@ -120,7 +121,7 @@ public class UploadQueue implements UploadQueueInterface {
}
}
String textList() {
@Override public String textList() {
String result = "";
CloseableIterator<DbRequest> iterator;
try {

View file

@ -1,481 +0,0 @@
package info.nightscout.androidaps.plugins.general.nsclient.data;
import android.text.Spanned;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import javax.inject.Inject;
import javax.inject.Singleton;
import dagger.android.HasAndroidInjector;
import info.nightscout.androidaps.R;
import info.nightscout.androidaps.interfaces.ConfigInterface;
import info.nightscout.androidaps.logging.AAPSLogger;
import info.nightscout.androidaps.logging.LTag;
import info.nightscout.androidaps.plugins.aps.loop.APSResult;
import info.nightscout.androidaps.plugins.configBuilder.RunningConfiguration;
import info.nightscout.androidaps.utils.DateUtil;
import info.nightscout.androidaps.utils.HtmlHelper;
import info.nightscout.androidaps.utils.Round;
import info.nightscout.androidaps.utils.resources.ResourceHelper;
import info.nightscout.androidaps.utils.sharedPreferences.SP;
/**
* Created by mike on 25.06.2017.
*/
/*
{
"_id": "594fdcec327b83c81b6b8c0f",
"device": "openaps://Sony D5803",
"pump": {
"battery": {
"percent": 100
},
"status": {
"status": "normal",
"timestamp": "2017-06-25T15:50:14Z"
},
"extended": {
"Version": "1.5-ac98852-2017.06.25",
"PumpIOB": 1.13,
"LastBolus": "25. 6. 2017 17:25:00",
"LastBolusAmount": 0.3,
"BaseBasalRate": 0.4,
"ActiveProfile": "2016 +30%"
},
"reservoir": 109,
"clock": "2017-06-25T15:55:10Z"
},
"openaps": {
"suggested": {
"temp": "absolute",
"bg": 115.9,
"tick": "+5",
"eventualBG": 105,
"snoozeBG": 105,
"predBGs": {
"IOB": [116, 114, 112, 110, 109, 107, 106, 105, 105, 104, 104, 104, 104, 104, 104, 104, 104, 105, 105, 105, 105, 105, 106, 106, 106, 106, 106, 107]
},
"COB": 0,
"IOB": -0.035,
"reason": "COB: 0, Dev: -18, BGI: 0.43, ISF: 216, Target: 99; Eventual BG 105 > 99 but Min. Delta -2.60 < Exp. Delta 0.1; setting current basal of 0.4 as temp. Suggested rate is same as profile rate, no temp basal is active, doing nothing",
"timestamp": "2017-06-25T15:55:10Z"
},
"iob": {
"iob": -0.035,
"basaliob": -0.035,
"activity": -0.0004,
"time": "2017-06-25T15:55:10Z"
}
},
"uploaderBattery": 93,
"created_at": "2017-06-25T15:55:10Z",
"NSCLIENT_ID": 1498406118857
}
*/
@Singleton
public class NSDeviceStatus {
private final AAPSLogger aapsLogger;
private final SP sp;
private final ResourceHelper resourceHelper;
private final NSSettingsStatus nsSettingsStatus;
private final ConfigInterface config;
private final RunningConfiguration runningConfiguration;
private JSONObject data = null;
@Inject
public NSDeviceStatus(
AAPSLogger aapsLogger,
SP sp,
ResourceHelper resourceHelper,
NSSettingsStatus nsSettingsStatus,
ConfigInterface config,
RunningConfiguration runningConfiguration
) {
this.aapsLogger = aapsLogger;
this.sp = sp;
this.resourceHelper = resourceHelper;
this.nsSettingsStatus = nsSettingsStatus;
this.config = config;
this.runningConfiguration = runningConfiguration;
}
public void handleNewData(JSONArray devicestatuses) {
aapsLogger.debug(LTag.NSCLIENT, "Got NS devicestatus: $devicestatuses}");
for (int i = 0; i < devicestatuses.length(); i++) {
try {
JSONObject devicestatusJson = devicestatuses.getJSONObject(i);
if (devicestatusJson != null) {
setData(devicestatusJson);
if (devicestatusJson.has("pump")) {
// Objectives 0
sp.putBoolean(R.string.key_ObjectivespumpStatusIsAvailableInNS, true);
}
if (devicestatusJson.has("configuration") && config.getNSCLIENT()) {
// copy configuration of Insulin and Sensitivity from main AAPS
runningConfiguration.apply(devicestatusJson.getJSONObject("configuration"));
}
}
} catch (JSONException jsonException) {
jsonException.printStackTrace();
}
}
}
public NSDeviceStatus setData(JSONObject obj) {
this.data = obj;
updatePumpData();
updateOpenApsData(obj);
updateUploaderData(obj);
return this;
}
public String getDevice() {
try {
if (data.has("device")) {
String device = data.getString("device");
if (device.startsWith("openaps://")) {
device = device.substring(10);
return device;
}
}
} catch (JSONException e) {
aapsLogger.error("Unhandled exception", e);
}
return "";
}
public static class Levels {
static int URGENT = 2;
static int WARN = 1;
static int INFO = 0;
int LOW = -1;
int LOWEST = -2;
static int NONE = -3;
}
// ***** PUMP DATA ******
private DeviceStatusPumpData deviceStatusPumpData = null;
public Spanned getExtendedPumpStatus() {
if (deviceStatusPumpData != null && deviceStatusPumpData.extended != null)
return deviceStatusPumpData.extended;
return HtmlHelper.INSTANCE.fromHtml("");
}
public Spanned getPumpStatus() {
//String[] ALL_STATUS_FIELDS = {"reservoir", "battery", "clock", "status", "device"};
StringBuilder string = new StringBuilder();
string.append("<span style=\"color:" + resourceHelper.gcs(R.color.defaulttext) + "\">");
string.append(resourceHelper.gs(R.string.pump));
string.append(": </span>");
if (deviceStatusPumpData == null)
return HtmlHelper.INSTANCE.fromHtml("");
// test warning level
int level = Levels.INFO;
long now = System.currentTimeMillis();
if (deviceStatusPumpData.clock + nsSettingsStatus.extendedPumpSettings("urgentClock") * 60 * 1000L < now)
level = Levels.URGENT;
else if (deviceStatusPumpData.reservoir < nsSettingsStatus.extendedPumpSettings("urgentRes"))
level = Levels.URGENT;
else if (deviceStatusPumpData.isPercent && deviceStatusPumpData.percent < nsSettingsStatus.extendedPumpSettings("urgentBattP"))
level = Levels.URGENT;
else if (!deviceStatusPumpData.isPercent && deviceStatusPumpData.voltage < nsSettingsStatus.extendedPumpSettings("urgentBattV"))
level = Levels.URGENT;
else if (deviceStatusPumpData.clock + nsSettingsStatus.extendedPumpSettings("warnClock") * 60 * 1000L < now)
level = Levels.WARN;
else if (deviceStatusPumpData.reservoir < nsSettingsStatus.extendedPumpSettings("warnRes"))
level = Levels.WARN;
else if (deviceStatusPumpData.isPercent && deviceStatusPumpData.percent < nsSettingsStatus.extendedPumpSettings("warnBattP"))
level = Levels.WARN;
else if (!deviceStatusPumpData.isPercent && deviceStatusPumpData.voltage < nsSettingsStatus.extendedPumpSettings("warnBattV"))
level = Levels.WARN;
string.append("<span style=\"color:");
if (level == Levels.INFO) string.append("white\">");
if (level == Levels.WARN) string.append("yellow\">");
if (level == Levels.URGENT) string.append("red\">");
String fields = nsSettingsStatus.pumpExtendedSettingsFields();
if (fields.contains("reservoir")) {
string.append((int) deviceStatusPumpData.reservoir).append("U ");
}
if (fields.contains("battery") && deviceStatusPumpData.isPercent) {
string.append(deviceStatusPumpData.percent).append("% ");
}
if (fields.contains("battery") && !deviceStatusPumpData.isPercent) {
string.append(Round.roundTo(deviceStatusPumpData.voltage, 0.001d)).append(" ");
}
if (fields.contains("clock")) {
string.append(DateUtil.minAgo(resourceHelper, deviceStatusPumpData.clock)).append(" ");
}
if (fields.contains("status")) {
string.append(deviceStatusPumpData.status).append(" ");
}
if (fields.contains("device")) {
string.append(getDevice()).append(" ");
}
string.append("</span>"); // color
return HtmlHelper.INSTANCE.fromHtml(string.toString());
}
static class DeviceStatusPumpData {
long clock = 0L;
boolean isPercent = false;
int percent = 0;
double voltage = 0;
String status = "N/A";
double reservoir = 0d;
Spanned extended = null;
}
private void updatePumpData() {
try {
JSONObject pump = data != null && data.has("pump") ? data.getJSONObject("pump") : new JSONObject();
long clock = 0L;
if (pump.has("clock"))
clock = DateUtil.fromISODateString(pump.getString("clock")).getTime();
// check if this is new data
if (clock == 0 || deviceStatusPumpData != null && clock < deviceStatusPumpData.clock)
return;
// create new status and process data
deviceStatusPumpData = new DeviceStatusPumpData();
deviceStatusPumpData.clock = clock;
if (pump.has("status") && pump.getJSONObject("status").has("status"))
deviceStatusPumpData.status = pump.getJSONObject("status").getString("status");
if (pump.has("reservoir"))
deviceStatusPumpData.reservoir = pump.getDouble("reservoir");
if (pump.has("battery") && pump.getJSONObject("battery").has("percent")) {
deviceStatusPumpData.isPercent = true;
deviceStatusPumpData.percent = pump.getJSONObject("battery").getInt("percent");
} else if (pump.has("battery") && pump.getJSONObject("battery").has("voltage")) {
deviceStatusPumpData.isPercent = false;
deviceStatusPumpData.voltage = pump.getJSONObject("battery").getDouble("voltage");
}
if (pump.has("extended")) {
JSONObject extendedJson = pump.getJSONObject("extended");
StringBuilder exteneded = new StringBuilder();
Iterator<?> keys = extendedJson.keys();
while (keys.hasNext()) {
String key = (String) keys.next();
String value = extendedJson.getString(key);
exteneded.append("<b>").append(key).append(":</b> ").append(value).append("<br>");
}
deviceStatusPumpData.extended = HtmlHelper.INSTANCE.fromHtml(exteneded.toString());
}
} catch (Exception e) {
aapsLogger.error("Unhandled exception", e);
}
}
// ********* OpenAPS data ***********
public static DeviceStatusOpenAPSData deviceStatusOpenAPSData = new DeviceStatusOpenAPSData();
public static class DeviceStatusOpenAPSData {
public long clockSuggested = 0L;
public long clockEnacted = 0L;
public JSONObject suggested = null;
public JSONObject enacted = null;
}
private void updateOpenApsData(JSONObject object) {
try {
JSONObject openaps = object.has("openaps") ? object.getJSONObject("openaps") : new JSONObject();
JSONObject suggested = openaps.has("suggested") ? openaps.getJSONObject("suggested") : new JSONObject();
JSONObject enacted = openaps.has("enacted") ? openaps.getJSONObject("enacted") : new JSONObject();
long clock = 0L;
if (suggested.has("timestamp"))
clock = DateUtil.fromISODateString(suggested.getString("timestamp")).getTime();
// check if this is new data
if (clock != 0 && clock > deviceStatusOpenAPSData.clockSuggested) {
deviceStatusOpenAPSData.suggested = suggested;
deviceStatusOpenAPSData.clockSuggested = clock;
}
clock = 0L;
if (enacted.has("timestamp"))
clock = DateUtil.fromISODateString(enacted.getString("timestamp")).getTime();
// check if this is new data
if (clock != 0 && clock > deviceStatusOpenAPSData.clockEnacted) {
deviceStatusOpenAPSData.enacted = enacted;
deviceStatusOpenAPSData.clockEnacted = clock;
}
} catch (Exception e) {
aapsLogger.error("Unhandled exception", e);
}
}
public Spanned getOpenApsStatus() {
StringBuilder string = new StringBuilder();
string.append("<span style=\"color:" + resourceHelper.gcs(R.color.defaulttext) + "\">");
string.append(resourceHelper.gs(R.string.openaps_short));
string.append(": </span>");
// test warning level
int level = Levels.INFO;
long now = System.currentTimeMillis();
if (deviceStatusOpenAPSData.clockSuggested != 0 && deviceStatusOpenAPSData.clockSuggested + sp.getInt(R.string.key_nsalarm_urgent_staledatavalue, 31) * 60 * 1000L < now)
level = Levels.URGENT;
else if (deviceStatusOpenAPSData.clockSuggested != 0 && deviceStatusOpenAPSData.clockSuggested + sp.getInt(R.string.key_nsalarm_staledatavalue, 16) * 60 * 1000L < now)
level = Levels.WARN;
string.append("<span style=\"color:");
if (level == Levels.INFO) string.append("white\">");
if (level == Levels.WARN) string.append("yellow\">");
if (level == Levels.URGENT) string.append("red\">");
if (deviceStatusOpenAPSData.clockSuggested != 0) {
string.append(DateUtil.minAgo(resourceHelper, deviceStatusOpenAPSData.clockSuggested)).append(" ");
}
string.append("</span>"); // color
return HtmlHelper.INSTANCE.fromHtml(string.toString());
}
public static long getOpenApsTimestamp() {
if (deviceStatusOpenAPSData.clockSuggested != 0) {
return deviceStatusOpenAPSData.clockSuggested;
} else {
return -1;
}
}
public Spanned getExtendedOpenApsStatus() {
StringBuilder string = new StringBuilder();
try {
if (deviceStatusOpenAPSData.enacted != null && deviceStatusOpenAPSData.clockEnacted != deviceStatusOpenAPSData.clockSuggested)
string.append("<b>").append(DateUtil.minAgo(resourceHelper, deviceStatusOpenAPSData.clockEnacted)).append("</b> ").append(deviceStatusOpenAPSData.enacted.getString("reason")).append("<br>");
if (deviceStatusOpenAPSData.suggested != null)
string.append("<b>").append(DateUtil.minAgo(resourceHelper, deviceStatusOpenAPSData.clockSuggested)).append("</b> ").append(deviceStatusOpenAPSData.suggested.getString("reason")).append("<br>");
return HtmlHelper.INSTANCE.fromHtml(string.toString());
} catch (JSONException e) {
aapsLogger.error("Unhandled exception", e);
}
return HtmlHelper.INSTANCE.fromHtml("");
}
// ********* Uploader data ***********
private static final HashMap<String, Uploader> uploaders = new HashMap<>();
static class Uploader {
long clock = 0L;
int battery = 0;
}
private void updateUploaderData(JSONObject object) {
try {
long clock = 0L;
if (object.has("mills"))
clock = object.getLong("mills");
else if (object.has("created_at"))
clock = DateUtil.fromISODateString(object.getString("created_at")).getTime();
String device = getDevice();
Integer battery = null;
if (object.has("uploaderBattery"))
battery = object.getInt("uploaderBattery");
else if (object.has("uploader")) {
if (object.getJSONObject("uploader").has("battery"))
battery = object.getJSONObject("uploader").getInt("battery");
}
Uploader uploader = uploaders.get(device);
// check if this is new data
if (clock != 0 && battery != null && (uploader == null || clock > uploader.clock)) {
if (uploader == null)
uploader = new Uploader();
uploader.battery = battery;
uploader.clock = clock;
uploaders.put(device, uploader);
}
} catch (Exception e) {
aapsLogger.error("Unhandled exception", e);
}
}
public String getUploaderStatus() {
Iterator iter = uploaders.entrySet().iterator();
int minBattery = 100;
while (iter.hasNext()) {
Map.Entry pair = (Map.Entry) iter.next();
Uploader uploader = (Uploader) pair.getValue();
if (minBattery > uploader.battery)
minBattery = uploader.battery;
}
return minBattery + "%";
}
public Spanned getUploaderStatusSpanned() {
StringBuilder string = new StringBuilder();
string.append("<span style=\"color:" + resourceHelper.gcs(R.color.defaulttext) + "\">");
string.append(resourceHelper.gs(R.string.uploader_short));
string.append(": </span>");
Iterator iter = uploaders.entrySet().iterator();
int minBattery = 100;
while (iter.hasNext()) {
Map.Entry pair = (Map.Entry) iter.next();
Uploader uploader = (Uploader) pair.getValue();
if (minBattery > uploader.battery)
minBattery = uploader.battery;
}
string.append(minBattery);
string.append("%");
return HtmlHelper.INSTANCE.fromHtml(string.toString());
}
public Spanned getExtendedUploaderStatus() {
StringBuilder string = new StringBuilder();
Iterator iter = uploaders.entrySet().iterator();
while (iter.hasNext()) {
Map.Entry pair = (Map.Entry) iter.next();
Uploader uploader = (Uploader) pair.getValue();
String device = (String) pair.getKey();
string.append("<b>").append(device).append(":</b> ").append(uploader.battery).append("%<br>");
}
return HtmlHelper.INSTANCE.fromHtml(string.toString());
}
public static APSResult getAPSResult(HasAndroidInjector injector) {
APSResult result = new APSResult(injector);
result.setJson(deviceStatusOpenAPSData.suggested);
result.setDate(deviceStatusOpenAPSData.clockSuggested);
return result;
}
}

View file

@ -0,0 +1,396 @@
package info.nightscout.androidaps.plugins.general.nsclient.data
import android.text.Spanned
import dagger.android.HasAndroidInjector
import info.nightscout.androidaps.R
import info.nightscout.androidaps.interfaces.ConfigInterface
import info.nightscout.androidaps.logging.AAPSLogger
import info.nightscout.androidaps.logging.LTag
import info.nightscout.androidaps.plugins.aps.loop.APSResult
import info.nightscout.androidaps.plugins.configBuilder.RunningConfiguration
import info.nightscout.androidaps.utils.DateUtil
import info.nightscout.androidaps.utils.HtmlHelper.fromHtml
import info.nightscout.androidaps.utils.Round
import info.nightscout.androidaps.utils.T
import info.nightscout.androidaps.utils.resources.ResourceHelper
import info.nightscout.androidaps.utils.sharedPreferences.SP
import org.json.JSONArray
import org.json.JSONException
import org.json.JSONObject
import java.util.*
import javax.inject.Inject
import javax.inject.Singleton
/*
{
"_id": "594fdcec327b83c81b6b8c0f",
"device": "openaps://Sony D5803",
"pump": {
"battery": {
"percent": 100
},
"status": {
"status": "normal",
"timestamp": "2017-06-25T15:50:14Z"
},
"extended": {
"Version": "1.5-ac98852-2017.06.25",
"PumpIOB": 1.13,
"LastBolus": "25. 6. 2017 17:25:00",
"LastBolusAmount": 0.3,
"BaseBasalRate": 0.4,
"ActiveProfile": "2016 +30%"
},
"reservoir": 109,
"clock": "2017-06-25T15:55:10Z"
},
"openaps": {
"suggested": {
"temp": "absolute",
"bg": 115.9,
"tick": "+5",
"eventualBG": 105,
"snoozeBG": 105,
"predBGs": {
"IOB": [116, 114, 112, 110, 109, 107, 106, 105, 105, 104, 104, 104, 104, 104, 104, 104, 104, 105, 105, 105, 105, 105, 106, 106, 106, 106, 106, 107]
},
"COB": 0,
"IOB": -0.035,
"reason": "COB: 0, Dev: -18, BGI: 0.43, ISF: 216, Target: 99; Eventual BG 105 > 99 but Min. Delta -2.60 < Exp. Delta 0.1; setting current basal of 0.4 as temp. Suggested rate is same as profile rate, no temp basal is active, doing nothing",
"timestamp": "2017-06-25T15:55:10Z"
},
"iob": {
"iob": -0.035,
"basaliob": -0.035,
"activity": -0.0004,
"time": "2017-06-25T15:55:10Z"
}
},
"uploaderBattery": 93,
"created_at": "2017-06-25T15:55:10Z",
"NSCLIENT_ID": 1498406118857
}
*/
@Suppress("SpellCheckingInspection")
@Singleton
class NSDeviceStatus @Inject constructor(
private val aapsLogger: AAPSLogger,
private val sp: SP,
private val resourceHelper: ResourceHelper,
private val nsSettingsStatus: NSSettingsStatus,
private val config: ConfigInterface,
private val dateUtil: DateUtil,
private val runningConfiguration: RunningConfiguration
) {
private var data: JSONObject? = null
fun handleNewData(deviceStatuses: JSONArray) {
aapsLogger.debug(LTag.NSCLIENT, "Got NS deviceStatus: \$deviceStatuses}")
try {
for (i in 0 until deviceStatuses.length()) {
val devicestatusJson = deviceStatuses.getJSONObject(i)
if (devicestatusJson != null) {
setData(devicestatusJson)
if (devicestatusJson.has("pump")) {
// Objectives 0
sp.putBoolean(R.string.key_ObjectivespumpStatusIsAvailableInNS, true)
}
if (devicestatusJson.has("configuration") && config.NSCLIENT) {
// copy configuration of Insulin and Sensitivity from main AAPS
runningConfiguration.apply(devicestatusJson.getJSONObject("configuration"))
}
}
}
} catch (jsonException: JSONException) {
jsonException.printStackTrace()
}
}
private fun setData(obj: JSONObject): NSDeviceStatus {
data = obj
updatePumpData()
updateOpenApsData(obj)
updateUploaderData(obj)
return this
}
val device: String
get() {
try {
if (data!!.has("device")) {
var device = data!!.getString("device")
if (device.startsWith("openaps://")) {
device = device.substring(10)
return device
}
}
} catch (e: JSONException) {
aapsLogger.error("Unhandled exception", e)
}
return ""
}
enum class Levels(val level: Int) {
URGENT(2),
WARN(1),
INFO(0);
fun toColor(): String =
when (level) {
INFO.level -> "white"
WARN.level -> "yellow"
URGENT.level -> "red"
else -> "white"
}
}
// ***** PUMP DATA ******
private var deviceStatusPumpData: DeviceStatusPumpData? = null
val extendedPumpStatus: Spanned
get() = deviceStatusPumpData?.extended ?: fromHtml("")
val pumpStatus: Spanned
// test warning level // color
get() {
val pumpData = deviceStatusPumpData ?: return fromHtml("")
//String[] ALL_STATUS_FIELDS = {"reservoir", "battery", "clock", "status", "device"};
val string = StringBuilder()
.append("<span style=\"color:${resourceHelper.gcs(R.color.defaulttext)}\">")
.append(resourceHelper.gs(R.string.pump))
.append(": </span>")
// test warning level
val level = when {
pumpData.clock + nsSettingsStatus.extendedPumpSettings("urgentClock") * 60 * 1000L < dateUtil._now() -> Levels.URGENT
pumpData.reservoir < nsSettingsStatus.extendedPumpSettings("urgentRes") -> Levels.URGENT
pumpData.isPercent && pumpData.percent < nsSettingsStatus.extendedPumpSettings("urgentBattP") -> Levels.URGENT
!pumpData.isPercent && pumpData.voltage < nsSettingsStatus.extendedPumpSettings("urgentBattV") -> Levels.URGENT
pumpData.clock + nsSettingsStatus.extendedPumpSettings("warnClock") * 60 * 1000L < dateUtil._now() -> Levels.WARN
pumpData.reservoir < nsSettingsStatus.extendedPumpSettings("warnRes") -> Levels.WARN
pumpData.isPercent && pumpData.percent < nsSettingsStatus.extendedPumpSettings("warnBattP") -> Levels.WARN
!pumpData.isPercent && pumpData.voltage < nsSettingsStatus.extendedPumpSettings("warnBattV") -> Levels.WARN
else -> Levels.INFO
}
string.append("<span style=\"color:${level.toColor()}\">")
val fields = nsSettingsStatus.pumpExtendedSettingsFields()
if (fields.contains("reservoir")) string.append(pumpData.reservoir.toInt()).append("U ")
if (fields.contains("battery") && pumpData.isPercent) string.append(pumpData.percent).append("% ")
if (fields.contains("battery") && !pumpData.isPercent) string.append(Round.roundTo(pumpData.voltage, 0.001)).append(" ")
if (fields.contains("clock")) string.append(DateUtil.minAgo(resourceHelper, pumpData.clock)).append(" ")
if (fields.contains("status")) string.append(pumpData.status).append(" ")
if (fields.contains("device")) string.append(device).append(" ")
string.append("</span>") // color
return fromHtml(string.toString())
}
internal class DeviceStatusPumpData {
var clock = 0L
var isPercent = false
var percent = 0
var voltage = 0.0
var status = "N/A"
var reservoir = 0.0
var extended: Spanned? = null
}
private fun updatePumpData() {
try {
val data = this.data ?: return
val pump = if (data.has("pump")) data.getJSONObject("pump") else JSONObject()
val clock = if (pump.has("clock")) DateUtil.fromISODateString(pump.getString("clock")).time else 0L
// check if this is new data
if (clock == 0L || deviceStatusPumpData != null && clock < deviceStatusPumpData!!.clock) return
// create new status and process data
val deviceStatusPumpData = DeviceStatusPumpData()
deviceStatusPumpData.clock = clock
if (pump.has("status") && pump.getJSONObject("status").has("status")) deviceStatusPumpData.status = pump.getJSONObject("status").getString("status")
if (pump.has("reservoir")) deviceStatusPumpData.reservoir = pump.getDouble("reservoir")
if (pump.has("battery") && pump.getJSONObject("battery").has("percent")) {
deviceStatusPumpData.isPercent = true
deviceStatusPumpData.percent = pump.getJSONObject("battery").getInt("percent")
} else if (pump.has("battery") && pump.getJSONObject("battery").has("voltage")) {
deviceStatusPumpData.isPercent = false
deviceStatusPumpData.voltage = pump.getJSONObject("battery").getDouble("voltage")
}
if (pump.has("extended")) {
val extendedJson = pump.getJSONObject("extended")
val extended = StringBuilder()
val keys: Iterator<*> = extendedJson.keys()
while (keys.hasNext()) {
val key = keys.next() as String
val value = extendedJson.getString(key)
extended.append("<b>").append(key).append(":</b> ").append(value).append("<br>")
}
deviceStatusPumpData.extended = fromHtml(extended.toString())
}
this.deviceStatusPumpData = deviceStatusPumpData
} catch (e: Exception) {
aapsLogger.error("Unhandled exception", e)
}
}
class DeviceStatusOpenAPSData {
var clockSuggested = 0L
var clockEnacted = 0L
var suggested: JSONObject? = null
var enacted: JSONObject? = null
}
private fun updateOpenApsData(jsonObject: JSONObject) {
try {
val openAps = if (jsonObject.has("openaps")) jsonObject.getJSONObject("openaps") else JSONObject()
val suggested = if (openAps.has("suggested")) openAps.getJSONObject("suggested") else JSONObject()
val enacted = if (openAps.has("enacted")) openAps.getJSONObject("enacted") else JSONObject()
var clock = if (suggested.has("timestamp")) DateUtil.fromISODateString(suggested.getString("timestamp")).time else 0L
// check if this is new data
if (clock != 0L && clock > deviceStatusOpenAPSData.clockSuggested) {
deviceStatusOpenAPSData.suggested = suggested
deviceStatusOpenAPSData.clockSuggested = clock
}
clock = if (enacted.has("timestamp")) DateUtil.fromISODateString(enacted.getString("timestamp")).time else 0L
// check if this is new data
if (clock != 0L && clock > deviceStatusOpenAPSData.clockEnacted) {
deviceStatusOpenAPSData.enacted = enacted
deviceStatusOpenAPSData.clockEnacted = clock
}
} catch (e: Exception) {
aapsLogger.error("Unhandled exception", e)
}
}
val openApsStatus: Spanned
get() {
val string = StringBuilder()
.append("<span style=\"color:${resourceHelper.gcs(R.color.defaulttext)}\">")
.append(resourceHelper.gs(R.string.openaps_short))
.append(": </span>")
// test warning level
val level = when {
deviceStatusOpenAPSData.clockSuggested + T.mins(sp.getLong(R.string.key_nsalarm_urgent_staledatavalue, 31)).msecs() < dateUtil._now() -> Levels.URGENT
deviceStatusOpenAPSData.clockSuggested + T.mins(sp.getLong(R.string.key_nsalarm_staledatavalue, 16)).msecs() < dateUtil._now() -> Levels.WARN
else -> Levels.INFO
}
string.append("<span style=\"color:${level.toColor()}\">")
if (deviceStatusOpenAPSData.clockSuggested != 0L) string.append(DateUtil.minAgo(resourceHelper, deviceStatusOpenAPSData.clockSuggested)).append(" ")
string.append("</span>") // color
return fromHtml(string.toString())
}
val extendedOpenApsStatus: Spanned
get() {
val string = StringBuilder()
try {
if (deviceStatusOpenAPSData.enacted != null && deviceStatusOpenAPSData.clockEnacted != deviceStatusOpenAPSData.clockSuggested) string.append("<b>").append(DateUtil.minAgo(resourceHelper, deviceStatusOpenAPSData.clockEnacted)).append("</b> ").append(deviceStatusOpenAPSData.enacted!!.getString("reason")).append("<br>")
if (deviceStatusOpenAPSData.suggested != null) string.append("<b>").append(DateUtil.minAgo(resourceHelper, deviceStatusOpenAPSData.clockSuggested)).append("</b> ").append(deviceStatusOpenAPSData.suggested!!.getString("reason")).append("<br>")
return fromHtml(string.toString())
} catch (e: JSONException) {
aapsLogger.error("Unhandled exception", e)
}
return fromHtml("")
}
internal class Uploader {
var clock = 0L
var battery = 0
}
private fun updateUploaderData(jsonObject: JSONObject) {
try {
val clock =
when {
jsonObject.has("mills") -> jsonObject.getLong("mills")
jsonObject.has("created_at") -> DateUtil.fromISODateString(jsonObject.getString("created_at")).time
else -> 0L
}
val device = device
val battery: Int =
when {
jsonObject.has("uploaderBattery") -> jsonObject.getInt("uploaderBattery")
jsonObject.has("uploader") && jsonObject.getJSONObject("uploader").has("battery") -> jsonObject.getJSONObject("uploader").getInt("battery")
else -> 0
}
var uploader = uploaderMap[device]
// check if this is new data
if (clock != 0L && battery != 0 && (uploader == null || clock > uploader.clock)) {
if (uploader == null) uploader = Uploader()
uploader.battery = battery
uploader.clock = clock
uploaderMap[device] = uploader
}
} catch (e: Exception) {
aapsLogger.error("Unhandled exception", e)
}
}
val uploaderStatus: String
get() {
val iterator: Iterator<*> = uploaderMap.entries.iterator()
var minBattery = 100
while (iterator.hasNext()) {
val pair = iterator.next() as Map.Entry<*, *>
val uploader = pair.value as Uploader
if (minBattery > uploader.battery) minBattery = uploader.battery
}
return "$minBattery%"
}
val uploaderStatusSpanned: Spanned
get() {
val string = StringBuilder()
string.append("<span style=\"color:${resourceHelper.gcs(R.color.defaulttext)}\">")
string.append(resourceHelper.gs(R.string.uploader_short))
string.append(": </span>")
val iterator: Iterator<*> = uploaderMap.entries.iterator()
var minBattery = 100
while (iterator.hasNext()) {
val pair = iterator.next() as Map.Entry<*, *>
val uploader = pair.value as Uploader
if (minBattery > uploader.battery) minBattery = uploader.battery
}
string.append(minBattery)
string.append("%")
return fromHtml(string.toString())
}
val extendedUploaderStatus: Spanned
get() {
val string = StringBuilder()
val iterator: Iterator<*> = uploaderMap.entries.iterator()
while (iterator.hasNext()) {
val pair = iterator.next() as Map.Entry<*, *>
val uploader = pair.value as Uploader
val device = pair.key as String
string.append("<b>").append(device).append(":</b> ").append(uploader.battery).append("%<br>")
}
return fromHtml(string.toString())
}
// ********* OpenAPS data ***********
var deviceStatusOpenAPSData = DeviceStatusOpenAPSData()
val openApsTimestamp: Long
get() =
if (deviceStatusOpenAPSData.clockSuggested != 0L) {
deviceStatusOpenAPSData.clockSuggested
} else {
-1
}
// ********* Uploader data ***********
private val uploaderMap = HashMap<String, Uploader>()
fun getAPSResult(injector: HasAndroidInjector): APSResult {
val result = APSResult(injector)
result.json = deviceStatusOpenAPSData.suggested
result.date = deviceStatusOpenAPSData.clockSuggested
return result
}
}

View file

@ -3,6 +3,7 @@ package info.nightscout.androidaps.plugins.general.nsclient.data
import android.content.Context
import info.nightscout.androidaps.Config
import info.nightscout.androidaps.R
import info.nightscout.androidaps.database.entities.UserEntry.Action
import info.nightscout.androidaps.logging.AAPSLogger
import info.nightscout.androidaps.logging.LTag
import info.nightscout.androidaps.logging.UserEntryLogger
@ -110,6 +111,7 @@ import javax.inject.Singleton
"activeProfile": "2016 +30%"
}
*/
@Suppress("SpellCheckingInspection")
@Singleton
class NSSettingsStatus @Inject constructor(
private val aapsLogger: AAPSLogger,
@ -121,15 +123,30 @@ class NSSettingsStatus @Inject constructor(
private val uel: UserEntryLogger
) {
var nightscoutVersionName = ""
// ***** PUMP STATUS ******
var data: JSONObject? = null
private var data: JSONObject? = null
fun handleNewData(nightscoutVersionName: String, nightscoutVersionCode: Int, status: JSONObject) {
this.nightscoutVersionName = nightscoutVersionName
aapsLogger.debug(LTag.NSCLIENT, "Got versions: Nightscout: $nightscoutVersionName")
if (nightscoutVersionCode != 0 && nightscoutVersionCode < config.SUPPORTEDNSVERSION) {
/* Other received data to 2016/02/10
{
status: 'ok'
, name: env.name
, version: env.version
, versionNum: versionNum (for ver 1.2.3 contains 10203)
, serverTime: new Date().toISOString()
, apiEnabled: apiEnabled
, careportalEnabled: apiEnabled && env.settings.enable.indexOf('careportal') > -1
, boluscalcEnabled: apiEnabled && env.settings.enable.indexOf('boluscalc') > -1
, head: env.head
, settings: env.settings
, extendedSettings: ctx.plugins && ctx.plugins.extendedClientSettings ? ctx.plugins.extendedClientSettings(env.extendedSettings) : {}
, activeProfile ..... calculated from treatments or missing
}
*/
fun handleNewData(status: JSONObject) {
data = status
aapsLogger.debug(LTag.NSCLIENT, "Got versions: Nightscout: ${getVersion()}")
if (getVersionNum() < config.SUPPORTEDNSVERSION) {
val notification = Notification(Notification.OLD_NS, resourceHelper.gs(R.string.unsupportednsversion), Notification.NORMAL)
rxBus.send(EventNewNotification(notification))
} else {
@ -144,13 +161,10 @@ class NSSettingsStatus @Inject constructor(
if (config.NSCLIENT) copyStatusLightsNsSettings(null)
}
fun getName(): String? =
JsonHelper.safeGetStringAllowNull(data, "name", null)
fun getVersion(): String =
JsonHelper.safeGetStringAllowNull(data, "version", null) ?: "UNKNOWN"
fun getVersion(): String? =
JsonHelper.safeGetStringAllowNull(data, "version", null)
fun getVersionNum(): Int =
private fun getVersionNum(): Int =
JsonHelper.safeGetInt(data, "versionNum")
private fun getSettings() =
@ -161,13 +175,13 @@ class NSSettingsStatus @Inject constructor(
// valid property is "warn" or "urgent"
// plugings "iage" "sage" "cage" "pbage"
fun getExtendedWarnValue(plugin: String, property: String): Double? {
private fun getExtendedWarnValue(plugin: String, property: String): Double? {
val extendedSettings = getExtendedSettings() ?: return null
val pluginJson = extendedSettings.optJSONObject(plugin) ?: return null
try {
return pluginJson.getDouble(property)
return try {
pluginJson.getDouble(property)
} catch (e: Exception) {
return null
null
}
}
@ -175,7 +189,7 @@ class NSSettingsStatus @Inject constructor(
// "bgTargetTop": 180,
// "bgTargetBottom": 72,
// "bgLow": 71
fun getSettingsThreshold(what: String): Double? {
private fun getSettingsThreshold(what: String): Double? {
val threshold = JsonHelper.safeGetJSONObject(getSettings(), "thresholds", null)
return JsonHelper.safeGetDoubleAllowNull(threshold, what)
}
@ -214,9 +228,6 @@ class NSSettingsStatus @Inject constructor(
private fun extendedPumpSettings(): JSONObject? =
JsonHelper.safeGetJSONObject(getExtendedSettings(), "pump", null)
fun pumpExtendedSettingsEnabledAlerts(): Boolean =
JsonHelper.safeGetBoolean(extendedPumpSettings(), "enableAlerts")
fun pumpExtendedSettingsFields(): String =
JsonHelper.safeGetString(extendedPumpSettings(), "fields", "")
@ -235,7 +246,7 @@ class NSSettingsStatus @Inject constructor(
getExtendedWarnValue("sage", "urgent")?.let { sp.putDouble(R.string.key_statuslights_sage_critical, it) }
getExtendedWarnValue("bage", "warn")?.let { sp.putDouble(R.string.key_statuslights_bage_warning, it) }
getExtendedWarnValue("bage", "urgent")?.let { sp.putDouble(R.string.key_statuslights_bage_critical, it) }
uel.log("NS SETTINGS COPIED")
uel.log(Action.NS_SETTINGS_COPIED)
}
if (context != null) OKDialog.showConfirmation(context, resourceHelper.gs(R.string.statuslights), resourceHelper.gs(R.string.copyexistingvalues), action)

View file

@ -0,0 +1,32 @@
package info.nightscout.androidaps.plugins.general.nsclient.data
import info.nightscout.androidaps.utils.JsonHelper
import org.json.JSONObject
/**
*
* {"mgdl":105,"mills":1455136282375,"device":"xDrip-BluetoothWixel","direction":"Flat","filtered":98272,"unfiltered":98272,"noise":1,"rssi":100}
*/
@Suppress("SpellCheckingInspection")
class NSSgv(val data: JSONObject) {
val mgdl: Int?
get() = JsonHelper.safeGetIntAllowNull(data, "mgdl")
val filtered: Int?
get() = JsonHelper.safeGetIntAllowNull(data, "filtered")
val unfiltered: Int?
get() = JsonHelper.safeGetIntAllowNull(data, "unfiltered")
val noise: Int?
get() = JsonHelper.safeGetIntAllowNull(data, "noise")
val rssi: Int?
get() = JsonHelper.safeGetIntAllowNull(data, "rssi")
val mills: Long?
get() = JsonHelper.safeGetLongAllowNull(data, "mills")
val device: String?
get() = JsonHelper.safeGetStringAllowNull(data, "device", null)
val direction: String?
get() = JsonHelper.safeGetStringAllowNull(data, "direction", null)
val id: String?
get() = JsonHelper.safeGetStringAllowNull(data, "_id", null)
}

View file

@ -1,127 +0,0 @@
package info.nightscout.androidaps.plugins.general.nsclient.data;
import org.json.JSONException;
import org.json.JSONObject;
import org.slf4j.Logger;
import java.util.Date;
import info.nightscout.androidaps.logging.LTag;
import info.nightscout.androidaps.logging.StacktraceLoggerWrapper;
public class NSTreatment {
private static final Logger log = StacktraceLoggerWrapper.getLogger(LTag.NSCLIENT);
private final JSONObject data;
private String action = null; // "update", "remove" or null (add)
public NSTreatment(JSONObject obj) {
this.data = obj;
this.action = getStringOrNull("action");
this.data.remove("action");
}
private String getStringOrNull(String key) {
String ret = null;
if (data.has(key)) {
try {
ret = data.getString(key);
} catch (JSONException e) {
log.error("Unhandled exception", e);
}
}
return ret;
}
private Double getDoubleOrNull(String key) {
Double ret = null;
if (data.has(key)) {
try {
ret = data.getDouble(key);
} catch (JSONException e) {
log.error("Unhandled exception", e);
}
}
return ret;
}
private Integer getIntegerOrNull(String key) {
Integer ret = null;
if (data.has(key)) {
try {
ret = data.getInt(key);
} catch (JSONException e) {
log.error("Unhandled exception", e);
}
}
return ret;
}
private Long getLongOrNull(String key) {
Long ret = null;
if (data.has(key)) {
try {
ret = data.getLong(key);
} catch (JSONException e) {
log.error("Unhandled exception", e);
}
}
return ret;
}
private Date getDateOrNull(String key) {
Date ret = null;
if (data.has(key)) {
try {
ret = new Date(data.getString(key));
} catch (JSONException e) {
log.error("Unhandled exception", e);
}
}
return ret;
}
public String getAction() {
return action;
}
public JSONObject getData() {
return data;
}
public String get_id() {
return getStringOrNull("_id");
}
public String getEnteredBy() {
return getStringOrNull("enteredBy");
}
public String getEventType() {
return getStringOrNull("eventType");
}
public Integer getHapp_id() {
return getIntegerOrNull("happ_id");
}
public Integer getDuration() {
return getIntegerOrNull("duration");
}
public Integer getMgdl() {
return getIntegerOrNull("mgdl");
}
public Double getAbsolute() {
return getDoubleOrNull("absolute");
}
public Long getMills() {
return getLongOrNull("mills");
}
public Date getCreated_at() {
return getDateOrNull("created_at");
}
}

View file

@ -11,6 +11,7 @@ import android.os.PowerManager;
import android.os.SystemClock;
import androidx.localbroadcastmanager.content.LocalBroadcastManager;
import androidx.work.OneTimeWorkRequest;
import com.google.common.base.Charsets;
import com.google.common.hash.Hashing;
@ -34,16 +35,18 @@ import info.nightscout.androidaps.R;
import info.nightscout.androidaps.db.DbRequest;
import info.nightscout.androidaps.events.EventAppExit;
import info.nightscout.androidaps.events.EventConfigBuilderChange;
import info.nightscout.androidaps.events.EventNsFood;
import info.nightscout.androidaps.events.EventPreferenceChange;
import info.nightscout.androidaps.interfaces.DatabaseHelperInterface;
import info.nightscout.androidaps.interfaces.PluginType;
import info.nightscout.androidaps.interfaces.ProfileStore;
import info.nightscout.androidaps.interfaces.UploadQueueInterface;
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.food.FoodPlugin;
import info.nightscout.androidaps.plugins.general.nsclient.NSClientAddUpdateWorker;
import info.nightscout.androidaps.plugins.general.nsclient.NSClientMbgWorker;
import info.nightscout.androidaps.plugins.general.nsclient.NSClientPlugin;
import info.nightscout.androidaps.plugins.general.nsclient.UploadQueue;
import info.nightscout.androidaps.plugins.general.nsclient.NSClientRemoveWorker;
import info.nightscout.androidaps.plugins.general.nsclient.acks.NSAddAck;
import info.nightscout.androidaps.plugins.general.nsclient.acks.NSAuthAck;
import info.nightscout.androidaps.plugins.general.nsclient.acks.NSUpdateAck;
@ -51,8 +54,6 @@ import info.nightscout.androidaps.plugins.general.nsclient.data.AlarmAck;
import info.nightscout.androidaps.plugins.general.nsclient.data.NSAlarm;
import info.nightscout.androidaps.plugins.general.nsclient.data.NSDeviceStatus;
import info.nightscout.androidaps.plugins.general.nsclient.data.NSSettingsStatus;
import info.nightscout.androidaps.plugins.general.nsclient.data.NSSgv;
import info.nightscout.androidaps.plugins.general.nsclient.data.NSTreatment;
import info.nightscout.androidaps.plugins.general.nsclient.events.EventNSClientNewLog;
import info.nightscout.androidaps.plugins.general.nsclient.events.EventNSClientRestart;
import info.nightscout.androidaps.plugins.general.nsclient.events.EventNSClientStatus;
@ -61,6 +62,9 @@ import info.nightscout.androidaps.plugins.general.overview.events.EventDismissNo
import info.nightscout.androidaps.plugins.general.overview.events.EventNewNotification;
import info.nightscout.androidaps.plugins.general.overview.notifications.Notification;
import info.nightscout.androidaps.plugins.general.overview.notifications.NotificationWithAction;
import info.nightscout.androidaps.plugins.profile.ns.NSProfilePlugin;
import info.nightscout.androidaps.plugins.source.NSClientSourcePlugin;
import info.nightscout.androidaps.receivers.DataWorker;
import info.nightscout.androidaps.services.Intents;
import info.nightscout.androidaps.utils.DateUtil;
import info.nightscout.androidaps.utils.FabricPrivacy;
@ -90,15 +94,14 @@ public class NSClientService extends DaggerService {
@Inject BuildHelper buildHelper;
@Inject Config config;
@Inject DateUtil dateUtil;
@Inject UploadQueue uploadQueue;
@Inject UploadQueueInterface uploadQueue;
@Inject DataWorker dataWorker;
private final CompositeDisposable disposable = new CompositeDisposable();
static public PowerManager.WakeLock mWakeLock;
private final IBinder mBinder = new NSClientService.LocalBinder();
static ProfileStore profileStore;
static public Handler handler;
public static Socket mSocket;
@ -108,9 +111,6 @@ public class NSClientService extends DaggerService {
private static Integer connectCounter = 0;
public static String nightscoutVersionName = "";
public static Integer nightscoutVersionCode = 0;
private boolean nsEnabled = false;
static public String nsURL = "";
private String nsAPISecret = "";
@ -214,7 +214,7 @@ public class NSClientService extends DaggerService {
public void processAddAck(NSAddAck ack) {
if (ack.nsClientID != null) {
uploadQueue.removeID(ack.json);
uploadQueue.removeByNsClientIdIfExists(ack.json);
rxBus.send(new EventNSClientNewLog("DBADD", "Acked " + ack.nsClientID));
} else {
rxBus.send(new EventNSClientNewLog("ERROR", "DBADD Unknown response"));
@ -223,7 +223,7 @@ public class NSClientService extends DaggerService {
public void processUpdateAck(NSUpdateAck ack) {
if (ack.result) {
uploadQueue.removeID(ack.action, ack._id);
uploadQueue.removeByMongoId(ack.action, ack._id);
rxBus.send(new EventNSClientNewLog("DBUPDATE/DBREMOVE", "Acked " + ack._id));
} else {
rxBus.send(new EventNSClientNewLog("ERROR", "DBUPDATE/DBREMOVE Unknown response"));
@ -535,185 +535,142 @@ public class NSClientService extends DaggerService {
boolean isFull = !isDelta;
rxBus.send(new EventNSClientNewLog("DATA", "Data packet #" + dataCounter++ + (isDelta ? " delta" : " full")));
if (data.has("profiles")) {
JSONArray profiles = data.getJSONArray("profiles");
if (profiles.length() > 0) {
JSONObject profile = (JSONObject) profiles.get(profiles.length() - 1);
profileStore = new ProfileStore(injector, profile);
broadcastProfile = true;
rxBus.send(new EventNSClientNewLog("PROFILE", "profile received"));
}
}
if (data.has("status")) {
JSONObject status = data.getJSONObject("status");
nsSettingsStatus.setData(status);
if (!status.has("versionNum")) {
if (status.getInt("versionNum") < config.getSUPPORTEDNSVERSION()) {
rxBus.send(new EventNSClientNewLog("ERROR", "Unsupported Nightscout version !!!!"));
}
} else {
nightscoutVersionName = nsSettingsStatus.getVersion();
nightscoutVersionCode = nsSettingsStatus.getVersionNum();
}
nsSettingsStatus.handleNewData(nightscoutVersionName, nightscoutVersionCode, status);
/* Other received data to 2016/02/10
{
status: 'ok'
, name: env.name
, version: env.version
, versionNum: versionNum (for ver 1.2.3 contains 10203)
, serverTime: new Date().toISOString()
, apiEnabled: apiEnabled
, careportalEnabled: apiEnabled && env.settings.enable.indexOf('careportal') > -1
, boluscalcEnabled: apiEnabled && env.settings.enable.indexOf('boluscalc') > -1
, head: env.head
, settings: env.settings
, extendedSettings: ctx.plugins && ctx.plugins.extendedClientSettings ? ctx.plugins.extendedClientSettings(env.extendedSettings) : {}
, activeProfile ..... calculated from treatments or missing
}
*/
nsSettingsStatus.handleNewData(status);
} else if (!isDelta) {
rxBus.send(new EventNSClientNewLog("ERROR", "Unsupported Nightscout version !!!!"));
}
// If new profile received or change detected broadcast it
if (broadcastProfile && profileStore != null) {
handleNewProfile(profileStore, isDelta);
rxBus.send(new EventNSClientNewLog("PROFILE", "broadcasting"));
if (data.has("profiles")) {
JSONArray profiles = data.getJSONArray("profiles");
if (profiles.length() > 0) {
// take the newest
JSONObject profileStoreJson = (JSONObject) profiles.get(profiles.length() - 1);
rxBus.send(new EventNSClientNewLog("PROFILE", "profile received"));
dataWorker.enqueue(
new OneTimeWorkRequest.Builder(NSProfilePlugin.NSProfileWorker.class)
.setInputData(dataWorker.storeInputData(profileStoreJson, null))
.build());
if (sp.getBoolean(R.string.key_nsclient_localbroadcasts, false)) {
Bundle bundle = new Bundle();
bundle.putString("profile", profileStoreJson.toString());
bundle.putBoolean("delta", isDelta);
Intent intent = new Intent(Intents.ACTION_NEW_PROFILE);
intent.putExtras(bundle);
intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES);
sendBroadcast(intent);
}
}
}
if (data.has("treatments")) {
JSONArray treatments = data.getJSONArray("treatments");
JSONArray removedTreatments = new JSONArray();
JSONArray updatedTreatments = new JSONArray();
JSONArray addedTreatments = new JSONArray();
JSONArray addedOrUpdatedTreatments = new JSONArray();
if (treatments.length() > 0)
rxBus.send(new EventNSClientNewLog("DATA", "received " + treatments.length() + " treatments"));
for (Integer index = 0; index < treatments.length(); index++) {
JSONObject jsonTreatment = treatments.getJSONObject(index);
NSTreatment treatment = new NSTreatment(jsonTreatment);
String action = JsonHelper.safeGetStringAllowNull(jsonTreatment, "action", null);
long mills = JsonHelper.safeGetLong(jsonTreatment, "mills");
// remove from upload queue if Ack is failing
uploadQueue.removeID(jsonTreatment);
//Find latest date in treatment
if (treatment.getMills() != null && treatment.getMills() < System.currentTimeMillis())
if (treatment.getMills() > latestDateInReceivedData)
latestDateInReceivedData = treatment.getMills();
if (treatment.getAction() == null) {
addedTreatments.put(jsonTreatment);
} else if (treatment.getAction().equals("update")) {
updatedTreatments.put(jsonTreatment);
} else if (treatment.getAction().equals("remove")) {
if (treatment.getMills() != null && treatment.getMills() > System.currentTimeMillis() - 24 * 60 * 60 * 1000L) // handle 1 day old deletions only
if (action == null) addedOrUpdatedTreatments.put(jsonTreatment);
else if (action.equals("update"))
addedOrUpdatedTreatments.put(jsonTreatment);
else if (action.equals("remove") && mills > dateUtil._now() - T.days(1).msecs()) // handle 1 day old deletions only
removedTreatments.put(jsonTreatment);
}
}
if (removedTreatments.length() > 0) {
handleRemovedTreatment(removedTreatments, isDelta);
dataWorker.enqueue(
new OneTimeWorkRequest.Builder(NSClientRemoveWorker.class)
.setInputData(dataWorker.storeInputData(removedTreatments, null))
.build());
if (sp.getBoolean(R.string.key_nsclient_localbroadcasts, false)) {
Bundle bundle = new Bundle();
bundle.putString("treatments", removedTreatments.toString());
bundle.putBoolean("delta", isDelta);
Intent intent = new Intent(Intents.ACTION_REMOVED_TREATMENT);
intent.putExtras(bundle);
intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES);
sendBroadcast(intent);
}
}
if (addedOrUpdatedTreatments.length() > 0) {
dataWorker.enqueue(
new OneTimeWorkRequest.Builder(NSClientAddUpdateWorker.class)
.setInputData(dataWorker.storeInputData(addedOrUpdatedTreatments, null))
.build());
if (sp.getBoolean(R.string.key_nsclient_localbroadcasts, false)) {
List<JSONArray> splitted = splitArray(addedOrUpdatedTreatments);
for (JSONArray part : splitted) {
Bundle bundle = new Bundle();
bundle.putString("treatments", part.toString());
bundle.putBoolean("delta", isDelta);
Intent intent = new Intent(Intents.ACTION_CHANGED_TREATMENT);
intent.putExtras(bundle);
intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES);
sendBroadcast(intent);
}
if (updatedTreatments.length() > 0) {
handleChangedTreatment(updatedTreatments, isDelta);
}
if (addedTreatments.length() > 0) {
handleNewTreatment(addedTreatments, isDelta);
}
}
if (data.has("devicestatus")) {
JSONArray devicestatuses = data.getJSONArray("devicestatus");
if (devicestatuses.length() > 0) {
rxBus.send(new EventNSClientNewLog("DATA", "received " + devicestatuses.length() + " device statuses"));
for (Integer index = 0; index < devicestatuses.length(); index++) {
JSONObject jsonStatus = devicestatuses.getJSONObject(index);
// remove from upload queue if Ack is failing
uploadQueue.removeID(jsonStatus);
}
nsDeviceStatus.handleNewData(devicestatuses);
}
}
if (data.has("food")) {
JSONArray foods = data.getJSONArray("food");
JSONArray removedFoods = new JSONArray();
JSONArray updatedFoods = new JSONArray();
JSONArray addedFoods = new JSONArray();
if (foods.length() > 0)
rxBus.send(new EventNSClientNewLog("DATA", "received " + foods.length() + " foods"));
for (Integer index = 0; index < foods.length(); index++) {
JSONObject jsonFood = foods.getJSONObject(index);
// remove from upload queue if Ack is failing
uploadQueue.removeID(jsonFood);
String action = JsonHelper.safeGetString(jsonFood, "action");
if (action == null) {
addedFoods.put(jsonFood);
} else if (action.equals("update")) {
updatedFoods.put(jsonFood);
} else if (action.equals("remove")) {
removedFoods.put(jsonFood);
}
}
if (removedFoods.length() > 0) {
EventNsFood evt = new EventNsFood(EventNsFood.Companion.getREMOVE(), removedFoods);
rxBus.send(evt);
}
if (updatedFoods.length() > 0) {
EventNsFood evt = new EventNsFood(EventNsFood.Companion.getUPDATE(), updatedFoods);
rxBus.send(evt);
}
if (addedFoods.length() > 0) {
EventNsFood evt = new EventNsFood(EventNsFood.Companion.getADD(), addedFoods);
rxBus.send(evt);
}
dataWorker.enqueue(
new OneTimeWorkRequest.Builder(FoodPlugin.FoodWorker.class)
.setInputData(dataWorker.storeInputData(foods, null))
.build());
}
//noinspection SpellCheckingInspection
if (data.has("mbgs")) {
JSONArray mbgs = data.getJSONArray("mbgs");
if (mbgs.length() > 0)
rxBus.send(new EventNSClientNewLog("DATA", "received " + mbgs.length() + " mbgs"));
for (Integer index = 0; index < mbgs.length(); index++) {
JSONObject jsonMbg = mbgs.getJSONObject(index);
// remove from upload queue if Ack is failing
uploadQueue.removeID(jsonMbg);
}
handleNewMbg(mbgs, isDelta);
JSONArray mbgArray = data.getJSONArray("mbgs");
if (mbgArray.length() > 0)
rxBus.send(new EventNSClientNewLog("DATA", "received " + mbgArray.length() + " mbgs"));
dataWorker.enqueue(
new OneTimeWorkRequest.Builder(NSClientMbgWorker.class)
.setInputData(dataWorker.storeInputData(mbgArray, null))
.build());
}
if (data.has("cals")) {
JSONArray cals = data.getJSONArray("cals");
if (cals.length() > 0)
rxBus.send(new EventNSClientNewLog("DATA", "received " + cals.length() + " cals"));
// Retreive actual calibration
for (Integer index = 0; index < cals.length(); index++) {
// remove from upload queue if Ack is failing
uploadQueue.removeID(cals.optJSONObject(index));
}
handleNewCal(cals, isDelta);
// Calibrations ignored
}
if (data.has("sgvs")) {
JSONArray sgvs = data.getJSONArray("sgvs");
if (sgvs.length() > 0)
rxBus.send(new EventNSClientNewLog("DATA", "received " + sgvs.length() + " sgvs"));
for (int index = 0; index < sgvs.length(); index++) {
JSONObject jsonSgv = sgvs.getJSONObject(index);
// rxBus.send(new EventNSClientNewLog("DATA", "svg " + sgvs.getJSONObject(index).toString());
NSSgv sgv = new NSSgv(jsonSgv);
// Handle new sgv here
// remove from upload queue if Ack is failing
uploadQueue.removeID(jsonSgv);
//Find latest date in sgv
if (sgv.getMills() != null && sgv.getMills() < System.currentTimeMillis())
if (sgv.getMills() > latestDateInReceivedData)
latestDateInReceivedData = sgv.getMills();
dataWorker.enqueue(new OneTimeWorkRequest.Builder(NSClientSourcePlugin.NSClientSourceWorker.class)
.setInputData(dataWorker.storeInputData(sgvs, null))
.build());
List<JSONArray> splitted = splitArray(sgvs);
if (sp.getBoolean(R.string.key_nsclient_localbroadcasts, false)) {
for (JSONArray part : splitted) {
Bundle bundle = new Bundle();
bundle.putString("sgvs", part.toString());
bundle.putBoolean("delta", isDelta);
Intent intent = new Intent(Intents.ACTION_NEW_SGV);
intent.putExtras(bundle);
intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES);
sendBroadcast(intent);
}
// Was that sgv more less 5 mins ago ?
if ((System.currentTimeMillis() - latestDateInReceivedData) / (60 * 1000L) < 5L) {
rxBus.send(new EventDismissNotification(Notification.NS_ALARM));
rxBus.send(new EventDismissNotification(Notification.NS_URGENT_ALARM));
}
handleNewSgv(sgvs, isDelta);
}
rxBus.send(new EventNSClientNewLog("LAST", dateUtil.dateAndTimeString(latestDateInReceivedData)));
} catch (JSONException e) {
@ -881,71 +838,6 @@ public class NSClientService extends DaggerService {
}
}
public void handleNewCal(JSONArray cals, boolean isDelta) {
Bundle bundle = new Bundle();
bundle.putString("cals", cals.toString());
bundle.putBoolean("delta", isDelta);
Intent intent = new Intent(Intents.ACTION_NEW_CAL);
intent.putExtras(bundle);
intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES);
LocalBroadcastManager.getInstance(this).sendBroadcast(intent);
}
public void handleNewMbg(JSONArray mbgs, boolean isDelta) {
Bundle bundle = new Bundle();
bundle.putString("mbgs", mbgs.toString());
bundle.putBoolean("delta", isDelta);
Intent intent = new Intent(Intents.ACTION_NEW_MBG);
intent.putExtras(bundle);
intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES);
LocalBroadcastManager.getInstance(this).sendBroadcast(intent);
}
public void handleNewProfile(ProfileStore profile, boolean isDelta) {
Bundle bundle = new Bundle();
bundle.putString("profile", profile.getData().toString());
bundle.putBoolean("delta", isDelta);
Intent intent = new Intent(Intents.ACTION_NEW_PROFILE);
intent.putExtras(bundle);
intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES);
LocalBroadcastManager.getInstance(this).sendBroadcast(intent);
if (sp.getBoolean(R.string.key_nsclient_localbroadcasts, false)) {
bundle = new Bundle();
bundle.putString("profile", profile.getData().toString());
bundle.putBoolean("delta", isDelta);
intent = new Intent(Intents.ACTION_NEW_PROFILE);
intent.putExtras(bundle);
intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES);
this.sendBroadcast(intent);
}
}
public void handleNewSgv(JSONArray sgvs, boolean isDelta) {
List<JSONArray> splitted = splitArray(sgvs);
for (JSONArray part : splitted) {
Bundle bundle = new Bundle();
bundle.putString("sgvs", part.toString());
bundle.putBoolean("delta", isDelta);
Intent intent = new Intent(Intents.ACTION_NEW_SGV);
intent.putExtras(bundle);
intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES);
LocalBroadcastManager.getInstance(this).sendBroadcast(intent);
}
if (sp.getBoolean(R.string.key_nsclient_localbroadcasts, false)) {
for (JSONArray part : splitted) {
Bundle bundle = new Bundle();
bundle.putString("sgvs", part.toString());
bundle.putBoolean("delta", isDelta);
Intent intent = new Intent(Intents.ACTION_NEW_SGV);
intent.putExtras(bundle);
intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES);
this.sendBroadcast(intent);
}
}
}
public void handleNewTreatment(JSONArray treatments, boolean isDelta) {
List<JSONArray> splitted = splitArray(treatments);
for (JSONArray part : splitted) {
@ -972,54 +864,6 @@ public class NSClientService extends DaggerService {
}
}
public void handleChangedTreatment(JSONArray treatments, boolean isDelta) {
List<JSONArray> splitted = splitArray(treatments);
for (JSONArray part : splitted) {
Bundle bundle = new Bundle();
bundle.putString("treatments", part.toString());
bundle.putBoolean("delta", isDelta);
Intent intent = new Intent(Intents.ACTION_CHANGED_TREATMENT);
intent.putExtras(bundle);
intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES);
LocalBroadcastManager.getInstance(this).sendBroadcast(intent);
}
if (sp.getBoolean(R.string.key_nsclient_localbroadcasts, false)) {
splitted = splitArray(treatments);
for (JSONArray part : splitted) {
Bundle bundle = new Bundle();
bundle.putString("treatments", part.toString());
bundle.putBoolean("delta", isDelta);
Intent intent = new Intent(Intents.ACTION_CHANGED_TREATMENT);
intent.putExtras(bundle);
intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES);
this.getApplicationContext().sendBroadcast(intent);
}
}
}
public void handleRemovedTreatment(JSONArray treatments, boolean isDelta) {
Bundle bundle = new Bundle();
bundle.putString("treatments", treatments.toString());
bundle.putBoolean("delta", isDelta);
Intent intent = new Intent(Intents.ACTION_REMOVED_TREATMENT);
intent.putExtras(bundle);
intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES);
LocalBroadcastManager.getInstance(this).sendBroadcast(intent);
if (sp.getBoolean(R.string.key_nsclient_localbroadcasts, false)) {
bundle = new Bundle();
bundle.putString("treatments", treatments.toString());
bundle.putBoolean("delta", isDelta);
intent = new Intent(Intents.ACTION_REMOVED_TREATMENT);
intent.putExtras(bundle);
intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES);
this.getApplicationContext().sendBroadcast(intent);
}
}
public List<JSONArray> splitArray(JSONArray array) {
List<JSONArray> ret = new ArrayList<>();
try {

View file

@ -31,6 +31,7 @@ import info.nightscout.androidaps.data.Profile
import info.nightscout.androidaps.database.AppRepository
import info.nightscout.androidaps.database.ValueWrapper
import info.nightscout.androidaps.database.entities.TemporaryTarget
import info.nightscout.androidaps.database.entities.UserEntry.*
import info.nightscout.androidaps.database.interfaces.end
import info.nightscout.androidaps.databinding.OverviewFragmentBinding
import info.nightscout.androidaps.dialogs.*
@ -350,7 +351,7 @@ class OverviewFragment : DaggerFragment(), View.OnClickListener, OnLongClickList
protectionCheck.queryProtection(activity, ProtectionCheck.Protection.BOLUS, UIRunnable {
OKDialog.showConfirmation(activity, resourceHelper.gs(R.string.tempbasal_label), lastRun.constraintsProcessed?.toSpanned()
?: "".toSpanned(), {
uel.log("ACCEPT TEMP BASAL")
uel.log(Action.ACCEPTS_TEMP_BASAL)
binding.buttonsLayout.acceptTempButton.visibility = View.GONE
(context?.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager).cancel(Constants.notificationID)
rxBus.send(EventWearInitiateAction("cancelChangeRequest"))
@ -838,7 +839,7 @@ class OverviewFragment : DaggerFragment(), View.OnClickListener, OnLongClickList
val toTime: Long
val fromTime: Long
val endTime: Long
val apsResult = if (config.APS) lastRun?.constraintsProcessed else NSDeviceStatus.getAPSResult(injector)
val apsResult = if (config.APS) lastRun?.constraintsProcessed else nsDeviceStatus.getAPSResult(injector)
if (predictionsAvailable && apsResult != null && menuChartSettings[0][OverviewMenus.CharType.PRE.ordinal]) {
var predictionHours = (ceil(apsResult.latestPredictionsTime - System.currentTimeMillis().toDouble()) / (60 * 60 * 1000)).toInt()
predictionHours = min(2, predictionHours)

View file

@ -17,6 +17,7 @@ import info.nightscout.androidaps.data.DetailedBolusInfo
import info.nightscout.androidaps.data.Profile
import info.nightscout.androidaps.database.AppRepository
import info.nightscout.androidaps.database.entities.TemporaryTarget
import info.nightscout.androidaps.database.entities.UserEntry.*
import info.nightscout.androidaps.database.transactions.CancelCurrentTemporaryTargetIfAnyTransaction
import info.nightscout.androidaps.database.transactions.InsertTemporaryTargetAndCancelCurrentTransaction
import info.nightscout.androidaps.db.Source
@ -35,11 +36,10 @@ import info.nightscout.androidaps.plugins.general.overview.events.EventNewNotifi
import info.nightscout.androidaps.plugins.general.overview.notifications.Notification
import info.nightscout.androidaps.plugins.general.smsCommunicator.events.EventSmsCommunicatorUpdateGui
import info.nightscout.androidaps.plugins.general.smsCommunicator.otp.OneTimePassword
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.GlucoseStatus
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.GlucoseStatusProvider
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.IobCobCalculatorPlugin
import info.nightscout.androidaps.queue.Callback
import info.nightscout.androidaps.receivers.BundleStore
import info.nightscout.androidaps.receivers.DataWorker
import info.nightscout.androidaps.receivers.DataReceiver
import info.nightscout.androidaps.utils.*
import info.nightscout.androidaps.utils.extensions.valueToUnitsString
@ -175,7 +175,7 @@ class SmsCommunicatorPlugin @Inject constructor(
) : Worker(context, params) {
@Inject lateinit var smsCommunicatorPlugin: SmsCommunicatorPlugin
@Inject lateinit var bundleStore: BundleStore
@Inject lateinit var dataWorker: DataWorker
init {
(context.applicationContext as HasAndroidInjector).androidInjector().inject(this)
@ -183,7 +183,7 @@ class SmsCommunicatorPlugin @Inject constructor(
@Suppress("SpellCheckingInspection")
override fun doWork(): Result {
val bundle = bundleStore.pickup(inputData.getLong(DataReceiver.STORE_KEY, -1))
val bundle = dataWorker.pickupBundle(inputData.getLong(DataWorker.STORE_KEY, -1))
?: return Result.failure()
val format = bundle.getString("format") ?: return Result.failure()
val pdus = bundle["pdus"] as Array<*>
@ -348,7 +348,7 @@ class SmsCommunicatorPlugin @Inject constructor(
receivedSms.processed = true
messageToConfirm = AuthRequest(injector, receivedSms, reply, passCode, object : SmsAction() {
override fun run() {
uel.log("SMS LOOP DISABLE")
uel.log(Action.SMS_LOOP_DISABLED)
loopPlugin.setPluginEnabled(PluginType.LOOP, false)
commandQueue.cancelTempBasal(true, object : Callback() {
override fun run() {
@ -372,7 +372,7 @@ class SmsCommunicatorPlugin @Inject constructor(
receivedSms.processed = true
messageToConfirm = AuthRequest(injector, receivedSms, reply, passCode, object : SmsAction() {
override fun run() {
uel.log("SMS LOOP ENABLE")
uel.log(Action.SMS_LOOP_ENABLED)
loopPlugin.setPluginEnabled(PluginType.LOOP, true)
sendSMS(Sms(receivedSms.phoneNumber, resourceHelper.gs(R.string.smscommunicator_loophasbeenenabled)))
rxBus.send(EventRefreshOverview("SMS_LOOP_START"))
@ -399,7 +399,7 @@ class SmsCommunicatorPlugin @Inject constructor(
receivedSms.processed = true
messageToConfirm = AuthRequest(injector, receivedSms, reply, passCode, object : SmsAction() {
override fun run() {
uel.log("SMS LOOP RESUME")
uel.log(Action.SMS_LOOP_RESUME)
loopPlugin.suspendTo(0L)
rxBus.send(EventRefreshOverview("SMS_LOOP_RESUME"))
commandQueue.cancelTempBasal(true, object : Callback() {
@ -432,7 +432,7 @@ class SmsCommunicatorPlugin @Inject constructor(
receivedSms.processed = true
messageToConfirm = AuthRequest(injector, receivedSms, reply, passCode, object : SmsAction(duration) {
override fun run() {
uel.log("SMS LOOP SUSPEND")
uel.log(Action.SMS_LOOP_SUSPEND)
commandQueue.cancelTempBasal(true, object : Callback() {
override fun run() {
if (result.success) {
@ -516,7 +516,7 @@ class SmsCommunicatorPlugin @Inject constructor(
receivedSms.processed = true
messageToConfirm = AuthRequest(injector, receivedSms, reply, passCode, object : SmsAction() {
override fun run() {
uel.log("SMS PUMP CONNECT")
uel.log(Action.SMS_PUMP_CONNECT)
commandQueue.cancelTempBasal(true, object : Callback() {
override fun run() {
if (!result.success) {
@ -545,7 +545,7 @@ class SmsCommunicatorPlugin @Inject constructor(
receivedSms.processed = true
messageToConfirm = AuthRequest(injector, receivedSms, reply, passCode, object : SmsAction() {
override fun run() {
uel.log("SMS PUMP DISCONNECT")
uel.log(Action.SMS_PUMP_DISCONNECT)
val profile = profileFunction.getProfile()
loopPlugin.disconnectPump(duration, profile)
rxBus.send(EventRefreshOverview("SMS_PUMP_DISCONNECT"))
@ -602,7 +602,7 @@ class SmsCommunicatorPlugin @Inject constructor(
activePlugin.activeTreatments.doProfileSwitch(store, list[pIndex - 1] as String, 0, finalPercentage, 0, DateUtil.now())
val replyText = resourceHelper.gs(R.string.profileswitchcreated)
sendSMS(Sms(receivedSms.phoneNumber, replyText))
uel.log("SMS PROFILE", replyText)
uel.log(Action.SMS_PROFILE, ValueWithUnit(R.string.profileswitchcreated, Units.R_String))
}
})
}
@ -624,12 +624,12 @@ class SmsCommunicatorPlugin @Inject constructor(
var replyText = resourceHelper.gs(R.string.smscommunicator_tempbasalcanceled)
replyText += "\n" + activePlugin.activePump.shortStatus(true)
sendSMSToAllNumbers(Sms(receivedSms.phoneNumber, replyText))
uel.log("SMS BASAL", replyText)
uel.log(Action.SMS_BASAL, activePlugin.activePump.shortStatus(true), ValueWithUnit(R.string.smscommunicator_tempbasalcanceled, Units.R_String))
} else {
var replyText = resourceHelper.gs(R.string.smscommunicator_tempbasalcancelfailed)
replyText += "\n" + activePlugin.activePump.shortStatus(true)
sendSMS(Sms(receivedSms.phoneNumber, replyText))
uel.log("SMS BASAL", replyText)
uel.log(Action.SMS_BASAL, activePlugin.activePump.shortStatus(true), ValueWithUnit(R.string.smscommunicator_tempbasalcancelfailed, Units.R_String))
}
}
})
@ -657,12 +657,15 @@ class SmsCommunicatorPlugin @Inject constructor(
var replyText = if (result.isPercent) String.format(resourceHelper.gs(R.string.smscommunicator_tempbasalset_percent), result.percent, result.duration) else String.format(resourceHelper.gs(R.string.smscommunicator_tempbasalset), result.absolute, result.duration)
replyText += "\n" + activePlugin.activePump.shortStatus(true)
sendSMSToAllNumbers(Sms(receivedSms.phoneNumber, replyText))
uel.log("SMS BASAL", replyText)
if (result.isPercent)
uel.log(Action.SMS_BASAL, activePlugin.activePump.shortStatus(true), ValueWithUnit(R.string.smscommunicator_tempbasalset_percent, 2), ValueWithUnit(result.percent, Units.Percent), ValueWithUnit(result.duration, Units.M))
else
uel.log(Action.SMS_BASAL, activePlugin.activePump.shortStatus(true), ValueWithUnit(R.string.smscommunicator_tempbasalset, 2), ValueWithUnit(result.absolute, Units.U_H), ValueWithUnit(result.duration, Units.M))
} else {
var replyText = resourceHelper.gs(R.string.smscommunicator_tempbasalfailed)
replyText += "\n" + activePlugin.activePump.shortStatus(true)
sendSMS(Sms(receivedSms.phoneNumber, replyText))
uel.log("SMS BASAL", replyText)
uel.log(Action.SMS_BASAL, activePlugin.activePump.shortStatus(true), ValueWithUnit(R.string.smscommunicator_tempbasalfailed, Units.R_String))
}
}
})
@ -692,12 +695,15 @@ class SmsCommunicatorPlugin @Inject constructor(
else String.format(resourceHelper.gs(R.string.smscommunicator_tempbasalset), result.absolute, result.duration)
replyText += "\n" + activePlugin.activePump.shortStatus(true)
sendSMSToAllNumbers(Sms(receivedSms.phoneNumber, replyText))
uel.log("SMS BASAL", replyText)
if (result.isPercent)
uel.log(Action.SMS_BASAL, activePlugin.activePump.shortStatus(true), ValueWithUnit(R.string.smscommunicator_tempbasalset_percent, 2), ValueWithUnit(result.percent, Units.Percent), ValueWithUnit(result.duration, Units.M))
else
uel.log(Action.SMS_BASAL, activePlugin.activePump.shortStatus(true), ValueWithUnit(R.string.smscommunicator_tempbasalset, 2), ValueWithUnit(result.absolute, Units.U_H), ValueWithUnit(result.duration, Units.M))
} else {
var replyText = resourceHelper.gs(R.string.smscommunicator_tempbasalfailed)
replyText += "\n" + activePlugin.activePump.shortStatus(true)
sendSMS(Sms(receivedSms.phoneNumber, replyText))
uel.log("SMS BASAL", replyText)
uel.log(Action.SMS_BASAL, activePlugin.activePump.shortStatus(true), ValueWithUnit(R.string.smscommunicator_tempbasalfailed, Units.R_String))
}
}
})
@ -724,7 +730,7 @@ class SmsCommunicatorPlugin @Inject constructor(
var replyText = resourceHelper.gs(R.string.smscommunicator_extendedcancelfailed)
replyText += "\n" + activePlugin.activePump.shortStatus(true)
sendSMS(Sms(receivedSms.phoneNumber, replyText))
uel.log("SMS EXTENDED", replyText)
uel.log(Action.SMS_EXTENDED_BOLUS, activePlugin.activePump.shortStatus(true), ValueWithUnit(R.string.smscommunicator_extendedcanceled, Units.R_String))
}
}
})
@ -750,12 +756,17 @@ class SmsCommunicatorPlugin @Inject constructor(
if (config.APS) replyText += "\n" + resourceHelper.gs(R.string.loopsuspended)
replyText += "\n" + activePlugin.activePump.shortStatus(true)
sendSMSToAllNumbers(Sms(receivedSms.phoneNumber, replyText))
uel.log("SMS EXTENDED", replyText)
if (config.APS)
uel.log(Action.SMS_EXTENDED_BOLUS, activePlugin.activePump.shortStatus(true), ValueWithUnit(R.string.smscommunicator_extendedset, 2), ValueWithUnit(aDouble
?: 0.0, Units.U), ValueWithUnit(duration, Units.M), ValueWithUnit(R.string.loopsuspended, Units.R_String))
else
uel.log(Action.SMS_EXTENDED_BOLUS, activePlugin.activePump.shortStatus(true), ValueWithUnit(R.string.smscommunicator_extendedset, 2), ValueWithUnit(aDouble
?: 0.0, Units.U), ValueWithUnit(duration, Units.M))
} else {
var replyText = resourceHelper.gs(R.string.smscommunicator_extendedfailed)
replyText += "\n" + activePlugin.activePump.shortStatus(true)
sendSMS(Sms(receivedSms.phoneNumber, replyText))
uel.log("SMS EXTENDED", replyText)
uel.log(Action.SMS_EXTENDED_BOLUS, activePlugin.activePump.shortStatus(true), ValueWithUnit(R.string.smscommunicator_extendedfailed, Units.R_String))
}
}
})
@ -828,12 +839,12 @@ class SmsCommunicatorPlugin @Inject constructor(
}
}
sendSMSToAllNumbers(Sms(receivedSms.phoneNumber, replyText))
uel.log("SMS BOLUS", replyText)
uel.log(Action.SMS_BOLUS, replyText)
} else {
var replyText = resourceHelper.gs(R.string.smscommunicator_bolusfailed)
replyText += "\n" + activePlugin.activePump.shortStatus(true)
sendSMS(Sms(receivedSms.phoneNumber, replyText))
uel.log("SMS BOLUS", replyText)
uel.log(Action.SMS_BOLUS, activePlugin.activePump.shortStatus(true), ValueWithUnit(R.string.smscommunicator_bolusfailed, Units.R_String))
}
}
})
@ -873,12 +884,14 @@ class SmsCommunicatorPlugin @Inject constructor(
var replyText = String.format(resourceHelper.gs(R.string.smscommunicator_carbsset), anInteger)
replyText += "\n" + activePlugin.activePump.shortStatus(true)
sendSMSToAllNumbers(Sms(receivedSms.phoneNumber, replyText))
uel.log("SMS CARBS", replyText)
uel.log(Action.SMS_CARBS, activePlugin.activePump.shortStatus(true), ValueWithUnit(R.string.smscommunicator_carbsset, 1), ValueWithUnit(anInteger
?: 0, Units.G))
} else {
var replyText = resourceHelper.gs(R.string.smscommunicator_carbsfailed)
var replyText = resourceHelper.gs(R.string.smscommunicator_carbsfailed, anInteger)
replyText += "\n" + activePlugin.activePump.shortStatus(true)
sendSMS(Sms(receivedSms.phoneNumber, replyText))
uel.log("SMS CARBS", replyText)
uel.log(Action.SMS_CARBS, activePlugin.activePump.shortStatus(true), ValueWithUnit(R.string.smscommunicator_carbsfailed, 1), ValueWithUnit(anInteger
?: 0, Units.G))
}
}
})
@ -887,7 +900,8 @@ class SmsCommunicatorPlugin @Inject constructor(
var replyText = String.format(resourceHelper.gs(R.string.smscommunicator_carbsset), anInteger)
replyText += "\n" + activePlugin.activePump.shortStatus(true)
sendSMSToAllNumbers(Sms(receivedSms.phoneNumber, replyText))
uel.log("SMS CARBS", replyText)
uel.log(Action.SMS_CARBS, activePlugin.activePump.shortStatus(true), ValueWithUnit(R.string.smscommunicator_carbsset, 1), ValueWithUnit(anInteger
?: 0, Units.G))
}
}
})
@ -956,7 +970,8 @@ class SmsCommunicatorPlugin @Inject constructor(
val ttString = if (units == Constants.MMOL) DecimalFormatter.to1Decimal(tt) else DecimalFormatter.to0Decimal(tt)
val replyText = String.format(resourceHelper.gs(R.string.smscommunicator_tt_set), ttString, ttDuration)
sendSMSToAllNumbers(Sms(receivedSms.phoneNumber, replyText))
uel.log("SMS TARGET", replyText)
//uel.log(Action.SMS_TT, ValueWithUnit(R.string.smscommunicator_tt_set, 2), ValueWithUnit(tt, units), ValueWithUnit(ttDuration, Units.M))
uel.log(Action.SMS_TT, ValueWithUnit(tt, units), ValueWithUnit(ttDuration, Units.M))
}
})
} else if (isStop) {
@ -973,7 +988,7 @@ class SmsCommunicatorPlugin @Inject constructor(
})
val replyText = String.format(resourceHelper.gs(R.string.smscommunicator_tt_canceled))
sendSMSToAllNumbers(Sms(receivedSms.phoneNumber, replyText))
uel.log("SMS TARGET", reply)
uel.log(Action.SMS_TT, ValueWithUnit(R.string.smscommunicator_tt_canceled, Units.R_String))
}
})
} else
@ -992,7 +1007,7 @@ class SmsCommunicatorPlugin @Inject constructor(
sp.putBoolean(R.string.key_smscommunicator_remotecommandsallowed, false)
val replyText = String.format(resourceHelper.gs(R.string.smscommunicator_stoppedsms))
sendSMSToAllNumbers(Sms(receivedSms.phoneNumber, replyText))
uel.log("SMS SMS", replyText)
uel.log(Action.SMS_SMS, ValueWithUnit(R.string.smscommunicator_stoppedsms, Units.R_String))
}
})
} else sendSMS(Sms(receivedSms.phoneNumber, resourceHelper.gs(R.string.wrongformat)))
@ -1010,7 +1025,10 @@ class SmsCommunicatorPlugin @Inject constructor(
val replyText =
if (result) resourceHelper.gs(R.string.smscommunicator_calibrationsent) else resourceHelper.gs(R.string.smscommunicator_calibrationfailed)
sendSMSToAllNumbers(Sms(receivedSms.phoneNumber, replyText))
uel.log("SMS CAL", replyText)
if (result)
uel.log(Action.SMS_CAL, ValueWithUnit(R.string.smscommunicator_calibrationsent, Units.R_String))
else
uel.log(Action.SMS_CAL, ValueWithUnit(R.string.smscommunicator_calibrationfailed, Units.R_String))
}
})
} else sendSMS(Sms(receivedSms.phoneNumber, resourceHelper.gs(R.string.wrongformat)))

View file

@ -14,6 +14,7 @@ import com.google.common.primitives.Ints.min
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel
import info.nightscout.androidaps.R
import info.nightscout.androidaps.activities.NoSplashAppCompatActivity
import info.nightscout.androidaps.database.entities.UserEntry.*
import info.nightscout.androidaps.databinding.ActivitySmscommunicatorOtpBinding
import info.nightscout.androidaps.logging.UserEntryLogger
import info.nightscout.androidaps.plugins.bus.RxBusWrapper
@ -72,7 +73,7 @@ class SmsCommunicatorOtpActivity : NoSplashAppCompatActivity() {
resourceHelper.gs(R.string.smscommunicator_otp_reset_title),
resourceHelper.gs(R.string.smscommunicator_otp_reset_prompt),
Runnable {
uel.log("OTP RESET")
uel.log(Action.OTP_RESET)
otp.ensureKey(true)
updateGui()
ToastUtils.Long.infoToast(this, resourceHelper.gs(R.string.smscommunicator_otp_reset_successful))
@ -88,7 +89,7 @@ class SmsCommunicatorOtpActivity : NoSplashAppCompatActivity() {
val clip = ClipData.newPlainText("OTP Secret", otp.provisioningSecret())
clipboard.primaryClip = clip
ToastUtils.Long.infoToast(this, resourceHelper.gs(R.string.smscommunicator_otp_export_successful))
uel.log("OTP EXPORT")
uel.log(Action.OTP_EXPORT)
})
true

View file

@ -715,7 +715,7 @@ public class WatchUpdaterService extends WearableListenerService implements Goog
openApsStatus = loopPlugin.getLastRun() != null && loopPlugin.getLastRun().getLastTBREnact() != 0 ? loopPlugin.getLastRun().getLastTBREnact() : -1;
} else {
//NSClient or remote
openApsStatus = NSDeviceStatus.getOpenApsTimestamp();
openApsStatus = nsDeviceStatus.getOpenApsTimestamp();
}
PutDataMapRequest dataMapRequest = PutDataMapRequest.create(NEW_STATUS_PATH);

View file

@ -12,6 +12,7 @@ import dagger.android.support.DaggerFragment
import info.nightscout.androidaps.Constants
import info.nightscout.androidaps.R
import info.nightscout.androidaps.data.Profile
import info.nightscout.androidaps.database.entities.UserEntry.*
import info.nightscout.androidaps.databinding.LocalprofileFragmentBinding
import info.nightscout.androidaps.dialogs.ProfileSwitchDialog
import info.nightscout.androidaps.interfaces.ActivePluginProvider
@ -162,7 +163,7 @@ class LocalProfileFragment : DaggerFragment() {
if (localProfilePlugin.isEdited) {
activity?.let { OKDialog.show(it, "", resourceHelper.gs(R.string.saveorresetchangesfirst)) }
} else {
uel.log("NEW PROFILE")
uel.log(Action.NEW_PROFILE)
localProfilePlugin.addNewProfile()
build()
}
@ -172,7 +173,7 @@ class LocalProfileFragment : DaggerFragment() {
if (localProfilePlugin.isEdited) {
activity?.let { OKDialog.show(it, "", resourceHelper.gs(R.string.saveorresetchangesfirst)) }
} else {
uel.log("CLONE PROFILE", localProfilePlugin.currentProfile()?.name ?: "")
uel.log(Action.CLONE_PROFILE, localProfilePlugin.currentProfile()?.name ?: "")
localProfilePlugin.cloneProfile()
build()
}
@ -181,7 +182,7 @@ class LocalProfileFragment : DaggerFragment() {
binding.profileRemove.setOnClickListener {
activity?.let { activity ->
OKDialog.showConfirmation(activity, resourceHelper.gs(R.string.deletecurrentprofile), {
uel.log("REMOVE PROFILE", localProfilePlugin.currentProfile()?.name ?: "")
uel.log(Action.PROFILE_REMOVED, localProfilePlugin.currentProfile()?.name ?: "")
localProfilePlugin.removeCurrentProfile()
build()
}, null)

View file

@ -5,6 +5,7 @@ import dagger.android.HasAndroidInjector
import info.nightscout.androidaps.Constants
import info.nightscout.androidaps.R
import info.nightscout.androidaps.data.Profile
import info.nightscout.androidaps.database.entities.UserEntry.*
import info.nightscout.androidaps.events.EventProfileStoreChanged
import info.nightscout.androidaps.interfaces.*
import info.nightscout.androidaps.logging.AAPSLogger
@ -115,7 +116,7 @@ class LocalProfilePlugin @Inject constructor(
createAndStoreConvertedProfile()
isEdited = false
aapsLogger.debug(LTag.PROFILE, "Storing settings: " + rawProfile?.data.toString())
uel.log("STORE PROFILE")
uel.log(Action.STORE_PROFILE)
rxBus.send(EventProfileStoreChanged())
var namesOK = true
profiles.forEach {

View file

@ -8,6 +8,7 @@ import android.widget.AdapterView
import android.widget.ArrayAdapter
import dagger.android.support.DaggerFragment
import info.nightscout.androidaps.R
import info.nightscout.androidaps.database.entities.UserEntry.*
import info.nightscout.androidaps.databinding.NsprofileFragmentBinding
import info.nightscout.androidaps.interfaces.ProfileFunction
import info.nightscout.androidaps.logging.UserEntryLogger
@ -61,7 +62,7 @@ class NSProfileFragment : DaggerFragment() {
activity?.let { activity ->
OKDialog.showConfirmation(activity, resourceHelper.gs(R.string.nsprofile),
resourceHelper.gs(R.string.activate_profile) + ": " + name + " ?", Runnable {
uel.log("PROFILE SWITCH", name, i1 = 100)
uel.log(Action.PROFILE_SWITCH, ValueWithUnit(name, Units.None), ValueWithUnit(100.toInt(), Units.Percent))
treatmentsPlugin.doProfileSwitch(store, name, 0, 100, 0, DateUtil.now())
})
}

View file

@ -17,8 +17,7 @@ import info.nightscout.androidaps.logging.LTag
import info.nightscout.androidaps.plugins.bus.RxBusWrapper
import info.nightscout.androidaps.plugins.general.nsclient.events.EventNSClientRestart
import info.nightscout.androidaps.plugins.profile.ns.events.EventNSProfileUpdateGUI
import info.nightscout.androidaps.receivers.BundleStore
import info.nightscout.androidaps.receivers.DataReceiver
import info.nightscout.androidaps.receivers.DataWorker
import info.nightscout.androidaps.utils.resources.ResourceHelper
import info.nightscout.androidaps.utils.sharedPreferences.SP
import org.json.JSONObject
@ -89,17 +88,16 @@ class NSProfilePlugin @Inject constructor(
@Inject lateinit var nsProfilePlugin: NSProfilePlugin
@Inject lateinit var aapsLogger: AAPSLogger
@Inject lateinit var rxBus: RxBusWrapper
@Inject lateinit var bundleStore: BundleStore
@Inject lateinit var dataWorker: DataWorker
init {
(context.applicationContext as HasAndroidInjector).androidInjector().inject(this)
}
override fun doWork(): Result {
val bundle = bundleStore.pickup(inputData.getLong(DataReceiver.STORE_KEY, -1))
val profileString = dataWorker.pickupJSONObject(inputData.getLong(DataWorker.STORE_KEY, -1))
?: return Result.failure()
bundle.getString("profile")?.let { profileString ->
nsProfilePlugin.profile = ProfileStore(injector, JSONObject(profileString))
nsProfilePlugin.profile = ProfileStore(injector, profileString)
nsProfilePlugin.storeNSProfile()
if (nsProfilePlugin.isEnabled()) {
rxBus.send(EventProfileStoreChanged())
@ -108,7 +106,5 @@ class NSProfilePlugin @Inject constructor(
aapsLogger.debug(LTag.PROFILE, "Received profileStore: ${nsProfilePlugin.profile}")
return Result.success()
}
return Result.failure()
}
}
}

View file

@ -40,7 +40,7 @@ import javax.inject.Singleton
import kotlin.math.min
@Singleton
class VirtualPumpPlugin @Inject constructor(
open class VirtualPumpPlugin @Inject constructor(
injector: HasAndroidInjector,
aapsLogger: AAPSLogger,
private val rxBus: RxBusWrapper,

View file

@ -11,6 +11,7 @@ import dagger.android.support.DaggerFragment
import info.nightscout.androidaps.R
import info.nightscout.androidaps.database.AppRepository
import info.nightscout.androidaps.database.entities.GlucoseValue
import info.nightscout.androidaps.database.entities.UserEntry.*
import info.nightscout.androidaps.database.transactions.InvalidateGlucoseValueTransaction
import info.nightscout.androidaps.databinding.BgsourceFragmentBinding
import info.nightscout.androidaps.databinding.BgsourceItemBinding
@ -128,7 +129,7 @@ class BGSourceFragment : DaggerFragment() {
activity?.let { activity ->
val text = dateUtil.dateAndTimeString(glucoseValue.timestamp) + "\n" + glucoseValue.valueToUnitsString(profileFunction.getUnits())
OKDialog.showConfirmation(activity, resourceHelper.gs(R.string.removerecord), text, Runnable {
uel.log("BG REMOVED", dateUtil.dateAndTimeString(glucoseValue.timestamp))
uel.log(Action.BG_REMOVED, ValueWithUnit(glucoseValue.timestamp, Units.Timestamp))
disposable += repository.runTransaction(InvalidateGlucoseValueTransaction(glucoseValue.id)).subscribe()
})
}

View file

@ -21,8 +21,7 @@ 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.BundleStore
import info.nightscout.androidaps.receivers.DataReceiver
import info.nightscout.androidaps.receivers.DataWorker
import info.nightscout.androidaps.utils.DateUtil
import info.nightscout.androidaps.utils.T
import info.nightscout.androidaps.utils.XDripBroadcast
@ -84,7 +83,7 @@ class DexcomPlugin @Inject constructor(
@Inject lateinit var dexcomPlugin: DexcomPlugin
@Inject lateinit var nsUpload: NSUpload
@Inject lateinit var sp: SP
@Inject lateinit var bundleStore: BundleStore
@Inject lateinit var dataWorker: DataWorker
@Inject lateinit var broadcastToXDrip: XDripBroadcast
@Inject lateinit var repository: AppRepository
@ -93,8 +92,10 @@ class DexcomPlugin @Inject constructor(
}
override fun doWork(): Result {
var ret = Result.success()
if (!dexcomPlugin.isEnabled(PluginType.BGSOURCE)) return Result.failure()
val bundle = bundleStore.pickup(inputData.getLong(DataReceiver.STORE_KEY, -1))
val bundle = dataWorker.pickupBundle(inputData.getLong(DataWorker.STORE_KEY, -1))
?: return Result.failure()
try {
val sourceSensor = when (bundle.getString("sensorType") ?: "") {
@ -142,23 +143,37 @@ class DexcomPlugin @Inject constructor(
broadcastToXDrip(it)
if (sp.getBoolean(R.string.key_dexcomg5_nsupload, false)) {
nsUpload.uploadBg(it, sourceSensor.text)
//aapsLogger.debug("XXXXX: dbAdd $it")
}
aapsLogger.debug(LTag.BGSOURCE, "Inserted bg $it")
}
result.updated.forEach {
broadcastToXDrip(it)
if (sp.getBoolean(R.string.key_dexcomg5_nsupload, false)) {
nsUpload.updateBg(it, sourceSensor.text)
//aapsLogger.debug("XXXXX: dpUpdate $it")
}
aapsLogger.debug(LTag.BGSOURCE, "Updated bg $it")
}
result.sensorInsertionsInserted.forEach {
if (sp.getBoolean(R.string.key_dexcomg5_nsupload, false)) {
nsUpload.uploadEvent(it)
}
aapsLogger.debug(LTag.BGSOURCE, "Inserted sensor insertion $it")
}
result.calibrationsInserted.forEach {
if (sp.getBoolean(R.string.key_dexcomg5_nsupload, false)) {
nsUpload.uploadEvent(it)
}
aapsLogger.debug(LTag.BGSOURCE, "Inserted calibration $it")
}
}, {
aapsLogger.error("Error while saving values from Dexcom App", it)
ret = Result.failure()
})
} catch (e: Exception) {
aapsLogger.error("Error while processing intent from Dexcom App", e)
ret = Result.failure()
}
return Result.success()
return ret
}
}

View file

@ -4,7 +4,6 @@ import android.content.Context
import androidx.work.Worker
import androidx.work.WorkerParameters
import dagger.android.HasAndroidInjector
import info.nightscout.androidaps.Constants
import info.nightscout.androidaps.R
import info.nightscout.androidaps.database.AppRepository
import info.nightscout.androidaps.database.entities.GlucoseValue
@ -18,14 +17,11 @@ 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.BundleStore
import info.nightscout.androidaps.receivers.DataReceiver
import info.nightscout.androidaps.receivers.DataWorker
import info.nightscout.androidaps.utils.DateUtil
import info.nightscout.androidaps.utils.XDripBroadcast
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 javax.inject.Inject
import javax.inject.Singleton
@ -48,13 +44,6 @@ class EversensePlugin @Inject constructor(
override var sensorBatteryLevel = -1
private val disposable = CompositeDisposable()
override fun onStop() {
disposable.clear()
super.onStop()
}
// cannot be inner class because of needed injection
class EversenseWorker(
context: Context,
@ -67,7 +56,7 @@ class EversensePlugin @Inject constructor(
@Inject lateinit var sp: SP
@Inject lateinit var nsUpload: NSUpload
@Inject lateinit var dateUtil: DateUtil
@Inject lateinit var bundleStore: BundleStore
@Inject lateinit var dataWorker: DataWorker
@Inject lateinit var repository: AppRepository
@Inject lateinit var broadcastToXDrip: XDripBroadcast
@ -76,8 +65,10 @@ class EversensePlugin @Inject constructor(
}
override fun doWork(): Result {
var ret = Result.success()
if (!eversensePlugin.isEnabled(PluginType.BGSOURCE)) return Result.failure()
val bundle = bundleStore.pickup(inputData.getLong(DataReceiver.STORE_KEY, -1))
val bundle = dataWorker.pickupBundle(inputData.getLong(DataWorker.STORE_KEY, -1))
?: return Result.failure()
if (bundle.containsKey("currentCalibrationPhase")) aapsLogger.debug(LTag.BGSOURCE, "currentCalibrationPhase: " + bundle.getString("currentCalibrationPhase"))
if (bundle.containsKey("placementModeInProgress")) aapsLogger.debug(LTag.BGSOURCE, "placementModeInProgress: " + bundle.getBoolean("placementModeInProgress"))
@ -116,15 +107,20 @@ class EversensePlugin @Inject constructor(
trendArrow = GlucoseValue.TrendArrow.NONE,
sourceSensor = GlucoseValue.SourceSensor.EVERSENSE
)
eversensePlugin.disposable += repository.runTransactionForResult(CgmSourceTransaction(glucoseValues, emptyList(), null)).subscribe({ savedValues ->
repository.runTransactionForResult(CgmSourceTransaction(glucoseValues, emptyList(), null))
.doOnError {
aapsLogger.error("Error while saving values from Eversense App", it)
ret = Result.failure()
}
.blockingGet()
.also { savedValues ->
savedValues.inserted.forEach {
broadcastToXDrip(it)
if (sp.getBoolean(R.string.key_dexcomg5_nsupload, false))
nsUpload.uploadBg(it, GlucoseValue.SourceSensor.EVERSENSE.text)
aapsLogger.debug(LTag.BGSOURCE, "Inserted bg $it")
}
}
}, {
aapsLogger.error("Error while saving values from Eversense App", it)
})
}
}
if (bundle.containsKey("calibrationGlucoseLevels")) {
@ -136,22 +132,29 @@ class EversensePlugin @Inject constructor(
aapsLogger.debug(LTag.BGSOURCE, "calibrationTimestamps" + Arrays.toString(calibrationTimestamps))
aapsLogger.debug(LTag.BGSOURCE, "calibrationRecordNumbers" + Arrays.toString(calibrationRecordNumbers))
for (i in calibrationGlucoseLevels.indices) {
eversensePlugin.disposable += repository.runTransactionForResult(InsertTherapyEventIfNewTransaction(
repository.runTransactionForResult(InsertTherapyEventIfNewTransaction(
timestamp = calibrationTimestamps[i],
type = TherapyEvent.Type.FINGER_STICK_BG_VALUE,
glucose = calibrationGlucoseLevels[i].toDouble(),
glucoseType = TherapyEvent.MeterType.FINGER,
glucoseUnit = TherapyEvent.GlucoseUnit.MGDL,
enteredBy = "AndroidAPS-Eversense"
)).subscribe({ result ->
result.inserted.forEach { nsUpload.uploadEvent(it) }
}, {
))
.doOnError {
aapsLogger.error(LTag.BGSOURCE, "Error while saving therapy event", it)
})
ret = Result.failure()
}
.blockingGet()
.also { result ->
result.inserted.forEach {
nsUpload.uploadEvent(it)
aapsLogger.debug(LTag.BGSOURCE, "Inserted bg $it")
}
}
}
return Result.success()
}
}
return ret
}
}
}

View file

@ -18,8 +18,6 @@ import info.nightscout.androidaps.plugins.general.nsclient.NSUpload
import info.nightscout.androidaps.utils.XDripBroadcast
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
@ -38,13 +36,6 @@ class GlimpPlugin @Inject constructor(
aapsLogger, resourceHelper, injector
), BgSourceInterface {
private val disposable = CompositeDisposable()
override fun onStop() {
disposable.clear()
super.onStop()
}
// cannot be inner class because of needed injection
class GlimpWorker(
context: Context,
@ -64,6 +55,8 @@ class GlimpPlugin @Inject constructor(
}
override fun doWork(): Result {
var ret = Result.success()
if (!glimpPlugin.isEnabled(PluginType.BGSOURCE)) return Result.failure()
aapsLogger.debug(LTag.BGSOURCE, "Received Glimp Data: $inputData}")
val glucoseValues = mutableListOf<CgmSourceTransaction.TransactionGlucoseValue>()
@ -75,16 +68,21 @@ class GlimpPlugin @Inject constructor(
trendArrow = GlucoseValue.TrendArrow.fromString(inputData.getString("myTrend")),
sourceSensor = GlucoseValue.SourceSensor.GLIMP
)
glimpPlugin.disposable += repository.runTransactionForResult(CgmSourceTransaction(glucoseValues, emptyList(), null)).subscribe({ savedValues ->
repository.runTransactionForResult(CgmSourceTransaction(glucoseValues, emptyList(), null))
.doOnError {
aapsLogger.error("Error while saving values from Glimp App", it)
ret = Result.failure()
}
.blockingGet()
.also { savedValues ->
savedValues.inserted.forEach {
broadcastToXDrip(it)
if (sp.getBoolean(R.string.key_dexcomg5_nsupload, false))
nsUpload.uploadBg(it, GlucoseValue.SourceSensor.GLIMP.text)
aapsLogger.debug(LTag.BGSOURCE, "Inserted bg $it")
}
}, {
aapsLogger.error("Error while saving values from Glimp App", it)
})
return Result.success()
}
return ret
}
}
}

View file

@ -15,13 +15,11 @@ 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.BundleStore
import info.nightscout.androidaps.receivers.DataWorker
import info.nightscout.androidaps.utils.DateUtil
import info.nightscout.androidaps.utils.XDripBroadcast
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 org.json.JSONArray
import org.json.JSONException
import javax.inject.Inject
@ -41,13 +39,6 @@ class MM640gPlugin @Inject constructor(
aapsLogger, resourceHelper, injector
), BgSourceInterface {
private val disposable = CompositeDisposable()
override fun onStop() {
disposable.clear()
super.onStop()
}
// cannot be inner class because of needed injection
class MM640gWorker(
context: Context,
@ -60,7 +51,7 @@ class MM640gPlugin @Inject constructor(
@Inject lateinit var sp: SP
@Inject lateinit var nsUpload: NSUpload
@Inject lateinit var dateUtil: DateUtil
@Inject lateinit var bundleStore: BundleStore
@Inject lateinit var dataWorker: DataWorker
@Inject lateinit var repository: AppRepository
@Inject lateinit var broadcastToXDrip: XDripBroadcast
@ -69,6 +60,8 @@ class MM640gPlugin @Inject constructor(
}
override fun doWork(): Result {
var ret = Result.success()
if (!mM640gPlugin.isEnabled(PluginType.BGSOURCE)) return Result.failure()
val collection = inputData.getString("collection") ?: return Result.failure()
if (collection == "entries") {
@ -93,21 +86,27 @@ class MM640gPlugin @Inject constructor(
else -> aapsLogger.debug(LTag.BGSOURCE, "Unknown entries type: $type")
}
}
mM640gPlugin.disposable += repository.runTransactionForResult(CgmSourceTransaction(glucoseValues, emptyList(), null)).subscribe({ savedValues ->
repository.runTransactionForResult(CgmSourceTransaction(glucoseValues, emptyList(), null))
.doOnError {
aapsLogger.error("Error while saving values from Eversense App", it)
ret = Result.failure()
}
.blockingGet()
.also { savedValues ->
savedValues.all().forEach {
broadcastToXDrip(it)
if (sp.getBoolean(R.string.key_dexcomg5_nsupload, false))
nsUpload.uploadBg(it, GlucoseValue.SourceSensor.MM_600_SERIES.text)
aapsLogger.debug(LTag.BGSOURCE, "Inserted bg $it")
}
}
}, {
aapsLogger.error("Error while saving values from Eversense App", it)
})
} catch (e: JSONException) {
aapsLogger.error("Exception: ", e)
ret = Result.failure()
}
}
}
return Result.success()
return ret
}
}
}

View file

@ -15,16 +15,18 @@ 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.bus.RxBusWrapper
import info.nightscout.androidaps.plugins.general.nsclient.NSClientPlugin
import info.nightscout.androidaps.plugins.general.nsclient.NSUpload
import info.nightscout.androidaps.plugins.general.nsclient.data.NSSgv
import info.nightscout.androidaps.receivers.BundleStore
import info.nightscout.androidaps.plugins.general.overview.events.EventDismissNotification
import info.nightscout.androidaps.plugins.general.overview.notifications.Notification
import info.nightscout.androidaps.receivers.DataWorker
import info.nightscout.androidaps.utils.DateUtil
import info.nightscout.androidaps.utils.T
import info.nightscout.androidaps.utils.XDripBroadcast
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 org.json.JSONArray
import org.json.JSONObject
import javax.inject.Inject
import javax.inject.Singleton
@ -55,13 +57,6 @@ class NSClientSourcePlugin @Inject constructor(
}
}
private val disposable = CompositeDisposable()
override fun onStop() {
disposable.clear()
super.onStop()
}
override fun advancedFilteringSupported(): Boolean {
return isAdvancedFilteringEnabled
}
@ -89,65 +84,85 @@ class NSClientSourcePlugin @Inject constructor(
@Inject lateinit var injector: HasAndroidInjector
@Inject lateinit var aapsLogger: AAPSLogger
@Inject lateinit var sp: SP
@Inject lateinit var rxBus: RxBusWrapper
@Inject lateinit var nsUpload: NSUpload
@Inject lateinit var dateUtil: DateUtil
@Inject lateinit var bundleStore: BundleStore
@Inject lateinit var dataWorker: DataWorker
@Inject lateinit var repository: AppRepository
@Inject lateinit var broadcastToXDrip: XDripBroadcast
@Inject lateinit var dexcomPlugin: DexcomPlugin
@Inject lateinit var nsClientPlugin: NSClientPlugin
init {
(context.applicationContext as HasAndroidInjector).androidInjector().inject(this)
}
private fun toGv(jsonObject: JSONObject): CgmSourceTransaction.TransactionGlucoseValue {
private fun toGv(jsonObject: JSONObject): CgmSourceTransaction.TransactionGlucoseValue? {
val sgv = NSSgv(jsonObject)
return CgmSourceTransaction.TransactionGlucoseValue(
timestamp = sgv.mills,
value = sgv.mgdl.toDouble(),
timestamp = sgv.mills ?: return null,
value = sgv.mgdl?.toDouble() ?: return null,
noise = null,
raw = if (sgv.filtered != null) sgv.filtered.toDouble() else sgv.mgdl.toDouble(),
raw = sgv.filtered?.toDouble() ?: sgv.mgdl?.toDouble(),
trendArrow = GlucoseValue.TrendArrow.fromString(sgv.direction),
nightscoutId = sgv.id,
sourceSensor = GlucoseValue.SourceSensor.fromString(sgv.device)
)
}
@Suppress("SpellCheckingInspection")
override fun doWork(): Result {
var ret = Result.success()
if (!nsClientSourcePlugin.isEnabled() && !sp.getBoolean(R.string.key_ns_autobackfill, true) && !dexcomPlugin.isEnabled()) return Result.failure()
val sgvs = dataWorker.pickupJSONArray(inputData.getLong(DataWorker.STORE_KEY, -1))
?: return Result.failure()
try {
var latestDateInReceivedData: Long = 0
aapsLogger.debug(LTag.BGSOURCE, "Received NS Data: $sgvs")
val glucoseValues = mutableListOf<CgmSourceTransaction.TransactionGlucoseValue>()
inputData.getString("sgv")?.let { sgvString ->
aapsLogger.debug(LTag.BGSOURCE, "Received NS Data: $sgvString")
glucoseValues += toGv(JSONObject(sgvString))
for (i in 0 until sgvs.length()) {
val sgv = toGv(sgvs.getJSONObject(i)) ?: continue
if (sgv.timestamp < dateUtil._now() && sgv.timestamp > latestDateInReceivedData) latestDateInReceivedData = sgv.timestamp
glucoseValues += sgv
}
inputData.getString("sgvs")?.let { sgvString ->
aapsLogger.debug(LTag.BGSOURCE, "Received NS Data: $sgvString")
val jsonArray = JSONArray(sgvString)
for (i in 0 until jsonArray.length())
glucoseValues += toGv(jsonArray.getJSONObject(i))
// Was that sgv more less 5 mins ago ?
if (T.msecs(dateUtil._now() - latestDateInReceivedData).mins() < 5L) {
rxBus.send(EventDismissNotification(Notification.NS_ALARM))
rxBus.send(EventDismissNotification(Notification.NS_URGENT_ALARM))
}
nsClientSourcePlugin.disposable += repository.runTransactionForResult(CgmSourceTransaction(glucoseValues, emptyList(), null, !nsClientSourcePlugin.isEnabled())).subscribe({ result ->
nsClientPlugin.updateLatestDateReceivedIfNewer(latestDateInReceivedData)
repository.runTransactionForResult(CgmSourceTransaction(glucoseValues, emptyList(), null, !nsClientSourcePlugin.isEnabled()))
.doOnError {
aapsLogger.error("Error while saving values from NSClient App", it)
ret = Result.failure()
}
.blockingGet()
.also { result ->
result.updated.forEach {
//aapsLogger.debug("XXXXX: Updated $it")
broadcastToXDrip(it)
nsClientSourcePlugin.detectSource(it)
aapsLogger.debug(LTag.BGSOURCE, "Updated bg $it")
}
result.inserted.forEach {
//aapsLogger.debug("XXXXX: Inserted $it")
broadcastToXDrip(it)
nsClientSourcePlugin.detectSource(it)
aapsLogger.debug(LTag.BGSOURCE, "Inserted bg $it")
}
}
}, {
aapsLogger.error("Error while saving values from NSClient App", it)
})
} catch (e: Exception) {
aapsLogger.error("Unhandled exception", e)
return Result.failure()
ret = Result.failure()
}
// Objectives 0
sp.putBoolean(R.string.key_ObjectivesbgIsAvailableInNS, true)
return Result.success()
return ret
}
}
}

View file

@ -20,8 +20,6 @@ import info.nightscout.androidaps.utils.JsonHelper.safeGetString
import info.nightscout.androidaps.utils.XDripBroadcast
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 org.json.JSONArray
import org.json.JSONException
import javax.inject.Inject
@ -42,13 +40,6 @@ class PoctechPlugin @Inject constructor(
aapsLogger, resourceHelper, injector
), BgSourceInterface {
private val disposable = CompositeDisposable()
override fun onStop() {
disposable.clear()
super.onStop()
}
// cannot be inner class because of needed injection
class PoctechWorker(
context: Context,
@ -68,6 +59,8 @@ class PoctechPlugin @Inject constructor(
}
override fun doWork(): Result {
var ret = Result.success()
if (!poctechPlugin.isEnabled(PluginType.BGSOURCE)) return Result.failure()
aapsLogger.debug(LTag.BGSOURCE, "Received Poctech Data $inputData")
try {
@ -86,20 +79,25 @@ class PoctechPlugin @Inject constructor(
sourceSensor = GlucoseValue.SourceSensor.POCTECH_NATIVE
)
}
poctechPlugin.disposable += repository.runTransactionForResult(CgmSourceTransaction(glucoseValues, emptyList(), null)).subscribe({ savedValues ->
repository.runTransactionForResult(CgmSourceTransaction(glucoseValues, emptyList(), null))
.doOnError {
aapsLogger.error("Error while saving values from Poctech App", it)
ret = Result.failure()
}
.blockingGet()
.also { savedValues ->
savedValues.inserted.forEach {
broadcastToXDrip(it)
if (sp.getBoolean(R.string.key_dexcomg5_nsupload, false))
nsUpload.uploadBg(it, GlucoseValue.SourceSensor.POCTECH_NATIVE.text)
aapsLogger.debug(LTag.BGSOURCE, "Inserted bg $it")
}
}
}, {
aapsLogger.error("Error while saving values from Poctech App", it)
})
} catch (e: JSONException) {
aapsLogger.error("Exception: ", e)
return Result.failure()
ret = Result.failure()
}
return Result.success()
return ret
}
}
}

View file

@ -112,6 +112,7 @@ class RandomBgPlugin @Inject constructor(
xDripBroadcast(it)
if (sp.getBoolean(R.string.key_dexcomg5_nsupload, false))
nsUpload.uploadBg(it, GlucoseValue.SourceSensor.RANDOM.text)
aapsLogger.debug(LTag.BGSOURCE, "Inserted bg $it")
}
}, {
aapsLogger.error(LTag.BGSOURCE, "Error while saving values from Random plugin", it)

View file

@ -18,8 +18,6 @@ import info.nightscout.androidaps.plugins.general.nsclient.NSUpload
import info.nightscout.androidaps.utils.XDripBroadcast
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
@ -39,13 +37,6 @@ class TomatoPlugin @Inject constructor(
aapsLogger, resourceHelper, injector
), BgSourceInterface {
private val disposable = CompositeDisposable()
override fun onStop() {
disposable.clear()
super.onStop()
}
// cannot be inner class because of needed injection
class TomatoWorker(
context: Context,
@ -64,7 +55,10 @@ class TomatoPlugin @Inject constructor(
(context.applicationContext as HasAndroidInjector).androidInjector().inject(this)
}
@Suppress("SpellCheckingInspection")
override fun doWork(): Result {
var ret = Result.success()
if (!tomatoPlugin.isEnabled(PluginType.BGSOURCE)) return Result.failure()
val glucoseValues = mutableListOf<CgmSourceTransaction.TransactionGlucoseValue>()
glucoseValues += CgmSourceTransaction.TransactionGlucoseValue(
@ -75,16 +69,21 @@ class TomatoPlugin @Inject constructor(
trendArrow = GlucoseValue.TrendArrow.NONE,
sourceSensor = GlucoseValue.SourceSensor.LIBRE_1_TOMATO
)
tomatoPlugin.disposable += repository.runTransactionForResult(CgmSourceTransaction(glucoseValues, emptyList(), null)).subscribe({ savedValues ->
repository.runTransactionForResult(CgmSourceTransaction(glucoseValues, emptyList(), null))
.doOnError {
aapsLogger.error("Error while saving values from Tomato App", it)
ret = Result.failure()
}
.blockingGet()
.also { savedValues ->
savedValues.inserted.forEach {
broadcastToXDrip(it)
if (sp.getBoolean(R.string.key_dexcomg5_nsupload, false))
nsUpload.uploadBg(it, GlucoseValue.SourceSensor.LIBRE_1_TOMATO.text)
aapsLogger.debug(LTag.BGSOURCE, "Inserted bg $it")
}
}, {
aapsLogger.error("Error while saving values from Tomato App", it)
})
return Result.success()
}
return ret
}
}
}

View file

@ -14,12 +14,9 @@ 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.receivers.BundleStore
import info.nightscout.androidaps.receivers.DataReceiver
import info.nightscout.androidaps.receivers.DataWorker
import info.nightscout.androidaps.services.Intents
import info.nightscout.androidaps.utils.resources.ResourceHelper
import io.reactivex.disposables.CompositeDisposable
import io.reactivex.rxkotlin.plusAssign
import javax.inject.Inject
import javax.inject.Singleton
@ -55,33 +52,29 @@ class XdripPlugin @Inject constructor(
).any { it == glucoseValue.sourceSensor }
}
private val disposable = CompositeDisposable()
override fun onStop() {
disposable.clear()
super.onStop()
}
// cannot be inner class because of needed injection
class XdripWorker(
context: Context,
params: WorkerParameters
) : Worker(context, params) {
@Inject lateinit var aapsLogger: AAPSLogger
@Inject lateinit var xdripPlugin: XdripPlugin
@Inject lateinit var repository: AppRepository
@Inject lateinit var bundleStore: BundleStore
@Inject lateinit var dataWorker: DataWorker
init {
(context.applicationContext as HasAndroidInjector).androidInjector().inject(this)
}
override fun doWork(): Result {
var ret = Result.success()
if (!xdripPlugin.isEnabled(PluginType.BGSOURCE)) return Result.failure()
val bundle = bundleStore.pickup(inputData.getLong(DataReceiver.STORE_KEY, -1))
val bundle = dataWorker.pickupBundle(inputData.getLong(DataWorker.STORE_KEY, -1))
?: return Result.failure()
xdripPlugin.aapsLogger.debug(LTag.BGSOURCE, "Received xDrip data: $bundle")
aapsLogger.debug(LTag.BGSOURCE, "Received xDrip data: $bundle")
val glucoseValues = mutableListOf<CgmSourceTransaction.TransactionGlucoseValue>()
glucoseValues += CgmSourceTransaction.TransactionGlucoseValue(
timestamp = bundle.getLong(Intents.EXTRA_TIMESTAMP, 0),
@ -92,15 +85,20 @@ class XdripPlugin @Inject constructor(
sourceSensor = GlucoseValue.SourceSensor.fromString(bundle.getString(Intents.XDRIP_DATA_SOURCE_DESCRIPTION)
?: "")
)
xdripPlugin.disposable += repository.runTransactionForResult(CgmSourceTransaction(glucoseValues, emptyList(), null)).subscribe({ savedValues ->
repository.runTransactionForResult(CgmSourceTransaction(glucoseValues, emptyList(), null))
.doOnError {
aapsLogger.error(LTag.BGSOURCE, "Error while saving values from Eversense App", it)
ret = Result.failure()
}
.blockingGet()
.also { savedValues ->
savedValues.all().forEach {
xdripPlugin.detectSource(it)
aapsLogger.debug(LTag.BGSOURCE, "Inserted bg $it")
}
}
}, {
xdripPlugin.aapsLogger.error(LTag.BGSOURCE, "Error while saving values from Eversense App", it)
})
xdripPlugin.sensorBatteryLevel = bundle.getInt(Intents.EXTRA_SENSOR_BATTERY, -1)
return Result.success()
return ret
}
}
}

View file

@ -45,11 +45,11 @@ import info.nightscout.androidaps.interfaces.PumpInterface;
import info.nightscout.androidaps.interfaces.TreatmentServiceInterface;
import info.nightscout.androidaps.interfaces.TreatmentsInterface;
import info.nightscout.androidaps.interfaces.UpdateReturn;
import info.nightscout.androidaps.interfaces.UploadQueueInterface;
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.nsclient.UploadQueue;
import info.nightscout.androidaps.plugins.general.overview.events.EventDismissNotification;
import info.nightscout.androidaps.plugins.general.overview.notifications.Notification;
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.AutosensResult;
@ -74,7 +74,7 @@ public class TreatmentsPlugin extends PluginBase implements TreatmentsInterface
private final ProfileFunction profileFunction;
private final ActivePluginProvider activePlugin;
private final NSUpload nsUpload;
private final UploadQueue uploadQueue;
private final UploadQueueInterface uploadQueue;
private final FabricPrivacy fabricPrivacy;
private final DateUtil dateUtil;
private final DatabaseHelperInterface databaseHelper;
@ -106,7 +106,7 @@ public class TreatmentsPlugin extends PluginBase implements TreatmentsInterface
NSUpload nsUpload,
FabricPrivacy fabricPrivacy,
DateUtil dateUtil,
UploadQueue uploadQueue,
UploadQueueInterface uploadQueue,
DatabaseHelperInterface databaseHelper,
AppRepository repository
) {
@ -386,7 +386,7 @@ public class TreatmentsPlugin extends PluginBase implements TreatmentsInterface
if (NSUpload.isIdValid(tempBasalId)) {
nsUpload.removeCareportalEntryFromNS(tempBasalId);
} else {
uploadQueue.removeID("dbAdd", tempBasalId);
uploadQueue.removeByMongoId("dbAdd", tempBasalId);
}
databaseHelper.delete(tempBasal);
}

View file

@ -9,6 +9,7 @@ import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import dagger.android.support.DaggerFragment
import info.nightscout.androidaps.R
import info.nightscout.androidaps.database.entities.UserEntry.*
import info.nightscout.androidaps.databinding.TreatmentsBolusFragmentBinding
import info.nightscout.androidaps.databinding.TreatmentsBolusItemBinding
import info.nightscout.androidaps.db.Source
@ -19,9 +20,9 @@ import info.nightscout.androidaps.interfaces.ProfileFunction
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.UploadQueue
import info.nightscout.androidaps.plugins.general.nsclient.events.EventNSClientRestart
import info.nightscout.androidaps.events.EventAutosensCalculationFinished
import info.nightscout.androidaps.interfaces.UploadQueueInterface
import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin
import info.nightscout.androidaps.plugins.treatments.fragments.TreatmentsBolusFragment.RecyclerViewAdapter.TreatmentsViewHolder
import info.nightscout.androidaps.utils.DateUtil
@ -45,7 +46,7 @@ class TreatmentsBolusFragment : DaggerFragment() {
@Inject lateinit var treatmentsPlugin: TreatmentsPlugin
@Inject lateinit var profileFunction: ProfileFunction
@Inject lateinit var nsUpload: NSUpload
@Inject lateinit var uploadQueue: UploadQueue
@Inject lateinit var uploadQueue: UploadQueueInterface
@Inject lateinit var dateUtil: DateUtil
@Inject lateinit var buildHelper: BuildHelper
@Inject lateinit var aapsSchedulers: AapsSchedulers
@ -68,7 +69,7 @@ class TreatmentsBolusFragment : DaggerFragment() {
binding.refreshFromNightscout.setOnClickListener {
activity?.let { activity ->
OKDialog.showConfirmation(activity, resourceHelper.gs(R.string.refresheventsfromnightscout) + "?") {
uel.log("TREAT NS REFRESH")
uel.log(Action.TREATMENTS_NS_REFRESH)
treatmentsPlugin.service.resetTreatments()
rxBus.send(EventNSClientRestart())
}
@ -77,13 +78,13 @@ class TreatmentsBolusFragment : DaggerFragment() {
binding.deleteFutureTreatments.setOnClickListener {
activity?.let { activity ->
OKDialog.showConfirmation(activity, resourceHelper.gs(R.string.overview_treatment_label), resourceHelper.gs(R.string.deletefuturetreatments) + "?", Runnable {
uel.log("DELETE FUTURE TREATMENTS")
uel.log(Action.DELETE_FUTURE_TREATMENTS)
val futureTreatments = treatmentsPlugin.service.getTreatmentDataFromTime(DateUtil.now() + 1000, true)
for (treatment in futureTreatments) {
if (NSUpload.isIdValid(treatment._id))
nsUpload.removeCareportalEntryFromNS(treatment._id)
else
uploadQueue.removeID("dbAdd", treatment._id)
uploadQueue.removeByMongoId("dbAdd", treatment._id)
treatmentsPlugin.service.delete(treatment)
}
updateGui()
@ -174,7 +175,7 @@ class TreatmentsBolusFragment : DaggerFragment() {
resourceHelper.gs(R.string.carbs) + ": " + resourceHelper.gs(R.string.format_carbs, treatment.carbs.toInt()) + "\n" +
resourceHelper.gs(R.string.date) + ": " + dateUtil.dateAndTimeString(treatment.date)
OKDialog.showConfirmation(activity, resourceHelper.gs(R.string.removerecord), text, Runnable {
uel.log("REMOVED TREATMENT", text)
uel.log(Action.TREATMENT_REMOVED, ValueWithUnit(treatment.date, Units.Timestamp), ValueWithUnit(treatment.insulin, Units.U, treatment.insulin != 0.0), ValueWithUnit(treatment.carbs.toInt(), Units.G, treatment.carbs != 0.0))
if (treatment.source == Source.PUMP) {
treatment.isValid = false
treatmentsPlugin.service.update(treatment)
@ -182,7 +183,7 @@ class TreatmentsBolusFragment : DaggerFragment() {
if (NSUpload.isIdValid(treatment._id))
nsUpload.removeCareportalEntryFromNS(treatment._id)
else
uploadQueue.removeID("dbAdd", treatment._id)
uploadQueue.removeByMongoId("dbAdd", treatment._id)
treatmentsPlugin.service.delete(treatment)
}
updateGui()

View file

@ -13,15 +13,16 @@ import info.nightscout.androidaps.database.AppRepository
import info.nightscout.androidaps.database.entities.TherapyEvent
import info.nightscout.androidaps.database.transactions.InvalidateAAPSStartedTherapyEventTransaction
import info.nightscout.androidaps.database.transactions.InvalidateTherapyEventTransaction
import info.nightscout.androidaps.database.entities.UserEntry.*
import info.nightscout.androidaps.databinding.TreatmentsCareportalFragmentBinding
import info.nightscout.androidaps.databinding.TreatmentsCareportalItemBinding
import info.nightscout.androidaps.events.EventTherapyEventChange
import info.nightscout.androidaps.interfaces.UploadQueueInterface
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.UploadQueue
import info.nightscout.androidaps.plugins.general.nsclient.events.EventNSClientRestart
import info.nightscout.androidaps.plugins.treatments.events.EventTreatmentUpdateGui
import info.nightscout.androidaps.plugins.treatments.fragments.TreatmentsCareportalFragment.RecyclerViewAdapter.TherapyEventsViewHolder
@ -51,7 +52,7 @@ class TreatmentsCareportalFragment : DaggerFragment() {
@Inject lateinit var fabricPrivacy: FabricPrivacy
@Inject lateinit var translator: Translator
@Inject lateinit var nsUpload: NSUpload
@Inject lateinit var uploadQueue: UploadQueue
@Inject lateinit var uploadQueue: UploadQueueInterface
@Inject lateinit var dateUtil: DateUtil
@Inject lateinit var buildHelper: BuildHelper
@Inject lateinit var aapsSchedulers: AapsSchedulers
@ -78,7 +79,7 @@ class TreatmentsCareportalFragment : DaggerFragment() {
binding.refreshFromNightscout.setOnClickListener {
activity?.let { activity ->
OKDialog.showConfirmation(activity, resourceHelper.gs(R.string.careportal), resourceHelper.gs(R.string.refresheventsfromnightscout) + " ?", Runnable {
uel.log("CAREPORTAL NS REFRESH")
uel.log(Action.CAREPORTAL_NS_REFRESH)
disposable += Completable.fromAction { repository.deleteAllTherapyEventsEntries() }
.subscribeOn(aapsSchedulers.io)
.observeOn(aapsSchedulers.main)
@ -93,7 +94,7 @@ class TreatmentsCareportalFragment : DaggerFragment() {
binding.removeAndroidapsStartedEvents.setOnClickListener {
activity?.let { activity ->
OKDialog.showConfirmation(activity, resourceHelper.gs(R.string.careportal), resourceHelper.gs(R.string.careportal_removestartedevents), Runnable {
uel.log("REMOVED RESTART EVENTS")
uel.log(Action.RESTART_EVENTS_REMOVED)
// val events = databaseHelper.getCareportalEvents(false)
repository.runTransactionForResult(InvalidateAAPSStartedTherapyEventTransaction())
.subscribe({ result ->
@ -101,7 +102,7 @@ class TreatmentsCareportalFragment : DaggerFragment() {
if (NSUpload.isIdValid(event.interfaceIDs.nightscoutId))
nsUpload.removeCareportalEntryFromNS(event.interfaceIDs.nightscoutId)
else
uploadQueue.removeID("dbAdd", event.timestamp.toString())
uploadQueue.removeByMongoId("dbAdd", event.timestamp.toString())
}
}, {
aapsLogger.error(LTag.BGSOURCE, "Error while invalidating therapy event", it)
@ -195,12 +196,12 @@ class TreatmentsCareportalFragment : DaggerFragment() {
resourceHelper.gs(R.string.notes_label) + ": " + (therapyEvent.note ?: "") + "\n" +
resourceHelper.gs(R.string.date) + ": " + dateUtil.dateAndTimeString(therapyEvent.timestamp)
OKDialog.showConfirmation(activity, resourceHelper.gs(R.string.removerecord), text, Runnable {
uel.log("REMOVED CAREPORTAL", text)
uel.log(Action.CAREPORTAL_REMOVED, therapyEvent.note , ValueWithUnit(therapyEvent.timestamp, Units.Timestamp), ValueWithUnit(therapyEvent.type.text, Units.TherapyEvent))
disposable += repository.runTransactionForResult(InvalidateTherapyEventTransaction(therapyEvent.id))
.subscribe({
val id = therapyEvent.interfaceIDs.nightscoutId
if (NSUpload.isIdValid(id)) nsUpload.removeCareportalEntryFromNS(id)
else uploadQueue.removeID("dbAdd", therapyEvent.timestamp.toString())
else uploadQueue.removeByMongoId("dbAdd", therapyEvent.timestamp.toString())
}, {
aapsLogger.error(LTag.BGSOURCE, "Error while invalidating therapy event", it)
})

View file

@ -12,6 +12,7 @@ import androidx.recyclerview.widget.RecyclerView
import dagger.android.support.DaggerFragment
import info.nightscout.androidaps.R
import info.nightscout.androidaps.data.Intervals
import info.nightscout.androidaps.database.entities.UserEntry.*
import info.nightscout.androidaps.databinding.TreatmentsExtendedbolusFragmentBinding
import info.nightscout.androidaps.databinding.TreatmentsExtendedbolusItemBinding
import info.nightscout.androidaps.db.ExtendedBolus
@ -21,10 +22,10 @@ import info.nightscout.androidaps.events.EventExtendedBolusChange
import info.nightscout.androidaps.interfaces.ActivePluginProvider
import info.nightscout.androidaps.interfaces.DatabaseHelperInterface
import info.nightscout.androidaps.interfaces.ProfileFunction
import info.nightscout.androidaps.interfaces.UploadQueueInterface
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.UploadQueue
import info.nightscout.androidaps.plugins.treatments.fragments.TreatmentsExtendedBolusesFragment.RecyclerViewAdapter.ExtendedBolusesViewHolder
import info.nightscout.androidaps.utils.DateUtil
import info.nightscout.androidaps.utils.FabricPrivacy
@ -43,7 +44,7 @@ class TreatmentsExtendedBolusesFragment : DaggerFragment() {
@Inject lateinit var resourceHelper: ResourceHelper
@Inject lateinit var fabricPrivacy: FabricPrivacy
@Inject lateinit var nsUpload: NSUpload
@Inject lateinit var uploadQueue: UploadQueue
@Inject lateinit var uploadQueue: UploadQueueInterface
@Inject lateinit var profileFunction: ProfileFunction
@Inject lateinit var dateUtil: DateUtil
@Inject lateinit var aapsSchedulers: AapsSchedulers
@ -122,10 +123,10 @@ class TreatmentsExtendedBolusesFragment : DaggerFragment() {
${resourceHelper.gs(R.string.extended_bolus)}
${resourceHelper.gs(R.string.date)}: ${dateUtil.dateAndTimeString(extendedBolus.date)}
""".trimIndent(), { _: DialogInterface, _: Int ->
uel.log("REMOVED EB")
uel.log(Action.EXTENDED_BOLUS_REMOVED)
val id = extendedBolus._id
if (NSUpload.isIdValid(id)) nsUpload.removeCareportalEntryFromNS(id)
else uploadQueue.removeID("dbAdd", id)
else uploadQueue.removeByMongoId("dbAdd", id)
databaseHelper.delete(extendedBolus)
}, null)
}

View file

@ -9,6 +9,7 @@ import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import dagger.android.support.DaggerFragment
import info.nightscout.androidaps.R
import info.nightscout.androidaps.database.entities.UserEntry.*
import info.nightscout.androidaps.databinding.TreatmentsProfileswitchFragmentBinding
import info.nightscout.androidaps.databinding.TreatmentsProfileswitchItemBinding
import info.nightscout.androidaps.db.ProfileSwitch
@ -16,10 +17,10 @@ import info.nightscout.androidaps.db.Source
import info.nightscout.androidaps.dialogs.ProfileViewerDialog
import info.nightscout.androidaps.events.EventProfileNeedsUpdate
import info.nightscout.androidaps.interfaces.DatabaseHelperInterface
import info.nightscout.androidaps.interfaces.UploadQueueInterface
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.UploadQueue
import info.nightscout.androidaps.plugins.general.nsclient.events.EventNSClientRestart
import info.nightscout.androidaps.plugins.profile.local.LocalProfilePlugin
import info.nightscout.androidaps.plugins.profile.local.events.EventLocalProfileChanged
@ -46,7 +47,7 @@ class TreatmentsProfileSwitchFragment : DaggerFragment() {
@Inject lateinit var resourceHelper: ResourceHelper
@Inject lateinit var fabricPrivacy: FabricPrivacy
@Inject lateinit var nsUpload: NSUpload
@Inject lateinit var uploadQueue: UploadQueue
@Inject lateinit var uploadQueue: UploadQueueInterface
@Inject lateinit var dateUtil: DateUtil
@Inject lateinit var buildHelper: BuildHelper
@Inject lateinit var aapsSchedulers: AapsSchedulers
@ -70,7 +71,7 @@ class TreatmentsProfileSwitchFragment : DaggerFragment() {
binding.refreshFromNightscout.setOnClickListener {
activity?.let { activity ->
uel.log("PROFILE SWITCH NS REFRESH")
uel.log(Action.PROFILE_SWITCH_NS_REFRESH)
OKDialog.showConfirmation(activity, resourceHelper.gs(R.string.refresheventsfromnightscout) + "?") {
databaseHelper.resetProfileSwitch()
rxBus.send(EventNSClientRestart())
@ -147,10 +148,10 @@ class TreatmentsProfileSwitchFragment : DaggerFragment() {
OKDialog.showConfirmation(activity, resourceHelper.gs(R.string.removerecord),
resourceHelper.gs(R.string.careportal_profileswitch) + ": " + profileSwitch.profileName +
"\n" + resourceHelper.gs(R.string.date) + ": " + dateUtil.dateAndTimeString(profileSwitch.date), Runnable {
uel.log("REMOVED PROFILE SWITCH", profileSwitch.profileName + " " + dateUtil.dateAndTimeString(profileSwitch.date))
uel.log(Action.PROFILE_SWITCH_REMOVED, profileSwitch.profileName, ValueWithUnit(profileSwitch.date, Units.Timestamp))
val id = profileSwitch._id
if (NSUpload.isIdValid(id)) nsUpload.removeCareportalEntryFromNS(id)
else uploadQueue.removeID("dbAdd", id)
else uploadQueue.removeByMongoId("dbAdd", id)
databaseHelper.delete(profileSwitch)
})
}
@ -160,7 +161,7 @@ class TreatmentsProfileSwitchFragment : DaggerFragment() {
val profileSwitch = it.tag as ProfileSwitch
OKDialog.showConfirmation(activity, resourceHelper.gs(R.string.careportal_profileswitch), resourceHelper.gs(R.string.copytolocalprofile) + "\n" + profileSwitch.customizedName + "\n" + dateUtil.dateAndTimeString(profileSwitch.date), Runnable {
profileSwitch.profileObject?.let {
uel.log("PROFILE SWITCH CLONE", profileSwitch.profileName + " " + dateUtil.dateAndTimeString(profileSwitch.date))
uel.log(Action.PROFILE_SWITCH_CLONED, ValueWithUnit(profileSwitch.date, Units.Timestamp), ValueWithUnit(profileSwitch.profileName, Units.None))
val nonCustomized = it.convertToNonCustomizedProfile()
if (nonCustomized.isValid(resourceHelper.gs(R.string.careportal_profileswitch, false))) {
localProfilePlugin.addProfile(localProfilePlugin.copyFrom(nonCustomized, profileSwitch.customizedName + " " + dateUtil.dateAndTimeString(profileSwitch.date).replace(".", "_")))

View file

@ -14,18 +14,19 @@ import info.nightscout.androidaps.R
import info.nightscout.androidaps.database.AppRepository
import info.nightscout.androidaps.database.ValueWrapper
import info.nightscout.androidaps.database.entities.TemporaryTarget
import info.nightscout.androidaps.database.entities.UserEntry.*
import info.nightscout.androidaps.database.interfaces.end
import info.nightscout.androidaps.database.transactions.InvalidateTemporaryTargetTransaction
import info.nightscout.androidaps.databinding.TreatmentsTemptargetFragmentBinding
import info.nightscout.androidaps.databinding.TreatmentsTemptargetItemBinding
import info.nightscout.androidaps.events.EventTempTargetChange
import info.nightscout.androidaps.interfaces.ProfileFunction
import info.nightscout.androidaps.interfaces.UploadQueueInterface
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.UploadQueue
import info.nightscout.androidaps.plugins.general.nsclient.events.EventNSClientRestart
import info.nightscout.androidaps.plugins.treatments.events.EventTreatmentUpdateGui
import info.nightscout.androidaps.plugins.treatments.fragments.TreatmentsTempTargetFragment.RecyclerViewAdapter.TempTargetsViewHolder
@ -57,7 +58,7 @@ class TreatmentsTempTargetFragment : DaggerFragment() {
@Inject lateinit var profileFunction: ProfileFunction
@Inject lateinit var resourceHelper: ResourceHelper
@Inject lateinit var nsUpload: NSUpload
@Inject lateinit var uploadQueue: UploadQueue
@Inject lateinit var uploadQueue: UploadQueueInterface
@Inject lateinit var fabricPrivacy: FabricPrivacy
@Inject lateinit var translator: Translator
@Inject lateinit var dateUtil: DateUtil
@ -85,7 +86,7 @@ class TreatmentsTempTargetFragment : DaggerFragment() {
binding.refreshFromNightscout.setOnClickListener {
context?.let { context ->
OKDialog.showConfirmation(context, resourceHelper.gs(R.string.refresheventsfromnightscout) + " ?", {
uel.log("TT NS REFRESH")
uel.log(Action.TT_NS_REFRESH)
disposable += Completable.fromAction { repository.deleteAllTempTargetEntries() }
.subscribeOn(aapsSchedulers.io)
.observeOn(aapsSchedulers.main)
@ -195,12 +196,12 @@ class TreatmentsTempTargetFragment : DaggerFragment() {
${dateUtil.dateAndTimeString(tempTarget.timestamp)}
""".trimIndent(),
{ _: DialogInterface?, _: Int ->
uel.log("TT REMOVE", tempTarget.friendlyDescription(profileFunction.getUnits(), resourceHelper))
uel.log(Action.TT_REMOVED, ValueWithUnit(tempTarget.timestamp, Units.Timestamp), ValueWithUnit(tempTarget.reason.text, Units.TherapyEvent), ValueWithUnit(tempTarget.lowTarget, Units.Mg_Dl), ValueWithUnit(tempTarget.highTarget, Units.Mg_Dl, tempTarget.lowTarget != tempTarget.highTarget), ValueWithUnit(tempTarget.duration.toInt(), Units.M))
disposable += repository.runTransactionForResult(InvalidateTemporaryTargetTransaction(tempTarget.id))
.subscribe({
val id = tempTarget.interfaceIDs.nightscoutId
if (NSUpload.isIdValid(id)) nsUpload.removeCareportalEntryFromNS(id)
else uploadQueue.removeID("dbAdd", tempTarget.timestamp.toString())
else uploadQueue.removeByMongoId("dbAdd", tempTarget.timestamp.toString())
}, {
aapsLogger.error(LTag.BGSOURCE, "Error while invalidating temporary target", it)
})

View file

@ -12,6 +12,7 @@ import dagger.android.support.DaggerFragment
import info.nightscout.androidaps.R
import info.nightscout.androidaps.data.Intervals
import info.nightscout.androidaps.data.IobTotal
import info.nightscout.androidaps.database.entities.UserEntry.*
import info.nightscout.androidaps.databinding.TreatmentsTempbasalsFragmentBinding
import info.nightscout.androidaps.databinding.TreatmentsTempbasalsItemBinding
import info.nightscout.androidaps.db.Source
@ -163,7 +164,7 @@ class TreatmentsTemporaryBasalsFragment : DaggerFragment() {
${resourceHelper.gs(R.string.date)}: ${dateUtil.dateAndTimeString(tempBasal.date)}
""".trimIndent(),
{ _: DialogInterface?, _: Int ->
uel.log("REMOVED TT", dateUtil.dateAndTimeString(tempBasal.date))
uel.log(Action.TT_REMOVED, ValueWithUnit(tempBasal.date, Units.Timestamp))
activePlugin.activeTreatments.removeTempBasal(tempBasal)
}, null)
}

View file

@ -7,22 +7,41 @@ import android.view.ViewGroup
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import dagger.android.support.DaggerFragment
import info.nightscout.androidaps.Constants
import info.nightscout.androidaps.R
import info.nightscout.androidaps.database.AppRepository
import info.nightscout.androidaps.database.entities.UserEntry
import info.nightscout.androidaps.database.entities.UserEntry.*
import info.nightscout.androidaps.databinding.TreatmentsUserEntryFragmentBinding
import info.nightscout.androidaps.databinding.TreatmentsUserEntryItemBinding
import info.nightscout.androidaps.events.EventPreferenceChange
import info.nightscout.androidaps.interfaces.ImportExportPrefsInterface
import info.nightscout.androidaps.interfaces.ProfileFunction
import info.nightscout.androidaps.logging.UserEntryLogger
import info.nightscout.androidaps.plugins.bus.RxBusWrapper
import info.nightscout.androidaps.utils.DateUtil
import info.nightscout.androidaps.utils.DecimalFormatter
import info.nightscout.androidaps.utils.FabricPrivacy
import info.nightscout.androidaps.utils.Translator
import info.nightscout.androidaps.utils.alertDialogs.OKDialog
import info.nightscout.androidaps.utils.extensions.*
import info.nightscout.androidaps.utils.resources.ResourceHelper
import info.nightscout.androidaps.utils.rx.AapsSchedulers
import io.reactivex.disposables.CompositeDisposable
import io.reactivex.rxkotlin.plusAssign
import javax.inject.Inject
class TreatmentsUserEntryFragment : DaggerFragment() {
@Inject lateinit var repository: AppRepository
@Inject lateinit var aapsSchedulers: AapsSchedulers
@Inject lateinit var resourceHelper: ResourceHelper
@Inject lateinit var dateUtil: DateUtil
@Inject lateinit var profileFunction: ProfileFunction
@Inject lateinit var fabricPrivacy: FabricPrivacy
@Inject lateinit var rxBus: RxBusWrapper
@Inject lateinit var translator: Translator
@Inject lateinit var importExportPrefs: ImportExportPrefsInterface
@Inject lateinit var uel: UserEntryLogger
private val disposable = CompositeDisposable()
@ -39,11 +58,40 @@ class TreatmentsUserEntryFragment : DaggerFragment() {
super.onViewCreated(view, savedInstanceState)
binding.recyclerview.setHasFixedSize(true)
binding.recyclerview.layoutManager = LinearLayoutManager(view.context)
binding.ueExportToXml.setOnClickListener {
activity?.let { activity ->
OKDialog.showConfirmation(activity, resourceHelper.gs(R.string.ue_export_to_csv) + "?") {
uel.log(Action.EXPORT_CSV)
importExportPrefs.exportUserEntriesCsv(activity, repository.getAllUserEntries())
}
}
}
disposable += repository
}
fun swapAdapter() {
disposable.add( repository
.getAllUserEntries()
.observeOn(aapsSchedulers.main)
.subscribe { list -> binding.recyclerview.swapAdapter(UserEntryAdapter(list), true) }
)
}
@Synchronized
override fun onResume() {
super.onResume()
swapAdapter()
disposable.add(rxBus
.toObservable(EventPreferenceChange::class.java)
.observeOn(aapsSchedulers.io)
.subscribe({ swapAdapter() }, fabricPrivacy::logException))
}
@Synchronized
override fun onPause() {
super.onPause()
disposable.clear()
}
@Synchronized
@ -63,12 +111,44 @@ class TreatmentsUserEntryFragment : DaggerFragment() {
override fun onBindViewHolder(holder: UserEntryViewHolder, position: Int) {
val current = entries[position]
holder.binding.date.text = dateUtil.dateAndTimeAndSecondsString(current.timestamp)
holder.binding.action.text = current.action
if (current.s != "") holder.binding.s.text = current.s else holder.binding.s.visibility = View.GONE
if (current.d1 != 0.0) holder.binding.d1.text = current.d1.toString() else holder.binding.d1.visibility = View.GONE
if (current.d2 != 0.0) holder.binding.d2.text = current.d2.toString() else holder.binding.d2.visibility = View.GONE
if (current.i1 != 0) holder.binding.i1.text = current.i1.toString() else holder.binding.i1.visibility = View.GONE
if (current.i2 != 0) holder.binding.i2.text = current.i2.toString() else holder.binding.i2.visibility = View.GONE
holder.binding.action.text = translator.translate(current.action.name)
holder.binding.action.setTextColor(resourceHelper.gc(current.action.colorGroup.colorId()))
if (current.s != "") {
holder.binding.s.text = current.s
holder.binding.s.visibility = View.VISIBLE
} else
holder.binding.s.visibility = View.GONE
var valuesWithUnitString = ""
var rStringParam = 0
val separator = " "
for(v in current.values) {
if (rStringParam >0)
rStringParam--
else
when (v.unit) {
Units.Timestamp -> valuesWithUnitString += dateUtil.dateAndTimeAndSecondsString(v.lValue) + separator
Units.TherapyEvent -> valuesWithUnitString += translator.translate(v.sValue) + separator
Units.R_String -> {
rStringParam = v.lValue.toInt()
when (rStringParam) { //
0 -> valuesWithUnitString += resourceHelper.gs(v.iValue) + separator
1 -> valuesWithUnitString += resourceHelper.gs(v.iValue, current.values[current.values.indexOf(v)+1].value()) + separator
2 -> valuesWithUnitString += resourceHelper.gs(v.iValue, current.values[current.values.indexOf(v)+1].value(), current.values[current.values.indexOf(v)+2].value()) + separator
3 -> valuesWithUnitString += resourceHelper.gs(v.iValue, current.values[current.values.indexOf(v)+1].value(), current.values[current.values.indexOf(v)+2].value(), current.values[current.values.indexOf(v)+3].value()) + separator
4 -> rStringParam = 0
}
}
Units.Mg_Dl -> valuesWithUnitString += if (profileFunction.getUnits()==Constants.MGDL) DecimalFormatter.to0Decimal(v.dValue) + translator.translate(Units.Mg_Dl.name) + separator else DecimalFormatter.to1Decimal(v.dValue/Constants.MMOLL_TO_MGDL) + translator.translate(Units.Mmol_L.name) + separator
Units.Mmol_L -> valuesWithUnitString += if (profileFunction.getUnits()==Constants.MGDL) DecimalFormatter.to0Decimal(v.dValue*Constants.MMOLL_TO_MGDL) + translator.translate(Units.Mg_Dl.name) + separator else DecimalFormatter.to1Decimal(v.dValue) + translator.translate(Units.Mmol_L.name) + separator
Units.U_H, Units.U
-> valuesWithUnitString += DecimalFormatter.to2Decimal(v.dValue) + translator.translate(v.unit.name) + separator
Units.G, Units.M, Units.H, Units.Percent
-> valuesWithUnitString += v.iValue.toString() + translator.translate(v.unit.name) + separator
else -> valuesWithUnitString += if (v.iValue != 0 || v.sValue != "") { v.value().toString() + separator } else ""
}
}
holder.binding.values.text = valuesWithUnitString.trim()
holder.binding.values.visibility = if (current.values.size > 0) View.VISIBLE else View.GONE
}
inner class UserEntryViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {

View file

@ -1,24 +0,0 @@
package info.nightscout.androidaps.receivers
import android.os.Bundle
import javax.inject.Inject
import javax.inject.Singleton
@Singleton
class BundleStore @Inject constructor() {
private val store = HashMap<Long, Bundle>()
private var counter = 0L
@Synchronized
fun store(bundle: Bundle) : Long {
store.put(counter, bundle)
return counter++
}
@Synchronized
fun pickup(key: Long) : Bundle? {
val bundle = store[key]
store.remove(key)
return bundle
}
}

View file

@ -2,34 +2,26 @@ package info.nightscout.androidaps.receivers
import android.content.Context
import android.content.Intent
import android.os.Bundle
import android.provider.Telephony
import androidx.work.Data
import androidx.work.ExistingWorkPolicy
import androidx.work.OneTimeWorkRequest
import androidx.work.WorkManager
import dagger.android.DaggerBroadcastReceiver
import info.nightscout.androidaps.logging.AAPSLogger
import info.nightscout.androidaps.logging.BundleLogger
import info.nightscout.androidaps.logging.LTag
import info.nightscout.androidaps.plugins.general.nsclient.NSClientWorker
import info.nightscout.androidaps.plugins.general.smsCommunicator.SmsCommunicatorPlugin
import info.nightscout.androidaps.plugins.profile.ns.NSProfilePlugin
import info.nightscout.androidaps.plugins.source.*
import info.nightscout.androidaps.services.Intents
import info.nightscout.androidaps.utils.extensions.copyDouble
import info.nightscout.androidaps.utils.extensions.copyInt
import info.nightscout.androidaps.utils.extensions.copyLong
import info.nightscout.androidaps.utils.extensions.copyString
import org.json.JSONObject
import javax.inject.Inject
open class DataReceiver : DaggerBroadcastReceiver() {
@Inject lateinit var aapsLogger: AAPSLogger
@Inject lateinit var bundleStore: BundleStore
private val jobGroupName = "data"
@Inject lateinit var dataWorker: DataWorker
override fun onReceive(context: Context, intent: Intent) {
super.onReceive(context, intent)
@ -40,7 +32,7 @@ open class DataReceiver : DaggerBroadcastReceiver() {
when (intent.action) {
Intents.ACTION_NEW_BG_ESTIMATE ->
OneTimeWorkRequest.Builder(XdripPlugin.XdripWorker::class.java)
.setInputData(bundleInputData(bundle, intent)).build()
.setInputData(dataWorker.storeInputData(bundle, intent)).build()
Intents.POCTECH_BG ->
OneTimeWorkRequest.Builder(PoctechPlugin.PoctechWorker::class.java)
.setInputData(Data.Builder().also {
@ -54,20 +46,12 @@ open class DataReceiver : DaggerBroadcastReceiver() {
it.copyLong("myTimestamp", bundle)
}.build()).build()
Intents.TOMATO_BG ->
@Suppress("SpellCheckingInspection")
OneTimeWorkRequest.Builder(TomatoPlugin.TomatoWorker::class.java)
.setInputData(Data.Builder().also {
it.copyDouble("com.fanqies.tomatofn.Extras.BgEstimate", bundle)
it.copyLong("com.fanqies.tomatofn.Extras.Time", bundle)
}.build()).build()
Intents.ACTION_NEW_PROFILE ->
OneTimeWorkRequest.Builder(NSProfilePlugin.NSProfileWorker::class.java)
.setInputData(bundleInputData(bundle, intent)).build()
Intents.ACTION_NEW_SGV ->
OneTimeWorkRequest.Builder(NSClientSourcePlugin.NSClientSourceWorker::class.java)
.setInputData(Data.Builder().also {
it.copyString("sgv", bundle, null)
it.copyString("sgvs", bundle, null)
}.build()).build()
Intents.NS_EMULATOR ->
OneTimeWorkRequest.Builder(MM640gPlugin.MM640gWorker::class.java)
.setInputData(Data.Builder().also {
@ -80,32 +64,15 @@ open class DataReceiver : DaggerBroadcastReceiver() {
}.build()).build()
Telephony.Sms.Intents.SMS_RECEIVED_ACTION ->
OneTimeWorkRequest.Builder(SmsCommunicatorPlugin.SmsCommunicatorWorker::class.java)
.setInputData(bundleInputData(bundle, intent)).build()
.setInputData(dataWorker.storeInputData(bundle, intent)).build()
Intents.EVERSENSE_BG ->
OneTimeWorkRequest.Builder(EversensePlugin.EversenseWorker::class.java)
.setInputData(bundleInputData(bundle, intent)).build()
.setInputData(dataWorker.storeInputData(bundle, intent)).build()
Intents.DEXCOM_BG ->
OneTimeWorkRequest.Builder(DexcomPlugin.DexcomWorker::class.java)
.setInputData(bundleInputData(bundle, intent)).build()
Intents.ACTION_NEW_TREATMENT,
Intents.ACTION_CHANGED_TREATMENT,
Intents.ACTION_REMOVED_TREATMENT,
Intents.ACTION_NEW_CAL,
Intents.ACTION_NEW_MBG ->
OneTimeWorkRequest.Builder(NSClientWorker::class.java)
.setInputData(bundleInputData(bundle, intent)).build()
.setInputData(dataWorker.storeInputData(bundle, intent)).build()
else -> null
}?.let { request ->
WorkManager.getInstance(context)
.enqueueUniqueWork(jobGroupName, ExistingWorkPolicy.APPEND_OR_REPLACE , request)
}
}?.let { request -> dataWorker.enqueue(request) }
}
private fun bundleInputData(bundle: Bundle, intent: Intent) =
Data.Builder().putLong(STORE_KEY, bundleStore.store(bundle)).putString(ACTION_KEY, intent.action).build()
companion object {
const val STORE_KEY = "storeKey"
const val ACTION_KEY = "action"
}
}

View file

@ -0,0 +1,70 @@
package info.nightscout.androidaps.receivers
import android.content.Context
import android.content.Intent
import android.os.Bundle
import androidx.work.Data
import androidx.work.ExistingWorkPolicy
import androidx.work.OneTimeWorkRequest
import androidx.work.WorkManager
import org.json.JSONArray
import org.json.JSONObject
import javax.inject.Inject
import javax.inject.Singleton
@Singleton
class DataWorker @Inject constructor(
private val context: Context
) {
private val store = HashMap<Long, Any>()
private var counter = 0L
private val jobGroupName = "data"
@Synchronized private fun store(value: Any): Long {
store[counter] = value
return counter++
}
@Synchronized fun pickupBundle(key: Long): Bundle? {
val value = store[key]
store.remove(key)
return value as Bundle?
}
@Synchronized fun pickupString(key: Long): String? {
val value = store[key]
store.remove(key)
return value as String?
}
@Synchronized fun pickupJSONArray(key: Long): JSONArray? {
val value = store[key]
store.remove(key)
return value as JSONArray?
}
@Synchronized fun pickupJSONObject(key: Long): JSONObject? {
val value = store[key]
store.remove(key)
return value as JSONObject?
}
fun storeInputData(value: Any, intent: Intent? = null) =
Data.Builder()
.putLong(STORE_KEY, store(value))
.putString(ACTION_KEY, intent?.action).build()
fun enqueue(request: OneTimeWorkRequest) {
WorkManager.getInstance(context)
.enqueueUniqueWork(jobGroupName, ExistingWorkPolicy.APPEND_OR_REPLACE, request)
}
companion object {
const val STORE_KEY = "storeKey"
const val ACTION_KEY = "action"
}
}

View file

@ -5,7 +5,7 @@ interface Intents {
companion object {
// NSClient -> App
// AAPS -> Xdrip
const val ACTION_NEW_TREATMENT = "info.nightscout.client.NEW_TREATMENT"
const val ACTION_CHANGED_TREATMENT = "info.nightscout.client.CHANGED_TREATMENT"
const val ACTION_REMOVED_TREATMENT = "info.nightscout.client.REMOVED_TREATMENT"
@ -14,7 +14,7 @@ interface Intents {
const val ACTION_NEW_MBG = "info.nightscout.client.NEW_MBG"
const val ACTION_NEW_CAL = "info.nightscout.client.NEW_CAL"
// xDrip -> App
// xDrip -> AAPS
const val ACTION_NEW_BG_ESTIMATE = "com.eveningoutpost.dexdrip.BgEstimate"
const val EXTRA_BG_ESTIMATE = "com.eveningoutpost.dexdrip.Extras.BgEstimate"
const val EXTRA_BG_SLOPE = "com.eveningoutpost.dexdrip.Extras.BgSlope"

View file

@ -38,20 +38,20 @@ class CarbTimer @Inject constructor(
// Bg under 180 mgdl and dropping by 15 mgdl
list.add(TriggerConnector(injector, TriggerConnector.Type.AND).apply {
list.add(TriggerBg(injector, 180.0, Constants.MGDL, Comparator.Compare.IS_LESSER))
list.add(TriggerDelta(injector, InputDelta(injector, -15.0, -360.0, 360.0, 1.0, DecimalFormat("0"), InputDelta.DeltaType.DELTA), Constants.MGDL, Comparator.Compare.IS_EQUAL_OR_LESSER))
list.add(TriggerDelta(injector, InputDelta(injector, -8.0, -360.0, 360.0, 1.0, DecimalFormat("0"), InputDelta.DeltaType.SHORT_AVERAGE), Constants.MGDL, Comparator.Compare.IS_EQUAL_OR_LESSER))
list.add(TriggerDelta(injector, InputDelta(resourceHelper, -15.0, -360.0, 360.0, 1.0, DecimalFormat("0"), InputDelta.DeltaType.DELTA), Constants.MGDL, Comparator.Compare.IS_EQUAL_OR_LESSER))
list.add(TriggerDelta(injector, InputDelta(resourceHelper, -8.0, -360.0, 360.0, 1.0, DecimalFormat("0"), InputDelta.DeltaType.SHORT_AVERAGE), Constants.MGDL, Comparator.Compare.IS_EQUAL_OR_LESSER))
})
// Bg under 160 mgdl and dropping by 9 mgdl
list.add(TriggerConnector(injector, TriggerConnector.Type.AND).apply {
list.add(TriggerBg(injector, 160.0, Constants.MGDL, Comparator.Compare.IS_LESSER))
list.add(TriggerDelta(injector, InputDelta(injector, -9.0, -360.0, 360.0, 1.0, DecimalFormat("0"), InputDelta.DeltaType.DELTA), Constants.MGDL, Comparator.Compare.IS_EQUAL_OR_LESSER))
list.add(TriggerDelta(injector, InputDelta(injector, -5.0, -360.0, 360.0, 1.0, DecimalFormat("0"), InputDelta.DeltaType.SHORT_AVERAGE), Constants.MGDL, Comparator.Compare.IS_EQUAL_OR_LESSER))
list.add(TriggerDelta(injector, InputDelta(resourceHelper, -9.0, -360.0, 360.0, 1.0, DecimalFormat("0"), InputDelta.DeltaType.DELTA), Constants.MGDL, Comparator.Compare.IS_EQUAL_OR_LESSER))
list.add(TriggerDelta(injector, InputDelta(resourceHelper, -5.0, -360.0, 360.0, 1.0, DecimalFormat("0"), InputDelta.DeltaType.SHORT_AVERAGE), Constants.MGDL, Comparator.Compare.IS_EQUAL_OR_LESSER))
})
// Bg under 145 mgdl and dropping
list.add(TriggerConnector(injector, TriggerConnector.Type.AND).apply {
list.add(TriggerBg(injector, 145.0, Constants.MGDL, Comparator.Compare.IS_LESSER))
list.add(TriggerDelta(injector, InputDelta(injector, 0.0, -360.0, 360.0, 1.0, DecimalFormat("0"), InputDelta.DeltaType.DELTA), Constants.MGDL, Comparator.Compare.IS_EQUAL_OR_LESSER))
list.add(TriggerDelta(injector, InputDelta(injector, 0.0, -360.0, 360.0, 1.0, DecimalFormat("0"), InputDelta.DeltaType.SHORT_AVERAGE), Constants.MGDL, Comparator.Compare.IS_EQUAL_OR_LESSER))
list.add(TriggerDelta(injector, InputDelta(resourceHelper, 0.0, -360.0, 360.0, 1.0, DecimalFormat("0"), InputDelta.DeltaType.DELTA), Constants.MGDL, Comparator.Compare.IS_EQUAL_OR_LESSER))
list.add(TriggerDelta(injector, InputDelta(resourceHelper, 0.0, -360.0, 360.0, 1.0, DecimalFormat("0"), InputDelta.DeltaType.SHORT_AVERAGE), Constants.MGDL, Comparator.Compare.IS_EQUAL_OR_LESSER))
})
}
actions.add(ActionAlarm(injector, resourceHelper.gs(R.string.time_to_eat)))

View file

@ -10,11 +10,11 @@ import info.nightscout.androidaps.db.TDD
import info.nightscout.androidaps.interfaces.ActivePluginProvider
import info.nightscout.androidaps.interfaces.DatabaseHelperInterface
import info.nightscout.androidaps.interfaces.ProfileFunction
import info.nightscout.androidaps.interfaces.UploadQueueInterface
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.nsclient.UploadQueue
import info.nightscout.androidaps.plugins.treatments.TreatmentService
import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin
import info.nightscout.androidaps.utils.DateUtil
@ -40,7 +40,7 @@ class TddCalculator @Inject constructor(
fabricPrivacy: FabricPrivacy,
nsUpload: NSUpload,
private val dateUtil: DateUtil,
uploadQueue: UploadQueue,
uploadQueue: UploadQueueInterface,
databaseHelper: DatabaseHelperInterface,
repository: AppRepository
) : TreatmentsPlugin(injector, aapsLogger, rxBus, aapsSchedulers, resourceHelper, context, sp, profileFunction, activePlugin, nsUpload, fabricPrivacy, dateUtil, uploadQueue, databaseHelper, repository) {

View file

@ -12,6 +12,7 @@ import info.nightscout.androidaps.data.DetailedBolusInfo
import info.nightscout.androidaps.data.Profile
import info.nightscout.androidaps.database.entities.TemporaryTarget
import info.nightscout.androidaps.database.entities.TherapyEvent
import info.nightscout.androidaps.database.entities.UserEntry.*
import info.nightscout.androidaps.db.Source
import info.nightscout.androidaps.events.EventRefreshOverview
import info.nightscout.androidaps.interfaces.*
@ -348,7 +349,7 @@ class BolusWizard @Inject constructor(
boluscalc = nsJSON()
source = Source.USER
notes = this@BolusWizard.notes
uel.log("BOLUS ADVISOR", d1 = insulinAfterConstraints)
uel.log(Action.BOLUS_ADVISOR, notes, ValueWithUnit(eventType, Units.TherapyEvent), ValueWithUnit(insulinAfterConstraints, Units.U))
if (insulin > 0) {
commandQueue.bolus(this, object : Callback() {
override fun run() {
@ -371,7 +372,7 @@ class BolusWizard @Inject constructor(
OKDialog.showConfirmation(ctx, resourceHelper.gs(R.string.boluswizard), confirmMessage, {
if (insulinAfterConstraints > 0 || carbs > 0) {
if (useSuperBolus) {
uel.log("SUPERBOLUS TBR")
uel.log(Action.SUPERBOLUS_TBR)
if (loopPlugin.isEnabled(PluginType.LOOP)) {
loopPlugin.superBolusTo(System.currentTimeMillis() + 2 * 60L * 60 * 1000)
rxBus.send(EventRefreshOverview("WizardDialog"))
@ -412,7 +413,7 @@ class BolusWizard @Inject constructor(
boluscalc = nsJSON()
source = Source.USER
notes = this@BolusWizard.notes
uel.log("BOLUS WIZARD", "", insulinAfterConstraints, carbs)
uel.log(Action.BOLUS, notes, ValueWithUnit(eventType,Units.TherapyEvent), ValueWithUnit(insulinAfterConstraints, Units.U), ValueWithUnit(this@BolusWizard.carbs, Units.G, this@BolusWizard.carbs != 0), ValueWithUnit(carbTime, Units.M, carbTime != 0))
if (insulin > 0 || pump.pumpDescription.storesCarbInfo) {
commandQueue.bolus(this, object : Callback() {
override fun run() {

View file

@ -4,6 +4,6 @@
android:viewportHeight="24"
android:viewportWidth="24"
xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="#67DFE8" android:pathData="M15.714,7.697l0.353,-0.684c0.18,-0.348 0.043,-0.775 -0.305,-0.955c-0.351,-0.181 -0.775,-0.043 -0.955,0.305l-0.354,0.685c-0.379,-0.148 -0.772,-0.265 -1.18,-0.344V6.106c0.45,-0.061 0.802,-0.431 0.802,-0.897c0,-0.509 -0.412,-0.921 -0.921,-0.921h-2.313c-0.509,0 -0.921,0.413 -0.921,0.921c0,0.467 0.352,0.836 0.802,0.897v0.598c-3.125,0.599 -5.495,3.349 -5.495,6.646c0,3.732 3.037,6.77 6.77,6.77c3.732,0 6.77,-3.037 6.77,-6.77C18.768,10.989 17.551,8.909 15.714,7.697zM11.998,19.119c-3.182,0 -5.77,-2.588 -5.77,-5.77s2.588,-5.77 5.77,-5.77s5.77,2.588 5.77,5.77S15.18,19.119 11.998,19.119z"/>
<path android:fillColor="#67DFE8" android:pathData="M12,8.814c-0.086,0 -0.169,0.035 -0.23,0.096s-0.096,0.144 -0.096,0.23v4.198c0,0.08 0.029,0.157 0.083,0.217l2.789,3.14c0.058,0.064 0.139,0.104 0.226,0.108c0.006,0.001 0.013,0.001 0.019,0.001c0.08,0 0.157,-0.029 0.217,-0.083c0.971,-0.866 1.527,-2.095 1.527,-3.372C16.533,10.85 14.5,8.816 12,8.814z"/>
<path android:fillColor="@color/extendedBolus" android:pathData="M15.714,7.697l0.353,-0.684c0.18,-0.348 0.043,-0.775 -0.305,-0.955c-0.351,-0.181 -0.775,-0.043 -0.955,0.305l-0.354,0.685c-0.379,-0.148 -0.772,-0.265 -1.18,-0.344V6.106c0.45,-0.061 0.802,-0.431 0.802,-0.897c0,-0.509 -0.412,-0.921 -0.921,-0.921h-2.313c-0.509,0 -0.921,0.413 -0.921,0.921c0,0.467 0.352,0.836 0.802,0.897v0.598c-3.125,0.599 -5.495,3.349 -5.495,6.646c0,3.732 3.037,6.77 6.77,6.77c3.732,0 6.77,-3.037 6.77,-6.77C18.768,10.989 17.551,8.909 15.714,7.697zM11.998,19.119c-3.182,0 -5.77,-2.588 -5.77,-5.77s2.588,-5.77 5.77,-5.77s5.77,2.588 5.77,5.77S15.18,19.119 11.998,19.119z"/>
<path android:fillColor="@color/extendedBolus" android:pathData="M12,8.814c-0.086,0 -0.169,0.035 -0.23,0.096s-0.096,0.144 -0.096,0.23v4.198c0,0.08 0.029,0.157 0.083,0.217l2.789,3.14c0.058,0.064 0.139,0.104 0.226,0.108c0.006,0.001 0.013,0.001 0.019,0.001c0.08,0 0.157,-0.029 0.217,-0.083c0.971,-0.866 1.527,-2.095 1.527,-3.372C16.533,10.85 14.5,8.816 12,8.814z"/>
</vector>

View file

@ -5,11 +5,11 @@
android:viewportHeight="24">
<path
android:pathData="M7.305,4.482c1.782,2.914 4.332,5.382 3.916,9.05c-0.256,2.254 -2.529,3.635 -4.783,3.199c-2.145,-0.415 -3.625,-2.546 -3.171,-4.728C3.858,9.168 5.537,6.894 7.305,4.482zM5.08,10.061c-0.212,0.638 -0.489,1.262 -0.621,1.916c-0.205,1.017 -0.065,1.994 0.764,2.731c0.297,0.264 0.68,0.354 1.038,0.077c0.242,-0.187 0.269,-0.46 0.096,-0.692C5.468,12.903 5.032,11.589 5.08,10.061z"
android:fillColor="#E83258"/>
android:fillColor="@color/calibration"/>
<path
android:pathData="M17.959,4.566c1.073,1.453 2.073,2.837 2.489,4.535c0.28,1.143 -0.069,2.1 -1.037,2.763c-0.943,0.645 -1.961,0.655 -2.904,0.009c-0.967,-0.662 -1.318,-1.635 -1.041,-2.769C15.88,7.408 16.875,6.019 17.959,4.566z"
android:fillColor="#E83258"/>
android:fillColor="@color/calibration"/>
<path
android:pathData="M14.82,14.425c0.797,1.094 1.535,2.104 1.819,3.355c0.188,0.826 -0.096,1.498 -0.784,1.965c-0.669,0.454 -1.393,0.467 -2.067,0.014c-0.688,-0.462 -0.985,-1.13 -0.8,-1.959C13.272,16.531 14.004,15.503 14.82,14.425z"
android:fillColor="#E83258"/>
android:fillColor="@color/calibration"/>
</vector>

View file

@ -5,5 +5,5 @@
android:viewportHeight="24">
<path
android:pathData="M24,9.343l-5.781,-3.968l-1.328,6.688l2.102,-1.757c0.014,0.056 0.03,0.111 0.043,0.168c0.116,0.512 0.183,1.042 0.183,1.589c0,3.952 -3.204,7.156 -7.156,7.156s-7.156,-3.204 -7.156,-7.156s3.204,-7.156 7.156,-7.156c1.072,0 2.085,0.242 2.998,0.665c0.325,0.151 0.639,0.321 0.936,0.517l0.002,-0.002l-0.352,-1.784l1.876,-0.538c-1.567,-1.033 -3.442,-1.639 -5.46,-1.639c-5.488,0 -9.938,4.449 -9.938,9.938S6.574,22 12.063,22S22,17.551 22,12.063c0,-0.759 -0.093,-1.496 -0.254,-2.206c-0.04,-0.176 -0.085,-0.35 -0.134,-0.523L24,9.343L24,9.343z"
android:fillColor="#00C03E"/>
android:fillColor="@color/loopClosed"/>
</vector>

View file

@ -5,11 +5,11 @@
android:viewportHeight="24">
<path
android:pathData="M24,9.343l-5.781,-3.968l-1.328,6.688l2.102,-1.757c0.014,0.056 0.03,0.111 0.043,0.168c0.116,0.512 0.183,1.042 0.183,1.589c0,3.952 -3.204,7.156 -7.156,7.156s-7.156,-3.204 -7.156,-7.156s3.204,-7.156 7.156,-7.156c1.072,0 2.085,0.242 2.998,0.665c0.325,0.151 0.639,0.321 0.936,0.517l0.002,-0.002l-0.352,-1.784l1.876,-0.538c-1.567,-1.033 -3.442,-1.639 -5.46,-1.639c-5.488,0 -9.938,4.449 -9.938,9.938S6.574,22 12.063,22S22,17.551 22,12.063c0,-0.759 -0.093,-1.496 -0.254,-2.206c-0.04,-0.176 -0.085,-0.35 -0.134,-0.523L24,9.343L24,9.343z"
android:fillColor="#FF1313"/>
android:fillColor="@color/loopDisabled"/>
<path
android:pathData="M10.2429,8.7408l5.0162,5.0162l-1.5026,1.5026l-5.0162,-5.0162z"
android:fillColor="#FF1313"/>
android:fillColor="@color/loopDisabled"/>
<path
android:pathData="M8.7408,13.7571l5.0162,-5.0162l1.5026,1.5026l-5.0162,5.0162z"
android:fillColor="#FF1313"/>
android:fillColor="@color/loopDisabled"/>
</vector>

View file

@ -5,8 +5,8 @@
android:viewportHeight="24">
<path
android:pathData="M17.523,3.764c-1.567,-1.033 -3.442,-1.639 -5.46,-1.639c-5.488,0 -9.938,4.449 -9.938,9.938c0,1.803 0.484,3.49 1.325,4.945l-0.319,0.365c-0.001,0.842 0.325,1.681 1.01,2.277l2.416,2.103l0.872,-1.002l1.746,1.523l0.472,-0.542l-1.747,-1.523l1.272,-1.461l1.748,1.524l0.472,-0.542l-1.749,-1.525l0.872,-1.001l-2.416,-2.103c-0.684,-0.596 -1.557,-0.803 -2.39,-0.687l-0.277,0.318c-0.335,-0.825 -0.528,-1.723 -0.528,-2.67c0,-3.952 3.204,-7.156 7.156,-7.156c1.072,0 2.085,0.242 2.998,0.665c0.325,0.151 0.639,0.321 0.936,0.517l0.002,-0.002l-0.352,-1.784L17.523,3.764z"
android:fillColor="#939393"/>
android:fillColor="@color/loopDisconnected"/>
<path
android:pathData="M24,9.343l-5.781,-3.968l-1.328,6.688l2.102,-1.757c0.014,0.056 0.03,0.111 0.043,0.168c0.116,0.512 0.183,1.042 0.183,1.589c0,0.938 -0.183,1.833 -0.511,2.653l-0.263,-0.302c-0.833,-0.116 -1.706,0.091 -2.39,0.687l-2.416,2.103l3.96,4.549l2.416,-2.103c0.685,-0.596 1.011,-1.435 1.01,-2.277l-0.346,-0.397C21.51,15.526 22,13.855 22,12.063c0,-0.759 -0.093,-1.496 -0.254,-2.206c-0.04,-0.176 -0.085,-0.35 -0.134,-0.523L24,9.343L24,9.343z"
android:fillColor="#939393"/>
android:fillColor="@color/loopDisconnected"/>
</vector>

View file

@ -5,20 +5,20 @@
android:viewportHeight="24">
<path
android:pathData="M6.349,7.767c0.408,-0.542 0.89,-1.022 1.433,-1.429L6.38,3.917C5.424,4.584 4.593,5.415 3.924,6.37L6.349,7.767z"
android:fillColor="#00C03E"/>
android:fillColor="@color/loopClosed"/>
<path
android:pathData="M9.258,5.478c0.613,-0.262 1.272,-0.436 1.959,-0.517l-0.003,-2.793c-1.191,0.101 -2.318,0.414 -3.352,0.898L9.258,5.478z"
android:fillColor="#00C03E"/>
android:fillColor="@color/loopClosed"/>
<path
android:pathData="M12.922,2.189l0.003,2.773c0.754,0.093 1.472,0.301 2.135,0.608c0.325,0.151 0.639,0.321 0.936,0.517l0.002,-0.002l-0.352,-1.784l1.876,-0.538C16.182,2.88 14.61,2.336 12.922,2.189z"
android:fillColor="#00C03E"/>
android:fillColor="@color/loopClosed"/>
<path
android:pathData="M4.963,11.199c0.083,-0.687 0.259,-1.345 0.523,-1.958L3.072,7.85c-0.485,1.034 -0.801,2.16 -0.903,3.351L4.963,11.199z"
android:fillColor="#00C03E"/>
android:fillColor="@color/loopClosed"/>
<path
android:pathData="M24,9.343l-5.781,-3.968l-1.328,6.688l2.102,-1.757c0.014,0.056 0.03,0.111 0.043,0.168c0.116,0.512 0.183,1.042 0.183,1.589c0,3.952 -3.204,7.156 -7.156,7.156c-2.345,0 -4.42,-1.133 -5.725,-2.876l-2.421,1.401C5.712,20.315 8.689,22 12.063,22C17.551,22 22,17.551 22,12.063c0,-0.759 -0.093,-1.496 -0.254,-2.206c-0.04,-0.176 -0.085,-0.35 -0.134,-0.523L24,9.343L24,9.343z"
android:fillColor="#00C03E"/>
android:fillColor="@color/loopClosed"/>
<path
android:pathData="M5.478,14.867c-0.262,-0.614 -0.436,-1.272 -0.517,-1.96L2.168,12.91c0.101,1.191 0.414,2.319 0.898,3.353L5.478,14.867z"
android:fillColor="#00C03E"/>
android:fillColor="@color/loopClosed"/>
</vector>

View file

@ -5,23 +5,23 @@
android:viewportHeight="24">
<path
android:pathData="M6.349,7.767c0.408,-0.542 0.89,-1.022 1.433,-1.429L6.38,3.917C5.424,4.584 4.593,5.415 3.924,6.37L6.349,7.767z"
android:fillColor="#4983D7"/>
android:fillColor="@color/loopOpened"/>
<path
android:pathData="M3.072,7.85c-0.485,1.034 -0.801,2.16 -0.903,3.351l2.795,-0.003c0.083,-0.687 0.259,-1.345 0.523,-1.958L3.072,7.85z"
android:fillColor="#4983D7"/>
android:fillColor="@color/loopOpened"/>
<path
android:pathData="M21.059,7.862l-2.412,1.396c0.262,0.614 0.437,1.272 0.518,1.96l2.793,-0.003C21.856,10.024 21.543,8.896 21.059,7.862z"
android:fillColor="#4983D7"/>
android:fillColor="@color/loopOpened"/>
<path
android:pathData="M17.787,7.781l2.421,-1.401c-0.668,-0.956 -1.499,-1.787 -2.454,-2.456l-1.397,2.425C16.9,6.757 17.38,7.238 17.787,7.781z"
android:fillColor="#4983D7"/>
android:fillColor="@color/loopOpened"/>
<path
android:pathData="M19.162,12.926c-0.427,3.544 -3.44,6.293 -7.099,6.293c-3.666,0 -6.684,-2.758 -7.102,-6.312L2.168,12.91C2.599,18.001 6.86,22 12.063,22c5.198,0 9.457,-3.992 9.894,-9.077L19.162,12.926z"
android:fillColor="#4983D7"/>
android:fillColor="@color/loopOpened"/>
<path
android:pathData="M9.258,5.478c0.613,-0.262 1.272,-0.436 1.959,-0.517l-0.003,-2.793c-1.191,0.101 -2.318,0.414 -3.352,0.898L9.258,5.478z"
android:fillColor="#4983D7"/>
android:fillColor="@color/loopOpened"/>
<path
android:pathData="M12.925,4.963c0.687,0.083 1.345,0.259 1.958,0.522l1.391,-2.414c-1.034,-0.485 -2.161,-0.801 -3.352,-0.903L12.925,4.963z"
android:fillColor="#4983D7"/>
android:fillColor="@color/loopOpened"/>
</vector>

View file

@ -5,11 +5,11 @@
android:viewportHeight="24">
<path
android:pathData="M24,9.343l-5.781,-3.968l-1.328,6.688l2.102,-1.757c0.014,0.056 0.03,0.111 0.043,0.168c0.116,0.512 0.183,1.042 0.183,1.589c0,3.952 -3.204,7.156 -7.156,7.156s-7.156,-3.204 -7.156,-7.156s3.204,-7.156 7.156,-7.156c1.072,0 2.085,0.242 2.998,0.665c0.325,0.151 0.639,0.321 0.936,0.517l0.002,-0.002l-0.352,-1.784l1.876,-0.538c-1.567,-1.033 -3.442,-1.639 -5.46,-1.639c-5.488,0 -9.938,4.449 -9.938,9.938S6.574,22 12.063,22S22,17.551 22,12.063c0,-0.759 -0.093,-1.496 -0.254,-2.206c-0.04,-0.176 -0.085,-0.35 -0.134,-0.523L24,9.343L24,9.343z"
android:fillColor="#FFFF13"/>
android:fillColor="@color/loopSuspended"/>
<path
android:pathData="M8.813,8.453h2.125v7.094h-2.125z"
android:fillColor="#FFFF13"/>
android:fillColor="@color/loopSuspended"/>
<path
android:pathData="M13.063,8.453h2.125v7.094h-2.125z"
android:fillColor="#FFFF13"/>
android:fillColor="@color/loopSuspended"/>
</vector>

View file

@ -5,8 +5,8 @@
android:viewportHeight="24">
<path
android:pathData="M24,9.343l-5.781,-3.968l-1.328,6.688l2.102,-1.757c0.014,0.056 0.03,0.111 0.043,0.168c0.116,0.512 0.183,1.042 0.183,1.589c0,3.952 -3.204,7.156 -7.156,7.156c-3.952,0 -7.156,-3.204 -7.156,-7.156c0,-3.952 3.204,-7.156 7.156,-7.156c1.072,0 2.085,0.242 2.998,0.665c0.325,0.151 0.639,0.321 0.936,0.517l0.002,-0.002l-0.352,-1.784l1.876,-0.538c-1.567,-1.033 -3.442,-1.639 -5.46,-1.639c-5.488,0 -9.937,4.449 -9.937,9.938c0,5.488 4.449,9.937 9.937,9.937C17.551,22 22,17.551 22,12.063c0,-0.759 -0.093,-1.496 -0.254,-2.206c-0.04,-0.176 -0.085,-0.35 -0.134,-0.523L24,9.343L24,9.343z"
android:fillColor="#939393"/>
android:fillColor="@color/loopDisconnected"/>
<path
android:pathData="M14.868,22.154c0.794,0 1.49,-0.418 1.973,-1.054l-0.001,-3.926c-0.482,-0.634 -1.177,-1.052 -1.969,-1.052l-5.612,-0.001c-0.793,0 -1.487,0.416 -1.97,1.05l-0.004,3.926c0.482,0.636 1.178,1.055 1.972,1.055"
android:fillColor="#939393"/>
android:fillColor="@color/loopDisconnected"/>
</vector>

View file

@ -5,8 +5,8 @@
android:viewportHeight="24">
<path
android:pathData="M24,9.343l-5.781,-3.968l-1.328,6.688l2.102,-1.757c0.014,0.056 0.03,0.111 0.043,0.168c0.116,0.512 0.183,1.042 0.183,1.589c0,3.952 -3.204,7.156 -7.156,7.156c-3.952,0 -7.156,-3.204 -7.156,-7.156c0,-3.952 3.204,-7.156 7.156,-7.156c1.072,0 2.085,0.242 2.998,0.665c0.325,0.151 0.639,0.321 0.936,0.517l0.002,-0.002l-0.352,-1.784l1.876,-0.538c-1.567,-1.033 -3.442,-1.639 -5.46,-1.639c-5.488,0 -9.937,4.449 -9.937,9.938c0,5.488 4.449,9.937 9.937,9.937C17.551,22 22,17.551 22,12.063c0,-0.759 -0.093,-1.496 -0.254,-2.206c-0.04,-0.176 -0.085,-0.35 -0.134,-0.523L24,9.343L24,9.343z"
android:fillColor="#00C03E"/>
android:fillColor="@color/loopClosed"/>
<path
android:pathData="M9.401,8.391l6.599,3.609l-6.599,3.609z"
android:fillColor="#00C03E"/>
android:fillColor="@color/loopClosed"/>
</vector>

View file

@ -4,7 +4,17 @@
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context="info.nightscout.androidaps.plugins.treatments.fragments.TreatmentsExtendedBolusesFragment">
tools:context="info.nightscout.androidaps.plugins.general.food.TreatmentsFoodFragment">
<info.nightscout.androidaps.utils.ui.SingleClickButton
android:id="@+id/refresh_from_nightscout"
style="?android:attr/buttonStyle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:drawableStart="@drawable/ic_refresh"
android:text="@string/refresheventsfromnightscout"
tools:visibility="visible" />
<LinearLayout
android:layout_width="match_parent"
@ -48,6 +58,7 @@
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="5dp"
android:text="@string/category" />
<Spinner
@ -65,6 +76,7 @@
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="5dp"
android:text="@string/subcategory" />
<Spinner

View file

@ -1,13 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.cardview.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:card_view="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center"
card_view:cardBackgroundColor="@color/cardColorBackground"
card_view:cardCornerRadius="6dp"
card_view:cardUseCompatPadding="true"
card_view:contentPadding="6dp">
card_view:cardBackgroundColor="?android:colorBackground">
<LinearLayout
android:layout_width="match_parent"
@ -26,21 +24,24 @@
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="Name"
android:textStyle="bold" />
android:textStyle="bold"
tools:ignore="HardcodedText" />
<TextView
android:id="@+id/portion"
android:layout_width="60dp"
android:layout_height="wrap_content"
android:gravity="end"
android:text="Portion" />
android:text="Portion"
tools:ignore="HardcodedText" />
<TextView
android:id="@+id/carbs"
android:layout_width="50dp"
android:layout_height="wrap_content"
android:gravity="end"
android:text="Carbs" />
android:text="Carbs"
tools:ignore="HardcodedText" />
</LinearLayout>
@ -56,21 +57,24 @@
android:layout_width="70dp"
android:layout_height="wrap_content"
android:gravity="end"
android:text="Fat" />
android:text="Fat"
tools:ignore="HardcodedText" />
<TextView
android:id="@+id/protein"
android:layout_width="70dp"
android:layout_height="wrap_content"
android:gravity="end"
android:text="Protein" />
android:text="Protein"
tools:ignore="HardcodedText" />
<TextView
android:id="@+id/energy"
android:layout_width="70dp"
android:layout_height="wrap_content"
android:gravity="end"
android:text="Energy" />
android:text="Energy"
tools:ignore="HardcodedText" />
<TextView
android:id="@+id/ns_sign"
@ -79,7 +83,8 @@
android:width="30dp"
android:text="NS"
android:textAlignment="viewEnd"
android:textColor="@color/colorSetTempButton" />
android:textColor="@color/colorSetTempButton"
tools:ignore="HardcodedText" />
<TextView
android:id="@+id/remove"
@ -93,6 +98,15 @@
</LinearLayout>
<View
android:layout_width="fill_parent"
android:layout_height="2dip"
android:layout_marginBottom="5dp"
android:layout_marginLeft="5dp"
android:layout_marginRight="5dp"
android:layout_marginTop="5dp"
android:background="@color/list_delimiter" />
</LinearLayout>
</androidx.cardview.widget.CardView>

View file

@ -75,6 +75,20 @@
android:text="@string/nav_import"
android:textColor="@color/colorTreatmentButton" />
<Button
android:id="@+id/export_csv"
style="?android:attr/buttonStyle"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="3dp"
android:layout_marginLeft="10dp"
android:layout_marginRight="10dp"
android:layout_marginTop="3dp"
android:layout_weight="0.5"
android:text="@string/ue_export_to_csv"
android:textColor="@color/colorTreatmentButton" />
<Button
android:id="@+id/nav_resetdb"
style="?android:attr/buttonStyle"

View file

@ -5,6 +5,15 @@
android:orientation="vertical"
tools:context=".plugins.treatments.fragments.TreatmentsUserEntryFragment">
<info.nightscout.androidaps.utils.ui.SingleClickButton
android:id="@+id/ue_export_to_xml"
style="?android:attr/buttonStyle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:drawableStart="@drawable/ic_header_export"
android:text="@string/ue_export_to_csv" />
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recyclerview"
android:layout_width="match_parent"

View file

@ -1,8 +1,21 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
<androidx.cardview.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:card_view="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center"
card_view:cardBackgroundColor="?android:colorBackground">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:baselineAligned="true"
android:orientation="horizontal">
<TextView
@ -23,48 +36,37 @@
android:textAppearance="?android:attr/textAppearanceSmall"
tools:ignore="HardcodedText,RtlSymmetry" />
</LinearLayout>
<TextView
android:id="@+id/values"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:paddingStart="20dp"
android:paddingEnd="10dp"
android:textStyle="bold"
android:visibility="gone"
android:text="Values with units" />
<TextView
android:id="@+id/s"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingStart="10dp"
android:paddingStart="20dp"
android:visibility="gone"
android:textAppearance="?android:attr/textAppearanceSmall"
tools:ignore="HardcodedText,RtlSymmetry" />
<TextView
android:id="@+id/d1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingStart="10dp"
android:text="0.0"
android:textAppearance="?android:attr/textAppearanceSmall"
tools:ignore="HardcodedText,RtlSymmetry" />
<TextView
android:id="@+id/d2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingStart="10dp"
android:text="0.0"
android:textAppearance="?android:attr/textAppearanceSmall"
tools:ignore="HardcodedText,RtlSymmetry" />
<TextView
android:id="@+id/i1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingStart="10dp"
android:text="0.0"
android:textAppearance="?android:attr/textAppearanceSmall"
tools:ignore="HardcodedText,RtlSymmetry" />
<TextView
android:id="@+id/i2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingStart="10dp"
android:text="0.0"
android:textAppearance="?android:attr/textAppearanceSmall"
tools:ignore="HardcodedText,RtlSymmetry" />
<View
android:layout_width="fill_parent"
android:layout_height="2dip"
android:layout_marginBottom="5dp"
android:layout_marginStart="5dp"
android:layout_marginEnd="5dp"
android:layout_marginTop="5dp"
android:background="@color/list_delimiter" />
</LinearLayout>
</androidx.cardview.widget.CardView>

View file

@ -1,7 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="prediction">#ff00ff</color>
<color name="basal">#00ffff</color>
<color name="iobPred">#00d2d2</color>
<color name="bolus">#1ea3e5</color>
<color name="ratio">#FFFFFF</color>
@ -22,7 +21,6 @@
<color name="ok_background">#323232</color>
<color name="defaultbackground">#424242</color>
<color name="defaulttext">#BBBBBB</color>
<color name="defaulttextcolor">#B3FFFFFF</color>
<color name="tempTargetBackground">#77dd77</color>

View file

@ -179,6 +179,7 @@
<string name="configbuilder_nightscoutversion_label">Nightscout version:</string>
<string name="missing_carbs">Missing %1$d g</string>
<string name="exported">Preferences exported</string>
<string name="ue_exported">User Entries exported</string>
<string name="export_to">Export settings to</string>
<string name="import_from">Import settings from</string>
<string name="setting_imported">Settings imported</string>
@ -316,7 +317,7 @@
<string name="openapsma_autosensdata_label">Autosens data</string>
<string name="openapsma_scriptdebugdata_label">Script debug</string>
<string name="openapsama_useautosens">Use Autosens feature</string>
<string name="refresheventsfromnightscout">Refresh events from NS</string>
<string name="refresheventsfromnightscout">Refresh from NS</string>
<string name="deletefuturetreatments">Delete treatments in the future</string>
<string name="actions_shortname">ACT</string>
<string name="configbuilder_shortname">CONF</string>
@ -932,7 +933,6 @@
<string name="format_carbs_ic">%1$.0fg IC: %2$.1f</string>
<string name="format_cob_ic">%1$.1fg IC: %2$.1f</string>
<string name="format_percent">%1$d%%</string>
<string name="boluswizard">Bolus wizard</string>
<string name="unit_minute_short">min</string>
<string name="profile_name">Profile name:</string>
<string name="selected_profile">Selected:</string>
@ -1126,4 +1126,6 @@
<string name="current_basal_value">Current basal value</string>
<string name="profile_carbs_ratio_value">Profile carbs ratio value</string>
</resources>

View file

@ -22,7 +22,6 @@ import info.nightscout.androidaps.plugins.constraints.objectives.objectives.Obje
import info.nightscout.androidaps.plugins.constraints.safety.SafetyPlugin
import info.nightscout.androidaps.plugins.general.maintenance.LoggerUtils
import info.nightscout.androidaps.plugins.general.nsclient.NSUpload
import info.nightscout.androidaps.plugins.general.nsclient.UploadQueue
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.GlucoseStatusProvider
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.IobCobCalculatorPlugin
import info.nightscout.androidaps.plugins.pump.combo.ComboPlugin
@ -69,7 +68,7 @@ class ConstraintsCheckerTest : TestBaseWithProfile() {
@Mock lateinit var sensitivityOref1Plugin: SensitivityOref1Plugin
@Mock lateinit var profiler: Profiler
@Mock lateinit var nsUpload: NSUpload
@Mock lateinit var uploadQueue: UploadQueue
@Mock lateinit var uploadQueue: UploadQueueInterface
@Mock lateinit var uel: UserEntryLogger
@Mock lateinit var loggerUtils: LoggerUtils
@Mock lateinit var databaseHelper: DatabaseHelperInterface

Some files were not shown because too many files have changed in this diff Show more