Merge pull request #3082 from swissalpine/garmin-sgv-json
Add iob, cob, tbr to GARMIN sgv.json endpoint
This commit is contained in:
commit
3cdf73ce46
|
@ -327,6 +327,14 @@ class GarminPlugin @Inject constructor(
|
||||||
GlucoseUnit.MGDL -> jo.addProperty("units_hint", "mgdl")
|
GlucoseUnit.MGDL -> jo.addProperty("units_hint", "mgdl")
|
||||||
GlucoseUnit.MMOL -> jo.addProperty("units_hint", "mmol")
|
GlucoseUnit.MMOL -> jo.addProperty("units_hint", "mmol")
|
||||||
}
|
}
|
||||||
|
jo.addProperty("iob", loopHub.insulinOnboard + loopHub.insulinBasalOnboard)
|
||||||
|
loopHub.temporaryBasal.also {
|
||||||
|
if (!it.isNaN()) {
|
||||||
|
val temporaryBasalRateInPercent = (it * 100.0).toInt()
|
||||||
|
jo.addProperty("tbr", temporaryBasalRateInPercent)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
jo.addProperty("cob", loopHub.carbsOnboard)
|
||||||
}
|
}
|
||||||
joa.add(jo)
|
joa.add(jo)
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,6 +20,12 @@ interface LoopHub {
|
||||||
/** Returns the remaining bolus insulin on board. */
|
/** Returns the remaining bolus insulin on board. */
|
||||||
val insulinOnboard: Double
|
val insulinOnboard: Double
|
||||||
|
|
||||||
|
/** Returns the basal insulin on board. */
|
||||||
|
val insulinBasalOnboard: Double
|
||||||
|
|
||||||
|
/** Returns the remaining carbs on board. */
|
||||||
|
val carbsOnboard: Double?
|
||||||
|
|
||||||
/** Returns true if the pump is connected. */
|
/** Returns true if the pump is connected. */
|
||||||
val isConnected: Boolean
|
val isConnected: Boolean
|
||||||
|
|
||||||
|
|
|
@ -13,6 +13,7 @@ import app.aaps.core.interfaces.profile.ProfileFunction
|
||||||
import app.aaps.core.interfaces.pump.DetailedBolusInfo
|
import app.aaps.core.interfaces.pump.DetailedBolusInfo
|
||||||
import app.aaps.core.interfaces.queue.CommandQueue
|
import app.aaps.core.interfaces.queue.CommandQueue
|
||||||
import app.aaps.core.interfaces.sharedPreferences.SP
|
import app.aaps.core.interfaces.sharedPreferences.SP
|
||||||
|
import app.aaps.core.main.graph.OverviewData
|
||||||
import app.aaps.database.ValueWrapper
|
import app.aaps.database.ValueWrapper
|
||||||
import app.aaps.database.entities.EffectiveProfileSwitch
|
import app.aaps.database.entities.EffectiveProfileSwitch
|
||||||
import app.aaps.database.entities.GlucoseValue
|
import app.aaps.database.entities.GlucoseValue
|
||||||
|
@ -42,6 +43,7 @@ class LoopHubImpl @Inject constructor(
|
||||||
private val repo: AppRepository,
|
private val repo: AppRepository,
|
||||||
private val userEntryLogger: UserEntryLogger,
|
private val userEntryLogger: UserEntryLogger,
|
||||||
private val sp: SP,
|
private val sp: SP,
|
||||||
|
private val overviewData: OverviewData,
|
||||||
) : LoopHub {
|
) : LoopHub {
|
||||||
|
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
|
@ -64,6 +66,14 @@ class LoopHubImpl @Inject constructor(
|
||||||
override val insulinOnboard: Double
|
override val insulinOnboard: Double
|
||||||
get() = iobCobCalculator.calculateIobFromBolus().iob
|
get() = iobCobCalculator.calculateIobFromBolus().iob
|
||||||
|
|
||||||
|
/** Returns the remaining bolus and basal insulin on board. */
|
||||||
|
override val insulinBasalOnboard :Double
|
||||||
|
get() = iobCobCalculator.calculateIobFromTempBasalsIncludingConvertedExtended().basaliob
|
||||||
|
|
||||||
|
/** Returns the remaining carbs on board. */
|
||||||
|
override val carbsOnboard: Double?
|
||||||
|
get() = overviewData.cobInfo(iobCobCalculator).displayCob
|
||||||
|
|
||||||
/** Returns true if the pump is connected. */
|
/** Returns true if the pump is connected. */
|
||||||
override val isConnected: Boolean get() = !loop.isDisconnected
|
override val isConnected: Boolean get() = !loop.isDisconnected
|
||||||
|
|
||||||
|
|
|
@ -57,6 +57,10 @@ class GarminPluginTest: TestBase() {
|
||||||
@AfterEach
|
@AfterEach
|
||||||
fun verifyNoFurtherInteractions() {
|
fun verifyNoFurtherInteractions() {
|
||||||
verify(loopHub, atMost(2)).currentProfileName
|
verify(loopHub, atMost(2)).currentProfileName
|
||||||
|
verify(loopHub, atMost(3)).insulinOnboard
|
||||||
|
verify(loopHub, atMost(3)).insulinBasalOnboard
|
||||||
|
verify(loopHub, atMost(3)).temporaryBasal
|
||||||
|
verify(loopHub, atMost(3)).carbsOnboard
|
||||||
verifyNoMoreInteractions(loopHub)
|
verifyNoMoreInteractions(loopHub)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -221,13 +225,17 @@ class GarminPluginTest: TestBase() {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun onSgv_NoDelta() {
|
fun onSgv_NoDelta() {
|
||||||
whenever(loopHub.glucoseUnit).thenReturn(GlucoseUnit.MMOL)
|
whenever(loopHub.glucoseUnit).thenReturn(GlucoseUnit.MMOL)
|
||||||
|
whenever(loopHub.insulinOnboard).thenReturn(2.7)
|
||||||
|
whenever(loopHub.insulinBasalOnboard).thenReturn(2.5)
|
||||||
|
whenever(loopHub.temporaryBasal).thenReturn(0.8)
|
||||||
|
whenever(loopHub.carbsOnboard).thenReturn(10.7)
|
||||||
whenever(loopHub.getGlucoseValues(any(), eq(false))).thenReturn(
|
whenever(loopHub.getGlucoseValues(any(), eq(false))).thenReturn(
|
||||||
listOf(createGlucoseValue(
|
listOf(createGlucoseValue(
|
||||||
clock.instant().minusSeconds(100L), 99.3)))
|
clock.instant().minusSeconds(100L), 99.3)))
|
||||||
assertEquals(
|
assertEquals(
|
||||||
"""[{"_id":"-900000","device":"RANDOM","deviceString":"1969-12-31T23:58:30Z","sysTime":"1969-12-31T23:58:30Z","unfiltered":90.0,"date":-90000,"sgv":99,"direction":"Flat","noise":4.5,"units_hint":"mmol"}]""",
|
"""[{"_id":"-900000","device":"RANDOM","deviceString":"1969-12-31T23:58:30Z","sysTime":"1969-12-31T23:58:30Z","unfiltered":90.0,"date":-90000,"sgv":99,"direction":"Flat","noise":4.5,"units_hint":"mmol","iob":5.2,"tbr":80,"cob":10.7}]""",
|
||||||
gp.onSgv(mock(), createUri(mapOf()), null))
|
gp.onSgv(mock(), createUri(mapOf()), null))
|
||||||
verify(loopHub).getGlucoseValues(clock.instant().minusSeconds(25L * 300L), false)
|
verify(loopHub).getGlucoseValues(clock.instant().minusSeconds(25L * 300L), false)
|
||||||
verify(loopHub).glucoseUnit
|
verify(loopHub).glucoseUnit
|
||||||
|
@ -236,26 +244,31 @@ class GarminPluginTest: TestBase() {
|
||||||
@Test
|
@Test
|
||||||
fun onSgv() {
|
fun onSgv() {
|
||||||
whenever(loopHub.glucoseUnit).thenReturn(GlucoseUnit.MMOL)
|
whenever(loopHub.glucoseUnit).thenReturn(GlucoseUnit.MMOL)
|
||||||
|
whenever(loopHub.insulinOnboard).thenReturn(2.7)
|
||||||
|
whenever(loopHub.insulinBasalOnboard).thenReturn(2.5)
|
||||||
|
whenever(loopHub.temporaryBasal).thenReturn(0.8)
|
||||||
|
whenever(loopHub.carbsOnboard).thenReturn(10.7)
|
||||||
whenever(loopHub.getGlucoseValues(any(), eq(false))).thenAnswer { i ->
|
whenever(loopHub.getGlucoseValues(any(), eq(false))).thenAnswer { i ->
|
||||||
val from = i.getArgument<Instant>(0)
|
val from = i.getArgument<Instant>(0)
|
||||||
fromClosedRange(from.toEpochMilli(), clock.instant().toEpochMilli(), 300_000L)
|
fromClosedRange(from.toEpochMilli(), clock.instant().toEpochMilli(), 300_000L)
|
||||||
.map(Instant::ofEpochMilli)
|
.map(Instant::ofEpochMilli)
|
||||||
.mapIndexed { idx, ts -> createGlucoseValue(ts, 100.0+(10 * idx)) }.reversed()}
|
.mapIndexed { idx, ts -> createGlucoseValue(ts, 100.0+(10 * idx)) }.reversed()}
|
||||||
assertEquals(
|
assertEquals(
|
||||||
"""[{"_id":"100000","device":"RANDOM","deviceString":"1970-01-01T00:00:10Z","sysTime":"1970-01-01T00:00:10Z","unfiltered":90.0,"date":10000,"sgv":120,"delta":10,"direction":"Flat","noise":4.5,"units_hint":"mmol"}]""",
|
"""[{"_id":"100000","device":"RANDOM","deviceString":"1970-01-01T00:00:10Z","sysTime":"1970-01-01T00:00:10Z","unfiltered":90.0,"date":10000,"sgv":120,"delta":10,"direction":"Flat","noise":4.5,"units_hint":"mmol","iob":5.2,"tbr":80,"cob":10.7}]""",
|
||||||
gp.onSgv(mock(), createUri(mapOf("count" to "1")), null))
|
gp.onSgv(mock(), createUri(mapOf("count" to "1")), null))
|
||||||
verify(loopHub).getGlucoseValues(
|
verify(loopHub).getGlucoseValues(
|
||||||
clock.instant().minusSeconds(600L), false)
|
clock.instant().minusSeconds(600L), false)
|
||||||
|
|
||||||
|
|
||||||
assertEquals(
|
assertEquals(
|
||||||
"""[{"_id":"100000","device":"RANDOM","deviceString":"1970-01-01T00:00:10Z","sysTime":"1970-01-01T00:00:10Z","unfiltered":90.0,"date":10000,"sgv":130,"delta":10,"direction":"Flat","noise":4.5,"units_hint":"mmol"},""" +
|
"""[{"_id":"100000","device":"RANDOM","deviceString":"1970-01-01T00:00:10Z","sysTime":"1970-01-01T00:00:10Z","unfiltered":90.0,"date":10000,"sgv":130,"delta":10,"direction":"Flat","noise":4.5,"units_hint":"mmol","iob":5.2,"tbr":80,"cob":10.7},""" +
|
||||||
"""{"_id":"-2900000","device":"RANDOM","deviceString":"1969-12-31T23:55:10Z","sysTime":"1969-12-31T23:55:10Z","unfiltered":90.0,"date":-290000,"sgv":120,"delta":10,"direction":"Flat","noise":4.5}]""",
|
"""{"_id":"-2900000","device":"RANDOM","deviceString":"1969-12-31T23:55:10Z","sysTime":"1969-12-31T23:55:10Z","unfiltered":90.0,"date":-290000,"sgv":120,"delta":10,"direction":"Flat","noise":4.5}]""",
|
||||||
gp.onSgv(mock(), createUri(mapOf("count" to "2")), null))
|
gp.onSgv(mock(), createUri(mapOf("count" to "2")), null))
|
||||||
verify(loopHub).getGlucoseValues(
|
verify(loopHub).getGlucoseValues(
|
||||||
clock.instant().minusSeconds(900L), false)
|
clock.instant().minusSeconds(900L), false)
|
||||||
|
|
||||||
assertEquals(
|
assertEquals(
|
||||||
"""[{"date":10000,"sgv":130,"delta":10,"direction":"Flat","noise":4.5,"units_hint":"mmol"},""" +
|
"""[{"date":10000,"sgv":130,"delta":10,"direction":"Flat","noise":4.5,"units_hint":"mmol","iob":5.2,"tbr":80,"cob":10.7},""" +
|
||||||
"""{"date":-290000,"sgv":120,"delta":10,"direction":"Flat","noise":4.5}]""",
|
"""{"date":-290000,"sgv":120,"delta":10,"direction":"Flat","noise":4.5}]""",
|
||||||
gp.onSgv(mock(), createUri(mapOf("count" to "2", "brief_mode" to "true")), null))
|
gp.onSgv(mock(), createUri(mapOf("count" to "2", "brief_mode" to "true")), null))
|
||||||
verify(loopHub, times(2)).getGlucoseValues(
|
verify(loopHub, times(2)).getGlucoseValues(
|
||||||
|
|
|
@ -5,6 +5,7 @@ import app.aaps.core.interfaces.aps.Loop
|
||||||
import app.aaps.core.interfaces.constraints.Constraint
|
import app.aaps.core.interfaces.constraints.Constraint
|
||||||
import app.aaps.core.interfaces.constraints.ConstraintsChecker
|
import app.aaps.core.interfaces.constraints.ConstraintsChecker
|
||||||
import app.aaps.core.interfaces.db.GlucoseUnit
|
import app.aaps.core.interfaces.db.GlucoseUnit
|
||||||
|
import app.aaps.core.interfaces.iob.CobInfo
|
||||||
import app.aaps.core.interfaces.iob.IobCobCalculator
|
import app.aaps.core.interfaces.iob.IobCobCalculator
|
||||||
import app.aaps.core.interfaces.iob.IobTotal
|
import app.aaps.core.interfaces.iob.IobTotal
|
||||||
import app.aaps.core.interfaces.logging.UserEntryLogger
|
import app.aaps.core.interfaces.logging.UserEntryLogger
|
||||||
|
@ -13,6 +14,7 @@ import app.aaps.core.interfaces.profile.ProfileFunction
|
||||||
import app.aaps.core.interfaces.pump.DetailedBolusInfo
|
import app.aaps.core.interfaces.pump.DetailedBolusInfo
|
||||||
import app.aaps.core.interfaces.queue.CommandQueue
|
import app.aaps.core.interfaces.queue.CommandQueue
|
||||||
import app.aaps.core.interfaces.sharedPreferences.SP
|
import app.aaps.core.interfaces.sharedPreferences.SP
|
||||||
|
import app.aaps.core.main.graph.OverviewData
|
||||||
import app.aaps.database.ValueWrapper
|
import app.aaps.database.ValueWrapper
|
||||||
import app.aaps.database.entities.EffectiveProfileSwitch
|
import app.aaps.database.entities.EffectiveProfileSwitch
|
||||||
import app.aaps.database.entities.GlucoseValue
|
import app.aaps.database.entities.GlucoseValue
|
||||||
|
@ -54,6 +56,7 @@ class LoopHubTest: TestBase() {
|
||||||
@Mock lateinit var repo: AppRepository
|
@Mock lateinit var repo: AppRepository
|
||||||
@Mock lateinit var userEntryLogger: UserEntryLogger
|
@Mock lateinit var userEntryLogger: UserEntryLogger
|
||||||
@Mock lateinit var sp: SP
|
@Mock lateinit var sp: SP
|
||||||
|
@Mock lateinit var overviewData: OverviewData
|
||||||
|
|
||||||
private lateinit var loopHub: LoopHubImpl
|
private lateinit var loopHub: LoopHubImpl
|
||||||
private val clock = Clock.fixed(Instant.ofEpochMilli(10_000), ZoneId.of("UTC"))
|
private val clock = Clock.fixed(Instant.ofEpochMilli(10_000), ZoneId.of("UTC"))
|
||||||
|
@ -62,7 +65,7 @@ class LoopHubTest: TestBase() {
|
||||||
fun setup() {
|
fun setup() {
|
||||||
loopHub = LoopHubImpl(
|
loopHub = LoopHubImpl(
|
||||||
aapsLogger, commandQueue, constraints, iobCobCalculator, loop,
|
aapsLogger, commandQueue, constraints, iobCobCalculator, loop,
|
||||||
profileFunction, repo, userEntryLogger, sp
|
profileFunction, repo, userEntryLogger, sp, overviewData
|
||||||
)
|
)
|
||||||
loopHub.clock = clock
|
loopHub.clock = clock
|
||||||
}
|
}
|
||||||
|
@ -76,9 +79,10 @@ class LoopHubTest: TestBase() {
|
||||||
verifyNoMoreInteractions(profileFunction)
|
verifyNoMoreInteractions(profileFunction)
|
||||||
verifyNoMoreInteractions(repo)
|
verifyNoMoreInteractions(repo)
|
||||||
verifyNoMoreInteractions(userEntryLogger)
|
verifyNoMoreInteractions(userEntryLogger)
|
||||||
|
verifyNoMoreInteractions(overviewData)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testCurrentProfile() {
|
fun testCurrentProfile() {
|
||||||
val profile = mock(Profile::class.java)
|
val profile = mock(Profile::class.java)
|
||||||
`when`(profileFunction.getProfile()).thenReturn(profile)
|
`when`(profileFunction.getProfile()).thenReturn(profile)
|
||||||
|
@ -109,6 +113,22 @@ class LoopHubTest: TestBase() {
|
||||||
verify(iobCobCalculator, times(1)).calculateIobFromBolus()
|
verify(iobCobCalculator, times(1)).calculateIobFromBolus()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testBasalOnBoard() {
|
||||||
|
val iobBasal = IobTotal(time = 0).apply { basaliob = 23.9 }
|
||||||
|
`when`(iobCobCalculator.calculateIobFromTempBasalsIncludingConvertedExtended()).thenReturn(iobBasal)
|
||||||
|
assertEquals(23.9, loopHub.insulinBasalOnboard, 1e-10)
|
||||||
|
verify(iobCobCalculator, times(1)).calculateIobFromTempBasalsIncludingConvertedExtended()
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testCarbsOnBoard() {
|
||||||
|
val cobInfo = CobInfo(0, 12.0, 0.0)
|
||||||
|
`when`(overviewData.cobInfo(iobCobCalculator)).thenReturn(cobInfo)
|
||||||
|
assertEquals(12.0, loopHub.carbsOnboard)
|
||||||
|
verify(overviewData, times(1)).cobInfo(iobCobCalculator)
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testIsConnected() {
|
fun testIsConnected() {
|
||||||
`when`(loop.isDisconnected).thenReturn(false)
|
`when`(loop.isDisconnected).thenReturn(false)
|
||||||
|
|
Loading…
Reference in a new issue