diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index e0e2a6b05b..cb897b727c 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -135,10 +135,6 @@ android:resource="@xml/filepaths" /> - - diff --git a/app/src/main/java/info/nightscout/androidaps/dependencyInjection/AppComponent.kt b/app/src/main/java/info/nightscout/androidaps/dependencyInjection/AppComponent.kt index ef728a2193..5e36be6be2 100644 --- a/app/src/main/java/info/nightscout/androidaps/dependencyInjection/AppComponent.kt +++ b/app/src/main/java/info/nightscout/androidaps/dependencyInjection/AppComponent.kt @@ -41,6 +41,7 @@ import javax.inject.Singleton DanaModule::class, DanaRModule::class, DanaRSModule::class, + WorkersModule::class, OHUploaderModule::class ] ) diff --git a/app/src/main/java/info/nightscout/androidaps/dependencyInjection/ServicesModule.kt b/app/src/main/java/info/nightscout/androidaps/dependencyInjection/ServicesModule.kt index 6ba01130ae..856ae3c106 100644 --- a/app/src/main/java/info/nightscout/androidaps/dependencyInjection/ServicesModule.kt +++ b/app/src/main/java/info/nightscout/androidaps/dependencyInjection/ServicesModule.kt @@ -12,7 +12,6 @@ import info.nightscout.androidaps.plugins.pump.insight.connection_service.Insigh import info.nightscout.androidaps.plugins.pump.medtronic.service.RileyLinkMedtronicService import info.nightscout.androidaps.plugins.pump.omnipod.rileylink.service.RileyLinkOmnipodService import info.nightscout.androidaps.services.AlarmSoundService -import info.nightscout.androidaps.services.DataService import info.nightscout.androidaps.services.LocationService @Module @@ -20,7 +19,6 @@ import info.nightscout.androidaps.services.LocationService abstract class ServicesModule { @ContributesAndroidInjector abstract fun contributesAlarmSoundService(): AlarmSoundService - @ContributesAndroidInjector abstract fun contributesDataService(): DataService @ContributesAndroidInjector abstract fun contributesDismissNotificationService(): DismissNotificationService @ContributesAndroidInjector abstract fun contributesDummyService(): DummyService @ContributesAndroidInjector abstract fun contributesLocationService(): LocationService diff --git a/app/src/main/java/info/nightscout/androidaps/dependencyInjection/WorkersModule.kt b/app/src/main/java/info/nightscout/androidaps/dependencyInjection/WorkersModule.kt new file mode 100644 index 0000000000..5f48be718c --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/dependencyInjection/WorkersModule.kt @@ -0,0 +1,25 @@ +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.smsCommunicator.SmsCommunicatorPlugin +import info.nightscout.androidaps.plugins.profile.ns.NSProfilePlugin +import info.nightscout.androidaps.plugins.source.* + +@Module +@Suppress("unused") +abstract class WorkersModule { + + @ContributesAndroidInjector abstract fun contributesXdripWorker(): XdripPlugin.XdripWorker + @ContributesAndroidInjector abstract fun contributesDexcomWorker(): DexcomPlugin.DexcomWorker + @ContributesAndroidInjector abstract fun contributesMM640gWorker(): MM640gPlugin.MM640gWorker + @ContributesAndroidInjector abstract fun contributesGlimpWorker(): GlimpPlugin.GlimpWorker + @ContributesAndroidInjector abstract fun contributesPoctechWorker(): PoctechPlugin.PoctechWorker + @ContributesAndroidInjector abstract fun contributesTomatoWorker(): TomatoPlugin.TomatoWorker + @ContributesAndroidInjector abstract fun contributesEversenseWorker(): EversensePlugin.EversenseWorker + @ContributesAndroidInjector abstract fun contributesNSClientSourceWorker(): NSClientSourcePlugin.NSClientSourceWorker + @ContributesAndroidInjector abstract fun contributesNSProfileWorker(): NSProfilePlugin.NSProfileWorker + @ContributesAndroidInjector abstract fun contributesSmsCommunicatorWorker(): SmsCommunicatorPlugin.SmsCommunicatorWorker + @ContributesAndroidInjector abstract fun contributesNSClientWorker(): NSClientWorker +} \ No newline at end of file diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/NSClientPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/NSClientPlugin.java index dfa2ec461a..ef0ad789f9 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/NSClientPlugin.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/NSClientPlugin.java @@ -4,6 +4,7 @@ import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.ServiceConnection; +import android.os.Bundle; import android.os.Handler; import android.os.HandlerThread; import android.os.IBinder; @@ -13,6 +14,9 @@ import androidx.preference.PreferenceFragmentCompat; import androidx.preference.SwitchPreference; import org.jetbrains.annotations.NotNull; +import org.json.JSONArray; +import org.json.JSONException; +import org.json.JSONObject; import java.util.ArrayList; import java.util.List; @@ -23,11 +27,15 @@ import javax.inject.Singleton; import dagger.android.HasAndroidInjector; import info.nightscout.androidaps.Config; import info.nightscout.androidaps.Constants; +import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.R; +import info.nightscout.androidaps.db.CareportalEvent; import info.nightscout.androidaps.events.EventAppExit; import info.nightscout.androidaps.events.EventChargingState; import info.nightscout.androidaps.events.EventNetworkChange; +import info.nightscout.androidaps.events.EventNsTreatment; import info.nightscout.androidaps.events.EventPreferenceChange; +import info.nightscout.androidaps.interfaces.ActivePluginProvider; import info.nightscout.androidaps.interfaces.PluginBase; import info.nightscout.androidaps.interfaces.PluginDescription; import info.nightscout.androidaps.interfaces.PluginType; @@ -36,13 +44,18 @@ import info.nightscout.androidaps.logging.LTag; 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; import info.nightscout.androidaps.plugins.general.nsclient.events.EventNSClientUpdateGUI; import info.nightscout.androidaps.plugins.general.nsclient.services.NSClientService; +import info.nightscout.androidaps.plugins.general.overview.events.EventNewNotification; +import info.nightscout.androidaps.plugins.general.overview.notifications.Notification; +import info.nightscout.androidaps.services.Intents; import info.nightscout.androidaps.utils.FabricPrivacy; import info.nightscout.androidaps.utils.HtmlHelper; +import info.nightscout.androidaps.utils.JsonHelper; import info.nightscout.androidaps.utils.ToastUtils; import info.nightscout.androidaps.utils.buildHelper.BuildHelper; import info.nightscout.androidaps.utils.resources.ResourceHelper; @@ -62,6 +75,8 @@ public class NSClientPlugin extends PluginBase { private final SP sp; private final Config config; private final BuildHelper buildHelper; + private final ActivePluginProvider activePlugin; + private final NSUpload nsUpload; public Handler handler; @@ -88,7 +103,9 @@ public class NSClientPlugin extends PluginBase { SP sp, NsClientReceiverDelegate nsClientReceiverDelegate, Config config, - BuildHelper buildHelper + BuildHelper buildHelper, + ActivePluginProvider activePlugin, + NSUpload nsUpload ) { super(new PluginDescription() .mainType(PluginType.GENERAL) @@ -110,6 +127,8 @@ public class NSClientPlugin extends PluginBase { this.nsClientReceiverDelegate = nsClientReceiverDelegate; this.config = config; this.buildHelper = buildHelper; + this.activePlugin = activePlugin; + this.nsUpload = nsUpload; if (config.getNSCLIENT()) { getPluginDescription().alwaysEnabled(true).visibleByDefault(true); @@ -310,4 +329,143 @@ 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) { + // new DB model + EventNsTreatment evtTreatment = new EventNsTreatment(EventNsTreatment.Companion.getREMOVE(), json); + rxBus.send(evtTreatment); + // old DB model + String _id = JsonHelper.safeGetString(json, "_id"); + MainApp.getDbHelper().deleteTempTargetById(_id); + MainApp.getDbHelper().deleteTempBasalById(_id); + MainApp.getDbHelper().deleteExtendedBolusById(_id); + MainApp.getDbHelper().deleteCareportalEventById(_id); + MainApp.getDbHelper().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(CareportalEvent.TEMPORARYTARGET)) { + MainApp.getDbHelper().createTemptargetFromJsonIfNotExists(json); + } else if (eventType.equals(CareportalEvent.TEMPBASAL)) { + MainApp.getDbHelper().createTempBasalFromJsonIfNotExists(json); + } else if (eventType.equals(CareportalEvent.COMBOBOLUS)) { + MainApp.getDbHelper().createExtendedBolusFromJsonIfNotExists(json); + } else if (eventType.equals(CareportalEvent.PROFILESWITCH)) { + MainApp.getDbHelper().createProfileSwitchFromJsonIfNotExists(activePlugin, nsUpload, json); + } else if (eventType.equals(CareportalEvent.SITECHANGE) || + eventType.equals(CareportalEvent.INSULINCHANGE) || + eventType.equals(CareportalEvent.SENSORCHANGE) || + eventType.equals(CareportalEvent.BGCHECK) || + eventType.equals(CareportalEvent.NOTE) || + eventType.equals(CareportalEvent.NONE) || + eventType.equals(CareportalEvent.ANNOUNCEMENT) || + eventType.equals(CareportalEvent.QUESTION) || + eventType.equals(CareportalEvent.EXERCISE) || + eventType.equals(CareportalEvent.OPENAPSOFFLINE) || + eventType.equals(CareportalEvent.PUMPBATTERYCHANGE)) { + MainApp.getDbHelper().createCareportalEventFromJsonIfNotExists(json); + } + + if (eventType.equals(CareportalEvent.ANNOUNCEMENT)) { + 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.NSANNOUNCEMENT, notes, Notification.ANNOUNCEMENT, 60); + rxBus.send(new EventNewNotification(announcement)); + } + } + } + } + + private void storeMbg(JSONObject mbgJson) { + NSMbg nsMbg = new NSMbg(mbgJson); + CareportalEvent careportalEvent = new CareportalEvent(nsMbg); + MainApp.getDbHelper().createOrUpdate(careportalEvent); + aapsLogger.debug(LTag.DATASERVICE, "Adding/Updating new MBG: " + careportalEvent.toString()); + } } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/NSClientWorker.java b/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/NSClientWorker.java new file mode 100644 index 0000000000..a6af4e431f --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/NSClientWorker.java @@ -0,0 +1,40 @@ +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 org.jetbrains.annotations.NotNull; + +import javax.inject.Inject; + +import dagger.android.HasAndroidInjector; +import info.nightscout.androidaps.receivers.BundleStore; + +// 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; + + @NotNull + @Override + public Result doWork() { + Bundle bundle = bundleStore.pickup(getInputData().getLong("storeKey", -1)); + if (bundle == null) Result.failure(); + String action = getInputData().getString("action"); + nsClientPlugin.handleNewDataFromNSClient(action, bundle); + return Result.success(); + } +} + diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/smsCommunicator/SmsCommunicatorPlugin.kt b/app/src/main/java/info/nightscout/androidaps/plugins/general/smsCommunicator/SmsCommunicatorPlugin.kt index 0bf3b61be1..b83b56ea8e 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/general/smsCommunicator/SmsCommunicatorPlugin.kt +++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/smsCommunicator/SmsCommunicatorPlugin.kt @@ -1,12 +1,14 @@ package info.nightscout.androidaps.plugins.general.smsCommunicator -import android.content.Intent +import android.content.Context import android.telephony.SmsManager import android.telephony.SmsMessage import android.text.TextUtils import androidx.preference.EditTextPreference import androidx.preference.Preference import androidx.preference.PreferenceFragmentCompat +import androidx.work.Worker +import androidx.work.WorkerParameters import dagger.android.HasAndroidInjector import info.nightscout.androidaps.Config import info.nightscout.androidaps.Constants @@ -32,6 +34,7 @@ import info.nightscout.androidaps.plugins.iob.iobCobCalculator.GlucoseStatus import info.nightscout.androidaps.plugins.iob.iobCobCalculator.IobCobCalculatorPlugin import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin import info.nightscout.androidaps.queue.Callback +import info.nightscout.androidaps.receivers.BundleStore import info.nightscout.androidaps.utils.* import info.nightscout.androidaps.utils.extensions.plusAssign import info.nightscout.androidaps.utils.resources.ResourceHelper @@ -152,6 +155,32 @@ class SmsCommunicatorPlugin @Inject constructor( } } + // cannot be inner class because of needed injection + class SmsCommunicatorWorker( + context: Context, + params: WorkerParameters + ) : Worker(context, params) { + + @Inject lateinit var smsCommunicatorPlugin: SmsCommunicatorPlugin + @Inject lateinit var bundleStore: BundleStore + + init { + (context.applicationContext as HasAndroidInjector).androidInjector().inject(this) + } + + override fun doWork(): Result { + val bundle = bundleStore.pickup(inputData.getLong("storeKey", -1)) + ?: return Result.failure() + val format = bundle.getString("format") ?: return Result.failure() + val pdus = bundle["pdus"] as Array<*> + for (pdu in pdus) { + val message = SmsMessage.createFromPdu(pdu as ByteArray, format) + smsCommunicatorPlugin.processSms(Sms(message)) + } + return Result.success() + } + } + private fun processSettings(ev: EventPreferenceChange?) { if (ev == null || ev.isChanged(resourceHelper, R.string.key_smscommunicator_allowednumbers)) { val settings = sp.getString(R.string.key_smscommunicator_allowednumbers, "") @@ -180,16 +209,6 @@ class SmsCommunicatorPlugin @Inject constructor( return false } - fun handleNewData(intent: Intent) { - val bundle = intent.extras ?: return - val format = bundle.getString("format") ?: return - val pdus = bundle["pdus"] as Array<*> - for (pdu in pdus) { - val message = SmsMessage.createFromPdu(pdu as ByteArray, format) - processSms(Sms(message)) - } - } - fun processSms(receivedSms: Sms) { if (!isEnabled(PluginType.GENERAL)) { aapsLogger.debug(LTag.SMS, "Ignoring SMS. Plugin disabled.") diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/profile/ns/NSProfilePlugin.kt b/app/src/main/java/info/nightscout/androidaps/plugins/profile/ns/NSProfilePlugin.kt index eb2b3ffe89..a47e53afe1 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/profile/ns/NSProfilePlugin.kt +++ b/app/src/main/java/info/nightscout/androidaps/plugins/profile/ns/NSProfilePlugin.kt @@ -1,15 +1,17 @@ package info.nightscout.androidaps.plugins.profile.ns -import android.content.Intent +import android.content.Context +import androidx.work.Worker +import androidx.work.WorkerParameters import dagger.android.HasAndroidInjector import info.nightscout.androidaps.Config import info.nightscout.androidaps.R -import info.nightscout.androidaps.interfaces.ProfileStore import info.nightscout.androidaps.events.EventProfileStoreChanged import info.nightscout.androidaps.interfaces.PluginBase import info.nightscout.androidaps.interfaces.PluginDescription import info.nightscout.androidaps.interfaces.PluginType import info.nightscout.androidaps.interfaces.ProfileInterface +import info.nightscout.androidaps.interfaces.ProfileStore import info.nightscout.androidaps.logging.AAPSLogger import info.nightscout.androidaps.logging.LTag import info.nightscout.androidaps.plugins.bus.RxBusWrapper @@ -49,21 +51,6 @@ class NSProfilePlugin @Inject constructor( loadNSProfile() } - fun handleNewData(intent: Intent) { - val bundles = intent.extras ?: return - - @Suppress("SpellCheckingInspection") - val activeProfile = bundles.getString("activeprofile") - val profileString = bundles.getString("profile") - profile = ProfileStore(injector, JSONObject(profileString)) - storeNSProfile() - if (isEnabled()) { - rxBus.send(EventProfileStoreChanged()) - rxBus.send(EventNSProfileUpdateGUI()) - } - aapsLogger.debug(LTag.PROFILE, "Received profileStore: $activeProfile $profile") - } - private fun storeNSProfile() { sp.putString("profile", profile!!.data.toString()) aapsLogger.debug(LTag.PROFILE, "Storing profile") @@ -90,4 +77,33 @@ class NSProfilePlugin @Inject constructor( return profile!!.getDefaultProfileName()!! } + // cannot be inner class because of needed injection + class NSProfileWorker( + context: Context, + params: WorkerParameters + ) : Worker(context, params) { + + @Inject lateinit var injector: HasAndroidInjector + @Inject lateinit var nsProfilePlugin: NSProfilePlugin + @Inject lateinit var aapsLogger: AAPSLogger + @Inject lateinit var rxBus: RxBusWrapper + + init { + (context.applicationContext as HasAndroidInjector).androidInjector().inject(this) + } + + override fun doWork(): Result { + inputData.getString("profile")?.let { profileString -> + nsProfilePlugin.profile = ProfileStore(injector, JSONObject(profileString)) + nsProfilePlugin.storeNSProfile() + if (nsProfilePlugin.isEnabled()) { + rxBus.send(EventProfileStoreChanged()) + rxBus.send(EventNSProfileUpdateGUI()) + } + aapsLogger.debug(LTag.PROFILE, "Received profileStore: ${nsProfilePlugin.profile}") + return Result.success() + } + return Result.failure() + } + } } \ No newline at end of file diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/source/DexcomPlugin.kt b/app/src/main/java/info/nightscout/androidaps/plugins/source/DexcomPlugin.kt index 29497ff29b..a8b3fcce65 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/source/DexcomPlugin.kt +++ b/app/src/main/java/info/nightscout/androidaps/plugins/source/DexcomPlugin.kt @@ -1,8 +1,11 @@ package info.nightscout.androidaps.plugins.source +import android.content.Context import android.content.Intent import android.content.pm.PackageManager import androidx.core.content.ContextCompat +import androidx.work.Worker +import androidx.work.WorkerParameters import dagger.android.HasAndroidInjector import info.nightscout.androidaps.Config import info.nightscout.androidaps.Constants @@ -18,6 +21,7 @@ import info.nightscout.androidaps.interfaces.PluginDescription import info.nightscout.androidaps.interfaces.PluginType import info.nightscout.androidaps.logging.AAPSLogger import info.nightscout.androidaps.plugins.general.nsclient.NSUpload +import info.nightscout.androidaps.receivers.BundleStore import info.nightscout.androidaps.utils.DateUtil import info.nightscout.androidaps.utils.T import info.nightscout.androidaps.utils.resources.ResourceHelper @@ -29,11 +33,9 @@ import javax.inject.Singleton @Singleton class DexcomPlugin @Inject constructor( injector: HasAndroidInjector, - private val sp: SP, private val mainApp: MainApp, resourceHelper: ResourceHelper, aapsLogger: AAPSLogger, - private val nsUpload: NSUpload, config: Config ) : PluginBase(PluginDescription() .mainType(PluginType.BGSOURCE) @@ -73,80 +75,103 @@ class DexcomPlugin @Inject constructor( return null } - override fun handleNewData(intent: Intent) { - if (!isEnabled(PluginType.BGSOURCE)) return - try { - val sensorType = intent.getStringExtra("sensorType") ?: "" - val glucoseValues = intent.getBundleExtra("glucoseValues") - for (i in 0 until glucoseValues.size()) { - glucoseValues.getBundle(i.toString())?.let { glucoseValue -> - val bgReading = BgReading() - bgReading.value = glucoseValue.getInt("glucoseValue").toDouble() - bgReading.direction = glucoseValue.getString("trendArrow") - bgReading.date = glucoseValue.getLong("timestamp") * 1000 - bgReading.raw = 0.0 - if (MainApp.getDbHelper().createIfNotExists(bgReading, "Dexcom$sensorType")) { - if (sp.getBoolean(R.string.key_dexcomg5_nsupload, false)) { - nsUpload.uploadBg(bgReading, "AndroidAPS-Dexcom$sensorType") - } - if (sp.getBoolean(R.string.key_dexcomg5_xdripupload, false)) { - nsUpload.sendToXdrip(bgReading) + // cannot be inner class because of needed injection + class DexcomWorker( + context: Context, + params: WorkerParameters + ) : Worker(context, params) { + + @Inject lateinit var aapsLogger: AAPSLogger + @Inject lateinit var injector: HasAndroidInjector + @Inject lateinit var dexcomPlugin: DexcomPlugin + @Inject lateinit var nsUpload: NSUpload + @Inject lateinit var sp: SP + @Inject lateinit var bundleStore: BundleStore + + init { + (context.applicationContext as HasAndroidInjector).androidInjector().inject(this) + } + + override fun doWork(): Result { + if (!dexcomPlugin.isEnabled(PluginType.BGSOURCE)) return Result.failure() + val bundle = bundleStore.pickup(inputData.getLong("storeKey", -1)) + ?: return Result.failure() + try { + val sensorType = bundle.getString("sensorType") ?: "" + val glucoseValues = bundle.getBundle("glucoseValues") ?: return Result.failure() + for (i in 0 until glucoseValues.size()) { + glucoseValues.getBundle(i.toString())?.let { glucoseValue -> + val bgReading = BgReading() + bgReading.value = glucoseValue.getInt("glucoseValue").toDouble() + bgReading.direction = glucoseValue.getString("trendArrow") + bgReading.date = glucoseValue.getLong("timestamp") * 1000 + bgReading.raw = 0.0 + if (MainApp.getDbHelper().createIfNotExists(bgReading, "Dexcom$sensorType")) { + if (sp.getBoolean(R.string.key_dexcomg5_nsupload, false)) { + nsUpload.uploadBg(bgReading, "AndroidAPS-Dexcom$sensorType") + } + if (sp.getBoolean(R.string.key_dexcomg5_xdripupload, false)) { + nsUpload.sendToXdrip(bgReading) + } } } } - } - val meters = intent.getBundleExtra("meters") - for (i in 0 until meters.size()) { - val meter = meters.getBundle(i.toString()) - meter?.let { - val timestamp = it.getLong("timestamp") * 1000 - val now = DateUtil.now() - if (timestamp > now - T.months(1).msecs() && timestamp < now) - if (MainApp.getDbHelper().getCareportalEventFromTimestamp(timestamp) == null) { - val jsonObject = JSONObject() - jsonObject.put("enteredBy", "AndroidAPS-Dexcom$sensorType") - jsonObject.put("created_at", DateUtil.toISOString(timestamp)) - jsonObject.put("eventType", CareportalEvent.BGCHECK) - jsonObject.put("glucoseType", "Finger") - jsonObject.put("glucose", meter.getInt("meterValue")) - jsonObject.put("units", Constants.MGDL) + bundle.getBundle("meters")?.let { meters -> + for (i in 0 until meters.size()) { + val meter = meters.getBundle(i.toString()) + meter?.let { + val timestamp = it.getLong("timestamp") * 1000 + val now = DateUtil.now() + if (timestamp > now - T.months(1).msecs() && timestamp < now) + if (MainApp.getDbHelper().getCareportalEventFromTimestamp(timestamp) == null) { + val jsonObject = JSONObject() + jsonObject.put("enteredBy", "AndroidAPS-Dexcom$sensorType") + jsonObject.put("created_at", DateUtil.toISOString(timestamp)) + jsonObject.put("eventType", CareportalEvent.BGCHECK) + jsonObject.put("glucoseType", "Finger") + jsonObject.put("glucose", meter.getInt("meterValue")) + jsonObject.put("units", Constants.MGDL) - val careportalEvent = CareportalEvent(injector) - careportalEvent.date = timestamp - careportalEvent.source = Source.USER - careportalEvent.eventType = CareportalEvent.BGCHECK - careportalEvent.json = jsonObject.toString() - MainApp.getDbHelper().createOrUpdate(careportalEvent) - nsUpload.uploadCareportalEntryToNS(jsonObject) + val careportalEvent = CareportalEvent(injector) + careportalEvent.date = timestamp + careportalEvent.source = Source.USER + careportalEvent.eventType = CareportalEvent.BGCHECK + careportalEvent.json = jsonObject.toString() + MainApp.getDbHelper().createOrUpdate(careportalEvent) + nsUpload.uploadCareportalEntryToNS(jsonObject) + } } + } } - } - if (sp.getBoolean(R.string.key_dexcom_lognssensorchange, false) && intent.hasExtra("sensorInsertionTime")) { - intent.extras?.let { - val sensorInsertionTime = it.getLong("sensorInsertionTime") * 1000 - val now = DateUtil.now() - if (sensorInsertionTime > now - T.months(1).msecs() && sensorInsertionTime < now) - if (MainApp.getDbHelper().getCareportalEventFromTimestamp(sensorInsertionTime) == null) { - val jsonObject = JSONObject() - jsonObject.put("enteredBy", "AndroidAPS-Dexcom$sensorType") - jsonObject.put("created_at", DateUtil.toISOString(sensorInsertionTime)) - jsonObject.put("eventType", CareportalEvent.SENSORCHANGE) - val careportalEvent = CareportalEvent(injector) - careportalEvent.date = sensorInsertionTime - careportalEvent.source = Source.USER - careportalEvent.eventType = CareportalEvent.SENSORCHANGE - careportalEvent.json = jsonObject.toString() - MainApp.getDbHelper().createOrUpdate(careportalEvent) - nsUpload.uploadCareportalEntryToNS(jsonObject) - } + if (sp.getBoolean(R.string.key_dexcom_lognssensorchange, false) && bundle.containsKey("sensorInsertionTime")) { + bundle.let { + val sensorInsertionTime = it.getLong("sensorInsertionTime") * 1000 + val now = DateUtil.now() + if (sensorInsertionTime > now - T.months(1).msecs() && sensorInsertionTime < now) + if (MainApp.getDbHelper().getCareportalEventFromTimestamp(sensorInsertionTime) == null) { + val jsonObject = JSONObject() + jsonObject.put("enteredBy", "AndroidAPS-Dexcom$sensorType") + jsonObject.put("created_at", DateUtil.toISOString(sensorInsertionTime)) + jsonObject.put("eventType", CareportalEvent.SENSORCHANGE) + val careportalEvent = CareportalEvent(injector) + careportalEvent.date = sensorInsertionTime + careportalEvent.source = Source.USER + careportalEvent.eventType = CareportalEvent.SENSORCHANGE + careportalEvent.json = jsonObject.toString() + MainApp.getDbHelper().createOrUpdate(careportalEvent) + nsUpload.uploadCareportalEntryToNS(jsonObject) + } + } } + } catch (e: Exception) { + aapsLogger.error("Error while processing intent from Dexcom App", e) } - } catch (e: Exception) { - aapsLogger.error("Error while processing intent from Dexcom App", e) + return Result.success() } } companion object { + private val PACKAGE_NAMES = arrayOf("com.dexcom.cgm.region1.mgdl", "com.dexcom.cgm.region1.mmol", "com.dexcom.cgm.region2.mgdl", "com.dexcom.cgm.region2.mmol", "com.dexcom.g6.region1.mmol", "com.dexcom.g6.region2.mgdl", diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/source/EversensePlugin.kt b/app/src/main/java/info/nightscout/androidaps/plugins/source/EversensePlugin.kt index d447602d37..8106a66b48 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/source/EversensePlugin.kt +++ b/app/src/main/java/info/nightscout/androidaps/plugins/source/EversensePlugin.kt @@ -1,6 +1,8 @@ package info.nightscout.androidaps.plugins.source -import android.content.Intent +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.MainApp @@ -14,6 +16,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.utils.DateUtil import info.nightscout.androidaps.utils.resources.ResourceHelper import info.nightscout.androidaps.utils.sharedPreferences.SP @@ -26,11 +29,8 @@ import javax.inject.Singleton @Singleton class EversensePlugin @Inject constructor( injector: HasAndroidInjector, - private val sp: SP, resourceHelper: ResourceHelper, - aapsLogger: AAPSLogger, - private val dateUtil: DateUtil, - private val nsUpload: NSUpload + aapsLogger: AAPSLogger ) : PluginBase(PluginDescription() .mainType(PluginType.BGSOURCE) .fragmentClass(BGSourceFragment::class.java.name) @@ -42,85 +42,98 @@ class EversensePlugin @Inject constructor( aapsLogger, resourceHelper, injector ), BgSourceInterface { - private var sensorBatteryLevel = -1 + override var sensorBatteryLevel = -1 - override fun advancedFilteringSupported(): Boolean { - return false - } + // cannot be inner class because of needed injection + class EversenseWorker( + context: Context, + params: WorkerParameters + ) : Worker(context, params) { - override fun handleNewData(intent: Intent) { - if (!isEnabled(PluginType.BGSOURCE)) return - val bundle = intent.extras ?: return - if (bundle.containsKey("currentCalibrationPhase")) aapsLogger.debug(LTag.BGSOURCE, "currentCalibrationPhase: " + bundle.getString("currentCalibrationPhase")) - if (bundle.containsKey("placementModeInProgress")) aapsLogger.debug(LTag.BGSOURCE, "placementModeInProgress: " + bundle.getBoolean("placementModeInProgress")) - if (bundle.containsKey("glucoseLevel")) aapsLogger.debug(LTag.BGSOURCE, "glucoseLevel: " + bundle.getInt("glucoseLevel")) - if (bundle.containsKey("glucoseTrendDirection")) aapsLogger.debug(LTag.BGSOURCE, "glucoseTrendDirection: " + bundle.getString("glucoseTrendDirection")) - if (bundle.containsKey("glucoseTimestamp")) aapsLogger.debug(LTag.BGSOURCE, "glucoseTimestamp: " + dateUtil.dateAndTimeString(bundle.getLong("glucoseTimestamp"))) - if (bundle.containsKey("batteryLevel")) { - aapsLogger.debug(LTag.BGSOURCE, "batteryLevel: " + bundle.getString("batteryLevel")) - //sensorBatteryLevel = bundle.getString("batteryLevel").toInt() // TODO: Philoul: Line to check I don't have eversens so I don't know what kind of information is sent... + @Inject lateinit var eversensePlugin: EversensePlugin + @Inject lateinit var aapsLogger: AAPSLogger + @Inject lateinit var sp: SP + @Inject lateinit var nsUpload: NSUpload + @Inject lateinit var dateUtil: DateUtil + @Inject lateinit var bundleStore: BundleStore + + init { + (context.applicationContext as HasAndroidInjector).androidInjector().inject(this) } - if (bundle.containsKey("signalStrength")) aapsLogger.debug(LTag.BGSOURCE, "signalStrength: " + bundle.getString("signalStrength")) - if (bundle.containsKey("transmitterVersionNumber")) aapsLogger.debug(LTag.BGSOURCE, "transmitterVersionNumber: " + bundle.getString("transmitterVersionNumber")) - if (bundle.containsKey("isXLVersion")) aapsLogger.debug(LTag.BGSOURCE, "isXLVersion: " + bundle.getBoolean("isXLVersion")) - if (bundle.containsKey("transmitterModelNumber")) aapsLogger.debug(LTag.BGSOURCE, "transmitterModelNumber: " + bundle.getString("transmitterModelNumber")) - if (bundle.containsKey("transmitterSerialNumber")) aapsLogger.debug(LTag.BGSOURCE, "transmitterSerialNumber: " + bundle.getString("transmitterSerialNumber")) - if (bundle.containsKey("transmitterAddress")) aapsLogger.debug(LTag.BGSOURCE, "transmitterAddress: " + bundle.getString("transmitterAddress")) - if (bundle.containsKey("sensorInsertionTimestamp")) aapsLogger.debug(LTag.BGSOURCE, "sensorInsertionTimestamp: " + dateUtil.dateAndTimeString(bundle.getLong("sensorInsertionTimestamp"))) - if (bundle.containsKey("transmitterVersionNumber")) aapsLogger.debug(LTag.BGSOURCE, "transmitterVersionNumber: " + bundle.getString("transmitterVersionNumber")) - if (bundle.containsKey("transmitterConnectionState")) aapsLogger.debug(LTag.BGSOURCE, "transmitterConnectionState: " + bundle.getString("transmitterConnectionState")) - if (bundle.containsKey("glucoseLevels")) { - val glucoseLevels = bundle.getIntArray("glucoseLevels") - val glucoseRecordNumbers = bundle.getIntArray("glucoseRecordNumbers") - val glucoseTimestamps = bundle.getLongArray("glucoseTimestamps") - if (glucoseLevels != null && glucoseRecordNumbers != null && glucoseTimestamps != null) { - aapsLogger.debug(LTag.BGSOURCE, "glucoseLevels" + Arrays.toString(glucoseLevels)) - aapsLogger.debug(LTag.BGSOURCE, "glucoseRecordNumbers" + Arrays.toString(glucoseRecordNumbers)) - aapsLogger.debug(LTag.BGSOURCE, "glucoseTimestamps" + Arrays.toString(glucoseTimestamps)) - for (i in glucoseLevels.indices) { - val bgReading = BgReading() - bgReading.value = glucoseLevels[i].toDouble() - bgReading.date = glucoseTimestamps[i] - bgReading.raw = 0.0 - val isNew = MainApp.getDbHelper().createIfNotExists(bgReading, "Eversense") - if (isNew && sp.getBoolean(R.string.key_dexcomg5_nsupload, false)) { - nsUpload.uploadBg(bgReading, "AndroidAPS-Eversense") - } - if (isNew && sp.getBoolean(R.string.key_dexcomg5_xdripupload, false)) { - nsUpload.sendToXdrip(bgReading) - } - } + + override fun doWork(): Result { + if (!eversensePlugin.isEnabled(PluginType.BGSOURCE)) return Result.failure() + val bundle = bundleStore.pickup(inputData.getLong("storeKey", -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")) + if (bundle.containsKey("glucoseLevel")) aapsLogger.debug(LTag.BGSOURCE, "glucoseLevel: " + bundle.getInt("glucoseLevel")) + if (bundle.containsKey("glucoseTrendDirection")) aapsLogger.debug(LTag.BGSOURCE, "glucoseTrendDirection: " + bundle.getString("glucoseTrendDirection")) + if (bundle.containsKey("glucoseTimestamp")) aapsLogger.debug(LTag.BGSOURCE, "glucoseTimestamp: " + dateUtil.dateAndTimeString(bundle.getLong("glucoseTimestamp"))) + if (bundle.containsKey("batteryLevel")) { + aapsLogger.debug(LTag.BGSOURCE, "batteryLevel: " + bundle.getString("batteryLevel")) + //sensorBatteryLevel = bundle.getString("batteryLevel").toInt() + // TODO: Philoul: Line to check I don't have eversense so I don't know what kind of information is sent... } - } - if (bundle.containsKey("calibrationGlucoseLevels")) { - val calibrationGlucoseLevels = bundle.getIntArray("calibrationGlucoseLevels") - val calibrationTimestamps = bundle.getLongArray("calibrationTimestamps") - val calibrationRecordNumbers = bundle.getLongArray("calibrationRecordNumbers") - if (calibrationGlucoseLevels != null && calibrationTimestamps != null && calibrationRecordNumbers != null) { - aapsLogger.debug(LTag.BGSOURCE, "calibrationGlucoseLevels" + Arrays.toString(calibrationGlucoseLevels)) - aapsLogger.debug(LTag.BGSOURCE, "calibrationTimestamps" + Arrays.toString(calibrationTimestamps)) - aapsLogger.debug(LTag.BGSOURCE, "calibrationRecordNumbers" + Arrays.toString(calibrationRecordNumbers)) - for (i in calibrationGlucoseLevels.indices) { - try { - if (MainApp.getDbHelper().getCareportalEventFromTimestamp(calibrationTimestamps[i]) == null) { - val data = JSONObject() - data.put("enteredBy", "AndroidAPS-Eversense") - data.put("created_at", DateUtil.toISOString(calibrationTimestamps[i])) - data.put("eventType", CareportalEvent.BGCHECK) - data.put("glucoseType", "Finger") - data.put("glucose", calibrationGlucoseLevels[i]) - data.put("units", Constants.MGDL) - nsUpload.uploadCareportalEntryToNS(data) + if (bundle.containsKey("signalStrength")) aapsLogger.debug(LTag.BGSOURCE, "signalStrength: " + bundle.getString("signalStrength")) + if (bundle.containsKey("transmitterVersionNumber")) aapsLogger.debug(LTag.BGSOURCE, "transmitterVersionNumber: " + bundle.getString("transmitterVersionNumber")) + if (bundle.containsKey("isXLVersion")) aapsLogger.debug(LTag.BGSOURCE, "isXLVersion: " + bundle.getBoolean("isXLVersion")) + if (bundle.containsKey("transmitterModelNumber")) aapsLogger.debug(LTag.BGSOURCE, "transmitterModelNumber: " + bundle.getString("transmitterModelNumber")) + if (bundle.containsKey("transmitterSerialNumber")) aapsLogger.debug(LTag.BGSOURCE, "transmitterSerialNumber: " + bundle.getString("transmitterSerialNumber")) + if (bundle.containsKey("transmitterAddress")) aapsLogger.debug(LTag.BGSOURCE, "transmitterAddress: " + bundle.getString("transmitterAddress")) + if (bundle.containsKey("sensorInsertionTimestamp")) aapsLogger.debug(LTag.BGSOURCE, "sensorInsertionTimestamp: " + dateUtil.dateAndTimeString(bundle.getLong("sensorInsertionTimestamp"))) + if (bundle.containsKey("transmitterVersionNumber")) aapsLogger.debug(LTag.BGSOURCE, "transmitterVersionNumber: " + bundle.getString("transmitterVersionNumber")) + if (bundle.containsKey("transmitterConnectionState")) aapsLogger.debug(LTag.BGSOURCE, "transmitterConnectionState: " + bundle.getString("transmitterConnectionState")) + if (bundle.containsKey("glucoseLevels")) { + val glucoseLevels = bundle.getIntArray("glucoseLevels") + val glucoseRecordNumbers = bundle.getIntArray("glucoseRecordNumbers") + val glucoseTimestamps = bundle.getLongArray("glucoseTimestamps") + if (glucoseLevels != null && glucoseRecordNumbers != null && glucoseTimestamps != null) { + aapsLogger.debug(LTag.BGSOURCE, "glucoseLevels" + Arrays.toString(glucoseLevels)) + aapsLogger.debug(LTag.BGSOURCE, "glucoseRecordNumbers" + Arrays.toString(glucoseRecordNumbers)) + aapsLogger.debug(LTag.BGSOURCE, "glucoseTimestamps" + Arrays.toString(glucoseTimestamps)) + for (i in glucoseLevels.indices) { + val bgReading = BgReading() + bgReading.value = glucoseLevels[i].toDouble() + bgReading.date = glucoseTimestamps[i] + bgReading.raw = 0.0 + val isNew = MainApp.getDbHelper().createIfNotExists(bgReading, "Eversense") + if (isNew && sp.getBoolean(R.string.key_dexcomg5_nsupload, false)) { + nsUpload.uploadBg(bgReading, "AndroidAPS-Eversense") + } + if (isNew && sp.getBoolean(R.string.key_dexcomg5_xdripupload, false)) { + nsUpload.sendToXdrip(bgReading) } - } catch (e: JSONException) { - aapsLogger.error("Unhandled exception", e) } } } + if (bundle.containsKey("calibrationGlucoseLevels")) { + val calibrationGlucoseLevels = bundle.getIntArray("calibrationGlucoseLevels") + val calibrationTimestamps = bundle.getLongArray("calibrationTimestamps") + val calibrationRecordNumbers = bundle.getLongArray("calibrationRecordNumbers") + if (calibrationGlucoseLevels != null && calibrationTimestamps != null && calibrationRecordNumbers != null) { + aapsLogger.debug(LTag.BGSOURCE, "calibrationGlucoseLevels" + Arrays.toString(calibrationGlucoseLevels)) + aapsLogger.debug(LTag.BGSOURCE, "calibrationTimestamps" + Arrays.toString(calibrationTimestamps)) + aapsLogger.debug(LTag.BGSOURCE, "calibrationRecordNumbers" + Arrays.toString(calibrationRecordNumbers)) + for (i in calibrationGlucoseLevels.indices) { + try { + if (MainApp.getDbHelper().getCareportalEventFromTimestamp(calibrationTimestamps[i]) == null) { + val data = JSONObject() + data.put("enteredBy", "AndroidAPS-Eversense") + data.put("created_at", DateUtil.toISOString(calibrationTimestamps[i])) + data.put("eventType", CareportalEvent.BGCHECK) + data.put("glucoseType", "Finger") + data.put("glucose", calibrationGlucoseLevels[i]) + data.put("units", Constants.MGDL) + nsUpload.uploadCareportalEntryToNS(data) + } + } catch (e: JSONException) { + aapsLogger.error("Unhandled exception", e) + } + } + } + } + return Result.success() } } - - override fun getSensorBatteryLevel(): Int { - return sensorBatteryLevel - } } \ No newline at end of file diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/source/GlimpPlugin.kt b/app/src/main/java/info/nightscout/androidaps/plugins/source/GlimpPlugin.kt index e14503bfbb..42ff746173 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/source/GlimpPlugin.kt +++ b/app/src/main/java/info/nightscout/androidaps/plugins/source/GlimpPlugin.kt @@ -1,6 +1,8 @@ package info.nightscout.androidaps.plugins.source -import android.content.Intent +import android.content.Context +import androidx.work.Worker +import androidx.work.WorkerParameters import dagger.android.HasAndroidInjector import info.nightscout.androidaps.MainApp import info.nightscout.androidaps.R @@ -10,7 +12,6 @@ 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.BundleLogger import info.nightscout.androidaps.logging.LTag import info.nightscout.androidaps.utils.resources.ResourceHelper import javax.inject.Inject @@ -31,19 +32,29 @@ class GlimpPlugin @Inject constructor( aapsLogger, resourceHelper, injector ), BgSourceInterface { - override fun advancedFilteringSupported(): Boolean { - return false - } + // cannot be inner class because of needed injection + class GlimpWorker( + context: Context, + params: WorkerParameters + ) : Worker(context, params) { - override fun handleNewData(intent: Intent) { - if (!isEnabled(PluginType.BGSOURCE)) return - val bundle = intent.extras ?: return - aapsLogger.debug(LTag.BGSOURCE, "Received Glimp Data: ${BundleLogger.log(bundle)}") - val bgReading = BgReading() - bgReading.value = bundle.getDouble("mySGV") - bgReading.direction = bundle.getString("myTrend") - bgReading.date = bundle.getLong("myTimestamp") - bgReading.raw = 0.0 - MainApp.getDbHelper().createIfNotExists(bgReading, "GLIMP") + @Inject lateinit var glimpPlugin: GlimpPlugin + @Inject lateinit var aapsLogger: AAPSLogger + + init { + (context.applicationContext as HasAndroidInjector).androidInjector().inject(this) + } + + override fun doWork(): Result { + if (!glimpPlugin.isEnabled(PluginType.BGSOURCE)) return Result.failure() + aapsLogger.debug(LTag.BGSOURCE, "Received Glimp Data: $inputData}") + val bgReading = BgReading() + bgReading.value = inputData.getDouble("mySGV", 0.0) + bgReading.direction = inputData.getString("myTrend") + bgReading.date = inputData.getLong("myTimestamp", 0) + bgReading.raw = 0.0 + MainApp.getDbHelper().createIfNotExists(bgReading, "GLIMP") + return Result.success() + } } } \ No newline at end of file diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/source/MM640gPlugin.kt b/app/src/main/java/info/nightscout/androidaps/plugins/source/MM640gPlugin.kt index 064830b175..5a886120d5 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/source/MM640gPlugin.kt +++ b/app/src/main/java/info/nightscout/androidaps/plugins/source/MM640gPlugin.kt @@ -1,6 +1,8 @@ package info.nightscout.androidaps.plugins.source -import android.content.Intent +import android.content.Context +import androidx.work.Worker +import androidx.work.WorkerParameters import dagger.android.HasAndroidInjector import info.nightscout.androidaps.MainApp import info.nightscout.androidaps.R @@ -31,39 +33,49 @@ class MM640gPlugin @Inject constructor( aapsLogger, resourceHelper, injector ), BgSourceInterface { - override fun advancedFilteringSupported(): Boolean { - return false - } + // cannot be inner class because of needed injection + class MM640gWorker( + context: Context, + params: WorkerParameters + ) : Worker(context, params) { - override fun handleNewData(intent: Intent) { - if (!isEnabled(PluginType.BGSOURCE)) return - val bundle = intent.extras ?: return - val collection = bundle.getString("collection") ?: return - if (collection == "entries") { - val data = bundle.getString("data") - aapsLogger.debug(LTag.BGSOURCE, "Received MM640g Data: $data") - if (data != null && data.isNotEmpty()) { - try { - val jsonArray = JSONArray(data) - for (i in 0 until jsonArray.length()) { - val jsonObject = jsonArray.getJSONObject(i) - when (val type = jsonObject.getString("type")) { - "sgv" -> { - val bgReading = BgReading() - bgReading.value = jsonObject.getDouble("sgv") - bgReading.direction = jsonObject.getString("direction") - bgReading.date = jsonObject.getLong("date") - bgReading.raw = jsonObject.getDouble("sgv") - MainApp.getDbHelper().createIfNotExists(bgReading, "MM640g") + @Inject lateinit var mM640gPlugin: MM640gPlugin + @Inject lateinit var aapsLogger: AAPSLogger + + init { + (context.applicationContext as HasAndroidInjector).androidInjector().inject(this) + } + + override fun doWork(): Result { + if (!mM640gPlugin.isEnabled(PluginType.BGSOURCE)) return Result.failure() + val collection = inputData.getString("collection") ?: return Result.failure() + if (collection == "entries") { + val data = inputData.getString("data") + aapsLogger.debug(LTag.BGSOURCE, "Received MM640g Data: $data") + if (data != null && data.isNotEmpty()) { + try { + val jsonArray = JSONArray(data) + for (i in 0 until jsonArray.length()) { + val jsonObject = jsonArray.getJSONObject(i) + when (val type = jsonObject.getString("type")) { + "sgv" -> { + val bgReading = BgReading() + bgReading.value = jsonObject.getDouble("sgv") + bgReading.direction = jsonObject.getString("direction") + bgReading.date = jsonObject.getLong("date") + bgReading.raw = jsonObject.getDouble("sgv") + MainApp.getDbHelper().createIfNotExists(bgReading, "MM640g") + } + + else -> aapsLogger.debug(LTag.BGSOURCE, "Unknown entries type: $type") } - - else -> aapsLogger.debug(LTag.BGSOURCE, "Unknown entries type: $type") } + } catch (e: JSONException) { + aapsLogger.error("Exception: ", e) } - } catch (e: JSONException) { - aapsLogger.error("Exception: ", e) } } + return Result.success() } } } \ No newline at end of file diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/source/NSClientSourcePlugin.kt b/app/src/main/java/info/nightscout/androidaps/plugins/source/NSClientSourcePlugin.kt index 7f3d4707d4..e6ed68b96f 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/source/NSClientSourcePlugin.kt +++ b/app/src/main/java/info/nightscout/androidaps/plugins/source/NSClientSourcePlugin.kt @@ -1,6 +1,8 @@ package info.nightscout.androidaps.plugins.source -import android.content.Intent +import android.content.Context +import androidx.work.Worker +import androidx.work.WorkerParameters import dagger.android.HasAndroidInjector import info.nightscout.androidaps.Config import info.nightscout.androidaps.MainApp @@ -27,7 +29,6 @@ class NSClientSourcePlugin @Inject constructor( injector: HasAndroidInjector, resourceHelper: ResourceHelper, aapsLogger: AAPSLogger, - private val sp: SP, config: Config ) : PluginBase(PluginDescription() .mainType(PluginType.BGSOURCE) @@ -53,32 +54,6 @@ class NSClientSourcePlugin @Inject constructor( return isAdvancedFilteringEnabled } - override fun handleNewData(intent: Intent) { - if (!isEnabled(PluginType.BGSOURCE) && !sp.getBoolean(R.string.key_ns_autobackfill, true)) return - val bundles = intent.extras ?: return - try { - if (bundles.containsKey("sgv")) { - val sgvString = bundles.getString("sgv") - aapsLogger.debug(LTag.BGSOURCE, "Received NS Data: $sgvString") - val sgvJson = JSONObject(sgvString) - storeSgv(sgvJson) - } - if (bundles.containsKey("sgvs")) { - val sgvString = bundles.getString("sgvs") - aapsLogger.debug(LTag.BGSOURCE, "Received NS Data: $sgvString") - val jsonArray = JSONArray(sgvString) - for (i in 0 until jsonArray.length()) { - val sgvJson = jsonArray.getJSONObject(i) - storeSgv(sgvJson) - } - } - } catch (e: Exception) { - aapsLogger.error("Unhandled exception", e) - } - // Objectives 0 - sp.putBoolean(R.string.key_ObjectivesbgIsAvailableInNS, true) - } - private fun storeSgv(sgvJson: JSONObject) { val nsSgv = NSSgv(sgvJson) val bgReading = BgReading(injector, nsSgv) @@ -92,4 +67,44 @@ class NSClientSourcePlugin @Inject constructor( lastBGTimeStamp = timeStamp } } + + // cannot be inner class because of needed injection + class NSClientSourceWorker( + context: Context, + params: WorkerParameters + ) : Worker(context, params) { + + @Inject lateinit var nsClientSourcePlugin: NSClientSourcePlugin + @Inject lateinit var aapsLogger: AAPSLogger + @Inject lateinit var sp: SP + + init { + (context.applicationContext as HasAndroidInjector).androidInjector().inject(this) + } + + override fun doWork(): Result { + if (!nsClientSourcePlugin.isEnabled(PluginType.BGSOURCE) && !sp.getBoolean(R.string.key_ns_autobackfill, true)) return Result.failure() + try { + inputData.getString("sgv")?.let { sgvString -> + aapsLogger.debug(LTag.BGSOURCE, "Received NS Data: $sgvString") + val sgvJson = JSONObject(sgvString) + nsClientSourcePlugin.storeSgv(sgvJson) + } + inputData.getString("sgvs")?.let { sgvString -> + aapsLogger.debug(LTag.BGSOURCE, "Received NS Data: $sgvString") + val jsonArray = JSONArray(sgvString) + for (i in 0 until jsonArray.length()) { + val sgvJson = jsonArray.getJSONObject(i) + nsClientSourcePlugin.storeSgv(sgvJson) + } + } + } catch (e: Exception) { + aapsLogger.error("Unhandled exception", e) + return Result.failure() + } + // Objectives 0 + sp.putBoolean(R.string.key_ObjectivesbgIsAvailableInNS, true) + return Result.success() + } + } } \ No newline at end of file diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/source/PoctechPlugin.kt b/app/src/main/java/info/nightscout/androidaps/plugins/source/PoctechPlugin.kt index eace9e0e0e..5d6861ca37 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/source/PoctechPlugin.kt +++ b/app/src/main/java/info/nightscout/androidaps/plugins/source/PoctechPlugin.kt @@ -1,6 +1,8 @@ package info.nightscout.androidaps.plugins.source -import android.content.Intent +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.MainApp @@ -25,9 +27,7 @@ import javax.inject.Singleton class PoctechPlugin @Inject constructor( injector: HasAndroidInjector, resourceHelper: ResourceHelper, - aapsLogger: AAPSLogger, - private val sp: SP, - private val nsUpload: NSUpload + aapsLogger: AAPSLogger ) : PluginBase(PluginDescription() .mainType(PluginType.BGSOURCE) .fragmentClass(BGSourceFragment::class.java.name) @@ -38,36 +38,48 @@ class PoctechPlugin @Inject constructor( aapsLogger, resourceHelper, injector ), BgSourceInterface { - override fun advancedFilteringSupported(): Boolean { - return false - } + // cannot be inner class because of needed injection + class PoctechWorker( + context: Context, + params: WorkerParameters + ) : Worker(context, params) { - override fun handleNewData(intent: Intent) { - if (!isEnabled(PluginType.BGSOURCE)) return - val bundle = intent.extras ?: return - val bgReading = BgReading() - val data = bundle.getString("data") - aapsLogger.debug(LTag.BGSOURCE, "Received Poctech Data $data") - try { - val jsonArray = JSONArray(data) - aapsLogger.debug(LTag.BGSOURCE, "Received Poctech Data size:" + jsonArray.length()) - for (i in 0 until jsonArray.length()) { - val json = jsonArray.getJSONObject(i) - bgReading.value = json.getDouble("current") - bgReading.direction = json.getString("direction") - bgReading.date = json.getLong("date") - bgReading.raw = json.getDouble("raw") - if (safeGetString(json, "units", Constants.MGDL) == "mmol/L") bgReading.value = bgReading.value * Constants.MMOLL_TO_MGDL - val isNew = MainApp.getDbHelper().createIfNotExists(bgReading, "Poctech") - if (isNew && sp.getBoolean(R.string.key_dexcomg5_nsupload, false)) { - nsUpload.uploadBg(bgReading, "AndroidAPS-Poctech") - } - if (isNew && sp.getBoolean(R.string.key_dexcomg5_xdripupload, false)) { - nsUpload.sendToXdrip(bgReading) + @Inject lateinit var poctechPlugin: PoctechPlugin + @Inject lateinit var aapsLogger: AAPSLogger + @Inject lateinit var sp: SP + @Inject lateinit var nsUpload: NSUpload + + init { + (context.applicationContext as HasAndroidInjector).androidInjector().inject(this) + } + + override fun doWork(): Result { + if (!poctechPlugin.isEnabled(PluginType.BGSOURCE)) return Result.failure() + aapsLogger.debug(LTag.BGSOURCE, "Received Poctech Data $inputData") + try { + val jsonArray = JSONArray(inputData.getString("data")) + aapsLogger.debug(LTag.BGSOURCE, "Received Poctech Data size:" + jsonArray.length()) + for (i in 0 until jsonArray.length()) { + val json = jsonArray.getJSONObject(i) + val bgReading = BgReading() + bgReading.value = json.getDouble("current") + bgReading.direction = json.getString("direction") + bgReading.date = json.getLong("date") + bgReading.raw = json.getDouble("raw") + if (safeGetString(json, "units", Constants.MGDL) == "mmol/L") bgReading.value = bgReading.value * Constants.MMOLL_TO_MGDL + val isNew = MainApp.getDbHelper().createIfNotExists(bgReading, "Poctech") + if (isNew && sp.getBoolean(R.string.key_dexcomg5_nsupload, false)) { + nsUpload.uploadBg(bgReading, "AndroidAPS-Poctech") + } + if (isNew && sp.getBoolean(R.string.key_dexcomg5_xdripupload, false)) { + nsUpload.sendToXdrip(bgReading) + } } + } catch (e: JSONException) { + aapsLogger.error("Exception: ", e) + return Result.failure() } - } catch (e: JSONException) { - aapsLogger.error("Exception: ", e) + return Result.success() } } } \ No newline at end of file diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/source/RandomBgPlugin.kt b/app/src/main/java/info/nightscout/androidaps/plugins/source/RandomBgPlugin.kt index fe98aad3e1..5083854976 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/source/RandomBgPlugin.kt +++ b/app/src/main/java/info/nightscout/androidaps/plugins/source/RandomBgPlugin.kt @@ -1,6 +1,5 @@ package info.nightscout.androidaps.plugins.source -import android.content.Intent import android.os.Handler import android.os.HandlerThread import dagger.android.HasAndroidInjector @@ -13,7 +12,6 @@ import info.nightscout.androidaps.interfaces.PluginDescription import info.nightscout.androidaps.interfaces.PluginType import info.nightscout.androidaps.logging.AAPSLogger import info.nightscout.androidaps.logging.LTag -import info.nightscout.androidaps.plugins.general.automation.AutomationPlugin import info.nightscout.androidaps.plugins.general.nsclient.NSUpload import info.nightscout.androidaps.plugins.pump.virtual.VirtualPumpPlugin import info.nightscout.androidaps.utils.DateUtil @@ -48,16 +46,17 @@ class RandomBgPlugin @Inject constructor( aapsLogger, resourceHelper, injector ), BgSourceInterface { - private val loopHandler : Handler = Handler(HandlerThread(RandomBgPlugin::class.java.simpleName + "Handler").also { it.start() }.looper) + private val loopHandler: Handler = Handler(HandlerThread(RandomBgPlugin::class.java.simpleName + "Handler").also { it.start() }.looper) private lateinit var refreshLoop: Runnable companion object { + const val interval = 5L // minutes } init { refreshLoop = Runnable { - handleNewData(Intent()) + handleNewData() loopHandler.postDelayed(refreshLoop, T.mins(interval).msecs()) } } @@ -80,14 +79,14 @@ class RandomBgPlugin @Inject constructor( return isRunningTest() || virtualPumpPlugin.isEnabled(PluginType.PUMP) && buildHelper.isEngineeringMode() } - override fun handleNewData(intent: Intent) { + private fun handleNewData() { if (!isEnabled(PluginType.BGSOURCE)) return val min = 70 val max = 190 val cal = GregorianCalendar() val currentMinute = cal.get(Calendar.MINUTE) + (cal.get(Calendar.HOUR_OF_DAY) % 2) * 60 - val bgMgdl = min + ((max - min) + (max - min) * sin(currentMinute / 120.0 * 2 * PI))/2 + val bgMgdl = min + ((max - min) + (max - min) * sin(currentMinute / 120.0 * 2 * PI)) / 2 val bgReading = BgReading() bgReading.value = bgMgdl diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/source/TomatoPlugin.kt b/app/src/main/java/info/nightscout/androidaps/plugins/source/TomatoPlugin.kt index 6d62468cd7..0b7bd539c2 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/source/TomatoPlugin.kt +++ b/app/src/main/java/info/nightscout/androidaps/plugins/source/TomatoPlugin.kt @@ -1,6 +1,8 @@ package info.nightscout.androidaps.plugins.source -import android.content.Intent +import android.content.Context +import androidx.work.Worker +import androidx.work.WorkerParameters import dagger.android.HasAndroidInjector import info.nightscout.androidaps.MainApp import info.nightscout.androidaps.R @@ -21,9 +23,7 @@ import javax.inject.Singleton class TomatoPlugin @Inject constructor( injector: HasAndroidInjector, resourceHelper: ResourceHelper, - aapsLogger: AAPSLogger, - private val sp: SP, - private val nsUpload: NSUpload + aapsLogger: AAPSLogger ) : PluginBase(PluginDescription() .mainType(PluginType.BGSOURCE) .fragmentClass(BGSourceFragment::class.java.name) @@ -35,23 +35,35 @@ class TomatoPlugin @Inject constructor( aapsLogger, resourceHelper, injector ), BgSourceInterface { - override fun advancedFilteringSupported(): Boolean { - return false - } + // cannot be inner class because of needed injection + class TomatoWorker( + context: Context, + params: WorkerParameters + ) : Worker(context, params) { - override fun handleNewData(intent: Intent) { - if (!isEnabled(PluginType.BGSOURCE)) return - val bundle = intent.extras ?: return - val bgReading = BgReading() - aapsLogger.debug(LTag.BGSOURCE, "Received Tomato Data") - bgReading.value = bundle.getDouble("com.fanqies.tomatofn.Extras.BgEstimate") - bgReading.date = bundle.getLong("com.fanqies.tomatofn.Extras.Time") - val isNew = MainApp.getDbHelper().createIfNotExists(bgReading, "Tomato") - if (isNew && sp.getBoolean(R.string.key_dexcomg5_nsupload, false)) { - nsUpload.uploadBg(bgReading, "AndroidAPS-Tomato") + @Inject lateinit var tomatoPlugin: TomatoPlugin + @Inject lateinit var aapsLogger: AAPSLogger + @Inject lateinit var sp: SP + @Inject lateinit var nsUpload: NSUpload + + init { + (context.applicationContext as HasAndroidInjector).androidInjector().inject(this) } - if (isNew && sp.getBoolean(R.string.key_dexcomg5_xdripupload, false)) { - nsUpload.sendToXdrip(bgReading) + + override fun doWork(): Result { + if (!tomatoPlugin.isEnabled(PluginType.BGSOURCE)) return Result.failure() + val bgReading = BgReading() + aapsLogger.debug(LTag.BGSOURCE, "Received Tomato Data") + bgReading.value = inputData.getDouble("com.fanqies.tomatofn.Extras.BgEstimate", 0.0) + bgReading.date = inputData.getLong("com.fanqies.tomatofn.Extras.Time", 0) + val isNew = MainApp.getDbHelper().createIfNotExists(bgReading, "Tomato") + if (isNew && sp.getBoolean(R.string.key_dexcomg5_nsupload, false)) { + nsUpload.uploadBg(bgReading, "AndroidAPS-Tomato") + } + if (isNew && sp.getBoolean(R.string.key_dexcomg5_xdripupload, false)) { + nsUpload.sendToXdrip(bgReading) + } + return Result.success() } } } \ No newline at end of file diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/source/XdripPlugin.kt b/app/src/main/java/info/nightscout/androidaps/plugins/source/XdripPlugin.kt index 130a985853..e8fcf3bdc8 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/source/XdripPlugin.kt +++ b/app/src/main/java/info/nightscout/androidaps/plugins/source/XdripPlugin.kt @@ -1,6 +1,8 @@ package info.nightscout.androidaps.plugins.source -import android.content.Intent +import android.content.Context +import androidx.work.Worker +import androidx.work.WorkerParameters import dagger.android.HasAndroidInjector import info.nightscout.androidaps.MainApp import info.nightscout.androidaps.R @@ -10,7 +12,6 @@ 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.BundleLogger import info.nightscout.androidaps.logging.LTag import info.nightscout.androidaps.services.Intents import info.nightscout.androidaps.utils.resources.ResourceHelper @@ -32,32 +33,41 @@ class XdripPlugin @Inject constructor( ), BgSourceInterface { private var advancedFiltering = false - private var sensorBatteryLevel = -1 + override var sensorBatteryLevel = -1 override fun advancedFilteringSupported(): Boolean { return advancedFiltering } - override fun handleNewData(intent: Intent) { - if (!isEnabled(PluginType.BGSOURCE)) return - val bundle = intent.extras ?: return - aapsLogger.debug(LTag.BGSOURCE, "Received xDrip data: " + BundleLogger.log(intent.extras)) - val bgReading = BgReading() - bgReading.value = bundle.getDouble(Intents.EXTRA_BG_ESTIMATE) - bgReading.direction = bundle.getString(Intents.EXTRA_BG_SLOPE_NAME) - bgReading.date = bundle.getLong(Intents.EXTRA_TIMESTAMP) - bgReading.raw = bundle.getDouble(Intents.EXTRA_RAW) - if (bundle.containsKey(Intents.EXTRA_SENSOR_BATTERY)) sensorBatteryLevel = bundle.getInt(Intents.EXTRA_SENSOR_BATTERY) - val source = bundle.getString(Intents.XDRIP_DATA_SOURCE_DESCRIPTION, "no Source specified") - setSource(source) - MainApp.getDbHelper().createIfNotExists(bgReading, "XDRIP") - } - private fun setSource(source: String) { advancedFiltering = source.contains("G5 Native") || source.contains("G6 Native") } - override fun getSensorBatteryLevel(): Int { - return sensorBatteryLevel + // cannot be inner class because of needed injection + class XdripWorker( + context: Context, + params: WorkerParameters + ) : Worker(context, params) { + + @Inject lateinit var xdripPlugin: XdripPlugin + + init { + (context.applicationContext as HasAndroidInjector).androidInjector().inject(this) + } + + override fun doWork(): Result { + if (!xdripPlugin.isEnabled(PluginType.BGSOURCE)) return Result.failure() + xdripPlugin.aapsLogger.debug(LTag.BGSOURCE, "Received xDrip data: $inputData") + val bgReading = BgReading() + bgReading.value = inputData.getDouble(Intents.EXTRA_BG_ESTIMATE, 0.0) + bgReading.direction = inputData.getString(Intents.EXTRA_BG_SLOPE_NAME) + bgReading.date = inputData.getLong(Intents.EXTRA_TIMESTAMP, 0) + bgReading.raw = inputData.getDouble(Intents.EXTRA_RAW, 0.0) + xdripPlugin.sensorBatteryLevel = inputData.getInt(Intents.EXTRA_SENSOR_BATTERY, -1) + val source = inputData.getString(Intents.XDRIP_DATA_SOURCE_DESCRIPTION) ?: "" + xdripPlugin.setSource(source) + MainApp.getDbHelper().createIfNotExists(bgReading, "XDRIP") + return Result.success() + } } } \ No newline at end of file diff --git a/app/src/main/java/info/nightscout/androidaps/receivers/BundleStore.kt b/app/src/main/java/info/nightscout/androidaps/receivers/BundleStore.kt new file mode 100644 index 0000000000..36e7e7bf7e --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/receivers/BundleStore.kt @@ -0,0 +1,24 @@ +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() + 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 + } +} \ No newline at end of file diff --git a/app/src/main/java/info/nightscout/androidaps/receivers/DataReceiver.kt b/app/src/main/java/info/nightscout/androidaps/receivers/DataReceiver.kt index b5fd362e57..a676211745 100644 --- a/app/src/main/java/info/nightscout/androidaps/receivers/DataReceiver.kt +++ b/app/src/main/java/info/nightscout/androidaps/receivers/DataReceiver.kt @@ -2,23 +2,118 @@ package info.nightscout.androidaps.receivers import android.content.Context import android.content.Intent -import androidx.legacy.content.* -import dagger.android.AndroidInjection +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.services.DataService +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 -// We are not ready to switch to JobScheduler -@Suppress("DEPRECATION") -open class DataReceiver : WakefulBroadcastReceiver() { +open class DataReceiver : DaggerBroadcastReceiver() { + @Inject lateinit var aapsLogger: AAPSLogger + @Inject lateinit var bundleStore: BundleStore + + private val jobGroupName = "data" override fun onReceive(context: Context, intent: Intent) { - AndroidInjection.inject(this, context) - aapsLogger.debug(LTag.DATASERVICE, "onReceive $intent") - startWakefulService(context, Intent(context, DataService::class.java) - .setAction(intent.action) - .putExtras(intent)) + super.onReceive(context, intent) + val bundle = intent.extras ?: return + aapsLogger.debug(LTag.DATASERVICE, "onReceive ${intent.action} ${BundleLogger.log(bundle)}") + + + when (intent.action) { + Intents.ACTION_NEW_BG_ESTIMATE -> + OneTimeWorkRequest.Builder(XdripPlugin.XdripWorker::class.java) + .setInputData(Data.Builder().also { + it.copyString("collection", bundle, null) + it.copyString("data", bundle) + }.build()).build() + Intents.POCTECH_BG -> + OneTimeWorkRequest.Builder(PoctechPlugin.PoctechWorker::class.java) + .setInputData(Data.Builder().also { + it.copyString("data", bundle) + }.build()).build() + Intents.GLIMP_BG -> + OneTimeWorkRequest.Builder(GlimpPlugin.GlimpWorker::class.java) + .setInputData(Data.Builder().also { + it.copyDouble("mySGV", bundle) + it.copyString("myTrend", bundle) + it.copyLong("myTimestamp", bundle) + }.build()).build() + Intents.TOMATO_BG -> + 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(Data.Builder().also { + it.copyString("profile", bundle, null) + }.build()).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 { + it.copyDouble(Intents.EXTRA_BG_ESTIMATE, bundle) + it.copyString(Intents.EXTRA_BG_SLOPE_NAME, bundle) + it.copyLong(Intents.EXTRA_TIMESTAMP, bundle) + it.copyDouble(Intents.EXTRA_RAW, bundle) + it.copyInt(Intents.EXTRA_SENSOR_BATTERY, bundle, -1) + it.copyString(Intents.XDRIP_DATA_SOURCE_DESCRIPTION, bundle) + }.build()).build() + Telephony.Sms.Intents.SMS_RECEIVED_ACTION -> + OneTimeWorkRequest.Builder(SmsCommunicatorPlugin.SmsCommunicatorWorker::class.java) + .setInputData(Data.Builder().also { + it.putLong("storeKey", bundleStore.store(bundle)) + it.putString("action", intent.action) + }.build()).build() + Intents.EVERSENSE_BG -> + OneTimeWorkRequest.Builder(EversensePlugin.EversenseWorker::class.java) + .setInputData(Data.Builder().also { + it.putLong("storeKey", bundleStore.store(bundle)) + it.putString("action", intent.action) + }.build()).build() + Intents.DEXCOM_BG -> + OneTimeWorkRequest.Builder(DexcomPlugin.DexcomWorker::class.java) + .setInputData(Data.Builder().also { + it.putLong("storeKey", bundleStore.store(bundle)) + it.putString("action", intent.action) + }.build()).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(Data.Builder().also { + it.putLong("storeKey", bundleStore.store(bundle)) + it.putString("action", intent.action) + }.build()).build() + else -> null + }?.let { request -> + WorkManager.getInstance(context) + .enqueueUniqueWork(jobGroupName, ExistingWorkPolicy.APPEND_OR_REPLACE , request) + } } } \ No newline at end of file diff --git a/app/src/main/java/info/nightscout/androidaps/services/DataService.java b/app/src/main/java/info/nightscout/androidaps/services/DataService.java deleted file mode 100644 index 06d78f2ae4..0000000000 --- a/app/src/main/java/info/nightscout/androidaps/services/DataService.java +++ /dev/null @@ -1,256 +0,0 @@ -package info.nightscout.androidaps.services; - -import android.content.Intent; -import android.os.Bundle; -import android.provider.Telephony; - -import org.json.JSONArray; -import org.json.JSONException; -import org.json.JSONObject; - -import javax.inject.Inject; - -import dagger.android.DaggerIntentService; -import info.nightscout.androidaps.Config; -import info.nightscout.androidaps.MainApp; -import info.nightscout.androidaps.R; -import info.nightscout.androidaps.db.CareportalEvent; -import info.nightscout.androidaps.events.EventNsTreatment; -import info.nightscout.androidaps.interfaces.ActivePluginProvider; -import info.nightscout.androidaps.logging.AAPSLogger; -import info.nightscout.androidaps.logging.BundleLogger; -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.data.NSMbg; -import info.nightscout.androidaps.plugins.general.overview.events.EventNewNotification; -import info.nightscout.androidaps.plugins.general.overview.notifications.Notification; -import info.nightscout.androidaps.plugins.general.smsCommunicator.SmsCommunicatorPlugin; -import info.nightscout.androidaps.plugins.profile.ns.NSProfilePlugin; -import info.nightscout.androidaps.plugins.source.DexcomPlugin; -import info.nightscout.androidaps.plugins.source.EversensePlugin; -import info.nightscout.androidaps.plugins.source.GlimpPlugin; -import info.nightscout.androidaps.plugins.source.MM640gPlugin; -import info.nightscout.androidaps.plugins.source.NSClientSourcePlugin; -import info.nightscout.androidaps.plugins.source.PoctechPlugin; -import info.nightscout.androidaps.plugins.source.TomatoPlugin; -import info.nightscout.androidaps.plugins.source.XdripPlugin; -import info.nightscout.androidaps.receivers.DataReceiver; -import info.nightscout.androidaps.utils.JsonHelper; -import info.nightscout.androidaps.utils.buildHelper.BuildHelper; -import info.nightscout.androidaps.utils.sharedPreferences.SP; - - -public class DataService extends DaggerIntentService { - @Inject AAPSLogger aapsLogger; - @Inject SP sp; - @Inject RxBusWrapper rxBus; - @Inject NSUpload nsUpload; - @Inject SmsCommunicatorPlugin smsCommunicatorPlugin; - @Inject DexcomPlugin dexcomPlugin; - @Inject EversensePlugin eversensePlugin; - @Inject GlimpPlugin glimpPlugin; - @Inject MM640gPlugin mm640GPlugin; - @Inject NSClientSourcePlugin nsClientSourcePlugin; - @Inject PoctechPlugin poctechPlugin; - @Inject TomatoPlugin tomatoPlugin; - @Inject XdripPlugin xdripPlugin; - @Inject NSProfilePlugin nsProfilePlugin; - @Inject ActivePluginProvider activePlugin; - @Inject Config config; - @Inject BuildHelper buildHelper; - - public DataService() { - super("DataService"); - } - - - @Override - protected void onHandleIntent(final Intent intent) { - aapsLogger.debug(LTag.DATASERVICE, "onHandleIntent " + intent); - aapsLogger.debug(LTag.DATASERVICE, "onHandleIntent " + BundleLogger.log(intent.getExtras())); - - - boolean acceptNSData = !sp.getBoolean(R.string.key_ns_upload_only, true) && buildHelper.isEngineeringMode() || config.getNSCLIENT(); - - final String action = intent.getAction(); - if (Intents.ACTION_NEW_BG_ESTIMATE.equals(action)) { - xdripPlugin.handleNewData(intent); - } else if (Intents.NS_EMULATOR.equals(action)) { - mm640GPlugin.handleNewData(intent); - } else if (Intents.GLIMP_BG.equals(action)) { - glimpPlugin.handleNewData(intent); - } else if (Intents.DEXCOM_BG.equals(action)) { - dexcomPlugin.handleNewData(intent); - } else if (Intents.POCTECH_BG.equals(action)) { - poctechPlugin.handleNewData(intent); - } else if (Intents.TOMATO_BG.equals(action)) { - tomatoPlugin.handleNewData(intent); - } else if (Intents.EVERSENSE_BG.equals(action)) { - eversensePlugin.handleNewData(intent); - } else if (Intents.ACTION_NEW_SGV.equals(action)) { - nsClientSourcePlugin.handleNewData(intent); - } else if (Intents.ACTION_NEW_PROFILE.equals(action)) { - // always handle Profile if NSProfile is enabled without looking at nsUploadOnly - nsProfilePlugin.handleNewData(intent); - } else if (acceptNSData && - (Intents.ACTION_NEW_TREATMENT.equals(action) || - Intents.ACTION_CHANGED_TREATMENT.equals(action) || - Intents.ACTION_REMOVED_TREATMENT.equals(action) || - Intents.ACTION_NEW_CAL.equals(action) || - Intents.ACTION_NEW_MBG.equals(action)) - ) { - handleNewDataFromNSClient(intent); - } else if (Telephony.Sms.Intents.SMS_RECEIVED_ACTION.equals(action)) { - smsCommunicatorPlugin.handleNewData(intent); - } - - aapsLogger.debug(LTag.DATASERVICE, "onHandleIntent exit " + intent); - DataReceiver.completeWakefulIntent(intent); - } - - @Override - public void onDestroy() { - super.onDestroy(); - } - - private void handleNewDataFromNSClient(Intent intent) { - Bundle bundles = intent.getExtras(); - if (bundles == null) return; - aapsLogger.debug(LTag.DATASERVICE, "Got intent: " + intent.getAction()); - - - if (intent.getAction().equals(Intents.ACTION_NEW_TREATMENT) || intent.getAction().equals(Intents.ACTION_CHANGED_TREATMENT)) { - try { - if (bundles.containsKey("treatment")) { - JSONObject json = new JSONObject(bundles.getString("treatment")); - handleTreatmentFromNS(json, intent); - } - if (bundles.containsKey("treatments")) { - String trstring = bundles.getString("treatments"); - JSONArray jsonArray = new JSONArray(trstring); - for (int i = 0; i < jsonArray.length(); i++) { - JSONObject json = jsonArray.getJSONObject(i); - handleTreatmentFromNS(json, intent); - } - } - } catch (JSONException e) { - aapsLogger.error(LTag.DATASERVICE, "Unhandled exception", e); - } - } - - if (intent.getAction().equals(Intents.ACTION_REMOVED_TREATMENT)) { - try { - if (bundles.containsKey("treatment")) { - String trstring = bundles.getString("treatment"); - JSONObject json = new JSONObject(trstring); - handleRemovedTreatmentFromNS(json); - } - - if (bundles.containsKey("treatments")) { - String trstring = bundles.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 (intent.getAction().equals(Intents.ACTION_NEW_MBG)) { - try { - if (bundles.containsKey("mbg")) { - String mbgstring = bundles.getString("mbg"); - JSONObject mbgJson = new JSONObject(mbgstring); - storeMbg(mbgJson); - } - - if (bundles.containsKey("mbgs")) { - String sgvstring = bundles.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) { - // new DB model - EventNsTreatment evtTreatment = new EventNsTreatment(EventNsTreatment.Companion.getREMOVE(), json); - rxBus.send(evtTreatment); - // old DB model - String _id = JsonHelper.safeGetString(json, "_id"); - MainApp.getDbHelper().deleteTempTargetById(_id); - MainApp.getDbHelper().deleteTempBasalById(_id); - MainApp.getDbHelper().deleteExtendedBolusById(_id); - MainApp.getDbHelper().deleteCareportalEventById(_id); - MainApp.getDbHelper().deleteProfileSwitchById(_id); - } - - private void handleTreatmentFromNS(JSONObject json, Intent intent) { - // new DB model - int mode = Intents.ACTION_NEW_TREATMENT.equals(intent.getAction()) ? 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(CareportalEvent.TEMPORARYTARGET)) { - MainApp.getDbHelper().createTemptargetFromJsonIfNotExists(json); - } else if (eventType.equals(CareportalEvent.TEMPBASAL)) { - MainApp.getDbHelper().createTempBasalFromJsonIfNotExists(json); - } else if (eventType.equals(CareportalEvent.COMBOBOLUS)) { - MainApp.getDbHelper().createExtendedBolusFromJsonIfNotExists(json); - } else if (eventType.equals(CareportalEvent.PROFILESWITCH)) { - MainApp.getDbHelper().createProfileSwitchFromJsonIfNotExists(activePlugin, nsUpload, json); - } else if (eventType.equals(CareportalEvent.SITECHANGE) || - eventType.equals(CareportalEvent.INSULINCHANGE) || - eventType.equals(CareportalEvent.SENSORCHANGE) || - eventType.equals(CareportalEvent.BGCHECK) || - eventType.equals(CareportalEvent.NOTE) || - eventType.equals(CareportalEvent.NONE) || - eventType.equals(CareportalEvent.ANNOUNCEMENT) || - eventType.equals(CareportalEvent.QUESTION) || - eventType.equals(CareportalEvent.EXERCISE) || - eventType.equals(CareportalEvent.OPENAPSOFFLINE) || - eventType.equals(CareportalEvent.PUMPBATTERYCHANGE)) { - MainApp.getDbHelper().createCareportalEventFromJsonIfNotExists(json); - } - - if (eventType.equals(CareportalEvent.ANNOUNCEMENT)) { - 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.NSANNOUNCEMENT, notes, Notification.ANNOUNCEMENT, 60); - rxBus.send(new EventNewNotification(announcement)); - } - } - } - } - - private void storeMbg(JSONObject mbgJson) { - NSMbg nsMbg = new NSMbg(mbgJson); - CareportalEvent careportalEvent = new CareportalEvent(nsMbg); - MainApp.getDbHelper().createOrUpdate(careportalEvent); - aapsLogger.debug(LTag.DATASERVICE, "Adding/Updating new MBG: " + careportalEvent.toString()); - } - -} diff --git a/app/src/main/java/info/nightscout/androidaps/utils/extensions/WorkerDataBuilder.kt b/app/src/main/java/info/nightscout/androidaps/utils/extensions/WorkerDataBuilder.kt new file mode 100644 index 0000000000..b5b75e5805 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/utils/extensions/WorkerDataBuilder.kt @@ -0,0 +1,16 @@ +package info.nightscout.androidaps.utils.extensions + +import android.os.Bundle +import androidx.work.Data + +fun Data.Builder.copyString(key: String, bundle: Bundle?, defaultValue : String? = ""): Data.Builder = + this.also { putString(key, bundle?.getString(key) ?: defaultValue) } + +fun Data.Builder.copyLong(key: String, bundle: Bundle?, defaultValue : Long = 0): Data.Builder = + this.also { putLong(key, bundle?.getLong(key) ?: defaultValue) } + +fun Data.Builder.copyInt(key: String, bundle: Bundle?, defaultValue : Int = 0): Data.Builder = + this.also { putInt(key, bundle?.getInt(key) ?: defaultValue) } + +fun Data.Builder.copyDouble(key: String, bundle: Bundle?, defaultValue : Double = 0.0): Data.Builder = + this.also { putDouble(key, bundle?.getDouble(key) ?: defaultValue) } diff --git a/build.gradle b/build.gradle index 42771275e3..977c6fe4ce 100644 --- a/build.gradle +++ b/build.gradle @@ -20,7 +20,7 @@ buildscript { constraintlayout_version = '2.0.4' preferencektx_version = '1.1.1' commonslang3_version = '3.11' - work_version = '2.4.0' + work_version = '2.5.0' junit_version = '4.13.1' mockitoVersion = '2.8.47' diff --git a/core/src/main/java/info/nightscout/androidaps/interfaces/BgSourceInterface.java b/core/src/main/java/info/nightscout/androidaps/interfaces/BgSourceInterface.java deleted file mode 100644 index 6a38de63b7..0000000000 --- a/core/src/main/java/info/nightscout/androidaps/interfaces/BgSourceInterface.java +++ /dev/null @@ -1,16 +0,0 @@ -package info.nightscout.androidaps.interfaces; - -import android.content.Intent; - -/** - * Created by mike on 20.06.2016. - */ -public interface BgSourceInterface { - boolean advancedFilteringSupported(); - - void handleNewData(Intent intent); - - default int getSensorBatteryLevel() { - return -1; - } -} diff --git a/core/src/main/java/info/nightscout/androidaps/interfaces/BgSourceInterface.kt b/core/src/main/java/info/nightscout/androidaps/interfaces/BgSourceInterface.kt new file mode 100644 index 0000000000..200b68102d --- /dev/null +++ b/core/src/main/java/info/nightscout/androidaps/interfaces/BgSourceInterface.kt @@ -0,0 +1,11 @@ +package info.nightscout.androidaps.interfaces + +/** + * Created by mike on 20.06.2016. + */ +interface BgSourceInterface { + + fun advancedFilteringSupported(): Boolean = false + val sensorBatteryLevel: Int + get() = -1 +} \ No newline at end of file