NSCv3: process DeviceStatus
This commit is contained in:
parent
854acc2992
commit
d190b53713
12 changed files with 846 additions and 300 deletions
|
@ -1,10 +1,15 @@
|
|||
package info.nightscout.interfaces.utils
|
||||
|
||||
import android.text.Html
|
||||
import android.text.SpannableStringBuilder
|
||||
import android.text.Spanned
|
||||
|
||||
object HtmlHelper {
|
||||
fun fromHtml(source: String): Spanned {
|
||||
return Html.fromHtml(source, Html.FROM_HTML_MODE_LEGACY)
|
||||
|
||||
fun fromHtml(source: String): Spanned =
|
||||
try {
|
||||
Html.fromHtml(source, Html.FROM_HTML_MODE_LEGACY)
|
||||
} catch (e: Exception) {
|
||||
SpannableStringBuilder("")
|
||||
}
|
||||
}
|
|
@ -227,6 +227,34 @@ class NSAndroidClientImpl(
|
|||
}
|
||||
}
|
||||
|
||||
override suspend fun createDeviceStatus(remoteDeviceStatus: RemoteDeviceStatus): CreateUpdateResponse = callWrapper(dispatcher) {
|
||||
|
||||
remoteDeviceStatus.app = "AAPS"
|
||||
val response = api.createDeviceStatus(remoteDeviceStatus)
|
||||
if (response.isSuccessful) {
|
||||
if (response.code() == 200) {
|
||||
return@callWrapper CreateUpdateResponse(
|
||||
response = response.code(),
|
||||
identifier = null,
|
||||
isDeduplication = true,
|
||||
deduplicatedIdentifier = null,
|
||||
lastModified = null
|
||||
)
|
||||
} else if (response.code() == 201) {
|
||||
return@callWrapper CreateUpdateResponse(
|
||||
response = response.code(),
|
||||
identifier = response.body()?.result?.identifier
|
||||
?: throw UnknownResponseNightscoutException(),
|
||||
isDeduplication = response.body()?.result?.isDeduplication ?: false,
|
||||
deduplicatedIdentifier = response.body()?.result?.deduplicatedIdentifier,
|
||||
lastModified = response.body()?.result?.lastModified
|
||||
)
|
||||
} else throw UnknownResponseNightscoutException()
|
||||
} else {
|
||||
throw UnsuccessfullNightscoutException()
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun createTreatment(nsTreatment: NSTreatment): CreateUpdateResponse = callWrapper(dispatcher) {
|
||||
|
||||
val remoteTreatment = nsTreatment.toRemoteTreatment() ?: throw InvalidFormatNightscoutException()
|
||||
|
|
|
@ -3,22 +3,13 @@ package info.nightscout.sdk
|
|||
import info.nightscout.sdk.interfaces.NSAndroidClient
|
||||
import info.nightscout.sdk.interfaces.NSAndroidRxClient
|
||||
import info.nightscout.sdk.localmodel.Status
|
||||
import info.nightscout.sdk.localmodel.entry.NSSgvV3
|
||||
import info.nightscout.sdk.localmodel.treatment.NSTreatment
|
||||
import info.nightscout.sdk.remotemodel.LastModified
|
||||
import info.nightscout.sdk.remotemodel.RemoteDeviceStatus
|
||||
import io.reactivex.rxjava3.core.Single
|
||||
import kotlinx.coroutines.rx3.rxSingle
|
||||
import retrofit2.http.Query
|
||||
|
||||
class NSAndroidRxClientImpl(private val client: NSAndroidClient) : NSAndroidRxClient {
|
||||
|
||||
override fun getVersion(): Single<String> = rxSingle { client.getVersion() }
|
||||
override fun getStatus(): Single<Status> = rxSingle { client.getStatus() }
|
||||
override fun getLastModified(): Single<LastModified> = rxSingle { client.getLastModified() }
|
||||
override fun getSgvsModifiedSince(from: Long, limit: Long): Single<NSAndroidClient.ReadResponse<List<NSSgvV3>>> = rxSingle { client.getSgvsModifiedSince(from, limit) }
|
||||
override fun getTreatmentsModifiedSince(from: Long, limit: Long): Single<NSAndroidClient.ReadResponse<List<NSTreatment>>> =
|
||||
rxSingle { client.getTreatmentsModifiedSince(from, limit) }
|
||||
override fun getDeviceStatusModifiedSince(from: Long): Single<List<RemoteDeviceStatus>> =
|
||||
rxSingle { client.getDeviceStatusModifiedSince(from) }
|
||||
}
|
||||
|
|
|
@ -19,17 +19,23 @@ interface NSAndroidClient {
|
|||
suspend fun getVersion(): String
|
||||
suspend fun getStatus(): Status
|
||||
suspend fun getLastModified(): LastModified
|
||||
|
||||
suspend fun getSgvs(): List<NSSgvV3>
|
||||
suspend fun getSgvsModifiedSince(from: Long, limit: Long): ReadResponse<List<NSSgvV3>>
|
||||
suspend fun getSgvsNewerThan(from: Long, limit: Long): List<NSSgvV3>
|
||||
suspend fun createSvg(nsSgvV3: NSSgvV3): CreateUpdateResponse
|
||||
suspend fun updateSvg(nsSgvV3: NSSgvV3): CreateUpdateResponse
|
||||
|
||||
suspend fun getTreatmentsNewerThan(createdAt: String, limit: Long): List<NSTreatment>
|
||||
suspend fun getTreatmentsModifiedSince(from: Long, limit: Long): ReadResponse<List<NSTreatment>>
|
||||
|
||||
suspend fun createDeviceStatus(remoteDeviceStatus: RemoteDeviceStatus): CreateUpdateResponse
|
||||
suspend fun getDeviceStatusModifiedSince(from: Long): List<RemoteDeviceStatus>
|
||||
|
||||
suspend fun createTreatment(nsTreatment: NSTreatment): CreateUpdateResponse
|
||||
suspend fun updateTreatment(nsTreatment: NSTreatment): CreateUpdateResponse
|
||||
suspend fun getFoods(limit: Long): List<NSFood>
|
||||
|
||||
//suspend fun getFoodsModifiedSince(from: Long, limit: Long): ReadResponse<List<NSFood>>
|
||||
suspend fun createFood(nsFood: NSFood): CreateUpdateResponse
|
||||
suspend fun updateFood(nsFood: NSFood): CreateUpdateResponse
|
||||
|
|
|
@ -1,10 +1,7 @@
|
|||
package info.nightscout.sdk.interfaces
|
||||
|
||||
import info.nightscout.sdk.localmodel.Status
|
||||
import info.nightscout.sdk.localmodel.entry.NSSgvV3
|
||||
import info.nightscout.sdk.localmodel.treatment.NSTreatment
|
||||
import info.nightscout.sdk.remotemodel.LastModified
|
||||
import info.nightscout.sdk.remotemodel.RemoteDeviceStatus
|
||||
import io.reactivex.rxjava3.core.Single
|
||||
|
||||
interface NSAndroidRxClient {
|
||||
|
@ -12,8 +9,5 @@ interface NSAndroidRxClient {
|
|||
fun getVersion(): Single<String>
|
||||
fun getStatus(): Single<Status>
|
||||
fun getLastModified(): Single<LastModified>
|
||||
fun getSgvsModifiedSince(from: Long, limit: Long): Single<NSAndroidClient.ReadResponse<List<NSSgvV3>>>
|
||||
fun getTreatmentsModifiedSince(from: Long, limit: Long): Single<NSAndroidClient.ReadResponse<List<NSTreatment>>>
|
||||
fun getDeviceStatusModifiedSince(from: Long): Single<List<RemoteDeviceStatus>>
|
||||
}
|
||||
|
||||
|
|
|
@ -56,15 +56,18 @@ internal interface NightscoutRemoteService {
|
|||
@GET("v3/treatments/history/{from}")
|
||||
suspend fun getTreatmentsModifiedSince(@Path("from") from: Long, @Query("limit") limit: Long): Response<NSResponse<List<RemoteTreatment>>>
|
||||
|
||||
@GET("v3/devicestatus/history/{from}")
|
||||
suspend fun getDeviceStatusModifiedSince(@Path("from") from: Long): Response<NSResponse<List<RemoteDeviceStatus>>>
|
||||
|
||||
@POST("v3/treatments")
|
||||
suspend fun createTreatment(@Body remoteTreatment: RemoteTreatment): Response<NSResponse<RemoteCreateUpdateResponse>>
|
||||
|
||||
@PATCH("v3/treatments/{identifier}")
|
||||
suspend fun updateTreatment(@Body remoteTreatment: RemoteTreatment, @Path("identifier") identifier: String): Response<NSResponse<RemoteCreateUpdateResponse>>
|
||||
|
||||
@POST("v3/devicestatus")
|
||||
suspend fun createDeviceStatus(@Body remoteDeviceStatus: RemoteDeviceStatus): Response<NSResponse<RemoteCreateUpdateResponse>>
|
||||
|
||||
@GET("v3/devicestatus/history/{from}")
|
||||
suspend fun getDeviceStatusModifiedSince(@Path("from") from: Long): Response<NSResponse<List<RemoteDeviceStatus>>>
|
||||
|
||||
@GET("v3/food")
|
||||
suspend fun getFoods(@Query("limit") limit: Long): Response<NSResponse<List<RemoteFood>>>
|
||||
/*
|
||||
|
|
|
@ -11,10 +11,12 @@ import org.json.JSONObject
|
|||
**/
|
||||
@Serializable
|
||||
data class RemoteDeviceStatus(
|
||||
@SerializedName("identifier") val identifier: String?, // string Main addressing, required field that identifies document in the collection. The client should not create the identifier, the server automatically assigns it when the document is inserted.
|
||||
@SerializedName("srvCreated") val srvCreated: Long?, // integer($int64) example: 1525383610088 The server's timestamp of document insertion into the database (Unix epoch in ms). This field appears only for documents which were inserted by API v3.
|
||||
@SerializedName("srvModified") val srvModified: Long?, // integer($int64) example: 1525383610088 The server's timestamp of the last document modification in the database (Unix epoch in ms). This field appears only for documents which were somehow modified by API v3 (inserted, updated or deleted).
|
||||
@SerializedName("created_at") val createdAt: String?, // string or string timestamp on previous version of api, in my examples, a lot of treatments don't have date, only created_at, some of them with string others with long...
|
||||
@SerializedName("app") var app: String? = null,
|
||||
@SerializedName("identifier") val identifier: String? = null, // string Main addressing, required field that identifies document in the collection. The client should not create the identifier, the server automatically assigns it when the document is inserted.
|
||||
@SerializedName("srvCreated") val srvCreated: Long? = null, // integer($int64) example: 1525383610088 The server's timestamp of document insertion into the database (Unix epoch in ms). This field appears only for documents which were inserted by API v3.
|
||||
@SerializedName("srvModified") val srvModified: Long? = null, // integer($int64) example: 1525383610088 The server's timestamp of the last document modification in the database (Unix epoch in ms). This field appears only for documents which were somehow modified by API v3 (inserted, updated or deleted).
|
||||
@SerializedName("created_at") val createdAt: String? = null, // string or string timestamp on previous version of api, in my examples, a lot of treatments don't have date, only created_at, some of them with string others with long...
|
||||
@SerializedName("date") val date: Long?, // date as milliseconds
|
||||
@SerializedName("uploaderBattery") val uploaderBattery: Int?,// integer($int64)
|
||||
@SerializedName("device") val device: String?, // "openaps://samsung SM-G970F"
|
||||
|
||||
|
|
|
@ -28,6 +28,7 @@ dependencies {
|
|||
|
||||
testImplementation "androidx.work:work-testing:$work_version"
|
||||
testImplementation project(':implementation')
|
||||
testImplementation project(':plugins:aps')
|
||||
|
||||
// NSClient, Tidepool
|
||||
api("io.socket:socket.io-client:1.0.2") {
|
||||
|
|
|
@ -47,6 +47,7 @@ import info.nightscout.plugins.sync.nsclientV3.extensions.toNSSvgV3
|
|||
import info.nightscout.plugins.sync.nsclientV3.extensions.toNSTemporaryBasal
|
||||
import info.nightscout.plugins.sync.nsclientV3.extensions.toNSTemporaryTarget
|
||||
import info.nightscout.plugins.sync.nsclientV3.extensions.toNSTherapyEvent
|
||||
import info.nightscout.plugins.sync.nsclientV3.extensions.toRemoteDeviceStatus
|
||||
import info.nightscout.plugins.sync.nsclientV3.workers.LoadBgWorker
|
||||
import info.nightscout.plugins.sync.nsclientV3.workers.LoadLastModificationWorker
|
||||
import info.nightscout.plugins.sync.nsclientV3.workers.LoadStatusWorker
|
||||
|
@ -330,8 +331,36 @@ class NSClientV3Plugin @Inject constructor(
|
|||
enum class Operation { CREATE, UPDATE }
|
||||
|
||||
private val gson: Gson = GsonBuilder().create()
|
||||
private fun dbOperation(collection: String, dataPair: DataSyncSelector.DataPair, progress: String, operation: Operation) {
|
||||
if (collection == "entries") {
|
||||
private fun dbOperationDeviceStatus(collection: String = "devicestatus", dataPair: DataSyncSelector.DataPair, progress: String) {
|
||||
val data = (dataPair as DataSyncSelector.PairDeviceStatus).value.toRemoteDeviceStatus()
|
||||
scope.launch {
|
||||
try {
|
||||
rxBus.send(EventNSClientNewLog("ADD $collection", "Sent ${dataPair.javaClass.simpleName} ${gson.toJson(data)} $progress"))
|
||||
nsAndroidClient?.createDeviceStatus(data)?.let { result ->
|
||||
when (result.response) {
|
||||
200 -> rxBus.send(EventNSClientNewLog("UPDATED", "OK ${dataPair.value.javaClass.simpleName}"))
|
||||
201 -> rxBus.send(EventNSClientNewLog("ADDED", "OK ${dataPair.value.javaClass.simpleName} ${result.identifier}"))
|
||||
|
||||
else -> {
|
||||
rxBus.send(EventNSClientNewLog("ERROR", "${dataPair.value.javaClass.simpleName} "))
|
||||
return@launch
|
||||
}
|
||||
}
|
||||
if (result.response == 201) { // created
|
||||
dataPair.value.interfaceIDs.nightscoutId = result.identifier
|
||||
storeDataForDb.nsIdDeviceStatuses.add(dataPair.value)
|
||||
storeDataForDb.scheduleNsIdUpdate()
|
||||
}
|
||||
dataSyncSelector.confirmLastDeviceStatusIdIfGreater(dataPair.id)
|
||||
dataSyncSelector.processChangedDeviceStatusesCompat()
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
aapsLogger.error(LTag.NSCLIENT, "Upload exception", e)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun dbOperationEntries(collection: String = "entries", dataPair: DataSyncSelector.DataPair, progress: String, operation: Operation) {
|
||||
val call = when (operation) {
|
||||
Operation.CREATE -> nsAndroidClient?.let { return@let it::createSvg }
|
||||
Operation.UPDATE -> nsAndroidClient?.let { return@let it::updateSvg }
|
||||
|
@ -384,7 +413,8 @@ class NSClientV3Plugin @Inject constructor(
|
|||
}
|
||||
}
|
||||
}
|
||||
if (collection == "food") {
|
||||
|
||||
private fun dbOperationFood(collection: String = "food", dataPair: DataSyncSelector.DataPair, progress: String, operation: Operation) {
|
||||
val call = when (operation) {
|
||||
Operation.CREATE -> nsAndroidClient?.let { return@let it::createFood }
|
||||
Operation.UPDATE -> nsAndroidClient?.let { return@let it::updateFood }
|
||||
|
@ -437,7 +467,8 @@ class NSClientV3Plugin @Inject constructor(
|
|||
}
|
||||
}
|
||||
}
|
||||
if (collection == "treatments") {
|
||||
|
||||
private fun dbOperationTreatments(collection: String = "treatments", dataPair: DataSyncSelector.DataPair, progress: String, operation: Operation) {
|
||||
val call = when (operation) {
|
||||
Operation.CREATE -> nsAndroidClient?.let { return@let it::createTreatment }
|
||||
Operation.UPDATE -> nsAndroidClient?.let { return@let it::updateTreatment }
|
||||
|
@ -458,6 +489,7 @@ class NSClientV3Plugin @Inject constructor(
|
|||
}
|
||||
dataPair.value.toNSTemporaryBasal(profile)
|
||||
}
|
||||
|
||||
is DataSyncSelector.PairExtendedBolus -> {
|
||||
val profile = profileFunction.getProfile(dataPair.value.timestamp)
|
||||
if (profile == null) {
|
||||
|
@ -467,6 +499,7 @@ class NSClientV3Plugin @Inject constructor(
|
|||
}
|
||||
dataPair.value.toNSExtendedBolus(profile)
|
||||
}
|
||||
|
||||
is DataSyncSelector.PairProfileSwitch -> dataPair.value.toNSProfileSwitch(dateUtil)
|
||||
is DataSyncSelector.PairEffectiveProfileSwitch -> dataPair.value.toNSEffectiveProfileSwitch(dateUtil)
|
||||
is DataSyncSelector.PairOfflineEvent -> dataPair.value.toNSOfflineEvent()
|
||||
|
@ -606,6 +639,14 @@ class NSClientV3Plugin @Inject constructor(
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun dbOperation(collection: String, dataPair: DataSyncSelector.DataPair, progress: String, operation: Operation) {
|
||||
when (collection) {
|
||||
"devicestatus" -> dbOperationDeviceStatus(dataPair = dataPair, progress = progress)
|
||||
"entries" -> dbOperationEntries(dataPair = dataPair, progress = progress, operation = operation)
|
||||
"food" -> dbOperationFood(dataPair = dataPair, progress = progress, operation = operation)
|
||||
"treatments" -> dbOperationTreatments(dataPair = dataPair, progress = progress, operation = operation)
|
||||
}
|
||||
}
|
||||
|
||||
fun storeLastLoadedSrvModified() {
|
||||
|
|
|
@ -0,0 +1,389 @@
|
|||
package info.nightscout.plugins.sync.nsclientV3.extensions
|
||||
|
||||
import com.google.gson.GsonBuilder
|
||||
import com.google.gson.JsonDeserializer
|
||||
import info.nightscout.database.entities.DeviceStatus
|
||||
import info.nightscout.sdk.remotemodel.RemoteDeviceStatus
|
||||
import org.json.JSONObject
|
||||
|
||||
fun DeviceStatus.toRemoteDeviceStatus(): RemoteDeviceStatus {
|
||||
val deserializer: JsonDeserializer<JSONObject?> =
|
||||
JsonDeserializer<JSONObject?> { json, _, _ ->
|
||||
JSONObject(json.asJsonObject.toString())
|
||||
}
|
||||
val gson = GsonBuilder().also {
|
||||
it.registerTypeAdapter(JSONObject::class.java, deserializer)
|
||||
}.create()
|
||||
|
||||
val pump = gson.fromJson(pump, RemoteDeviceStatus.Pump::class.java)
|
||||
val openAps = RemoteDeviceStatus.OpenAps(
|
||||
suggested = suggested?.let { JSONObject(it) },
|
||||
enacted = enacted?.let { JSONObject(it) },
|
||||
iob = iob?.let { JSONObject(it) },
|
||||
)
|
||||
return RemoteDeviceStatus(
|
||||
date = timestamp,
|
||||
device = device,
|
||||
pump = pump,
|
||||
openaps = openAps,
|
||||
uploaderBattery = if (uploaderBattery != 0) uploaderBattery else null,
|
||||
configuration = gson.fromJson(configuration, RemoteDeviceStatus.Configuration::class.java),
|
||||
uploader = null
|
||||
)
|
||||
}
|
||||
/*
|
||||
{
|
||||
"_id": "576cfd15217b0bed77d63641",
|
||||
"device": "openaps://indy2",
|
||||
"pump": {
|
||||
"battery": {
|
||||
"status": "normal",
|
||||
"voltage": 1.56
|
||||
},
|
||||
"status": {
|
||||
"status": "normal",
|
||||
"timestamp": "2016-06-24T09:26:38.000Z",
|
||||
"bolusing": false,
|
||||
"suspended": false
|
||||
},
|
||||
"reservoir": 31.25,
|
||||
"clock": "2016-06-24T02:26:16-07:00"
|
||||
},
|
||||
"openaps": {
|
||||
"suggested": {
|
||||
"bg": 173,
|
||||
"temp": "absolute",
|
||||
"snoozeBG": 194,
|
||||
"timestamp": "2016-06-24T09:27:40.000Z",
|
||||
"predBGs": {
|
||||
"IOB": [173, 178, 183, 187, 191, 194, 196, 197, 198, 197, 197, 195, 192, 190, 187, 184, 181, 178, 175, 172, 169, 167, 164, 162, 160, 158, 156, 154, 152, 151, 149, 148, 147, 146, 146, 145]
|
||||
},
|
||||
"reason": "COB: 0, Dev: 46, BGI: -1.92, ISF: 80, Target: 115; Eventual BG 194>=115, adj. req. rate:2.7 to maxSafeBasal:2.3, temp 2.25 >~ req 2.3U/hr",
|
||||
"COB": 0,
|
||||
"eventualBG": 194,
|
||||
"tick": "+6",
|
||||
"IOB": 0.309
|
||||
},
|
||||
"iob": [{
|
||||
"netbasalinsulin": -0.3,
|
||||
"activity": 0.0048,
|
||||
"basaliob": 0.078,
|
||||
"time": "2016-06-24T09:26:16.000Z",
|
||||
"hightempinsulin": 0.25,
|
||||
"bolussnooze": 0,
|
||||
"iob": 0.309
|
||||
}, {
|
||||
"netbasalinsulin": -0.15,
|
||||
"activity": 0.0041,
|
||||
"basaliob": 0.238,
|
||||
"time": "2016-06-24T09:31:16.000Z",
|
||||
"hightempinsulin": 0.4,
|
||||
"bolussnooze": 0,
|
||||
"iob": 0.438
|
||||
}, {
|
||||
"netbasalinsulin": 0,
|
||||
"activity": 0.0036,
|
||||
"basaliob": 0.345,
|
||||
"time": "2016-06-24T09:36:16.000Z",
|
||||
"hightempinsulin": 0.5,
|
||||
"bolussnooze": 0,
|
||||
"iob": 0.52
|
||||
}, {
|
||||
"netbasalinsulin": 0.2,
|
||||
"activity": 0.0036,
|
||||
"basaliob": 0.5,
|
||||
"time": "2016-06-24T09:41:16.000Z",
|
||||
"hightempinsulin": 0.65,
|
||||
"bolussnooze": 0,
|
||||
"iob": 0.653
|
||||
}, {
|
||||
"netbasalinsulin": 0.35,
|
||||
"activity": 0.0038,
|
||||
"basaliob": 0.602,
|
||||
"time": "2016-06-24T09:46:16.000Z",
|
||||
"hightempinsulin": 0.75,
|
||||
"bolussnooze": 0,
|
||||
"iob": 0.734
|
||||
}, {
|
||||
"netbasalinsulin": 0.45,
|
||||
"activity": 0.0042,
|
||||
"basaliob": 0.651,
|
||||
"time": "2016-06-24T09:51:16.000Z",
|
||||
"hightempinsulin": 0.8,
|
||||
"bolussnooze": 0,
|
||||
"iob": 0.763
|
||||
}, {
|
||||
"netbasalinsulin": 0.45,
|
||||
"activity": 0.0045,
|
||||
"basaliob": 0.647,
|
||||
"time": "2016-06-24T09:56:16.000Z",
|
||||
"hightempinsulin": 0.8,
|
||||
"bolussnooze": 0,
|
||||
"iob": 0.74
|
||||
}, {
|
||||
"netbasalinsulin": 0.5,
|
||||
"activity": 0.0048,
|
||||
"basaliob": 0.639,
|
||||
"time": "2016-06-24T10:01:16.000Z",
|
||||
"hightempinsulin": 0.8,
|
||||
"bolussnooze": 0,
|
||||
"iob": 0.716
|
||||
}, {
|
||||
"netbasalinsulin": 0.5,
|
||||
"activity": 0.0052,
|
||||
"basaliob": 0.628,
|
||||
"time": "2016-06-24T10:06:16.000Z",
|
||||
"hightempinsulin": 0.8,
|
||||
"bolussnooze": 0,
|
||||
"iob": 0.691
|
||||
}, {
|
||||
"netbasalinsulin": 0.5,
|
||||
"activity": 0.0055,
|
||||
"basaliob": 0.614,
|
||||
"time": "2016-06-24T10:11:16.000Z",
|
||||
"hightempinsulin": 0.8,
|
||||
"bolussnooze": 0,
|
||||
"iob": 0.663
|
||||
}, {
|
||||
"netbasalinsulin": 0.5,
|
||||
"activity": 0.0059,
|
||||
"basaliob": 0.596,
|
||||
"time": "2016-06-24T10:16:16.000Z",
|
||||
"hightempinsulin": 0.8,
|
||||
"bolussnooze": 0,
|
||||
"iob": 0.633
|
||||
}, {
|
||||
"netbasalinsulin": 0.55,
|
||||
"activity": 0.0063,
|
||||
"basaliob": 0.575,
|
||||
"time": "2016-06-24T10:21:16.000Z",
|
||||
"hightempinsulin": 0.8,
|
||||
"bolussnooze": 0,
|
||||
"iob": 0.602
|
||||
}, {
|
||||
"netbasalinsulin": 0.55,
|
||||
"activity": 0.0067,
|
||||
"basaliob": 0.549,
|
||||
"time": "2016-06-24T10:26:16.000Z",
|
||||
"hightempinsulin": 0.8,
|
||||
"bolussnooze": 0,
|
||||
"iob": 0.568
|
||||
}, {
|
||||
"netbasalinsulin": 0.55,
|
||||
"activity": 0.0071,
|
||||
"basaliob": 0.521,
|
||||
"time": "2016-06-24T10:31:16.000Z",
|
||||
"hightempinsulin": 0.8,
|
||||
"bolussnooze": 0,
|
||||
"iob": 0.533
|
||||
}, {
|
||||
"netbasalinsulin": 0.6,
|
||||
"activity": 0.0074,
|
||||
"basaliob": 0.489,
|
||||
"time": "2016-06-24T10:36:16.000Z",
|
||||
"hightempinsulin": 0.8,
|
||||
"bolussnooze": 0,
|
||||
"iob": 0.496
|
||||
}, {
|
||||
"netbasalinsulin": 0.6,
|
||||
"activity": 0.0075,
|
||||
"basaliob": 0.456,
|
||||
"time": "2016-06-24T10:41:16.000Z",
|
||||
"hightempinsulin": 0.8,
|
||||
"bolussnooze": 0,
|
||||
"iob": 0.458
|
||||
}, {
|
||||
"netbasalinsulin": 0.6,
|
||||
"activity": 0.0075,
|
||||
"basaliob": 0.42,
|
||||
"time": "2016-06-24T10:46:16.000Z",
|
||||
"hightempinsulin": 0.8,
|
||||
"bolussnooze": 0,
|
||||
"iob": 0.421
|
||||
}, {
|
||||
"netbasalinsulin": 0.6,
|
||||
"activity": 0.0073,
|
||||
"basaliob": 0.384,
|
||||
"time": "2016-06-24T10:51:16.000Z",
|
||||
"hightempinsulin": 0.8,
|
||||
"bolussnooze": 0,
|
||||
"iob": 0.384
|
||||
}, {
|
||||
"netbasalinsulin": 0.65,
|
||||
"activity": 0.0071,
|
||||
"basaliob": 0.349,
|
||||
"time": "2016-06-24T10:56:16.000Z",
|
||||
"hightempinsulin": 0.8,
|
||||
"bolussnooze": 0,
|
||||
"iob": 0.349
|
||||
}, {
|
||||
"netbasalinsulin": 0.65,
|
||||
"activity": 0.0069,
|
||||
"basaliob": 0.314,
|
||||
"time": "2016-06-24T11:01:16.000Z",
|
||||
"hightempinsulin": 0.8,
|
||||
"bolussnooze": 0,
|
||||
"iob": 0.314
|
||||
}, {
|
||||
"netbasalinsulin": 0.65,
|
||||
"activity": 0.0066,
|
||||
"basaliob": 0.281,
|
||||
"time": "2016-06-24T11:06:16.000Z",
|
||||
"hightempinsulin": 0.8,
|
||||
"bolussnooze": 0,
|
||||
"iob": 0.281
|
||||
}, {
|
||||
"netbasalinsulin": 0.65,
|
||||
"activity": 0.0062,
|
||||
"basaliob": 0.25,
|
||||
"time": "2016-06-24T11:11:16.000Z",
|
||||
"hightempinsulin": 0.8,
|
||||
"bolussnooze": 0,
|
||||
"iob": 0.25
|
||||
}, {
|
||||
"netbasalinsulin": 0.65,
|
||||
"activity": 0.0059,
|
||||
"basaliob": 0.221,
|
||||
"time": "2016-06-24T11:16:16.000Z",
|
||||
"hightempinsulin": 0.8,
|
||||
"bolussnooze": 0,
|
||||
"iob": 0.221
|
||||
}, {
|
||||
"netbasalinsulin": 0.65,
|
||||
"activity": 0.0055,
|
||||
"basaliob": 0.193,
|
||||
"time": "2016-06-24T11:21:16.000Z",
|
||||
"hightempinsulin": 0.8,
|
||||
"bolussnooze": 0,
|
||||
"iob": 0.193
|
||||
}, {
|
||||
"netbasalinsulin": 0.65,
|
||||
"activity": 0.0052,
|
||||
"basaliob": 0.167,
|
||||
"time": "2016-06-24T11:26:16.000Z",
|
||||
"hightempinsulin": 0.8,
|
||||
"bolussnooze": 0,
|
||||
"iob": 0.167
|
||||
}, {
|
||||
"netbasalinsulin": 0.7,
|
||||
"activity": 0.0049,
|
||||
"basaliob": 0.143,
|
||||
"time": "2016-06-24T11:31:16.000Z",
|
||||
"hightempinsulin": 0.8,
|
||||
"bolussnooze": 0,
|
||||
"iob": 0.143
|
||||
}, {
|
||||
"netbasalinsulin": 0.7,
|
||||
"activity": 0.0045,
|
||||
"basaliob": 0.12,
|
||||
"time": "2016-06-24T11:36:16.000Z",
|
||||
"hightempinsulin": 0.8,
|
||||
"bolussnooze": 0,
|
||||
"iob": 0.12
|
||||
}, {
|
||||
"netbasalinsulin": 0.7,
|
||||
"activity": 0.0041,
|
||||
"basaliob": 0.1,
|
||||
"time": "2016-06-24T11:41:16.000Z",
|
||||
"hightempinsulin": 0.8,
|
||||
"bolussnooze": 0,
|
||||
"iob": 0.1
|
||||
}, {
|
||||
"netbasalinsulin": 0.7,
|
||||
"activity": 0.0037,
|
||||
"basaliob": 0.081,
|
||||
"time": "2016-06-24T11:46:16.000Z",
|
||||
"hightempinsulin": 0.8,
|
||||
"bolussnooze": 0,
|
||||
"iob": 0.081
|
||||
}, {
|
||||
"netbasalinsulin": 0.75,
|
||||
"activity": 0.0034,
|
||||
"basaliob": 0.064,
|
||||
"time": "2016-06-24T11:51:16.000Z",
|
||||
"hightempinsulin": 0.8,
|
||||
"bolussnooze": 0,
|
||||
"iob": 0.064
|
||||
}, {
|
||||
"netbasalinsulin": 0.75,
|
||||
"activity": 0.003,
|
||||
"basaliob": 0.049,
|
||||
"time": "2016-06-24T11:56:16.000Z",
|
||||
"hightempinsulin": 0.8,
|
||||
"bolussnooze": 0,
|
||||
"iob": 0.049
|
||||
}, {
|
||||
"netbasalinsulin": 0.8,
|
||||
"activity": 0.0026,
|
||||
"basaliob": 0.036,
|
||||
"time": "2016-06-24T12:01:16.000Z",
|
||||
"hightempinsulin": 0.8,
|
||||
"bolussnooze": 0,
|
||||
"iob": 0.036
|
||||
}, {
|
||||
"netbasalinsulin": 0.8,
|
||||
"activity": 0.0021,
|
||||
"basaliob": 0.026,
|
||||
"time": "2016-06-24T12:06:16.000Z",
|
||||
"hightempinsulin": 0.8,
|
||||
"bolussnooze": 0,
|
||||
"iob": 0.026
|
||||
}, {
|
||||
"netbasalinsulin": 0.75,
|
||||
"activity": 0.0017,
|
||||
"basaliob": 0.017,
|
||||
"time": "2016-06-24T12:11:16.000Z",
|
||||
"hightempinsulin": 0.75,
|
||||
"bolussnooze": 0,
|
||||
"iob": 0.017
|
||||
}, {
|
||||
"netbasalinsulin": 0.75,
|
||||
"activity": 0.0013,
|
||||
"basaliob": 0.011,
|
||||
"time": "2016-06-24T12:16:16.000Z",
|
||||
"hightempinsulin": 0.75,
|
||||
"bolussnooze": 0,
|
||||
"iob": 0.011
|
||||
}, {
|
||||
"netbasalinsulin": 0.65,
|
||||
"activity": 0.0009,
|
||||
"basaliob": 0.006,
|
||||
"time": "2016-06-24T12:21:16.000Z",
|
||||
"hightempinsulin": 0.65,
|
||||
"bolussnooze": 0,
|
||||
"iob": 0.006
|
||||
}],
|
||||
"enacted": {
|
||||
"bg": 161,
|
||||
"temp": "absolute",
|
||||
"snoozeBG": 181,
|
||||
"recieved": true,
|
||||
"predBGs": {
|
||||
"IOB": [161, 164, 166, 168, 170, 172, 174, 175, 176, 177, 177, 176, 175, 175, 174, 173, 173, 172, 172, 171, 171, 171, 171, 170, 170, 170, 170, 170, 169, 169, 169, 169, 169, 168]
|
||||
},
|
||||
"reason": "COB: undefined, Dev: 33, BGI: -2.56, ISF: 80, Target: 115; Eventual BG 181>=115, adj. req. rate:2.4 to maxSafeBasal:2.3, temp 1<2.3U/hr",
|
||||
"rate": 2.25,
|
||||
"eventualBG": 181,
|
||||
"timestamp": "2016-06-24T09:19:06.000Z",
|
||||
"duration": 30,
|
||||
"tick": "+5",
|
||||
"IOB": 0.166
|
||||
}
|
||||
},
|
||||
"mmtune": {
|
||||
"scanDetails": [
|
||||
["916.564", 5, -78],
|
||||
["916.588", 3, -80],
|
||||
["916.612", 4, -68],
|
||||
["916.636", 5, -65],
|
||||
["916.660", 5, -60],
|
||||
["916.684", 5, -67],
|
||||
["916.708", 5, -71]
|
||||
],
|
||||
"setFreq": 916.66,
|
||||
"timestamp": "2016-06-24T09:26:22.000Z",
|
||||
"usedDefault": false
|
||||
},
|
||||
"created_at": "2016-06-24T09:27:49.230Z"
|
||||
}
|
||||
*/
|
|
@ -0,0 +1,86 @@
|
|||
package info.nightscout.plugins.sync.nsclientV3.extensions
|
||||
|
||||
import dagger.android.AndroidInjector
|
||||
import dagger.android.HasAndroidInjector
|
||||
import info.nightscout.androidaps.TestBase
|
||||
import info.nightscout.database.entities.DeviceStatus
|
||||
import info.nightscout.interfaces.Config
|
||||
import info.nightscout.interfaces.configBuilder.RunningConfiguration
|
||||
import info.nightscout.interfaces.constraints.Constraints
|
||||
import info.nightscout.interfaces.iob.IobCobCalculator
|
||||
import info.nightscout.interfaces.nsclient.ProcessedDeviceStatusData
|
||||
import info.nightscout.interfaces.plugin.ActivePlugin
|
||||
import info.nightscout.interfaces.profile.Instantiator
|
||||
import info.nightscout.interfaces.profile.ProfileFunction
|
||||
import info.nightscout.plugins.aps.APSResultObject
|
||||
import info.nightscout.plugins.sync.nsclient.data.NSDeviceStatusHandler
|
||||
import info.nightscout.plugins.sync.nsclient.data.ProcessedDeviceStatusDataImpl
|
||||
import info.nightscout.shared.interfaces.ResourceHelper
|
||||
import info.nightscout.shared.sharedPreferences.SP
|
||||
import info.nightscout.shared.utils.DateUtil
|
||||
import org.junit.jupiter.api.Assertions
|
||||
import org.junit.jupiter.api.BeforeEach
|
||||
import org.junit.jupiter.api.Test
|
||||
import org.mockito.Mock
|
||||
|
||||
@Suppress("SpellCheckingInspection")
|
||||
internal class DeviceStatusExtensionKtTest : TestBase() {
|
||||
|
||||
@Mock lateinit var constraintChecker: Constraints
|
||||
@Mock lateinit var sp: SP
|
||||
@Mock lateinit var activePlugin: ActivePlugin
|
||||
@Mock lateinit var iobCobCalculator: IobCobCalculator
|
||||
@Mock lateinit var profileFunction: ProfileFunction
|
||||
@Mock lateinit var rh: ResourceHelper
|
||||
@Mock lateinit var dateUtil: DateUtil
|
||||
@Mock lateinit var config: Config
|
||||
@Mock lateinit var runningConfiguration: RunningConfiguration
|
||||
@Mock lateinit var instantiator: Instantiator
|
||||
|
||||
private lateinit var processedDeviceStatusData: ProcessedDeviceStatusData
|
||||
private lateinit var nsDeviceStatusHandler: NSDeviceStatusHandler
|
||||
|
||||
val injector = HasAndroidInjector {
|
||||
AndroidInjector {
|
||||
if (it is APSResultObject) {
|
||||
it.aapsLogger = aapsLogger
|
||||
it.constraintChecker = constraintChecker
|
||||
it.sp = sp
|
||||
it.activePlugin = activePlugin
|
||||
it.iobCobCalculator = iobCobCalculator
|
||||
it.profileFunction = profileFunction
|
||||
it.rh = rh
|
||||
it.dateUtil = dateUtil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@BeforeEach
|
||||
fun setup() {
|
||||
processedDeviceStatusData = ProcessedDeviceStatusDataImpl(rh, dateUtil, sp, instantiator)
|
||||
nsDeviceStatusHandler = NSDeviceStatusHandler(sp, config, dateUtil, runningConfiguration, processedDeviceStatusData)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun dotest() {
|
||||
|
||||
val deviceStatus = DeviceStatus(
|
||||
timestamp = 10000,
|
||||
suggested = "{\"temp\":\"absolute\",\"bg\":133,\"tick\":-6,\"eventualBG\":67,\"targetBG\":99,\"insulinReq\":0,\"deliverAt\":\"2023-01-02T15:29:33.374Z\",\"sensitivityRatio\":1,\"variable_sens\":97.5,\"predBGs\":{\"IOB\":[133,127,121,116,111,106,101,97,93,89,85,81,78,75,72,69,67,65,62,60,58,57,55,54,52,51,50,49,48,47,46,45,45,44,43,43,42,42,41,41,41,41,40,40,40,40,39],\"ZT\":[133,127,121,115,110,105,101,96,92,88,84,81,77,74,71,69,66,64,62,59,58,56,54,53,51,50,49,48,47,46,45,44,44,43,42,42,41,41,40,40,40,39,39,39,39,39,39,39],\"UAM\":[133,127,121,115,110,105,101,96,92,88,84,81,77,74,71,69,66,64,62,59,58,56,54,53,51,50,49,48,47,46,45,44,44,43,42,42,41,41,40,40,40,39]},\"reason\":\"COB: 0, Dev: 0.1, BGI: -0.3, ISF: 5.4, CR: 13, Target: 5.5, minPredBG 2.2, minGuardBG 2.1, IOBpredBG 2.2, UAMpredBG 2.2; minGuardBG 2.1<4.0\",\"COB\":0,\"IOB\":0.692,\"duration\":90,\"rate\":0,\"timestamp\":\"2023-01-02T15:29:39.460Z\"}",
|
||||
iob = "{\"iob\":0.692,\"basaliob\":-0.411,\"activity\":0.0126,\"time\":\"2023-01-02T15:29:39.460Z\"}",
|
||||
enacted = "{\"temp\":\"absolute\",\"bg\":133,\"tick\":-6,\"eventualBG\":67,\"targetBG\":99,\"insulinReq\":0,\"deliverAt\":\"2023-01-02T15:29:33.374Z\",\"sensitivityRatio\":1,\"variable_sens\":97.5,\"predBGs\":{\"IOB\":[133,127,121,116,111,106,101,97,93,89,85,81,78,75,72,69,67,65,62,60,58,57,55,54,52,51,50,49,48,47,46,45,45,44,43,43,42,42,41,41,41,41,40,40,40,40,39],\"ZT\":[133,127,121,115,110,105,101,96,92,88,84,81,77,74,71,69,66,64,62,59,58,56,54,53,51,50,49,48,47,46,45,44,44,43,42,42,41,41,40,40,40,39,39,39,39,39,39,39],\"UAM\":[133,127,121,115,110,105,101,96,92,88,84,81,77,74,71,69,66,64,62,59,58,56,54,53,51,50,49,48,47,46,45,44,44,43,42,42,41,41,40,40,40,39]},\"reason\":\"COB: 0, Dev: 0.1, BGI: -0.3, ISF: 5.4, CR: 13, Target: 5.5, minPredBG 2.2, minGuardBG 2.1, IOBpredBG 2.2, UAMpredBG 2.2; minGuardBG 2.1<4.0\",\"COB\":0,\"IOB\":0.692,\"duration\":90,\"rate\":0,\"timestamp\":\"2023-01-02T15:29:39.460Z\"}",
|
||||
device = "openaps://samsung SM-G970F",
|
||||
pump = "{\"battery\":{\"percent\":75},\"status\":{\"status\":\"normal\",\"timestamp\":\"2023-01-02T15:20:20.656Z\"},\"extended\":{\"Version\":\"3.1.0.3-dev-e-295e1ad18f-2022.12.24\"," +
|
||||
"\"LastBolus\":\"02.01.23 15:24\",\"LastBolusAmount\":\"1\",\"TempBasalAbsoluteRate\":\"0\",\"TempBasalStart\":\"02.01.23 16:20\",\"TempBasalRemaining\":\"55\",\"BaseBasalRate\":\"0" +
|
||||
".41\"," +
|
||||
"\"ActiveProfile\":\"L29_U200 IC\"},\"reservoir\":\"133\",\"clock\":\"2023-01-02T15:25:05.826Z\"}",
|
||||
uploaderBattery = 60,
|
||||
configuration = "{\"insulin\":5,\"insulinConfiguration\":{},\"sensitivity\":2,\"sensitivityConfiguration\":{\"openapsama_min_5m_carbimpact\":8,\"absorption_cutoff\":4,\"autosens_max\":1.2,\"autosens_min\":0.7},\"overviewConfiguration\":{\"units\":\"mmol\",\"QuickWizard\":\"[]\",\"eatingsoon_duration\":60,\"eatingsoon_target\":4,\"activity_duration\":180,\"activity_target\":7.5,\"hypo_duration\":90,\"hypo_target\":8,\"low_mark\":3.9,\"high_mark\":10,\"statuslights_cage_warning\":72,\"statuslights_cage_critical\":96,\"statuslights_iage_warning\":120,\"statuslights_iage_critical\":150,\"statuslights_sage_warning\":168,\"statuslights_sage_critical\":336,\"statuslights_sbat_warning\":25,\"statuslights_sbat_critical\":5,\"statuslights_bage_warning\":720,\"statuslights_bage_critical\":800,\"statuslights_res_warning\":30,\"statuslights_res_critical\":10,\"statuslights_bat_warning\":50,\"statuslights_bat_critical\":25,\"boluswizard_percentage\":70},\"safetyConfiguration\":{\"age\":\"resistantadult\",\"treatmentssafety_maxbolus\":10,\"treatmentssafety_maxcarbs\":70}}"
|
||||
)
|
||||
|
||||
val remoteDeviceStatus = deviceStatus.toRemoteDeviceStatus()
|
||||
|
||||
nsDeviceStatusHandler.handleNewData(arrayOf(remoteDeviceStatus))
|
||||
Assertions.assertEquals(75, processedDeviceStatusData.pumpData?.percent)
|
||||
}
|
||||
}
|
|
@ -8,7 +8,7 @@ import org.junit.jupiter.api.Assertions
|
|||
import org.junit.jupiter.api.Test
|
||||
|
||||
@Suppress("SpellCheckingInspection")
|
||||
internal class OfflineEventKtTest {
|
||||
internal class OfflineEventExtensionKtTest {
|
||||
|
||||
@Test
|
||||
fun toOfflineEvent() {
|
Loading…
Reference in a new issue