diff --git a/core/interfaces/src/main/java/info/nightscout/interfaces/XDripBroadcast.kt b/core/interfaces/src/main/java/info/nightscout/interfaces/XDripBroadcast.kt index 7690c74dd3..e76c7df808 100644 --- a/core/interfaces/src/main/java/info/nightscout/interfaces/XDripBroadcast.kt +++ b/core/interfaces/src/main/java/info/nightscout/interfaces/XDripBroadcast.kt @@ -1,14 +1,87 @@ package info.nightscout.interfaces +import info.nightscout.database.entities.Bolus +import info.nightscout.database.entities.Carbs +import info.nightscout.database.entities.DeviceStatus +import info.nightscout.database.entities.EffectiveProfileSwitch +import info.nightscout.database.entities.ExtendedBolus import info.nightscout.database.entities.GlucoseValue +import info.nightscout.database.entities.OfflineEvent +import info.nightscout.database.entities.ProfileSwitch +import info.nightscout.database.entities.TemporaryBasal +import info.nightscout.database.entities.TemporaryTarget +import info.nightscout.database.entities.TherapyEvent import org.json.JSONArray import org.json.JSONObject +/** + * Send data to xDrip+ via Inter-app settings + */ interface XDripBroadcast { + /** + * Send calibration to xDrip+ + * Accepting must be enabled in Inter-app settings - Accept Calibrations + */ fun sendCalibration(bg: Double): Boolean - fun send(glucoseValue: GlucoseValue) + fun sendIn640gMode(glucoseValue: GlucoseValue) fun sendProfile(profileStoreJson: JSONObject) fun sendTreatments(addedOrUpdatedTreatments: JSONArray) fun sendSgvs(sgvs: JSONArray) + + /** + * Send data to xDrip+ + * Accepting must be enabled in Inter-app settings - Accept Glucose + */ + fun send(gv: GlucoseValue) + /** + * Send data to xDrip+ + * Accepting must be enabled in Inter-app settings - Accept treatments + */ + fun send(bolus: Bolus) + /** + * Send data to xDrip+ + * Accepting must be enabled in Inter-app settings - Accept treatments + */ + fun send(carbs: Carbs) + /** + * Send data to xDrip+ + * Accepting must be enabled in Inter-app settings - Accept treatments + */ + fun send(tt: TemporaryTarget) + /** + * Send data to xDrip+ + * Accepting must be enabled in Inter-app settings - Accept treatments + */ + fun send(te: TherapyEvent) + /** + * Send data to xDrip+ + * Accepting must be enabled in Inter-app settings - Accept treatments + */ + fun send(deviceStatus: DeviceStatus) + /** + * Send data to xDrip+ + * Accepting must be enabled in Inter-app settings - Accept treatments + */ + fun send(tb: TemporaryBasal) + /** + * Send data to xDrip+ + * Accepting must be enabled in Inter-app settings - Accept treatments + */ + fun send(eb: ExtendedBolus) + /** + * Send data to xDrip+ + * Accepting must be enabled in Inter-app settings - Accept treatments + */ + fun send(ps: ProfileSwitch) + /** + * Send data to xDrip+ + * Accepting must be enabled in Inter-app settings - Accept treatments + */ + fun send(ps: EffectiveProfileSwitch) + /** + * Send data to xDrip+ + * Accepting must be enabled in Inter-app settings - Accept treatments + */ + fun send(ps: OfflineEvent) } \ No newline at end of file diff --git a/core/interfaces/src/main/java/info/nightscout/interfaces/receivers/Intents.kt b/core/interfaces/src/main/java/info/nightscout/interfaces/receivers/Intents.kt index e7e15ea428..81716dbe36 100644 --- a/core/interfaces/src/main/java/info/nightscout/interfaces/receivers/Intents.kt +++ b/core/interfaces/src/main/java/info/nightscout/interfaces/receivers/Intents.kt @@ -10,6 +10,10 @@ interface Intents { const val ACTION_NEW_PROFILE = "info.nightscout.client.NEW_PROFILE" const val ACTION_NEW_SGV = "info.nightscout.client.NEW_SGV" + const val EXTRA_STATUSLINE = "com.eveningoutpost.dexdrip.Extras.Statusline" + const val ACTION_NEW_EXTERNAL_STATUSLINE = "com.eveningoutpost.dexdrip.ExternalStatusline" + const val RECEIVER_PERMISSION = "com.eveningoutpost.dexdrip.permissions.RECEIVE_EXTERNAL_STATUSLINE" + // AAPS -> xDrip 640G mode const val XDRIP_PLUS_NS_EMULATOR = "com.eveningoutpost.dexdrip.NS_EMULATOR" diff --git a/implementation/src/main/java/info/nightscout/implementation/XDripBroadcastImpl.kt b/implementation/src/main/java/info/nightscout/implementation/XDripBroadcastImpl.kt deleted file mode 100644 index 322baa2d6d..0000000000 --- a/implementation/src/main/java/info/nightscout/implementation/XDripBroadcastImpl.kt +++ /dev/null @@ -1,163 +0,0 @@ -package info.nightscout.implementation - -import android.content.Context -import android.content.Intent -import android.os.Bundle -import info.nightscout.androidaps.annotations.OpenForTesting -import info.nightscout.core.ui.toast.ToastUtils -import info.nightscout.database.entities.GlucoseValue -import info.nightscout.interfaces.GlucoseUnit -import info.nightscout.interfaces.XDripBroadcast -import info.nightscout.interfaces.profile.ProfileFunction -import info.nightscout.interfaces.receivers.Intents -import info.nightscout.rx.logging.AAPSLogger -import info.nightscout.rx.logging.LTag -import info.nightscout.shared.extensions.safeQueryBroadcastReceivers -import info.nightscout.shared.interfaces.ResourceHelper -import info.nightscout.shared.sharedPreferences.SP -import org.json.JSONArray -import org.json.JSONException -import org.json.JSONObject -import java.text.SimpleDateFormat -import java.util.Locale -import javax.inject.Inject -import javax.inject.Singleton - -@Suppress("SpellCheckingInspection") -@OpenForTesting -@Singleton -class XDripBroadcastImpl @Inject constructor( - private val context: Context, - private val aapsLogger: AAPSLogger, - private val sp: SP, - private val rh: ResourceHelper, - private val profileFunction: ProfileFunction -) : XDripBroadcast { - - override fun sendCalibration(bg: Double): Boolean { - val bundle = Bundle() - bundle.putDouble("glucose_number", bg) - bundle.putString("units", if (profileFunction.getUnits() == GlucoseUnit.MGDL) "mgdl" else "mmol") - bundle.putLong("timestamp", System.currentTimeMillis()) - val intent = Intent(Intents.ACTION_REMOTE_CALIBRATION) - intent.putExtras(bundle) - intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES) - context.sendBroadcast(intent) - val q = context.packageManager.safeQueryBroadcastReceivers(intent, 0) - return if (q.isEmpty()) { - ToastUtils.errorToast(context, R.string.xdrip_not_installed) - aapsLogger.debug(rh.gs(R.string.xdrip_not_installed)) - false - } else { - ToastUtils.errorToast(context, R.string.calibration_sent) - aapsLogger.debug(rh.gs(R.string.calibration_sent)) - true - } - } - - // sent in 640G mode - override fun send(glucoseValue: GlucoseValue) { - if (sp.getBoolean(info.nightscout.core.utils.R.string.key_dexcomg5_xdripupload, false)) { - val format = SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ", Locale.US) - try { - val entriesBody = JSONArray() - val json = JSONObject() - json.put("sgv", glucoseValue.value) - json.put("direction", glucoseValue.trendArrow.text) - json.put("device", "G5") - json.put("type", "sgv") - json.put("date", glucoseValue.timestamp) - json.put("dateString", format.format(glucoseValue.timestamp)) - entriesBody.put(json) - val bundle = Bundle() - bundle.putString("action", "add") - bundle.putString("collection", "entries") - bundle.putString("data", entriesBody.toString()) - val intent = Intent(Intents.XDRIP_PLUS_NS_EMULATOR) - intent.putExtras(bundle).addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES) - context.sendBroadcast(intent) - val receivers = context.packageManager.safeQueryBroadcastReceivers(intent, 0) - if (receivers.isEmpty()) { - //NSUpload.log.debug("No xDrip receivers found. ") - aapsLogger.debug(LTag.BGSOURCE, "No xDrip receivers found.") - } else { - aapsLogger.debug(LTag.BGSOURCE, "${receivers.size} xDrip receivers") - } - } catch (e: JSONException) { - aapsLogger.error(LTag.BGSOURCE, "Unhandled exception", e) - } - } - } - - // sent in NSClient dbaccess mode - override fun sendProfile(profileStoreJson: JSONObject) { - if (sp.getBoolean(info.nightscout.core.utils.R.string.key_nsclient_localbroadcasts, false)) - broadcast( - Intent(Intents.ACTION_NEW_PROFILE).apply { - addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES) - putExtras(Bundle().apply { putString("profile", profileStoreJson.toString()) }) - } - ) - - } - - // sent in NSClient dbaccess mode - override fun sendTreatments(addedOrUpdatedTreatments: JSONArray) { - if (sp.getBoolean(info.nightscout.core.utils.R.string.key_nsclient_localbroadcasts, false)) - splitArray(addedOrUpdatedTreatments).forEach { part -> - broadcast( - Intent(Intents.ACTION_NEW_TREATMENT).apply { - addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES) - putExtras(Bundle().apply { putString("treatments", part.toString()) }) - } - ) - } - } - - // sent in NSClient dbaccess mode - override fun sendSgvs(sgvs: JSONArray) { - if (sp.getBoolean(info.nightscout.core.utils.R.string.key_nsclient_localbroadcasts, false)) - splitArray(sgvs).forEach { part -> - broadcast( - Intent(Intents.ACTION_NEW_SGV).apply { - addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES) - putExtras(Bundle().apply { putString("sgvs", part.toString()) }) - } - ) - } - } - - private fun splitArray(array: JSONArray): List { - var ret: MutableList = ArrayList() - try { - val size = array.length() - var count = 0 - var newarr: JSONArray? = null - for (i in 0 until size) { - if (count == 0) { - if (newarr != null) ret.add(newarr) - newarr = JSONArray() - count = 20 - } - newarr?.put(array[i]) - --count - } - if (newarr != null && newarr.length() > 0) ret.add(newarr) - } catch (e: JSONException) { - aapsLogger.error("Unhandled exception", e) - ret = ArrayList() - ret.add(array) - } - return ret - } - - private fun broadcast(intent: Intent) { - context.packageManager.safeQueryBroadcastReceivers(intent, 0).forEach { resolveInfo -> - resolveInfo.activityInfo.packageName?.let { - intent.setPackage(it) - context.sendBroadcast(intent) - aapsLogger.debug(LTag.CORE, "Sending broadcast " + intent.action + " to: " + it) - } - } - } -} \ No newline at end of file diff --git a/implementation/src/main/java/info/nightscout/implementation/di/ImplementationModule.kt b/implementation/src/main/java/info/nightscout/implementation/di/ImplementationModule.kt index 5a665df59c..4570cd97a0 100644 --- a/implementation/src/main/java/info/nightscout/implementation/di/ImplementationModule.kt +++ b/implementation/src/main/java/info/nightscout/implementation/di/ImplementationModule.kt @@ -10,7 +10,6 @@ import info.nightscout.implementation.LocalAlertUtilsImpl import info.nightscout.implementation.TranslatorImpl import info.nightscout.implementation.TrendCalculatorImpl import info.nightscout.implementation.UserEntryLoggerImpl -import info.nightscout.implementation.XDripBroadcastImpl import info.nightscout.implementation.androidNotification.NotificationHolderImpl import info.nightscout.implementation.db.PersistenceLayerImpl import info.nightscout.implementation.iob.GlucoseStatusProviderImpl @@ -40,7 +39,6 @@ import info.nightscout.implementation.userEntry.UserEntryPresentationHelperImpl import info.nightscout.interfaces.LocalAlertUtils import info.nightscout.interfaces.NotificationHolder import info.nightscout.interfaces.Translator -import info.nightscout.interfaces.XDripBroadcast import info.nightscout.interfaces.db.PersistenceLayer import info.nightscout.interfaces.iob.GlucoseStatusProvider import info.nightscout.interfaces.logging.LoggerUtils @@ -105,7 +103,6 @@ abstract class ImplementationModule { @Binds fun bindTirCalculatorInterface(tirCalculator: TirCalculatorImpl): TirCalculator @Binds fun bindDexcomTirCalculatorInterface(dexcomTirCalculator: DexcomTirCalculatorImpl): DexcomTirCalculator @Binds fun bindPumpSyncInterface(pumpSyncImplementation: PumpSyncImplementation): PumpSync - @Binds fun bindXDripBroadcastInterface(xDripBroadcastImpl: XDripBroadcastImpl): XDripBroadcast @Binds fun bindLocalAlertUtilsInterface(localAlertUtils: LocalAlertUtilsImpl): LocalAlertUtils @Binds fun bindIconsProviderInterface(iconsProvider: IconsProviderImplementation): IconsProvider @Binds fun bindNotificationHolderInterface(notificationHolder: NotificationHolderImpl): NotificationHolder diff --git a/implementation/src/main/res/values/strings.xml b/implementation/src/main/res/values/strings.xml index 6df0df72ce..c9d2c3b0ab 100644 --- a/implementation/src/main/res/values/strings.xml +++ b/implementation/src/main/res/values/strings.xml @@ -1,8 +1,5 @@ - xDrip+ not installed - Calibration sent to xDrip+ - BG Command is executed right now diff --git a/plugins/source/src/main/java/info/nightscout/source/DexcomPlugin.kt b/plugins/source/src/main/java/info/nightscout/source/DexcomPlugin.kt index 7e6a943e64..99d8db5525 100644 --- a/plugins/source/src/main/java/info/nightscout/source/DexcomPlugin.kt +++ b/plugins/source/src/main/java/info/nightscout/source/DexcomPlugin.kt @@ -185,11 +185,11 @@ class DexcomPlugin @Inject constructor( } } } - xDripBroadcast.send(result.inserted[i]) + xDripBroadcast.sendIn640gMode(result.inserted[i]) aapsLogger.debug(LTag.DATABASE, "Inserted bg ${result.inserted[i]}") } result.updated.forEach { - xDripBroadcast.send(it) + xDripBroadcast.sendIn640gMode(it) aapsLogger.debug(LTag.DATABASE, "Updated bg $it") } result.sensorInsertionsInserted.forEach { diff --git a/plugins/source/src/main/java/info/nightscout/source/EversensePlugin.kt b/plugins/source/src/main/java/info/nightscout/source/EversensePlugin.kt index bdb9d0b2b8..b915b0df08 100644 --- a/plugins/source/src/main/java/info/nightscout/source/EversensePlugin.kt +++ b/plugins/source/src/main/java/info/nightscout/source/EversensePlugin.kt @@ -114,7 +114,7 @@ class EversensePlugin @Inject constructor( .blockingGet() .also { savedValues -> savedValues.inserted.forEach { - xDripBroadcast.send(it) + xDripBroadcast.sendIn640gMode(it) aapsLogger.debug(LTag.DATABASE, "Inserted bg $it") } } diff --git a/plugins/source/src/main/java/info/nightscout/source/GlimpPlugin.kt b/plugins/source/src/main/java/info/nightscout/source/GlimpPlugin.kt index ddfbdf0295..a161674bd5 100644 --- a/plugins/source/src/main/java/info/nightscout/source/GlimpPlugin.kt +++ b/plugins/source/src/main/java/info/nightscout/source/GlimpPlugin.kt @@ -74,7 +74,7 @@ class GlimpPlugin @Inject constructor( .blockingGet() .also { savedValues -> savedValues.inserted.forEach { - xDripBroadcast.send(it) + xDripBroadcast.sendIn640gMode(it) aapsLogger.debug(LTag.DATABASE, "Inserted bg $it") } } diff --git a/plugins/source/src/main/java/info/nightscout/source/GlunovoPlugin.kt b/plugins/source/src/main/java/info/nightscout/source/GlunovoPlugin.kt index 367ac7580e..29cec010b6 100644 --- a/plugins/source/src/main/java/info/nightscout/source/GlunovoPlugin.kt +++ b/plugins/source/src/main/java/info/nightscout/source/GlunovoPlugin.kt @@ -148,7 +148,7 @@ class GlunovoPlugin @Inject constructor( .blockingGet() .also { savedValues -> savedValues.inserted.forEach { - xDripBroadcast.send(it) + xDripBroadcast.sendIn640gMode(it) aapsLogger.debug(LTag.DATABASE, "Inserted bg $it") } savedValues.calibrationsInserted.forEach { calibration -> diff --git a/plugins/source/src/main/java/info/nightscout/source/IntelligoPlugin.kt b/plugins/source/src/main/java/info/nightscout/source/IntelligoPlugin.kt index 25b4511871..a1f166ab7b 100644 --- a/plugins/source/src/main/java/info/nightscout/source/IntelligoPlugin.kt +++ b/plugins/source/src/main/java/info/nightscout/source/IntelligoPlugin.kt @@ -159,7 +159,7 @@ class IntelligoPlugin @Inject constructor( .blockingGet() .also { savedValues -> savedValues.inserted.forEach { - xDripBroadcast.send(it) + xDripBroadcast.sendIn640gMode(it) aapsLogger.debug(LTag.DATABASE, "Inserted bg $it") } savedValues.calibrationsInserted.forEach { calibration -> diff --git a/plugins/source/src/main/java/info/nightscout/source/MM640gPlugin.kt b/plugins/source/src/main/java/info/nightscout/source/MM640gPlugin.kt index 2a6e78de14..78440fd2de 100644 --- a/plugins/source/src/main/java/info/nightscout/source/MM640gPlugin.kt +++ b/plugins/source/src/main/java/info/nightscout/source/MM640gPlugin.kt @@ -90,7 +90,7 @@ class MM640gPlugin @Inject constructor( .blockingGet() .also { savedValues -> savedValues.all().forEach { - xDripBroadcast.send(it) + xDripBroadcast.sendIn640gMode(it) aapsLogger.debug(LTag.DATABASE, "Inserted bg $it") } } diff --git a/plugins/source/src/main/java/info/nightscout/source/NSClientSourcePlugin.kt b/plugins/source/src/main/java/info/nightscout/source/NSClientSourcePlugin.kt index 05ae35c21a..9863eff071 100644 --- a/plugins/source/src/main/java/info/nightscout/source/NSClientSourcePlugin.kt +++ b/plugins/source/src/main/java/info/nightscout/source/NSClientSourcePlugin.kt @@ -150,7 +150,6 @@ class NSClientSourcePlugin @Inject constructor( } } else if (sgvs is List<*>) { // V3 client -// xDripBroadcast.sendSgvs(sgvs) for (i in 0 until sgvs.size) { val sgv = toGv(sgvs[i] as NSSgvV3) diff --git a/plugins/source/src/main/java/info/nightscout/source/PoctechPlugin.kt b/plugins/source/src/main/java/info/nightscout/source/PoctechPlugin.kt index a90bf8fbd3..ff20504e27 100644 --- a/plugins/source/src/main/java/info/nightscout/source/PoctechPlugin.kt +++ b/plugins/source/src/main/java/info/nightscout/source/PoctechPlugin.kt @@ -83,7 +83,7 @@ class PoctechPlugin @Inject constructor( .blockingGet() .also { savedValues -> savedValues.inserted.forEach { - xDripBroadcast.send(it) + xDripBroadcast.sendIn640gMode(it) aapsLogger.debug(LTag.DATABASE, "Inserted bg $it") } } diff --git a/plugins/source/src/main/java/info/nightscout/source/RandomBgPlugin.kt b/plugins/source/src/main/java/info/nightscout/source/RandomBgPlugin.kt index 5888ec983b..c1b14e5a54 100644 --- a/plugins/source/src/main/java/info/nightscout/source/RandomBgPlugin.kt +++ b/plugins/source/src/main/java/info/nightscout/source/RandomBgPlugin.kt @@ -119,7 +119,7 @@ class RandomBgPlugin @Inject constructor( disposable += repository.runTransactionForResult(CgmSourceTransaction(glucoseValues, emptyList(), null)) .subscribe({ savedValues -> savedValues.inserted.forEach { - xDripBroadcast.send(it) + xDripBroadcast.sendIn640gMode(it) aapsLogger.debug(LTag.DATABASE, "Inserted bg $it") } }, { aapsLogger.error(LTag.DATABASE, "Error while saving values from Random plugin", it) } diff --git a/plugins/source/src/main/java/info/nightscout/source/TomatoPlugin.kt b/plugins/source/src/main/java/info/nightscout/source/TomatoPlugin.kt index d6e23238bb..bf7fd2c0cf 100644 --- a/plugins/source/src/main/java/info/nightscout/source/TomatoPlugin.kt +++ b/plugins/source/src/main/java/info/nightscout/source/TomatoPlugin.kt @@ -74,7 +74,7 @@ class TomatoPlugin @Inject constructor( .blockingGet() .also { savedValues -> savedValues.inserted.forEach { - xDripBroadcast.send(it) + xDripBroadcast.sendIn640gMode(it) aapsLogger.debug(LTag.DATABASE, "Inserted bg $it") } } diff --git a/plugins/sync/src/main/java/info/nightscout/plugins/sync/di/SyncModule.kt b/plugins/sync/src/main/java/info/nightscout/plugins/sync/di/SyncModule.kt index 84fa420c96..731d4b729a 100644 --- a/plugins/sync/src/main/java/info/nightscout/plugins/sync/di/SyncModule.kt +++ b/plugins/sync/src/main/java/info/nightscout/plugins/sync/di/SyncModule.kt @@ -7,6 +7,7 @@ import dagger.Module import dagger.Provides import dagger.Reusable import dagger.android.ContributesAndroidInjector +import info.nightscout.interfaces.XDripBroadcast import info.nightscout.interfaces.nsclient.NSSettingsStatus import info.nightscout.interfaces.nsclient.ProcessedDeviceStatusData import info.nightscout.interfaces.nsclient.StoreDataForDb @@ -32,6 +33,7 @@ import info.nightscout.plugins.sync.nsclientV3.workers.LoadTreatmentsWorker import info.nightscout.plugins.sync.nsclientV3.workers.ProcessFoodWorker import info.nightscout.plugins.sync.nsclientV3.workers.ProcessTreatmentsWorker import info.nightscout.plugins.sync.tidepool.TidepoolFragment +import info.nightscout.plugins.sync.xdrip.XdripPlugin @Module( includes = [ @@ -80,6 +82,7 @@ abstract class SyncModule { @Binds fun bindNSSettingsStatus(nsSettingsStatusImpl: NSSettingsStatusImpl): NSSettingsStatus @Binds fun bindDataSyncSelectorInterface(dataSyncSelectorImplementation: DataSyncSelectorImplementation): DataSyncSelector @Binds fun bindStoreDataForDb(storeDataForDbImpl: StoreDataForDbImpl): StoreDataForDb + @Binds fun bindXDripBroadcastInterface(xDripBroadcastImpl: XdripPlugin): XDripBroadcast } } \ No newline at end of file diff --git a/plugins/sync/src/main/java/info/nightscout/plugins/sync/nsShared/StoreDataForDbImpl.kt b/plugins/sync/src/main/java/info/nightscout/plugins/sync/nsShared/StoreDataForDbImpl.kt index 8378a9fee6..68f4dd170a 100644 --- a/plugins/sync/src/main/java/info/nightscout/plugins/sync/nsShared/StoreDataForDbImpl.kt +++ b/plugins/sync/src/main/java/info/nightscout/plugins/sync/nsShared/StoreDataForDbImpl.kt @@ -163,19 +163,19 @@ class StoreDataForDbImpl @Inject constructor( .also { result -> glucoseValues.clear() result.updated.forEach { - xDripBroadcast.send(it) + xDripBroadcast.sendIn640gMode(it) nsClientSource.detectSource(it) aapsLogger.debug(LTag.DATABASE, "Updated bg $it") updated.inc(GlucoseValue::class.java.simpleName) } result.inserted.forEach { - xDripBroadcast.send(it) + xDripBroadcast.sendIn640gMode(it) nsClientSource.detectSource(it) aapsLogger.debug(LTag.DATABASE, "Inserted bg $it") inserted.inc(GlucoseValue::class.java.simpleName) } result.updatedNsId.forEach { - xDripBroadcast.send(it) + xDripBroadcast.sendIn640gMode(it) nsClientSource.detectSource(it) aapsLogger.debug(LTag.DATABASE, "Updated nsId bg $it") nsIdUpdated.inc(GlucoseValue::class.java.simpleName) diff --git a/plugins/sync/src/main/java/info/nightscout/plugins/sync/xdrip/XdripPlugin.kt b/plugins/sync/src/main/java/info/nightscout/plugins/sync/xdrip/XdripPlugin.kt index 785cde4be5..99b166862a 100644 --- a/plugins/sync/src/main/java/info/nightscout/plugins/sync/xdrip/XdripPlugin.kt +++ b/plugins/sync/src/main/java/info/nightscout/plugins/sync/xdrip/XdripPlugin.kt @@ -7,7 +7,21 @@ import dagger.android.HasAndroidInjector import info.nightscout.core.extensions.toStringShort import info.nightscout.core.iob.generateCOBString import info.nightscout.core.iob.round +import info.nightscout.core.ui.toast.ToastUtils import info.nightscout.core.utils.fabric.FabricPrivacy +import info.nightscout.database.entities.Bolus +import info.nightscout.database.entities.Carbs +import info.nightscout.database.entities.DeviceStatus +import info.nightscout.database.entities.EffectiveProfileSwitch +import info.nightscout.database.entities.ExtendedBolus +import info.nightscout.database.entities.GlucoseValue +import info.nightscout.database.entities.OfflineEvent +import info.nightscout.database.entities.ProfileSwitch +import info.nightscout.database.entities.TemporaryBasal +import info.nightscout.database.entities.TemporaryTarget +import info.nightscout.database.entities.TherapyEvent +import info.nightscout.interfaces.GlucoseUnit +import info.nightscout.interfaces.XDripBroadcast import info.nightscout.interfaces.aps.Loop import info.nightscout.interfaces.iob.IobCobCalculator import info.nightscout.interfaces.plugin.PluginBase @@ -15,23 +29,27 @@ import info.nightscout.interfaces.plugin.PluginDescription import info.nightscout.interfaces.plugin.PluginType import info.nightscout.interfaces.profile.Profile import info.nightscout.interfaces.profile.ProfileFunction +import info.nightscout.interfaces.receivers.Intents import info.nightscout.interfaces.utils.DecimalFormatter import info.nightscout.plugins.sync.R import info.nightscout.rx.AapsSchedulers import info.nightscout.rx.bus.RxBus import info.nightscout.rx.events.EventAppInitialized import info.nightscout.rx.events.EventAutosensCalculationFinished -import info.nightscout.rx.events.EventConfigBuilderChange -import info.nightscout.rx.events.EventExtendedBolusChange -import info.nightscout.rx.events.EventPreferenceChange +import info.nightscout.rx.events.EventNewHistoryData import info.nightscout.rx.events.EventRefreshOverview -import info.nightscout.rx.events.EventTempBasalChange -import info.nightscout.rx.events.EventTreatmentChange import info.nightscout.rx.logging.AAPSLogger +import info.nightscout.rx.logging.LTag +import info.nightscout.shared.extensions.safeQueryBroadcastReceivers import info.nightscout.shared.interfaces.ResourceHelper import info.nightscout.shared.sharedPreferences.SP import io.reactivex.rxjava3.disposables.CompositeDisposable import io.reactivex.rxjava3.kotlin.plusAssign +import org.json.JSONArray +import org.json.JSONException +import org.json.JSONObject +import java.text.SimpleDateFormat +import java.util.Locale import javax.inject.Inject import javax.inject.Singleton @@ -58,65 +76,40 @@ class XdripPlugin @Inject constructor( .preferencesId(R.xml.pref_xdrip) .description(R.string.description_xdrip), aapsLogger, rh, injector -) { +), XDripBroadcast { private val disposable = CompositeDisposable() private var lastLoopStatus = false - companion object { - - //broadcast related constants - @Suppress("SpellCheckingInspection") - private const val EXTRA_STATUSLINE = "com.eveningoutpost.dexdrip.Extras.Statusline" - - @Suppress("SpellCheckingInspection") - private const val ACTION_NEW_EXTERNAL_STATUSLINE = "com.eveningoutpost.dexdrip.ExternalStatusline" - - @Suppress("SpellCheckingInspection", "unused") - private const val RECEIVER_PERMISSION = "com.eveningoutpost.dexdrip.permissions.RECEIVE_EXTERNAL_STATUSLINE" - } - override fun onStart() { super.onStart() disposable += rxBus.toObservable(EventRefreshOverview::class.java) .observeOn(aapsSchedulers.io) - .subscribe({ if (lastLoopStatus != (loop as PluginBase).isEnabled()) sendStatus() }, fabricPrivacy::logException) - disposable += rxBus.toObservable(EventExtendedBolusChange::class.java) + .subscribe({ if (lastLoopStatus != loop.isEnabled()) sendStatusLine() }, fabricPrivacy::logException) + disposable += rxBus.toObservable(EventNewHistoryData::class.java) .observeOn(aapsSchedulers.io) - .subscribe({ sendStatus() }, fabricPrivacy::logException) - disposable += rxBus.toObservable(EventTempBasalChange::class.java) - .observeOn(aapsSchedulers.io) - .subscribe({ sendStatus() }, fabricPrivacy::logException) - disposable += rxBus.toObservable(EventTreatmentChange::class.java) - .observeOn(aapsSchedulers.io) - .subscribe({ sendStatus() }, fabricPrivacy::logException) - disposable += rxBus.toObservable(EventConfigBuilderChange::class.java) - .observeOn(aapsSchedulers.io) - .subscribe({ sendStatus() }, fabricPrivacy::logException) + .subscribe({ sendStatusLine() }, fabricPrivacy::logException) disposable += rxBus.toObservable(EventAutosensCalculationFinished::class.java) .observeOn(aapsSchedulers.io) - .subscribe({ sendStatus() }, fabricPrivacy::logException) - disposable += rxBus.toObservable(EventPreferenceChange::class.java) - .observeOn(aapsSchedulers.io) - .subscribe({ sendStatus() }, fabricPrivacy::logException) + .subscribe({ sendStatusLine() }, fabricPrivacy::logException) disposable += rxBus.toObservable(EventAppInitialized::class.java) .observeOn(aapsSchedulers.io) - .subscribe({ sendStatus() }, fabricPrivacy::logException) + .subscribe({ sendStatusLine() }, fabricPrivacy::logException) } override fun onStop() { super.onStop() disposable.clear() - sendStatus() + sendStatusLine() } - private fun sendStatus() { + private fun sendStatusLine() { if (sp.getBoolean(R.string.key_xdrip_send_status, false)) { val status = profileFunction.getProfile()?.let { buildStatusLine(it) } ?: "" context.sendBroadcast( - Intent(ACTION_NEW_EXTERNAL_STATUSLINE).also { + Intent(Intents.ACTION_NEW_EXTERNAL_STATUSLINE).also { it.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES) - it.putExtras(Bundle().apply { putString(EXTRA_STATUSLINE, status) }) + it.putExtras(Bundle().apply { putString(Intents.EXTRA_STATUSLINE, status) }) } ) } @@ -154,4 +147,176 @@ class XdripPlugin @Inject constructor( status.append(" ").append(iobCobCalculator.getCobInfo("StatusLinePlugin").generateCOBString()) return status.toString() } + + override fun sendCalibration(bg: Double): Boolean { + val bundle = Bundle() + bundle.putDouble("glucose_number", bg) + bundle.putString("units", if (profileFunction.getUnits() == GlucoseUnit.MGDL) "mgdl" else "mmol") + bundle.putLong("timestamp", System.currentTimeMillis()) + val intent = Intent(Intents.ACTION_REMOTE_CALIBRATION) + intent.putExtras(bundle) + intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES) + context.sendBroadcast(intent) + val q = context.packageManager.safeQueryBroadcastReceivers(intent, 0) + return if (q.isEmpty()) { + ToastUtils.errorToast(context, R.string.xdrip_not_installed) + aapsLogger.debug(rh.gs(R.string.xdrip_not_installed)) + false + } else { + ToastUtils.errorToast(context, R.string.calibration_sent) + aapsLogger.debug(rh.gs(R.string.calibration_sent)) + true + } + } + + // sent in 640G mode + // com.eveningoutpost.dexdrip.NSEmulatorReceiver + override fun sendIn640gMode(glucoseValue: GlucoseValue) { + if (sp.getBoolean(info.nightscout.core.utils.R.string.key_dexcomg5_xdripupload, false)) { + val format = SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ", Locale.US) + try { + val entriesBody = JSONArray() + val json = JSONObject() + json.put("sgv", glucoseValue.value) + json.put("direction", glucoseValue.trendArrow.text) + json.put("device", "G5") + json.put("type", "sgv") + json.put("date", glucoseValue.timestamp) + json.put("dateString", format.format(glucoseValue.timestamp)) + entriesBody.put(json) + val bundle = Bundle() + bundle.putString("action", "add") + bundle.putString("collection", "entries") + bundle.putString("data", entriesBody.toString()) + val intent = Intent(Intents.XDRIP_PLUS_NS_EMULATOR) + intent.putExtras(bundle).addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES) + context.sendBroadcast(intent) + val receivers = context.packageManager.safeQueryBroadcastReceivers(intent, 0) + if (receivers.isEmpty()) { + //NSUpload.log.debug("No xDrip receivers found. ") + aapsLogger.debug(LTag.BGSOURCE, "No xDrip receivers found.") + } else { + aapsLogger.debug(LTag.BGSOURCE, "${receivers.size} xDrip receivers") + } + } catch (e: JSONException) { + aapsLogger.error(LTag.BGSOURCE, "Unhandled exception", e) + } + } + } + + // sent in NSClient dbaccess mode + override fun sendProfile(profileStoreJson: JSONObject) { + if (sp.getBoolean(info.nightscout.core.utils.R.string.key_nsclient_localbroadcasts, false)) + broadcast( + Intent(Intents.ACTION_NEW_PROFILE).apply { + addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES) + putExtras(Bundle().apply { putString("profile", profileStoreJson.toString()) }) + } + ) + + } + + // sent in NSClient dbaccess mode + override fun sendTreatments(addedOrUpdatedTreatments: JSONArray) { + if (sp.getBoolean(info.nightscout.core.utils.R.string.key_nsclient_localbroadcasts, false)) + splitArray(addedOrUpdatedTreatments).forEach { part -> + broadcast( + Intent(Intents.ACTION_NEW_TREATMENT).apply { + addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES) + putExtras(Bundle().apply { putString("treatments", part.toString()) }) + } + ) + } + } + + // sent in NSClient dbaccess mode + override fun sendSgvs(sgvs: JSONArray) { + if (sp.getBoolean(info.nightscout.core.utils.R.string.key_nsclient_localbroadcasts, false)) + splitArray(sgvs).forEach { part -> + broadcast( + Intent(Intents.ACTION_NEW_SGV).apply { + addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES) + putExtras(Bundle().apply { putString("sgvs", part.toString()) }) + } + ) + } + } + + override fun send(gv: GlucoseValue) { + TODO("Not yet implemented") + } + + override fun send(bolus: Bolus) { + TODO("Not yet implemented") + } + + override fun send(carbs: Carbs) { + TODO("Not yet implemented") + } + + override fun send(tt: TemporaryTarget) { + TODO("Not yet implemented") + } + + override fun send(te: TherapyEvent) { + TODO("Not yet implemented") + } + + override fun send(deviceStatus: DeviceStatus) { + TODO("Not yet implemented") + } + + override fun send(tb: TemporaryBasal) { + TODO("Not yet implemented") + } + + override fun send(eb: ExtendedBolus) { + TODO("Not yet implemented") + } + + override fun send(ps: ProfileSwitch) { + TODO("Not yet implemented") + } + + override fun send(ps: EffectiveProfileSwitch) { + TODO("Not yet implemented") + } + + override fun send(ps: OfflineEvent) { + TODO("Not yet implemented") + } + + private fun splitArray(array: JSONArray): List { + var ret: MutableList = ArrayList() + try { + val size = array.length() + var count = 0 + var newarr: JSONArray? = null + for (i in 0 until size) { + if (count == 0) { + if (newarr != null) ret.add(newarr) + newarr = JSONArray() + count = 20 + } + newarr?.put(array[i]) + --count + } + if (newarr != null && newarr.length() > 0) ret.add(newarr) + } catch (e: JSONException) { + aapsLogger.error("Unhandled exception", e) + ret = ArrayList() + ret.add(array) + } + return ret + } + + private fun broadcast(intent: Intent) { + context.packageManager.safeQueryBroadcastReceivers(intent, 0).forEach { resolveInfo -> + resolveInfo.activityInfo.packageName?.let { + intent.setPackage(it) + context.sendBroadcast(intent) + aapsLogger.debug(LTag.CORE, "Sending broadcast " + intent.action + " to: " + it) + } + } + } } \ No newline at end of file diff --git a/plugins/sync/src/main/res/values/strings.xml b/plugins/sync/src/main/res/values/strings.xml index 404d3bfe83..ce19f868b7 100644 --- a/plugins/sync/src/main/res/values/strings.xml +++ b/plugins/sync/src/main/res/values/strings.xml @@ -165,6 +165,10 @@ Loop Disabled Send Status line to xDrip+ + xDrip+ not installed + Calibration sent to xDrip+ + + Data Broadcaster