From 6fbdda57164765f1212081f85b1d924feb824d1e Mon Sep 17 00:00:00 2001 From: Milos Kozak Date: Wed, 27 Jan 2021 15:40:13 +0100 Subject: [PATCH 01/84] force reset fabric upload --- core/src/main/res/values/strings.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/src/main/res/values/strings.xml b/core/src/main/res/values/strings.xml index 5ace811950..8a4d80bf2a 100644 --- a/core/src/main/res/values/strings.xml +++ b/core/src/main/res/values/strings.xml @@ -1,7 +1,7 @@ - enable_fabric + enable_fabric2 language units loop_openmode_min_change From 78974d045cf78c97a6eff01f6b5043bb4597b15f Mon Sep 17 00:00:00 2001 From: Milos Kozak Date: Wed, 27 Jan 2021 16:11:37 +0100 Subject: [PATCH 02/84] update certs --- app/src/main/assets/revoked_certs.txt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/app/src/main/assets/revoked_certs.txt b/app/src/main/assets/revoked_certs.txt index 103792a183..473b5d0322 100644 --- a/app/src/main/assets/revoked_certs.txt +++ b/app/src/main/assets/revoked_certs.txt @@ -4,4 +4,7 @@ 55:5D:70:C9:BE:10:41:7E:4B:01:A9:C4:C6:44:4A:F8:69:71:35:25:ED:95:23:16:C7:15:E8:EB:C6:08:FC:B1 # àqΣnΖ`ZϼγwÛ/τàΒϳ9Φ'$ΑϵžλUΛ`ÆÌΣЃA E0:71:A3:6E:96:60:5A:FC:B3:77:DB:2F:C4:E0:92:F3:39:A6:27:24:91:F5:7E:BB:55:9B:60:C6:CC:A3:03:41 +# 2ΙšÄΠΒϨÒÇeЄtЄЗž-*Ж*ZcHijЊÄœ<|x"Ε 32:99:61:C4:A0:92:E8:D2:C7:65:04:74:04:17:7E:2D:2A:16:2A:5A:63:48:69:6A:0A:C4:53:3C:7C:78:22:95 +# mςRr¡ЇζΛLφK&ĐΨ5CnЎϴPDñЍŒkϼ{ΨδwВb +6D:C2:52:72:A1:07:B6:9B:4C:C6:4B:26:10:A8:35:43:6E:0E:F4:50:44:F1:0D:52:6B:FC:7B:A8:B4:77:12:62 \ No newline at end of file From 59995419d4415b340eb14d944dfde041eca607e1 Mon Sep 17 00:00:00 2001 From: parapenT1sta Date: Sat, 30 Jan 2021 11:54:24 +0000 Subject: [PATCH 03/84] fix double space --- app/src/main/res/values/exam.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/res/values/exam.xml b/app/src/main/res/values/exam.xml index 99c87a2dc6..a5860ecd86 100644 --- a/app/src/main/res/values/exam.xml +++ b/app/src/main/res/values/exam.xml @@ -8,7 +8,7 @@ If you are satisfied that the value for DIA that you used in your pump prior to AndroidAPS worked well, there is no need to change this when you start looping. You should determine for yourself the appropriate value for DIA. Hypo Temp-Target - What is primary reason to set a hypo temp target? + What is primary reason to set a hypo temp target? To correct for hypos caused by incorrect basal rate settings. To prevent AndroidAPS from overcorrecting for a blood glucose rise caused by the fast acting carbs used to treat a hypo. To correct for a hypo induced as a result of exercise. From 1befbb278e4055d1234bd5eaf335a09c031a7d61 Mon Sep 17 00:00:00 2001 From: parapenT1sta Date: Sat, 30 Jan 2021 11:55:34 +0000 Subject: [PATCH 04/84] Update exam.xml --- app/src/main/res/values/exam.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/res/values/exam.xml b/app/src/main/res/values/exam.xml index a5860ecd86..98a216033d 100644 --- a/app/src/main/res/values/exam.xml +++ b/app/src/main/res/values/exam.xml @@ -48,7 +48,7 @@ Exercise and Profiles How can you use profiles to best help the system deal with aerobic exercise? Do a profile switch to less than 100%. - Do a profile switch to more than 100%.  + Do a profile switch to more than 100%. Leave the profile set to 100%. Suspend the loop. https://androidaps.readthedocs.io/en/latest/EN/Usage/temptarget.html#activity-temp-target From cd0f4d3b74919c106540ded709ab18e0f5a0b21d Mon Sep 17 00:00:00 2001 From: parapenT1sta Date: Sat, 30 Jan 2021 12:30:43 +0000 Subject: [PATCH 05/84] Update exam.xml --- app/src/main/res/values/exam.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/res/values/exam.xml b/app/src/main/res/values/exam.xml index 98a216033d..b5505d5f38 100644 --- a/app/src/main/res/values/exam.xml +++ b/app/src/main/res/values/exam.xml @@ -41,7 +41,7 @@ Noisy CGM Readings What should be done if CGM data is noisy? Do nothing - AndroidAPS will deal with it. - Disable the closed loop to avoid possible over- or underdosing. + Disable the closed loop to avoid possible over or underdosing. Replace consistently noisy or inaccurate sensors. Verify that your CGM app provides smoothed data. https://androidaps.readthedocs.io/en/latest/EN/Usage/Smoothing-Blood-Glucose-Data-in-xDrip.html#smoothing-blood-glucose-data From 71af958fca584ab498db67b0099b5378d89d3e87 Mon Sep 17 00:00:00 2001 From: Philoul Date: Sat, 30 Jan 2021 21:27:22 +0100 Subject: [PATCH 06/84] Replace Activity by -BGI in secondary graphs Align scales (IOB / Absolute) and (deviation / -BGI) if selected in the same graph --- .../historyBrowser/HistoryBrowseActivity.kt | 17 +++-- .../general/overview/OverviewFragment.kt | 14 ++-- .../plugins/general/overview/OverviewMenus.kt | 3 +- .../general/overview/graphData/GraphData.kt | 66 +++++++++++++++++-- app/src/main/res/values/strings.xml | 2 + 5 files changed, 83 insertions(+), 19 deletions(-) diff --git a/app/src/main/java/info/nightscout/androidaps/historyBrowser/HistoryBrowseActivity.kt b/app/src/main/java/info/nightscout/androidaps/historyBrowser/HistoryBrowseActivity.kt index e4b37130e4..9daf4d6e52 100644 --- a/app/src/main/java/info/nightscout/androidaps/historyBrowser/HistoryBrowseActivity.kt +++ b/app/src/main/java/info/nightscout/androidaps/historyBrowser/HistoryBrowseActivity.kt @@ -334,24 +334,27 @@ class HistoryBrowseActivity : NoSplashAppCompatActivity() { var useDevForScale = false var useRatioForScale = false var useDSForScale = false - var useIAForScale = false + var useBGIForScale = false var useABSForScale = false when { menuChartSettings[g + 1][OverviewMenus.CharType.IOB.ordinal] -> useIobForScale = true menuChartSettings[g + 1][OverviewMenus.CharType.COB.ordinal] -> useCobForScale = true menuChartSettings[g + 1][OverviewMenus.CharType.DEV.ordinal] -> useDevForScale = true menuChartSettings[g + 1][OverviewMenus.CharType.SEN.ordinal] -> useRatioForScale = true - menuChartSettings[g + 1][OverviewMenus.CharType.ACT.ordinal] -> useIAForScale = true + menuChartSettings[g + 1][OverviewMenus.CharType.BGI.ordinal] -> useBGIForScale = true menuChartSettings[g + 1][OverviewMenus.CharType.ABS.ordinal] -> useABSForScale = true menuChartSettings[g + 1][OverviewMenus.CharType.DEVSLOPE.ordinal] -> useDSForScale = true } - if (menuChartSettings[g + 1][OverviewMenus.CharType.IOB.ordinal]) secondGraphData.addIob(fromTime, toTime, useIobForScale, 1.0, menuChartSettings[g + 1][OverviewMenus.CharType.PRE.ordinal]) - if (menuChartSettings[g + 1][OverviewMenus.CharType.COB.ordinal]) secondGraphData.addCob(fromTime, toTime, useCobForScale, if (useCobForScale) 1.0 else 0.5) - if (menuChartSettings[g + 1][OverviewMenus.CharType.DEV.ordinal]) secondGraphData.addDeviations(fromTime, toTime, useDevForScale, 1.0) - if (menuChartSettings[g + 1][OverviewMenus.CharType.SEN.ordinal]) secondGraphData.addRatio(fromTime, toTime, useRatioForScale, 1.0) - if (menuChartSettings[g + 1][OverviewMenus.CharType.ACT.ordinal]) secondGraphData.addActivity(fromTime, toTime, useIAForScale, 0.8) + var alignIobScale = menuChartSettings[g + 1][OverviewMenus.CharType.ABS.ordinal] && menuChartSettings[g + 1][OverviewMenus.CharType.IOB.ordinal] + var alignDevBgiScale = menuChartSettings[g + 1][OverviewMenus.CharType.DEV.ordinal] && menuChartSettings[g + 1][OverviewMenus.CharType.BGI.ordinal] + if (menuChartSettings[g + 1][OverviewMenus.CharType.ABS.ordinal]) secondGraphData.addAbsIob(fromTime, toTime, useABSForScale, 1.0) + if (menuChartSettings[g + 1][OverviewMenus.CharType.IOB.ordinal]) secondGraphData.addIob(fromTime, toTime, useIobForScale, 1.0, menuChartSettings[g + 1][OverviewMenus.CharType.PRE.ordinal], alignIobScale) + if (menuChartSettings[g + 1][OverviewMenus.CharType.COB.ordinal]) secondGraphData.addCob(fromTime, toTime, useCobForScale, if (useCobForScale) 1.0 else 0.5) + if (menuChartSettings[g + 1][OverviewMenus.CharType.DEV.ordinal]) secondGraphData.addDeviations(fromTime, toTime, useDevForScale, 1.0, alignDevBgiScale) + if (menuChartSettings[g + 1][OverviewMenus.CharType.SEN.ordinal]) secondGraphData.addRatio(fromTime, toTime, useRatioForScale, 1.0) + if (menuChartSettings[g + 1][OverviewMenus.CharType.BGI.ordinal]) secondGraphData.addMinusBGI(fromTime, toTime, useBGIForScale, if (alignDevBgiScale) 1.0 else 0.8, alignDevBgiScale) if (menuChartSettings[g + 1][OverviewMenus.CharType.DEVSLOPE.ordinal] && buildHelper.isDev()) secondGraphData.addDeviationSlope(fromTime, toTime, useDSForScale, 1.0) // set manual x bounds to have nice steps diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/OverviewFragment.kt b/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/OverviewFragment.kt index a8c0b10866..57f8280ba0 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/OverviewFragment.kt +++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/OverviewFragment.kt @@ -877,23 +877,25 @@ class OverviewFragment : DaggerFragment(), View.OnClickListener, OnLongClickList var useDevForScale = false var useRatioForScale = false var useDSForScale = false - var useIAForScale = false + var useBGIForScale = false when { menuChartSettings[g + 1][OverviewMenus.CharType.ABS.ordinal] -> useABSForScale = true menuChartSettings[g + 1][OverviewMenus.CharType.IOB.ordinal] -> useIobForScale = true menuChartSettings[g + 1][OverviewMenus.CharType.COB.ordinal] -> useCobForScale = true menuChartSettings[g + 1][OverviewMenus.CharType.DEV.ordinal] -> useDevForScale = true menuChartSettings[g + 1][OverviewMenus.CharType.SEN.ordinal] -> useRatioForScale = true - menuChartSettings[g + 1][OverviewMenus.CharType.ACT.ordinal] -> useIAForScale = true + menuChartSettings[g + 1][OverviewMenus.CharType.BGI.ordinal] -> useBGIForScale = true menuChartSettings[g + 1][OverviewMenus.CharType.DEVSLOPE.ordinal] -> useDSForScale = true } + var alignIobScale = menuChartSettings[g + 1][OverviewMenus.CharType.ABS.ordinal] && menuChartSettings[g + 1][OverviewMenus.CharType.IOB.ordinal] + var alignDevBgiScale = menuChartSettings[g + 1][OverviewMenus.CharType.DEV.ordinal] && menuChartSettings[g + 1][OverviewMenus.CharType.BGI.ordinal] if (menuChartSettings[g + 1][OverviewMenus.CharType.ABS.ordinal]) secondGraphData.addAbsIob(fromTime, now, useABSForScale, 1.0) - if (menuChartSettings[g + 1][OverviewMenus.CharType.IOB.ordinal]) secondGraphData.addIob(fromTime, now, useIobForScale, 1.0, menuChartSettings[g + 1][OverviewMenus.CharType.PRE.ordinal]) + if (menuChartSettings[g + 1][OverviewMenus.CharType.IOB.ordinal]) secondGraphData.addIob(fromTime, now, useIobForScale, 1.0, menuChartSettings[g + 1][OverviewMenus.CharType.PRE.ordinal], alignIobScale) if (menuChartSettings[g + 1][OverviewMenus.CharType.COB.ordinal]) secondGraphData.addCob(fromTime, now, useCobForScale, if (useCobForScale) 1.0 else 0.5) - if (menuChartSettings[g + 1][OverviewMenus.CharType.DEV.ordinal]) secondGraphData.addDeviations(fromTime, now, useDevForScale, 1.0) + if (menuChartSettings[g + 1][OverviewMenus.CharType.DEV.ordinal]) secondGraphData.addDeviations(fromTime, now, useDevForScale, 1.0, alignDevBgiScale) if (menuChartSettings[g + 1][OverviewMenus.CharType.SEN.ordinal]) secondGraphData.addRatio(fromTime, now, useRatioForScale, 1.0) - if (menuChartSettings[g + 1][OverviewMenus.CharType.ACT.ordinal]) secondGraphData.addActivity(fromTime, endTime, useIAForScale, 0.8) + if (menuChartSettings[g + 1][OverviewMenus.CharType.BGI.ordinal]) secondGraphData.addMinusBGI(fromTime, endTime, useBGIForScale, if(alignDevBgiScale) 1.0 else 0.8, alignDevBgiScale) if (menuChartSettings[g + 1][OverviewMenus.CharType.DEVSLOPE.ordinal] && buildHelper.isDev()) secondGraphData.addDeviationSlope(fromTime, now, useDSForScale, 1.0) // set manual x bounds to have nice steps @@ -914,7 +916,7 @@ class OverviewFragment : DaggerFragment(), View.OnClickListener, OnLongClickList menuChartSettings[g + 1][OverviewMenus.CharType.COB.ordinal] || menuChartSettings[g + 1][OverviewMenus.CharType.DEV.ordinal] || menuChartSettings[g + 1][OverviewMenus.CharType.SEN.ordinal] || - menuChartSettings[g + 1][OverviewMenus.CharType.ACT.ordinal] || + menuChartSettings[g + 1][OverviewMenus.CharType.BGI.ordinal] || menuChartSettings[g + 1][OverviewMenus.CharType.DEVSLOPE.ordinal] ).toVisibility() secondaryGraphsData[g].performUpdate() diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/OverviewMenus.kt b/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/OverviewMenus.kt index af10d60f85..b2662f876b 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/OverviewMenus.kt +++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/OverviewMenus.kt @@ -40,7 +40,8 @@ class OverviewMenus @Inject constructor( COB(R.string.overview_show_cob, R.color.cob, primary = false, secondary = true,shortnameId = R.string.cob), DEV(R.string.overview_show_deviations, R.color.deviations, primary = false, secondary = true,shortnameId = R.string.deviation_shortname), SEN(R.string.overview_show_sensitivity, R.color.ratio, primary = false, secondary = true,shortnameId = R.string.sensitivity_shortname), - ACT(R.string.overview_show_activity, R.color.activity, primary = true, secondary = true,shortnameId = R.string.activity_shortname), + ACT(R.string.overview_show_activity, R.color.activity, primary = true, secondary = false,shortnameId = R.string.activity_shortname), + BGI(R.string.overview_show_bgi, R.color.activity, primary = false, secondary = true,shortnameId = R.string.bgi_shortname), DEVSLOPE(R.string.overview_show_deviationslope, R.color.devslopepos, primary = false, secondary = true,shortnameId = R.string.devslope_shortname) } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/graphData/GraphData.kt b/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/graphData/GraphData.kt index e5d0ff4fab..f8f066eb13 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/graphData/GraphData.kt +++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/graphData/GraphData.kt @@ -329,8 +329,51 @@ class GraphData( actScale.setMultiplier(maxY * scale / maxIAValue) } + //Function below show -BGI to be able to compare curves with deviations + fun addMinusBGI(fromTime: Long, toTime: Long, useForScale: Boolean, scale: Double, devBgiScale: Boolean) { + val bgiArrayHist: MutableList = ArrayList() + val bgiArrayPred: MutableList = ArrayList() + val now = System.currentTimeMillis().toDouble() + val bgiScale = Scale() + var total: IobTotal + var maxBGIValue = 0.0 + var time = fromTime + while (time <= toTime) { + val profile = profileFunction.getProfile(time) + if (profile == null) { + time += 5 * 60 * 1000L + continue + } + val deviation = if (devBgiScale) iobCobCalculatorPlugin.getAutosensData(time)?.deviation ?:0.0 else 0.0 + + total = iobCobCalculatorPlugin.calculateFromTreatmentsAndTempsSynchronized(time, profile) + val bgi: Double = total.activity * profile.getIsfMgdl(time) * 5.0 + if (time <= now) bgiArrayHist.add(ScaledDataPoint(time, bgi, bgiScale)) else bgiArrayPred.add(ScaledDataPoint(time, bgi, bgiScale)) + maxBGIValue = max(maxBGIValue, max(abs(bgi), deviation)) + time += 5 * 60 * 1000L + } + addSeries(FixedLineGraphSeries(Array(bgiArrayHist.size) { i -> bgiArrayHist[i] }).also { + it.isDrawBackground = false + it.color = resourceHelper.gc(R.color.activity) + it.thickness = 3 + }) + addSeries(FixedLineGraphSeries(Array(bgiArrayPred.size) { i -> bgiArrayPred[i] }).also { + it.setCustomPaint(Paint().also { paint -> + paint.style = Paint.Style.STROKE + paint.strokeWidth = 3f + paint.pathEffect = DashPathEffect(floatArrayOf(4f, 4f), 0f) + paint.color = resourceHelper.gc(R.color.activity) + }) + }) + if (useForScale) { + maxY = maxBGIValue + minY = -maxBGIValue + } + bgiScale.setMultiplier(maxY * scale / maxBGIValue) + } + // scale in % of vertical size (like 0.3) - fun addIob(fromTime: Long, toTime: Long, useForScale: Boolean, scale: Double, showPrediction: Boolean) { + fun addIob(fromTime: Long, toTime: Long, useForScale: Boolean, scale: Double, showPrediction: Boolean, absScale: Boolean) { val iobSeries: FixedLineGraphSeries val iobArray: MutableList = ArrayList() var maxIobValueFound = Double.MIN_VALUE @@ -340,11 +383,15 @@ class GraphData( while (time <= toTime) { val profile = profileFunction.getProfile(time) var iob = 0.0 - if (profile != null) iob = iobCobCalculatorPlugin.calculateFromTreatmentsAndTempsSynchronized(time, profile).iob + var absIob = 0.0 + if (profile != null) { + iob = iobCobCalculatorPlugin.calculateFromTreatmentsAndTempsSynchronized(time, profile).iob + if (absScale) absIob = iobCobCalculatorPlugin.calculateAbsInsulinFromTreatmentsAndTempsSynchronized(time, profile).iob + } if (abs(lastIob - iob) > 0.02) { if (abs(lastIob - iob) > 0.2) iobArray.add(ScaledDataPoint(time, lastIob, iobScale)) iobArray.add(ScaledDataPoint(time, iob, iobScale)) - maxIobValueFound = max(maxIobValueFound, abs(iob)) + maxIobValueFound = if (absScale) max(maxIobValueFound, abs(absIob)) else max(maxIobValueFound, abs(iob)) lastIob = iob } time += 5 * 60 * 1000L @@ -460,14 +507,23 @@ class GraphData( } // scale in % of vertical size (like 0.3) - fun addDeviations(fromTime: Long, toTime: Long, useForScale: Boolean, scale: Double) { + fun addDeviations(fromTime: Long, toTime: Long, useForScale: Boolean, scale: Double, devBgiScale: Boolean) { class DeviationDataPoint(x: Double, y: Double, var color: Int, scale: Scale) : ScaledDataPoint(x, y, scale) val devArray: MutableList = ArrayList() var maxDevValueFound = 0.0 val devScale = Scale() var time = fromTime + var total: IobTotal + while (time <= toTime) { + // if align Dev Scale with BGI scale, then calculate BGI value, else bgi = 0.0 + val bgi: Double = if (devBgiScale) { + val profile = profileFunction.getProfile(time) + total = iobCobCalculatorPlugin.calculateFromTreatmentsAndTempsSynchronized(time, profile) + total.activity * (profile?.getIsfMgdl(time) ?: 0.0) * 5.0 + } else 0.0 + iobCobCalculatorPlugin.getAutosensData(time)?.let { autosensData -> var color = resourceHelper.gc(R.color.deviationblack) // "=" if (autosensData.type == "" || autosensData.type == "non-meal") { @@ -480,7 +536,7 @@ class GraphData( color = resourceHelper.gc(R.color.deviationgrey) } devArray.add(DeviationDataPoint(time.toDouble(), autosensData.deviation, color, devScale)) - maxDevValueFound = max(maxDevValueFound, abs(autosensData.deviation)) + maxDevValueFound = max(maxDevValueFound, max(abs(autosensData.deviation), abs(bgi))) } time += 5 * 60 * 1000L } diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index eb8278a83c..7a2920919e 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -495,6 +495,7 @@ BAS DEV ACT + -BGI ABS DEVSLOPE About @@ -751,6 +752,7 @@ ns_autobackfill SMB set by pump Activity + Blood Glucose Impact Sensitivity Deviations Carbs On Board From 920cba5219737d8a92e553f7a785e6a86b88f377 Mon Sep 17 00:00:00 2001 From: Milos Kozak Date: Sat, 30 Jan 2021 22:34:05 +0100 Subject: [PATCH 07/84] DataService refactor --- app/src/main/AndroidManifest.xml | 4 - .../dependencyInjection/AppComponent.kt | 1 + .../dependencyInjection/ServicesModule.kt | 2 - .../dependencyInjection/WorkersModule.kt | 25 ++ .../general/nsclient/NSClientPlugin.java | 160 ++++++++++- .../general/nsclient/NSClientWorker.java | 39 +++ .../smsCommunicator/SmsCommunicatorPlugin.kt | 78 ++++-- .../plugins/profile/ns/NSProfilePlugin.kt | 50 ++-- .../androidaps/plugins/source/DexcomPlugin.kt | 153 ++++++----- .../plugins/source/EversensePlugin.kt | 164 +++++------ .../androidaps/plugins/source/GlimpPlugin.kt | 41 ++- .../androidaps/plugins/source/MM640gPlugin.kt | 68 +++-- .../plugins/source/NSClientSourcePlugin.kt | 71 +++-- .../plugins/source/PoctechPlugin.kt | 74 ++--- .../plugins/source/RandomBgPlugin.kt | 11 +- .../androidaps/plugins/source/TomatoPlugin.kt | 50 ++-- .../androidaps/plugins/source/XdripPlugin.kt | 50 ++-- .../androidaps/receivers/DataReceiver.kt | 116 +++++++- .../androidaps/services/DataService.java | 256 ------------------ .../utils/extensions/WorkerDataBuilder.kt | 16 ++ build.gradle | 2 +- .../interfaces/BgSourceInterface.java | 16 -- .../interfaces/BgSourceInterface.kt | 11 + 23 files changed, 836 insertions(+), 622 deletions(-) create mode 100644 app/src/main/java/info/nightscout/androidaps/dependencyInjection/WorkersModule.kt create mode 100644 app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/NSClientWorker.java delete mode 100644 app/src/main/java/info/nightscout/androidaps/services/DataService.java create mode 100644 app/src/main/java/info/nightscout/androidaps/utils/extensions/WorkerDataBuilder.kt delete mode 100644 core/src/main/java/info/nightscout/androidaps/interfaces/BgSourceInterface.java create mode 100644 core/src/main/java/info/nightscout/androidaps/interfaces/BgSourceInterface.kt diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 861ee368ca..ea9693236c 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -136,10 +136,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..54e1e68561 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/NSClientWorker.java @@ -0,0 +1,39 @@ +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 com.google.gson.Gson; + +import org.jetbrains.annotations.NotNull; + +import javax.inject.Inject; + +import dagger.android.HasAndroidInjector; + +// 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; + + @NotNull + @Override + public Result doWork() { + Bundle bundle = new Gson().fromJson(getInputData().getString("data"), Bundle.class); + 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 ed177167c1..68d1cf8243 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,18 +1,24 @@ package info.nightscout.androidaps.plugins.general.smsCommunicator -import android.content.Intent +import android.content.Context +import android.os.Bundle 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 com.google.gson.Gson 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.data.DetailedBolusInfo import info.nightscout.androidaps.data.Profile +import info.nightscout.androidaps.db.BgReading import info.nightscout.androidaps.db.Source import info.nightscout.androidaps.db.TempTarget import info.nightscout.androidaps.events.EventPreferenceChange @@ -23,6 +29,7 @@ import info.nightscout.androidaps.logging.LTag import info.nightscout.androidaps.plugins.aps.loop.LoopPlugin import info.nightscout.androidaps.plugins.bus.RxBusWrapper import info.nightscout.androidaps.plugins.configBuilder.ConstraintChecker +import info.nightscout.androidaps.plugins.general.nsclient.NSUpload import info.nightscout.androidaps.plugins.general.nsclient.events.EventNSClientRestart import info.nightscout.androidaps.plugins.general.overview.events.EventNewNotification import info.nightscout.androidaps.plugins.general.overview.notifications.Notification @@ -30,6 +37,7 @@ import info.nightscout.androidaps.plugins.general.smsCommunicator.events.EventSm import info.nightscout.androidaps.plugins.general.smsCommunicator.otp.OneTimePassword import info.nightscout.androidaps.plugins.iob.iobCobCalculator.GlucoseStatus import info.nightscout.androidaps.plugins.iob.iobCobCalculator.IobCobCalculatorPlugin +import info.nightscout.androidaps.plugins.source.PoctechPlugin import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin import info.nightscout.androidaps.queue.Callback import info.nightscout.androidaps.utils.* @@ -40,6 +48,8 @@ import info.nightscout.androidaps.utils.textValidator.ValidatingEditTextPreferen import io.reactivex.disposables.CompositeDisposable import io.reactivex.schedulers.Schedulers import org.apache.commons.lang3.StringUtils +import org.json.JSONArray +import org.json.JSONException import java.text.Normalizer import java.util.* import javax.inject.Inject @@ -151,6 +161,30 @@ 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 + + init { + (context.applicationContext as HasAndroidInjector).androidInjector().inject(this) + } + + override fun doWork(): Result { + val bundle = Gson().fromJson(inputData.getString("data"), Bundle::class.java) + 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, "") @@ -179,16 +213,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.") @@ -214,58 +238,58 @@ class SmsCommunicatorPlugin @Inject constructor( if (splitted.isNotEmpty() && isCommand(splitted[0].toUpperCase(Locale.getDefault()), receivedSms.phoneNumber)) { when (splitted[0].toUpperCase(Locale.getDefault())) { - "BG" -> + "BG" -> if (splitted.size == 1) processBG(receivedSms) else sendSMS(Sms(receivedSms.phoneNumber, resourceHelper.gs(R.string.wrongformat))) - "LOOP" -> + "LOOP" -> if (!remoteCommandsAllowed) sendSMS(Sms(receivedSms.phoneNumber, resourceHelper.gs(R.string.smscommunicator_remotecommandnotallowed))) else if (splitted.size == 2 || splitted.size == 3) processLOOP(splitted, receivedSms) else sendSMS(Sms(receivedSms.phoneNumber, resourceHelper.gs(R.string.wrongformat))) "TREATMENTS" -> if (splitted.size == 2) processTREATMENTS(splitted, receivedSms) else sendSMS(Sms(receivedSms.phoneNumber, resourceHelper.gs(R.string.wrongformat))) - "NSCLIENT" -> + "NSCLIENT" -> if (splitted.size == 2) processNSCLIENT(splitted, receivedSms) else sendSMS(Sms(receivedSms.phoneNumber, resourceHelper.gs(R.string.wrongformat))) - "PUMP" -> + "PUMP" -> if (!remoteCommandsAllowed && splitted.size > 1) sendSMS(Sms(receivedSms.phoneNumber, resourceHelper.gs(R.string.smscommunicator_remotecommandnotallowed))) else if (splitted.size <= 3) processPUMP(splitted, receivedSms) else sendSMS(Sms(receivedSms.phoneNumber, resourceHelper.gs(R.string.wrongformat))) - "PROFILE" -> + "PROFILE" -> if (!remoteCommandsAllowed) sendSMS(Sms(receivedSms.phoneNumber, resourceHelper.gs(R.string.smscommunicator_remotecommandnotallowed))) else if (splitted.size == 2 || splitted.size == 3) processPROFILE(splitted, receivedSms) else sendSMS(Sms(receivedSms.phoneNumber, resourceHelper.gs(R.string.wrongformat))) - "BASAL" -> + "BASAL" -> if (!remoteCommandsAllowed) sendSMS(Sms(receivedSms.phoneNumber, resourceHelper.gs(R.string.smscommunicator_remotecommandnotallowed))) else if (splitted.size == 2 || splitted.size == 3) processBASAL(splitted, receivedSms) else sendSMS(Sms(receivedSms.phoneNumber, resourceHelper.gs(R.string.wrongformat))) - "EXTENDED" -> + "EXTENDED" -> if (!remoteCommandsAllowed) sendSMS(Sms(receivedSms.phoneNumber, resourceHelper.gs(R.string.smscommunicator_remotecommandnotallowed))) else if (splitted.size == 2 || splitted.size == 3) processEXTENDED(splitted, receivedSms) else sendSMS(Sms(receivedSms.phoneNumber, resourceHelper.gs(R.string.wrongformat))) - "BOLUS" -> + "BOLUS" -> if (!remoteCommandsAllowed) sendSMS(Sms(receivedSms.phoneNumber, resourceHelper.gs(R.string.smscommunicator_remotecommandnotallowed))) else if (splitted.size == 2 && DateUtil.now() - lastRemoteBolusTime < minDistance) sendSMS(Sms(receivedSms.phoneNumber, resourceHelper.gs(R.string.smscommunicator_remotebolusnotallowed))) else if (splitted.size == 2 && pump.isSuspended) sendSMS(Sms(receivedSms.phoneNumber, resourceHelper.gs(R.string.pumpsuspended))) else if (splitted.size == 2 || splitted.size == 3) processBOLUS(splitted, receivedSms) else sendSMS(Sms(receivedSms.phoneNumber, resourceHelper.gs(R.string.wrongformat))) - "CARBS" -> + "CARBS" -> if (!remoteCommandsAllowed) sendSMS(Sms(receivedSms.phoneNumber, resourceHelper.gs(R.string.smscommunicator_remotecommandnotallowed))) else if (splitted.size == 2 || splitted.size == 3) processCARBS(splitted, receivedSms) else sendSMS(Sms(receivedSms.phoneNumber, resourceHelper.gs(R.string.wrongformat))) - "CAL" -> + "CAL" -> if (!remoteCommandsAllowed) sendSMS(Sms(receivedSms.phoneNumber, resourceHelper.gs(R.string.smscommunicator_remotecommandnotallowed))) else if (splitted.size == 2) processCAL(splitted, receivedSms) else sendSMS(Sms(receivedSms.phoneNumber, resourceHelper.gs(R.string.wrongformat))) - "TARGET" -> + "TARGET" -> if (!remoteCommandsAllowed) sendSMS(Sms(receivedSms.phoneNumber, resourceHelper.gs(R.string.smscommunicator_remotecommandnotallowed))) else if (splitted.size == 2) processTARGET(splitted, receivedSms) else sendSMS(Sms(receivedSms.phoneNumber, resourceHelper.gs(R.string.wrongformat))) - "SMS" -> + "SMS" -> if (!remoteCommandsAllowed) sendSMS(Sms(receivedSms.phoneNumber, resourceHelper.gs(R.string.smscommunicator_remotecommandnotallowed))) else if (splitted.size == 2) processSMS(splitted, receivedSms) else sendSMS(Sms(receivedSms.phoneNumber, resourceHelper.gs(R.string.wrongformat))) - "HELP" -> + "HELP" -> if (splitted.size == 1 || splitted.size == 2) processHELP(splitted, receivedSms) else sendSMS(Sms(receivedSms.phoneNumber, resourceHelper.gs(R.string.wrongformat))) else -> @@ -349,7 +373,7 @@ class SmsCommunicatorPlugin @Inject constructor( receivedSms.processed = true } - "STATUS" -> { + "STATUS" -> { val reply = if (loopPlugin.isEnabled(PluginType.LOOP)) { if (loopPlugin.isSuspended) String.format(resourceHelper.gs(R.string.loopsuspendedfor), loopPlugin.minutesToEndOfSuspend()) else resourceHelper.gs(R.string.smscommunicator_loopisenabled) @@ -359,7 +383,7 @@ class SmsCommunicatorPlugin @Inject constructor( receivedSms.processed = true } - "RESUME" -> { + "RESUME" -> { val passCode = generatePasscode() val reply = String.format(resourceHelper.gs(R.string.smscommunicator_loopresumereplywithcode), passCode) receivedSms.processed = true @@ -383,7 +407,7 @@ class SmsCommunicatorPlugin @Inject constructor( }) } - "SUSPEND" -> { + "SUSPEND" -> { var duration = 0 if (splitted.size == 3) duration = SafeParse.stringToInt(splitted[2]) duration = Math.max(0, duration) 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..c8b74398f9 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,13 @@ package info.nightscout.androidaps.plugins.source +import android.content.Context import android.content.Intent import android.content.pm.PackageManager +import android.os.Bundle import androidx.core.content.ContextCompat +import androidx.work.Worker +import androidx.work.WorkerParameters +import com.google.gson.Gson import dagger.android.HasAndroidInjector import info.nightscout.androidaps.Config import info.nightscout.androidaps.Constants @@ -29,11 +34,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 +76,102 @@ 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 + + init { + (context.applicationContext as HasAndroidInjector).androidInjector().inject(this) + } + + override fun doWork(): Result { + if (!dexcomPlugin.isEnabled(PluginType.BGSOURCE)) return Result.failure() + val action = inputData.getString("action") + val bundle = Gson().fromJson(inputData.getString("data"), Bundle::class.java) + 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..9e4af176bc 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,10 @@ package info.nightscout.androidaps.plugins.source -import android.content.Intent +import android.content.Context +import android.os.Bundle +import androidx.work.Worker +import androidx.work.WorkerParameters +import com.google.gson.Gson import dagger.android.HasAndroidInjector import info.nightscout.androidaps.Constants import info.nightscout.androidaps.MainApp @@ -26,11 +30,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 +43,96 @@ 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 + + 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 = Gson().fromJson(inputData.getString("data"), Bundle::class.java) + 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/DataReceiver.kt b/app/src/main/java/info/nightscout/androidaps/receivers/DataReceiver.kt index b5fd362e57..b9f0374fe9 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,117 @@ 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 com.google.gson.Gson +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 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 + 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.putString("data", Gson().toJson(bundle)) + it.putString("action", intent.action) + }.build()).build() + Intents.EVERSENSE_BG -> + OneTimeWorkRequest.Builder(EversensePlugin.EversenseWorker::class.java) + .setInputData(Data.Builder().also { + it.putString("data", Gson().toJson(bundle)) + it.putString("action", intent.action) + }.build()).build() + Intents.DEXCOM_BG -> + OneTimeWorkRequest.Builder(DexcomPlugin.DexcomWorker::class.java) + .setInputData(Data.Builder().also { + it.putString("data", Gson().toJson(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.putString("data", Gson().toJson(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 87f1d32bd3..f237879017 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 From acf3b23bf7b5f8126bf0ffa043fb249cdacbe577 Mon Sep 17 00:00:00 2001 From: Milos Kozak Date: Mon, 1 Feb 2021 15:24:48 +0100 Subject: [PATCH 08/84] cleanup --- .../general/smsCommunicator/AuthRequest.kt | 11 +- .../smsCommunicator/SmsCommunicatorPlugin.kt | 279 +++++++++--------- .../smsCommunicator/otp/OneTimePassword.kt | 15 - app/src/main/res/values/strings.xml | 3 - app/src/main/res/xml/pref_smscommunicator.xml | 8 - 5 files changed, 139 insertions(+), 177 deletions(-) diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/smsCommunicator/AuthRequest.kt b/app/src/main/java/info/nightscout/androidaps/plugins/general/smsCommunicator/AuthRequest.kt index 942613c872..ae454e1f2b 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/general/smsCommunicator/AuthRequest.kt +++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/smsCommunicator/AuthRequest.kt @@ -21,7 +21,7 @@ class AuthRequest internal constructor( @Inject lateinit var aapsLogger: AAPSLogger @Inject lateinit var smsCommunicatorPlugin: SmsCommunicatorPlugin @Inject lateinit var resourceHelper: ResourceHelper - @Inject lateinit var otp : OneTimePassword + @Inject lateinit var otp: OneTimePassword private val date = DateUtil.now() private var processed = false @@ -31,13 +31,8 @@ class AuthRequest internal constructor( smsCommunicatorPlugin.sendSMS(Sms(requester.phoneNumber, requestText)) } - private fun codeIsValid(toValidate: String) : Boolean { - return if (otp.isEnabled()) { - otp.checkOTP(toValidate) == OneTimePasswordValidationResult.OK - } else { - confirmCode == toValidate - } - } + private fun codeIsValid(toValidate: String): Boolean = + otp.checkOTP(toValidate) == OneTimePasswordValidationResult.OK fun action(codeReceived: String) { if (processed) { 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 ed177167c1..ca2db7303e 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 @@ -44,6 +44,8 @@ import java.text.Normalizer import java.util.* import javax.inject.Inject import javax.inject.Singleton +import kotlin.math.max +import kotlin.math.min @Singleton class SmsCommunicatorPlugin @Inject constructor( @@ -144,8 +146,7 @@ class SmsCommunicatorPlugin @Inject constructor( override fun updatePreferenceSummary(pref: Preference) { super.updatePreferenceSummary(pref) if (pref is EditTextPreference) { - val editTextPref = pref - if (pref.getKey().contains("smscommunicator_allowednumbers") && (editTextPref.text == null || TextUtils.isEmpty(editTextPref.text.trim { it <= ' ' }))) { + if (pref.getKey().contains("smscommunicator_allowednumbers") && (pref.text == null || TextUtils.isEmpty(pref.text.trim { it <= ' ' }))) { pref.setSummary(resourceHelper.gs(R.string.smscommunicator_allowednumbers_summary)) } } @@ -204,7 +205,7 @@ class SmsCommunicatorPlugin @Inject constructor( val pump = activePlugin.activePump messages.add(receivedSms) aapsLogger.debug(LTag.SMS, receivedSms.toString()) - val splitted = receivedSms.text.split(Regex("\\s+")).toTypedArray() + val divided = receivedSms.text.split(Regex("\\s+")).toTypedArray() val remoteCommandsAllowed = sp.getBoolean(R.string.key_smscommunicator_remotecommandsallowed, false) val minDistance = @@ -212,65 +213,65 @@ class SmsCommunicatorPlugin @Inject constructor( T.mins(sp.getLong(R.string.key_smscommunicator_remotebolusmindistance, T.msecs(Constants.remoteBolusMinDistance).mins())).msecs() else Constants.remoteBolusMinDistance - if (splitted.isNotEmpty() && isCommand(splitted[0].toUpperCase(Locale.getDefault()), receivedSms.phoneNumber)) { - when (splitted[0].toUpperCase(Locale.getDefault())) { - "BG" -> - if (splitted.size == 1) processBG(receivedSms) + if (divided.isNotEmpty() && isCommand(divided[0].toUpperCase(Locale.getDefault()), receivedSms.phoneNumber)) { + when (divided[0].toUpperCase(Locale.getDefault())) { + "BG" -> + if (divided.size == 1) processBG(receivedSms) else sendSMS(Sms(receivedSms.phoneNumber, resourceHelper.gs(R.string.wrongformat))) - "LOOP" -> + "LOOP" -> if (!remoteCommandsAllowed) sendSMS(Sms(receivedSms.phoneNumber, resourceHelper.gs(R.string.smscommunicator_remotecommandnotallowed))) - else if (splitted.size == 2 || splitted.size == 3) processLOOP(splitted, receivedSms) + else if (divided.size == 2 || divided.size == 3) processLOOP(divided, receivedSms) else sendSMS(Sms(receivedSms.phoneNumber, resourceHelper.gs(R.string.wrongformat))) "TREATMENTS" -> - if (splitted.size == 2) processTREATMENTS(splitted, receivedSms) + if (divided.size == 2) processTREATMENTS(divided, receivedSms) else sendSMS(Sms(receivedSms.phoneNumber, resourceHelper.gs(R.string.wrongformat))) - "NSCLIENT" -> - if (splitted.size == 2) processNSCLIENT(splitted, receivedSms) + "NSCLIENT" -> + if (divided.size == 2) processNSCLIENT(divided, receivedSms) else sendSMS(Sms(receivedSms.phoneNumber, resourceHelper.gs(R.string.wrongformat))) - "PUMP" -> - if (!remoteCommandsAllowed && splitted.size > 1) sendSMS(Sms(receivedSms.phoneNumber, resourceHelper.gs(R.string.smscommunicator_remotecommandnotallowed))) - else if (splitted.size <= 3) processPUMP(splitted, receivedSms) + "PUMP" -> + if (!remoteCommandsAllowed && divided.size > 1) sendSMS(Sms(receivedSms.phoneNumber, resourceHelper.gs(R.string.smscommunicator_remotecommandnotallowed))) + else if (divided.size <= 3) processPUMP(divided, receivedSms) else sendSMS(Sms(receivedSms.phoneNumber, resourceHelper.gs(R.string.wrongformat))) - "PROFILE" -> + "PROFILE" -> if (!remoteCommandsAllowed) sendSMS(Sms(receivedSms.phoneNumber, resourceHelper.gs(R.string.smscommunicator_remotecommandnotallowed))) - else if (splitted.size == 2 || splitted.size == 3) processPROFILE(splitted, receivedSms) + else if (divided.size == 2 || divided.size == 3) processPROFILE(divided, receivedSms) else sendSMS(Sms(receivedSms.phoneNumber, resourceHelper.gs(R.string.wrongformat))) - "BASAL" -> + "BASAL" -> if (!remoteCommandsAllowed) sendSMS(Sms(receivedSms.phoneNumber, resourceHelper.gs(R.string.smscommunicator_remotecommandnotallowed))) - else if (splitted.size == 2 || splitted.size == 3) processBASAL(splitted, receivedSms) + else if (divided.size == 2 || divided.size == 3) processBASAL(divided, receivedSms) else sendSMS(Sms(receivedSms.phoneNumber, resourceHelper.gs(R.string.wrongformat))) - "EXTENDED" -> + "EXTENDED" -> if (!remoteCommandsAllowed) sendSMS(Sms(receivedSms.phoneNumber, resourceHelper.gs(R.string.smscommunicator_remotecommandnotallowed))) - else if (splitted.size == 2 || splitted.size == 3) processEXTENDED(splitted, receivedSms) + else if (divided.size == 2 || divided.size == 3) processEXTENDED(divided, receivedSms) else sendSMS(Sms(receivedSms.phoneNumber, resourceHelper.gs(R.string.wrongformat))) - "BOLUS" -> + "BOLUS" -> if (!remoteCommandsAllowed) sendSMS(Sms(receivedSms.phoneNumber, resourceHelper.gs(R.string.smscommunicator_remotecommandnotallowed))) - else if (splitted.size == 2 && DateUtil.now() - lastRemoteBolusTime < minDistance) sendSMS(Sms(receivedSms.phoneNumber, resourceHelper.gs(R.string.smscommunicator_remotebolusnotallowed))) - else if (splitted.size == 2 && pump.isSuspended) sendSMS(Sms(receivedSms.phoneNumber, resourceHelper.gs(R.string.pumpsuspended))) - else if (splitted.size == 2 || splitted.size == 3) processBOLUS(splitted, receivedSms) + else if (divided.size == 2 && DateUtil.now() - lastRemoteBolusTime < minDistance) sendSMS(Sms(receivedSms.phoneNumber, resourceHelper.gs(R.string.smscommunicator_remotebolusnotallowed))) + else if (divided.size == 2 && pump.isSuspended) sendSMS(Sms(receivedSms.phoneNumber, resourceHelper.gs(R.string.pumpsuspended))) + else if (divided.size == 2 || divided.size == 3) processBOLUS(divided, receivedSms) else sendSMS(Sms(receivedSms.phoneNumber, resourceHelper.gs(R.string.wrongformat))) - "CARBS" -> + "CARBS" -> if (!remoteCommandsAllowed) sendSMS(Sms(receivedSms.phoneNumber, resourceHelper.gs(R.string.smscommunicator_remotecommandnotallowed))) - else if (splitted.size == 2 || splitted.size == 3) processCARBS(splitted, receivedSms) + else if (divided.size == 2 || divided.size == 3) processCARBS(divided, receivedSms) else sendSMS(Sms(receivedSms.phoneNumber, resourceHelper.gs(R.string.wrongformat))) - "CAL" -> + "CAL" -> if (!remoteCommandsAllowed) sendSMS(Sms(receivedSms.phoneNumber, resourceHelper.gs(R.string.smscommunicator_remotecommandnotallowed))) - else if (splitted.size == 2) processCAL(splitted, receivedSms) + else if (divided.size == 2) processCAL(divided, receivedSms) else sendSMS(Sms(receivedSms.phoneNumber, resourceHelper.gs(R.string.wrongformat))) - "TARGET" -> + "TARGET" -> if (!remoteCommandsAllowed) sendSMS(Sms(receivedSms.phoneNumber, resourceHelper.gs(R.string.smscommunicator_remotecommandnotallowed))) - else if (splitted.size == 2) processTARGET(splitted, receivedSms) + else if (divided.size == 2) processTARGET(divided, receivedSms) else sendSMS(Sms(receivedSms.phoneNumber, resourceHelper.gs(R.string.wrongformat))) - "SMS" -> + "SMS" -> if (!remoteCommandsAllowed) sendSMS(Sms(receivedSms.phoneNumber, resourceHelper.gs(R.string.smscommunicator_remotecommandnotallowed))) - else if (splitted.size == 2) processSMS(splitted, receivedSms) + else if (divided.size == 2) processSMS(divided, receivedSms) else sendSMS(Sms(receivedSms.phoneNumber, resourceHelper.gs(R.string.wrongformat))) - "HELP" -> - if (splitted.size == 1 || splitted.size == 2) processHELP(splitted, receivedSms) + "HELP" -> + if (divided.size == 1 || divided.size == 2) processHELP(divided, receivedSms) else sendSMS(Sms(receivedSms.phoneNumber, resourceHelper.gs(R.string.wrongformat))) else -> if (messageToConfirm?.requester?.phoneNumber == receivedSms.phoneNumber) { - messageToConfirm?.action(splitted[0]) + messageToConfirm?.action(divided[0]) messageToConfirm = null } else sendSMS(Sms(receivedSms.phoneNumber, resourceHelper.gs(R.string.smscommunicator_unknowncommand))) } @@ -305,11 +306,11 @@ class SmsCommunicatorPlugin @Inject constructor( receivedSms.processed = true } - private fun processLOOP(splitted: Array, receivedSms: Sms) { - when (splitted[1].toUpperCase(Locale.getDefault())) { + private fun processLOOP(divided: Array, receivedSms: Sms) { + when (divided[1].toUpperCase(Locale.getDefault())) { "DISABLE", "STOP" -> { if (loopPlugin.isEnabled(PluginType.LOOP)) { - val passCode = generatePasscode() + val passCode = generatePassCode() val reply = String.format(resourceHelper.gs(R.string.smscommunicator_loopdisablereplywithcode), passCode) receivedSms.processed = true messageToConfirm = AuthRequest(injector, receivedSms, reply, passCode, object : SmsAction() { @@ -333,7 +334,7 @@ class SmsCommunicatorPlugin @Inject constructor( "ENABLE", "START" -> { if (!loopPlugin.isEnabled(PluginType.LOOP)) { - val passCode = generatePasscode() + val passCode = generatePassCode() val reply = String.format(resourceHelper.gs(R.string.smscommunicator_loopenablereplywithcode), passCode) receivedSms.processed = true messageToConfirm = AuthRequest(injector, receivedSms, reply, passCode, object : SmsAction() { @@ -349,7 +350,7 @@ class SmsCommunicatorPlugin @Inject constructor( receivedSms.processed = true } - "STATUS" -> { + "STATUS" -> { val reply = if (loopPlugin.isEnabled(PluginType.LOOP)) { if (loopPlugin.isSuspended) String.format(resourceHelper.gs(R.string.loopsuspendedfor), loopPlugin.minutesToEndOfSuspend()) else resourceHelper.gs(R.string.smscommunicator_loopisenabled) @@ -359,8 +360,8 @@ class SmsCommunicatorPlugin @Inject constructor( receivedSms.processed = true } - "RESUME" -> { - val passCode = generatePasscode() + "RESUME" -> { + val passCode = generatePassCode() val reply = String.format(resourceHelper.gs(R.string.smscommunicator_loopresumereplywithcode), passCode) receivedSms.processed = true messageToConfirm = AuthRequest(injector, receivedSms, reply, passCode, object : SmsAction() { @@ -383,17 +384,17 @@ class SmsCommunicatorPlugin @Inject constructor( }) } - "SUSPEND" -> { + "SUSPEND" -> { var duration = 0 - if (splitted.size == 3) duration = SafeParse.stringToInt(splitted[2]) - duration = Math.max(0, duration) - duration = Math.min(180, duration) + if (divided.size == 3) duration = SafeParse.stringToInt(divided[2]) + duration = max(0, duration) + duration = min(180, duration) if (duration == 0) { receivedSms.processed = true sendSMS(Sms(receivedSms.phoneNumber, resourceHelper.gs(R.string.smscommunicator_wrongduration))) return } else { - val passCode = generatePasscode() + val passCode = generatePassCode() val reply = String.format(resourceHelper.gs(R.string.smscommunicator_suspendreplywithcode), duration, passCode) receivedSms.processed = true messageToConfirm = AuthRequest(injector, receivedSms, reply, passCode, object : SmsAction(duration) { @@ -424,8 +425,8 @@ class SmsCommunicatorPlugin @Inject constructor( } } - private fun processTREATMENTS(splitted: Array, receivedSms: Sms) { - if (splitted[1].toUpperCase(Locale.getDefault()) == "REFRESH") { + private fun processTREATMENTS(divided: Array, receivedSms: Sms) { + if (divided[1].toUpperCase(Locale.getDefault()) == "REFRESH") { (activePlugin.activeTreatments as TreatmentsPlugin).service.resetTreatments() rxBus.send(EventNSClientRestart()) sendSMS(Sms(receivedSms.phoneNumber, "TREATMENTS REFRESH SENT")) @@ -434,8 +435,8 @@ class SmsCommunicatorPlugin @Inject constructor( sendSMS(Sms(receivedSms.phoneNumber, resourceHelper.gs(R.string.wrongformat))) } - private fun processNSCLIENT(splitted: Array, receivedSms: Sms) { - if (splitted[1].toUpperCase(Locale.getDefault()) == "RESTART") { + private fun processNSCLIENT(divided: Array, receivedSms: Sms) { + if (divided[1].toUpperCase(Locale.getDefault()) == "RESTART") { rxBus.send(EventNSClientRestart()) sendSMS(Sms(receivedSms.phoneNumber, "NSCLIENT RESTART SENT")) receivedSms.processed = true @@ -443,21 +444,26 @@ class SmsCommunicatorPlugin @Inject constructor( sendSMS(Sms(receivedSms.phoneNumber, resourceHelper.gs(R.string.wrongformat))) } - private fun processHELP(splitted: Array, receivedSms: Sms) { - if (splitted.size == 1) { - sendSMS(Sms(receivedSms.phoneNumber, commands.keys.toString().replace("[", "").replace("]", ""))) - receivedSms.processed = true - } else if (isCommand(splitted[1].toUpperCase(Locale.getDefault()), receivedSms.phoneNumber)) { - commands[splitted[1].toUpperCase(Locale.getDefault())]?.let { - sendSMS(Sms(receivedSms.phoneNumber, it)) + private fun processHELP(divided: Array, receivedSms: Sms) { + when { + divided.size == 1 -> { + sendSMS(Sms(receivedSms.phoneNumber, commands.keys.toString().replace("[", "").replace("]", ""))) receivedSms.processed = true } - } else - sendSMS(Sms(receivedSms.phoneNumber, resourceHelper.gs(R.string.wrongformat))) + + isCommand(divided[1].toUpperCase(Locale.getDefault()), receivedSms.phoneNumber) -> { + commands[divided[1].toUpperCase(Locale.getDefault())]?.let { + sendSMS(Sms(receivedSms.phoneNumber, it)) + receivedSms.processed = true + } + } + + else -> sendSMS(Sms(receivedSms.phoneNumber, resourceHelper.gs(R.string.wrongformat))) + } } - private fun processPUMP(splitted: Array, receivedSms: Sms) { - if (splitted.size == 1) { + private fun processPUMP(divided: Array, receivedSms: Sms) { + if (divided.size == 1) { commandQueue.readStatus("SMS", object : Callback() { override fun run() { val pump = activePlugin.activePump @@ -471,8 +477,8 @@ class SmsCommunicatorPlugin @Inject constructor( } }) receivedSms.processed = true - } else if ((splitted.size == 2) && (splitted[1].equals("CONNECT", ignoreCase = true))) { - val passCode = generatePasscode() + } else if ((divided.size == 2) && (divided[1].equals("CONNECT", ignoreCase = true))) { + val passCode = generatePassCode() val reply = String.format(resourceHelper.gs(R.string.smscommunicator_pumpconnectwithcode), passCode) receivedSms.processed = true messageToConfirm = AuthRequest(injector, receivedSms, reply, passCode, object : SmsAction() { @@ -492,16 +498,16 @@ class SmsCommunicatorPlugin @Inject constructor( }) } }) - } else if ((splitted.size == 3) && (splitted[1].equals("DISCONNECT", ignoreCase = true))) { - var duration = SafeParse.stringToInt(splitted[2]) - duration = Math.max(0, duration) - duration = Math.min(120, duration) + } else if ((divided.size == 3) && (divided[1].equals("DISCONNECT", ignoreCase = true))) { + var duration = SafeParse.stringToInt(divided[2]) + duration = max(0, duration) + duration = min(120, duration) if (duration == 0) { receivedSms.processed = true sendSMS(Sms(receivedSms.phoneNumber, resourceHelper.gs(R.string.smscommunicator_wrongduration))) return } else { - val passCode = generatePasscode() + val passCode = generatePassCode() val reply = String.format(resourceHelper.gs(R.string.smscommunicator_pumpdisconnectwithcode), duration, passCode) receivedSms.processed = true messageToConfirm = AuthRequest(injector, receivedSms, reply, passCode, object : SmsAction() { @@ -520,7 +526,7 @@ class SmsCommunicatorPlugin @Inject constructor( } } - private fun processPROFILE(splitted: Array, receivedSms: Sms) { // load profiles + private fun processPROFILE(divided: Array, receivedSms: Sms) { // load profiles val anInterface = activePlugin.activeProfileInterface val store = anInterface.profile if (store == null) { @@ -530,9 +536,9 @@ class SmsCommunicatorPlugin @Inject constructor( } val profileName = profileFunction.getProfileName() val list = store.getProfileList() - if (splitted[1].toUpperCase(Locale.getDefault()) == "STATUS") { + if (divided[1].toUpperCase(Locale.getDefault()) == "STATUS") { sendSMS(Sms(receivedSms.phoneNumber, profileName)) - } else if (splitted[1].toUpperCase(Locale.getDefault()) == "LIST") { + } else if (divided[1].toUpperCase(Locale.getDefault()) == "LIST") { if (list.isEmpty()) sendSMS(Sms(receivedSms.phoneNumber, resourceHelper.gs(R.string.invalidprofile))) else { var reply = "" @@ -544,9 +550,9 @@ class SmsCommunicatorPlugin @Inject constructor( sendSMS(Sms(receivedSms.phoneNumber, reply)) } } else { - val pindex = SafeParse.stringToInt(splitted[1]) + val pindex = SafeParse.stringToInt(divided[1]) var percentage = 100 - if (splitted.size > 2) percentage = SafeParse.stringToInt(splitted[2]) + if (divided.size > 2) percentage = SafeParse.stringToInt(divided[2]) if (pindex > list.size) sendSMS(Sms(receivedSms.phoneNumber, resourceHelper.gs(R.string.wrongformat))) else if (percentage == 0) sendSMS(Sms(receivedSms.phoneNumber, resourceHelper.gs(R.string.wrongformat))) else if (pindex == 0) sendSMS(Sms(receivedSms.phoneNumber, resourceHelper.gs(R.string.wrongformat))) @@ -554,7 +560,7 @@ class SmsCommunicatorPlugin @Inject constructor( val profile = store.getSpecificProfile(list[pindex - 1] as String) if (profile == null) sendSMS(Sms(receivedSms.phoneNumber, resourceHelper.gs(R.string.noprofile))) else { - val passCode = generatePasscode() + val passCode = generatePassCode() val reply = String.format(resourceHelper.gs(R.string.smscommunicator_profilereplywithcode), list[pindex - 1], percentage, passCode) receivedSms.processed = true val finalPercentage = percentage @@ -571,9 +577,9 @@ class SmsCommunicatorPlugin @Inject constructor( receivedSms.processed = true } - private fun processBASAL(splitted: Array, receivedSms: Sms) { - if (splitted[1].toUpperCase(Locale.getDefault()) == "CANCEL" || splitted[1].toUpperCase(Locale.getDefault()) == "STOP") { - val passCode = generatePasscode() + private fun processBASAL(divided: Array, receivedSms: Sms) { + if (divided[1].toUpperCase(Locale.getDefault()) == "CANCEL" || divided[1].toUpperCase(Locale.getDefault()) == "STOP") { + val passCode = generatePassCode() val reply = String.format(resourceHelper.gs(R.string.smscommunicator_basalstopreplywithcode), passCode) receivedSms.processed = true messageToConfirm = AuthRequest(injector, receivedSms, reply, passCode, object : SmsAction() { @@ -594,18 +600,18 @@ class SmsCommunicatorPlugin @Inject constructor( }) } }) - } else if (splitted[1].endsWith("%")) { - var tempBasalPct = SafeParse.stringToInt(StringUtils.removeEnd(splitted[1], "%")) + } else if (divided[1].endsWith("%")) { + var tempBasalPct = SafeParse.stringToInt(StringUtils.removeEnd(divided[1], "%")) val durationStep = activePlugin.activePump.model().tbrSettings.durationStep var duration = 30 - if (splitted.size > 2) duration = SafeParse.stringToInt(splitted[2]) + if (divided.size > 2) duration = SafeParse.stringToInt(divided[2]) val profile = profileFunction.getProfile() if (profile == null) sendSMS(Sms(receivedSms.phoneNumber, resourceHelper.gs(R.string.noprofile))) - else if (tempBasalPct == 0 && splitted[1] != "0%") sendSMS(Sms(receivedSms.phoneNumber, resourceHelper.gs(R.string.wrongformat))) + else if (tempBasalPct == 0 && divided[1] != "0%") sendSMS(Sms(receivedSms.phoneNumber, resourceHelper.gs(R.string.wrongformat))) else if (duration <= 0 || duration % durationStep != 0) sendSMS(Sms(receivedSms.phoneNumber, resourceHelper.gs(R.string.wrongTbrDuration, durationStep))) else { tempBasalPct = constraintChecker.applyBasalPercentConstraints(Constraint(tempBasalPct), profile).value() - val passCode = generatePasscode() + val passCode = generatePassCode() val reply = String.format(resourceHelper.gs(R.string.smscommunicator_basalpctreplywithcode), tempBasalPct, duration, passCode) receivedSms.processed = true messageToConfirm = AuthRequest(injector, receivedSms, reply, passCode, object : SmsAction(tempBasalPct, duration) { @@ -614,8 +620,7 @@ class SmsCommunicatorPlugin @Inject constructor( commandQueue.tempBasalPercent(anInteger(), secondInteger(), true, profile, object : Callback() { override fun run() { if (result.success) { - var replyText: String - replyText = if (result.isPercent) String.format(resourceHelper.gs(R.string.smscommunicator_tempbasalset_percent), result.percent, result.duration) else String.format(resourceHelper.gs(R.string.smscommunicator_tempbasalset), result.absolute, result.duration) + var replyText = if (result.isPercent) String.format(resourceHelper.gs(R.string.smscommunicator_tempbasalset_percent), result.percent, result.duration) else String.format(resourceHelper.gs(R.string.smscommunicator_tempbasalset), result.absolute, result.duration) replyText += "\n" + activePlugin.activePump.shortStatus(true) sendSMSToAllNumbers(Sms(receivedSms.phoneNumber, replyText)) } else { @@ -629,17 +634,17 @@ class SmsCommunicatorPlugin @Inject constructor( }) } } else { - var tempBasal = SafeParse.stringToDouble(splitted[1]) + var tempBasal = SafeParse.stringToDouble(divided[1]) val durationStep = activePlugin.activePump.model().tbrSettings.durationStep var duration = 30 - if (splitted.size > 2) duration = SafeParse.stringToInt(splitted[2]) + if (divided.size > 2) duration = SafeParse.stringToInt(divided[2]) val profile = profileFunction.getProfile() if (profile == null) sendSMS(Sms(receivedSms.phoneNumber, resourceHelper.gs(R.string.noprofile))) - else if (tempBasal == 0.0 && splitted[1] != "0") sendSMS(Sms(receivedSms.phoneNumber, resourceHelper.gs(R.string.wrongformat))) + else if (tempBasal == 0.0 && divided[1] != "0") sendSMS(Sms(receivedSms.phoneNumber, resourceHelper.gs(R.string.wrongformat))) else if (duration <= 0 || duration % durationStep != 0) sendSMS(Sms(receivedSms.phoneNumber, resourceHelper.gs(R.string.wrongTbrDuration, durationStep))) else { tempBasal = constraintChecker.applyBasalConstraints(Constraint(tempBasal), profile).value() - val passCode = generatePasscode() + val passCode = generatePassCode() val reply = String.format(resourceHelper.gs(R.string.smscommunicator_basalreplywithcode), tempBasal, duration, passCode) receivedSms.processed = true messageToConfirm = AuthRequest(injector, receivedSms, reply, passCode, object : SmsAction(tempBasal, duration) { @@ -665,9 +670,9 @@ class SmsCommunicatorPlugin @Inject constructor( } } - private fun processEXTENDED(splitted: Array, receivedSms: Sms) { - if (splitted[1].toUpperCase(Locale.getDefault()) == "CANCEL" || splitted[1].toUpperCase(Locale.getDefault()) == "STOP") { - val passCode = generatePasscode() + private fun processEXTENDED(divided: Array, receivedSms: Sms) { + if (divided[1].toUpperCase(Locale.getDefault()) == "CANCEL" || divided[1].toUpperCase(Locale.getDefault()) == "STOP") { + val passCode = generatePassCode() val reply = String.format(resourceHelper.gs(R.string.smscommunicator_extendedstopreplywithcode), passCode) receivedSms.processed = true messageToConfirm = AuthRequest(injector, receivedSms, reply, passCode, object : SmsAction() { @@ -688,15 +693,15 @@ class SmsCommunicatorPlugin @Inject constructor( }) } }) - } else if (splitted.size != 3) { + } else if (divided.size != 3) { sendSMS(Sms(receivedSms.phoneNumber, resourceHelper.gs(R.string.wrongformat))) } else { - var extended = SafeParse.stringToDouble(splitted[1]) - val duration = SafeParse.stringToInt(splitted[2]) + var extended = SafeParse.stringToDouble(divided[1]) + val duration = SafeParse.stringToInt(divided[2]) extended = constraintChecker.applyExtendedBolusConstraints(Constraint(extended)).value() if (extended == 0.0 || duration == 0) sendSMS(Sms(receivedSms.phoneNumber, resourceHelper.gs(R.string.wrongformat))) else { - val passCode = generatePasscode() + val passCode = generatePassCode() val reply = String.format(resourceHelper.gs(R.string.smscommunicator_extendedreplywithcode), extended, duration, passCode) receivedSms.processed = true messageToConfirm = AuthRequest(injector, receivedSms, reply, passCode, object : SmsAction(extended, duration) { @@ -722,14 +727,14 @@ class SmsCommunicatorPlugin @Inject constructor( } } - private fun processBOLUS(splitted: Array, receivedSms: Sms) { - var bolus = SafeParse.stringToDouble(splitted[1]) - val isMeal = splitted.size > 2 && splitted[2].equals("MEAL", ignoreCase = true) + private fun processBOLUS(divided: Array, receivedSms: Sms) { + var bolus = SafeParse.stringToDouble(divided[1]) + val isMeal = divided.size > 2 && divided[2].equals("MEAL", ignoreCase = true) bolus = constraintChecker.applyBolusConstraints(Constraint(bolus)).value() - if (splitted.size == 3 && !isMeal) { + if (divided.size == 3 && !isMeal) { sendSMS(Sms(receivedSms.phoneNumber, resourceHelper.gs(R.string.wrongformat))) } else if (bolus > 0.0) { - val passCode = generatePasscode() + val passCode = generatePassCode() val reply = if (isMeal) String.format(resourceHelper.gs(R.string.smscommunicator_mealbolusreplywithcode), bolus, passCode) else @@ -762,9 +767,11 @@ class SmsCommunicatorPlugin @Inject constructor( else Constants.defaultEatingSoonTTDuration var eatingSoonTT = sp.getDouble(R.string.key_eatingsoon_target, if (currentProfile.units == Constants.MMOL) Constants.defaultEatingSoonTTmmol else Constants.defaultEatingSoonTTmgdl) eatingSoonTT = - if (eatingSoonTT > 0) eatingSoonTT - else if (currentProfile.units == Constants.MMOL) Constants.defaultEatingSoonTTmmol - else Constants.defaultEatingSoonTTmgdl + when { + eatingSoonTT > 0 -> eatingSoonTT + currentProfile.units == Constants.MMOL -> Constants.defaultEatingSoonTTmmol + else -> Constants.defaultEatingSoonTTmgdl + } val tempTarget = TempTarget() .date(System.currentTimeMillis()) .duration(eatingSoonTTDuration) @@ -794,11 +801,11 @@ class SmsCommunicatorPlugin @Inject constructor( } else sendSMS(Sms(receivedSms.phoneNumber, resourceHelper.gs(R.string.wrongformat))) } - private fun processCARBS(splitted: Array, receivedSms: Sms) { - var grams = SafeParse.stringToInt(splitted[1]) + private fun processCARBS(divided: Array, receivedSms: Sms) { + var grams = SafeParse.stringToInt(divided[1]) var time = DateUtil.now() - if (splitted.size > 2) { - time = DateUtil.toTodayTime(splitted[2].toUpperCase(Locale.getDefault())) + if (divided.size > 2) { + time = DateUtil.toTodayTime(divided[2].toUpperCase(Locale.getDefault())) if (time == 0L) { sendSMS(Sms(receivedSms.phoneNumber, resourceHelper.gs(R.string.wrongformat))) return @@ -807,7 +814,7 @@ class SmsCommunicatorPlugin @Inject constructor( grams = constraintChecker.applyCarbsConstraints(Constraint(grams)).value() if (grams == 0) sendSMS(Sms(receivedSms.phoneNumber, resourceHelper.gs(R.string.wrongformat))) else { - val passCode = generatePasscode() + val passCode = generatePassCode() val reply = String.format(resourceHelper.gs(R.string.smscommunicator_carbsreplywithcode), grams, dateUtil.timeString(time), passCode) receivedSms.processed = true messageToConfirm = AuthRequest(injector, receivedSms, reply, passCode, object : SmsAction(grams, time) { @@ -842,14 +849,14 @@ class SmsCommunicatorPlugin @Inject constructor( } } - private fun processTARGET(splitted: Array, receivedSms: Sms) { - val isMeal = splitted[1].equals("MEAL", ignoreCase = true) - val isActivity = splitted[1].equals("ACTIVITY", ignoreCase = true) - val isHypo = splitted[1].equals("HYPO", ignoreCase = true) - val isStop = splitted[1].equals("STOP", ignoreCase = true) || splitted[1].equals("CANCEL", ignoreCase = true) + private fun processTARGET(divided: Array, receivedSms: Sms) { + val isMeal = divided[1].equals("MEAL", ignoreCase = true) + val isActivity = divided[1].equals("ACTIVITY", ignoreCase = true) + val isHypo = divided[1].equals("HYPO", ignoreCase = true) + val isStop = divided[1].equals("STOP", ignoreCase = true) || divided[1].equals("CANCEL", ignoreCase = true) if (isMeal || isActivity || isHypo) { - val passCode = generatePasscode() - val reply = String.format(resourceHelper.gs(R.string.smscommunicator_temptargetwithcode), splitted[1].toUpperCase(Locale.getDefault()), passCode) + val passCode = generatePassCode() + val reply = String.format(resourceHelper.gs(R.string.smscommunicator_temptargetwithcode), divided[1].toUpperCase(Locale.getDefault()), passCode) receivedSms.processed = true messageToConfirm = AuthRequest(injector, receivedSms, reply, passCode, object : SmsAction() { override fun run() { @@ -904,7 +911,7 @@ class SmsCommunicatorPlugin @Inject constructor( } }) } else if (isStop) { - val passCode = generatePasscode() + val passCode = generatePassCode() val reply = String.format(resourceHelper.gs(R.string.smscommunicator_temptargetcancel), passCode) receivedSms.processed = true messageToConfirm = AuthRequest(injector, receivedSms, reply, passCode, object : SmsAction() { @@ -925,11 +932,11 @@ class SmsCommunicatorPlugin @Inject constructor( sendSMS(Sms(receivedSms.phoneNumber, resourceHelper.gs(R.string.wrongformat))) } - private fun processSMS(splitted: Array, receivedSms: Sms) { - val isStop = (splitted[1].equals("STOP", ignoreCase = true) - || splitted[1].equals("DISABLE", ignoreCase = true)) + private fun processSMS(divided: Array, receivedSms: Sms) { + val isStop = (divided[1].equals("STOP", ignoreCase = true) + || divided[1].equals("DISABLE", ignoreCase = true)) if (isStop) { - val passCode = generatePasscode() + val passCode = generatePassCode() val reply = String.format(resourceHelper.gs(R.string.smscommunicator_stopsmswithcode), passCode) receivedSms.processed = true messageToConfirm = AuthRequest(injector, receivedSms, reply, passCode, object : SmsAction() { @@ -943,10 +950,10 @@ class SmsCommunicatorPlugin @Inject constructor( } else sendSMS(Sms(receivedSms.phoneNumber, resourceHelper.gs(R.string.wrongformat))) } - private fun processCAL(splitted: Array, receivedSms: Sms) { - val cal = SafeParse.stringToDouble(splitted[1]) + private fun processCAL(divided: Array, receivedSms: Sms) { + val cal = SafeParse.stringToDouble(divided[1]) if (cal > 0.0) { - val passCode = generatePasscode() + val passCode = generatePassCode() val reply = String.format(resourceHelper.gs(R.string.smscommunicator_calibrationreplywithcode), cal, passCode) receivedSms.processed = true messageToConfirm = AuthRequest(injector, receivedSms, reply, passCode, object : SmsAction(cal) { @@ -1006,22 +1013,8 @@ class SmsCommunicatorPlugin @Inject constructor( return true } - private fun generatePasscode(): String { - - if (otp.isEnabled()) { - // this not realy generate password - rather info to use Authenticator TOTP instead - return resourceHelper.gs(R.string.smscommunicator_code_from_authenticator_for, otp.name()) - } - - val startChar1 = 'A'.toInt() // on iphone 1st char is uppercase :) - var passCode = Character.toString((startChar1 + Math.random() * ('z' - 'a' + 1)).toChar()) - val startChar2: Int = if (Math.random() > 0.5) 'a'.toInt() else 'A'.toInt() - passCode += Character.toString((startChar2 + Math.random() * ('z' - 'a' + 1)).toChar()) - val startChar3: Int = if (Math.random() > 0.5) 'a'.toInt() else 'A'.toInt() - passCode += Character.toString((startChar3 + Math.random() * ('z' - 'a' + 1)).toChar()) - passCode = passCode.replace('l', 'k').replace('I', 'J') - return passCode - } + private fun generatePassCode(): String = + resourceHelper.gs(R.string.smscommunicator_code_from_authenticator_for, otp.name()) private fun stripAccents(str: String): String { var s = str @@ -1030,8 +1023,8 @@ class SmsCommunicatorPlugin @Inject constructor( return s } - private fun areMoreNumbers(allowednumbers: String?): Boolean { - return allowednumbers?.let { + private fun areMoreNumbers(allowedNumbers: String?): Boolean { + return allowedNumbers?.let { val knownNumbers = HashSet() val substrings = it.split(";").toTypedArray() for (number in substrings) { diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/smsCommunicator/otp/OneTimePassword.kt b/app/src/main/java/info/nightscout/androidaps/plugins/general/smsCommunicator/otp/OneTimePassword.kt index 75b913c302..68018f8f9f 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/general/smsCommunicator/otp/OneTimePassword.kt +++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/smsCommunicator/otp/OneTimePassword.kt @@ -26,24 +26,9 @@ class OneTimePassword @Inject constructor( private val totp = HmacOneTimePasswordGenerator() init { - instance = this configure() } - companion object { - private lateinit var instance: OneTimePassword - - @JvmStatic - fun getInstance(): OneTimePassword = instance - } - - /** - * If OTP Authenticator support is enabled by user - */ - fun isEnabled(): Boolean { - return sp.getBoolean(R.string.key_smscommunicator_otp_enabled, true) - } - /** * Name of master device (target of OTP) */ diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index eb8278a83c..406973b9fe 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -1266,14 +1266,11 @@ - smscommunicator_otp_enabled smscommunicator_otp_password smscommunicator_otp_secret from Authenticator app for: %1$s followed by PIN - Enable Authenticator - Authenticate commands using One Time Passwords generated by Google Authenticator or similar 2FA apps. Additional mandatory PIN at token end Additional digits that should be memorised and glued at end of each generated One Time Password diff --git a/app/src/main/res/xml/pref_smscommunicator.xml b/app/src/main/res/xml/pref_smscommunicator.xml index 91e83a7084..dc61d1c1a2 100644 --- a/app/src/main/res/xml/pref_smscommunicator.xml +++ b/app/src/main/res/xml/pref_smscommunicator.xml @@ -27,14 +27,6 @@ validate:minNumber="3" validate:testType="numericRange" /> - - Date: Mon, 1 Feb 2021 20:36:58 +0100 Subject: [PATCH 09/84] EditQuickWizardDialog -> jetpack --- .../overview/dialogs/EditQuickWizardDialog.kt | 160 ++++--- .../utils/extensions/RadioGroupExtension.kt | 16 + .../overview_editquickwizard_dialog.xml | 414 ++++++++++++------ app/src/main/res/values/arrays.xml | 12 - 4 files changed, 394 insertions(+), 208 deletions(-) create mode 100644 app/src/main/java/info/nightscout/androidaps/utils/extensions/RadioGroupExtension.kt diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/dialogs/EditQuickWizardDialog.kt b/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/dialogs/EditQuickWizardDialog.kt index 463c7564fa..d2bf09df4f 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/dialogs/EditQuickWizardDialog.kt +++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/dialogs/EditQuickWizardDialog.kt @@ -1,29 +1,33 @@ package info.nightscout.androidaps.plugins.general.overview.dialogs +import android.app.TimePickerDialog import android.os.Bundle +import android.text.format.DateFormat import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import android.view.Window import android.view.WindowManager -import android.widget.AdapterView -import android.widget.ArrayAdapter import dagger.android.support.DaggerDialogFragment -import info.nightscout.androidaps.R -import info.nightscout.androidaps.utils.wizard.QuickWizard -import info.nightscout.androidaps.utils.wizard.QuickWizardEntry +import info.nightscout.androidaps.databinding.OverviewEditquickwizardDialogBinding import info.nightscout.androidaps.logging.AAPSLogger import info.nightscout.androidaps.plugins.bus.RxBusWrapper import info.nightscout.androidaps.plugins.general.overview.events.EventQuickWizardChange import info.nightscout.androidaps.utils.DateUtil import info.nightscout.androidaps.utils.SafeParse +import info.nightscout.androidaps.utils.T +import info.nightscout.androidaps.utils.extensions.selectedItemPosition +import info.nightscout.androidaps.utils.extensions.setEnableForChildren +import info.nightscout.androidaps.utils.extensions.setSelection +import info.nightscout.androidaps.utils.wizard.QuickWizard +import info.nightscout.androidaps.utils.wizard.QuickWizardEntry import kotlinx.android.synthetic.main.okcancel.* import kotlinx.android.synthetic.main.overview_editquickwizard_dialog.* import org.json.JSONException -import java.util.* import javax.inject.Inject -class EditQuickWizardDialog : DaggerDialogFragment() { +class EditQuickWizardDialog : DaggerDialogFragment(), View.OnClickListener { + @Inject lateinit var rxBus: RxBusWrapper @Inject lateinit var aapsLogger: AAPSLogger @Inject lateinit var quickWizard: QuickWizard @@ -31,37 +35,43 @@ class EditQuickWizardDialog : DaggerDialogFragment() { var position = -1 + var fromSeconds: Int = 0 + var toSeconds: Int = 0 + + private var _binding: OverviewEditquickwizardDialogBinding? = null + + // This property is only valid between onCreateView and + // onDestroyView. + private val binding get() = _binding!! + override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, - savedInstanceState: Bundle?): View? { + savedInstanceState: Bundle?): View { dialog?.window?.requestFeature(Window.FEATURE_NO_TITLE) dialog?.window?.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN) isCancelable = true dialog?.setCanceledOnTouchOutside(false) - return inflater.inflate(R.layout.overview_editquickwizard_dialog, container, false) + _binding = OverviewEditquickwizardDialogBinding.inflate(inflater, container, false) + return binding.root } override fun onViewCreated(view: View, savedInstanceState: Bundle?) { (arguments ?: savedInstanceState)?.let { bundle -> position = bundle.getInt("position", -1) } - val entry = if (position ==-1) quickWizard.newEmptyItem() else quickWizard[position] + val entry = if (position == -1) quickWizard.newEmptyItem() else quickWizard[position] ok.setOnClickListener { - if (overview_editquickwizard_from_spinner.selectedItem == null) return@setOnClickListener - if (overview_editquickwizard_to_spinner.selectedItem == null) return@setOnClickListener try { - entry.storage.put("buttonText", overview_editquickwizard_button_edit.text.toString()) - entry.storage.put("carbs", SafeParse.stringToInt(overview_editquickwizard_carbs_edit.text.toString())) - val validFromInt = DateUtil.toSeconds(overview_editquickwizard_from_spinner.selectedItem.toString()) - entry.storage.put("validFrom", validFromInt) - val validToInt = DateUtil.toSeconds(overview_editquickwizard_to_spinner.selectedItem.toString()) - entry.storage.put("validTo", validToInt) - entry.storage.put("useBG", overview_editquickwizard_usebg_spinner.selectedItemPosition) - entry.storage.put("useCOB", overview_editquickwizard_usecob_spinner.selectedItemPosition) - entry.storage.put("useBolusIOB", overview_editquickwizard_usebolusiob_spinner.selectedItemPosition) - entry.storage.put("useBasalIOB", overview_editquickwizard_usebasaliob_spinner.selectedItemPosition) - entry.storage.put("useTrend", overview_editquickwizard_usetrend_spinner.selectedItemPosition) - entry.storage.put("useSuperBolus", overview_editquickwizard_usesuperbolus_spinner.selectedItemPosition) - entry.storage.put("useTempTarget", overview_editquickwizard_usetemptarget_spinner.selectedItemPosition) + entry.storage.put("buttonText", binding.buttonEdit.text.toString()) + entry.storage.put("carbs", SafeParse.stringToInt(binding.carbsEdit.text.toString())) + entry.storage.put("validFrom", fromSeconds) + entry.storage.put("validTo", toSeconds) + entry.storage.put("useBG", binding.useBg.selectedItemPosition) + entry.storage.put("useCOB", binding.useCob.selectedItemPosition) + entry.storage.put("useBolusIOB", binding.useBolusIob.selectedItemPosition) + entry.storage.put("useBasalIOB", binding.useBasalIob.selectedItemPosition) + entry.storage.put("useTrend", binding.useTrend.selectedItemPosition) + entry.storage.put("useSuperBolus", binding.useSuperBolus.selectedItemPosition) + entry.storage.put("useTempTarget", binding.useTempTarget.selectedItemPosition) } catch (e: JSONException) { aapsLogger.error("Unhandled exception", e) } @@ -72,41 +82,58 @@ class EditQuickWizardDialog : DaggerDialogFragment() { } cancel.setOnClickListener { dismiss() } - var posFrom = 0 - var posTo = 95 - val timeList = ArrayList() - var pos = 0 - var t = 0 - while (t < 24 * 60 * 60) { - timeList.add(dateUtil.timeString(DateUtil.toDate(t))) - if (entry.validFrom() == t) posFrom = pos - if (entry.validTo() == t) posTo = pos - pos++ - t += 15 * 60 + // create an OnTimeSetListener + val fromTimeSetListener = TimePickerDialog.OnTimeSetListener { _, hour, minute -> + fromSeconds = (T.hours(hour.toLong()).secs() + T.mins(minute.toLong()).secs()).toInt() + from.text = dateUtil.timeString(DateUtil.toDate(fromSeconds)) } - timeList.add(dateUtil.timeString(DateUtil.toDate(24 * 60 * 60 - 60))) - val adapter = context?.let { context -> ArrayAdapter(context, R.layout.spinner_centered, timeList) } - overview_editquickwizard_from_spinner.adapter = adapter - overview_editquickwizard_to_spinner.adapter = adapter - - overview_editquickwizard_button_edit.setText(entry.buttonText()) - overview_editquickwizard_carbs_edit.setText(entry.carbs().toString()) - overview_editquickwizard_from_spinner.setSelection(posFrom) - overview_editquickwizard_to_spinner.setSelection(posTo) - - overview_editquickwizard_usebg_spinner.setSelection(entry.useBG()) - overview_editquickwizard_usecob_spinner.setSelection(entry.useCOB()) - overview_editquickwizard_usebolusiob_spinner.setSelection(entry.useBolusIOB()) - overview_editquickwizard_usebasaliob_spinner.setSelection(entry.useBasalIOB()) - overview_editquickwizard_usetrend_spinner.setSelection(entry.useTrend()) - overview_editquickwizard_usesuperbolus_spinner.setSelection(entry.useSuperBolus()) - overview_editquickwizard_usetemptarget_spinner.setSelection(entry.useTempTarget()) - - overview_editquickwizard_usecob_spinner.onItemSelectedListener = object : AdapterView.OnItemSelectedListener { - override fun onItemSelected(parent: AdapterView<*>, view: View?, position: Int, id: Long) = processCob() - override fun onNothingSelected(parent: AdapterView<*>) {} + binding.from.setOnClickListener { + context?.let { + TimePickerDialog(it, fromTimeSetListener, + T.secs(fromSeconds.toLong()).hours().toInt(), + T.secs((fromSeconds % 3600).toLong()).mins().toInt(), + DateFormat.is24HourFormat(context) + ).show() + } } + fromSeconds = entry.validFrom() + from.text = dateUtil.timeString(DateUtil.toDate(fromSeconds)) + + val toTimeSetListener = TimePickerDialog.OnTimeSetListener { _, hour, minute -> + toSeconds = (T.hours(hour.toLong()).secs() + T.mins(minute.toLong()).secs()).toInt() + binding.from.text = dateUtil.timeString(DateUtil.toDate(toSeconds)) + } + + binding.to.setOnClickListener { + context?.let { + TimePickerDialog(it, toTimeSetListener, + T.secs(fromSeconds.toLong()).hours().toInt(), + T.secs((fromSeconds % 3600).toLong()).mins().toInt(), + DateFormat.is24HourFormat(context) + ).show() + } + } + toSeconds = entry.validFrom() + binding.to.text = dateUtil.timeString(DateUtil.toDate(toSeconds)) + + binding.buttonEdit.setText(entry.buttonText()) + binding.carbsEdit.setText(entry.carbs().toString()) + + binding.useBg.setSelection(entry.useBG()) + binding.useCob.setSelection(entry.useCOB()) + binding.useBolusIob.setSelection(entry.useBolusIOB()) + binding.useBasalIob.setSelection(entry.useBasalIOB()) + binding.useTrend.setSelection(entry.useTrend()) + binding.useSuperBolus.setSelection(entry.useSuperBolus()) + binding.useTempTarget.setSelection(entry.useTempTarget()) + + use_cob_yes.setOnClickListener(this) + use_cob_no.setOnClickListener(this) + processCob() + } + + override fun onClick(v: View?) { processCob() } @@ -120,15 +147,20 @@ class EditQuickWizardDialog : DaggerDialogFragment() { outState.putInt("position", position) } + override fun onDestroyView() { + super.onDestroyView() + _binding = null + } + private fun processCob() { - if (overview_editquickwizard_usecob_spinner.selectedItemPosition == QuickWizardEntry.YES) { - overview_editquickwizard_usebolusiob_spinner.isEnabled = false - overview_editquickwizard_usebasaliob_spinner.isEnabled = false - overview_editquickwizard_usebolusiob_spinner.setSelection(QuickWizardEntry.YES) - overview_editquickwizard_usebasaliob_spinner.setSelection(QuickWizardEntry.YES) + if (binding.useCob.selectedItemPosition == QuickWizardEntry.YES) { + binding.useBolusIob.setEnableForChildren(false) + binding.useBasalIob.setEnableForChildren(false) + binding.useBolusIob.setSelection(QuickWizardEntry.YES) + binding.useBasalIob.setSelection(QuickWizardEntry.YES) } else { - overview_editquickwizard_usebolusiob_spinner.isEnabled = true - overview_editquickwizard_usebasaliob_spinner.isEnabled = true + binding.useBolusIob.setEnableForChildren(true) + binding.useBasalIob.setEnableForChildren(true) } } } diff --git a/app/src/main/java/info/nightscout/androidaps/utils/extensions/RadioGroupExtension.kt b/app/src/main/java/info/nightscout/androidaps/utils/extensions/RadioGroupExtension.kt new file mode 100644 index 0000000000..0bf51f656f --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/utils/extensions/RadioGroupExtension.kt @@ -0,0 +1,16 @@ +package info.nightscout.androidaps.utils.extensions + +import android.widget.RadioGroup +import androidx.appcompat.widget.AppCompatRadioButton +import androidx.core.view.forEach + +val RadioGroup.selectedItemPosition: Int + get() = this.indexOfChild(this.findViewById(this.checkedRadioButtonId)) + +fun RadioGroup.setSelection(index: Int) { + (this.getChildAt(index) as AppCompatRadioButton).isChecked = true +} + +fun RadioGroup.setEnableForChildren(state : Boolean) { + forEach { child -> child.isEnabled = state} +} \ No newline at end of file diff --git a/app/src/main/res/layout/overview_editquickwizard_dialog.xml b/app/src/main/res/layout/overview_editquickwizard_dialog.xml index f7517bcfbe..5dd381371a 100644 --- a/app/src/main/res/layout/overview_editquickwizard_dialog.xml +++ b/app/src/main/res/layout/overview_editquickwizard_dialog.xml @@ -1,159 +1,309 @@ - - + android:layout_height="wrap_content" + android:orientation="vertical"> + + + + + + + + + + + + + + + + + android:layout_height="wrap_content" + android:orientation="horizontal"> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/values/arrays.xml b/app/src/main/res/values/arrays.xml index 3328d5a3fe..0b02d9a048 100644 --- a/app/src/main/res/values/arrays.xml +++ b/app/src/main/res/values/arrays.xml @@ -87,18 +87,6 @@ @string/key_pregnant - - @string/yes - @string/no - - - - @string/yes - @string/no - @string/positiveonly - @string/negativeonly - - @string/use_passive_location @string/use_network_location From 31924ce6d1cc0a5e2e0b36ed9e32787576c53b0a Mon Sep 17 00:00:00 2001 From: Milos Kozak Date: Tue, 2 Feb 2021 17:48:39 +0100 Subject: [PATCH 10/84] BundleStore --- .../general/nsclient/NSClientWorker.java | 7 +++--- .../smsCommunicator/SmsCommunicatorPlugin.kt | 15 ++++-------- .../androidaps/plugins/source/DexcomPlugin.kt | 8 +++---- .../plugins/source/EversensePlugin.kt | 7 +++--- .../androidaps/receivers/BundleStore.kt | 24 +++++++++++++++++++ .../androidaps/receivers/DataReceiver.kt | 11 +++++---- 6 files changed, 47 insertions(+), 25 deletions(-) create mode 100644 app/src/main/java/info/nightscout/androidaps/receivers/BundleStore.kt 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 index 54e1e68561..a6af4e431f 100644 --- 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 @@ -7,13 +7,12 @@ import androidx.annotation.NonNull; import androidx.work.Worker; import androidx.work.WorkerParameters; -import com.google.gson.Gson; - 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 { @@ -26,11 +25,13 @@ public class NSClientWorker extends Worker { } @Inject NSClientPlugin nsClientPlugin; + @Inject BundleStore bundleStore; @NotNull @Override public Result doWork() { - Bundle bundle = new Gson().fromJson(getInputData().getString("data"), Bundle.class); + 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 68d1cf8243..9f15e16dff 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,7 +1,6 @@ package info.nightscout.androidaps.plugins.general.smsCommunicator import android.content.Context -import android.os.Bundle import android.telephony.SmsManager import android.telephony.SmsMessage import android.text.TextUtils @@ -10,15 +9,12 @@ import androidx.preference.Preference import androidx.preference.PreferenceFragmentCompat import androidx.work.Worker import androidx.work.WorkerParameters -import com.google.gson.Gson 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.data.DetailedBolusInfo import info.nightscout.androidaps.data.Profile -import info.nightscout.androidaps.db.BgReading import info.nightscout.androidaps.db.Source import info.nightscout.androidaps.db.TempTarget import info.nightscout.androidaps.events.EventPreferenceChange @@ -29,7 +25,6 @@ import info.nightscout.androidaps.logging.LTag import info.nightscout.androidaps.plugins.aps.loop.LoopPlugin import info.nightscout.androidaps.plugins.bus.RxBusWrapper import info.nightscout.androidaps.plugins.configBuilder.ConstraintChecker -import info.nightscout.androidaps.plugins.general.nsclient.NSUpload import info.nightscout.androidaps.plugins.general.nsclient.events.EventNSClientRestart import info.nightscout.androidaps.plugins.general.overview.events.EventNewNotification import info.nightscout.androidaps.plugins.general.overview.notifications.Notification @@ -37,9 +32,9 @@ import info.nightscout.androidaps.plugins.general.smsCommunicator.events.EventSm import info.nightscout.androidaps.plugins.general.smsCommunicator.otp.OneTimePassword import info.nightscout.androidaps.plugins.iob.iobCobCalculator.GlucoseStatus import info.nightscout.androidaps.plugins.iob.iobCobCalculator.IobCobCalculatorPlugin -import info.nightscout.androidaps.plugins.source.PoctechPlugin 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 @@ -48,8 +43,6 @@ import info.nightscout.androidaps.utils.textValidator.ValidatingEditTextPreferen import io.reactivex.disposables.CompositeDisposable import io.reactivex.schedulers.Schedulers import org.apache.commons.lang3.StringUtils -import org.json.JSONArray -import org.json.JSONException import java.text.Normalizer import java.util.* import javax.inject.Inject @@ -161,7 +154,6 @@ class SmsCommunicatorPlugin @Inject constructor( } } - // cannot be inner class because of needed injection class SmsCommunicatorWorker( context: Context, @@ -169,13 +161,15 @@ class SmsCommunicatorPlugin @Inject constructor( ) : 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 = Gson().fromJson(inputData.getString("data"), Bundle::class.java) + 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) { @@ -185,6 +179,7 @@ class SmsCommunicatorPlugin @Inject constructor( 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, "") 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 c8b74398f9..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 @@ -3,11 +3,9 @@ package info.nightscout.androidaps.plugins.source import android.content.Context import android.content.Intent import android.content.pm.PackageManager -import android.os.Bundle import androidx.core.content.ContextCompat import androidx.work.Worker import androidx.work.WorkerParameters -import com.google.gson.Gson import dagger.android.HasAndroidInjector import info.nightscout.androidaps.Config import info.nightscout.androidaps.Constants @@ -23,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 @@ -87,6 +86,7 @@ class DexcomPlugin @Inject constructor( @Inject lateinit var dexcomPlugin: DexcomPlugin @Inject lateinit var nsUpload: NSUpload @Inject lateinit var sp: SP + @Inject lateinit var bundleStore: BundleStore init { (context.applicationContext as HasAndroidInjector).androidInjector().inject(this) @@ -94,8 +94,8 @@ class DexcomPlugin @Inject constructor( override fun doWork(): Result { if (!dexcomPlugin.isEnabled(PluginType.BGSOURCE)) return Result.failure() - val action = inputData.getString("action") - val bundle = Gson().fromJson(inputData.getString("data"), Bundle::class.java) + 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() 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 9e4af176bc..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,10 +1,8 @@ package info.nightscout.androidaps.plugins.source import android.content.Context -import android.os.Bundle import androidx.work.Worker import androidx.work.WorkerParameters -import com.google.gson.Gson import dagger.android.HasAndroidInjector import info.nightscout.androidaps.Constants import info.nightscout.androidaps.MainApp @@ -18,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 @@ -56,6 +55,7 @@ class EversensePlugin @Inject constructor( @Inject lateinit var sp: SP @Inject lateinit var nsUpload: NSUpload @Inject lateinit var dateUtil: DateUtil + @Inject lateinit var bundleStore: BundleStore init { (context.applicationContext as HasAndroidInjector).androidInjector().inject(this) @@ -63,7 +63,8 @@ class EversensePlugin @Inject constructor( override fun doWork(): Result { if (!eversensePlugin.isEnabled(PluginType.BGSOURCE)) return Result.failure() - val bundle = Gson().fromJson(inputData.getString("data"), Bundle::class.java) + 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")) 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 b9f0374fe9..a676211745 100644 --- a/app/src/main/java/info/nightscout/androidaps/receivers/DataReceiver.kt +++ b/app/src/main/java/info/nightscout/androidaps/receivers/DataReceiver.kt @@ -7,7 +7,6 @@ import androidx.work.Data import androidx.work.ExistingWorkPolicy import androidx.work.OneTimeWorkRequest import androidx.work.WorkManager -import com.google.gson.Gson import dagger.android.DaggerBroadcastReceiver import info.nightscout.androidaps.logging.AAPSLogger import info.nightscout.androidaps.logging.BundleLogger @@ -21,11 +20,13 @@ import info.nightscout.androidaps.utils.extensions.copyDouble import info.nightscout.androidaps.utils.extensions.copyInt import info.nightscout.androidaps.utils.extensions.copyLong import info.nightscout.androidaps.utils.extensions.copyString +import org.json.JSONObject import javax.inject.Inject open class DataReceiver : DaggerBroadcastReceiver() { @Inject lateinit var aapsLogger: AAPSLogger + @Inject lateinit var bundleStore: BundleStore private val jobGroupName = "data" @@ -84,19 +85,19 @@ open class DataReceiver : DaggerBroadcastReceiver() { Telephony.Sms.Intents.SMS_RECEIVED_ACTION -> OneTimeWorkRequest.Builder(SmsCommunicatorPlugin.SmsCommunicatorWorker::class.java) .setInputData(Data.Builder().also { - it.putString("data", Gson().toJson(bundle)) + 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.putString("data", Gson().toJson(bundle)) + 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.putString("data", Gson().toJson(bundle)) + it.putLong("storeKey", bundleStore.store(bundle)) it.putString("action", intent.action) }.build()).build() Intents.ACTION_NEW_TREATMENT, @@ -106,7 +107,7 @@ open class DataReceiver : DaggerBroadcastReceiver() { Intents.ACTION_NEW_MBG -> OneTimeWorkRequest.Builder(NSClientWorker::class.java) .setInputData(Data.Builder().also { - it.putString("data", Gson().toJson(bundle)) + it.putLong("storeKey", bundleStore.store(bundle)) it.putString("action", intent.action) }.build()).build() else -> null From e7d58a8f84f8629ee4977ea50328ca3385641958 Mon Sep 17 00:00:00 2001 From: Milos Kozak Date: Tue, 2 Feb 2021 20:25:15 +0100 Subject: [PATCH 11/84] EditQuickWizardDialog -> jetpack #2 --- .../overview/dialogs/EditQuickWizardDialog.kt | 14 ++++++-------- .../res/layout/overview_editquickwizard_dialog.xml | 4 +++- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/dialogs/EditQuickWizardDialog.kt b/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/dialogs/EditQuickWizardDialog.kt index d2bf09df4f..237afba172 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/dialogs/EditQuickWizardDialog.kt +++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/dialogs/EditQuickWizardDialog.kt @@ -21,8 +21,6 @@ import info.nightscout.androidaps.utils.extensions.setEnableForChildren import info.nightscout.androidaps.utils.extensions.setSelection import info.nightscout.androidaps.utils.wizard.QuickWizard import info.nightscout.androidaps.utils.wizard.QuickWizardEntry -import kotlinx.android.synthetic.main.okcancel.* -import kotlinx.android.synthetic.main.overview_editquickwizard_dialog.* import org.json.JSONException import javax.inject.Inject @@ -59,7 +57,7 @@ class EditQuickWizardDialog : DaggerDialogFragment(), View.OnClickListener { position = bundle.getInt("position", -1) } val entry = if (position == -1) quickWizard.newEmptyItem() else quickWizard[position] - ok.setOnClickListener { + binding.okcancel.ok.setOnClickListener { try { entry.storage.put("buttonText", binding.buttonEdit.text.toString()) entry.storage.put("carbs", SafeParse.stringToInt(binding.carbsEdit.text.toString())) @@ -80,12 +78,12 @@ class EditQuickWizardDialog : DaggerDialogFragment(), View.OnClickListener { rxBus.send(EventQuickWizardChange()) dismiss() } - cancel.setOnClickListener { dismiss() } + binding.okcancel.cancel.setOnClickListener { dismiss() } // create an OnTimeSetListener val fromTimeSetListener = TimePickerDialog.OnTimeSetListener { _, hour, minute -> fromSeconds = (T.hours(hour.toLong()).secs() + T.mins(minute.toLong()).secs()).toInt() - from.text = dateUtil.timeString(DateUtil.toDate(fromSeconds)) + binding.from.text = dateUtil.timeString(DateUtil.toDate(fromSeconds)) } binding.from.setOnClickListener { @@ -98,7 +96,7 @@ class EditQuickWizardDialog : DaggerDialogFragment(), View.OnClickListener { } } fromSeconds = entry.validFrom() - from.text = dateUtil.timeString(DateUtil.toDate(fromSeconds)) + binding.from.text = dateUtil.timeString(DateUtil.toDate(fromSeconds)) val toTimeSetListener = TimePickerDialog.OnTimeSetListener { _, hour, minute -> toSeconds = (T.hours(hour.toLong()).secs() + T.mins(minute.toLong()).secs()).toInt() @@ -128,8 +126,8 @@ class EditQuickWizardDialog : DaggerDialogFragment(), View.OnClickListener { binding.useSuperBolus.setSelection(entry.useSuperBolus()) binding.useTempTarget.setSelection(entry.useTempTarget()) - use_cob_yes.setOnClickListener(this) - use_cob_no.setOnClickListener(this) + binding.useCobYes.setOnClickListener(this) + binding.useCobNo.setOnClickListener(this) processCob() } diff --git a/app/src/main/res/layout/overview_editquickwizard_dialog.xml b/app/src/main/res/layout/overview_editquickwizard_dialog.xml index 5dd381371a..89348ac41c 100644 --- a/app/src/main/res/layout/overview_editquickwizard_dialog.xml +++ b/app/src/main/res/layout/overview_editquickwizard_dialog.xml @@ -302,7 +302,9 @@ - + From 2078962057d51bcb84701589dc0ff5920bfeb3a2 Mon Sep 17 00:00:00 2001 From: Milos Kozak Date: Tue, 2 Feb 2021 20:32:07 +0100 Subject: [PATCH 12/84] SmsCommunicatorOtpActivity -> jetpack --- .../activities/SmsCommunicatorOtpActivity.kt | 26 +++++++++++-------- .../layout/activity_smscommunicator_otp.xml | 10 +++---- 2 files changed, 20 insertions(+), 16 deletions(-) diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/smsCommunicator/activities/SmsCommunicatorOtpActivity.kt b/app/src/main/java/info/nightscout/androidaps/plugins/general/smsCommunicator/activities/SmsCommunicatorOtpActivity.kt index f491aaf14b..d11ee90f70 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/general/smsCommunicator/activities/SmsCommunicatorOtpActivity.kt +++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/smsCommunicator/activities/SmsCommunicatorOtpActivity.kt @@ -14,6 +14,7 @@ import com.google.common.primitives.Ints.min import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel import info.nightscout.androidaps.R import info.nightscout.androidaps.activities.NoSplashAppCompatActivity +import info.nightscout.androidaps.databinding.ActivitySmscommunicatorOtpBinding import info.nightscout.androidaps.plugins.bus.RxBusWrapper import info.nightscout.androidaps.plugins.general.smsCommunicator.SmsCommunicatorPlugin import info.nightscout.androidaps.plugins.general.smsCommunicator.otp.OneTimePassword @@ -21,7 +22,6 @@ import info.nightscout.androidaps.plugins.general.smsCommunicator.otp.OneTimePas import info.nightscout.androidaps.utils.FabricPrivacy import info.nightscout.androidaps.utils.ToastUtils import info.nightscout.androidaps.utils.alertDialogs.OKDialog -import kotlinx.android.synthetic.main.activity_smscommunicator_otp.* import net.glxn.qrgen.android.QRCode import javax.inject.Inject @@ -32,23 +32,27 @@ class SmsCommunicatorOtpActivity : NoSplashAppCompatActivity() { @Inject lateinit var smsCommunicatorPlugin: SmsCommunicatorPlugin @Inject lateinit var otp: OneTimePassword + private lateinit var binding: ActivitySmscommunicatorOtpBinding + override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) window.setFlags(WindowManager.LayoutParams.FLAG_SECURE, WindowManager.LayoutParams.FLAG_SECURE) - setContentView(R.layout.activity_smscommunicator_otp) - smscommunicator_otp_verify_edit.addTextChangedListener(object : TextWatcher { + binding = ActivitySmscommunicatorOtpBinding.inflate(layoutInflater) + setContentView(binding.root) + + binding.otpVerifyEdit.addTextChangedListener(object : TextWatcher { override fun afterTextChanged(s: Editable) { val checkResult = otp.checkOTP(s.toString()) - smscommunicator_otp_verify_label.text = when (checkResult) { + binding.otpVerifyLabel.text = when (checkResult) { OneTimePasswordValidationResult.OK -> "OK" OneTimePasswordValidationResult.ERROR_WRONG_LENGTH -> "INVALID SIZE!" OneTimePasswordValidationResult.ERROR_WRONG_PIN -> "WRONG PIN" OneTimePasswordValidationResult.ERROR_WRONG_OTP -> "WRONG OTP" } - smscommunicator_otp_verify_label.setTextColor(when (checkResult) { + binding.otpVerifyLabel.setTextColor(when (checkResult) { OneTimePasswordValidationResult.OK -> Color.GREEN OneTimePasswordValidationResult.ERROR_WRONG_LENGTH -> Color.YELLOW OneTimePasswordValidationResult.ERROR_WRONG_PIN -> Color.RED @@ -61,7 +65,7 @@ class SmsCommunicatorOtpActivity : NoSplashAppCompatActivity() { override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {} }) - actions_smscommunicator_otp_reset.setOnClickListener { + binding.otpReset.setOnClickListener { OKDialog.showConfirmation(this, resourceHelper.gs(R.string.smscommunicator_otp_reset_title), resourceHelper.gs(R.string.smscommunicator_otp_reset_prompt), @@ -72,7 +76,7 @@ class SmsCommunicatorOtpActivity : NoSplashAppCompatActivity() { }) } - smscommunicator_otp_provisioning.setOnLongClickListener { + binding.otpProvisioning.setOnLongClickListener { OKDialog.showConfirmation(this, resourceHelper.gs(R.string.smscommunicator_otp_export_title), resourceHelper.gs(R.string.smscommunicator_otp_export_prompt), @@ -104,12 +108,12 @@ class SmsCommunicatorOtpActivity : NoSplashAppCompatActivity() { if (provURI != null) { val myBitmap = QRCode.from(provURI).withErrorCorrection(ErrorCorrectionLevel.H).withSize(dim, dim).bitmap() - smscommunicator_otp_provisioning.setImageBitmap(myBitmap) - smscommunicator_otp_provisioning.visibility = View.VISIBLE + binding.otpProvisioning.setImageBitmap(myBitmap) + binding.otpProvisioning.visibility = View.VISIBLE } else { - smscommunicator_otp_provisioning.visibility = View.GONE + binding.otpProvisioning.visibility = View.GONE } - smscommunicator_otp_verify_edit.text = smscommunicator_otp_verify_edit.text + binding.otpVerifyEdit.text = binding.otpVerifyEdit.text } } \ No newline at end of file diff --git a/app/src/main/res/layout/activity_smscommunicator_otp.xml b/app/src/main/res/layout/activity_smscommunicator_otp.xml index 91e9fef298..cfa5865277 100644 --- a/app/src/main/res/layout/activity_smscommunicator_otp.xml +++ b/app/src/main/res/layout/activity_smscommunicator_otp.xml @@ -9,7 +9,7 @@ android:layout_height="fill_parent"> @@ -32,7 +32,7 @@ android:text="@string/smscommunicator_otp_step2_provisioning_header" /> Date: Tue, 2 Feb 2021 20:48:03 +0100 Subject: [PATCH 13/84] SmsCommunicatorOtpActivity -> jetpack --- .../SmsCommunicatorFragment.kt | 27 ++++++++++++++----- .../res/layout/smscommunicator_fragment.xml | 19 +++++-------- 2 files changed, 28 insertions(+), 18 deletions(-) diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/smsCommunicator/SmsCommunicatorFragment.kt b/app/src/main/java/info/nightscout/androidaps/plugins/general/smsCommunicator/SmsCommunicatorFragment.kt index 49a1778a7e..092f67aa38 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/general/smsCommunicator/SmsCommunicatorFragment.kt +++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/smsCommunicator/SmsCommunicatorFragment.kt @@ -5,7 +5,7 @@ import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import dagger.android.support.DaggerFragment -import info.nightscout.androidaps.R +import info.nightscout.androidaps.databinding.SmscommunicatorFragmentBinding import info.nightscout.androidaps.plugins.bus.RxBusWrapper import info.nightscout.androidaps.plugins.general.smsCommunicator.events.EventSmsCommunicatorUpdateGui import info.nightscout.androidaps.utils.DateUtil @@ -14,22 +14,30 @@ import info.nightscout.androidaps.utils.HtmlHelper import info.nightscout.androidaps.utils.extensions.plusAssign import io.reactivex.android.schedulers.AndroidSchedulers import io.reactivex.disposables.CompositeDisposable -import kotlinx.android.synthetic.main.smscommunicator_fragment.* import java.util.* import javax.inject.Inject import kotlin.math.max class SmsCommunicatorFragment : DaggerFragment() { - @Inject lateinit var fabricPrivacy : FabricPrivacy + + @Inject lateinit var fabricPrivacy: FabricPrivacy @Inject lateinit var rxBus: RxBusWrapper @Inject lateinit var smsCommunicatorPlugin: SmsCommunicatorPlugin @Inject lateinit var dateUtil: DateUtil private val disposable = CompositeDisposable() + private var _binding: SmscommunicatorFragmentBinding? = null + + // This property is only valid between onCreateView and + // onDestroyView. + private val binding get() = _binding!! + override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, - savedInstanceState: Bundle?): View? { - return inflater.inflate(R.layout.smscommunicator_fragment, container, false) + savedInstanceState: Bundle?): View { + _binding = SmscommunicatorFragmentBinding.inflate(inflater, container, false) + return binding.root + } @Synchronized @@ -48,8 +56,15 @@ class SmsCommunicatorFragment : DaggerFragment() { disposable.clear() } + override fun onDestroyView() { + super.onDestroyView() + _binding = null + } + fun updateGui() { + if (_binding == null) return class CustomComparator : Comparator { + override fun compare(object1: Sms, object2: Sms): Int { return (object1.date - object2.date).toInt() } @@ -74,6 +89,6 @@ class SmsCommunicatorFragment : DaggerFragment() { } } } - smscommunicator_log?.text = HtmlHelper.fromHtml(logText) + binding.log.text = HtmlHelper.fromHtml(logText) } } \ No newline at end of file diff --git a/app/src/main/res/layout/smscommunicator_fragment.xml b/app/src/main/res/layout/smscommunicator_fragment.xml index c10b129605..acb97c9dc7 100644 --- a/app/src/main/res/layout/smscommunicator_fragment.xml +++ b/app/src/main/res/layout/smscommunicator_fragment.xml @@ -1,18 +1,13 @@ - - + - - - - + From 026d6039dc5945156c49638d9fb0e083a53392b4 Mon Sep 17 00:00:00 2001 From: Milos Kozak Date: Tue, 2 Feb 2021 21:04:44 +0100 Subject: [PATCH 14/84] SmsCommunicatorOtpActivity -> jetpack --- .../general/tidepool/TidepoolFragment.kt | 37 ++++++++++++++----- app/src/main/res/layout/tidepool_fragment.xml | 30 +++++++-------- 2 files changed, 42 insertions(+), 25 deletions(-) diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/tidepool/TidepoolFragment.kt b/app/src/main/java/info/nightscout/androidaps/plugins/general/tidepool/TidepoolFragment.kt index e11ee70a93..a3ac2622df 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/general/tidepool/TidepoolFragment.kt +++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/tidepool/TidepoolFragment.kt @@ -7,6 +7,7 @@ import android.view.ViewGroup import android.widget.ScrollView import dagger.android.support.DaggerFragment import info.nightscout.androidaps.R +import info.nightscout.androidaps.databinding.TidepoolFragmentBinding import info.nightscout.androidaps.plugins.bus.RxBusWrapper import info.nightscout.androidaps.plugins.general.tidepool.comm.TidepoolUploader import info.nightscout.androidaps.plugins.general.tidepool.events.EventTidepoolDoUpload @@ -29,16 +30,23 @@ class TidepoolFragment : DaggerFragment() { private var disposable: CompositeDisposable = CompositeDisposable() - override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { - return inflater.inflate(R.layout.tidepool_fragment, container, false) + private var _binding: TidepoolFragmentBinding? = null + + // This property is only valid between onCreateView and + // onDestroyView. + private val binding get() = _binding!! + + override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View { + _binding = TidepoolFragmentBinding.inflate(inflater, container, false) + return binding.root } override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) - tidepool_login.setOnClickListener { tidepoolUploader.doLogin(false) } - tidepool_uploadnow.setOnClickListener { rxBus.send(EventTidepoolDoUpload()) } - tidepool_removeall.setOnClickListener { rxBus.send(EventTidepoolResetData()) } - tidepool_resertstart.setOnClickListener { sp.putLong(R.string.key_tidepool_last_end, 0) } + binding.login.setOnClickListener { tidepoolUploader.doLogin(false) } + binding.uploadnow.setOnClickListener { rxBus.send(EventTidepoolDoUpload()) } + binding.removeall.setOnClickListener { rxBus.send(EventTidepoolResetData()) } + binding.resertstart.setOnClickListener { sp.putLong(R.string.key_tidepool_last_end, 0) } } @Synchronized @@ -48,11 +56,12 @@ class TidepoolFragment : DaggerFragment() { .toObservable(EventTidepoolUpdateGUI::class.java) .observeOn(AndroidSchedulers.mainThread()) .subscribe({ + if (_binding == null) return@subscribe tidepoolPlugin.updateLog() - tidepool_log?.text = tidepoolPlugin.textLog - tidepool_status?.text = tidepoolUploader.connectionStatus.name - tidepool_log?.text = tidepoolPlugin.textLog - tidepool_logscrollview?.fullScroll(ScrollView.FOCUS_DOWN) + binding.log.text = tidepoolPlugin.textLog + binding.status.text = tidepoolUploader.connectionStatus.name + binding.log.text = tidepoolPlugin.textLog + binding.logscrollview.fullScroll(ScrollView.FOCUS_DOWN) }, { fabricPrivacy.logException(it) }) } @@ -61,4 +70,12 @@ class TidepoolFragment : DaggerFragment() { super.onPause() disposable.clear() } + + @Synchronized + override fun onDestroyView() { + super.onDestroyView() + _binding = null + } + + } diff --git a/app/src/main/res/layout/tidepool_fragment.xml b/app/src/main/res/layout/tidepool_fragment.xml index 2640e96893..ef426f3f1a 100644 --- a/app/src/main/res/layout/tidepool_fragment.xml +++ b/app/src/main/res/layout/tidepool_fragment.xml @@ -5,7 +5,7 @@ android:layout_height="match_parent">