NSCLIENT: upload only valid profiles
This commit is contained in:
parent
7ffb273a8d
commit
50c2a19743
|
@ -940,6 +940,7 @@ class DataSyncSelectorImplementation @Inject constructor(
|
||||||
val lastChange = sp.getLong(R.string.key_local_profile_last_change, 0)
|
val lastChange = sp.getLong(R.string.key_local_profile_last_change, 0)
|
||||||
if (lastChange == 0L) return
|
if (lastChange == 0L) return
|
||||||
if (lastChange > lastSync) {
|
if (lastChange > lastSync) {
|
||||||
|
if (localProfilePlugin.profile?.allProfilesValid != true) return
|
||||||
val profileJson = localProfilePlugin.profile?.data ?: return
|
val profileJson = localProfilePlugin.profile?.data ?: return
|
||||||
nsClientPlugin.nsClientService?.dbAdd("profile", profileJson, DataSyncSelector.PairProfileStore(profileJson, dateUtil.now()), "")
|
nsClientPlugin.nsClientService?.dbAdd("profile", profileJson, DataSyncSelector.PairProfileStore(profileJson, dateUtil.now()), "")
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,19 +2,26 @@ package info.nightscout.androidaps.interfaces
|
||||||
|
|
||||||
import androidx.collection.ArrayMap
|
import androidx.collection.ArrayMap
|
||||||
import dagger.android.HasAndroidInjector
|
import dagger.android.HasAndroidInjector
|
||||||
|
import info.nightscout.androidaps.data.ProfileSealed
|
||||||
import info.nightscout.androidaps.data.PureProfile
|
import info.nightscout.androidaps.data.PureProfile
|
||||||
import info.nightscout.androidaps.extensions.pureProfileFromJson
|
import info.nightscout.androidaps.extensions.pureProfileFromJson
|
||||||
import info.nightscout.shared.logging.AAPSLogger
|
import info.nightscout.androidaps.plugins.bus.RxBus
|
||||||
import info.nightscout.androidaps.utils.DateUtil
|
import info.nightscout.androidaps.utils.DateUtil
|
||||||
|
import info.nightscout.androidaps.utils.HardLimits
|
||||||
import info.nightscout.androidaps.utils.JsonHelper
|
import info.nightscout.androidaps.utils.JsonHelper
|
||||||
|
import info.nightscout.shared.logging.AAPSLogger
|
||||||
import org.json.JSONException
|
import org.json.JSONException
|
||||||
import org.json.JSONObject
|
import org.json.JSONObject
|
||||||
import java.util.*
|
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
class ProfileStore(val injector: HasAndroidInjector, val data: JSONObject, val dateUtil: DateUtil) {
|
class ProfileStore(val injector: HasAndroidInjector, val data: JSONObject, val dateUtil: DateUtil) {
|
||||||
|
|
||||||
@Inject lateinit var aapsLogger: AAPSLogger
|
@Inject lateinit var aapsLogger: AAPSLogger
|
||||||
|
@Inject lateinit var activePlugin: ActivePlugin
|
||||||
|
@Inject lateinit var config: Config
|
||||||
|
@Inject lateinit var rh: ResourceHelper
|
||||||
|
@Inject lateinit var rxBus: RxBus
|
||||||
|
@Inject lateinit var hardLimits: HardLimits
|
||||||
|
|
||||||
init {
|
init {
|
||||||
injector.androidInjector().inject(this)
|
injector.androidInjector().inject(this)
|
||||||
|
@ -22,7 +29,7 @@ class ProfileStore(val injector: HasAndroidInjector, val data: JSONObject, val d
|
||||||
|
|
||||||
private val cachedObjects = ArrayMap<String, PureProfile>()
|
private val cachedObjects = ArrayMap<String, PureProfile>()
|
||||||
|
|
||||||
private fun storeUnits() : String? = JsonHelper.safeGetStringAllowNull(data, "units", null)
|
private fun storeUnits(): String? = JsonHelper.safeGetStringAllowNull(data, "units", null)
|
||||||
|
|
||||||
private fun getStore(): JSONObject? {
|
private fun getStore(): JSONObject? {
|
||||||
try {
|
try {
|
||||||
|
@ -86,4 +93,11 @@ class ProfileStore(val injector: HasAndroidInjector, val data: JSONObject, val d
|
||||||
}
|
}
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val allProfilesValid: Boolean
|
||||||
|
get() = getProfileList()
|
||||||
|
.asSequence()
|
||||||
|
.map { profileName -> getSpecificProfile(profileName.toString()) }
|
||||||
|
.map { pureProfile -> pureProfile?.let { ProfileSealed.Pure(pureProfile).isValid("allProfilesValid", activePlugin.activePump, config, rh, rxBus, hardLimits, false) } }
|
||||||
|
.all { it?.isValid == true}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,22 +1,27 @@
|
||||||
package info.nightscout.androidaps
|
package info.nightscout.androidaps
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
import dagger.android.AndroidInjector
|
import dagger.android.AndroidInjector
|
||||||
import dagger.android.HasAndroidInjector
|
import dagger.android.HasAndroidInjector
|
||||||
import info.nightscout.androidaps.data.ProfileSealed
|
import info.nightscout.androidaps.data.ProfileSealed
|
||||||
|
import info.nightscout.androidaps.database.AppRepository
|
||||||
import info.nightscout.androidaps.extensions.pureProfileFromJson
|
import info.nightscout.androidaps.extensions.pureProfileFromJson
|
||||||
import info.nightscout.androidaps.interfaces.ActivePlugin
|
import info.nightscout.androidaps.interfaces.ActivePlugin
|
||||||
import info.nightscout.androidaps.interfaces.Config
|
import info.nightscout.androidaps.interfaces.Config
|
||||||
import info.nightscout.androidaps.interfaces.Profile
|
import info.nightscout.androidaps.interfaces.Profile
|
||||||
import info.nightscout.androidaps.interfaces.ProfileFunction
|
import info.nightscout.androidaps.interfaces.ProfileFunction
|
||||||
import info.nightscout.androidaps.interfaces.ProfileStore
|
import info.nightscout.androidaps.interfaces.ProfileStore
|
||||||
|
import info.nightscout.androidaps.interfaces.ResourceHelper
|
||||||
import info.nightscout.androidaps.plugins.bus.RxBus
|
import info.nightscout.androidaps.plugins.bus.RxBus
|
||||||
import info.nightscout.androidaps.utils.DateUtil
|
import info.nightscout.androidaps.utils.DateUtil
|
||||||
import info.nightscout.androidaps.utils.DefaultValueHelper
|
import info.nightscout.androidaps.utils.DefaultValueHelper
|
||||||
import info.nightscout.androidaps.utils.FabricPrivacy
|
import info.nightscout.androidaps.utils.FabricPrivacy
|
||||||
import info.nightscout.androidaps.interfaces.ResourceHelper
|
import info.nightscout.androidaps.utils.HardLimits
|
||||||
|
import info.nightscout.shared.sharedPreferences.SP
|
||||||
import org.json.JSONObject
|
import org.json.JSONObject
|
||||||
import org.junit.Before
|
import org.junit.Before
|
||||||
import org.mockito.Mock
|
import org.mockito.Mock
|
||||||
|
import org.mockito.Mockito
|
||||||
|
|
||||||
@Suppress("SpellCheckingInspection")
|
@Suppress("SpellCheckingInspection")
|
||||||
open class TestBaseWithProfile : TestBase() {
|
open class TestBaseWithProfile : TestBase() {
|
||||||
|
@ -28,24 +33,44 @@ open class TestBaseWithProfile : TestBase() {
|
||||||
@Mock lateinit var defaultValueHelper: DefaultValueHelper
|
@Mock lateinit var defaultValueHelper: DefaultValueHelper
|
||||||
@Mock lateinit var dateUtil: DateUtil
|
@Mock lateinit var dateUtil: DateUtil
|
||||||
@Mock lateinit var config: Config
|
@Mock lateinit var config: Config
|
||||||
|
@Mock lateinit var sp: SP
|
||||||
|
@Mock lateinit var context: Context
|
||||||
|
@Mock lateinit var repository: AppRepository
|
||||||
|
|
||||||
|
lateinit var testPumpPlugin: TestPumpPlugin
|
||||||
|
|
||||||
val rxBus = RxBus(aapsSchedulers, aapsLogger)
|
val rxBus = RxBus(aapsSchedulers, aapsLogger)
|
||||||
|
|
||||||
val profileInjector = HasAndroidInjector {
|
val profileInjector = HasAndroidInjector {
|
||||||
AndroidInjector {
|
AndroidInjector {
|
||||||
|
if (it is ProfileStore) {
|
||||||
|
it.aapsLogger = aapsLogger
|
||||||
|
it.activePlugin = activePluginProvider
|
||||||
|
it.config = config
|
||||||
|
it.rh = rh
|
||||||
|
it.rxBus = rxBus
|
||||||
|
it.hardLimits = HardLimits(aapsLogger, rxBus, sp, rh, context, repository)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private lateinit var invalidProfileJSON: String
|
||||||
private lateinit var validProfileJSON: String
|
private lateinit var validProfileJSON: String
|
||||||
lateinit var validProfile: Profile
|
lateinit var validProfile: Profile
|
||||||
|
lateinit var invalidProfile: Profile
|
||||||
@Suppress("PropertyName") val TESTPROFILENAME = "someProfile"
|
@Suppress("PropertyName") val TESTPROFILENAME = "someProfile"
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
fun prepareMock() {
|
fun prepareMock() {
|
||||||
|
invalidProfileJSON = "{\"dia\":\"1\",\"carbratio\":[{\"time\":\"00:00\",\"value\":\"30\"}],\"carbs_hr\":\"20\",\"delay\":\"20\",\"sens\":[{\"time\":\"00:00\",\"value\":\"3\"}," +
|
||||||
|
"{\"time\":\"2:00\",\"value\":\"3.4\"}],\"timezone\":\"UTC\",\"basal\":[{\"time\":\"00:00\",\"value\":\"1\"}],\"target_low\":[{\"time\":\"00:00\",\"value\":\"4.5\"}]," +
|
||||||
|
"\"target_high\":[{\"time\":\"00:00\",\"value\":\"7\"}],\"startDate\":\"1970-01-01T00:00:00.000Z\",\"units\":\"mmol\"}"
|
||||||
validProfileJSON = "{\"dia\":\"5\",\"carbratio\":[{\"time\":\"00:00\",\"value\":\"30\"}],\"carbs_hr\":\"20\",\"delay\":\"20\",\"sens\":[{\"time\":\"00:00\",\"value\":\"3\"}," +
|
validProfileJSON = "{\"dia\":\"5\",\"carbratio\":[{\"time\":\"00:00\",\"value\":\"30\"}],\"carbs_hr\":\"20\",\"delay\":\"20\",\"sens\":[{\"time\":\"00:00\",\"value\":\"3\"}," +
|
||||||
"{\"time\":\"2:00\",\"value\":\"3.4\"}],\"timezone\":\"UTC\",\"basal\":[{\"time\":\"00:00\",\"value\":\"1\"}],\"target_low\":[{\"time\":\"00:00\",\"value\":\"4.5\"}]," +
|
"{\"time\":\"2:00\",\"value\":\"3.4\"}],\"timezone\":\"UTC\",\"basal\":[{\"time\":\"00:00\",\"value\":\"1\"}],\"target_low\":[{\"time\":\"00:00\",\"value\":\"4.5\"}]," +
|
||||||
"\"target_high\":[{\"time\":\"00:00\",\"value\":\"7\"}],\"startDate\":\"1970-01-01T00:00:00.000Z\",\"units\":\"mmol\"}"
|
"\"target_high\":[{\"time\":\"00:00\",\"value\":\"7\"}],\"startDate\":\"1970-01-01T00:00:00.000Z\",\"units\":\"mmol\"}"
|
||||||
validProfile = ProfileSealed.Pure(pureProfileFromJson(JSONObject(validProfileJSON), dateUtil)!!)
|
validProfile = ProfileSealed.Pure(pureProfileFromJson(JSONObject(validProfileJSON), dateUtil)!!)
|
||||||
|
testPumpPlugin = TestPumpPlugin(profileInjector)
|
||||||
|
Mockito.`when`(activePluginProvider.activePump).thenReturn(testPumpPlugin)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getValidProfileStore(): ProfileStore {
|
fun getValidProfileStore(): ProfileStore {
|
||||||
|
@ -56,4 +81,22 @@ open class TestBaseWithProfile : TestBase() {
|
||||||
json.put("store", store)
|
json.put("store", store)
|
||||||
return ProfileStore(profileInjector, json, dateUtil)
|
return ProfileStore(profileInjector, json, dateUtil)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun getInvalidProfileStore1(): ProfileStore {
|
||||||
|
val json = JSONObject()
|
||||||
|
val store = JSONObject()
|
||||||
|
store.put(TESTPROFILENAME, JSONObject(invalidProfileJSON))
|
||||||
|
json.put("defaultProfile", TESTPROFILENAME)
|
||||||
|
json.put("store", store)
|
||||||
|
return ProfileStore(profileInjector, json, dateUtil)
|
||||||
|
}
|
||||||
|
fun getInvalidProfileStore2(): ProfileStore {
|
||||||
|
val json = JSONObject()
|
||||||
|
val store = JSONObject()
|
||||||
|
store.put(TESTPROFILENAME, JSONObject(validProfileJSON))
|
||||||
|
store.put("invalid", JSONObject(invalidProfileJSON))
|
||||||
|
json.put("defaultProfile", TESTPROFILENAME)
|
||||||
|
json.put("store", store)
|
||||||
|
return ProfileStore(profileInjector, json, dateUtil)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,46 @@
|
||||||
|
package info.nightscout.androidaps.interfaces
|
||||||
|
|
||||||
|
import info.nightscout.androidaps.TestBaseWithProfile
|
||||||
|
import info.nightscout.androidaps.data.PureProfile
|
||||||
|
import org.junit.Assert
|
||||||
|
import org.junit.Test
|
||||||
|
|
||||||
|
internal class ProfileStoreTest : TestBaseWithProfile() {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun getStartDateTest() {
|
||||||
|
Assert.assertEquals(0, getValidProfileStore().getStartDate())
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun getDefaultProfileTest() {
|
||||||
|
Assert.assertTrue(getValidProfileStore().getDefaultProfile() is PureProfile)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun getDefaultProfileJsonTest() {
|
||||||
|
Assert.assertTrue(getValidProfileStore().getDefaultProfileJson()?.has("dia") ?: false)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun getDefaultProfileNameTest() {
|
||||||
|
Assert.assertEquals(TESTPROFILENAME, getValidProfileStore().getDefaultProfileName())
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun getProfileListTest() {
|
||||||
|
Assert.assertEquals(1, getValidProfileStore().getProfileList().size)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun getSpecificProfileTest() {
|
||||||
|
Assert.assertTrue(getValidProfileStore().getSpecificProfile(TESTPROFILENAME) is PureProfile)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun allProfilesValidTest() {
|
||||||
|
Assert.assertTrue(getValidProfileStore().allProfilesValid)
|
||||||
|
Assert.assertFalse(getInvalidProfileStore1().allProfilesValid)
|
||||||
|
Assert.assertFalse(getInvalidProfileStore2().allProfilesValid)
|
||||||
|
}
|
||||||
|
}
|
|
@ -3,14 +3,12 @@ package info.nightscout.androidaps.plugins.aps.loop
|
||||||
import dagger.android.AndroidInjector
|
import dagger.android.AndroidInjector
|
||||||
import dagger.android.HasAndroidInjector
|
import dagger.android.HasAndroidInjector
|
||||||
import info.nightscout.androidaps.TestBaseWithProfile
|
import info.nightscout.androidaps.TestBaseWithProfile
|
||||||
import info.nightscout.androidaps.TestPumpPlugin
|
|
||||||
import info.nightscout.androidaps.database.entities.TemporaryBasal
|
import info.nightscout.androidaps.database.entities.TemporaryBasal
|
||||||
import info.nightscout.androidaps.interfaces.Constraint
|
import info.nightscout.androidaps.interfaces.Constraint
|
||||||
import info.nightscout.androidaps.interfaces.IobCobCalculator
|
import info.nightscout.androidaps.interfaces.IobCobCalculator
|
||||||
import info.nightscout.androidaps.plugins.configBuilder.ConstraintChecker
|
import info.nightscout.androidaps.plugins.configBuilder.ConstraintChecker
|
||||||
import info.nightscout.androidaps.plugins.pump.common.defs.PumpType
|
import info.nightscout.androidaps.plugins.pump.common.defs.PumpType
|
||||||
import info.nightscout.androidaps.utils.JsonHelper.safeGetDouble
|
import info.nightscout.androidaps.utils.JsonHelper.safeGetDouble
|
||||||
import info.nightscout.shared.sharedPreferences.SP
|
|
||||||
import org.junit.Assert
|
import org.junit.Assert
|
||||||
import org.junit.Before
|
import org.junit.Before
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
|
@ -21,10 +19,8 @@ import org.mockito.Mockito.`when`
|
||||||
class APSResultTest : TestBaseWithProfile() {
|
class APSResultTest : TestBaseWithProfile() {
|
||||||
|
|
||||||
@Mock lateinit var constraintChecker: ConstraintChecker
|
@Mock lateinit var constraintChecker: ConstraintChecker
|
||||||
@Mock lateinit var sp: SP
|
|
||||||
@Mock lateinit var iobCobCalculator: IobCobCalculator
|
@Mock lateinit var iobCobCalculator: IobCobCalculator
|
||||||
|
|
||||||
private lateinit var testPumpPlugin: TestPumpPlugin
|
|
||||||
private val injector = HasAndroidInjector { AndroidInjector { } }
|
private val injector = HasAndroidInjector { AndroidInjector { } }
|
||||||
|
|
||||||
private var closedLoopEnabled = Constraint(false)
|
private var closedLoopEnabled = Constraint(false)
|
||||||
|
@ -188,7 +184,6 @@ class APSResultTest : TestBaseWithProfile() {
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
fun prepare() {
|
fun prepare() {
|
||||||
testPumpPlugin = TestPumpPlugin(profileInjector)
|
|
||||||
`when`(constraintChecker.isClosedLoopAllowed()).thenReturn(closedLoopEnabled)
|
`when`(constraintChecker.isClosedLoopAllowed()).thenReturn(closedLoopEnabled)
|
||||||
`when`(activePluginProvider.activePump).thenReturn(testPumpPlugin)
|
`when`(activePluginProvider.activePump).thenReturn(testPumpPlugin)
|
||||||
`when`(sp.getDouble(ArgumentMatchers.anyInt(), ArgumentMatchers.anyDouble())).thenReturn(30.0)
|
`when`(sp.getDouble(ArgumentMatchers.anyInt(), ArgumentMatchers.anyDouble())).thenReturn(30.0)
|
||||||
|
|
Loading…
Reference in a new issue