NSCv3: NSDeviceStatus

This commit is contained in:
Milos Kozak 2023-01-08 22:18:35 +01:00
parent 4b6eab6aa4
commit 9fa5017b15
13 changed files with 250 additions and 52 deletions

View file

@ -1,6 +1,6 @@
package info.nightscout.interfaces.configBuilder package info.nightscout.interfaces.configBuilder
import info.nightscout.sdk.remotemodel.RemoteDeviceStatus import info.nightscout.sdk.localmodel.devicestatus.NSDeviceStatus
import org.json.JSONObject import org.json.JSONObject
interface RunningConfiguration { interface RunningConfiguration {
@ -9,5 +9,5 @@ interface RunningConfiguration {
fun configuration(): JSONObject fun configuration(): JSONObject
// called in NSClient mode only // called in NSClient mode only
fun apply(configuration: RemoteDeviceStatus.Configuration) fun apply(configuration: NSDeviceStatus.Configuration)
} }

View file

@ -9,12 +9,15 @@ import info.nightscout.sdk.exceptions.UnknownResponseNightscoutException
import info.nightscout.sdk.exceptions.UnsuccessfullNightscoutException import info.nightscout.sdk.exceptions.UnsuccessfullNightscoutException
import info.nightscout.sdk.interfaces.NSAndroidClient import info.nightscout.sdk.interfaces.NSAndroidClient
import info.nightscout.sdk.localmodel.Status import info.nightscout.sdk.localmodel.Status
import info.nightscout.sdk.localmodel.devicestatus.NSDeviceStatus
import info.nightscout.sdk.localmodel.entry.NSSgvV3 import info.nightscout.sdk.localmodel.entry.NSSgvV3
import info.nightscout.sdk.localmodel.food.NSFood import info.nightscout.sdk.localmodel.food.NSFood
import info.nightscout.sdk.localmodel.treatment.CreateUpdateResponse import info.nightscout.sdk.localmodel.treatment.CreateUpdateResponse
import info.nightscout.sdk.localmodel.treatment.NSTreatment import info.nightscout.sdk.localmodel.treatment.NSTreatment
import info.nightscout.sdk.mapper.toLocal import info.nightscout.sdk.mapper.toLocal
import info.nightscout.sdk.mapper.toNSDeviceStatus
import info.nightscout.sdk.mapper.toNSFood import info.nightscout.sdk.mapper.toNSFood
import info.nightscout.sdk.mapper.toRemoteDeviceStatus
import info.nightscout.sdk.mapper.toRemoteEntry import info.nightscout.sdk.mapper.toRemoteEntry
import info.nightscout.sdk.mapper.toRemoteFood import info.nightscout.sdk.mapper.toRemoteFood
import info.nightscout.sdk.mapper.toRemoteTreatment import info.nightscout.sdk.mapper.toRemoteTreatment
@ -227,20 +230,20 @@ class NSAndroidClientImpl(
} }
} }
override suspend fun getDeviceStatusModifiedSince(from: Long): List<RemoteDeviceStatus> = callWrapper(dispatcher) { override suspend fun getDeviceStatusModifiedSince(from: Long): List<NSDeviceStatus> = callWrapper(dispatcher) {
val response = api.getDeviceStatusModifiedSince(from) val response = api.getDeviceStatusModifiedSince(from)
if (response.isSuccessful) { if (response.isSuccessful) {
return@callWrapper response.body()?.result.toNotNull() return@callWrapper response.body()?.result?.map(RemoteDeviceStatus::toNSDeviceStatus).toNotNull()
} else { } else {
throw UnsuccessfullNightscoutException() throw UnsuccessfullNightscoutException()
} }
} }
override suspend fun createDeviceStatus(remoteDeviceStatus: RemoteDeviceStatus): CreateUpdateResponse = callWrapper(dispatcher) { override suspend fun createDeviceStatus(nsDeviceStatus: NSDeviceStatus): CreateUpdateResponse = callWrapper(dispatcher) {
remoteDeviceStatus.app = "AAPS" nsDeviceStatus.app = "AAPS"
val response = api.createDeviceStatus(remoteDeviceStatus) val response = api.createDeviceStatus(nsDeviceStatus.toRemoteDeviceStatus())
if (response.isSuccessful) { if (response.isSuccessful) {
if (response.code() == 200) { if (response.code() == 200) {
return@callWrapper CreateUpdateResponse( return@callWrapper CreateUpdateResponse(

View file

@ -1,12 +1,12 @@
package info.nightscout.sdk.interfaces package info.nightscout.sdk.interfaces
import info.nightscout.sdk.localmodel.Status import info.nightscout.sdk.localmodel.Status
import info.nightscout.sdk.localmodel.devicestatus.NSDeviceStatus
import info.nightscout.sdk.localmodel.entry.NSSgvV3 import info.nightscout.sdk.localmodel.entry.NSSgvV3
import info.nightscout.sdk.localmodel.food.NSFood import info.nightscout.sdk.localmodel.food.NSFood
import info.nightscout.sdk.localmodel.treatment.CreateUpdateResponse import info.nightscout.sdk.localmodel.treatment.CreateUpdateResponse
import info.nightscout.sdk.localmodel.treatment.NSTreatment import info.nightscout.sdk.localmodel.treatment.NSTreatment
import info.nightscout.sdk.remotemodel.LastModified import info.nightscout.sdk.remotemodel.LastModified
import info.nightscout.sdk.remotemodel.RemoteDeviceStatus
import org.json.JSONObject import org.json.JSONObject
interface NSAndroidClient { interface NSAndroidClient {
@ -30,8 +30,8 @@ interface NSAndroidClient {
suspend fun getTreatmentsNewerThan(createdAt: String, limit: Long): List<NSTreatment> suspend fun getTreatmentsNewerThan(createdAt: String, limit: Long): List<NSTreatment>
suspend fun getTreatmentsModifiedSince(from: Long, limit: Long): ReadResponse<List<NSTreatment>> suspend fun getTreatmentsModifiedSince(from: Long, limit: Long): ReadResponse<List<NSTreatment>>
suspend fun createDeviceStatus(remoteDeviceStatus: RemoteDeviceStatus): CreateUpdateResponse suspend fun createDeviceStatus(nsDeviceStatus: NSDeviceStatus): CreateUpdateResponse
suspend fun getDeviceStatusModifiedSince(from: Long): List<RemoteDeviceStatus> suspend fun getDeviceStatusModifiedSince(from: Long): List<NSDeviceStatus>
suspend fun createProfileStore(remoteProfileStore: JSONObject): CreateUpdateResponse suspend fun createProfileStore(remoteProfileStore: JSONObject): CreateUpdateResponse
suspend fun getLastProfileStore(): ReadResponse<List<JSONObject>> suspend fun getLastProfileStore(): ReadResponse<List<JSONObject>>

View file

@ -0,0 +1,74 @@
package info.nightscout.sdk.localmodel.devicestatus
import com.google.gson.annotations.SerializedName
import kotlinx.serialization.Contextual
import kotlinx.serialization.Serializable
import org.json.JSONObject
/**
* NS DeviceStatus coming from uploader or AAPS
*
**/
@Serializable
data class NSDeviceStatus(
@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"
@SerializedName("uploader") val uploader: Uploader?,
@SerializedName("pump") val pump: Pump?,
@SerializedName("openaps") val openaps: OpenAps?,
@SerializedName("configuration") val configuration: Configuration?
) {
@Serializable data class Pump(
@SerializedName("clock") val clock: String?, // timestamp in ISO
@SerializedName("reservoir") val reservoir: Double?,
@SerializedName("reservoir_display_override") val reservoirDisplayOverride: String?,
@SerializedName("battery") val battery: Battery?,
@SerializedName("status") val status: Status?,
@Contextual @SerializedName("extended") val extended: JSONObject? // Gson, content depending on pump driver
) {
@Serializable data class Battery(
@SerializedName("percent") val percent: Int?,
@SerializedName("voltage") val voltage: Double?
)
@Serializable data class Status(
@SerializedName("status") val status: String?,
@SerializedName("timestamp") val timestamp: String?
)
}
@Serializable data class OpenAps(
@Contextual @SerializedName("suggested") val suggested: JSONObject?, // Gson
@Contextual @SerializedName("enacted") val enacted: JSONObject?, // Gson
@Contextual @SerializedName("iob") val iob: JSONObject? // Gson
)
@Serializable data class Uploader(
@SerializedName("battery") val battery: Int?,
)
@Serializable data class Configuration(
@SerializedName("pump") val pump: String?,
@SerializedName("version") val version: String?,
@SerializedName("insulin") val insulin: Int?,
@SerializedName("sensitivity") val sensitivity: Int?,
@SerializedName("smoothing") val smoothing: String?,
@Contextual @SerializedName("insulinConfiguration") val insulinConfiguration: JSONObject?,
@Contextual @SerializedName("sensitivityConfiguration") val sensitivityConfiguration: JSONObject?,
@Contextual @SerializedName("overviewConfiguration") val overviewConfiguration: JSONObject?,
@Contextual @SerializedName("safetyConfiguration") val safetyConfiguration: JSONObject?
)
}

View file

@ -0,0 +1,102 @@
package info.nightscout.sdk.mapper
import com.google.gson.JsonParser
import info.nightscout.sdk.localmodel.devicestatus.NSDeviceStatus
import info.nightscout.sdk.remotemodel.RemoteDeviceStatus
import org.json.JSONObject
fun NSDeviceStatus.convertToRemoteAndBack(): NSDeviceStatus =
toRemoteDeviceStatus().toNSDeviceStatus()
internal fun RemoteDeviceStatus.toNSDeviceStatus(): NSDeviceStatus =
NSDeviceStatus(
app = app,
identifier = identifier,
srvCreated = srvCreated,
srvModified = srvModified,
createdAt = createdAt,
date = date,
uploaderBattery = uploaderBattery,
device = device,
uploader = NSDeviceStatus.Uploader(uploader?.battery),
pump = pump?.toNSDeviceStatusPump(),
openaps = openaps?.toNSDeviceStatusOpenAps(),
configuration = configuration?.toNSDeviceStatusConfiguration()
)
internal fun NSDeviceStatus.toRemoteDeviceStatus(): RemoteDeviceStatus =
RemoteDeviceStatus(
app = app,
identifier = identifier,
srvCreated = srvCreated,
srvModified = srvModified,
createdAt = createdAt,
date = date,
uploaderBattery = uploaderBattery,
device = device,
uploader = RemoteDeviceStatus.Uploader(uploader?.battery),
pump = pump?.toRemoteDeviceStatusPump(),
openaps = openaps?.toRemoteDeviceStatusOpenAps(),
configuration = configuration?.toRemoteDeviceStatusConfiguration()
)
internal fun RemoteDeviceStatus.Pump.toNSDeviceStatusPump(): NSDeviceStatus.Pump =
NSDeviceStatus.Pump(
clock = clock,
reservoir = reservoir,
reservoirDisplayOverride = reservoirDisplayOverride,
battery = NSDeviceStatus.Pump.Battery(battery?.percent, battery?.voltage),
status = NSDeviceStatus.Pump.Status(status?.status, status?.timestamp),
extended = extended?.let { JSONObject(it.toString()) }
)
internal fun NSDeviceStatus.Pump.toRemoteDeviceStatusPump(): RemoteDeviceStatus.Pump =
RemoteDeviceStatus.Pump(
clock = clock,
reservoir = reservoir,
reservoirDisplayOverride = reservoirDisplayOverride,
battery = RemoteDeviceStatus.Pump.Battery(battery?.percent, battery?.voltage),
status = RemoteDeviceStatus.Pump.Status(status?.status, status?.timestamp),
extended = extended?.let { JsonParser.parseString(it.toString()).asJsonObject }
)
internal fun RemoteDeviceStatus.OpenAps.toNSDeviceStatusOpenAps(): NSDeviceStatus.OpenAps =
NSDeviceStatus.OpenAps(
suggested = suggested?.let { JSONObject(it.toString()) },
enacted = enacted?.let { JSONObject(it.toString()) },
iob = iob?.let { JSONObject(it.toString()) }
)
internal fun NSDeviceStatus.OpenAps.toRemoteDeviceStatusOpenAps(): RemoteDeviceStatus.OpenAps =
RemoteDeviceStatus.OpenAps(
suggested = suggested?.let { JsonParser.parseString(it.toString()).asJsonObject },
enacted = enacted?.let { JsonParser.parseString(it.toString()).asJsonObject },
iob = iob?.let { JsonParser.parseString(it.toString()).asJsonObject }
)
internal fun RemoteDeviceStatus.Configuration.toNSDeviceStatusConfiguration(): NSDeviceStatus.Configuration =
NSDeviceStatus.Configuration(
pump = pump,
version = version,
insulin = insulin,
sensitivity = sensitivity,
smoothing = smoothing,
insulinConfiguration = insulinConfiguration?.let { JSONObject(it.toString()) },
sensitivityConfiguration = sensitivityConfiguration?.let { JSONObject(it.toString()) },
overviewConfiguration = overviewConfiguration?.let { JSONObject(it.toString()) },
safetyConfiguration = safetyConfiguration?.let { JSONObject(it.toString()) }
)
internal fun NSDeviceStatus.Configuration.toRemoteDeviceStatusConfiguration(): RemoteDeviceStatus.Configuration =
RemoteDeviceStatus.Configuration(
pump = pump,
version = version,
insulin = insulin,
sensitivity = sensitivity,
smoothing = smoothing,
insulinConfiguration = insulinConfiguration?.let { JsonParser.parseString(it.toString()).asJsonObject },
sensitivityConfiguration = sensitivityConfiguration?.let { JsonParser.parseString(it.toString()).asJsonObject },
overviewConfiguration = overviewConfiguration?.let { JsonParser.parseString(it.toString()).asJsonObject },
safetyConfiguration = safetyConfiguration?.let { JsonParser.parseString(it.toString()).asJsonObject }
)

View file

@ -1,21 +1,25 @@
package info.nightscout.sdk.remotemodel package info.nightscout.sdk.remotemodel
import com.google.gson.JsonObject
import com.google.gson.annotations.SerializedName import com.google.gson.annotations.SerializedName
import kotlinx.serialization.Contextual import kotlinx.serialization.Contextual
import kotlinx.serialization.Serializable import kotlinx.serialization.Serializable
import org.json.JSONObject
/** /**
* DeviceStatus coming from uploader or AAPS * DeviceStatus coming from uploader or AAPS
* *
**/ **/
@Serializable @Serializable
data class RemoteDeviceStatus( internal data class RemoteDeviceStatus(
@SerializedName("app") var app: String? = null, @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("identifier")
@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. 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("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("srvCreated")
@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... 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("date") val date: Long?, // date as milliseconds
@SerializedName("uploaderBattery") val uploaderBattery: Int?,// integer($int64) @SerializedName("uploaderBattery") val uploaderBattery: Int?,// integer($int64)
@SerializedName("device") val device: String?, // "openaps://samsung SM-G970F" @SerializedName("device") val device: String?, // "openaps://samsung SM-G970F"
@ -32,7 +36,7 @@ data class RemoteDeviceStatus(
@SerializedName("reservoir_display_override") val reservoirDisplayOverride: String?, @SerializedName("reservoir_display_override") val reservoirDisplayOverride: String?,
@SerializedName("battery") val battery: Battery?, @SerializedName("battery") val battery: Battery?,
@SerializedName("status") val status: Status?, @SerializedName("status") val status: Status?,
@Contextual @SerializedName("extended") val extended: JSONObject? // Gson, content depending on pump driver @Contextual @SerializedName("extended") val extended: JsonObject? // Gson, content depending on pump driver
) { ) {
@Serializable data class Battery( @Serializable data class Battery(
@ -47,9 +51,9 @@ data class RemoteDeviceStatus(
} }
@Serializable data class OpenAps( @Serializable data class OpenAps(
@Contextual @SerializedName("suggested") val suggested: JSONObject?, // Gson @Contextual @SerializedName("suggested") val suggested: JsonObject?, // Gson
@Contextual @SerializedName("enacted") val enacted: JSONObject?, // Gson @Contextual @SerializedName("enacted") val enacted: JsonObject?, // Gson
@Contextual @SerializedName("iob") val iob: JSONObject? // Gson @Contextual @SerializedName("iob") val iob: JsonObject? // Gson
) )
@Serializable data class Uploader( @Serializable data class Uploader(
@ -62,9 +66,9 @@ data class RemoteDeviceStatus(
@SerializedName("insulin") val insulin: Int?, @SerializedName("insulin") val insulin: Int?,
@SerializedName("sensitivity") val sensitivity: Int?, @SerializedName("sensitivity") val sensitivity: Int?,
@SerializedName("smoothing") val smoothing: String?, @SerializedName("smoothing") val smoothing: String?,
@Contextual @SerializedName("insulinConfiguration") val insulinConfiguration: JSONObject?, @Contextual @SerializedName("insulinConfiguration") val insulinConfiguration: JsonObject?,
@Contextual @SerializedName("sensitivityConfiguration") val sensitivityConfiguration: JSONObject?, @Contextual @SerializedName("sensitivityConfiguration") val sensitivityConfiguration: JsonObject?,
@Contextual @SerializedName("overviewConfiguration") val overviewConfiguration: JSONObject?, @Contextual @SerializedName("overviewConfiguration") val overviewConfiguration: JsonObject?,
@Contextual @SerializedName("safetyConfiguration") val safetyConfiguration: JSONObject? @Contextual @SerializedName("safetyConfiguration") val safetyConfiguration: JsonObject?
) )
} }

View file

@ -17,7 +17,7 @@ import info.nightscout.rx.bus.RxBus
import info.nightscout.rx.events.EventNSClientNewLog import info.nightscout.rx.events.EventNSClientNewLog
import info.nightscout.rx.logging.AAPSLogger import info.nightscout.rx.logging.AAPSLogger
import info.nightscout.rx.logging.LTag import info.nightscout.rx.logging.LTag
import info.nightscout.sdk.remotemodel.RemoteDeviceStatus import info.nightscout.sdk.localmodel.devicestatus.NSDeviceStatus
import info.nightscout.shared.interfaces.ResourceHelper import info.nightscout.shared.interfaces.ResourceHelper
import info.nightscout.shared.sharedPreferences.SP import info.nightscout.shared.sharedPreferences.SP
import org.json.JSONException import org.json.JSONException
@ -71,7 +71,7 @@ class RunningConfigurationImpl @Inject constructor(
} }
// called in NSClient mode only // called in NSClient mode only
override fun apply(configuration: RemoteDeviceStatus.Configuration) { override fun apply(configuration: NSDeviceStatus.Configuration) {
assert(config.NSCLIENT) assert(config.NSCLIENT)
configuration.version?.let { configuration.version?.let {

View file

@ -5,7 +5,7 @@ import info.nightscout.interfaces.configBuilder.RunningConfiguration
import info.nightscout.interfaces.nsclient.ProcessedDeviceStatusData import info.nightscout.interfaces.nsclient.ProcessedDeviceStatusData
import info.nightscout.interfaces.utils.HtmlHelper import info.nightscout.interfaces.utils.HtmlHelper
import info.nightscout.interfaces.utils.JsonHelper import info.nightscout.interfaces.utils.JsonHelper
import info.nightscout.sdk.remotemodel.RemoteDeviceStatus import info.nightscout.sdk.localmodel.devicestatus.NSDeviceStatus
import info.nightscout.shared.sharedPreferences.SP import info.nightscout.shared.sharedPreferences.SP
import info.nightscout.shared.utils.DateUtil import info.nightscout.shared.utils.DateUtil
import javax.inject.Inject import javax.inject.Inject
@ -73,7 +73,7 @@ class NSDeviceStatusHandler @Inject constructor(
private val processedDeviceStatusData: ProcessedDeviceStatusData private val processedDeviceStatusData: ProcessedDeviceStatusData
) { ) {
fun handleNewData(deviceStatuses: Array<RemoteDeviceStatus>) { fun handleNewData(deviceStatuses: Array<NSDeviceStatus>) {
var configurationDetected = false var configurationDetected = false
for (i in deviceStatuses.size - 1 downTo 0) { for (i in deviceStatuses.size - 1 downTo 0) {
val nsDeviceStatus = deviceStatuses[i] val nsDeviceStatus = deviceStatuses[i]
@ -91,7 +91,7 @@ class NSDeviceStatusHandler @Inject constructor(
} }
} }
private fun updateDeviceData(deviceStatus: RemoteDeviceStatus) { private fun updateDeviceData(deviceStatus: NSDeviceStatus) {
val createdAt = deviceStatus.createdAt?.let { dateUtil.fromISODateString(it) } ?: return val createdAt = deviceStatus.createdAt?.let { dateUtil.fromISODateString(it) } ?: return
processedDeviceStatusData.device?.let { if (createdAt < it.createdAt) return } // take only newer record processedDeviceStatusData.device?.let { if (createdAt < it.createdAt) return } // take only newer record
deviceStatus.device?.let { deviceStatus.device?.let {
@ -99,8 +99,8 @@ class NSDeviceStatusHandler @Inject constructor(
} }
} }
private fun updatePumpData(remoteDeviceStatus: RemoteDeviceStatus) { private fun updatePumpData(NSDeviceStatus: NSDeviceStatus) {
val pump = remoteDeviceStatus.pump ?: return val pump = NSDeviceStatus.pump ?: return
val clock = pump.clock?.let { dateUtil.fromISODateString(it) } ?: return val clock = pump.clock?.let { dateUtil.fromISODateString(it) } ?: return
processedDeviceStatusData.pumpData?.let { if (clock < it.clock) return } // take only newer record processedDeviceStatusData.pumpData?.let { if (clock < it.clock) return } // take only newer record
@ -132,8 +132,8 @@ class NSDeviceStatusHandler @Inject constructor(
} }
} }
private fun updateOpenApsData(remoteDeviceStatus: RemoteDeviceStatus) { private fun updateOpenApsData(NSDeviceStatus: NSDeviceStatus) {
remoteDeviceStatus.openaps?.suggested?.let { NSDeviceStatus.openaps?.suggested?.let {
JsonHelper.safeGetString(it, "timestamp")?.let { timestamp -> JsonHelper.safeGetString(it, "timestamp")?.let { timestamp ->
val clock = dateUtil.fromISODateString(timestamp) val clock = dateUtil.fromISODateString(timestamp)
// check if this is new data // check if this is new data
@ -143,7 +143,7 @@ class NSDeviceStatusHandler @Inject constructor(
} }
} }
} }
remoteDeviceStatus.openaps?.enacted?.let { NSDeviceStatus.openaps?.enacted?.let {
JsonHelper.safeGetString(it, "timestamp")?.let { timestamp -> JsonHelper.safeGetString(it, "timestamp")?.let { timestamp ->
val clock = dateUtil.fromISODateString(timestamp) val clock = dateUtil.fromISODateString(timestamp)
// check if this is new data // check if this is new data
@ -155,10 +155,10 @@ class NSDeviceStatusHandler @Inject constructor(
} }
} }
private fun updateUploaderData(remoteDeviceStatus: RemoteDeviceStatus) { private fun updateUploaderData(NSDeviceStatus: NSDeviceStatus) {
val clock = remoteDeviceStatus.createdAt?.let { dateUtil.fromISODateString(it) } ?: return val clock = NSDeviceStatus.createdAt?.let { dateUtil.fromISODateString(it) } ?: return
val device = remoteDeviceStatus.device ?: return val device = NSDeviceStatus.device ?: return
val battery = remoteDeviceStatus.uploaderBattery ?: remoteDeviceStatus.uploader?.battery ?: return val battery = NSDeviceStatus.uploaderBattery ?: NSDeviceStatus.uploader?.battery ?: return
var uploader = processedDeviceStatusData.uploaderMap[device] var uploader = processedDeviceStatusData.uploaderMap[device]
// check if this is new data // check if this is new data

View file

@ -59,7 +59,7 @@ class ProcessedDeviceStatusDataImpl @Inject constructor(
} }
string.append("<span style=\"color:${level.toColor()}\">") string.append("<span style=\"color:${level.toColor()}\">")
// val insulinUnit = rh.gs(info.nightscout.core.ui.R.string.insulin_unit_shortname) // val insulinUnit = rh.gs(info.nightscout.core.ui.R.string.insulin_unit_shortname)
val fields = nsSettingsStatus.pumpExtendedSettingsFields() // val fields = nsSettingsStatus.pumpExtendedSettingsFields()
// Removed here. Same value is in StatusLights // Removed here. Same value is in StatusLights
// if (pumpData.reservoirDisplayOverride != "") string.append(pumpData.reservoirDisplayOverride).append("$insulinUnit ") // if (pumpData.reservoirDisplayOverride != "") string.append(pumpData.reservoirDisplayOverride).append("$insulinUnit ")
// else if (fields.contains("reservoir")) string.append(pumpData.reservoir.toInt()).append("$insulinUnit ") // else if (fields.contains("reservoir")) string.append(pumpData.reservoir.toInt()).append("$insulinUnit ")

View file

@ -52,7 +52,7 @@ import info.nightscout.rx.events.EventNSClientRestart
import info.nightscout.rx.events.EventPreferenceChange import info.nightscout.rx.events.EventPreferenceChange
import info.nightscout.rx.logging.AAPSLogger import info.nightscout.rx.logging.AAPSLogger
import info.nightscout.rx.logging.LTag import info.nightscout.rx.logging.LTag
import info.nightscout.sdk.remotemodel.RemoteDeviceStatus import info.nightscout.sdk.localmodel.devicestatus.NSDeviceStatus
import info.nightscout.shared.interfaces.ResourceHelper import info.nightscout.shared.interfaces.ResourceHelper
import info.nightscout.shared.sharedPreferences.SP import info.nightscout.shared.sharedPreferences.SP
import info.nightscout.shared.utils.DateUtil import info.nightscout.shared.utils.DateUtil
@ -510,7 +510,7 @@ class NSClientService : DaggerService() {
} }
} }
val devicestatuses = gson.fromJson(data.getString("devicestatus"), Array<RemoteDeviceStatus>::class.java) val devicestatuses = gson.fromJson(data.getString("devicestatus"), Array<NSDeviceStatus>::class.java)
if (devicestatuses.isNotEmpty()) { if (devicestatuses.isNotEmpty()) {
rxBus.send(EventNSClientNewLog("DATA", "received " + devicestatuses.size + " device statuses")) rxBus.send(EventNSClientNewLog("DATA", "received " + devicestatuses.size + " device statuses"))
nsDeviceStatusHandler.handleNewData(devicestatuses) nsDeviceStatusHandler.handleNewData(devicestatuses)

View file

@ -39,6 +39,7 @@ import info.nightscout.plugins.sync.nsclient.NsClientReceiverDelegate
import info.nightscout.plugins.sync.nsclientV3.extensions.toNSBolus import info.nightscout.plugins.sync.nsclientV3.extensions.toNSBolus
import info.nightscout.plugins.sync.nsclientV3.extensions.toNSBolusWizard import info.nightscout.plugins.sync.nsclientV3.extensions.toNSBolusWizard
import info.nightscout.plugins.sync.nsclientV3.extensions.toNSCarbs import info.nightscout.plugins.sync.nsclientV3.extensions.toNSCarbs
import info.nightscout.plugins.sync.nsclientV3.extensions.toNSDeviceStatus
import info.nightscout.plugins.sync.nsclientV3.extensions.toNSEffectiveProfileSwitch import info.nightscout.plugins.sync.nsclientV3.extensions.toNSEffectiveProfileSwitch
import info.nightscout.plugins.sync.nsclientV3.extensions.toNSExtendedBolus import info.nightscout.plugins.sync.nsclientV3.extensions.toNSExtendedBolus
import info.nightscout.plugins.sync.nsclientV3.extensions.toNSFood import info.nightscout.plugins.sync.nsclientV3.extensions.toNSFood
@ -48,7 +49,6 @@ import info.nightscout.plugins.sync.nsclientV3.extensions.toNSSvgV3
import info.nightscout.plugins.sync.nsclientV3.extensions.toNSTemporaryBasal import info.nightscout.plugins.sync.nsclientV3.extensions.toNSTemporaryBasal
import info.nightscout.plugins.sync.nsclientV3.extensions.toNSTemporaryTarget import info.nightscout.plugins.sync.nsclientV3.extensions.toNSTemporaryTarget
import info.nightscout.plugins.sync.nsclientV3.extensions.toNSTherapyEvent 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.LoadBgWorker
import info.nightscout.plugins.sync.nsclientV3.workers.LoadLastModificationWorker import info.nightscout.plugins.sync.nsclientV3.workers.LoadLastModificationWorker
import info.nightscout.plugins.sync.nsclientV3.workers.LoadStatusWorker import info.nightscout.plugins.sync.nsclientV3.workers.LoadStatusWorker
@ -371,7 +371,7 @@ class NSClientV3Plugin @Inject constructor(
} }
private fun dbOperationDeviceStatus(collection: String = "devicestatus", dataPair: DataSyncSelector.DataPair, progress: String) { private fun dbOperationDeviceStatus(collection: String = "devicestatus", dataPair: DataSyncSelector.DataPair, progress: String) {
val data = (dataPair as DataSyncSelector.PairDeviceStatus).value.toRemoteDeviceStatus() val data = (dataPair as DataSyncSelector.PairDeviceStatus).value.toNSDeviceStatus()
scope.launch { scope.launch {
try { try {
rxBus.send(EventNSClientNewLog("ADD $collection", "Sent ${dataPair.javaClass.simpleName} ${gson.toJson(data)} $progress")) rxBus.send(EventNSClientNewLog("ADD $collection", "Sent ${dataPair.javaClass.simpleName} ${gson.toJson(data)} $progress"))

View file

@ -3,10 +3,10 @@ package info.nightscout.plugins.sync.nsclientV3.extensions
import com.google.gson.GsonBuilder import com.google.gson.GsonBuilder
import com.google.gson.JsonDeserializer import com.google.gson.JsonDeserializer
import info.nightscout.database.entities.DeviceStatus import info.nightscout.database.entities.DeviceStatus
import info.nightscout.sdk.remotemodel.RemoteDeviceStatus import info.nightscout.sdk.localmodel.devicestatus.NSDeviceStatus
import org.json.JSONObject import org.json.JSONObject
fun DeviceStatus.toRemoteDeviceStatus(): RemoteDeviceStatus { fun DeviceStatus.toNSDeviceStatus(): NSDeviceStatus {
val deserializer: JsonDeserializer<JSONObject?> = val deserializer: JsonDeserializer<JSONObject?> =
JsonDeserializer<JSONObject?> { json, _, _ -> JsonDeserializer<JSONObject?> { json, _, _ ->
JSONObject(json.asJsonObject.toString()) JSONObject(json.asJsonObject.toString())
@ -15,19 +15,19 @@ fun DeviceStatus.toRemoteDeviceStatus(): RemoteDeviceStatus {
it.registerTypeAdapter(JSONObject::class.java, deserializer) it.registerTypeAdapter(JSONObject::class.java, deserializer)
}.create() }.create()
val pump = gson.fromJson(pump, RemoteDeviceStatus.Pump::class.java) val pump = gson.fromJson(pump, NSDeviceStatus.Pump::class.java)
val openAps = RemoteDeviceStatus.OpenAps( val openAps = NSDeviceStatus.OpenAps(
suggested = suggested?.let { JSONObject(it) }, suggested = suggested?.let { JSONObject(it) },
enacted = enacted?.let { JSONObject(it) }, enacted = enacted?.let { JSONObject(it) },
iob = iob?.let { JSONObject(it) }, iob = iob?.let { JSONObject(it) },
) )
return RemoteDeviceStatus( return NSDeviceStatus(
date = timestamp, date = timestamp,
device = device, device = device,
pump = pump, pump = pump,
openaps = openAps, openaps = openAps,
uploaderBattery = if (uploaderBattery != 0) uploaderBattery else null, uploaderBattery = if (uploaderBattery != 0) uploaderBattery else null,
configuration = gson.fromJson(configuration, RemoteDeviceStatus.Configuration::class.java), configuration = gson.fromJson(configuration, NSDeviceStatus.Configuration::class.java),
uploader = null uploader = null
) )
} }

View file

@ -15,6 +15,7 @@ import info.nightscout.interfaces.profile.ProfileFunction
import info.nightscout.plugins.aps.APSResultObject import info.nightscout.plugins.aps.APSResultObject
import info.nightscout.plugins.sync.nsclient.data.NSDeviceStatusHandler import info.nightscout.plugins.sync.nsclient.data.NSDeviceStatusHandler
import info.nightscout.plugins.sync.nsclient.data.ProcessedDeviceStatusDataImpl import info.nightscout.plugins.sync.nsclient.data.ProcessedDeviceStatusDataImpl
import info.nightscout.sdk.mapper.convertToRemoteAndBack
import info.nightscout.shared.interfaces.ResourceHelper import info.nightscout.shared.interfaces.ResourceHelper
import info.nightscout.shared.sharedPreferences.SP import info.nightscout.shared.sharedPreferences.SP
import info.nightscout.shared.utils.DateUtil import info.nightscout.shared.utils.DateUtil
@ -78,9 +79,23 @@ internal class DeviceStatusExtensionKtTest : TestBase() {
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}}" 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() val nsDeviceStatus = deviceStatus.toNSDeviceStatus()
nsDeviceStatusHandler.handleNewData(arrayOf(remoteDeviceStatus)) nsDeviceStatusHandler.handleNewData(arrayOf(nsDeviceStatus))
Assertions.assertEquals(75, processedDeviceStatusData.pumpData?.percent) Assertions.assertEquals(75, processedDeviceStatusData.pumpData?.percent)
val nsDeviceStatus2 = nsDeviceStatus.convertToRemoteAndBack()
Assertions.assertTrue(nsDeviceStatus.device == nsDeviceStatus2.device)
Assertions.assertTrue(nsDeviceStatus.identifier == nsDeviceStatus2.identifier)
Assertions.assertTrue(nsDeviceStatus.srvCreated == nsDeviceStatus2.srvCreated)
Assertions.assertTrue(nsDeviceStatus.srvModified == nsDeviceStatus2.srvModified)
Assertions.assertTrue(nsDeviceStatus.createdAt == nsDeviceStatus2.createdAt)
Assertions.assertTrue(nsDeviceStatus.date == nsDeviceStatus2.date)
Assertions.assertTrue(nsDeviceStatus.uploaderBattery == nsDeviceStatus2.uploaderBattery)
Assertions.assertTrue(nsDeviceStatus.device == nsDeviceStatus2.device)
Assertions.assertTrue(nsDeviceStatus.uploader?.battery == nsDeviceStatus2.uploader?.battery)
Assertions.assertTrue(nsDeviceStatus.pump?.battery == nsDeviceStatus2.pump?.battery)
Assertions.assertTrue(nsDeviceStatus.openaps?.enacted?.toString() == nsDeviceStatus2.openaps?.enacted?.toString())
Assertions.assertTrue(nsDeviceStatus.configuration?.toString() == nsDeviceStatus2.configuration?.toString())
} }
} }